diff --git a/nightly_8.4/doctrees/7-to-8/caveats.doctree b/nightly_8.4/doctrees/7-to-8/caveats.doctree new file mode 100644 index 00000000000..3a53b38cf1b Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/caveats.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/cheat-sheet.doctree b/nightly_8.4/doctrees/7-to-8/cheat-sheet.doctree new file mode 100644 index 00000000000..2f942effb57 Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/cheat-sheet.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/index.doctree b/nightly_8.4/doctrees/7-to-8/index.doctree new file mode 100644 index 00000000000..6e4ddbac0b6 Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/index.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/cli.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/cli.doctree new file mode 100644 index 00000000000..63ac5c81d4c Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/cli.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/compatibility-mode.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/compatibility-mode.doctree new file mode 100644 index 00000000000..d9a10fa6c0e Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/compatibility-mode.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/config-changes.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/config-changes.doctree new file mode 100644 index 00000000000..78fb5727ee1 Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/config-changes.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/continuing-c7-c8.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/continuing-c7-c8.doctree new file mode 100644 index 00000000000..d5ee5ffb0ea Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/continuing-c7-c8.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/cylc-install.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/cylc-install.doctree new file mode 100644 index 00000000000..3a883f30c9c Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/cylc-install.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/excluding-tasks.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/excluding-tasks.doctree new file mode 100644 index 00000000000..c0b09482e7f Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/excluding-tasks.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/index.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/index.doctree new file mode 100644 index 00000000000..8f474bde528 Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/index.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/parameters.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/parameters.doctree new file mode 100644 index 00000000000..393236ba520 Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/parameters.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/platforms.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/platforms.doctree new file mode 100644 index 00000000000..1f2b04f2508 Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/platforms.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/play-pause-stop.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/play-pause-stop.doctree new file mode 100644 index 00000000000..ad177d3c73f Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/play-pause-stop.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/python-2-3.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/python-2-3.doctree new file mode 100644 index 00000000000..46d2d515b7f Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/python-2-3.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/remote-owner.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/remote-owner.doctree new file mode 100644 index 00000000000..4307d177c76 Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/remote-owner.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/scheduling.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/scheduling.doctree new file mode 100644 index 00000000000..bb0f1c259ab Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/scheduling.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/suicide-triggers.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/suicide-triggers.doctree new file mode 100644 index 00000000000..09757dd68cc Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/suicide-triggers.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/task-job-states.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/task-job-states.doctree new file mode 100644 index 00000000000..5a7f0c9e252 Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/task-job-states.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/template-vars.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/template-vars.doctree new file mode 100644 index 00000000000..158acaf7201 Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/template-vars.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/major-changes/ui.doctree b/nightly_8.4/doctrees/7-to-8/major-changes/ui.doctree new file mode 100644 index 00000000000..a71e353e1f1 Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/major-changes/ui.doctree differ diff --git a/nightly_8.4/doctrees/7-to-8/summary.doctree b/nightly_8.4/doctrees/7-to-8/summary.doctree new file mode 100644 index 00000000000..6b3ad061741 Binary files /dev/null and b/nightly_8.4/doctrees/7-to-8/summary.doctree differ diff --git a/nightly_8.4/doctrees/environment.pickle b/nightly_8.4/doctrees/environment.pickle new file mode 100644 index 00000000000..93fe89e7335 Binary files /dev/null and b/nightly_8.4/doctrees/environment.pickle differ diff --git a/nightly_8.4/doctrees/glossary.doctree b/nightly_8.4/doctrees/glossary.doctree new file mode 100644 index 00000000000..ae5a2914aa7 Binary files /dev/null and b/nightly_8.4/doctrees/glossary.doctree differ diff --git a/nightly_8.4/doctrees/index.doctree b/nightly_8.4/doctrees/index.doctree new file mode 100644 index 00000000000..ea728f5ae8b Binary files /dev/null and b/nightly_8.4/doctrees/index.doctree differ diff --git a/nightly_8.4/doctrees/installation.doctree b/nightly_8.4/doctrees/installation.doctree new file mode 100644 index 00000000000..0ff733d4d62 Binary files /dev/null and b/nightly_8.4/doctrees/installation.doctree differ diff --git a/nightly_8.4/doctrees/plugins/cylc-rose.doctree b/nightly_8.4/doctrees/plugins/cylc-rose.doctree new file mode 100644 index 00000000000..bf48bb5357f Binary files /dev/null and b/nightly_8.4/doctrees/plugins/cylc-rose.doctree differ diff --git a/nightly_8.4/doctrees/plugins/index.doctree b/nightly_8.4/doctrees/plugins/index.doctree new file mode 100644 index 00000000000..b06288609ed Binary files /dev/null and b/nightly_8.4/doctrees/plugins/index.doctree differ diff --git a/nightly_8.4/doctrees/plugins/install/built-in/cylc.flow.install_plugins.log_vc_info.doctree b/nightly_8.4/doctrees/plugins/install/built-in/cylc.flow.install_plugins.log_vc_info.doctree new file mode 100644 index 00000000000..494dd776dc9 Binary files /dev/null and b/nightly_8.4/doctrees/plugins/install/built-in/cylc.flow.install_plugins.log_vc_info.doctree differ diff --git a/nightly_8.4/doctrees/plugins/install/index.doctree b/nightly_8.4/doctrees/plugins/install/index.doctree new file mode 100644 index 00000000000..5c96b145fd3 Binary files /dev/null and b/nightly_8.4/doctrees/plugins/install/index.doctree differ diff --git a/nightly_8.4/doctrees/plugins/job-runners/index.doctree b/nightly_8.4/doctrees/plugins/job-runners/index.doctree new file mode 100644 index 00000000000..04008890215 Binary files /dev/null and b/nightly_8.4/doctrees/plugins/job-runners/index.doctree differ diff --git a/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.auto_restart.doctree b/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.auto_restart.doctree new file mode 100644 index 00000000000..97ae033a76e Binary files /dev/null and b/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.auto_restart.doctree differ diff --git a/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.health_check.doctree b/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.health_check.doctree new file mode 100644 index 00000000000..865a1e4f895 Binary files /dev/null and b/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.health_check.doctree differ diff --git a/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.log_data_store.doctree b/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.log_data_store.doctree new file mode 100644 index 00000000000..4085b20ff3b Binary files /dev/null and b/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.log_data_store.doctree differ diff --git a/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.log_main_loop.doctree b/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.log_main_loop.doctree new file mode 100644 index 00000000000..5cee2b471e1 Binary files /dev/null and b/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.log_main_loop.doctree differ diff --git a/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.log_memory.doctree b/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.log_memory.doctree new file mode 100644 index 00000000000..3cce1709619 Binary files /dev/null and b/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.log_memory.doctree differ diff --git a/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.reset_bad_hosts.doctree b/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.reset_bad_hosts.doctree new file mode 100644 index 00000000000..668c4090aee Binary files /dev/null and b/nightly_8.4/doctrees/plugins/main-loop/built-in/cylc.flow.main_loop.reset_bad_hosts.doctree differ diff --git a/nightly_8.4/doctrees/plugins/main-loop/index.doctree b/nightly_8.4/doctrees/plugins/main-loop/index.doctree new file mode 100644 index 00000000000..f426feca4a0 Binary files /dev/null and b/nightly_8.4/doctrees/plugins/main-loop/index.doctree differ diff --git a/nightly_8.4/doctrees/plugins/xtriggers/index.doctree b/nightly_8.4/doctrees/plugins/xtriggers/index.doctree new file mode 100644 index 00000000000..d84387bdfa0 Binary files /dev/null and b/nightly_8.4/doctrees/plugins/xtriggers/index.doctree differ diff --git a/nightly_8.4/doctrees/reference/api/exceptions.doctree b/nightly_8.4/doctrees/reference/api/exceptions.doctree new file mode 100644 index 00000000000..a0df8e5d0cc Binary files /dev/null and b/nightly_8.4/doctrees/reference/api/exceptions.doctree differ diff --git a/nightly_8.4/doctrees/reference/api/index.doctree b/nightly_8.4/doctrees/reference/api/index.doctree new file mode 100644 index 00000000000..9fbe5821663 Binary files /dev/null and b/nightly_8.4/doctrees/reference/api/index.doctree differ diff --git a/nightly_8.4/doctrees/reference/api/scan.doctree b/nightly_8.4/doctrees/reference/api/scan.doctree new file mode 100644 index 00000000000..31af222798b Binary files /dev/null and b/nightly_8.4/doctrees/reference/api/scan.doctree differ diff --git a/nightly_8.4/doctrees/reference/api/zmq.doctree b/nightly_8.4/doctrees/reference/api/zmq.doctree new file mode 100644 index 00000000000..c5808fc6a2b Binary files /dev/null and b/nightly_8.4/doctrees/reference/api/zmq.doctree differ diff --git a/nightly_8.4/doctrees/reference/architecture/data-flow.doctree b/nightly_8.4/doctrees/reference/architecture/data-flow.doctree new file mode 100644 index 00000000000..1ac8640f0a8 Binary files /dev/null and b/nightly_8.4/doctrees/reference/architecture/data-flow.doctree differ diff --git a/nightly_8.4/doctrees/reference/architecture/index.doctree b/nightly_8.4/doctrees/reference/architecture/index.doctree new file mode 100644 index 00000000000..beedffc2d31 Binary files /dev/null and b/nightly_8.4/doctrees/reference/architecture/index.doctree differ diff --git a/nightly_8.4/doctrees/reference/architecture/ui-server.doctree b/nightly_8.4/doctrees/reference/architecture/ui-server.doctree new file mode 100644 index 00000000000..a1f421943fa Binary files /dev/null and b/nightly_8.4/doctrees/reference/architecture/ui-server.doctree differ diff --git a/nightly_8.4/doctrees/reference/changes.doctree b/nightly_8.4/doctrees/reference/changes.doctree new file mode 100644 index 00000000000..f8b80e8ed92 Binary files /dev/null and b/nightly_8.4/doctrees/reference/changes.doctree differ diff --git a/nightly_8.4/doctrees/reference/config/file-format.doctree b/nightly_8.4/doctrees/reference/config/file-format.doctree new file mode 100644 index 00000000000..705e16fe1b8 Binary files /dev/null and b/nightly_8.4/doctrees/reference/config/file-format.doctree differ diff --git a/nightly_8.4/doctrees/reference/config/global.doctree b/nightly_8.4/doctrees/reference/config/global.doctree new file mode 100644 index 00000000000..87488ad10b1 Binary files /dev/null and b/nightly_8.4/doctrees/reference/config/global.doctree differ diff --git a/nightly_8.4/doctrees/reference/config/index.doctree b/nightly_8.4/doctrees/reference/config/index.doctree new file mode 100644 index 00000000000..c859ea46f1e Binary files /dev/null and b/nightly_8.4/doctrees/reference/config/index.doctree differ diff --git a/nightly_8.4/doctrees/reference/config/sharing-access-to-workflows.doctree b/nightly_8.4/doctrees/reference/config/sharing-access-to-workflows.doctree new file mode 100644 index 00000000000..5df97318b68 Binary files /dev/null and b/nightly_8.4/doctrees/reference/config/sharing-access-to-workflows.doctree differ diff --git a/nightly_8.4/doctrees/reference/config/shorthand.doctree b/nightly_8.4/doctrees/reference/config/shorthand.doctree new file mode 100644 index 00000000000..e0d06ead904 Binary files /dev/null and b/nightly_8.4/doctrees/reference/config/shorthand.doctree differ diff --git a/nightly_8.4/doctrees/reference/config/types.doctree b/nightly_8.4/doctrees/reference/config/types.doctree new file mode 100644 index 00000000000..b2670a9b1ca Binary files /dev/null and b/nightly_8.4/doctrees/reference/config/types.doctree differ diff --git a/nightly_8.4/doctrees/reference/config/ui-server.doctree b/nightly_8.4/doctrees/reference/config/ui-server.doctree new file mode 100644 index 00000000000..013de2517a9 Binary files /dev/null and b/nightly_8.4/doctrees/reference/config/ui-server.doctree differ diff --git a/nightly_8.4/doctrees/reference/config/workflow.doctree b/nightly_8.4/doctrees/reference/config/workflow.doctree new file mode 100644 index 00000000000..fdd9d8a2961 Binary files /dev/null and b/nightly_8.4/doctrees/reference/config/workflow.doctree differ diff --git a/nightly_8.4/doctrees/reference/config/writing-platform-configs.doctree b/nightly_8.4/doctrees/reference/config/writing-platform-configs.doctree new file mode 100644 index 00000000000..5196669dedd Binary files /dev/null and b/nightly_8.4/doctrees/reference/config/writing-platform-configs.doctree differ diff --git a/nightly_8.4/doctrees/reference/dev-history-major-changes.doctree b/nightly_8.4/doctrees/reference/dev-history-major-changes.doctree new file mode 100644 index 00000000000..d41d09f63a2 Binary files /dev/null and b/nightly_8.4/doctrees/reference/dev-history-major-changes.doctree differ diff --git a/nightly_8.4/doctrees/reference/environments/conda.doctree b/nightly_8.4/doctrees/reference/environments/conda.doctree new file mode 100644 index 00000000000..e192e7ac942 Binary files /dev/null and b/nightly_8.4/doctrees/reference/environments/conda.doctree differ diff --git a/nightly_8.4/doctrees/reference/index.doctree b/nightly_8.4/doctrees/reference/index.doctree new file mode 100644 index 00000000000..6b75d830aea Binary files /dev/null and b/nightly_8.4/doctrees/reference/index.doctree differ diff --git a/nightly_8.4/doctrees/reference/job-script-vars/index.doctree b/nightly_8.4/doctrees/reference/job-script-vars/index.doctree new file mode 100644 index 00000000000..2b642b0fe9f Binary files /dev/null and b/nightly_8.4/doctrees/reference/job-script-vars/index.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/furthertopics/broadcast.doctree b/nightly_8.4/doctrees/tutorial/furthertopics/broadcast.doctree new file mode 100644 index 00000000000..fab0446d05b Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/furthertopics/broadcast.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/furthertopics/clock-triggered-tasks.doctree b/nightly_8.4/doctrees/tutorial/furthertopics/clock-triggered-tasks.doctree new file mode 100644 index 00000000000..f709fb7c1f4 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/furthertopics/clock-triggered-tasks.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/furthertopics/family-triggers.doctree b/nightly_8.4/doctrees/tutorial/furthertopics/family-triggers.doctree new file mode 100644 index 00000000000..720666df4c8 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/furthertopics/family-triggers.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/furthertopics/index.doctree b/nightly_8.4/doctrees/tutorial/furthertopics/index.doctree new file mode 100644 index 00000000000..fc61614be5f Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/furthertopics/index.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/furthertopics/inheritance.doctree b/nightly_8.4/doctrees/tutorial/furthertopics/inheritance.doctree new file mode 100644 index 00000000000..f7a6422d694 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/furthertopics/inheritance.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/furthertopics/message-triggers.doctree b/nightly_8.4/doctrees/tutorial/furthertopics/message-triggers.doctree new file mode 100644 index 00000000000..9aad7a0a063 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/furthertopics/message-triggers.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/furthertopics/queues.doctree b/nightly_8.4/doctrees/tutorial/furthertopics/queues.doctree new file mode 100644 index 00000000000..c0a341bf9a9 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/furthertopics/queues.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/furthertopics/retries.doctree b/nightly_8.4/doctrees/tutorial/furthertopics/retries.doctree new file mode 100644 index 00000000000..d0c388c58e6 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/furthertopics/retries.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/index.doctree b/nightly_8.4/doctrees/tutorial/index.doctree new file mode 100644 index 00000000000..998fda4c136 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/index.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/introduction.doctree b/nightly_8.4/doctrees/tutorial/introduction.doctree new file mode 100644 index 00000000000..b9665ed7bce Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/introduction.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/runtime/configuration-consolidation/families.doctree b/nightly_8.4/doctrees/tutorial/runtime/configuration-consolidation/families.doctree new file mode 100644 index 00000000000..275ce9c6af5 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/runtime/configuration-consolidation/families.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/runtime/configuration-consolidation/index.doctree b/nightly_8.4/doctrees/tutorial/runtime/configuration-consolidation/index.doctree new file mode 100644 index 00000000000..ef5e996d1a2 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/runtime/configuration-consolidation/index.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/runtime/configuration-consolidation/jinja2.doctree b/nightly_8.4/doctrees/tutorial/runtime/configuration-consolidation/jinja2.doctree new file mode 100644 index 00000000000..54bb29f03b5 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/runtime/configuration-consolidation/jinja2.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/runtime/configuration-consolidation/parameters.doctree b/nightly_8.4/doctrees/tutorial/runtime/configuration-consolidation/parameters.doctree new file mode 100644 index 00000000000..6317c2691c7 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/runtime/configuration-consolidation/parameters.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/runtime/index.doctree b/nightly_8.4/doctrees/tutorial/runtime/index.doctree new file mode 100644 index 00000000000..012d12538e9 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/runtime/index.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/runtime/introduction.doctree b/nightly_8.4/doctrees/tutorial/runtime/introduction.doctree new file mode 100644 index 00000000000..872084341f7 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/runtime/introduction.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/runtime/runtime-configuration.doctree b/nightly_8.4/doctrees/tutorial/runtime/runtime-configuration.doctree new file mode 100644 index 00000000000..fab575cad95 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/runtime/runtime-configuration.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/runtime/summary.doctree b/nightly_8.4/doctrees/tutorial/runtime/summary.doctree new file mode 100644 index 00000000000..0308931f524 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/runtime/summary.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/scheduling/datetime-cycling.doctree b/nightly_8.4/doctrees/tutorial/scheduling/datetime-cycling.doctree new file mode 100644 index 00000000000..4f7fc3a733d Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/scheduling/datetime-cycling.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/scheduling/further-scheduling.doctree b/nightly_8.4/doctrees/tutorial/scheduling/further-scheduling.doctree new file mode 100644 index 00000000000..927d2efbf24 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/scheduling/further-scheduling.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/scheduling/graphing.doctree b/nightly_8.4/doctrees/tutorial/scheduling/graphing.doctree new file mode 100644 index 00000000000..990cf22b93e Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/scheduling/graphing.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/scheduling/index.doctree b/nightly_8.4/doctrees/tutorial/scheduling/index.doctree new file mode 100644 index 00000000000..0331ac3078a Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/scheduling/index.doctree differ diff --git a/nightly_8.4/doctrees/tutorial/scheduling/integer-cycling.doctree b/nightly_8.4/doctrees/tutorial/scheduling/integer-cycling.doctree new file mode 100644 index 00000000000..81593bf09b7 Binary files /dev/null and b/nightly_8.4/doctrees/tutorial/scheduling/integer-cycling.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/cheat-sheet.doctree b/nightly_8.4/doctrees/user-guide/cheat-sheet.doctree new file mode 100644 index 00000000000..194123adc96 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/cheat-sheet.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/examples/1-hello-world/index.doctree b/nightly_8.4/doctrees/user-guide/examples/1-hello-world/index.doctree new file mode 100644 index 00000000000..e48e88150f4 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/examples/1-hello-world/index.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/examples/2-integer-cycling/index.doctree b/nightly_8.4/doctrees/user-guide/examples/2-integer-cycling/index.doctree new file mode 100644 index 00000000000..9640eb544df Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/examples/2-integer-cycling/index.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/examples/3-datetime-cycling/index.doctree b/nightly_8.4/doctrees/user-guide/examples/3-datetime-cycling/index.doctree new file mode 100644 index 00000000000..6bbc9836f45 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/examples/3-datetime-cycling/index.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/examples/converging-workflow/index.doctree b/nightly_8.4/doctrees/user-guide/examples/converging-workflow/index.doctree new file mode 100644 index 00000000000..34c8053910b Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/examples/converging-workflow/index.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/examples/event-driven-cycling/README.doctree b/nightly_8.4/doctrees/user-guide/examples/event-driven-cycling/README.doctree new file mode 100644 index 00000000000..32b53bcc181 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/examples/event-driven-cycling/README.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/examples/event-driven-cycling/index.doctree b/nightly_8.4/doctrees/user-guide/examples/event-driven-cycling/index.doctree new file mode 100644 index 00000000000..b272c490ae0 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/examples/event-driven-cycling/index.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/examples/extending-workflow/index.doctree b/nightly_8.4/doctrees/user-guide/examples/extending-workflow/index.doctree new file mode 100644 index 00000000000..f1b887e4135 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/examples/extending-workflow/index.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/examples/index.doctree b/nightly_8.4/doctrees/user-guide/examples/index.doctree new file mode 100644 index 00000000000..8d85bf1f172 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/examples/index.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/examples/inter-workflow-triggers/README.doctree b/nightly_8.4/doctrees/user-guide/examples/inter-workflow-triggers/README.doctree new file mode 100644 index 00000000000..ec2dfb37a40 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/examples/inter-workflow-triggers/README.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/examples/inter-workflow-triggers/index.doctree b/nightly_8.4/doctrees/user-guide/examples/inter-workflow-triggers/index.doctree new file mode 100644 index 00000000000..4e410257f28 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/examples/inter-workflow-triggers/index.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/index.doctree b/nightly_8.4/doctrees/user-guide/index.doctree new file mode 100644 index 00000000000..ae72c79b3ea Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/index.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/installing-workflows.doctree b/nightly_8.4/doctrees/user-guide/installing-workflows.doctree new file mode 100644 index 00000000000..25e35ce1a5c Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/installing-workflows.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/interventions/index.doctree b/nightly_8.4/doctrees/user-guide/interventions/index.doctree new file mode 100644 index 00000000000..5065a68cfe6 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/interventions/index.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/introduction.doctree b/nightly_8.4/doctrees/user-guide/introduction.doctree new file mode 100644 index 00000000000..4d6f1737598 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/introduction.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/removing-workflows.doctree b/nightly_8.4/doctrees/user-guide/removing-workflows.doctree new file mode 100644 index 00000000000..d1ed0b10324 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/removing-workflows.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/running-workflows/authentication-files.doctree b/nightly_8.4/doctrees/user-guide/running-workflows/authentication-files.doctree new file mode 100644 index 00000000000..04764f7c6b3 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/running-workflows/authentication-files.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/running-workflows/dynamic-behaviour.doctree b/nightly_8.4/doctrees/user-guide/running-workflows/dynamic-behaviour.doctree new file mode 100644 index 00000000000..10b6dd00cd2 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/running-workflows/dynamic-behaviour.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/running-workflows/handling-job-preemption.doctree b/nightly_8.4/doctrees/user-guide/running-workflows/handling-job-preemption.doctree new file mode 100644 index 00000000000..626be8c57a6 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/running-workflows/handling-job-preemption.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/running-workflows/index.doctree b/nightly_8.4/doctrees/user-guide/running-workflows/index.doctree new file mode 100644 index 00000000000..9b0149c2bb0 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/running-workflows/index.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/running-workflows/reflow.doctree b/nightly_8.4/doctrees/user-guide/running-workflows/reflow.doctree new file mode 100644 index 00000000000..71ff65e802c Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/running-workflows/reflow.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/running-workflows/retrying-tasks.doctree b/nightly_8.4/doctrees/user-guide/running-workflows/retrying-tasks.doctree new file mode 100644 index 00000000000..9422a793355 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/running-workflows/retrying-tasks.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/running-workflows/scheduler-log-files.doctree b/nightly_8.4/doctrees/user-guide/running-workflows/scheduler-log-files.doctree new file mode 100644 index 00000000000..9ec61f2d608 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/running-workflows/scheduler-log-files.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/running-workflows/scheduler-start-up.doctree b/nightly_8.4/doctrees/user-guide/running-workflows/scheduler-start-up.doctree new file mode 100644 index 00000000000..b0d1f4a49eb Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/running-workflows/scheduler-start-up.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/running-workflows/simulation-modes.doctree b/nightly_8.4/doctrees/user-guide/running-workflows/simulation-modes.doctree new file mode 100644 index 00000000000..42ecc1c1654 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/running-workflows/simulation-modes.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/running-workflows/tasks-jobs-ui.doctree b/nightly_8.4/doctrees/user-guide/running-workflows/tasks-jobs-ui.doctree new file mode 100644 index 00000000000..9b7fee7817d Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/running-workflows/tasks-jobs-ui.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/running-workflows/tracking-task-state.doctree b/nightly_8.4/doctrees/user-guide/running-workflows/tracking-task-state.doctree new file mode 100644 index 00000000000..ad0176de08f Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/running-workflows/tracking-task-state.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/running-workflows/workflow-completion.doctree b/nightly_8.4/doctrees/user-guide/running-workflows/workflow-completion.doctree new file mode 100644 index 00000000000..38e15c285bb Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/running-workflows/workflow-completion.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/running-workflows/workflow-databases.doctree b/nightly_8.4/doctrees/user-guide/running-workflows/workflow-databases.doctree new file mode 100644 index 00000000000..3bb05c63814 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/running-workflows/workflow-databases.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/task-implementation/index.doctree b/nightly_8.4/doctrees/user-guide/task-implementation/index.doctree new file mode 100644 index 00000000000..7e41f6fd608 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/task-implementation/index.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.at.doctree b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.at.doctree new file mode 100644 index 00000000000..f16fb73c8b7 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.at.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.background.doctree b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.background.doctree new file mode 100644 index 00000000000..2cf7ab907f7 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.background.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.loadleveler.doctree b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.loadleveler.doctree new file mode 100644 index 00000000000..3daff63db1b Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.loadleveler.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.lsf.doctree b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.lsf.doctree new file mode 100644 index 00000000000..69406facad9 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.lsf.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.moab.doctree b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.moab.doctree new file mode 100644 index 00000000000..c8d38174636 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.moab.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.pbs.doctree b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.pbs.doctree new file mode 100644 index 00000000000..03fe7ec1f07 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.pbs.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.sge.doctree b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.sge.doctree new file mode 100644 index 00000000000..8f2efc2e324 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.sge.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm.doctree b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm.doctree new file mode 100644 index 00000000000..ce01b42097a Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm_packjob.doctree b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm_packjob.doctree new file mode 100644 index 00000000000..2586ac48f46 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm_packjob.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/task-implementation/job-scripts.doctree b/nightly_8.4/doctrees/user-guide/task-implementation/job-scripts.doctree new file mode 100644 index 00000000000..a28d6441cac Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/task-implementation/job-scripts.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/task-implementation/job-submission.doctree b/nightly_8.4/doctrees/user-guide/task-implementation/job-submission.doctree new file mode 100644 index 00000000000..cac1b2d2232 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/task-implementation/job-submission.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/task-implementation/ssh-job-management.doctree b/nightly_8.4/doctrees/user-guide/task-implementation/ssh-job-management.doctree new file mode 100644 index 00000000000..661b1262eb5 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/task-implementation/ssh-job-management.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/troubleshooting.doctree b/nightly_8.4/doctrees/user-guide/troubleshooting.doctree new file mode 100644 index 00000000000..dc590deefab Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/troubleshooting.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/writing-workflows/configuration.doctree b/nightly_8.4/doctrees/user-guide/writing-workflows/configuration.doctree new file mode 100644 index 00000000000..0ca5ec5e25b Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/writing-workflows/configuration.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/writing-workflows/empy.doctree b/nightly_8.4/doctrees/user-guide/writing-workflows/empy.doctree new file mode 100644 index 00000000000..dd9569e5487 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/writing-workflows/empy.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/writing-workflows/external-triggers.doctree b/nightly_8.4/doctrees/user-guide/writing-workflows/external-triggers.doctree new file mode 100644 index 00000000000..239112b8f83 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/writing-workflows/external-triggers.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/writing-workflows/index.doctree b/nightly_8.4/doctrees/user-guide/writing-workflows/index.doctree new file mode 100644 index 00000000000..4dd5b717441 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/writing-workflows/index.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/writing-workflows/jinja2.doctree b/nightly_8.4/doctrees/user-guide/writing-workflows/jinja2.doctree new file mode 100644 index 00000000000..cb7eb35208e Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/writing-workflows/jinja2.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/writing-workflows/parameterized-tasks.doctree b/nightly_8.4/doctrees/user-guide/writing-workflows/parameterized-tasks.doctree new file mode 100644 index 00000000000..bd907e0e399 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/writing-workflows/parameterized-tasks.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/writing-workflows/runtime.doctree b/nightly_8.4/doctrees/user-guide/writing-workflows/runtime.doctree new file mode 100644 index 00000000000..2d0952f3047 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/writing-workflows/runtime.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/writing-workflows/scheduler.doctree b/nightly_8.4/doctrees/user-guide/writing-workflows/scheduler.doctree new file mode 100644 index 00000000000..81d69498696 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/writing-workflows/scheduler.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/writing-workflows/scheduling.doctree b/nightly_8.4/doctrees/user-guide/writing-workflows/scheduling.doctree new file mode 100644 index 00000000000..d992cc3f4a2 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/writing-workflows/scheduling.doctree differ diff --git a/nightly_8.4/doctrees/user-guide/writing-workflows/suicide-triggers.doctree b/nightly_8.4/doctrees/user-guide/writing-workflows/suicide-triggers.doctree new file mode 100644 index 00000000000..c02307f8679 Binary files /dev/null and b/nightly_8.4/doctrees/user-guide/writing-workflows/suicide-triggers.doctree differ diff --git a/nightly_8.4/doctrees/workflow-design-guide/efficiency.doctree b/nightly_8.4/doctrees/workflow-design-guide/efficiency.doctree new file mode 100644 index 00000000000..cdc5795fed2 Binary files /dev/null and b/nightly_8.4/doctrees/workflow-design-guide/efficiency.doctree differ diff --git a/nightly_8.4/doctrees/workflow-design-guide/general-principles.doctree b/nightly_8.4/doctrees/workflow-design-guide/general-principles.doctree new file mode 100644 index 00000000000..5fd11402a2d Binary files /dev/null and b/nightly_8.4/doctrees/workflow-design-guide/general-principles.doctree differ diff --git a/nightly_8.4/doctrees/workflow-design-guide/index.doctree b/nightly_8.4/doctrees/workflow-design-guide/index.doctree new file mode 100644 index 00000000000..bb6277479d6 Binary files /dev/null and b/nightly_8.4/doctrees/workflow-design-guide/index.doctree differ diff --git a/nightly_8.4/doctrees/workflow-design-guide/portable-workflows.doctree b/nightly_8.4/doctrees/workflow-design-guide/portable-workflows.doctree new file mode 100644 index 00000000000..e1204d0cc23 Binary files /dev/null and b/nightly_8.4/doctrees/workflow-design-guide/portable-workflows.doctree differ diff --git a/nightly_8.4/doctrees/workflow-design-guide/style-guide.doctree b/nightly_8.4/doctrees/workflow-design-guide/style-guide.doctree new file mode 100644 index 00000000000..b2137f7c4a8 Binary files /dev/null and b/nightly_8.4/doctrees/workflow-design-guide/style-guide.doctree differ diff --git a/nightly_8.4/html/.buildinfo b/nightly_8.4/html/.buildinfo new file mode 100644 index 00000000000..587696b7bb7 --- /dev/null +++ b/nightly_8.4/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 23007d18127b3fcc37584cff048bfd3c +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/nightly_8.4/html/7-to-8/caveats.html b/nightly_8.4/html/7-to-8/caveats.html new file mode 100644 index 00000000000..f08953c5a53 --- /dev/null +++ b/nightly_8.4/html/7-to-8/caveats.html @@ -0,0 +1,227 @@ + + + + + + + Cylc 8.4 Caveats — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Cylc 8.4 Caveats

+

There are a few Cylc 7 features which do not yet have direct replacements in +Cylc 8. These features will be re-implemented in future releases.

+
+

Cylc Flow

+
+
Multiple Flows

The new scheduler can manage multiple flows in the workflow graph. +Commands and options for interacting with flows are still being refined.

+
+
+
+
+

Browser Based UI

+

The old “GUI” has been replaced by the new browser-based “UI”.

+
+
Static Graph Visualization

Not yet reimplemented for Cylc 8. As an interim measure the +cylc graph command can generate a basic PNG image of a workflow +graph if Graphviz is installed in the Cylc environment.

+
+
Multiple Selection

Multiple selection is yet to be implemented, however, it is possible +to issue action for multiple tasks (e.g. kill) without using +multiple selection:

+
    +
  • From the UI click on a workflow/cycle/task/job.

  • +
  • Find the action you want to call (e.g. kill).

  • +
  • Click the pencil symbol next to this action.

  • +
  • Edit the workflows/cycles/tasks/jobs in the form and press submit.

  • +
  • https://github.com/cylc/cylc-ui/issues/434

  • +
+
+
Installing Workflows

At present there is no way to view or install +source workflows in the UI.

+
+
Rose Edit

Rose Edit is awaiting reimplementation.

+
+
Xtrigger Visibility

Xtriggers are not yet visible in the UI.

+ +
+
Documentation / Orientation Guide

Some form of documentation will be provided within the UI itself.

+ +
+
+
+
+

UI Server

+
+
CLI via UIS

The ability to route Cylc commands via the UIS is planned for a future release

+ +
+
+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/cheat-sheet.html b/nightly_8.4/html/7-to-8/cheat-sheet.html new file mode 100644 index 00000000000..247efc28a1d --- /dev/null +++ b/nightly_8.4/html/7-to-8/cheat-sheet.html @@ -0,0 +1,564 @@ + + + + + + + Cheat Sheet — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Cheat Sheet

+

Quick summary of the command line changes between Cylc 7 / Rose 2019 and Cylc 8.

+
+

Validating

+

Check the workflow configuration for errors:

+ + + + + + + + + + + +

Cylc 7

Rose 2019

Cylc 8 (Rose 2)

cylc validate <name/path>
+
+
+
# validate from $PWD
+rose suite-run --validate
+
+
+
cylc validate <name/path>
+
+
+
+
+
+

Installing & Running

+

Install a workflow from source and run it:

+ + + + + + + + + + + +

Cylc 7

Rose 2019

Cylc 8 (Rose 2)

# no installation capability
+# run from source
+cylc run <name>
+
+
+
# install from $PWD
+# then run
+rose suite-run
+
+
+
# validate, install & play
+cylc vip <name>
+cylc vip # use $PWD
+
+
+
+
+
+

Reloading

+

To update a running workflow with changes from the source directory:

+ + + + + + + + + + + +

Cylc 7

Rose 2019

Cylc 8 (Rose 2)

# update the live source
+# directly, then
+cylc reload <name>
+
+
+
# re-install from source
+# and do ``cylc reload``
+rose suite-run --reload
+
+
+
# Validate against source;
+# Reinstall;
+# Reload or Play
+cylc vr <name>
+
+
+
+
+
+

Pausing & Unpausing

+

Tell a workflow not to submit any new jobs:

+ + + + + + + + + +

Cylc 7 & Rose 2019

Cylc 8 (Rose 2)

cylc hold <name>
+
+cylc unhold <name>
+
+
+
cylc pause <name>
+
+cylc play <name>
+
+
+
+
+
+

Stopping

+

Stop a running workflow:

+
cylc stop <name>
+
+
+
+
+

Restarting

+

Restart a stopped workflow and pick up where it left off:

+ + + + + + + + + + + +

Cylc 7

Rose 2019

Cylc 8 (Rose 2)

# no installation capability
+# restart from source
+cylc restart <name>
+
+
+
# regular restart
+rose suite-restart
+
+
+

Or alternatively:

+
# reinstall and restart
+rose suite-run --restart
+
+
+
# optionally reinstall
+cylc reinstall <name>
+
+# restart
+cylc play <name>
+
+
+
+
+
+

Deleting

+

Delete the workflow run directory (leave source files untouched):

+ + + + + + + + + + + +

Cylc 7

Rose 2019

Cylc 8 (Rose 2)

rm -rf ~/cylc-run/<name>
+
+
+
rose suite-clean <name>
+
+
+
cylc clean <name>
+
+
+
+
+
+

Scanning

+

List all running workflows:

+
cylc scan
+
+
+
+
+

View A Workflow’s Configuration

+

View the parsed workflow configuration:

+ + + + + + + + + + + +

Cylc 7

Rose 2019

Cylc 8 (Rose 2)

cylc get-config --sparse \
+    <name/path>
+
+
+
# install workflow
+rose suite-run -l
+
+# view installed config
+cylc get-config --sparse \
+    <name/path>
+
+
+
cylc config <name/path>
+
+
+
+
+
+

Opening User Interfaces

+

Opening the graphical user interface (GUI) or terminal user interface (TUI) +for monitoring / controlling running workflows:

+ + + + + + + + + + + + + + + + + + + +

Cylc 7 & Rose 2019

Cylc 8 (Rose 2)

Terminal

cylc monitor <name>
+
+
+
cylc tui <name>
+
+
+

Graphical

cylc gui <name>
+
+
+
cylc gui
+
+
+

Web Server

cylc review start
+
+
+
cylc hub
+
+
+
+
+
+

Static Graph Visualisation

+

Generate a visualisation for a workflow without running it:

+ + + + + + + + + +

Cylc 7 & Rose 2019

Cylc 8 (Rose 2)

cylc graph <name>
+
+
+
cylc graph <name>
+
+
+

This generates a basic image file if Graphviz is installed.

+

The web UI will have full graph vis. in a future release.

+
+
+
+

Datetime Operations

+

Datetime operations in task scripts:

+ + + + + + + + + + + + +

Cylc 7 & Rose 2019

Cylc 8 (Rose 2)

rose date <point> --offset <offset>
+
+
+
isodatetime <point> --offset <offset>
+
+
+
rose date -c
+# equivalent to:
+rose date "$CYLC_TASK_CYCLE_POINT"
+
+
+
isodatetime ref
+# equivalent to:
+isodatetime "$CYLC_TASK_CYCLE_POINT"
+
+
+
+
+
+

Rose Stem

+

Run a Rose Stem test suite.

+ + + + + + + + + +

Rose 2019

Rose 2 (Cylc 8)

# install and start
+rose stem
+
+
+
# install
+rose stem
+
+# start
+cylc play <name>
+
+
+
+
+
+

Interventions

+
+

Note

+

See the Interventions section for more details.

+
+

Set task outputs:

+ + + + + + + + + +

Cylc 7

Cylc 8

cylc reset -s=succeeded
+
+
+
cylc set --out=succeeded
+
+
+
+

Insert a task:

+ + + + + + + + + +

Cylc 7

Cylc 8

cylc insert
+
+
+

Tasks are inserted automatically when you “trigger” or “set” them.

+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/index.html b/nightly_8.4/html/7-to-8/index.html new file mode 100644 index 00000000000..d86e89cd989 --- /dev/null +++ b/nightly_8.4/html/7-to-8/index.html @@ -0,0 +1,182 @@ + + + + + + + Cylc 8 Migration Guide — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Cylc 8 Migration Guide

+

A quick guide for Cylc 7 (and Rose 2019) users upgrading to Cylc 8.

+
+

Tip

+

If you need help using or understanding Cylc 8 please post questions to the +Cylc 8 Migration category +on the Cylc Forum

+
+

Cylc 8 differs from Cylc 7 in many ways: architecture, scheduling +algorithm, security, UIs, working practices, and more.

+ +
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/cli.html b/nightly_8.4/html/7-to-8/major-changes/cli.html new file mode 100644 index 00000000000..f8b4d053d0b --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/cli.html @@ -0,0 +1,404 @@ + + + + + + + Command Line Interface — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Command Line Interface

+
+

Does This Change Affect Me?

+

This will affect you if you use the Cylc command line interface.

+
+
+

Overview

+
    +
  • Some commands have been renamed e.g. cylc run -> cylc play.

  • +
  • Some tools have been added or removed.

  • +
  • A new task ID format has been introduced.

  • +
+

For a quick side by side comparison see the Cheat Sheet.

+
+
+

Full List Of Command Changes

+

The command line has been simplified from Cylc 7 with some commands being +renamed or removed.

+

Commands that have been removed entirely:

+
+
cylc checkpoint
    +
  • Database checkpoints are no longer needed.

  • +
  • All task state changes are written to the database when they occur.

  • +
  • Remaining use cases can be handled by starting a new flow +which allow a new execution of the graph to be started from an +arbitrary point in the graph.

  • +
+
+
cylc documentation
    +
  • We no longer include a command for locating this documentation.

  • +
+
+
cylc edit
    +
  • Use a text editor to edit the workflow configuration file.

  • +
+
+
cylc jobscript
    +
  • It is no longer possible generate a jobscript from outside of a workflow.

  • +
+
+
cylc nudge
    +
  • No longer required.

  • +
+
+
cylc register
    +
  • Registration is no longer required, all workflows in the ~/cylc-run +directory are “registered” automatically.

  • +
  • To install a workflow from a working copy use cylc install.

  • +
+
+
cylc review
    +
  • The read-only cylc review web GUI has been removed.

  • +
  • The latest Cylc 7 version of cylc review is Cylc 8 compatible +so can still be used to monitor both Cylc 7 and Cylc 8 workflows +side by side.

  • +
+
+
cylc search
    +
  • Use grep or a text editor to search the workflow configuration or +source directory.

  • +
+
+
cylc submit
    +
  • It is no longer possible to submit a job from outside of a workflow.

  • +
+
+
cylc warranty
    +
  • The Cylc license remains unchanged from Cylc 7.

  • +
+
+
+

Commands that have been replaced:

+
+
cylc conditions
    +
  • See the license file for conditions of usage, or cylc help license

  • +
  • The Cylc license remains unchanged from Cylc 7.

  • +
+
+
cylc get-config,
    +
  • Replaced by cylc config.

  • +
+
+
cylc get-*-config
    +
  • (Where * is site, suite or global)

  • +
  • Replaced by cylc config.

  • +
+
+
cylc graph-diff
    +
  • Replaced by cylc graph <flow1> --diff <flow2>

  • +
+
+
cylc insert
    +
  • Task insertion is now automatic, use cylc trigger.

  • +
+
+
cylc monitor
    +
  • There is now a new more powerful terminal user interface (TUI).

  • +
  • Try cylc tui.

  • +
+
+
cylc print
    +
  • Equivalent to cylc scan --states=all.

  • +
+
+
cylc reset
    +
  • cylc reset has been replaced by cylc set

  • +
  • At Cylc 8 we override task’s prerequisites & outputs rather than modifying +the task state directly.

  • +
+
+
cylc restart
    +
  • Replaced by cylc play.

  • +
+
+
cylc run
    +
  • Replaced by cylc play.

  • +
+
+
cylc spawn
    +
  • Spawning is now performed automatically, on demand. Use cylc trigger to run +a task, or cylc set to spawn tasks that depend on specified outputs.

  • +
+
+
cylc suite-state
    +
  • Renamed as cylc workflow-state.

  • +
+
+
+

Commands that have changed:

+
+
cylc hold
    +
  • Now used on tasks only; use cylc pause to pause an entire workflow +(i.e. to halt all job submissions).

  • +
+
+
cylc release
    +
  • Now used only to release held tasks; use cylc play to resume a paused workflow.

  • +
+
+
+

Graphical User Interfaces (GUIs):

+

The GTK based GUI based GUIs have been removed, please use the new web based +GUI. Consequently the following commands have also been removed:

+
    +
  • cylc gpanel

  • +
  • cylc gscan

  • +
  • cylc gcylc

  • +
+

The cylc gui command remains, it launches a standalone version of the +web GUI (providing the Cylc UI Server is installed).

+

Additionally, there are two +“compound commands” +which automate common working practices, namely:

+
+
cylc vip

Validate, install and play a workflow. This is similar to what +rose suite-run did.

+
+
cylc vr

Validate, reinstall, then either reload (if the workflow is running) or restart +(if it is stopped) the workflow. This is similar to what +rose suite-run --reload and rose suite-run --restart did.

+
+
+
+
+

Cylc 8 Standardised IDs

+

In Cylc 7 there were two ways to specify a task:

+
task.cycle
+cycle/task
+
+
+

In Cylc 8 the former is now deprecated, and the latter has been extended to +provide a unique identifier for all workflows, cycles, tasks and jobs using a +standard format:

+
~user/workflow//cycle/task/job
+
+
+

Consequently task IDs have changed:

+
# old
+cycle.task
+
+# new
+cycle/task
+
+
+

An example using cylc trigger:

+
# old
+cylc trigger workflow task.cycle
+
+# new
+cylc trigger workflow//cycle/task
+
+
+

Cylc 8 still supports the old format, however, the new format unlocks extra +functionality e.g:

+
# stop all running workflows
+cylc stop '*'
+
+# pause all running workflows
+cylc pause '*'
+
+# (re-)trigger all failed tasks in all running workflows
+cylc trigger '*//*:failed'
+
+# hold all tasks in the cycle "2000" in workflows with IDs
+ # beginning with "model"
+cylc hold 'model*//2000'
+
+# delete the run directories for all workflows with IDs
+# beginning with "model_a/"
+cylc clean 'model_a/*'
+
+
+

For more information run cylc help id.

+

For a quick overview of the motivation see the ID post on Discourse.

+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/compatibility-mode.html b/nightly_8.4/html/7-to-8/major-changes/compatibility-mode.html new file mode 100644 index 00000000000..1d5f217de18 --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/compatibility-mode.html @@ -0,0 +1,395 @@ + + + + + + + Cylc 7 Compatibility Mode — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Cylc 7 Compatibility Mode

+
+

Does This Change Affect Me?

+

This will affect you if you want to run Cylc 7 (suite.rc) workflows +using Cylc 8.

+
+
+

Overview

+

Cylc 8 can run most Cylc 7 workflows “as is”. +The suite.rc filename triggers a backward compatibility mode in which:

+
    +
  • implicit tasks are allowed by default

    +
      +
    • (unless a rose-suite.conf file is found in the run directory +for consistency with rose suite-run behaviour)

    • +
    • (Cylc 8 does not allow implicit tasks by default)

    • +
    +
  • +
  • cycle point time zone defaults to the local time zone

    +
      +
    • (Cylc 8 defaults to UTC)

    • +
    +
  • +
  • waiting tasks are pre-spawned to mimic the Cylc 7 scheduling algorithm and +stall behaviour, and these require +suicide triggers +for alternate graph branching

    +
      +
    • (Cylc 8 spawns tasks on demand, and suicide triggers are not needed for +branching)

    • +
    +
  • +
  • succeeded task outputs are required, +so in the absence of suicide triggers the scheduler will retain other +final status tasks in the n=0 window to stall the +workflow.

    +
      +
    • (in Cylc 8, all outputs are required unless marked as +*optional* by the new ? syntax)

    • +
    +
  • +
+
+
+

Required Changes

+

Providing your Cylc 7 workflow does not use syntax that was deprecated at Cylc 7, +you may be able to run it using Cylc 8 without any modifications while in +compatibility mode.

+

First, run cylc validate with Cylc 7 on your suite.rc workflow +to check for deprecation warnings and fix those before validating with Cylc 8. +See below for an example.

+
+

Warning

+

cylc validate operates on the processed suite.rc, which +means it will not detect any deprecated syntax that is inside a +currently-unused Jinja2/EmPy if...else branch.

+
+

Some workflows may require modifications to either upgrade to Cylc 8 or make +interoperable with Cylc 8 backward compatibility mode. Read on for more details.

+
+

Cylc commands in task scripts

+

Check for any use of Cylc commands in task scripting. Some Cylc 7 commands +have been removed and some others now behave differently. +However, cylc message and cylc broadcast have not changed. +See the full list of command line interface changes +and see below for an example.

+
+
+

Python 2 to 3

+

Whereas Cylc 7 runs using Python 2, Cylc 8 runs using Python 3. This affects: +- modules imported in Jinja2 +- Jinja2 filters, tests and globals +- custom xtrigger functions

+

Note that task scripts are not affected - they run in an independent +environment.

+

See Python 2 => 3 for more information and examples of how to implement +interoperability if your workflows extend Cylc or Jinja2 with custom Python scripts.

+
+
+

Other caveats

+ +
+
+
+

Examples

+
+

Validating with Cylc 7

+

Consider this configuration:

+
+
suite.rc
+
[scheduling]
+    initial cycle point = 11000101T00
+    [[dependencies]]
+        [[[R1]]]
+            graph = task
+
+[runtime]
+    [[task]]
+        pre-command scripting = echo "Hello World"
+
+
+
+

Running cylc validate at Cylc 7 we see that the +workflow is valid, but we are warned that pre-command scripting +was replaced by pre-script at 6.4.0:

+
+
Cylc 7 validation
+
$ cylc validate .
+WARNING - deprecated items were automatically upgraded in 'suite definition':
+WARNING -  * (6.4.0) [runtime][task][pre-command scripting] -> [runtime][task][pre-script] - value unchanged
+Valid for cylc-7.8.7
+
+
+
+
+

Note

+

Cylc 7 has handled this deprecation for us, but at Cylc 8 this +workflow will fail validation.

+
+
Cylc 8 validation
+
$ cylc validate .
+IllegalItemError: [runtime][task]pre-command scripting
+
+
+
+
+

You must change the configuration yourself. In this case:

+
-     pre-command scripting = echo "Hello World"
++     pre-script = echo "Hello World"
+
+
+

Validation will now succeed.

+
+
+

Cylc commands in task scripts

+

You might have a task script that calls a Cylc command like so:

+
[runtime]
+    [[foo]]
+        script = cylc hold "$CYLC_SUITE_NAME"
+
+
+

The cylc hold command has changed in Cylc 8. It is now used for holding +tasks only; use cylc pause for entire workflows. +(Additionally, $CYLC_SUITE_NAME is deprecated in favour of +$CYLC_WORKFLOW_ID, though still supported.)

+

In order to make this interoperable, so that you can run it with both Cylc 7 +and Cylc 8 backward compatibility mode, you could do something like this +in the bash script:

+
[runtime]
+    [[foo]]
+        script = """
+            if [[ "${CYLC_VERSION:0:1}" == 7 ]]; then
+                cylc hold "$CYLC_SUITE_NAME"
+            else
+                cylc pause "$CYLC_WORKFLOW_ID"
+            fi
+        """
+
+
+

Note this logic (and the $CYLC_VERSION environment variable) is executed +at runtime on the job host.

+

Alternatively, you could use Jinja2 like so:

+
[runtime]
+    [[foo]]
+        {% if CYLC_VERSION is defined and CYLC_VERSION[0] == '8' %}
+            script = cylc pause "$CYLC_WORKFLOW_ID"
+        {% else %}
+            script = cylc hold "$CYLC_SUITE_NAME"
+        {% endif %}
+
+
+

Note this logic (and the CYLC_VERSION Jinja2 variable) is executed locally +prior to Cylc parsing the workflow configuration.

+
+
+
+

Renaming to flow.cylc

+

When your workflow runs successfully in backward compatibility mode, it is +ready for renaming suite.rc to flow.cylc. Doing this will turn off +backward compatibility mode, and validation in Cylc 8 will show +deprecation warnings.

+ +
+

Important

+

More complex workflows (e.g. those with suicide triggers) may +fail validation once backward compatibility is off - see +Graph branching, optional outputs and suicide triggers

+
+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/config-changes.html b/nightly_8.4/html/7-to-8/major-changes/config-changes.html new file mode 100644 index 00000000000..512246dd5cf --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/config-changes.html @@ -0,0 +1,290 @@ + + + + + + + Configuration Changes at Cylc 8 — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Configuration Changes at Cylc 8

+

Some configurations have moved or been renamed at Cylc 8.

+

The old configurations are now deprecated, but still supported. +These will be highlighted upon cylc validate after renaming suite.rc +to flow.cylc.

+

Because some workflows use Jinja2 or EmPy branches which may not be switched on at +the time of the initial cylc validate we have also provided +a script, cylc lint -r 728 to check for Cylc 7 +syntax which may be deprecated.

+

There are some examples below of how to upgrade:

+
+

Graph

+

Cylc 7 had unnecessarily deep nesting of graph config sections:

+
[scheduling]
+    initial cycle point = now
+    [[dependencies]]
+        [[[R1]]]
+            graph = "prep => foo"
+        [[[R/^/P1D]]]
+            graph = "foo => bar => baz"
+
+
+

Cylc 8 cleans this up:

+
[scheduling]
+    initial cycle point = now
+    [[graph]]
+        R1 = "prep => foo"
+        R/^/P1D = "foo => bar => baz"
+
+
+
+
+

Fixing deprecation warnings

+

Take the following example flow.cylc file:

+
[cylc]
+   UTC mode = True
+[scheduling]
+    initial cycle point = 2000-01-01
+    [[dependencies]]
+        [[[R1]]]
+            graph = foo => bar
+[runtime]
+    [[foo, bar]]
+
+
+

This workflow will pass validation at Cylc 8, but will give warnings:

+
$ cylc validate .
+WARNING - deprecated items were automatically upgraded in "workflow definition"
+WARNING -  * (8.0.0) [cylc] -> [scheduler] - value unchanged
+WARNING - deprecated graph items were automatically upgraded in "workflow definition":
+   * (8.0.0) [scheduling][dependencies][X]graph -> [scheduling][graph]X - for X in:
+         R1
+Valid for cylc-8.0.0
+
+
+

The warnings explain what needs to be fixed. After making the following changes, +the workflow will validate without any warnings:

+
-[cylc]
++[scheduler]
+     UTC mode = True
+ [scheduling]
+     initial cycle point = 2000-01-01
+-    [[dependencies]]
+-        [[[R1]]]
+-            graph = foo => bar
++    [[graph]]
++        R1 = foo => bar
+ [runtime]
+     [[foo, bar]]
+
+
+
+

Tip

+

Later Cylc releases will not be able to upgrade obsolete Cylc 7 +configurations. It’s a good idea to address warnings as part of routine +workflow review and maintenance to avoid problems later on.

+
+
+
+

Platforms

+ +

At Cylc 7, job hosts were defined to indicate where a job should run. +At Cylc 8, this has been replaced by Platforms.

+
 [runtime]
+     [[foo]]
+-        [[[job]]]
+-            batch system = slurm
+-        [[[remote]]]
+-            host = hpc1.login.1
++        platform = hpc1
+
+
+

For a comprehensive list of valid configuration, see: Workflow Configuration +and Global Configuration.

+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/continuing-c7-c8.html b/nightly_8.4/html/7-to-8/major-changes/continuing-c7-c8.html new file mode 100644 index 00000000000..c26831682a8 --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/continuing-c7-c8.html @@ -0,0 +1,233 @@ + + + + + + + Continuing a Cylc 7 Workflow with Cylc 8 — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Continuing a Cylc 7 Workflow with Cylc 8

+
+

Does This Change Affect Me?

+

Read this if you have a partially complete Cylc 7 workflow that you want to +continue, rather than start from scratch, with Cylc 8. Some cycling +workflows, for example, may need to run expensive “cold start” tasks and +incur a multi-cycle spin-up if started from scratch.

+
+
+

Warning

+

Cylc 8 cannot restart a Cylc 7 workflow in-place, and continuing in a new +run directory involves some careful set up (below). So, if possible you +should complete the run with Cylc 7.

+
+

To continue a Cylc 7 workflow with Cylc 8:

+
    +
  1. Stop the Cylc 7 workflow at an convenient place

    +
      +
    • Typically the end of a cycle point, to simplify the continuation

    • +
    +
  2. +
  3. Install a new instance of the workflow from +source, with Cylc 8

    +
      +
    • Adapt file paths to the new run directory structure, in workflow and task +configurations

    • +
    • Note Cylc 8 does remote file installation +when a job is first submitted to a platform

    • +
    +
  4. +
  5. Copy runtime files needed by upcoming tasks from the old to the new run +directory

    +
      +
    • This could include external files installed by initial tasks at runtime

    • +
    • Note different files could be present on different job platforms

    • +
    +
  6. +
  7. Start the new Cylc 8 run at the appropriate cycle point or task(s) in the +graph

    +
      +
    • Don’t reset the initial cycle point (in the flow.cylc or on +the command line) to the start point of the +Cylc 8 run. That would result in the “cold start” that this continuation +procedure is designed to avoid. Instead use the --start-cycle-point +option (or --start-task) with cylc play, to start at the right +place within the graph.

    • +
    +
  8. +
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/cylc-install.html b/nightly_8.4/html/7-to-8/major-changes/cylc-install.html new file mode 100644 index 00000000000..f0e5a279140 --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/cylc-install.html @@ -0,0 +1,363 @@ + + + + + + + Cylc Install — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Cylc Install

+ +
+

Does This Change Affect Me?

+

Almost certainly.

+

This change will affect you:

+
    +
  • If you use rose suite-run to install and run Cylc workflows.

  • +
  • If you usually develop Cylc workflows in the ~/cylc-run directory.

  • +
  • If you develop Cylc workflows outside of the ~/cylc-run directory and +manually copy the files to ~/cylc-run.

  • +
+
+
+

Overview

+

Cylc 7 ran workflows in ~/cylc-run/. You could develop your +workflow in ~/cylc-run or copy it after developing it elsewhere. +If you developed in the ~/cylc-run directory there was a risk that +Cylc might alter your files. If you developed elsewhere you needed to +install your workflows manually with another tool.

+

We designed Cylc 8 to help you keep your development and +running copies separate. By default you can now develop workflows in the +~/cylc-src directory. As a result, you will not change your development +copy by running a workflow. You will, however, need to install your workflow +from ~/cylc-src to ~/cylc-run using the cylc install command.

+
+

Note

+

If you have previously used Rose, cylc install functions in a +similar way to rose suite-run --install-only.

+
+

Examples:

+
    +
  • You can install a workflow from inside the source directory:

    +
    $ cd ~/cylc-src/my-workflow
    +$ cylc install
    +INSTALLED my-workflow/run1 from /home/me/cylc-src/my-workflow
    +
    +
    +
  • +
  • You can install a workflow by providing the workflow source name +(if the source directory is located in any of the +Configurable Source Directories, e.g. ~/cylc-src):

    +
    $ cylc install my-workflow
    +INSTALLED my-workflow/run2 from /home/me/cylc-src/my-workflow
    +
    +
    +
  • +
  • You can install a workflow by providing the path to the source directory:

    +
    $ cylc install ~/cylc-src/my-workflow
    +INSTALLED my-workflow/run3 from /home/me/cylc-src/my-workflow
    +
    +
    +
  • +
+
+

Note

+

Each time you run cylc install for a particular workflow, a new copy of +the workflow is installed to a new run directory. In the example above, we +created three run directories inside ~/cylc-run/my-workflow.

+
+

Once you have installed a workflow you can use cylc play to run it - see +Running Workflows.

+

You can delete installed workflows using cylc clean - see +Removing Workflows.

+

A .cylcignore file can be used to control which files cylc install +transfers to the installed workflow, see 1. File Installation for details.

+
+
+

Remote Installation

+

Remote file installation does not occur until running the workflow. +When the first task runs on a remote platform, Cylc will transfer files from +the run directory to the install target.

+

If you have used Rose 2019, you may be used to all files and directories in +the run directory being included. +However, Cylc 8 will only copy the ana, app, bin, etc and +lib directories by default (in addition to authentication files in +.service). +If you want to include custom files and directories in remote installation, +use flow.cylc[scheduler]install.

+
+

Tip

+

If you need to ensure your workflow is still +interoperable with Cylc 7, wrap it in a +Jinja2 check like so:

+
{% if CYLC_VERSION is defined and CYLC_VERSION[0] == '8' %}
+[scheduler]
+    install = my-dir/, my-file
+{% endif %}
+
+
+
+

See the user guide for more details.

+
+

Warning

+

If you have tasks that mirror/copy the run directory to a remote platform +(such as FCM make tasks), this can cause conflicts with +symlink directory setup.

+

You can find out if symlink directories are configured for the platform by +running:

+
cylc config -i '[install][symlink dirs][<platform-name>]'
+
+
+

The recommended workaround is to use a “dummy” task that runs on the +particular platform before any such mirror tasks in order to setup symlink +directories, but without running anything.

+

For example:

+
[scheduling]
+    [[graph]]
+        R1 = hpc_init => fcm_make
+
+[runtime]
+    [[hpc_init]]
+        platform = <platform-name>
+        script = true
+
+
+
+
+
+

Migrating From rose suite-run

+

The rose suite-run command has been replaced by cylc install.

+
# rose 2019 / Cylc 7
+$ rose suite-run
+
+# rose 2 / Cylc 8
+$ cylc install
+$ cylc play <id>
+
+
+

Support for the rose-suite.conf file is provided by the Cylc Rose +plugin which must be installed for Rose integration.

+
+

Installation

+

See the Installation section for instructions.

+

If Cylc Rose is installed it should appear in the list of installed +Cylc plugins:

+
$ cylc version --long
+8.0 (/path/to/cylc-8)
+
+Plugins:
+    cylc-rose       0.1.1   /path/to/cylc-rose
+
+
+
+
+

Notable differences to rose suite-run

+
+
Command line options:

The cylc install command remembers any options specified on the command +line including Rose optional configurations and template variables and +automatically applies them with future re-installations.

+
+
Rose Stem:

The rose stem command is provided by Cylc Rose. Like rose suite-run, +rose stem used to install and run workflows. It now only +installs the workflow which can then be run with cylc play.

+

See the Rose Stem documentation for more information.

+
+
Roses directory:

By default cylc install looks for workflows in ~/cylc-src, you +you may want to add ~/roses to the list of +global.cylc[install]source dirs.

+
+
Remote Installation:

With Rose 2019 / rose suite-run, files were installed on remote platforms +before the workflow started running.

+

With Rose 2 / cylc install, files are installed on remote platforms just +before the first task runs on that platform.

+

Rose used to install the entire workflow run directory to remote +platforms. It now only installs configured directories for efficiency. +See Remote Installation above for details.

+
+
+
+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/excluding-tasks.html b/nightly_8.4/html/7-to-8/major-changes/excluding-tasks.html new file mode 100644 index 00000000000..166696010e0 --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/excluding-tasks.html @@ -0,0 +1,220 @@ + + + + + + + Excluding Tasks at Start-up is Not Supported — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Excluding Tasks at Start-up is Not Supported

+
+

Does This Change Affect Me?

+

This will affect you if your workflows use the following configurations:

+
    +
  • [scheduling][special tasks]include at start-up

  • +
  • [scheduling][special tasks]exclude at start-up

  • +
+
+
+

Overview

+

The Cylc 7 scheduler allowed you to exclude tasks from the scheduler at start-up:

+
# Cylc 7 only
+[scheduling]
+   [[special tasks]]
+        include at start-up = foo, bar, baz  # Cylc 8 ERROR!
+        exclude at start-up = bar  # Cylc 8 ERROR!
+
+
+

The first config item above excludes all task names not in the include-list; +the second excludes specific tasks that would otherwise be included.

+

The Cylc 7 scheduler started up with an instance of every task in its “task +pool”, and the workflow evolved by each task spawning its own next-cycle +instance at the right time. So, if you excluded a task a start-up it would not +run in the workflow at all unless manually inserted later at runtime.

+

The Cylc 8 scheduler starts up with only the initial tasks in the graph and the +workflow evolves by spawning new tasks on demand as dictated by the graph. +Consequently excluding a task at start up as described above would have no +effect at all on most tasks.

+

This feature also predated the current Cylc dependency graph configuration. To +exclude tasks now without entirely removing them from the workflow definition, +just comment them out of the graph.

+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/index.html b/nightly_8.4/html/7-to-8/major-changes/index.html new file mode 100644 index 00000000000..b828c38593f --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/index.html @@ -0,0 +1,206 @@ + + + + + + + Detailed Description of Major Changes — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+ + +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/parameters.html b/nightly_8.4/html/7-to-8/major-changes/parameters.html new file mode 100644 index 00000000000..bc850de10ea --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/parameters.html @@ -0,0 +1,271 @@ + + + + + + + Parameters — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Parameters

+
+

does this change affect me?

+

If you use Cylc parameters with negative offsets (e.g. foo<x-1>).

+
+
+

Overview

+

There has been a subtle change in the way negative offsets are handled in parameters.

+
+
+

Example

+

If you have a parameter x with the values 1, 2 & 3:

+
[task parameters]
+   x = 1..3
+
+
+

And use it like so:

+
a<x-1> => b<x> => c<x>
+
+
+

There is some ambiguity about how this should be interpreted when x=1 +because <x-1> would be 0 which is not a valid value for the parameter +x.

+

Cylc 7 removed the part of the expression which was out of range resulting in a +partial evaluation of that line:

+
        b_x1 => c_x1  # x=1
+a_x1 => b_x2 => c_x2  # x=2
+a_x2 => b_x3 => c_x3  # x=3
+
+
+

Whereas Cylc 8 will remove everything after the first out-of-range parameter - <x-1> (so the entire line for this example):

+
a_x1 => b_x2 => c_x2  # x=2
+a_x2 => b_x2 => c_x2  # x=3
+
+
+
+
+

Migration

+

If your workflow depends on the Cylc 7 behaviour, then the solution is +to break the expression into two parts which Cylc will then evaluate separately.

+
- a<x-1> => b<x> => c<x>
++ a<x-1> => b<x>
++ b<x> => c<x>
+
+
+

Resulting in:

+
# a<x-1> => b<x>
+a_x1 => a_x2  # x=2
+a_x2 => a_x3  # x=3
+
+# b<x> => c<x>
+b_x1 => c_x1  # x=1
+b_x2 => c_x2  # x=2
+b_x3 => c_x3  # x=3
+
+
+
+
+

Line Breaks

+

Note that these expressions are all equivalent:

+ + + + + + + +
a<x-1> => b<x> => c<x>
+
+
+
a<x-1> =>
+b<x> =>
+c<x>
+
+
+
a<x-1> => b<x> => \
+c<x>
+
+
+
+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/platforms.html b/nightly_8.4/html/7-to-8/major-changes/platforms.html new file mode 100644 index 00000000000..1e9493dfed2 --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/platforms.html @@ -0,0 +1,417 @@ + + + + + + + Platforms — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Platforms

+
+

Does This Change Affect Me?

+

Cylc platforms are a new feature which replace the task job and +remote configuration sections:

+ +
+
+

Overview

+
+

Note

+
    +
  • The terms platform and job platform are equivalent.

  • +
  • The terms job runner (in Cylc 8 configurations) and batch system +(in Cylc 7 configurations) are equivalent.

  • +
+
+

Submitting a job to a job runner may require configuration.

+

In Cylc 7 this configuration must be provided for each task in the workflow +configuration (suite.rc).

+

In Cylc 8 “platforms” can be defined in the global configuration +(global.cylc) so that this configuration doesn’t have to be +repeated for each task in each workflow.

+

There may be cases where sets of platforms (for example a group of +standalone compute servers, or a pair of mirrored HPC’s) might be equally +suitable for a task. Such platforms can be set up to be platform groups

+
+

See also

+

Listing available platforms for details of how to list platforms +already defined.

+

Platform Configuration for detailed examples of platform +configurations.

+
+
+

Tip

+

Cylc 8 contains upgrade logic (see below) +which handles the deprecated Cylc 7 settings in most cases. +Unless you are in backward compatibility mode, +you should upgrade to using platforms instead. +Deprecated settings will be removed in a later release of Cylc.

+
+
+
+

What is a Platform?

+

A “platform” represents one or more hosts from which jobs can be submitted to or +polled from a common job submission system.

+

If a platform has multiple hosts Cylc will automatically select a host when +needed and will fallback to other hosts if it is not contactable.

+

A “platform group” represents a collection of independent platforms. Cylc will +automatically select a platform and will fallback to other platforms in the +group (for appropriate operations) if the platform is not contactable.

+
+
+

Examples

+
+

See also

+

global.cylc[platforms] has a detailed explanation of how +platforms and platform groups are defined.

+
+
+

Simple example

+

Consider this Cylc 7 syntax in a flow.cylc file:

+
[runtime]
+    [[mytask]]
+        [[[job]]]
+            batch system = slurm
+        [[[remote]]]
+            host = login_node01
+
+
+

The Cylc 8 global config (global.cylc) might contain:

+
[platforms]
+    [[our_cluster]]
+        hosts = login_node01, login_node02
+        job runner = slurm
+
+
+
+

Tip

+

You can view the platforms available at your site by running:

+
cylc config --platforms
+
+
+
+

The platform our_cluster matches the current configuration due to having +the same job runner (batch system) and correct hosts. Thus we can replace the +deprecated syntax:

+
 [runtime]
+     [[mytask]]
+-        [[[job]]]
+-            batch system = slurm
+-        [[[remote]]]
+-            host = login_node01
++        platform = our_cluster
+
+
+
+
+

A variety of other examples

+

Here are some example Cylc 7 task definitions:

+
[runtime]
+   [[mytask_cylc_server]]
+
+   [[mytask_big_server]]
+      [[[remote]]]
+         host = linuxbox42
+
+   [[mytask_submit_local_to_remote_computer]]
+      [[[job]]]
+         batch system = pbs
+
+   [[mytask_login_to_hpc_and_submit]]
+      [[[remote]]]
+         # e.g. rose host-select
+         host = $(supercomputer_login_node_selector_script)
+      [[[job]]]
+         batch system = slurm
+
+
+

This will result in Cylc running:

+
    +
  • mytask_cylc_server on the machine the workflow is running on.

  • +
  • mytask_big_server on linuxbox42, using background.

  • +
  • mytask_submit_local_to_remote_computer on a system where you can +use PBS to submit from the workflow server.

  • +
  • mytask_login_to_hpc_and_submit on a host set by the subshelled +script using Slurm.

  • +
+

At Cylc 8 the equivalent might be:

+
[runtime]
+    [[mytask_cylc_server]]
+
+    [[mytask_big_server]]
+        platform = linuxbox42
+
+    [[mytask_submit_local_to_remote_computer]]
+        platform = pbs_local
+
+    [[mytask_login_to_hpc_and_submit]]
+        # Recommended:
+        platform = slurm_supercomputer
+        # ...but This is still legal:
+        #platform = $(selector-script)
+
+
+

And the platform settings for these examples might be:

+
[platforms]
+    [[linuxbox\d\d]]  # Regex to allow any linuxboxNN to use this definition
+        # Without a hosts, platform name is used as a single host.
+
+    [[pbs_local]]
+        # A computer with PBS, that takes local job submissions
+        job runner = pbs
+        hosts = localhost
+        install target = localhost
+
+    [[slurm_supercomputer]]
+        # This computer with Slurm requires you to use a login node.
+        hosts = login_node01, login_node02  # Cylc will pick a host.
+        job runner = slurm
+
+
+

Note that in these examples, it is assumed that linuxboxNN, pbs_local and +slurm_supercomputer have distinct file systems. +Sets of platforms which share a file system must specify +a single install target.

+
+

Note

+

If an install target is not set, a platform will use its own platform name +as the install target name. If multiple platforms share a file system +but have separate install targets task initialization +will fail.

+
+
+
+
+

How Cylc 8 handles host-to-platform upgrades

+

If you are using the deprecated [remote] and [job] runtime sections, +Cylc 8 will attempt to find a platform which matches the task specification.

+
+

Important

+

Cylc 8 needs platforms matching the Cylc 7 job configuration to be +available in global.cylc[platforms].

+
+
+

Example

+

If, for example you have a Cylc 8 global.cylc with the following +platforms section:

+
[platforms]
+    [[supercomputer_A]]
+        hosts = localhost
+        job runner = slurm
+        install target = localhost
+    [[supercomputer_B]]
+        hosts = tigger, wol, eeyore
+        job runner = pbs
+
+
+

And you have a workflow runtime configuration:

+
[runtime]
+    [[task1]]
+        [[[job]]]
+            batch system = slurm
+    [[task2]]
+        [[[remote]]]
+            host = eeyore
+        [[[job]]]
+            batch system = pbs
+
+
+

Then, task1 will be assigned platform +supercomputer_A because the specified host (implicitly localhost) +is in the list of hosts for supercomputer_A and the batch system is the same. +Likewise, task2 will run on supercomputer_B.

+
+

Important

+

For simplicity, and because the host key is a special case (it can +match and host in [platform]hosts) we only show these two config keys +here. In reality, Cylc 8 compares the whole of +[<task>][job] and [<task>][remote] +sections and all items must match to select a platform.

+
+
+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/play-pause-stop.html b/nightly_8.4/html/7-to-8/major-changes/play-pause-stop.html new file mode 100644 index 00000000000..bf9ca43be9b --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/play-pause-stop.html @@ -0,0 +1,311 @@ + + + + + + + Play Pause Stop — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Play Pause Stop

+
+

Does This Change Affect Me?

+

Yes if you run Cylc workflows.

+
+
+

Overview

+

Cylc 8 uses a simplified model for controlling workflows based on the controls +of a tape player.

+

There are now three controls, play, pause and stop:

+
    +
  • When a workflow is playing, the scheduler is running.

  • +
  • When a workflow is paused, no new jobs will be submitted.

  • +
  • When a workflow is stopped the scheduler is no longer running.

  • +
+

These controls are available in the web GUI or on the command line with the +commands:

+
    +
  • cylc play

  • +
  • cylc pause

  • +
  • cylc stop

  • +
+

A workflow can be safely played, paused and stopped any number of times without +interrupting the workflow.

+
+
+

Re-Running Workflows

+

The cylc play command will always pick up where it left off (a +restart).

+

If you want to re-run the entire workflow again from the start either:

+
    +
  • Install a new run.

  • +
  • Or if you want to keep the data from the old run start a new flow at +the beginning of the graph, and stop the original flow.

  • +
+

It is still possible to re-run workflows in-place in the Cylc 7 manner, however, +this is discouraged. +To do this remove the workflow database as well as any other evidence of the +previous run that is no longer desired:

+
# remove the workflow database, the work, share and log directories
+cylc clean <id> --rm .service/db:work:share:log
+
+# only remove the worflow database
+$ cylc clean <id> --rm .service/db
+
+
+

Then restart with cylc play.

+
+
+

Hold & Release

+

The cylc hold and cylc release commands are still present. These +work on individual tasks rather than the workflow as a whole.

+
+
+

Mapping To Old Commands

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Cylc 7

Rose 2019

Cylc 8 (Rose 2)

Play

cylc run <id>
+
+
+
rose suite-run
+
+
+
cylc play <id>
+
+
+

Pause

cylc hold <id>
+
+
+
cylc hold <id>
+
+
+
cylc pause <id>
+
+
+

Resume

cylc release <id>
+
+
+
cylc release <id>
+
+
+
cylc play <id>
+
+
+

Stop

cylc stop <id>
+
+
+
rose suite-shutdown
+
+
+
cylc stop <id>
+
+
+
+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/python-2-3.html b/nightly_8.4/html/7-to-8/major-changes/python-2-3.html new file mode 100644 index 00000000000..49e9ce30241 --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/python-2-3.html @@ -0,0 +1,302 @@ + + + + + + + Python 2 => 3 — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Python 2 => 3

+
+

Does This Change Affect Me?

+

This change will affect you if your workflows extend Cylc or Jinja2 with +custom Python scripts.

+

This does not impact task scripts; Cylc can still run Python 2 +tasks if desired.

+
+
+

Overview

+

Cylc 7 ran under Python 2; Cylc 8 runs under Python 3.

+

Cylc can be extended with custom Python scripts. These scripts are run under +the same version of Python used by Cylc.

+

As a result, if you are moving from Cylc 7 to Cylc 8, you must upgrade any +scripts from Python 2 to Python 3 in the process.

+

If you want to support both Cylc 7 and 8, you must support both Python 2 and 3. +There are tools to help you do this, e.g. six.

+
+
+

Impacted Scripts

+

The following scripts must be upgraded if used:

+
+
Custom Jinja2 Filters, Tests and Globals

These allow you to extend Jinja2 with Python code.

+

These scripts are located in the following directories within a workflow:

+
    +
  • Jinja2Filters

  • +
  • Jinja2Tests

  • +
  • Jinja2Globals

  • +
+
+
Modules imported by Jinja2

Python modules can be imported from Jinja2 e.g:

+
{% from "os" import path %}
+
+
+
+
Custom Trigger Functions

Any custom xtrigger functions.

+
+
+
+
+

Package Name Changes

+

Three Python packages have been renamed between Cylc 7 and Cylc 8:

+
    +
  • cylc => cylc.flow

  • +
  • isodatetime => metomi.isodatetime

  • +
  • rose => metomi.rose

  • +
+

If you are importing from these packages you will need to update the package names.

+

Here are some examples:

+

Convert Python code from Cylc 7 to Cylc 8:

+
- from cylc import LOG
++ from cylc.flow import LOG
+- from isodatetime.data import Duration
++ from metomi.isodatetime.data import Duration
+
+
+

Python code which supports both Cylc 7 & Cylc 8:

+
import sys
+if sys.version[0] == '3':
+    from cylc.flow import LOG
+    from metomi.isodatetime.data import Duration
+else:
+    from cylc import LOG
+    from isodatetime.data import Duration
+
+
+

Convert Jinja2 code from Cylc 7 to Cylc 8:

+
#!Jinja2
+- {% from "cylc" import LOG %}
++ {% from "cylc.flow" import LOG %}
+  {% do LOG.debug("Hello World!") %}
+
+
+

Jinja2 code which supports both Cylc 7 & Cylc 8:

+
#!Jinja2
+{% from "sys" import version -%}
+{% if version[0] == '3' -%}
+    {% from "cylc.flow" import LOG -%}
+{% else -%}
+    {% from "cylc" import LOG -%}
+{% endif -%}
+
+{% do LOG.debug("Hello World!") %}
+
+
+
+
+

Jinja2 - integers with leading zeros

+

Integers with leading zeros in Jinja2 expressions are now illegal and will +cause an error like Jinja2Error: expected token 'x', got 'integer'. +For example:

+
$ cylc validate my-workflow
+Jinja2Error: expected token 'end of statement block', got 'integer'
+File ~/cylc-run/my-workflow/flow.cylc
+  {% if START_HOUR == 06 or START_HOUR == 12 %}       <-- TemplateSyntaxError
+
+
+

The solution in this case is:

+
-{% if START_HOUR == 06 or START_HOUR == 12 %}
++{% if START_HOUR == 6 or START_HOUR == 12 %}
+
+
+
+
+

Rose

+

The same changes also impact Rose extensions:

+ +
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/remote-owner.html b/nightly_8.4/html/7-to-8/major-changes/remote-owner.html new file mode 100644 index 00000000000..3dde271b19b --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/remote-owner.html @@ -0,0 +1,217 @@ + + + + + + + Remote Usernames — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Remote Usernames

+
+

does this change affect me?

+ +
+
+

Overview

+

If your username differs between the scheduler host and job hosts, then +you may have configured Cylc to run jobs under the correct account using +flow.cylc[runtime][<namespace>][remote]owner +or used the --owner Cylc command line option +with commands which access remote hosts.

+

Cylc no longer supports specifying the username in this way, we suggest +configuring your remote username using the SSH configuration file e.g:

+
Host MyHost
+  User root
+
+
+

SSH will then automatically use the configured username when connecting to the +remote machine.

+

Since Cylc uses SSH and Rsync to manage job hosts, the SSH config also configures +Cylc.

+
+

Note

+

This approach using the SSH configuration file also works with Cylc 7.

+
+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/scheduling.html b/nightly_8.4/html/7-to-8/major-changes/scheduling.html new file mode 100644 index 00000000000..db45ee2cfee --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/scheduling.html @@ -0,0 +1,234 @@ + + + + + + + Scheduling Algorithm — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Scheduling Algorithm

+ +

Cylc can manage infinite workflows of repeating tasks:

+../../_images/cycling.png +

Cylc 8 has a new scheduling algorithm that:

+
    +
  • Is much more efficient because it only has to manage active tasks

    +
      +
    • waiting tasks are not pre-spawned before they are needed

    • +
    • succeeded tasks are not kept across the active task window

    • +
    • no costly indiscriminate dependency matching is done

    • +
    +
  • +
  • Distinguishes between optional and +required task outputs, to support:

    + +
  • +
  • Causes no implicit dependence on previous-instance job submit

    +
      +
    • instances of same task can run out of cycle point order

    • +
    • the workflow will not unnecessarily stall downstream of failed tasks

    • +
    +
  • +
  • Provides a sensible active-task based window on the evolving workflow

    +
      +
    • (to fully understand which tasks appeared in the Cylc 7 GUI you had to +understand the scheduling algorithm)

    • +
    +
  • +
  • Supports multiple concurrent flows within the same workflow.

  • +
  • Can start a workflow from any task or tasks in the graph (no need for +checkpoint restart)

  • +
  • Can limit activity within as well as across cycles, without risking a stall

  • +
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/suicide-triggers.html b/nightly_8.4/html/7-to-8/major-changes/suicide-triggers.html new file mode 100644 index 00000000000..ec229963fed --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/suicide-triggers.html @@ -0,0 +1,282 @@ + + + + + + + Graph branching, optional outputs and suicide triggers — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Graph branching, optional outputs and suicide triggers

+

Cylc 8 has a new scheduling algorithm and +a new syntax for dealing with tasks that may not necessarily complete. +It handles graphs in an event-driven manner which means +that a workflow can follow different paths in different eventualities (without +the need for suicide triggers). This is called graph branching.

+
+

Does This Change Affect Me?

+

This change affects you if you are upgrading a Cylc 7 workflow that +contains graph branches that are not necessarily expected to complete +at runtime. You might get a GraphParseError during validation with +Cylc 8.

+

Typically this will be the case if you are using +suicide triggers (marked by ! before the +task name in the graph, e.g. foo:fail => !foo).

+

You should not perform this upgrade if still in Cylc 7 Compatibility Mode +(suite.rc filename).

+
+
+

Required Changes

+

Any task outputs that are not necessarily expected to +complete must be marked as optional using ?. +Suicide triggers can then be removed.

+
+
+

Example

+

Here is an example Cylc 7 graph:

+
foo:fail => recover
+
+foo | recover => bar
+
+# Remove the "recover" task in the success case.
+foo => ! recover
+# Remove the "foo" task in the fail case.
+recover => ! foo
+
+
+
+

digraph Example { +subgraph cluster_1 { + label = ":fail" + color = "red" + fontcolor = "red" + style = "dashed" + recover +} + +foo -> recover +recover -> bar [arrowhead="onormal"] +foo -> bar [arrowhead="onormal" weight=2] +}

+
+

Validating this with Cylc 8 will give an error:

+
$ cylc validate .
+GraphParseError: Opposite outputs foo:succeeded and foo:failed must both be optional if both are used
+
+
+

In Cylc 8, all task outputs are required to complete +unless otherwise indicated. However, it is impossible for both :succeed +and :fail to occur when a task runs.

+

The solution is to mark the outputs which are optional +(in this case foo:succeed and foo:fail) with a ? in the graph. +Also, the suicide triggers can be removed.

+
- foo:fail => recover
++ foo:fail? => recover
+
+- foo | recover => bar
++ foo? | recover => bar
+
+- # Remove the "recover" task in the success case.
+- foo => ! recover
+- # Remove the "foo" task in the fail case.
+- recover => ! foo
+
+
+

In Cylc 7, suicide triggers were used to remove tasks that did not complete +during runtime. Cylc 8’s event-driven graph handling allows such graph +branching using optional output syntax, without the need for suicide triggers. +(Suicide triggers are still supported in Cylc 8; however, they are most +likely unnecessary.)

+
+

Tip

+

Remember: foo? is short for foo:succeed?. It is the output +that is optional, not the task itself.

+
+
+

See also

+ +
+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/task-job-states.html b/nightly_8.4/html/7-to-8/major-changes/task-job-states.html new file mode 100644 index 00000000000..c31d8166872 --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/task-job-states.html @@ -0,0 +1,201 @@ + + + + + + + Task/Job States — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Task/Job States

+
+

See also

+ +
+

Tasks are nodes in the abstract workflow graph representing +processes that should run once their prerequisites are satisfied. Jobs are the real processes submitted to execute these tasks (or at least, at +the submission stage, real job scripts). A task can have multiple jobs, by +automatic retries and manual re-triggering.

+

Cylc 7 had 13 task/job states. The GUI only showed tasks, with job data +from the latest job.

+

Cylc 8 has only 8 task/job states. The Cylc 8 UI shows both task and jobs. +Task icons are monochrome circles; job icons are coloured squares. The running +task icon incorporates a radial progress indicator.

+../../_images/task-job.png +
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/template-vars.html b/nightly_8.4/html/7-to-8/major-changes/template-vars.html new file mode 100644 index 00000000000..1f30ce78228 --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/template-vars.html @@ -0,0 +1,266 @@ + + + + + + + Template Variables — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Template Variables

+
+

Does This Change Affect Me?

+

Read this section if you set Cylc template variables on the command line +using the -s, --set or -set-file options.

+

This does not affect the Rose jinja2:suite.rc and +empy:suite.rc variables set using the -S option to the +rose suite-run command.

+
+
+

Overview

+

Template variables are passed to Jinja2 or +EmPy for parsing the workflow definition in the +flow.cylc file.

+

In Cylc 7 template variables could only be strings, in Cylc 8 they can be any +valid Python literal including numbers, booleans, and lists.

+
+
+

Changes

+

Strings must be explicitly quoted i.e. key="value" rather than key=value.

+
+
+

Example

+

Setting template variables on the command line:

+
# Cylc 7
+cylc run <suite> -s 'FOO=abc'
+# Cylc 8
+cylc play <flow> -s 'FOO="abc"'
+
+
+

Setting template variables in a “set file” (using --set-file):

+
# Cylc 7
+FOO = abc
+BAR = bcd
+
+# Cylc 8
+FOO = "abc"
+BAR = "bcd"
+
+
+
+
+

New Features

+
+

Any valid Python literals

+

Template variables can now be any valid Python literals e.g:

+
"string"   # string
+123        # integer
+12.34      # float
+True       # boolean
+None       # None type
+[1, 2, 3]  # list
+(1, 2, 3)  # tuple
+{1, 2, 3}  # set
+{"a": 1, "b": 2, "c": 3}  # dictionary
+
+
+

See Default Values and Template Variables for more information.

+
+
+

Shorthand for list of strings

+
+

Added in version 8.2.

+
+

A new shorthand argument (-z/--set-list/--set-template) +has been introduced allowing easier definition of template +variables containing lists of strings on the command line:

+
# Before (still works)
+cylc <command> --set "X=['a', 'b', 'c']"
+
+# After
+cylc <command> --set-list X=a,b,c
+
+
+
+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/major-changes/ui.html b/nightly_8.4/html/7-to-8/major-changes/ui.html new file mode 100644 index 00000000000..28bfa54c8b9 --- /dev/null +++ b/nightly_8.4/html/7-to-8/major-changes/ui.html @@ -0,0 +1,258 @@ + + + + + + + Cylc 8 UIs — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Cylc 8 UIs

+

There are two UI options available to monitor and control workflows at Cylc 8.

+
+

Cylc Tui

+

Cylc Tui (TUI = Terminal User Interface) is a command line version of the GUI +which comes packaged with the Cylc scheduler.

+

It can be used to monitor and control any workflows running under your user +account, trigger tasks, access log files and perform other common activities.

+

Start Tui by running the cylc tui command.

+
+../../_images/tui-1.png +
+

Tui showing the details of a failed job.

+
+
+
+../../_images/tui-2.png +
+

A list of actions that can be performed on the selected task.

+
+
+
+../../_images/tui-3.png +
+

Tui displaying the workflow configuration. It can also show scheduler and +job log files.

+
+
+

Tui replaces the Cylc 7 cylc monitor command.

+
+
+

Cylc Web GUI

+

The Cylc GUI application is a monitoring and control application which runs in +a web browser, it is distributed in the Cylc UI Server package which comes +separately from the core scheduler.

+

Start the GUI server and open the web app in your browser by running +cylc gui.

+
+../../_images/cylc-ui-dash.png +
+

The GUI homepage.

+
+
+
+../../_images/cylc-ui-tree.png +
+

The GUI displaying a workflow using the “tree” view.

+
+
+

See UI Server Configuration for how to configure the GUI.

+

As some workflows can be very large, or even infinite, the GUI uses a “window” +system to determine what to display. For more information, see The “n” Window.

+
+
+

Cylc Hub

+

The Cylc 8 GUI can be deployed with Jupyter Hub to support multi-user access +where it is possible to grant users the permission to view and interact with +workflows running under other user accounts. In these deployments, users will +have to authenticate when they open the GUI in the browser.

+

The central server is started by the cylc hub command.

+
+../../_images/hub.png +
+

The Jupyter Hub authentication page in a multi-user setup.

+
+
+

Multi-user setups need to be configured by site administrators, for more +information see Authorizing Others to Access Your Workflows.

+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/7-to-8/summary.html b/nightly_8.4/html/7-to-8/summary.html new file mode 100644 index 00000000000..39152b4da9e --- /dev/null +++ b/nightly_8.4/html/7-to-8/summary.html @@ -0,0 +1,432 @@ + + + + + + + Summary Of Major Changes — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Summary Of Major Changes

+
+

Terminology

+

Cylc now uses more widely understood terms for several core concepts.

+ + + + + + + + + + + + + + + + + + + + +

Cylc 7 Term

Cylc 8 Term

suite

workflow

batch system

job runner

suite daemon

scheduler

suite.rc

flow.cylc

+

Note the configuration filename is now flow.cylc, not suite.rc.

+
+
+

Cylc 7 Compatibility Mode

+

Continuing to use the old suite.rc filename triggers a backward +compatibility mode in Cylc 8 which supports Cylc 7 +workflow configurations out of the box, with +some caveats. However, to future-proof +your workflow and take full advantage of Cylc 8 you should upgrade to Cylc 8 syntax.

+
+
+

Upgrading To Cylc 8

+
+

See also

+ +
+

There have been some configuration changes at Cylc 8. +To upgrade your Cylc 7 suite to a Cylc 8 workflow, first make sure it validates +in Cylc 7 without any warnings, then rename the workflow configuration file +from suite.rc to flow.cylc, then run cylc validate in Cylc 8 and +take action on any warnings.

+
+

Note

+

Validation warnings use a shorthand notation +to refer to nested configuration settings on a single line, like this: +[section][sub-section]item.

+
+
+
+

New Web and Terminal UIs

+
+

See also

+ +
+

At Cylc 8, there are two UIs available to monitor and control your workflows:

+
    +
  • a terminal UI application

    +
    +
    cylc tui
    +
    +
    +
    +
  • +
  • a web based UI application (requires Cylc UI Server)

    +
    +
    cylc gui
    +
    +
    +
    +
  • +
+
+
+

Command Changes

+

cylc run <suite_name> at Cylc 7 has become cylc play <workflow_id>.

+
+

See also

+ +
+

At Cylc 8, use cylc pause <workflow_id> to pause a workflow, halting all job +submission. To restart the workflow, use cylc play <workflow_id>.

+

To start a fresh run, use cylc install and play it safely in the new run +directory.

+

(Note that cylc hold and cylc release pause and release individual tasks.)

+
+
+

Task/Job States

+

Tasks are nodes in the abstract workflow graph, representing +applications to run at the appropriate point in the workflow. A job +is the script (and subsequent process) submitted by Cylc to +actually run the application. A task can have multiple jobs as the result of +automatic retries or manual re-triggering.

+

The 13 task/job states in Cylc 7 have been simplified to 8. Tasks and jobs have been +separated and states of both can be viewed in the GUI.

+../_images/task-job.png +

For more information, see Task/Job States.

+
+
+

Optional and Required Task Outputs

+
+

See also

+ +
+

By default, all Cylc 8 tasks are required to succeed - i.e., success is +a required output. Tasks with final status and incomplete +outputs get retained in the n=0 window pending user +intervention, which will stall the workflow.

+

Alternatively, outputs can be marked as optional, +which allows optional graph branching.

+

This allows the scheduler to correctly diagnose workflow completion.

+
+
+

Platform Awareness

+
+

See also

+

Platforms at Cylc 8.

+
+

Cylc 7 was aware of individual job hosts - one selected a host using: +[runtime][<namespace>][remote]host.

+

Cylc 8 is aware of sets of host settings called +[job] platforms. To choose a platform for a task use +[runtime][<namespace>]platform

+

Hosts of a platform must share a file system and job runner: +If one host is unavailable Cylc 8 can use other hosts +on the same platform to interact with jobs.

+

The same hosts can belong to multiple platforms, for example +you might be able to use the same host to launch both background and Slurm +jobs.

+
+

Note

+

Cylc 8 will pick a sensible platform for your Cylc 7 settings, +These deprecated settings will be removed in a future release.

+
+
+
+

Workflow Installation

+

Cylc 8 supports workflow installation.

+

For users of Rose, this replaces the functionality of rose suite-run.

+
+

Cylc Install

+
+

See also

+ +
+

Cylc install cleanly separates workflow source directory from +run directory. It installs workflow files ready for cylc play.

+
$ pwd
+~/cylc-src/demo
+
+$ ls
+flow.cylc
+
+$ cylc install
+INSTALLED demo/run1 from /home/oliverh/cylc-src/demo
+
+$ cylc play demo
+...
+demo/run1: oliver.niwa.local PID=6702
+
+
+

By default, run numbers increment with each install.

+
+
+

File Installation

+

When the first job runs on a remote platform (after start-up, or after a cylc reload), a +remote initialization process is triggered to install workflow files there.

+
+ +
+
+

Removing Workflows

+

Workflows can be deleted with cylc clean - see Removing Workflows. This +replaces the rose suite-clean functionality.

+
+
+

Architecture

+

There have been fundamental changes to the architecture of Cylc. You can read +about the new system design here Architecture.

+
+
+

Scheduling Algorithm

+

The scheduling algorithm has been changed, more information is available: +Scheduling Algorithm.

+
+
+

Other Changes

+

There are an assortment of other features implemented at Cylc 8. Some noteworthy +minor changes include:

+
+
Runahead Limit

The default runahead limit has been increased from three cycles to five.

+
+
Queues

Internal Queues are now more efficient (for the scheduler), +we now recommend using queues to restrict the number of running tasks in +situations where graphing may have been used previously.

+
+
Time Zones

[scheduler]cycle point time zone now defaults to UTC, unless you +are working in Cylc 7 Compatibility Mode.

+
+
Job Scripts

All user-defined task scripting now runs in a subshell, so you can safely +switch Python environments inside tasks without affecting Cylc. +Further information is available in the User Guide: Job Scripts.

+
+
Packaging

Cylc 8 (and its package dependencies) is now available from Conda Forge and PyPI +for installations into a Python 3 virtual environment.

+
+
Remote usernames

If usernames differ on remote job hosts they must now be configured using +an SSH config file rather than the via Cylc 7 [remote]owner configuration. +See Remote Usernames.

+
+
+
+
+ + +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_images/analysis_view.gif b/nightly_8.4/html/_images/analysis_view.gif new file mode 100644 index 00000000000..c54b5c6d434 Binary files /dev/null and b/nightly_8.4/html/_images/analysis_view.gif differ diff --git a/nightly_8.4/html/_images/conditional-triggers.png b/nightly_8.4/html/_images/conditional-triggers.png new file mode 100644 index 00000000000..96b2af67c68 Binary files /dev/null and b/nightly_8.4/html/_images/conditional-triggers.png differ diff --git a/nightly_8.4/html/_images/cycling.png b/nightly_8.4/html/_images/cycling.png new file mode 100644 index 00000000000..b7be9a34c52 Binary files /dev/null and b/nightly_8.4/html/_images/cycling.png differ diff --git a/nightly_8.4/html/_images/cylc-completion.bash.gif b/nightly_8.4/html/_images/cylc-completion.bash.gif new file mode 100644 index 00000000000..5477aa9f42b Binary files /dev/null and b/nightly_8.4/html/_images/cylc-completion.bash.gif differ diff --git a/nightly_8.4/html/_images/cylc-graph-group-by-cycle-point.png b/nightly_8.4/html/_images/cylc-graph-group-by-cycle-point.png new file mode 100644 index 00000000000..518537b3494 Binary files /dev/null and b/nightly_8.4/html/_images/cylc-graph-group-by-cycle-point.png differ diff --git a/nightly_8.4/html/_images/cylc-graph-reversible.svg b/nightly_8.4/html/_images/cylc-graph-reversible.svg new file mode 100644 index 00000000000..72327dafef5 --- /dev/null +++ b/nightly_8.4/html/_images/cylc-graph-reversible.svg @@ -0,0 +1,77 @@ + + + + + + +_anonymous_0 +cluster_1 + + +cluster_2 + + + +1/foo + +foo + + +1/baz + +baz + + +1/foo->1/baz + + + + +1/bar + +bar + + +1/bar->1/baz + + + + +2/bar + +bar + + +2/baz + +baz + + +2/foo->2/baz + + + + +2/foo + +foo + + +2/bar->2/baz + + + + + diff --git a/nightly_8.4/html/_images/cylc-graph.gif b/nightly_8.4/html/_images/cylc-graph.gif new file mode 100644 index 00000000000..733b6e92081 Binary files /dev/null and b/nightly_8.4/html/_images/cylc-graph.gif differ diff --git a/nightly_8.4/html/_images/cylc-graph.png b/nightly_8.4/html/_images/cylc-graph.png new file mode 100644 index 00000000000..4e108700754 Binary files /dev/null and b/nightly_8.4/html/_images/cylc-graph.png differ diff --git a/nightly_8.4/html/_images/cylc-gui-scan-view.png b/nightly_8.4/html/_images/cylc-gui-scan-view.png new file mode 100644 index 00000000000..8b33785cdb4 Binary files /dev/null and b/nightly_8.4/html/_images/cylc-gui-scan-view.png differ diff --git a/nightly_8.4/html/_images/cylc-gui-table-view.png b/nightly_8.4/html/_images/cylc-gui-table-view.png new file mode 100644 index 00000000000..6c237d76a3c Binary files /dev/null and b/nightly_8.4/html/_images/cylc-gui-table-view.png differ diff --git a/nightly_8.4/html/_images/cylc-gui-tree-view.png b/nightly_8.4/html/_images/cylc-gui-tree-view.png new file mode 100644 index 00000000000..7df1c4d49ba Binary files /dev/null and b/nightly_8.4/html/_images/cylc-gui-tree-view.png differ diff --git a/nightly_8.4/html/_images/cylc-gui-views-button.png b/nightly_8.4/html/_images/cylc-gui-views-button.png new file mode 100644 index 00000000000..1cd741543c0 Binary files /dev/null and b/nightly_8.4/html/_images/cylc-gui-views-button.png differ diff --git a/nightly_8.4/html/_images/cylc-set-outputs.gif b/nightly_8.4/html/_images/cylc-set-outputs.gif new file mode 100644 index 00000000000..a731371ae97 Binary files /dev/null and b/nightly_8.4/html/_images/cylc-set-outputs.gif differ diff --git a/nightly_8.4/html/_images/cylc-set.gif b/nightly_8.4/html/_images/cylc-set.gif new file mode 100644 index 00000000000..9ab94c7473b Binary files /dev/null and b/nightly_8.4/html/_images/cylc-set.gif differ diff --git a/nightly_8.4/html/_images/cylc-tools.png b/nightly_8.4/html/_images/cylc-tools.png new file mode 100644 index 00000000000..298445dff3e Binary files /dev/null and b/nightly_8.4/html/_images/cylc-tools.png differ diff --git a/nightly_8.4/html/_images/cylc-ui-dash.png b/nightly_8.4/html/_images/cylc-ui-dash.png new file mode 100644 index 00000000000..81bd5c6c90c Binary files /dev/null and b/nightly_8.4/html/_images/cylc-ui-dash.png differ diff --git a/nightly_8.4/html/_images/cylc-ui-tree.png b/nightly_8.4/html/_images/cylc-ui-tree.png new file mode 100644 index 00000000000..11c5d9f58a6 Binary files /dev/null and b/nightly_8.4/html/_images/cylc-ui-tree.png differ diff --git a/nightly_8.4/html/_images/edit-a-tasks-configuration.gui.gif b/nightly_8.4/html/_images/edit-a-tasks-configuration.gui.gif new file mode 100644 index 00000000000..e9df3a18b2b Binary files /dev/null and b/nightly_8.4/html/_images/edit-a-tasks-configuration.gui.gif differ diff --git a/nightly_8.4/html/_images/edit-runtime-screenshot.png b/nightly_8.4/html/_images/edit-runtime-screenshot.png new file mode 100644 index 00000000000..264b0f5f9e7 Binary files /dev/null and b/nightly_8.4/html/_images/edit-runtime-screenshot.png differ diff --git a/nightly_8.4/html/_images/edit-the-workflow-configuration.tui.gif b/nightly_8.4/html/_images/edit-the-workflow-configuration.tui.gif new file mode 100644 index 00000000000..77b27980d37 Binary files /dev/null and b/nightly_8.4/html/_images/edit-the-workflow-configuration.tui.gif differ diff --git a/nightly_8.4/html/_images/eg2-dynamic.png b/nightly_8.4/html/_images/eg2-dynamic.png new file mode 100644 index 00000000000..34a8eb05803 Binary files /dev/null and b/nightly_8.4/html/_images/eg2-dynamic.png differ diff --git a/nightly_8.4/html/_images/eg2-static.png b/nightly_8.4/html/_images/eg2-static.png new file mode 100644 index 00000000000..4bd6087adad Binary files /dev/null and b/nightly_8.4/html/_images/eg2-static.png differ diff --git a/nightly_8.4/html/_images/failure-recovery.png b/nightly_8.4/html/_images/failure-recovery.png new file mode 100644 index 00000000000..625a11bd3c4 Binary files /dev/null and b/nightly_8.4/html/_images/failure-recovery.png differ diff --git a/nightly_8.4/html/_images/fam-to-fam-1.png b/nightly_8.4/html/_images/fam-to-fam-1.png new file mode 100644 index 00000000000..e263198d12a Binary files /dev/null and b/nightly_8.4/html/_images/fam-to-fam-1.png differ diff --git a/nightly_8.4/html/_images/fam-to-fam-2.png b/nightly_8.4/html/_images/fam-to-fam-2.png new file mode 100644 index 00000000000..a0c2b97b3bc Binary files /dev/null and b/nightly_8.4/html/_images/fam-to-fam-2.png differ diff --git a/nightly_8.4/html/_images/gantt_view.png b/nightly_8.4/html/_images/gantt_view.png new file mode 100644 index 00000000000..454167a24f8 Binary files /dev/null and b/nightly_8.4/html/_images/gantt_view.png differ diff --git a/nightly_8.4/html/_images/graphviz-01cdfbbf3d7a8a7da6b86824adc2682acb58bc7c.svg b/nightly_8.4/html/_images/graphviz-01cdfbbf3d7a8a7da6b86824adc2682acb58bc7c.svg new file mode 100644 index 00000000000..6a501709030 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-01cdfbbf3d7a8a7da6b86824adc2682acb58bc7c.svg @@ -0,0 +1,244 @@ + + + + + + +example + + +cluster_1 + +1 + + +cluster_2 + +2 + + +cluster_3 + +3 + + + +1/pur + +buy_ingredients +1 + + + +1/mak + +make_dough +1 + + + +1/pur->1/mak + + + + + +1/bak + +bake_bread +1 + + + +1/mak->1/bak + + + + + +1/sel + +sell_bread +1 + + + +1/bak->1/sel + + + + + +1/cle + +clean_oven +1 + + + +1/bak->1/cle + + + + + +1/pre + +pre_heat_oven +1 + + + +1/pre->1/bak + + + + + +2/pur + +buy_ingredients +2 + + + +2/mak + +make_dough +2 + + + +2/pur->2/mak + + + + + +2/bak + +bake_bread +2 + + + +2/mak->2/bak + + + + + +2/sel + +sell_bread +2 + + + +2/bak->2/sel + + + + + +2/cle + +clean_oven +2 + + + +2/bak->2/cle + + + + + +2/pre + +pre_heat_oven +2 + + + +2/pre->2/bak + + + + + +3/pur + +buy_ingredients +3 + + + +3/mak + +make_dough +3 + + + +3/pur->3/mak + + + + + +3/bak + +bake_bread +3 + + + +3/mak->3/bak + + + + + +3/sel + +sell_bread +3 + + + +3/bak->3/sel + + + + + +3/cle + +clean_oven +3 + + + +3/bak->3/cle + + + + + +3/pre + +pre_heat_oven +3 + + + +3/pre->3/bak + + + + + diff --git a/nightly_8.4/html/_images/graphviz-0b0909ede98c7ce9e0a52dfc78d5a8fb69f0abb9.svg b/nightly_8.4/html/_images/graphviz-0b0909ede98c7ce9e0a52dfc78d5a8fb69f0abb9.svg new file mode 100644 index 00000000000..8dd48cfe61d --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-0b0909ede98c7ce9e0a52dfc78d5a8fb69f0abb9.svg @@ -0,0 +1,55 @@ + + + + + + +Example + + + +ENGINE + +ENGINE + + + +TURBINE_ENGINE + +TURBINE_ENGINE + + + +ENGINE->TURBINE_ENGINE + + + + + +INTERNAL_COMBUSTION_ENGINE + +INTERNAL_COMBUSTION_ENGINE + + + +ENGINE->INTERNAL_COMBUSTION_ENGINE + + + + + +HUMAN_ENGINE + +HUMAN_ENGINE + + + +ENGINE->HUMAN_ENGINE + + + + + diff --git a/nightly_8.4/html/_images/graphviz-0bee4c9c9c742616fb232cb9cddb1033b1add029.svg b/nightly_8.4/html/_images/graphviz-0bee4c9c9c742616fb232cb9cddb1033b1add029.svg new file mode 100644 index 00000000000..941d6982b98 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-0bee4c9c9c742616fb232cb9cddb1033b1add029.svg @@ -0,0 +1,115 @@ + + + + + + +Example + + + +VEHICLE + +VEHICLE + + + +AIR_VEHICLE + +AIR_VEHICLE + + + +VEHICLE->AIR_VEHICLE + + + + + +LAND_VEHICLE + +LAND_VEHICLE + + + +VEHICLE->LAND_VEHICLE + + + + + +WATER_VEHICLE + +WATER_VEHICLE + + + +VEHICLE->WATER_VEHICLE + + + + + +HOVERCRAFT + +HOVERCRAFT + + + +AIR_VEHICLE->HOVERCRAFT + + + + + +LAND_VEHICLE->HOVERCRAFT + + + + + +WATER_VEHICLE->HOVERCRAFT + + + + + +bht130 + +bht130 + + + +HOVERCRAFT->bht130 + + + + + +ENGINE + +ENGINE + + + +INTERNAL_COMBUSTION_ENGINE + +INTERNAL_COMBUSTION_ENGINE + + + +ENGINE->INTERNAL_COMBUSTION_ENGINE + + + + + +INTERNAL_COMBUSTION_ENGINE->bht130 + + + + + diff --git a/nightly_8.4/html/_images/graphviz-2177d3d933cdc16287d883a6c7ec5a4c5e8ed10b.svg b/nightly_8.4/html/_images/graphviz-2177d3d933cdc16287d883a6c7ec5a4c5e8ed10b.svg new file mode 100644 index 00000000000..964ce86ce21 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-2177d3d933cdc16287d883a6c7ec5a4c5e8ed10b.svg @@ -0,0 +1,54 @@ + + + + + + +Example + + +cluster_1 + +:fail + + + +recover + +recover + + + +bar + +bar + + + +recover->bar + + + + + +foo + +foo + + + +foo->recover + + + + + +foo->bar + + + + + diff --git a/nightly_8.4/html/_images/graphviz-309a6f1074f1f753764c56c9f6c29577d957299a.svg b/nightly_8.4/html/_images/graphviz-309a6f1074f1f753764c56c9f6c29577d957299a.svg new file mode 100644 index 00000000000..38a03c742d4 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-309a6f1074f1f753764c56c9f6c29577d957299a.svg @@ -0,0 +1,141 @@ + + + + + + +example + + +cluster_legend + +Legend + + +cluster_diagram + + +cluster_subshell + +Subshell process + + + +user defined script + +user defined script + + + +cylc defined script + +cylc defined script + + + + +cylc-env + +cylc-env + + + +env-script + +env-script + + + +cylc-env->env-script + + + + + +user-env + +user-env + + + +pre-script + +pre-script + + + +user-env->pre-script + + + + + +init-script + +init-script + + + +init-script->cylc-env + + + + + +env-script->user-env + + + + + +script + +script + + + +pre-script->script + + + + + +post-script + +post-script + + + +script->post-script + + + + + +err-script + +err-script + + + +post-script->err-script + + + + + +exit-script + +exit-script + + + +post-script->exit-script + + + + + diff --git a/nightly_8.4/html/_images/graphviz-49ba9b997629895dcb4de0b35f149b3287affd13.svg b/nightly_8.4/html/_images/graphviz-49ba9b997629895dcb4de0b35f149b3287affd13.svg new file mode 100644 index 00000000000..d525e5d6241 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-49ba9b997629895dcb4de0b35f149b3287affd13.svg @@ -0,0 +1,83 @@ + + + + + + +example + + +cluster_success + +:succeed + + +cluster_failure + +:fail + + + +c + +c + + + +d + +d + + + +c->d + + + + + +r + +r + + + +r->d + + + + + +a + +a + + + +b + +b + + + +a->b + + + + + +b->c + + + + + +b->r + + + + + diff --git a/nightly_8.4/html/_images/graphviz-5bcc0ec6c89032b0219d6542b92a01a9ebb98158.svg b/nightly_8.4/html/_images/graphviz-5bcc0ec6c89032b0219d6542b92a01a9ebb98158.svg new file mode 100644 index 00000000000..d72568a3c71 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-5bcc0ec6c89032b0219d6542b92a01a9ebb98158.svg @@ -0,0 +1,71 @@ + + + + + + +example + + + +get_observations_aldergrove + +get_observations_aldergrove + + + +consolidate_observations + +consolidate_observations + + + +get_observations_aldergrove->consolidate_observations + + + + + + + +get_observations_camborne + +get_observations_camborne + + + +get_observations_camborne->consolidate_observations + + + + + + +get_observations_heathrow + +get_observations_heathrow + + + +get_observations_heathrow->consolidate_observations + + + + + +get_observations_shetland + +get_observations_shetland + + + +get_observations_shetland->consolidate_observations + + + + + + diff --git a/nightly_8.4/html/_images/graphviz-5f4338a38f33be80a79375baa7603c453526438e.svg b/nightly_8.4/html/_images/graphviz-5f4338a38f33be80a79375baa7603c453526438e.svg new file mode 100644 index 00000000000..ebf21079342 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-5f4338a38f33be80a79375baa7603c453526438e.svg @@ -0,0 +1,79 @@ + + + + + + +Mini_Cylc + + + +b + +b + + + +c + +c + + + +b->c + + + + + +d + +d + + + +b->d + + + + + +f + +f + + + +d->f + + + + + +a + +a + + + +a->b + + + + + +e + +e + + + +e->f + + + + + diff --git a/nightly_8.4/html/_images/graphviz-6437cd2c62395d4695c4220027574b1021f6efbb.svg b/nightly_8.4/html/_images/graphviz-6437cd2c62395d4695c4220027574b1021f6efbb.svg new file mode 100644 index 00000000000..0c044b18fcb --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-6437cd2c62395d4695c4220027574b1021f6efbb.svg @@ -0,0 +1,46 @@ + + + + + + +Example + + + +1/foo + +foo +2000-01-01T12 + + + +2/foo + +foo +2000-01-02T12 + + + +1/foo->2/foo + + + + + +3/foo + +foo +2000-01-03T12 + + + +2/foo->3/foo + + + + + diff --git a/nightly_8.4/html/_images/graphviz-65d4dbac5a6d4914d2c419d6ab0e28a1fdf0a091.svg b/nightly_8.4/html/_images/graphviz-65d4dbac5a6d4914d2c419d6ab0e28a1fdf0a091.svg new file mode 100644 index 00000000000..5a1c564c23f --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-65d4dbac5a6d4914d2c419d6ab0e28a1fdf0a091.svg @@ -0,0 +1,271 @@ + + + + + + +Example + + + +root + +root + + + +ENGINE + +ENGINE + + + +root->ENGINE + + + + + +VEHICLE + +VEHICLE + + + +root->VEHICLE + + + + + +INTERNAL_COMBUSTION_ENGINE + +INTERNAL_COMBUSTION_ENGINE + + + +ENGINE->INTERNAL_COMBUSTION_ENGINE + + + + + +TURBINE_ENGINE + +TURBINE_ENGINE + + + +ENGINE->TURBINE_ENGINE + + + + + +HUMAN_ENGINE + +HUMAN_ENGINE + + + +ENGINE->HUMAN_ENGINE + + + + + +LAND_VEHICLE + +LAND_VEHICLE + + + +VEHICLE->LAND_VEHICLE + + + + + +WATER_VEHICLE + +WATER_VEHICLE + + + +VEHICLE->WATER_VEHICLE + + + + + +AIR_VEHICLE + +AIR_VEHICLE + + + +VEHICLE->AIR_VEHICLE + + + + + +r44 + +r44 + + + +INTERNAL_COMBUSTION_ENGINE->r44 + + + + + +bht130 + +bht130 + + + +INTERNAL_COMBUSTION_ENGINE->bht130 + + + + + +v22 + +v22 + + + +TURBINE_ENGINE->v22 + + + + + +a380 + +a380 + + + +TURBINE_ENGINE->a380 + + + + + +penny_farthing + +penny_farthing + + + +HUMAN_ENGINE->penny_farthing + + + + + +HOVERCRAFT + +HOVERCRAFT + + + +LAND_VEHICLE->HOVERCRAFT + + + + + +BICYCLE + +BICYCLE + + + +LAND_VEHICLE->BICYCLE + + + + + +WATER_VEHICLE->HOVERCRAFT + + + + + +AIRPLANE + +AIRPLANE + + + +AIR_VEHICLE->AIRPLANE + + + + + +HELICOPTER + +HELICOPTER + + + +AIR_VEHICLE->HELICOPTER + + + + + +AIR_VEHICLE->HOVERCRAFT + + + + + +AIRPLANE->v22 + + + + + +AIRPLANE->a380 + + + + + +HELICOPTER->r44 + + + + + +HELICOPTER->v22 + + + + + +HOVERCRAFT->bht130 + + + + + +BICYCLE->penny_farthing + + + + + diff --git a/nightly_8.4/html/_images/graphviz-67061a0cb1a093d3d29cd2a417dc12c16a2e0b16.svg b/nightly_8.4/html/_images/graphviz-67061a0cb1a093d3d29cd2a417dc12c16a2e0b16.svg new file mode 100644 index 00000000000..6e4acb75d2e --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-67061a0cb1a093d3d29cd2a417dc12c16a2e0b16.svg @@ -0,0 +1,256 @@ + + + + + + +example + + +cluster_1 + +1 + + +cluster_2 + +2 + + +cluster_3 + +3 + + + +1/pur + +buy_ingredients +1 + + + +1/mak + +make_dough +1 + + + +1/pur->1/mak + + + + + +1/bak + +bake_bread +1 + + + +1/mak->1/bak + + + + + +1/sel + +sell_bread +1 + + + +1/bak->1/sel + + + + + +1/cle + +clean_oven +1 + + + +1/bak->1/cle + + + + + +2/pre + +pre_heat_oven +2 + + + +1/cle->2/pre + + + + + +1/pre + +pre_heat_oven +1 + + + +1/pre->1/bak + + + + + +2/pur + +buy_ingredients +2 + + + +2/mak + +make_dough +2 + + + +2/pur->2/mak + + + + + +2/bak + +bake_bread +2 + + + +2/mak->2/bak + + + + + +2/sel + +sell_bread +2 + + + +2/bak->2/sel + + + + + +2/cle + +clean_oven +2 + + + +2/bak->2/cle + + + + + +3/pre + +pre_heat_oven +3 + + + +2/cle->3/pre + + + + + +2/pre->2/bak + + + + + +3/pur + +buy_ingredients +3 + + + +3/mak + +make_dough +3 + + + +3/pur->3/mak + + + + + +3/bak + +bake_bread +3 + + + +3/mak->3/bak + + + + + +3/sel + +sell_bread +3 + + + +3/bak->3/sel + + + + + +3/cle + +clean_oven +3 + + + +3/bak->3/cle + + + + + +3/pre->3/bak + + + + + diff --git a/nightly_8.4/html/_images/graphviz-817a33585e29a9085dc786f917f2f0e7bbb12f81.svg b/nightly_8.4/html/_images/graphviz-817a33585e29a9085dc786f917f2f0e7bbb12f81.svg new file mode 100644 index 00000000000..06d46aefb32 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-817a33585e29a9085dc786f917f2f0e7bbb12f81.svg @@ -0,0 +1,67 @@ + + + + + + +Mini_Cylc + + + +bar_m3 + +bar_m3 + + + +baz_m3 + +baz_m3 + + + +bar_m3->baz_m3 + + + + + +baz_m1 + +baz_m1 + + + +bar_m2 + +bar_m2 + + + +baz_m2 + +baz_m2 + + + +bar_m2->baz_m2 + + + + + +bar_m1 + +bar_m1 + + + +bar_m1->baz_m1 + + + + + diff --git a/nightly_8.4/html/_images/graphviz-8e0c9728aa86a233cf46544e68a49dea2fe207ab.svg b/nightly_8.4/html/_images/graphviz-8e0c9728aa86a233cf46544e68a49dea2fe207ab.svg new file mode 100644 index 00000000000..ecf8ae22d65 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-8e0c9728aa86a233cf46544e68a49dea2fe207ab.svg @@ -0,0 +1,43 @@ + + + + + + +Example + + + +foo + +foo + + + +bar + +bar + + + +foo->bar + + + + + +baz + +baz + + + +bar->baz + + + + + diff --git a/nightly_8.4/html/_images/graphviz-8e506f6bf51898e3f9d2d2af1fa383f3d3b2bcbc.svg b/nightly_8.4/html/_images/graphviz-8e506f6bf51898e3f9d2d2af1fa383f3d3b2bcbc.svg new file mode 100644 index 00000000000..40517f9826d --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-8e506f6bf51898e3f9d2d2af1fa383f3d3b2bcbc.svg @@ -0,0 +1,361 @@ + + + + + + + + + +absolute_outputs + +absolute_outputs + +cycle + +name + +output + + + +broadcast_events + +broadcast_events + +time + +change + +point + +namespace + +key + +value + + + +broadcast_states + +broadcast_states + +point + +namespace + +key + +value + + + +inheritance + +inheritance + +namespace + +inheritance + + + +task_action_timers + +task_action_timers + +cycle + +name + +ctx_key + +ctx + +delays + +num + +delay + +timeout + + + +task_events + +task_events + +name + +cycle + +time + +submit_num + +event + +message + + + +task_jobs + +task_jobs + +cycle + +name + +submit_num + +flow_nums + +is_manual_submit + +try_num + +time_submit + +time_submit_exit + +submit_status + +time_run + +time_run_exit + +run_signal + +run_status + +platform_name + +job_runner_name + +job_id + + + +task_late_flags + +task_late_flags + +cycle + +name + +value + + + +task_outputs + +task_outputs + +cycle + +name + +flow_nums + +outputs + + + +task_pool + +task_pool + +cycle + +name + +flow_nums + +status + +is_held + + + +task_pool--task_action_timers + +{0,1} +0..N + + + +task_pool--task_late_flags + +{0,1} +{0,1} + + + +task_pool--task_outputs + +{0,1} +0..N + + + +task_prerequisites + +task_prerequisites + +cycle + +name + +flow_nums + +prereq_name + +prereq_cycle + +prereq_output + +satisfied + + + +task_pool--task_prerequisites + +{0,1} +0..N + + + +task_timeout_timers + +task_timeout_timers + +cycle + +name + +timeout + + + +task_pool--task_timeout_timers + +{0,1} +{0,1} + + + +task_states + +task_states + +name + +cycle + +flow_nums + +time_created + +time_updated + +submit_num + +status + +flow_wait + +is_manual_submit + + + +task_states--task_events + +{0,1} +0..N + + + +task_states--task_jobs + +{0,1} +0..N + + + +tasks_to_hold + +tasks_to_hold + +name + +cycle + + + +workflow_flows + +workflow_flows + +flow_num + +start_time + +description + + + +workflow_params + +workflow_params + +key + +value + + + +workflow_template_vars + +workflow_template_vars + +key + +value + + + +xtriggers + +xtriggers + +signature + +results + +absolute_outputs + +broadcast_events + +broadcast_states + +inheritance + +tasks_to_hold + +workflow_flows + +workflow_params + +workflow_template_vars + +xtriggers + + + diff --git a/nightly_8.4/html/_images/graphviz-8e815b3f336404aebf4c3ca5d0d776c2c9baf002.svg b/nightly_8.4/html/_images/graphviz-8e815b3f336404aebf4c3ca5d0d776c2c9baf002.svg new file mode 100644 index 00000000000..1d15b2a6330 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-8e815b3f336404aebf4c3ca5d0d776c2c9baf002.svg @@ -0,0 +1,94 @@ + + + + + + +Example + + +cluster_1 + +:good + + +cluster_2 + +:bad + + +cluster_3 + +:ugly + + + +good + +good + + + +fin + +fin + + + +good->fin + + + + + +bad + +bad + + + +bad->fin + + + + + +ugly + +ugly + + + +ugly->fin + + + + + +showdown + +showdown + + + +showdown->good + + + + + +showdown->bad + + + + + +showdown->ugly + + + + + diff --git a/nightly_8.4/html/_images/graphviz-8e953bca465d702d8315a6faf120744a23b51272.svg b/nightly_8.4/html/_images/graphviz-8e953bca465d702d8315a6faf120744a23b51272.svg new file mode 100644 index 00000000000..c18a85de909 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-8e953bca465d702d8315a6faf120744a23b51272.svg @@ -0,0 +1,55 @@ + + + + + + +Mini_Cylc + + + +bake_bread + +bake_bread + + + +sell_bread + +sell_bread + + + +bake_bread->sell_bread + + + + + +buy_ingredients + +buy_ingredients + + + +make_dough + +make_dough + + + +buy_ingredients->make_dough + + + + + +make_dough->bake_bread + + + + + diff --git a/nightly_8.4/html/_images/graphviz-96a7dfe8255fbca2ef4621d8e1a50a80c86195c2.svg b/nightly_8.4/html/_images/graphviz-96a7dfe8255fbca2ef4621d8e1a50a80c86195c2.svg new file mode 100644 index 00000000000..e13181b05dd --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-96a7dfe8255fbca2ef4621d8e1a50a80c86195c2.svg @@ -0,0 +1,66 @@ + + + + + + +Example + + +cluster_1 + +:fail + + + +recover + +recover + + + +baz + +baz + + + +recover->baz + + + + + +foo + +foo + + + +bar + +bar + + + +foo->bar + + + + + +bar->recover + + + + + +bar->baz + + + + + diff --git a/nightly_8.4/html/_images/graphviz-9726db191ee25dce5b92484f57f89135b5e17b75.svg b/nightly_8.4/html/_images/graphviz-9726db191ee25dce5b92484f57f89135b5e17b75.svg new file mode 100644 index 00000000000..3383b01ad2b --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-9726db191ee25dce5b92484f57f89135b5e17b75.svg @@ -0,0 +1,61 @@ + + + + + + +example + + +cluster_T06 + +T06 + + +cluster_T12 + +T12 + + +cluster_T18 + +T18 + + + +forecast.t06 + +forecast +T06 + + + +forecast.t12 + +forecast +T12 + + + +forecast.t06->forecast.t12 + + + + + +forecast.t18 + +forecast +T18 + + + +forecast.t12->forecast.t18 + + + + + diff --git a/nightly_8.4/html/_images/graphviz-973f7a17b789c0420fc4acc3fa1d4b8e9c03b664.svg b/nightly_8.4/html/_images/graphviz-973f7a17b789c0420fc4acc3fa1d4b8e9c03b664.svg new file mode 100644 index 00000000000..992903ee092 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-973f7a17b789c0420fc4acc3fa1d4b8e9c03b664.svg @@ -0,0 +1,67 @@ + + + + + + +Example + + + +VEHICLE + +VEHICLE + + + +LAND_VEHICLE + +LAND_VEHICLE + + + +VEHICLE->LAND_VEHICLE + + + + + +BICYCLE + +BICYCLE + + + +LAND_VEHICLE->BICYCLE + + + + + +penny_farthing + +penny_farthing + + + +BICYCLE->penny_farthing + + + + + +HUMAN_ENGINE + +HUMAN_ENGINE + + + +HUMAN_ENGINE->penny_farthing + + + + + diff --git a/nightly_8.4/html/_images/graphviz-97706327755f266e946da142ff5b9c269a7417e0.svg b/nightly_8.4/html/_images/graphviz-97706327755f266e946da142ff5b9c269a7417e0.svg new file mode 100644 index 00000000000..413bfd096aa --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-97706327755f266e946da142ff5b9c269a7417e0.svg @@ -0,0 +1,61 @@ + + + + + + +Example + + + +random_seed + +random_seed + + + +breed + +breed + + + +random_seed->breed + + + + + +test_fitness + +test_fitness + + + +breed->test_fitness + + + + + +test_fitness->breed + + + + + +stop + +stop + + + +test_fitness->stop + + + + + diff --git a/nightly_8.4/html/_images/graphviz-9c6c3320344b9bad792fb330e3b5a3287587062f.svg b/nightly_8.4/html/_images/graphviz-9c6c3320344b9bad792fb330e3b5a3287587062f.svg new file mode 100644 index 00000000000..db3cfdef0ba --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-9c6c3320344b9bad792fb330e3b5a3287587062f.svg @@ -0,0 +1,89 @@ + + + + + + +Example + + +cluster_1 + +2000-01-01T00:00Z + + +cluster_2 + +2000-01-01T12:00Z + + +cluster_3 + +2000-01-02T00:00Z + + + +01T00/foo + +foo +2000-01-01T00:00Z + + + +01T00/bar + +bar +2000-01-01T00:00Z + + + +01T00/foo->01T00/bar + + + + + +01T00/baz + +baz +2000-01-01T00:00Z + + + +b01T12/az + +baz +2000-01-01T12:00Z + + + +02T00/foo + +foo +2000-01-02T00:00Z + + + +02T00/bar + +bar +2000-01-02T00:00Z + + + +02T00/foo->02T00/bar + + + + + +02T00/baz + +baz +2000-01-02T00:00Z + + + diff --git a/nightly_8.4/html/_images/graphviz-a02e167fd91d9a135d2030f0136dc13a230eb00f.svg b/nightly_8.4/html/_images/graphviz-a02e167fd91d9a135d2030f0136dc13a230eb00f.svg new file mode 100644 index 00000000000..784b8e9c670 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-a02e167fd91d9a135d2030f0136dc13a230eb00f.svg @@ -0,0 +1,46 @@ + + + + + + +Example + + + +1/foo + +foo +2000-01-01T00 + + + +2/foo + +foo +2000-01-02T00 + + + +1/foo->2/foo + + + + + +3/foo + +foo +2000-01-03T00 + + + +2/foo->3/foo + + + + + diff --git a/nightly_8.4/html/_images/graphviz-a0b983d4be5182e8e12f4aacfcc75c2683db3c40.svg b/nightly_8.4/html/_images/graphviz-a0b983d4be5182e8e12f4aacfcc75c2683db3c40.svg new file mode 100644 index 00000000000..8144bc373c2 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-a0b983d4be5182e8e12f4aacfcc75c2683db3c40.svg @@ -0,0 +1,139 @@ + + + + + + +Example + + +cluster_1 + +1 + + +cluster_2 + +2 + + +cluster_3 + +3 + + + +1/foo + +foo +1 + + + +1/bar + +bar +1 + + + +1/foo->1/bar + + + + + +1/baz + +baz +1 + + + +1/bar->1/baz + + + + + +2/bar + +bar +2 + + + +1/bar->2/bar + + + + + +2/foo + +foo +2 + + + +2/foo->2/bar + + + + + +2/baz + +baz +2 + + + +2/bar->2/baz + + + + + +3/bar + +bar +3 + + + +2/bar->3/bar + + + + + +3/foo + +foo +3 + + + +3/foo->3/bar + + + + + +3/baz + +baz +3 + + + +3/bar->3/baz + + + + + diff --git a/nightly_8.4/html/_images/graphviz-a8b1e9e93fab74bdbf93d1612a22c4eef701651d.svg b/nightly_8.4/html/_images/graphviz-a8b1e9e93fab74bdbf93d1612a22c4eef701651d.svg new file mode 100644 index 00000000000..d525e5d6241 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-a8b1e9e93fab74bdbf93d1612a22c4eef701651d.svg @@ -0,0 +1,83 @@ + + + + + + +example + + +cluster_success + +:succeed + + +cluster_failure + +:fail + + + +c + +c + + + +d + +d + + + +c->d + + + + + +r + +r + + + +r->d + + + + + +a + +a + + + +b + +b + + + +a->b + + + + + +b->c + + + + + +b->r + + + + + diff --git a/nightly_8.4/html/_images/graphviz-aca8d285197e57a400e199c11a8dce9f5229b6a0.svg b/nightly_8.4/html/_images/graphviz-aca8d285197e57a400e199c11a8dce9f5229b6a0.svg new file mode 100644 index 00000000000..3732efbe638 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-aca8d285197e57a400e199c11a8dce9f5229b6a0.svg @@ -0,0 +1,255 @@ + + + + + + +example + + +cluster_1 + +1 + + +cluster_2 + +2 + + +cluster_3 + +3 + + + +1/a + +a +1 + + + +1/b + +b +1 + + + +1/a->1/b + + + + + +1/d + +d +1 + + + +1/b->1/d + + + + + +1/f + +f +1 + + + +1/b->1/f + + + + + +1/e + +e +1 + + + +1/d->1/e + + + + + +2/c + +c +2 + + + +1/f->2/c + + + + + +1/c + +c +1 + + + +1/c->1/b + + + + + +2/a + +a +2 + + + +1/e->2/a + + + + + +2/b + +b +2 + + + +2/a->2/b + + + + + +2/d + +d +2 + + + +2/b->2/d + + + + + +2/f + +f +2 + + + +2/b->2/f + + + + + +3/a + +a +3 + + + +2/d->3/a + + + + + +3/c + +c +3 + + + +2/f->3/c + + + + + +2/c->2/b + + + + + +3/b + +b +3 + + + +3/a->3/b + + + + + +3/d + +d +3 + + + +3/b->3/d + + + + + +3/f + +f +3 + + + +3/b->3/f + + + + + +3/e + +e +3 + + + +3/d->3/e + + + + + +3/c->3/b + + + + + diff --git a/nightly_8.4/html/_images/graphviz-b280465dc5ff0105af7f02b917256ecf1a7e9c85.svg b/nightly_8.4/html/_images/graphviz-b280465dc5ff0105af7f02b917256ecf1a7e9c85.svg new file mode 100644 index 00000000000..157281b96bd --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-b280465dc5ff0105af7f02b917256ecf1a7e9c85.svg @@ -0,0 +1,79 @@ + + + + + + +bakery + + + +purchase ingredients + +purchase ingredients + + + +make dough + +make dough + + + +purchase ingredients->make dough + + + + + +bake bread + +bake bread + + + +make dough->bake bread + + + + + +sell bread + +sell bread + + + +bake bread->sell bread + + + + + +clean oven + +clean oven + + + +bake bread->clean oven + + + + + +pre-heat oven + +pre-heat oven + + + +pre-heat oven->bake bread + + + + + diff --git a/nightly_8.4/html/_images/graphviz-b850ea169f58a15feb1d5b7b3a2b593602948b1e.svg b/nightly_8.4/html/_images/graphviz-b850ea169f58a15feb1d5b7b3a2b593602948b1e.svg new file mode 100644 index 00000000000..84edd71d7d2 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-b850ea169f58a15feb1d5b7b3a2b593602948b1e.svg @@ -0,0 +1,91 @@ + + + + + + +Example + + + +AIRPLANE + +AIRPLANE + + + +a380 + +a380 + + + +AIRPLANE->a380 + + + + + +HELICOPTER + +HELICOPTER + + + +r44 + +r44 + + + +HELICOPTER->r44 + + + + + +root + +root + + + +VEHICLE + +VEHICLE + + + +root->VEHICLE + + + + + +AIR_VEHICLE + +AIR_VEHICLE + + + +VEHICLE->AIR_VEHICLE + + + + + +AIR_VEHICLE->AIRPLANE + + + + + +AIR_VEHICLE->HELICOPTER + + + + + diff --git a/nightly_8.4/html/_images/graphviz-bbc033dc2abc4e5b314270dae1e5c178111a46e8.svg b/nightly_8.4/html/_images/graphviz-bbc033dc2abc4e5b314270dae1e5c178111a46e8.svg new file mode 100644 index 00000000000..e3ec57224bf --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-bbc033dc2abc4e5b314270dae1e5c178111a46e8.svg @@ -0,0 +1,63 @@ + + + + + + +_ + + + +Jobs + +Jobs + + + +Scheduler + +Scheduler + + + +Jobs->Scheduler + + + ZMQ + GraphQL + (default) + + + +UIS + +UIS + + + +Scheduler->UIS + + + ZMQ + GraphQL (control) + Protobuf (data) + + + +UI + +UI + + + +UIS->UI + + + Websocket + GraphQL + + + diff --git a/nightly_8.4/html/_images/graphviz-d5181c18b29b889a1db79d16a30c45bed288b3d9.svg b/nightly_8.4/html/_images/graphviz-d5181c18b29b889a1db79d16a30c45bed288b3d9.svg new file mode 100644 index 00000000000..90fbd5e95c8 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-d5181c18b29b889a1db79d16a30c45bed288b3d9.svg @@ -0,0 +1,79 @@ + + + + + + +graph_tutorial + + + +a + +a + + + +b + +b + + + +a->b + + + + + +d + +d + + + +b->d + + + + + +f + +f + + + +b->f + + + + + +e + +e + + + +d->e + + + + + +c + +c + + + +c->b + + + + + diff --git a/nightly_8.4/html/_images/graphviz-de969f40c8e352a7e47096688411d71e3383c9a6.svg b/nightly_8.4/html/_images/graphviz-de969f40c8e352a7e47096688411d71e3383c9a6.svg new file mode 100644 index 00000000000..2fd49cceed3 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-de969f40c8e352a7e47096688411d71e3383c9a6.svg @@ -0,0 +1,79 @@ + + + + + + +Mini_Cylc + + + +buy_ingredients + +buy_ingredients + + + +make_dough + +make_dough + + + +buy_ingredients->make_dough + + + + + +bake_bread + +bake_bread + + + +make_dough->bake_bread + + + + + +pre_heat_oven + +pre_heat_oven + + + +pre_heat_oven->bake_bread + + + + + +clean_oven + +clean_oven + + + +bake_bread->clean_oven + + + + + +sell_bread + +sell_bread + + + +bake_bread->sell_bread + + + + + diff --git a/nightly_8.4/html/_images/graphviz-e0054d6b31d1071b99e7fe278d0ac5efbadd46a8.svg b/nightly_8.4/html/_images/graphviz-e0054d6b31d1071b99e7fe278d0ac5efbadd46a8.svg new file mode 100644 index 00000000000..b6ff0945f11 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-e0054d6b31d1071b99e7fe278d0ac5efbadd46a8.svg @@ -0,0 +1,351 @@ + + + + + + +example + + +cluster_1 + +1 + + +cluster_2 + +2 + + +cluster_3 + +3 + + +cluster_4 + +4 + + + +1/pur + +buy_ingredients +1 + + + +1/mak + +make_dough +1 + + + +1/pur->1/mak + + + + + +1/bak + +bake_bread +1 + + + +1/mak->1/bak + + + + + +1/sel + +sell_bread +1 + + + +1/bak->1/sel + + + + + +1/cle + +clean_oven +1 + + + +1/bak->1/cle + + + + + +3/pur + +buy_ingredients +3 + + + +1/sel->3/pur + + + + + +2/pre + +pre_heat_oven +2 + + + +1/cle->2/pre + + + + + +1/pre + +pre_heat_oven +1 + + + +1/pre->1/bak + + + + + +2/pur + +buy_ingredients +2 + + + +2/mak + +make_dough +2 + + + +2/pur->2/mak + + + + + +2/bak + +bake_bread +2 + + + +2/mak->2/bak + + + + + +2/sel + +sell_bread +2 + + + +2/bak->2/sel + + + + + +2/cle + +clean_oven +2 + + + +2/bak->2/cle + + + + + +4/pur + +buy_ingredients +4 + + + +2/sel->4/pur + + + + + +3/pre + +pre_heat_oven +3 + + + +2/cle->3/pre + + + + + +2/pre->2/bak + + + + + +3/mak + +make_dough +3 + + + +3/pur->3/mak + + + + + +3/bak + +bake_bread +3 + + + +3/mak->3/bak + + + + + +3/sel + +sell_bread +3 + + + +3/bak->3/sel + + + + + +3/cle + +clean_oven +3 + + + +3/bak->3/cle + + + + + +4/pre + +pre_heat_oven +4 + + + +3/cle->4/pre + + + + + +3/pre->3/bak + + + + + +4/mak + +make_dough +4 + + + +4/pur->4/mak + + + + + +4/bak + +bake_bread +4 + + + +4/mak->4/bak + + + + + +4/sel + +sell_bread +4 + + + +4/bak->4/sel + + + + + +4/cle + +clean_oven +4 + + + +4/bak->4/cle + + + + + +4/pre->4/bak + + + + + diff --git a/nightly_8.4/html/_images/graphviz-ef2dddb2d1e236bd5f1ad509bb4a2ff37c434c50.svg b/nightly_8.4/html/_images/graphviz-ef2dddb2d1e236bd5f1ad509bb4a2ff37c434c50.svg new file mode 100644 index 00000000000..afdef195454 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-ef2dddb2d1e236bd5f1ad509bb4a2ff37c434c50.svg @@ -0,0 +1,31 @@ + + + + + + +Mini_Cylc + + + +buy_ingredients + +buy_ingredients + + + +make_dough + +make_dough + + + +buy_ingredients->make_dough + + + + + diff --git a/nightly_8.4/html/_images/graphviz-f6aacb832331612a9543a5f40d8dc8da04c9400d.svg b/nightly_8.4/html/_images/graphviz-f6aacb832331612a9543a5f40d8dc8da04c9400d.svg new file mode 100644 index 00000000000..2d0513cedd4 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-f6aacb832331612a9543a5f40d8dc8da04c9400d.svg @@ -0,0 +1,31 @@ + + + + + + +example + + + +forecast + +forecast + + + +post_process_exeter + +post_process_exeter + + + +forecast->post_process_exeter + + + + + diff --git a/nightly_8.4/html/_images/graphviz-fd21ff6d92366e729e6e7bc9abd416eee88993a1.svg b/nightly_8.4/html/_images/graphviz-fd21ff6d92366e729e6e7bc9abd416eee88993a1.svg new file mode 100644 index 00000000000..0fcf26389eb --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-fd21ff6d92366e729e6e7bc9abd416eee88993a1.svg @@ -0,0 +1,87 @@ + + + + + + +example + + +cluster_T00 + ++PT0H + + +cluster_T03 + ++PT3H + + +cluster_T06 + ++PT6H + + + +observations.t00 + +consolidate observations ++PT0H + + + +forecast.t06 + +forecast ++PT6H + + + +observations.t00->forecast.t06 + + + + + +observations.t03 + +consolidate observations ++PT3H + + + +observations.t03->forecast.t06 + + + + + +get_rainfall.t06 + +get_rainfall ++PT6H + + + +get_rainfall.t06->forecast.t06 + + + + + +observations.t06 + +consolidate observations ++PT6H + + + +observations.t06->forecast.t06 + + + + + diff --git a/nightly_8.4/html/_images/graphviz-fe358295b739cfd9b1c6fb67e74ce961621f9cd7.svg b/nightly_8.4/html/_images/graphviz-fe358295b739cfd9b1c6fb67e74ce961621f9cd7.svg new file mode 100644 index 00000000000..2bedb3d96d3 --- /dev/null +++ b/nightly_8.4/html/_images/graphviz-fe358295b739cfd9b1c6fb67e74ce961621f9cd7.svg @@ -0,0 +1,109 @@ + + + + + + +Example + + + +AIRPLANE + +AIRPLANE + + + +v22 + +v22 + + + +AIRPLANE->v22 + + + + + +a380 + +a380 + + + +AIRPLANE->a380 + + + + + +HELICOPTER + +HELICOPTER + + + +HELICOPTER->v22 + + + + + +r44 + +r44 + + + +HELICOPTER->r44 + + + + + +root + +root + + + +VEHICLE + +VEHICLE + + + +root->VEHICLE + + + + + +AIR_VEHICLE + +AIR_VEHICLE + + + +VEHICLE->AIR_VEHICLE + + + + + +AIR_VEHICLE->AIRPLANE + + + + + +AIR_VEHICLE->HELICOPTER + + + + + diff --git a/nightly_8.4/html/_images/gui-arch-multi-user.svg b/nightly_8.4/html/_images/gui-arch-multi-user.svg new file mode 100644 index 00000000000..71dea933f0e --- /dev/null +++ b/nightly_8.4/html/_images/gui-arch-multi-user.svg @@ -0,0 +1,2568 @@ + + + + + + + + + + image/svg+xml + + + + + + + + z + + + + + + + + + + + https://<host>:port?token + + + + + + Browser + + + + + + + + + + + + + + + + Cylc Workflow + + + + + + + + + + + + + + + + + + + + + + + + + + Cylc Jobs + + + + + + + + + #1234 + #2345 + + + + + + + + + + Cylc Workflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cylc Jobs + + + + + #3456 + + + User 1 + + + + + + + + + Connects + (Certificate from filesystem) + + + User Machine 1 + + + + + + + + + + Cylc Servers + + + + + + + + + + Job Platform 1 + + + + + + + + + + + + Job Platform 2 + + + + + + + + + + Submits + Updates + + + + + + + + + + + + + + + + + + + + + + + https://<host>:port?token + + + + + + Browser + + + + + + + + Jupyter Server + + + + Cylc UI Server + Jupyter Lab + Workflow data services + Workflow control services + User interface + Optionally any number ofJupyter Server extensions(e.g. Jupyter Lab) can be runwithin the same Jupyter Serverinstance as the Cylc UI Server. + + + + + + + + Token / cookie management + + + + + + + + + + Cylc Workflow + + + + + + + + + + + + + + + + + + + + + + + + + + Cylc Jobs + + + + + #4567 + + User 2 + + + Connects + (Certificate from filesystem) + + + User Machine 2 + + + + + + + + + + + Job Platform 1 + + + + + + + + + + Submits + Updates + + + + + + + + Jupyter Server + + + + Cylc UI Server + Jupyter Lab + Workflow data services + Workflow control services + User interface + Optionally any number ofJupyter Server extensions(e.g. Jupyter Lab) can be runwithin the same Jupyter Serverinstance as the Cylc UI Server. + + + + + + + + Token / cookie management + + + Jupyter Hub + + + Authenticator + Database + Spawner + Spawns + + + + + (privileged) + Spawns + + + Authenticates + + + + + Proxy + + + Configures + + + + + + Connects + + + + + Configurable-HTTP-proxy + Hub User + + + Connects + Authenticates + + + + diff --git a/nightly_8.4/html/_images/gui-arch-single-user.svg b/nightly_8.4/html/_images/gui-arch-single-user.svg new file mode 100644 index 00000000000..0bc174c8fc3 --- /dev/null +++ b/nightly_8.4/html/_images/gui-arch-single-user.svg @@ -0,0 +1,1469 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + Jupyter Server + + + + Cylc UI Server + Jupyter Lab + Workflow data services + Workflow control services + User interface + Optionally any number ofJupyter Server extensions(e.g. Jupyter Lab) can be runwithin the same Jupyter Serverinstance as the Cylc UI Server. + + + + > + + CLI + + + + https://<host>:port?token + + + + + + Browser + + + + + + + + + + + + + + + Authentication services + Token / cookie management + + + + + + + + + + Cylc Workflow + + + + + + + + + + + + + + + + + + + + + + + + + + Cylc Jobs + + + + + + + + + #1234 + #2345 + + + + + + + + + + Cylc Workflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cylc Jobs + + + + + #3456 + + + User + Spawns + + + + + Connects + (URL token) + + + + + + + + + Connects + (Certificate from filesystem) + + + + User Machine + + + + + + + + + + Cylc Servers + + + + + + + + + + Job Platform 1 + + + + + + + + + + + + Job Platform 2 + + + + + + + + + + + + + + Submits + Updates + + + + + + + + + + + + + + + + z + + diff --git a/nightly_8.4/html/_images/gui-n-window-selector.gif b/nightly_8.4/html/_images/gui-n-window-selector.gif new file mode 100644 index 00000000000..d7c54e18413 Binary files /dev/null and b/nightly_8.4/html/_images/gui-n-window-selector.gif differ diff --git a/nightly_8.4/html/_images/hub.png b/nightly_8.4/html/_images/hub.png new file mode 100644 index 00000000000..49f9511d47a Binary files /dev/null and b/nightly_8.4/html/_images/hub.png differ diff --git a/nightly_8.4/html/_images/initial-start-stop-final-cp.svg b/nightly_8.4/html/_images/initial-start-stop-final-cp.svg new file mode 100644 index 00000000000..b89348a5220 --- /dev/null +++ b/nightly_8.4/html/_images/initial-start-stop-final-cp.svg @@ -0,0 +1,421 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + initial + final + start + stop + + + 1 + 2 + 3 + 4 + 5 + 6 + + 0 + P1=foo + + + tasks are scheduled in this range + the scheduler is run in this range + P2=bar + + + + + + + diff --git a/nightly_8.4/html/_images/iso8601-dates.svg b/nightly_8.4/html/_images/iso8601-dates.svg new file mode 100644 index 00000000000..83b561be6aa --- /dev/null +++ b/nightly_8.4/html/_images/iso8601-dates.svg @@ -0,0 +1,265 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + 1985-04-12 + 23:20:30Z + T + Date Components + Time Components + + + + + + + + + + + Separator + Year + Month + Day + Hour + Minute + Second + Time Zone + + + diff --git a/nightly_8.4/html/_images/jinja2-ensemble-graph.png b/nightly_8.4/html/_images/jinja2-ensemble-graph.png new file mode 100644 index 00000000000..55f8fe9a1e2 Binary files /dev/null and b/nightly_8.4/html/_images/jinja2-ensemble-graph.png differ diff --git a/nightly_8.4/html/_images/jinja2-workflow-graph.png b/nightly_8.4/html/_images/jinja2-workflow-graph.png new file mode 100644 index 00000000000..8772afbf272 Binary files /dev/null and b/nightly_8.4/html/_images/jinja2-workflow-graph.png differ diff --git a/nightly_8.4/html/_images/job-failed.png b/nightly_8.4/html/_images/job-failed.png new file mode 100644 index 00000000000..57b42de1a4d Binary files /dev/null and b/nightly_8.4/html/_images/job-failed.png differ diff --git a/nightly_8.4/html/_images/job-running.png b/nightly_8.4/html/_images/job-running.png new file mode 100644 index 00000000000..32d08b54ace Binary files /dev/null and b/nightly_8.4/html/_images/job-running.png differ diff --git a/nightly_8.4/html/_images/job-submit-failed.png b/nightly_8.4/html/_images/job-submit-failed.png new file mode 100644 index 00000000000..1be29f87753 Binary files /dev/null and b/nightly_8.4/html/_images/job-submit-failed.png differ diff --git a/nightly_8.4/html/_images/job-submitted.png b/nightly_8.4/html/_images/job-submitted.png new file mode 100644 index 00000000000..e16aef0b6b5 Binary files /dev/null and b/nightly_8.4/html/_images/job-submitted.png differ diff --git a/nightly_8.4/html/_images/job-succeeded.png b/nightly_8.4/html/_images/job-succeeded.png new file mode 100644 index 00000000000..657e5c48406 Binary files /dev/null and b/nightly_8.4/html/_images/job-succeeded.png differ diff --git a/nightly_8.4/html/_images/log-view-screenshot.png b/nightly_8.4/html/_images/log-view-screenshot.png new file mode 100644 index 00000000000..1e5dac9ed63 Binary files /dev/null and b/nightly_8.4/html/_images/log-view-screenshot.png differ diff --git a/nightly_8.4/html/_images/n-window.gif b/nightly_8.4/html/_images/n-window.gif new file mode 100644 index 00000000000..351a27b47b2 Binary files /dev/null and b/nightly_8.4/html/_images/n-window.gif differ diff --git a/nightly_8.4/html/_images/n-window.png b/nightly_8.4/html/_images/n-window.png new file mode 100644 index 00000000000..0a98ab44baa Binary files /dev/null and b/nightly_8.4/html/_images/n-window.png differ diff --git a/nightly_8.4/html/_images/new-flow-n.png b/nightly_8.4/html/_images/new-flow-n.png new file mode 100644 index 00000000000..0f74647a325 Binary files /dev/null and b/nightly_8.4/html/_images/new-flow-n.png differ diff --git a/nightly_8.4/html/_images/no-flow-n.png b/nightly_8.4/html/_images/no-flow-n.png new file mode 100644 index 00000000000..efe0cb53eec Binary files /dev/null and b/nightly_8.4/html/_images/no-flow-n.png differ diff --git a/nightly_8.4/html/_images/param-1.png b/nightly_8.4/html/_images/param-1.png new file mode 100644 index 00000000000..6f839b0bd28 Binary files /dev/null and b/nightly_8.4/html/_images/param-1.png differ diff --git a/nightly_8.4/html/_images/param-2.png b/nightly_8.4/html/_images/param-2.png new file mode 100644 index 00000000000..5c5245176f4 Binary files /dev/null and b/nightly_8.4/html/_images/param-2.png differ diff --git a/nightly_8.4/html/_images/params1.png b/nightly_8.4/html/_images/params1.png new file mode 100644 index 00000000000..8ec5cd73588 Binary files /dev/null and b/nightly_8.4/html/_images/params1.png differ diff --git a/nightly_8.4/html/_images/re-run-a-task.gui.gif b/nightly_8.4/html/_images/re-run-a-task.gui.gif new file mode 100644 index 00000000000..bbc293b5e3d Binary files /dev/null and b/nightly_8.4/html/_images/re-run-a-task.gui.gif differ diff --git a/nightly_8.4/html/_images/re-run-a-task.tui.gif b/nightly_8.4/html/_images/re-run-a-task.tui.gif new file mode 100644 index 00000000000..131193792ba Binary files /dev/null and b/nightly_8.4/html/_images/re-run-a-task.tui.gif differ diff --git a/nightly_8.4/html/_images/re-run-all-failed-tasks.gui.gif b/nightly_8.4/html/_images/re-run-all-failed-tasks.gui.gif new file mode 100644 index 00000000000..686cf46df37 Binary files /dev/null and b/nightly_8.4/html/_images/re-run-all-failed-tasks.gui.gif differ diff --git a/nightly_8.4/html/_images/re-run-multiple-tasks.gui.gif b/nightly_8.4/html/_images/re-run-multiple-tasks.gui.gif new file mode 100644 index 00000000000..bf6f635b61f Binary files /dev/null and b/nightly_8.4/html/_images/re-run-multiple-tasks.gui.gif differ diff --git a/nightly_8.4/html/_images/recurrence-sections.svg b/nightly_8.4/html/_images/recurrence-sections.svg new file mode 100644 index 00000000000..05d0223f231 --- /dev/null +++ b/nightly_8.4/html/_images/recurrence-sections.svg @@ -0,0 +1,416 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + 1 + + 2 + + 3 + + 4 + + 5 + + 6 + + 7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Foo + Bar + Baz + + + + + + + + diff --git a/nightly_8.4/html/_images/same-flow-behind.png b/nightly_8.4/html/_images/same-flow-behind.png new file mode 100644 index 00000000000..94de228370e Binary files /dev/null and b/nightly_8.4/html/_images/same-flow-behind.png differ diff --git a/nightly_8.4/html/_images/same-flow-n.png b/nightly_8.4/html/_images/same-flow-n.png new file mode 100644 index 00000000000..9aa0be6d2f4 Binary files /dev/null and b/nightly_8.4/html/_images/same-flow-n.png differ diff --git a/nightly_8.4/html/_images/same-flow-wait-n.png b/nightly_8.4/html/_images/same-flow-wait-n.png new file mode 100644 index 00000000000..b54aaa96416 Binary files /dev/null and b/nightly_8.4/html/_images/same-flow-wait-n.png differ diff --git a/nightly_8.4/html/_images/set-a-switch-task.gui.gif b/nightly_8.4/html/_images/set-a-switch-task.gui.gif new file mode 100644 index 00000000000..877d0c6065f Binary files /dev/null and b/nightly_8.4/html/_images/set-a-switch-task.gui.gif differ diff --git a/nightly_8.4/html/_images/set-and-release-hold-point.gif b/nightly_8.4/html/_images/set-and-release-hold-point.gif new file mode 100644 index 00000000000..055c6790629 Binary files /dev/null and b/nightly_8.4/html/_images/set-and-release-hold-point.gif differ diff --git a/nightly_8.4/html/_images/set-task-outputs.gui.gif b/nightly_8.4/html/_images/set-task-outputs.gui.gif new file mode 100644 index 00000000000..c28ffc391c3 Binary files /dev/null and b/nightly_8.4/html/_images/set-task-outputs.gui.gif differ diff --git a/nightly_8.4/html/_images/set-task-outputs.tui.gif b/nightly_8.4/html/_images/set-task-outputs.tui.gif new file mode 100644 index 00000000000..2abcbb35cf8 Binary files /dev/null and b/nightly_8.4/html/_images/set-task-outputs.tui.gif differ diff --git a/nightly_8.4/html/_images/set-task-prerequisites.gui.gif b/nightly_8.4/html/_images/set-task-prerequisites.gui.gif new file mode 100644 index 00000000000..abe55b3c940 Binary files /dev/null and b/nightly_8.4/html/_images/set-task-prerequisites.gui.gif differ diff --git a/nightly_8.4/html/_images/task-expired.png b/nightly_8.4/html/_images/task-expired.png new file mode 100644 index 00000000000..b4344ac41b8 Binary files /dev/null and b/nightly_8.4/html/_images/task-expired.png differ diff --git a/nightly_8.4/html/_images/task-failed.png b/nightly_8.4/html/_images/task-failed.png new file mode 100644 index 00000000000..fb628682fba Binary files /dev/null and b/nightly_8.4/html/_images/task-failed.png differ diff --git a/nightly_8.4/html/_images/task-isHeld.png b/nightly_8.4/html/_images/task-isHeld.png new file mode 100644 index 00000000000..cd37e27c930 Binary files /dev/null and b/nightly_8.4/html/_images/task-isHeld.png differ diff --git a/nightly_8.4/html/_images/task-isQueued.png b/nightly_8.4/html/_images/task-isQueued.png new file mode 100644 index 00000000000..77f2a7fd192 Binary files /dev/null and b/nightly_8.4/html/_images/task-isQueued.png differ diff --git a/nightly_8.4/html/_images/task-isRunahead.png b/nightly_8.4/html/_images/task-isRunahead.png new file mode 100644 index 00000000000..59bdbc5f80b Binary files /dev/null and b/nightly_8.4/html/_images/task-isRunahead.png differ diff --git a/nightly_8.4/html/_images/task-job.png b/nightly_8.4/html/_images/task-job.png new file mode 100644 index 00000000000..7f79ea734e4 Binary files /dev/null and b/nightly_8.4/html/_images/task-job.png differ diff --git a/nightly_8.4/html/_images/task-preparing.png b/nightly_8.4/html/_images/task-preparing.png new file mode 100644 index 00000000000..e4ea5699c92 Binary files /dev/null and b/nightly_8.4/html/_images/task-preparing.png differ diff --git a/nightly_8.4/html/_images/task-running-0.png b/nightly_8.4/html/_images/task-running-0.png new file mode 100644 index 00000000000..ca51f50524d Binary files /dev/null and b/nightly_8.4/html/_images/task-running-0.png differ diff --git a/nightly_8.4/html/_images/task-running-100.png b/nightly_8.4/html/_images/task-running-100.png new file mode 100644 index 00000000000..1a2f80f1f35 Binary files /dev/null and b/nightly_8.4/html/_images/task-running-100.png differ diff --git a/nightly_8.4/html/_images/task-running-25.png b/nightly_8.4/html/_images/task-running-25.png new file mode 100644 index 00000000000..da231a1ea0c Binary files /dev/null and b/nightly_8.4/html/_images/task-running-25.png differ diff --git a/nightly_8.4/html/_images/task-running-50.png b/nightly_8.4/html/_images/task-running-50.png new file mode 100644 index 00000000000..2354d2b0d01 Binary files /dev/null and b/nightly_8.4/html/_images/task-running-50.png differ diff --git a/nightly_8.4/html/_images/task-running-75.png b/nightly_8.4/html/_images/task-running-75.png new file mode 100644 index 00000000000..0f4e332e7f3 Binary files /dev/null and b/nightly_8.4/html/_images/task-running-75.png differ diff --git a/nightly_8.4/html/_images/task-submit-failed.png b/nightly_8.4/html/_images/task-submit-failed.png new file mode 100644 index 00000000000..09e3e999da8 Binary files /dev/null and b/nightly_8.4/html/_images/task-submit-failed.png differ diff --git a/nightly_8.4/html/_images/task-submitted.png b/nightly_8.4/html/_images/task-submitted.png new file mode 100644 index 00000000000..e4ea5699c92 Binary files /dev/null and b/nightly_8.4/html/_images/task-submitted.png differ diff --git a/nightly_8.4/html/_images/task-succeeded.png b/nightly_8.4/html/_images/task-succeeded.png new file mode 100644 index 00000000000..04751161280 Binary files /dev/null and b/nightly_8.4/html/_images/task-succeeded.png differ diff --git a/nightly_8.4/html/_images/task-waiting.png b/nightly_8.4/html/_images/task-waiting.png new file mode 100644 index 00000000000..20914633329 Binary files /dev/null and b/nightly_8.4/html/_images/task-waiting.png differ diff --git a/nightly_8.4/html/_images/test1.png b/nightly_8.4/html/_images/test1.png new file mode 100644 index 00000000000..06a4bdf07f7 Binary files /dev/null and b/nightly_8.4/html/_images/test1.png differ diff --git a/nightly_8.4/html/_images/test2.png b/nightly_8.4/html/_images/test2.png new file mode 100644 index 00000000000..4ea60b9dd07 Binary files /dev/null and b/nightly_8.4/html/_images/test2.png differ diff --git a/nightly_8.4/html/_images/test4.png b/nightly_8.4/html/_images/test4.png new file mode 100644 index 00000000000..8cd8a9c0a23 Binary files /dev/null and b/nightly_8.4/html/_images/test4.png differ diff --git a/nightly_8.4/html/_images/test5.png b/nightly_8.4/html/_images/test5.png new file mode 100644 index 00000000000..f0940ea6820 Binary files /dev/null and b/nightly_8.4/html/_images/test5.png differ diff --git a/nightly_8.4/html/_images/time_series.png b/nightly_8.4/html/_images/time_series.png new file mode 100644 index 00000000000..7c4ecbc8b63 Binary files /dev/null and b/nightly_8.4/html/_images/time_series.png differ diff --git a/nightly_8.4/html/_images/tui-1.gif b/nightly_8.4/html/_images/tui-1.gif new file mode 100644 index 00000000000..33837a001b5 Binary files /dev/null and b/nightly_8.4/html/_images/tui-1.gif differ diff --git a/nightly_8.4/html/_images/tui-1.png b/nightly_8.4/html/_images/tui-1.png new file mode 100644 index 00000000000..77d39023cff Binary files /dev/null and b/nightly_8.4/html/_images/tui-1.png differ diff --git a/nightly_8.4/html/_images/tui-2.png b/nightly_8.4/html/_images/tui-2.png new file mode 100644 index 00000000000..b8c31db7c10 Binary files /dev/null and b/nightly_8.4/html/_images/tui-2.png differ diff --git a/nightly_8.4/html/_images/tui-3.png b/nightly_8.4/html/_images/tui-3.png new file mode 100644 index 00000000000..b819f2a289e Binary files /dev/null and b/nightly_8.4/html/_images/tui-3.png differ diff --git a/nightly_8.4/html/_images/ui-view-selector.jpg b/nightly_8.4/html/_images/ui-view-selector.jpg new file mode 100644 index 00000000000..f39bb446f7a Binary files /dev/null and b/nightly_8.4/html/_images/ui-view-selector.jpg differ diff --git a/nightly_8.4/html/_images/ui-workspace-tabs.gif b/nightly_8.4/html/_images/ui-workspace-tabs.gif new file mode 100644 index 00000000000..519cc9a596e Binary files /dev/null and b/nightly_8.4/html/_images/ui-workspace-tabs.gif differ diff --git a/nightly_8.4/html/_images/vip-vr.gif b/nightly_8.4/html/_images/vip-vr.gif new file mode 100644 index 00000000000..3785db19cf3 Binary files /dev/null and b/nightly_8.4/html/_images/vip-vr.gif differ diff --git a/nightly_8.4/html/_images/websocket-communication.png b/nightly_8.4/html/_images/websocket-communication.png new file mode 100644 index 00000000000..7c5586e6829 Binary files /dev/null and b/nightly_8.4/html/_images/websocket-communication.png differ diff --git a/nightly_8.4/html/_images/websocket-graphql-ws-protocol.png b/nightly_8.4/html/_images/websocket-graphql-ws-protocol.png new file mode 100644 index 00000000000..70f36175380 Binary files /dev/null and b/nightly_8.4/html/_images/websocket-graphql-ws-protocol.png differ diff --git a/nightly_8.4/html/_modules/cylc/flow/exceptions.html b/nightly_8.4/html/_modules/cylc/flow/exceptions.html new file mode 100644 index 00000000000..a2cead22a16 --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/exceptions.html @@ -0,0 +1,773 @@ + + + + + + cylc.flow.exceptions — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.exceptions

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""Exceptions for "expected" errors."""
+
+
+from textwrap import wrap
+from typing import (
+    Dict,
+    Optional,
+    Sequence,
+    Set,
+    Union,
+    TYPE_CHECKING,
+)
+
+from cylc.flow.util import format_cmd
+
+if TYPE_CHECKING:
+    from cylc.flow.subprocctx import SubFuncContext
+
+
+
+[docs] +class CylcError(Exception): + """Generic exception for Cylc errors. + + This exception is raised in-place of "expected" errors where a short + message to the user is more appropriate than traceback. + + CLI commands will catch this exception and exit with str(exception). + """
+ + + +
+[docs] +class PluginError(CylcError): + """Represents an error arising from a Cylc plugin. + + Args: + entry_point: + The plugin entry point as defined in setup.cfg + (e.g. 'cylc.main_loop') + plugin_name: + Name of the plugin + exc: + Original exception caught when trying to run the plugin + + """ + + def __init__(self, entry_point: str, plugin_name: str, exc: Exception): + self.entry_point = entry_point + self.plugin_name = plugin_name + self.exc = exc + + def __str__(self) -> str: + return ( + f"Error in plugin {self.entry_point}.{self.plugin_name}\n" + f"{type(self.exc).__name__}: {self.exc}" + )
+ + + +
+[docs] +class InputError(CylcError): + """Exception covering erroneous user input to a Cylc interface. + + Ideally this would be handled in the interface (e.g. argument parser). + If this isn't possible raise InputError. + + """
+ + + +
+[docs] +class CylcConfigError(CylcError): + """Generic exception to handle an error in a Cylc configuration file."""
+ + # TODO: reference the configuration element causing the problem + + +
+[docs] +class WorkflowConfigError(CylcConfigError): + """Exception for configuration errors in a Cylc workflow configuration."""
+ + + +
+[docs] +class GlobalConfigError(CylcConfigError): + """Exception for configuration errors in a Cylc global configuration."""
+ + + +
+[docs] +class GraphParseError(WorkflowConfigError): + """Exception for errors in Cylc workflow graphing."""
+ + + +
+[docs] +class TriggerExpressionError(GraphParseError): + """Trigger expression syntax issue."""
+ + + +
+[docs] +class TaskProxySequenceBoundsError(CylcError): + """Error on TaskProxy.__init__ with out of sequence bounds start point.""" + + def __init__(self, msg): + CylcError.__init__( + self, 'Not loading %s (out of sequence bounds)' % msg)
+ + + +
+[docs] +class ParamExpandError(WorkflowConfigError): + """Exception for errors in Cylc parameter expansion."""
+ + + +
+[docs] +class WorkflowEventError(CylcError): + """Exception for errors in Cylc event handlers."""
+ + + +
+[docs] +class CommandFailedError(CylcError): + """Exception for when scheduler commands fail.""" + def __init__(self, value: Union[str, Exception]): + self.value = value + + def __str__(self) -> str: + if isinstance(self.value, Exception): + return f"{type(self.value).__name__}: {self.value}" + return self.value
+ + + +
+[docs] +class ServiceFileError(CylcError): + """Exception for errors related to workflow service files."""
+ + + +
+[docs] +class WorkflowFilesError(CylcError): + """Exception for errors related to workflow files/directories.""" + bullet = "\n -"
+ + + +
+[docs] +class ContactFileExists(CylcError): + """Workflow contact file exists."""
+ + + +
+[docs] +class FileRemovalError(CylcError): + """Exception for errors during deletion of files/directories, which are + probably the filesystem's fault, not Cylc's.""" + + def __init__(self, exc: Exception) -> None: + CylcError.__init__( + self, + f"{exc}. This is probably a temporary issue with the filesystem, " + "not a problem with Cylc." + )
+ + + +
+[docs] +class PlatformError(CylcError): + """Error in the management of a remote platform. + + If the exception represents a command failure, provide either the ctx OR + manually populate the remaining kwargs. Otherwise leave the kwargs blank. + + Args: + message: + Short description. + platform_name: + Name of the platform. + ctx: + SubFuncContext object if available. + The other kwargs are derived from this. + cmd: + The remote command. + ret_code: + The command's return code. + out: + The command's stdout. + err: + The command's stderr. + + """ + + MSG_INIT = "initialisation did not complete" + MSG_SELECT = "host selection failed" + MSG_TIDY = "clean up did not complete" + + def __init__( + self, + message: str, + platform_name: str, + *, + ctx: 'Optional[SubFuncContext]' = None, + cmd: Union[str, Sequence[str], None] = None, + ret_code: Optional[int] = None, + out: Optional[str] = None, + err: Optional[str] = None + ) -> None: + self.msg = message + self.platform_name = platform_name + if ctx: + self.cmd = ctx.cmd + self.ret_code = ctx.ret_code + self.out = ctx.out + self.err = ctx.err + else: + self.cmd = cmd + self.ret_code = ret_code + self.out = out + self.err = err + # convert the cmd object to a str if needed + if self.cmd and not isinstance(self.cmd, str): + self.cmd = format_cmd(self.cmd) + + def __str__(self): + # matches cylc.flow.platforms.log_platform_event format + if self.platform_name: + ret = f'platform: {self.platform_name} - {self.msg}' + else: + ret = f'{self.msg}' + for label, item in [ + ('COMMAND', self.cmd), + ('RETURN CODE', self.ret_code), + ('STDOUT', self.out), + ('STDERR', self.err) + ]: + if item is not None: + ret += f'\n{label}:' + for line in str(item).splitlines(True): # keep newline chars + ret += f"\n {line}" + return ret
+ + + +
+[docs] +class TaskDefError(WorkflowConfigError): + """Exception raise for errors in TaskDef initialization."""
+ + + +
+[docs] +class XtriggerConfigError(WorkflowConfigError): + """An error in an xtrigger. + + For example: + + * If the function module was not found. + * If the function was not found in the xtrigger module. + * If the function is not callable. + * If any string template in the function context + arguments are not present in the expected template values. + + """ + + def __init__(self, label: str, func: str, message: Union[str, Exception]): + self.label = label + self.func = func + self.message = message + + def __str__(self) -> str: + return f'[@{self.label}] {self.func}\n{self.message}'
+ + + +
+[docs] +class ClientError(CylcError): + """Base class for errors raised by Cylc client instances. + + For example, the workflow you are trying to connect to is stopped. + + Attributes: + message: + The exception message. + traceback: + The underlying exception instance if available. + workflow: + The workflow ID if available. + """ + + def __init__( + self, + message: str, + traceback: Optional[str] = None, + workflow: Optional[str] = None + ): + self.message = message + self.traceback = traceback + # Workflow not included in string representation but useful bit of + # info to attach to the exception object + self.workflow = workflow + + def __str__(self) -> str: + ret = self.message + if self.traceback: + # append server-side traceback + ret += '\n' + self.traceback + return ret
+ + + +
+[docs] +class WorkflowStopped(ClientError): + """The Cylc scheduler you attempted to connect to is stopped.""" + + def __init__(self, workflow): + self.workflow = workflow + + def __str__(self): + return f'{self.workflow} is not running'
+ + + +
+[docs] +class ClientTimeout(CylcError): + """The scheduler did not respond within the timeout. + + This could be due to: + * Network issues. + * Scheduler issues. + * Insufficient timeout. + + To increase the timeout, use the ``--comms-timeout`` option. + + """ + + def __init__(self, message: str, workflow: Optional[str] = None): + self.message = message + self.workflow = workflow + + def __str__(self) -> str: + return self.message
+ + + +
+[docs] +class CyclingError(CylcError): + """Base class for errors in cycling configuration."""
+ + + +
+[docs] +class CyclerTypeError(CyclingError): + """An error raised when incompatible cycling types are wrongly mixed.""" + + def __init__(self, *args): + CyclingError.__init__( + self, + 'Incompatible cycling types: {0} ({1}), {2} ({3})'.format(*args))
+ + + +
+[docs] +class PointParsingError(CyclingError): + """An error raised when a point has an incorrect value.""" + + def __init__(self, *args): + CyclingError.__init__( + self, 'Incompatible value for {0}: {1}: {2}'.format(*args))
+ + + +
+[docs] +class IntervalParsingError(CyclingError): + """An error raised when an interval has an incorrect value.""" + + def __init__(self, *args): + CyclingError.__init__( + self, 'Incompatible value for {0}: {1}'.format(*args))
+ + + +
+[docs] +class SequenceParsingError(CyclingError): + """Error on parsing an invalid sequence."""
+ + + +
+[docs] +class SequenceDegenerateError(CyclingError): + """An error raised when adjacent points on a sequence are equal.""" + + def __init__(self, *args): + CyclingError.__init__( + self, ( + '{0}, point format {1}: equal adjacent points:' + ' {2} => {3}.' + ).format(*args))
+ + + +
+[docs] +class CylcTimeSyntaxError(CyclingError): + """An error denoting invalid ISO/Cylc input syntax."""
+ + + +
+[docs] +class CylcMissingContextPointError(CyclingError): + """An error denoting a missing (but required) context cycle point."""
+ + + +
+[docs] +class CylcMissingFinalCyclePointError(CyclingError): + """An error denoting a missing (but required) final cycle point."""
+ + + +
+[docs] +class PlatformLookupError(CylcConfigError): + """Unable to determine the correct job platform from the information + given"""
+ + + +
+[docs] +class HostSelectException(CylcError): + """No hosts could be selected from the provided configuration.""" + + def __init__(self, data: Dict[str, dict]): + self.data = data + + def __str__(self) -> str: + ret = 'Could not select host from:' + for host, data in sorted(self.data.items()): + if host != 'ranking': + ret += f'\n {host}:' + for key, value in data.items(): + ret += f'\n {key}: {value}' + hint = self.get_hint() + if hint: + ret += f'\n\n{hint}' + return ret + +
+[docs] + def get_hint(self): + """Return a hint to explain this error for certain cases.""" + if all( + # all procs came back with special SSH error code 255 + datum.get('returncode') == 255 + for key, datum in self.data.items() + if key != 'ranking' + ): + # likely SSH issues + return ( + 'Cylc could not establish SSH connection to the run hosts.' + '\nEnsure you can SSH to these hosts without having to' + ' answer any prompts.' + ) + + if ( + # a ranking expression was used + self.data.get('ranking') + # and all procs came back with special 'cylc psutil' error code 2 + # (which is used for errors relating to the extraction of metrics) + and all( + datum.get('returncode') == 2 + for key, datum in self.data.items() + if key != 'ranking' + ) + ): + # likely an issue with the ranking expression + lines = wrap( + self.data.get("ranking"), + initial_indent=' ', + subsequent_indent=' ', + ) + ranking = "\n".join(lines) + return ( + 'This is likely an error in the ranking expression:' + f'\n{ranking}' + '\n\nConfigured by:' + '\n global.cylc[scheduler][run hosts]ranking' + ) + + return None
+
+ + + +
+[docs] +class NoHostsError(CylcError): + """None of the hosts of a given platform were reachable.""" + def __init__(self, platform): + self.platform_name = platform['name'] + + def __str__(self): + return f'Unable to find valid host for {self.platform_name}'
+ + + +
+[docs] +class NoPlatformsError(PlatformLookupError): + """None of the platforms of a given set were reachable. + + Args: + identity: + The name of the platform group or install target. + set_type: + Whether the set of platforms is a platform group or an install + target. + place: + Where the attempt to get the platform failed. + """ + def __init__( + self, + identity: str, + hosts_consumed: Set[str], + set_type: str = 'group', + place: str = '', + ): + self.identity = identity + self.type = set_type + self.hosts_consumed = hosts_consumed + if place: + self.place = f' during {place}.' + else: + self.place = '.' + + def __str__(self): + return ( + f'Unable to find a platform from {self.type} {self.identity}' + f'{self.place}' + )
+ + + +
+[docs] +class CylcVersionError(CylcError): + """Contact file is for a Cylc Version not supported by this script.""" + def __init__(self, version=None): + self.version = version + + def __str__(self): + if self.version is not None: + return ( + f'Installed Cylc {self.version} workflow is not ' + 'compatible with Cylc 8.' + ) + else: + return "Installed workflow is not compatible with Cylc 8."
+ + + +
+[docs] +class InvalidCompletionExpression(CylcError): + """For the [runtime][<namespace>]completion configuration. + + Raised when non-whitelisted syntax is present. + """ + def __init__(self, message, expr=None): + self.message = message + self.expr = expr + + def __str__(self): + return self.message
+ +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/jinja/filters/duration_as.html b/nightly_8.4/html/_modules/cylc/flow/jinja/filters/duration_as.html new file mode 100644 index 00000000000..006ff3309a4 --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/jinja/filters/duration_as.html @@ -0,0 +1,261 @@ + + + + + + cylc.flow.jinja.filters.duration_as — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for cylc.flow.jinja.filters.duration_as

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) 2008-2019 NIWA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""Filter for formatting ISO8601 duration strings."""
+
+from typing import Callable, Dict, Tuple
+
+from metomi.isodatetime.parsers import DurationParser
+
+SECONDS_PER_MINUTE = 60.0
+MINUTES_PER_HOUR = 60.0
+HOURS_PER_DAY = 24.0
+DAYS_PER_WEEK = 7.0
+
+SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR
+SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY
+SECONDS_PER_WEEK = SECONDS_PER_DAY * DAYS_PER_WEEK
+
+CONVERSIONS: Dict[Tuple[str, str], Callable] = {
+    ('s', 'seconds'): float,
+    ('m', 'minutes'): lambda s: float(s) / SECONDS_PER_MINUTE,
+    ('h', 'hours'): lambda s: float(s) / SECONDS_PER_HOUR,
+    ('d', 'days'): lambda s: float(s) / SECONDS_PER_DAY,
+    ('w', 'weeks'): lambda s: float(s) / SECONDS_PER_WEEK,
+}
+
+
+
+[docs] +def duration_as(iso8601_duration: str, units: str) -> float: + """Format an :term:`ISO8601 duration` string as the specified units. + + Units for the conversion can be specified in a case-insensitive short or + long form: + + - Seconds - "s" or "seconds" + - Minutes - "m" or "minutes" + - Hours - "h" or "hours" + - Days - "d" or "days" + - Weeks - "w" or "weeks" + + While the filtered value is a floating-point number, it is often required + to supply an integer to workflow entities (e.g. environment variables) that + require it. This is accomplished by chaining filters: + + - ``{{CYCLE_INTERVAL | duration_as('h') | int}}`` - 24 + - ``{{CYCLE_SUBINTERVAL | duration_as('h') | int}}`` - 0 + - ``{{CYCLE_INTERVAL | duration_as('s') | int}}`` - 86400 + - ``{{CYCLE_SUBINTERVAL | duration_as('s') | int}}`` - 1800 + + Args: + iso8601_duration: Any valid ISO8601 duration as a string. + units: Destination unit for the duration conversion + + Return: + The total number of the specified unit contained in the specified + duration as a floating-point number. + + Raises: + ISO8601SyntaxError: In the event of an invalid datetime string. + + Python Examples: + >>> # Basic usage. + >>> duration_as('PT1M', 's') + 60.0 + >>> duration_as('PT1H', 'seconds') + 3600.0 + + >>> # Exceptions. + >>> duration_as('invalid value', 's') # doctest: +NORMALIZE_WHITESPACE + Traceback (most recent call last): + metomi.isodatetime.exceptions.ISO8601SyntaxError: Invalid ISO 8601\ + duration representation: invalid value + >>> duration_as('invalid unit', '#') # doctest: +NORMALIZE_WHITESPACE + Traceback (most recent call last): + ValueError: No matching units found for # + + Jinja2 Examples: + .. code-block:: cylc + + {% set CYCLE_INTERVAL = 'PT1D' %} + {{ CYCLE_INTERVAL | duration_as('h') }} # 24.0 + {% set CYCLE_SUBINTERVAL = 'PT30M' %} + {{ CYCLE_SUBINTERVAL | duration_as('hours') }} # 0.5 + {% set CYCLE_INTERVAL = 'PT1D' %} + {{ CYCLE_INTERVAL | duration_as('s') }} # 86400.0 + {% set CYCLE_SUBINTERVAL = 'PT30M' %} + {{ CYCLE_SUBINTERVAL | duration_as('seconds') }} # 1800.0 + + """ + for converter_names in CONVERSIONS: + if units.lower() in converter_names: + converter = CONVERSIONS[converter_names] + break + else: + raise ValueError('No matching units found for %s' % units) + return converter(DurationParser().parse(iso8601_duration).get_seconds())
+ +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/jinja/filters/pad.html b/nightly_8.4/html/_modules/cylc/flow/jinja/filters/pad.html new file mode 100644 index 00000000000..141777c99e6 --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/jinja/filters/pad.html @@ -0,0 +1,208 @@ + + + + + + cylc.flow.jinja.filters.pad — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.jinja.filters.pad

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""Filter for padding strings to a set number of chars."""
+
+from typing import Union
+
+
+
+[docs] +def pad(value: str, length: Union[int, str], fillchar: str = ' '): + """Pads a string to some length with a fill character + + Useful for generating task names and related values in ensemble workflows. + + Args: + value: + The string to pad. + length: + The length for the returned string. + fillchar: + The character to fill in surplus space (space by default). + + Returns: + str: value padded to the left with fillchar to length length. + + Python Examples: + >>> pad('13', 3, '0') + '013' + >>> pad('foo', 6) + ' foo' + >>> pad('foo', 2) + 'foo' + + Jinja2 Examples: + .. code-block:: cylc + + {% for i in range(0,100) %} # 0, 1, ..., 99 + {% set j = i | pad(2,'0') %} + [[A_{{j}}]] # [[A_00]], [[A_01]], ..., [[A_99]] + {% endfor %} + + """ + return str(value).rjust(int(length), str(fillchar))
+ +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/jinja/filters/strftime.html b/nightly_8.4/html/_modules/cylc/flow/jinja/filters/strftime.html new file mode 100644 index 00000000000..a7902f4565d --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/jinja/filters/strftime.html @@ -0,0 +1,258 @@ + + + + + + cylc.flow.jinja.filters.strftime — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for cylc.flow.jinja.filters.strftime

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""Filter for formatting ISO8601 datetime strings."""
+
+from typing import Optional
+
+from metomi.isodatetime.parsers import TimePointParser
+
+
+
+[docs] +def strftime( + iso8601_datetime: str, + strftime_str: str, + strptime_str: Optional[str] = None, +): + """Format an :term:`ISO8601 datetime` string using an strftime string. + + .. code-block:: cylc + + {{ '10661004T08+01' | strftime('%H') }} # 00 + + It is also possible to parse non-standard date-time strings by passing a + strptime string as the second argument. + + Args: + iso8601_datetime: + Any valid ISO8601 datetime as a string. + strftime_str: + A valid strftime string to format the output datetime. + strptime_str: + A valid strptime string defining the format of the provided + iso8601_datetime. + + Return: + The result of applying the strftime to the iso8601_datetime as parsed + by the strptime string if provided. + + Raises: + ISO8601SyntaxError: In the event of an invalid datetime string. + StrftimeSyntaxError: In the event of an invalid strftime string. + + Python Examples: + >>> # Basic usage. + >>> strftime('2000-01-01T00Z', '%H') + '00' + >>> strftime('2000', '%H') + '00' + >>> strftime('2000', '%Y/%m/%d %H:%M:%S') + '2000/01/01 00:00:00' + >>> strftime('10661014T08+01', '%z') # Timezone offset. + '+0100' + >>> strftime('10661014T08+01', '%j') # Day of the year + '287' + + >>> # Strptime. + >>> strftime('12,30,2000', '%m', '%m,%d,%Y') + '12' + >>> strftime('1066/10/14 08:00:00', '%Y%m%dT%H', '%Y/%m/%d %H:%M:%S') + '10661014T08' + + >>> # Exceptions. + >>> strftime('invalid', '%H') # doctest: +NORMALIZE_WHITESPACE + Traceback (most recent call last): + <class 'metomi.isodatetime.exceptions.ISO8601SyntaxError'> + metomi.isodatetime.exceptions.ISO8601SyntaxError: Invalid ISO 8601 \ + date representation: invalid + >>> strftime('2000', '%invalid') # doctest: +NORMALIZE_WHITESPACE + Traceback (most recent call last): + metomi.isodatetime.exceptions.StrftimeSyntaxError: Invalid \ + strftime/strptime representation: %i + >>> strftime('2000', '%Y', '%invalid') + ... # doctest: +NORMALIZE_WHITESPACE + Traceback (most recent call last): + metomi.isodatetime.exceptions.StrftimeSyntaxError: Invalid \ + strftime/strptime representation: %i + + Jinja2 Examples: + .. code-block:: cylc + + {% set START_CYCLE = '10661004T08+01' %} + + {{START_CYCLE | strftime('%Y')}} # 1066 + {{START_CYCLE | strftime('%m')}} # 10 + {{START_CYCLE | strftime('%d')}} # 14 + {{START_CYCLE | strftime('%H:%M:%S %z')}} # 08:00:00 +01 + {{'12,30,2000' | strftime('%m', '%m,%d,%Y')}} # 12 + + """ + if not strptime_str: + return TimePointParser().parse(iso8601_datetime).strftime(strftime_str) + return TimePointParser().strptime(iso8601_datetime, strptime_str).strftime( + strftime_str)
+ +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/job_runner_handlers/documentation.html b/nightly_8.4/html/_modules/cylc/flow/job_runner_handlers/documentation.html new file mode 100644 index 00000000000..9582768f201 --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/job_runner_handlers/documentation.html @@ -0,0 +1,623 @@ + + + + + + cylc.flow.job_runner_handlers.documentation — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for cylc.flow.job_runner_handlers.documentation

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+This file is used to auto-generate some reference documentation for the
+job runner plugin interface.
+
+Note the class contained here is just for documentation purposes and is
+not intended to be subclassed.
+"""
+
+from typing import (
+    Iterable,
+    List,
+    Tuple,
+    TYPE_CHECKING,
+)
+
+if TYPE_CHECKING:
+    import re
+
+
+
+[docs] +class ExampleHandler(): + """Documentation for writing job runner handlers. + + Cylc can submit jobs to a number of different job runners + (aka batch systems) e.g. Slurm and PBS. For a list of built-in integrations + see :ref:`AvailableMethods`. + + If the job runner you require is not on this list, Cylc provides a generic + interface for writing your own integration. + + Defining a new job runner handler requires a little Python programming. Use + the built-in handlers + (e.g. :py:mod:`cylc.flow.job_runner_handlers.background`) as examples. + + .. _where to put job runner handler modules: + + .. rubric:: Installation + + Custom job runner handlers must be installed on workflow and job + hosts in one of these locations: + + - under ``WORKFLOW-RUN-DIR/lib/python/`` + - under ``CYLC-PATH/cylc/flow/job_runner_handlers/`` + - or anywhere in ``$PYTHONPATH`` + + Each module should export the symbol ``JOB_RUNNER_HANDLER`` for the + singleton instance that implements the job system handler logic e.g: + + .. code-block:: python + :caption: my_handler.py + + class MyHandler(): + pass + + JOB_RUNNER_HANDLER = MyHandler() + + Each job runner handler class should instantiate with no argument. + + + .. rubric:: Usage + + You can then define a Cylc platform using the handler: + + .. code-block:: cylc + :caption: global.cylc + + [platforms] + [[my_platform]] + job runner = my_handler # note matches Python module name + hosts = localhost + + And configure tasks to submit to it: + + .. code-block:: cylc + :caption: flow.cylc + + [runtime] + [[my_task]] + script = echo "Hello World!" + platform = my_platform + + + .. rubric:: Common Arguments + + ``job_conf: dict`` + The Cylc job configuration as a dictionary with the following fields: + + * ``dependencies`` + * ``directives`` + * ``env-script`` + * ``environment`` + * ``err-script`` + * ``execution_time_limit`` + * ``exit-script`` + * ``flow_nums`` + * ``init-script`` + * ``job_d`` + * ``job_file_path`` + * ``job_runner_command_template`` + * ``job_runner_name`` + * ``namespace_hierarchy`` + * ``param_var`` + * ``platform`` + * ``post-script`` + * ``pre-script`` + * ``script`` + * ``submit_num`` + * ``task_id`` + * ``try_num`` + * ``uuid_str`` + * ``work_d`` + * ``workflow_name`` + + ``submit_opts: dict`` + The Cylc job submission options as a dictionary which may contain + the following fields: + + * ``env`` + * ``execution_time_limit`` + * ``execution_time_limit`` + * ``job_runner_cmd_tmpl`` + * ``job_runner_cmd_tmpl`` + + + .. rubric:: An Example + + The following ``qsub.py`` module overrides the built-in *pbs* + job runner handler to change the directive prefix from ``#PBS`` to + ``#QSUB``: + + .. TODO - double check that this still works, it's been a while + + .. code-block:: python + + #!/usr/bin/env python3 + + from cylc.flow.job_runner_handlers.pbs import PBSHandler + + class QSUBHandler(PBSHandler): + DIRECTIVE_PREFIX = "#QSUB " + + JOB_RUNNER_HANDLER = QSUBHandler() + + If this is in the Python search path (see + :ref:`Where To Put Job Runner Handler Modules` above) you can use it by + name in your global configuration: + + .. code-block:: cylc + + [platforms] + [[my_platform]] + hosts = myhostA, myhostB + job runner = qsub # <---! + + Then in your ``flow.cylc`` file you can use this platform: + + .. code-block:: cylc + + # Note, this workflow will fail at run time because we only changed the + # directive format, and PBS does not accept ``#QSUB`` directives in + # reality. + + [scheduling] + [[graph]] + R1 = "a" + [runtime] + [[root]] + execution time limit = PT1M + platform = my_platform + [[[directives]]] + -l nodes = 1 + -q = long + -V = + + .. note:: + + Don't subclass this class as it provides optional interfaces which + you may not want to inherit. + + """ + + FAIL_SIGNALS: Tuple[str] + """A tuple containing the names of signals to trap for reporting errors. + + The default is ``("EXIT", "ERR", "TERM", "XCPU")``. + + ``ERR`` and ``EXIT`` are always recommended. + ``EXIT`` is used to report premature stopping of the job + script, and its trap is unset at the end of the script. + """ + + KILL_CMD_TMPL: str + """Command template for killing a job submission. + + A Python string template for getting the job runner command to remove + and terminate a job ID. The command is formed using the logic: + ``job_runner.KILL_CMD_TMPL % {"job_id": job_id}``. + + For info on Python string template format see: + https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting + + """ + + POLL_CMD: str + """Command for checking job submissions. + + A list of job IDs to poll will be provided as arguments. + + The command should write valid submitted/running job IDs to stdout. + + * To filter out invalid/failed jobs use + :py:meth:`ExampleHandler.filter_poll_many_output`. + * To build a more advanced command than is possible with this configuration + use :py:meth:`ExampleHandler.get_poll_many_cmd`. + + """ + + POLL_CANT_CONNECT_ERR: str + """String for detecting communication errors in poll command output. + + A string containing an error message. If this is defined, when a poll + command returns a non-zero return code and its STDERR contains this + string, then the poll result will not be trusted, because it is assumed + that the job runner is currently unavailable. Jobs submitted to the + job runner will be assumed OK until we are able to connect to the + job runner again. + + """ + + SHOULD_KILL_PROC_GROUP: bool + """Kill jobs by killing the process group. + + A boolean to indicate whether it is necessary to kill a job by sending + a signal to its Unix process group. This boolean also indicates that + a job submitted via this job runner will physically run on the same + host it is submitted to. + + """ + + SHOULD_POLL_PROC_GROUP: bool + """Poll jobs by PID. + + A boolean to indicate whether it is necessary to poll a job by its PID + as well as the job ID. + + """ + + REC_ID_FROM_SUBMIT_OUT: 're.Pattern' + """Regular expression to extract job IDs from submission stderr. + + A regular expression (compiled) to extract the job "id" from the standard + output or standard error of the job submission command. + + """ + + REC_ID_FROM_SUBMIT_ERR: 're.Pattern' + """Regular expression to extract job IDs from submission stderr. + + See :py:attr:`ExampleHandler.REC_ID_FROM_SUBMIT_OUT`. + + """ + + SUBMIT_CMD_ENV: Iterable[str] + """Extra environment variables for the job runner command. + + A Python dict (or an iterable that can be used to update a dict) + containing extra environment variables for getting the job runner + command to submit a job file. + + """ + + SUBMIT_CMD_TMPL: str + """Command template for job submission. + + A Python string template for getting the job runner command to submit a + job file. The command is formed using the logic: + ``job_runner.SUBMIT_CMD_TMPL % {"job": job_file_path}`` + + For info on Python string template format see: + https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting + + """ + +
+[docs] + def filter_poll_many_output(self, out: str) -> List[str]: + """Filter job ides out of poll output. + + Called after the job runner's poll command. The method should read + the output and return a list of job IDs that are still in the + job runner. + + Args: + out: Job poll stdout. + + Returns: + List of job IDs + + """ + raise NotImplementedError()
+ + +
+[docs] + def filter_submit_output(self, out: str, err: str) -> Tuple[str, str]: + """Filter job submission stdout/err. + + Filter the standard output and standard error of the job submission + command. This is useful if the job submission command returns + information that should just be ignored. + + See also :py:meth:`ExampleHandler.SUBMIT_CMD_TMPL`. + + Args: + out: Job submit stdout. + err: Job submit stderr. + + Returns: + (new_out, new_err) + """ + raise NotImplementedError()
+ + +
+[docs] + def format_directives(self, job_conf: dict) -> List[str]: + """Returns lines to be appended to the job script. + + This method formats the job directives for a job file, if + job file directives are relevant for the job runner. The argument + "job_conf" is a dict containing the job configuration. + + Args: + job_conf: The Cylc configuration. + + Returns: + lines + + """ + raise NotImplementedError()
+ + +
+[docs] + def get_poll_many_cmd(self, job_id_list: List[str]) -> List[str]: + """Return a command to poll the specified jobs. + + If specified, this will be called instead of + :py:attr:`ExampleHandler.POLL_CMD`. + + Args: + job_id_list: The list of job IDs to poll. + + Returns: + command e.g. ['foo', '--bar', 'baz'] + + """ + raise NotImplementedError()
+ + +
+[docs] + def get_submit_stdin(self, job_file_path: str, submit_opts: dict) -> Tuple: + """ + + Return a 2-element tuple ``(proc_stdin_arg, proc_stdin_value)``. + + * Element 1 is suitable for the ``stdin=...`` argument of + ``subprocess.Popen`` so it can be a file handle, ``subprocess.PIPE`` + or ``None``. + * Element 2 is the string content to pipe to stdin of the submit + command (relevant only if ``proc_stdin_arg`` is ``subprocess.PIPE``. + + Args: + job_file_path: The path to the job file for this submission. + submit_opts: Job submission options. + + Returns: + (proc_stdin_arg, proc_stdin_value) + + """ + raise NotImplementedError()
+ + +
+[docs] + def get_vacation_signal(self, job_conf: dict) -> str: + """Return the vacation signal. + + If relevant, return a string containing the name of the signal that + indicates the job has been vacated by the job runner. + + Args: + job_conf: The Cylc configuration. + + Returns: + signal + + """ + raise NotImplementedError()
+ + +
+[docs] + def submit( + self, + job_file_path: str, + submit_opts: dict, + ) -> Tuple[int, str, str]: + """Submit a job. + + Submit a job and return an instance of the Popen object for the + submission. This method is useful if the job submission requires logic + beyond just running a system or shell command. + + See also :py:attr:`ExampleHandler.SUBMIT_CMD_TMPL`. + + You must pass "env=submit_opts.get('env')" to Popen - see + :py:mod:`cylc.flow.job_runner_handlers.background` + for an example. + + Args: + job_file_path: The job file for this submission. + submit_opts: Job submission options. + + Returns: + (ret_code, out, err) + + ret_code: + Subprocess return code. + out: + Subprocess standard output, note this should be newline + terminated. + err: + Subprocess standard error. + + """ + raise NotImplementedError()
+ + +
+[docs] + def manip_job_id(self, job_id: str) -> str: + """Modify the job ID that is returned by the job submit command. + + Args: + job_id: The job ID returned by the submit command. + + Returns: + job_id + + """ + raise NotImplementedError()
+
+ +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/main_loop.html b/nightly_8.4/html/_modules/cylc/flow/main_loop.html new file mode 100644 index 00000000000..89fe93c5a47 --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/main_loop.html @@ -0,0 +1,536 @@ + + + + + + cylc.flow.main_loop — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.main_loop

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""Plugins for running Python code inside of the Cylc scheduler.
+
+.. _BuiltInPlugins:
+
+Built In Plugins
+----------------
+
+Cylc Flow provides the following plugins:
+
+.. autosummary::
+   :toctree: built-in
+   :template: main_loop_plugin.rst
+
+   cylc.flow.main_loop.auto_restart
+   cylc.flow.main_loop.health_check
+   cylc.flow.main_loop.log_data_store
+   cylc.flow.main_loop.log_main_loop
+   cylc.flow.main_loop.log_memory
+   cylc.flow.main_loop.reset_bad_hosts
+
+.. Note: Autosummary generates files in this directory, these are cleaned
+         up by `make clean`.
+
+
+Configuring
+-----------
+
+Main loop plugins can be activated either by:
+
+* Using the ``--main-loop`` option with ``cylc play`` e.g:
+
+  .. code-block:: console
+
+     $ # run a workflow using the "health check" and "auto restart" plugins:
+     $ cylc play my-workflow --main-loop 'health check' \
+--main-loop 'auto restart'
+
+* Adding them to the default list of plugins in
+  :cylc:conf:`global.cylc[scheduler][main loop]plugins` e.g:
+
+  .. code-block:: cylc
+
+     [scheduler]
+         [[main loop]]
+             plugins = health check, auto restart
+
+Main loop plugins can be individually configured in their
+:cylc:conf:`global.cylc[scheduler][main loop][<plugin name>]` section e.g:
+
+.. code-block:: cylc
+
+   [scheduler]
+       [[main loop]]
+           [[[health check]]]
+               interval = PT5M  # perform check every 5 minutes
+
+
+Developing Main Loop Plugins
+----------------------------
+
+Main loop plugins are Python modules containing asynchronous function(s)
+(sometimes referred to as coroutines) which Cylc Flow executes within the
+scheduler.
+
+Hello World
+^^^^^^^^^^^
+
+Here is the "hello world" of main loop plugins:
+
+.. code-block:: python
+   :caption: my_plugin.py
+
+   from cylc.flow import LOG
+   from cylc.flow.main_loop import startup
+
+   @startup
+   async def my_startup_coroutine(schd, state):
+      # write Hello <workflow name> to the Cylc log.
+      LOG.info(f'Hello {schd.workflow}')
+
+Plugins are registered by registering them with the ``cylc.main_loop``
+entry point:
+
+.. code-block:: python
+   :caption: setup.py
+
+   # plugins must be properly installed, in-place PYTHONPATH meddling will
+   # not work.
+
+   from setuptools import setup
+
+   setup(
+       name='my-plugin',
+       version='1.0',
+       py_modules=['my_plugin'],
+       entry_points={
+          # register this plugin with Cylc
+          'cylc.main_loop': [
+            # name = python.namespace.of.module
+            'my_plugin=my_plugin.my_plugin'
+          ]
+       }
+   )
+
+Examples
+^^^^^^^^
+
+For examples see the built-in plugins in the :py:mod:`cylc.flow.main_loop`
+module which are registered in the Cylc Flow ``setup.cfg`` file.
+
+Coroutines
+^^^^^^^^^^
+
+.. _coroutines: https://docs.python.org/3/library/asyncio-task.html#coroutines
+
+Plugins provide asynchronous functions (`coroutines`_) which Cylc will
+then run inside the scheduler.
+
+Coroutines should be fast running (read as gentle on the scheduler)
+and perform IO asynchronously.
+
+Coroutines shouldn't meddle with the state of the scheduler and should be
+parallel-safe with other plugins.
+
+Event Types
+^^^^^^^^^^^
+
+Coroutines must be decorated using one of the main loop decorators. The
+choice of decorator effects when the coroutine is called and what
+arguments are provided to it.
+
+The available event types are:
+
+.. autofunction:: cylc.flow.main_loop.startup
+
+.. autofunction:: cylc.flow.main_loop.shutdown
+
+.. autofunction:: cylc.flow.main_loop.periodic
+
+"""
+from collections import deque
+from inspect import (
+    getmembers,
+    isfunction
+)
+from textwrap import indent
+from time import time
+
+from cylc.flow import LOG, iter_entry_points
+from cylc.flow.exceptions import CylcError, InputError, PluginError
+
+
+class MainLoopPluginException(Exception):
+    """Raised in-place of CylcError exceptions.
+
+    Note:
+        * Not an instace of CylcError as that is used for controlled
+          shutdown e.g. SchedulerStop.
+
+    """
+
+
+async def _wrapper(fcn, scheduler, state, timings=None):
+    """Wrapper for all plugin functions.
+
+    * Logs the function's execution.
+    * Times the function.
+    * Catches any exceptions which aren't subclasses of CylcError.
+
+    """
+    sig = f'{fcn.__module__}:{fcn.__name__}'
+    LOG.debug(f'main_loop [run] {sig}')
+    start_time = time()
+    try:
+        await fcn(scheduler, state)
+    except CylcError as exc:
+        # allow CylcErrors through (e.g. SchedulerStop)
+        # NOTE: the `from None` bit gets rid of this gunk:
+        # > During handling of the above exception another exception
+        raise MainLoopPluginException(exc) from None
+    except Exception as exc:
+        LOG.error(f'Error in main loop plugin {sig}')
+        LOG.exception(exc)
+    duration = time() - start_time
+    LOG.debug(f'main_loop [end] {sig} ({duration:.3f}s)')
+    if timings is not None:
+        timings.append((start_time, duration))
+
+
+def _debounce(interval, timings):
+    """Rate limiter, returns True if the interval has elapsed.
+
+    Arguments:
+        interval (float):
+            Time interval in seconds as a float-type object.
+        timings (list):
+            List-list object of the timings of previous runs in the form
+            ``(completion_wallclock_time, run_duration)``.
+            Wallclock times are unix epoch times in seconds.
+
+    Examples:
+        >>> from time import time
+
+        No previous run (should always return True):
+        >>> _debounce(1., [(0, 0)])
+        True
+
+        Interval not yet elapsed since previous run:
+        >>> _debounce(1., [(time(), 0)])
+        False
+
+        Interval has elapsed since previous run:
+        >>> _debounce(1., [(time() - 2, 0)])
+        True
+
+    """
+    if not interval:
+        return True
+    try:
+        last_run_at = timings[-1][0]
+    except IndexError:
+        last_run_at = 0
+    if (time() - last_run_at) > interval:
+        return True
+    return False
+
+
+
+[docs] +def startup(fcn): + """Decorates a coroutine which is run at workflow startup. + + The decorated coroutine should have the signature: + + ``async coroutine(scheduler, plugin_state) -> None`` + + Exceptions: + + * Regular Exceptions are caught and logged. + * Exceptions which subclass CylcError are re-raised as + MainLoopPluginException + + """ + fcn.main_loop = CoroTypes.StartUp + return fcn
+ + + +
+[docs] +def shutdown(fcn): + """Decorates a coroutine which is run at workflow shutdown. + + Note shutdown refers to "clean" shutdown as opposed to workflow abort. + + The decorated coroutine should have the signature: + + ``async coroutine(scheduler, plugin_state) -> None`` + + Exceptions: + + * Regular Exceptions are caught and logged. + * Exceptions which subclass CylcError are re-raised as + MainLoopPluginException + + """ + fcn.main_loop = CoroTypes.ShutDown + return fcn
+ + + +
+[docs] +def periodic(fcn): + """Decorates a coroutine which is run at a set interval. + + The decorated coroutine should have the signature: + + ``async coroutine(scheduler, plugin_state) -> None`` + + Exceptions: + + * Regular Exceptions are caught and logged. + * Exceptions which subclass CylcError are re-raised as + MainLoopPluginException + + Configuration: + + * The interval of execution can be altered using + :cylc:conf:`global.cylc[scheduler][main loop][<plugin name>]interval` + + """ + fcn.main_loop = CoroTypes.Periodic + return fcn
+ + + +class CoroTypes: + """Different types of coroutine which can be used with the main loop.""" + + StartUp = startup + ShutDown = shutdown + Periodic = periodic + + +def load(config, additional_plugins=None): + additional_plugins = additional_plugins or [] + entry_points = { + entry_point.name: entry_point + for entry_point in + iter_entry_points('cylc.main_loop') + } + plugins = { + 'state': {}, + 'timings': {} + } + for plugin_name in set(config['plugins'] + additional_plugins): + # get plugin + try: + entry_point = entry_points[plugin_name.replace(' ', '_')] + except KeyError: + raise InputError( + f'No main-loop plugin: "{plugin_name}"\n' + + ' Available plugins:\n' + + indent('\n'.join(sorted(entry_points)), ' ') + ) from None + # load plugin + try: + module = entry_point.load() + except Exception as exc: + raise PluginError( + 'cylc.main_loop', entry_point.name, exc + ) from None + # load coroutines + log = [] + for coro_name, coro in getmembers(module): + if isfunction(coro) and hasattr(coro, 'main_loop'): + log.append(coro_name) + plugins.setdefault( + coro.main_loop, {} + )[(plugin_name, coro_name)] = coro + plugins['timings'][(plugin_name, coro_name)] = deque(maxlen=1) + LOG.debug( + 'Loaded main loop plugin "%s":\n%s', + plugin_name, + '\n'.join(f'* {x}' for x in log) + ) + # set the initial state of the plugin + plugins['state'][plugin_name] = {} + # make a note of the config here for ease of reference + plugins['config'] = config + return plugins + + +def get_runners(plugins, coro_type, scheduler): + return [ + _wrapper( + coro, + scheduler, + plugins['state'][plugin_name], + timings=plugins['timings'][(plugin_name, coro_name)] + ) + for (plugin_name, coro_name), coro + in plugins.get(coro_type, {}).items() + if coro_type != CoroTypes.Periodic + or _debounce( + plugins['config'].get(plugin_name, {}).get('interval', None), + plugins['timings'][(plugin_name, coro_name)] + ) + ] +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/main_loop/auto_restart.html b/nightly_8.4/html/_modules/cylc/flow/main_loop/auto_restart.html new file mode 100644 index 00000000000..bf68637e1d6 --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/main_loop/auto_restart.html @@ -0,0 +1,408 @@ + + + + + + cylc.flow.main_loop.auto_restart — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.main_loop.auto_restart

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""Automatically restart workflows if they are running on bad servers.
+
+Loads in the global configuration to check if the server a workflow is running
+on is listed in :cylc:conf:`global.cylc[scheduler][run hosts]condemned`.
+
+This is useful if a host needs to be taken off-line e.g. for scheduled
+maintenance.
+
+This functionality is configured via the following site configuration
+settings:
+
+.. cylc-scope:: global.cylc
+
+- :cylc:conf:`[scheduler]auto restart delay`
+- :cylc:conf:`[scheduler][run hosts]condemned`
+- :cylc:conf:`[scheduler][run hosts]available`
+
+
+
+The auto stop-restart feature has two modes:
+
+Normal Mode
+   When a host is added to the
+   :cylc:conf:`[scheduler][run hosts]condemned` list, any workflows
+   running on that host will automatically shutdown then restart selecting a
+   new host from :cylc:conf:`[scheduler][run hosts]available`.
+
+   For safety, before attempting to stop the workflow Cylc will first wait
+   for any jobs running locally (under background or at) to complete.
+
+   In order for Cylc to be able to restart workflows the
+   :cylc:conf:`[scheduler][run hosts]available` hosts must all be on a
+   shared filesystem.
+Force Mode
+   If a host is suffixed with an exclamation mark then Cylc will not attempt
+   to automatically restart the workflow and any local jobs (running under
+   background or at) will be left running.
+
+For example in the following configuration any workflows running on
+``foo`` will attempt to restart on ``pub`` whereas any workflows
+running on ``bar`` will stop immediately, making no attempt to restart.
+
+.. code-block:: cylc
+
+   [scheduler]
+        [[run hosts]]
+            available = pub
+            condemned = foo, bar!
+
+.. warning::
+
+   Cylc will reject hosts with ambiguous names such as ``localhost`` or
+   ``127.0.0.1`` for this configuration as
+   :cylc:conf:`[scheduler][run hosts]condemned`
+   are evaluated on the workflow host server.
+
+To prevent large numbers of workflows attempting to restart simultaneously the
+:cylc:conf:`[scheduler]auto restart delay` setting defines a period
+of time in seconds.
+Workflows will wait for a random period of time between zero and
+:cylc:conf:`[scheduler]auto restart delay` seconds before
+attempting to stop and restart.
+
+Workflows that are started up in no-detach mode cannot auto stop-restart on a
+different host - as it will still end up attached to the condemned host.
+Therefore, a workflow in no-detach mode running on a condemned host will abort
+with a non-zero return code. The parent process should manually handle the
+restart of the workflow if desired.
+
+.. cylc-scope::
+
+"""
+from random import random
+from time import time
+import traceback
+
+from cylc.flow import LOG
+from cylc.flow.cfgspec.glbl_cfg import glbl_cfg
+from cylc.flow.exceptions import CylcConfigError, HostSelectException
+from cylc.flow.host_select import select_workflow_host
+from cylc.flow.hostuserutil import get_fqdn_by_host
+from cylc.flow.main_loop import periodic
+from cylc.flow.parsec.exceptions import ParsecError
+from cylc.flow.scheduler import SchedulerError
+from cylc.flow.workflow_status import AutoRestartMode
+from cylc.flow.wallclock import (
+    get_time_string_from_unix_time as time2str
+)
+
+
+
+[docs] +@periodic +async def auto_restart(scheduler, _): + """Automatically restart the workflow if configured to do so.""" + try: + current_glbl_cfg = glbl_cfg(cached=False) + except (CylcConfigError, ParsecError) as exc: + LOG.error( + 'auto restart: an error in the global config is preventing it from' + f' being reloaded:\n{exc}' + ) + # skip check - we can't do anything until the global config has been + # fixed + return False # return False to make testing easier + mode = _should_auto_restart(scheduler, current_glbl_cfg) + + if mode: + LOG.info('The Cylc workflow host will soon become un-available.') + _set_auto_restart( + scheduler, + restart_delay=current_glbl_cfg.get( + ['scheduler', 'auto restart delay'] + ), + mode=mode + )
+ + + +def _should_auto_restart(scheduler, current_glbl_cfg): + # check if workflow host is condemned - if so auto restart + if scheduler.stop_mode is None: + for host in current_glbl_cfg.get( + ['scheduler', 'run hosts', 'condemned'] + ): + if host.endswith('!'): + # host ends in an `!` -> force shutdown mode + mode = AutoRestartMode.FORCE_STOP + host = host[:-1] + else: + # normal mode (stop and restart the workflow) + mode = AutoRestartMode.RESTART_NORMAL + if scheduler.auto_restart_time is not None: + # workflow is already scheduled to stop-restart only + # AutoRestartMode.FORCE_STOP can override this. + continue + + if get_fqdn_by_host(host) == scheduler.host: + # this host is condemned, take the appropriate action + + return mode + return False + + +def _can_auto_restart(): + """Determine whether this workflow can safely auto stop-restart.""" + # Check whether there is currently an available host to restart on. + try: + select_workflow_host(cached=False) + except HostSelectException: + LOG.critical( + 'Workflow cannot automatically restart because:\n' + + 'No alternative host to restart workflow on.') + return False + except Exception: + # Any unexpected error in host selection shouldn't be able to take + # down the workflow. + LOG.critical( + 'Workflow cannot automatically restart because:\n' + + 'Error in host selection:\n' + + traceback.format_exc()) + return False + else: + return True + + +def _set_auto_restart( + scheduler, + restart_delay=None, + mode=AutoRestartMode.RESTART_NORMAL +): + """Configure the workflow to automatically stop and restart. + + Restart handled by `workflow_auto_restart`. + + Args: + scheduler (cylc.flow.scheduler.Scheduler): + Scheduler instance of the running workflow. + restart_delay (cylc.flow.parsec.DurationFloat): + Workflow will wait a random period between 0 and + `restart_delay` seconds before attempting to stop/restart in + order to avoid multiple workflows restarting simultaneously. + mode (str): Auto stop-restart mode. + + Return: + bool: False if it is not possible to automatically stop/restart + the workflow due to its configuration/runtime state. + """ + # Check that the workflow isn't already shutting down. + if scheduler.stop_mode: + return True + + # Force mode, stop the workflow now, don't restart it. + if mode == AutoRestartMode.FORCE_STOP: + LOG.critical( + 'This workflow will be shutdown as the workflow ' + 'host is unable to continue running it.\n' + 'When another workflow host becomes available ' + 'the workflow can be restarted by:\n' + f' $ cylc play {scheduler.workflow}') + if scheduler.auto_restart_time: + LOG.info('Scheduled automatic restart canceled') + scheduler.auto_restart_time = time() + scheduler.auto_restart_mode = mode + return True + + # Check workflow isn't already scheduled to auto-stop. + if scheduler.auto_restart_time is not None: + return True + + # Workflow host is condemned and workflow running in no detach mode. + # Raise an error to cause the workflow to abort. + # This should raise an "abort" event and return a non-zero code to the + # caller still attached to the workflow process. + if scheduler.options.no_detach: + raise SchedulerError('Workflow host condemned in no detach mode') + + # Check workflow is able to be safely restarted. + if not _can_auto_restart(): + return False + + LOG.info('Workflow will automatically restart on a new host.') + if restart_delay is not None and restart_delay != 0: + if restart_delay > 0: + # Delay shutdown by a random interval to avoid many + # workflows restarting simultaneously. + shutdown_delay = int(random() * restart_delay) # nosec + else: + # Un-documented feature, schedule exact restart interval for + # testing purposes. + shutdown_delay = abs(int(restart_delay)) + shutdown_time = time() + shutdown_delay + LOG.info('Workflow will restart in %ss (at %s)', shutdown_delay, + time2str(shutdown_time)) + scheduler.auto_restart_time = shutdown_time + else: + scheduler.auto_restart_time = time() + + scheduler.auto_restart_mode = AutoRestartMode.RESTART_NORMAL + + return True +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/main_loop/health_check.html b/nightly_8.4/html/_modules/cylc/flow/main_loop/health_check.html new file mode 100644 index 00000000000..4f6e44484bd --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/main_loop/health_check.html @@ -0,0 +1,214 @@ + + + + + + cylc.flow.main_loop.health_check — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.main_loop.health_check

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""Checks the integrity of the workflow run directory.
+
+* Ensures workflow run directory is still present.
+* Ensures contact file is present and consistent with the running workflow.
+
+Shuts down the workflow in the event of inconsistency or error.
+
+"""
+import os
+
+from cylc.flow import workflow_files
+from cylc.flow.exceptions import CylcError, ServiceFileError
+from cylc.flow.main_loop import periodic
+
+
+
+[docs] +@periodic +async def health_check(scheduler, _): + """Perform workflow health checks.""" + # 1. check if workflow run dir still present - if not shutdown. + _check_workflow_run_dir(scheduler) + # 2. check if contact file consistent with current start - if not + # shutdown. + _check_contact_file(scheduler)
+ + + +def _check_workflow_run_dir(scheduler): + if not os.path.exists(scheduler.workflow_run_dir): + raise CylcError( + 'Workflow run directory does not exist:' + f' {scheduler.workflow_run_dir}' + ) + + +def _check_contact_file(scheduler): + try: + contact_data = workflow_files.load_contact_file( + scheduler.workflow) + if contact_data != scheduler.contact_data: + raise CylcError('contact file modified') + except (AssertionError, IOError, ValueError, ServiceFileError) as exc: + raise CylcError( + '%s: contact file corrupted/modified and may be left' + % workflow_files.get_contact_file_path(scheduler.workflow) + ) from exc +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/main_loop/log_data_store.html b/nightly_8.4/html/_modules/cylc/flow/main_loop/log_data_store.html new file mode 100644 index 00000000000..e07949a1cad --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/main_loop/log_data_store.html @@ -0,0 +1,292 @@ + + + + + + cylc.flow.main_loop.log_data_store — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.main_loop.log_data_store

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""Log the number and size of each type of object in the data store.
+
+.. note::
+
+   This plugin is for Cylc developers debugging the data store.
+
+If ``matplotlib`` is installed this plugin will plot results as a PDF in
+the run directory when the workflow is shut down (cleanly).
+
+"""
+import json
+from pathlib import Path
+from time import time
+
+from cylc.flow.main_loop import (startup, shutdown, periodic)
+
+
+try:
+    import matplotlib
+    matplotlib.use('Agg')
+    from matplotlib import pyplot as plt
+    PLT = True
+except ModuleNotFoundError:
+    PLT = False
+
+from pympler.asizeof import asized
+
+
+
+[docs] +@startup +async def init(scheduler, state): + """Construct the initial state.""" + state['objects'] = {} + state['size'] = {} + state['times'] = [] + for key, _ in _iter_data_store(scheduler.data_store_mgr.data): + state['objects'][key] = [] + state['size'][key] = []
+ + + +
+[docs] +@periodic +async def log_data_store(scheduler, state): + """Count the number of objects and the data store size.""" + state['times'].append(time()) + for key, value in _iter_data_store(scheduler.data_store_mgr.data): + state['objects'][key].append( + len(value) + ) + state['size'][key].append( + asized(value).size + )
+ + + +
+[docs] +@shutdown +async def report(scheduler, state): + """Dump data to JSON, attempt to plot results.""" + _dump(state, scheduler.workflow_run_dir) + _plot(state, scheduler.workflow_run_dir)
+ + + +def _iter_data_store(data_store): + for item in data_store.values(): + for key, value in item.items(): + if key != 'workflow': + yield (key, value) + # there should only be one workflow in the data store + break + + +def _dump(state, path): + data = { + 'times': state['times'], + 'objects': state['objects'], + 'size': state['size'] + } + json.dump( + data, + Path(path, f'{__name__}.json').open('w+') + ) + return True + + +def _plot(state, path): + if ( + not PLT + or len(state['times']) < 2 + ): + return False + + times = [tick - state['times'][0] for tick in state['times']] + _, ax1 = plt.subplots(figsize=(10, 7.5)) + + ax1.set_xlabel('Time (s)') + + ax1.set_ylabel('Objects') + for key, objects in state['objects'].items(): + ax1.plot(times, objects, label=key) + + ax2 = ax1.twinx() + ax2.set_ylabel('Size (kb)') + for sizes in state['size'].values(): + ax2.plot(times, [x / 1000 for x in sizes], linestyle=':') + + ax1.legend(loc=0) + ax2.legend( + (ax1.get_children()[0], ax2.get_children()[0]), + ('objects', 'size'), + loc=1 + ) + + # start the x-axis at zero + ax1.set_xlim(0, ax1.get_xlim()[1]) + + plt.savefig( + Path(path, f'{__name__}.pdf') + ) + return True +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/main_loop/log_main_loop.html b/nightly_8.4/html/_modules/cylc/flow/main_loop/log_main_loop.html new file mode 100644 index 00000000000..c744198b86c --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/main_loop/log_main_loop.html @@ -0,0 +1,267 @@ + + + + + + cylc.flow.main_loop.log_main_loop — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.main_loop.log_main_loop

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""Main loop plugin for monitoring main loop plugins.
+
+.. note::
+
+   This plugin is for Cylc developers debugging main loop operations.
+
+If ``matplotlib`` is installed this plugin will plot results as a PDF in
+the run directory when the workflow is shut down (cleanly).
+
+"""
+from collections import deque
+import json
+from pathlib import Path
+
+from cylc.flow.main_loop import startup, shutdown
+
+try:
+    import matplotlib
+    matplotlib.use('Agg')
+    from matplotlib import pyplot as plt
+    PLT = True
+except ModuleNotFoundError:
+    PLT = False
+
+
+
+[docs] +@startup +async def init(scheduler, _): + """Override default queue length of 1. + + This allows timings to accumulate, normally only the most recent is kept. + """ + plugins = scheduler.main_loop_plugins + for plugin in plugins['timings']: + plugins['timings'][plugin] = deque()
+ + + +
+[docs] +@shutdown +async def report(scheduler, _): + """Extract plugin function timings.""" + data = scheduler.main_loop_plugins['timings'] + if data: + data = _normalise(data) + _dump(data, scheduler.workflow_run_dir) + _plot(data, scheduler.workflow_run_dir)
+ + + +def _normalise(data): + earliest_time = min(( + start_time + for _, timings in data.items() + for start_time, duration in timings + )) + return { + plugin_name: [ + (start_time - earliest_time, duration) + for start_time, duration in timings + ] + for (plugin_name, _), timings in data.items() + } + + +def _dump(data, path): + json.dump( + data, + Path(path, f'{__name__}.json').open('w+'), + indent=4 + ) + return True + + +def _plot(data, path): + if not PLT: + return False + + _, ax1 = plt.subplots(figsize=(10, 7.5)) + ax1.set_xlabel('Workflow Run Time (s)') + ax1.set_ylabel('XTrigger Run Time (s)') + + for plugin_name, (timings) in data.items(): + x_data = [] + y_data = [] + for start_time, duration in timings: + x_data.append(start_time) + y_data.append(duration) + ax1.scatter(x_data, y_data, label=plugin_name) + + ax1.set_xlim(0, ax1.get_xlim()[1]) + ax1.set_ylim(0, ax1.get_ylim()[1]) + + ax1.legend() + plt.savefig( + Path(path, f'{__name__}.pdf') + ) + return True +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/main_loop/log_memory.html b/nightly_8.4/html/_modules/cylc/flow/main_loop/log_memory.html new file mode 100644 index 00000000000..ff2efcf7148 --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/main_loop/log_memory.html @@ -0,0 +1,342 @@ + + + + + + cylc.flow.main_loop.log_memory — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.main_loop.log_memory

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""Log the memory usage of a running scheduler over time.
+
+.. note::
+
+   This plugin is for Cylc developers debugging cylc memory usage.
+
+   For general interest memory measurement try
+   ``/usr/bin/time -v cylc play`` or ``cylc play --profile``.
+
+.. note::
+
+   Pympler associates memory with the first object which references it.
+
+   In Cylc we have some objects (e.g. the configuration) which are references
+   from multiple places.
+
+   This can result in a certain amount of "jitter" in the results where
+   pympler has swapper from associating memory with one object to another.
+
+   Watch out for matching increase/decrease in reported memory in
+   different objects.
+
+.. warning::
+
+   This plugin can slow down a workflow significantly due to the
+   complexity of memory calculations.
+
+   Set a sensible interval before running workflows.
+
+If ``matplotlib`` is installed this plugin will plot results as a PDF in
+the run directory when the workflow is shut down (cleanly).
+
+"""
+
+import json
+from pathlib import Path
+from time import time
+
+from cylc.flow.main_loop import (startup, shutdown, periodic)
+
+try:
+    import matplotlib
+    matplotlib.use('Agg')
+    from matplotlib import pyplot as plt
+    PLT = True
+except ModuleNotFoundError:
+    PLT = False
+
+from pympler.asizeof import asized
+
+
+# TODO: make this configurable in the global config
+MIN_SIZE = 10000
+
+
+
+[docs] +@startup +async def init(scheduler, state): + """Take an initial memory snapshot.""" + state['data'] = [] + await take_snapshot(scheduler, state)
+ + + +
+[docs] +@periodic +async def take_snapshot(scheduler, state): + """Take a memory snapshot""" + state['data'].append(( + time(), + _compute_sizes(scheduler, min_size=MIN_SIZE) + ))
+ + + +
+[docs] +@shutdown +async def report(scheduler, state): + """Take a final memory snapshot and dump the results.""" + await take_snapshot(scheduler, state) + _dump(state['data'], scheduler.workflow_run_dir) + fields, times = _transpose(state['data']) + _plot( + fields, + times, + scheduler.workflow_run_dir, + f'cylc.flow.scheduler.Scheduler attrs > {MIN_SIZE / 1000}kb' + )
+ + + +def _compute_sizes(obj, min_size=10000): + """Return the sizes of the attributes of an object.""" + size = asized(obj, detail=2) + for ref in size.refs: + if ref.name == '__dict__': + break + else: + raise Exception('Cannot find __dict__ reference') + + return { + **{ + item.name.split(':')[0][4:]: item.size + for item in ref.refs + if item.size > min_size + }, + **{'total': size.size}, + } + + +def _transpose(data): + """Pivot data from snapshot to series oriented.""" + all_keys = set() + for _, datum in data: + all_keys.update(datum.keys()) + + # sort keys by the size of the last checkpoint so that the fields + # get plotted from largest to smallest + all_keys = list(all_keys) + all_keys.sort(key=lambda x: data[-1][1].get(x, 0), reverse=True) + + # extract data for each field, if not present + fields = {} + for key in all_keys: + fields[key] = [ + datum.get(key, -1) + for _, datum in data + ] + + start_time = data[0][0] + times = [ + timestamp - start_time + for timestamp, _ in data + ] + + return fields, times + + +def _dump(data, path): + json.dump( + data, + Path(path, f'{__name__}.json').open('w+') + ) + return True + + +def _plot(fields, times, path, title='Objects'): + if ( + not PLT + or len(times) < 2 + ): + return False + + fig, ax1 = plt.subplots(figsize=(10, 7.5)) + + fig.suptitle(title) + ax1.set_xlabel('Time (s)') + ax1.set_ylabel('Memory (kb)') + + for key, sizes in fields.items(): + ax1.plot(times, [x / 1000 for x in sizes], label=key) + + ax1.legend(loc=0) + + # start both axis at 0 + ax1.set_xlim(0, ax1.get_xlim()[1]) + ax1.set_ylim(0, ax1.get_ylim()[1]) + + plt.savefig( + Path(path, f'{__name__}.pdf') + ) + return True +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/main_loop/reset_bad_hosts.html b/nightly_8.4/html/_modules/cylc/flow/main_loop/reset_bad_hosts.html new file mode 100644 index 00000000000..ecb416a1d24 --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/main_loop/reset_bad_hosts.html @@ -0,0 +1,193 @@ + + + + + + cylc.flow.main_loop.reset_bad_hosts — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.main_loop.reset_bad_hosts

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""Resets the list of bad hosts.
+
+The scheduler stores a set of hosts which it has been unable to contact to
+save contacting these hosts again.
+
+This list is cleared if a task cannot be submitted because all of the hosts it
+might use cannot be reached.
+
+If a task succeeds in submitting a job on the second host it tries, then the
+first host remains in the set of unreachable (bad) hosts, even though the
+failure might have been transitory. For this reason, this plugin periodically
+clears the set.
+
+Suggested interval - an hour.
+"""
+
+from cylc.flow.main_loop import periodic
+
+
+
+[docs] +@periodic +async def reset_bad_hosts(scheduler, _): + """Empty bad_hosts.""" + scheduler.task_events_mgr.reset_bad_hosts()
+ +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/network/client.html b/nightly_8.4/html/_modules/cylc/flow/network/client.html new file mode 100644 index 00000000000..749345e3449 --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/network/client.html @@ -0,0 +1,521 @@ + + + + + + cylc.flow.network.client — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.network.client

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""Client for workflow runtime API."""
+
+from abc import ABCMeta, abstractmethod
+import asyncio
+import os
+from shutil import which
+import socket
+import sys
+from typing import Any, Optional, Union, Dict
+
+import zmq
+import zmq.asyncio
+
+from cylc.flow import LOG
+from cylc.flow.exceptions import (
+    ClientError,
+    ClientTimeout,
+    ContactFileExists,
+    CylcError,
+    WorkflowStopped,
+)
+from cylc.flow.hostuserutil import get_fqdn_by_host
+from cylc.flow.network import (
+    encode_,
+    decode_,
+    get_location,
+    ZMQSocketBase
+)
+from cylc.flow.network.client_factory import CommsMeth
+from cylc.flow.network.server import PB_METHOD_MAP
+from cylc.flow.workflow_files import (
+    detect_old_contact_file,
+)
+
+
+class WorkflowRuntimeClientBase(metaclass=ABCMeta):
+    """Base class for WorkflowRuntimeClients.
+
+    WorkflowRuntimeClients that inherit from this must implement an async
+    method ``async_request()``. This base class provides a ``serial_request()``
+    method based on the ``async_request()`` method, callable by ``__call__``.
+    It also provides a comms timeout handler method.
+    """
+
+    DEFAULT_TIMEOUT = 5  # seconds
+
+    def __init__(
+        self,
+        workflow: str,
+        host: Optional[str] = None,
+        port: Union[int, str, None] = None,
+        timeout: Union[float, str, None] = None
+    ):
+        self.workflow = workflow
+        if not host or not port:
+            host, port, _ = get_location(workflow)
+        else:
+            port = int(port)
+        self.host = self._orig_host = host
+        self.port = self._orig_port = port
+        self.timeout = (
+            float(timeout) if timeout is not None else self.DEFAULT_TIMEOUT
+        )
+
+    @abstractmethod
+    async def async_request(
+        self,
+        command: str,
+        args: Optional[Dict[str, Any]] = None,
+        timeout: Optional[float] = None,
+        req_meta: Optional[Dict[str, Any]] = None
+    ) -> object:
+        """Send an asynchronous request."""
+        ...
+
+    def serial_request(
+        self,
+        command: str,
+        args: Optional[Dict[str, Any]] = None,
+        timeout: Optional[float] = None,
+        req_meta: Optional[Dict[str, Any]] = None
+    ) -> object:
+        """Send a request.
+
+        For convenience use ``__call__`` to call this method.
+
+        Args:
+            command: The name of the endpoint to call.
+            args: Arguments to pass to the endpoint function.
+            timeout: Override the default timeout (seconds).
+
+        Raises:
+            ClientTimeout: If a response takes longer than timeout to arrive.
+            ClientError: Coverall for all other issues including failed auth.
+
+        Returns:
+            object: The data exactly as returned from the endpoint function,
+                nothing more, nothing less.
+
+        """
+        loop = getattr(self, 'loop', asyncio.new_event_loop())
+        task = loop.create_task(
+            self.async_request(command, args, timeout, req_meta)
+        )
+        loop.run_until_complete(task)
+        if not hasattr(self, 'loop'):
+            # (If inheriting class does have an event loop, don't mess with it)
+            loop.close()
+        return task.result()
+
+    __call__ = serial_request
+
+    def timeout_handler(self) -> None:
+        """Handle the eventuality of a communication timeout with the workflow.
+
+        Raises:
+            WorkflowStopped: if the workflow has already stopped.
+            CyclError: if the workflow has moved to different host/port.
+        """
+        contact_host, contact_port, _ = get_location(self.workflow)
+        if (
+            contact_host != get_fqdn_by_host(self._orig_host)
+            or contact_port != self._orig_port
+        ):
+            raise CylcError(
+                'The workflow is no longer running at '
+                f'{self._orig_host}:{self._orig_port}\n'
+                f'It has moved to {contact_host}:{contact_port}'
+            )
+
+        if os.getenv('CYLC_TASK_COMMS_METHOD'):
+            # don't attempt to clean up old contact files in task messages
+            return
+
+        # Cannot connect, perhaps workflow is no longer running and is leaving
+        # behind a contact file?
+        try:
+            detect_old_contact_file(self.workflow)
+        except ContactFileExists:
+            # old contact file exists and the workflow process still alive
+            return
+        else:
+            # the workflow has stopped
+            raise WorkflowStopped(self.workflow)
+
+
+
+[docs] +class WorkflowRuntimeClient( # type: ignore[misc] + ZMQSocketBase, WorkflowRuntimeClientBase +): + # (Ignoring mypy 'definition of "host" in base class "ZMQSocketBase" is + # incompatible with definition in base class "WorkflowRuntimeClientBase"') + """Initiate a client to the scheduler API. + + Initiates the REQ part of a ZMQ REQ-REP pair. + + This class contains the logic for the ZMQ message interface and client - + server communication. + + Determine host and port from the contact file unless provided. + + If there is no socket bound to the specified host/port the client will + bail after ``timeout`` seconds. + + Args: + workflow: + Name of the workflow to connect to. + timeout: + Set the default timeout in seconds. The default is + ``ZMQClient.DEFAULT_TIMEOUT``. + Note the default timeout can be overridden for individual requests. + host: + The host where the flow is running if known. + + If both host and port are provided it is not necessary to load + the contact file. + port: + The port on which the REQ-REP TCP server is listening. + + If both host and port are provided it is not necessary to load + the contact file. + + Attributes: + host: + Workflow host name. + port: + Workflow host port. + timeout_handler: + Optional function which runs before ClientTimeout is raised. + This provides an interface for raising more specific exceptions in + the event of a communication timeout. + header: + Request "header" data to attach to each request. + + Usage: + Call endpoints using ``ZMQClient.__call__``. + + Message interface: + * Accepts responses of the format: {"data": {...}} + * Accepts error in the format: {"error": {"message": MSG}} + * Returns requests of the format: {"command": CMD, + "args": {...}} + + Raises: + WorkflowStopped: if the workflow is not running. + + Call server "endpoints" using: + ``__call__``, ``serial_request`` + .. automethod:: + cylc.flow.network.client.WorkflowRuntimeClient.serial_request + + ``async_request`` + .. automethod:: + cylc.flow.network.client.WorkflowRuntimeClient.async_request + + """ + # socket & event loop not None - get assigned on init by self.start(): + socket: zmq.asyncio.Socket + loop: asyncio.AbstractEventLoop + + def __init__( + self, + workflow: str, + host: Optional[str] = None, + port: Union[int, str, None] = None, + timeout: Union[float, str, None] = None, + context: Optional[zmq.asyncio.Context] = None, + srv_public_key_loc: Optional[str] = None + ): + ZMQSocketBase.__init__(self, zmq.REQ, workflow, context=context) + WorkflowRuntimeClientBase.__init__(self, workflow, host, port, timeout) + # convert to milliseconds: + self.timeout *= 1000 + self.poller: Any = None + # Connect the ZMQ socket on instantiation + self.start(self.host, self.port, srv_public_key_loc) + # gather header info post start + self.header = self.get_header() + + def _socket_options(self): + """Set socket options after socket instantiation before connect. + + Overwrites Base method. + + """ + # if there is no server don't keep the client hanging around + self.socket.setsockopt(zmq.LINGER, int(self.DEFAULT_TIMEOUT)) + + # create a poller to handle timeouts + self.poller = zmq.Poller() + self.poller.register(self.socket, zmq.POLLIN) + +
+[docs] + async def async_request( + self, + command: str, + args: Optional[Dict[str, Any]] = None, + timeout: Optional[float] = None, + req_meta: Optional[Dict[str, Any]] = None + ) -> object: + """Send an asynchronous request using asyncio. + + Has the same arguments and return values as ``serial_request``. + + """ + timeout = (float(timeout) * 1000 if timeout else None) or self.timeout + if not args: + args = {} + + # Note: we are using CurveZMQ to secure the messages (see + # self.curve_auth, self.socket.curve_...key etc.). We have set up + # public-key cryptography on the ZMQ messaging and sockets, so + # there is no need to encrypt messages ourselves before sending. + + # send message + msg: Dict[str, Any] = {'command': command, 'args': args} + msg.update(self.header) + # add the request metadata + if req_meta: + msg['meta'].update(req_meta) + LOG.debug('zmq:send %s', msg) + message = encode_(msg) + self.socket.send_string(message) + + # receive response + if self.poller.poll(timeout): + res = await self.socket.recv() + else: + self.timeout_handler() + raise ClientTimeout( + 'Timeout waiting for server response.' + ' This could be due to network or server issues.' + '\n* You might want to increase the timeout using the' + ' --comms-timeout option;' + '\n* or check the workflow log.' + ) + + if msg['command'] in PB_METHOD_MAP: + response = {'data': res} + else: + response = decode_( + res.decode() if isinstance(res, bytes) else res + ) + LOG.debug('zmq:recv %s', response) + + try: + return response['data'] + except KeyError: + error = response.get( + 'error', + {'message': f'Received invalid response: {response}'}, + ) + raise ClientError( + error.get('message'), # type: ignore + error.get('traceback'), # type: ignore + ) from None
+ + + def get_header(self) -> dict: + """Return "header" data to attach to each request for traceability. + + Returns: + dict: dictionary with the header information, such as + program and hostname. + """ + host = socket.gethostname() + if len(sys.argv) > 1: + cmd = sys.argv[1] + else: + cmd = sys.argv[0] + + cylc_executable_location = which("cylc") + if cylc_executable_location: + cylc_bin_dir = os.path.abspath( + os.path.join(cylc_executable_location, os.pardir) + ) + if not cylc_bin_dir.endswith("/"): + cylc_bin_dir = f"{cylc_bin_dir}/" + + if cmd.startswith(cylc_bin_dir): + cmd = cmd.replace(cylc_bin_dir, '') + return { + 'meta': { + 'prog': cmd, + 'host': host, + 'comms_method': + os.getenv( + "CLIENT_COMMS_METH", + default=CommsMeth.ZMQ.value + ) + } + }
+ +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/network/server.html b/nightly_8.4/html/_modules/cylc/flow/network/server.html new file mode 100644 index 00000000000..26f202af230 --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/network/server.html @@ -0,0 +1,615 @@ + + + + + + cylc.flow.network.server — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.network.server

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""Server for workflow runtime API."""
+
+import asyncio
+from queue import Queue
+from textwrap import dedent
+from time import sleep
+from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Union
+
+from graphql.execution.executors.asyncio import AsyncioExecutor
+import zmq
+from zmq.auth.thread import ThreadAuthenticator
+
+from cylc.flow import LOG, workflow_files
+from cylc.flow.cfgspec.glbl_cfg import glbl_cfg
+from cylc.flow.network.authorisation import authorise
+from cylc.flow.network.graphql import (
+    CylcGraphQLBackend, IgnoreFieldMiddleware, instantiate_middleware
+)
+from cylc.flow.network.publisher import WorkflowPublisher
+from cylc.flow.network.replier import WorkflowReplier
+from cylc.flow.network.resolvers import Resolvers
+from cylc.flow.network.schema import schema
+from cylc.flow.data_store_mgr import DELTAS_MAP
+from cylc.flow.data_messages_pb2 import PbEntireWorkflow
+
+if TYPE_CHECKING:
+    from cylc.flow.scheduler import Scheduler
+    from graphql.execution import ExecutionResult
+
+
+# maps server methods to the protobuf message (for client/UIS import)
+PB_METHOD_MAP: Dict[str, Any] = {
+    'pb_entire_workflow': PbEntireWorkflow,
+    'pb_data_elements': DELTAS_MAP
+}
+
+
+def expose(func=None):
+    """Expose a method on the sever."""
+    func.exposed = True
+    return func
+
+
+def filter_none(dictionary):
+    """Filter out `None` items from a dictionary:
+
+    Examples:
+        >>> filter_none({
+        ...     'a': 0,
+        ...     'b': '',
+        ...     'c': None
+        ... })
+        {'a': 0, 'b': ''}
+
+    """
+    return {
+        key: value
+        for key, value in dictionary.items()
+        if value is not None
+    }
+
+
+
+[docs] +class WorkflowRuntimeServer: + """Workflow runtime service API facade exposed via zmq. + + This class starts and coordinates the publisher and replier, and + contains the Cylc endpoints invoked by the receiver to provide a response + to incoming messages. + + Args: + schd (object): The parent object instantiating the server. In + this case, the workflow scheduler. + + Usage: + * Define endpoints using the ``expose`` decorator. + * Endpoints are called via the receiver using the function name. + + Message interface: + * Accepts messages of the format: {"command": CMD, "args": {...}} + * Returns responses of the format: {"data": {...}} + * Returns error in the format: {"error": {"message": MSG}} + + Common Arguments: + Arguments which are shared between multiple commands. + + task identifier (str): + A task identifier in the format ``cycle-point/task-name`` + e.g. ``1/foo`` or ``20000101T0000Z/bar``. + + .. _task globs: + + task globs (list): + A list of Cylc IDs relative to the workflow. + + * ``1`` - The cycle point "1". + * ``1/foo`` - The task "foo" in the cycle "1". + * ``1/foo/01`` - The first job of the task "foo" from the cycle + "1". + + Glob-like patterns may be used to match multiple items e.g. + + ``*`` + Matches everything. + ``1/*`` + Matches everything in cycle ``1``. + ``*/*:failed`` + Matches all failed tasks. + + """ + endpoints: Dict[str, object] + + OPERATE_SLEEP_INTERVAL = 0.2 + STOP_SLEEP_INTERVAL = 0.2 + + def __init__(self, schd): + + self.zmq_context = None + self.port = None + self.pub_port = None + self.replier = None + self.publisher = None + self.loop = None + self.thread = None + self.curve_auth = None + self.client_pub_key_dir = None + + self.schd: 'Scheduler' = schd + self.resolvers = Resolvers( + self.schd.data_store_mgr, + schd=self.schd + ) + self.middleware = [ + IgnoreFieldMiddleware, + ] + + self.publish_queue: 'Queue[Iterable[tuple]]' = Queue() + self.waiting_to_stop = False + self.stopped = True + + self.register_endpoints() + +
+[docs] + def start(self, barrier): + """Start the TCP servers.""" + # set asyncio loop on thread + try: + self.loop = asyncio.get_running_loop() + except RuntimeError: + self.loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.loop) + + # TODO: this in zmq asyncio context? + # Requires the scheduler main loop in asyncio first + # And use of concurrent.futures.ThreadPoolExecutor? + self.zmq_context = zmq.Context() + # create an authenticator for the ZMQ context + self.curve_auth = ThreadAuthenticator(self.zmq_context, log=LOG) + self.curve_auth.start() # start the authentication thread + + # Setting the location means that the CurveZMQ auth will only + # accept public client certificates from the given directory, as + # generated by a user when they initiate a ZMQ socket ready to + # connect to a server. + workflow_srv_dir = workflow_files.get_workflow_srv_dir( + self.schd.workflow) + client_pub_keyinfo = workflow_files.KeyInfo( + workflow_files.KeyType.PUBLIC, + workflow_files.KeyOwner.CLIENT, + workflow_srv_dir=workflow_srv_dir) + self.client_pub_key_dir = client_pub_keyinfo.key_path + + # Initial load for the localhost key. + self.curve_auth.configure_curve( + domain='*', + location=(self.client_pub_key_dir) + ) + + min_, max_ = glbl_cfg().get(['scheduler', 'run hosts', 'ports']) + self.replier = WorkflowReplier(self, context=self.zmq_context) + self.replier.start(min_, max_) + self.publisher = WorkflowPublisher( + self.schd.workflow, context=self.zmq_context + ) + self.publisher.start(min_, max_) + self.port = self.replier.port + self.pub_port = self.publisher.port + self.schd.data_store_mgr.delta_workflow_ports() + + # wait for threads to setup socket ports before continuing + barrier.wait() + + self.stopped = False + + self.operate()
+ + +
+[docs] + async def stop(self, reason: Union[BaseException, str]) -> None: + """Stop the TCP servers, and clean up authentication. + + This method must be called/awaited from a different thread to the + server's self.thread in order to interrupt the self.operate() loop + and wait for self.thread to terminate. + """ + self.waiting_to_stop = True + if self.thread and self.thread.is_alive(): + # Wait for self.operate() loop to finish: + while self.waiting_to_stop: + # Non-async sleep - yield to other threads rather than + # event loop (allows self.operate() running in different + # thread to return) + sleep(self.STOP_SLEEP_INTERVAL) + + if self.replier: + self.replier.stop(stop_loop=False) + if self.publisher: + await self.publish_queued_items() + await self.publisher.publish( + (b'shutdown', str(reason).encode('utf-8')) + ) + self.publisher.stop(stop_loop=False) + self.publisher = None + if self.curve_auth: + self.curve_auth.stop() # stop the authentication thread + if self.loop and self.loop.is_running(): + self.loop.stop() + if self.thread and self.thread.is_alive(): + self.thread.join() # Wait for processes to return + + self.stopped = True
+ + +
+[docs] + def operate(self) -> None: + """Orchestrate the receive, send, publish of messages.""" + # Note: this cannot be an async method because the response part + # of the listener runs the event loop synchronously + # (in graphql AsyncioExecutor) + while True: + if self.waiting_to_stop: + # The self.stop() method is waiting for us to signal that we + # have finished here + self.waiting_to_stop = False + return + + # Gather and respond to any requests. + self.replier.listener() + # Publish all requested/queued. + self.loop.run_until_complete(self.publish_queued_items()) + + # Yield control to other threads + sleep(self.OPERATE_SLEEP_INTERVAL)
+ + +
+[docs] + async def publish_queued_items(self) -> None: + """Publish all queued items.""" + while self.publish_queue.qsize(): + articles = self.publish_queue.get() + await self.publisher.publish(*articles)
+ + +
+[docs] + def receiver(self, message): + """Process incoming messages and coordinate response. + + Wrap incoming messages, dispatch them to exposed methods and/or + coordinate a publishing stream. + + Args: + message (dict): message contents + """ + # TODO: If requested, coordinate publishing response/stream. + + # determine the server method to call + try: + method = getattr(self, message['command']) + args = message['args'] + args.update({'user': message['user']}) + if 'meta' in message: + args['meta'] = message['meta'] + except KeyError: + # malformed message + return {'error': { + 'message': 'Request missing required field(s).'}} + except AttributeError: + # no exposed method by that name + return {'error': { + 'message': 'No method by the name "%s"' % message['command']}} + + # generate response + try: + response = method(**args) + except Exception as exc: + # includes incorrect arguments (TypeError) + LOG.exception(exc) # note the error server side + import traceback + return {'error': { + 'message': str(exc), 'traceback': traceback.format_exc()}} + + return {'data': response}
+ + +
+[docs] + def register_endpoints(self): + """Register all exposed methods.""" + self.endpoints = {name: obj + for name, obj in self.__class__.__dict__.items() + if hasattr(obj, 'exposed')}
+ + +
+[docs] + @authorise() + @expose + def api( + self, + endpoint: Optional[str] = None, + **_kwargs + ) -> Union[str, List[str]]: + """Return information about this API. + + Returns a list of callable endpoints. + + Args: + endpoint: + If specified the documentation for the endpoint + will be returned instead. + + Returns: + List of endpoints or string documentation of the + requested endpoint. + + """ + if not endpoint: + return [ + method for method in dir(self) + if getattr(getattr(self, method), 'exposed', False) + ] + + try: + method = getattr(self, endpoint) + except AttributeError: + return 'No method by name "%s"' % endpoint + if method.exposed: + head, tail = method.__doc__.split('\n', 1) + tail = dedent(tail) + return '%s\n%s' % (head, tail) + return 'No method by name "%s"' % endpoint
+ + +
+[docs] + @authorise() + @expose + def graphql( + self, + request_string: Optional[str] = None, + variables: Optional[Dict[str, Any]] = None, + meta: Optional[Dict[str, Any]] = None + ): + """Return the GraphQL schema execution result. + + Args: + request_string: GraphQL request passed to Graphene. + variables: Dict of variables passed to Graphene. + meta: Dict containing auth user etc. + + Returns: + object: Execution result, or a list with errors. + """ + try: + executed: 'ExecutionResult' = schema.execute( + request_string, + variable_values=variables, + context_value={ + 'resolvers': self.resolvers, + 'meta': meta or {}, + }, + backend=CylcGraphQLBackend(), + middleware=list(instantiate_middleware(self.middleware)), + executor=AsyncioExecutor(), + validate=True, # validate schema (dev only? default is True) + return_promise=False, + ) + except Exception as exc: + return 'ERROR: GraphQL execution error \n%s' % exc + if executed.errors: + errors: List[Any] = [] + for error in executed.errors: + LOG.error(error) + if hasattr(error, '__traceback__'): + import traceback + formatted_tb = traceback.format_exception( + type(error), error, error.__traceback__ + ) + LOG.error("".join(formatted_tb)) + errors.append({ + 'error': { + 'message': str(error), + 'traceback': formatted_tb + } + }) + continue + errors.append(getattr(error, 'message', None)) + return errors + return executed.data
+ + + # UIServer Data Commands +
+[docs] + @authorise() + @expose + def pb_entire_workflow(self, **_kwargs) -> bytes: + """Send the entire data-store in a single Protobuf message. + + Returns serialised Protobuf message + + """ + pb_msg = self.schd.data_store_mgr.get_entire_workflow() + return pb_msg.SerializeToString()
+ + +
+[docs] + @authorise() + @expose + def pb_data_elements(self, element_type: str, **_kwargs) -> bytes: + """Send the specified data elements in delta form. + + Args: + element_type: Key from DELTAS_MAP dictionary. + + Returns serialised Protobuf message + + """ + pb_msg = self.schd.data_store_mgr.get_data_elements(element_type) + return pb_msg.SerializeToString()
+
+ +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/parsec/exceptions.html b/nightly_8.4/html/_modules/cylc/flow/parsec/exceptions.html new file mode 100644 index 00000000000..b623cfb4bf6 --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/parsec/exceptions.html @@ -0,0 +1,461 @@ + + + + + + cylc.flow.parsec.exceptions — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.parsec.exceptions

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from copy import copy
+import os
+import textwrap
+import typing as t
+
+from cylc.flow.parsec.util import itemstr
+
+
+TRACEBACK_WRAPPER = textwrap.TextWrapper()
+
+
+
+[docs] +class ParsecError(Exception): + """Generic exception for Parsec errors.""" + + schd_expected: bool = False + """Set this flag to True on the exception if it is anticipated during + Cylc Scheduler run (apart from loading of config we do not expect + ParsecErrors during runtime)."""
+ + + +
+[docs] +class ItemNotFoundError(ParsecError, KeyError): + """Error raised for missing configuration items.""" + + def __init__(self, item): + self.item = item + + def __str__(self): + return f'You have not set \"{self.item}\" in this config.'
+ + + +
+[docs] +class InvalidConfigError(ParsecError, KeyError): + """Error raised for missing configuration items.""" + + def __init__(self, item, specname): + self.item = item + self.specname = specname + + def __str__(self): + return ( + f'"{self.item}" is not a valid ' + f'configuration for {self.specname}.' + )
+ + + +
+[docs] +class NotSingleItemError(ParsecError, TypeError): + """Error raised if an iterable is given where an item is expected.""" + + def __init__(self, item): + self.item = item + + def __str__(self): + return f'not a singular item: {self.item}'
+ + + +
+[docs] +class FileParseError(ParsecError): + """Error raised when attempting to read in the config file(s). + + Args: + reason: + Description of error. + err_type: + Classification of error (e.g. Jinja2Error). + help_lines: + Additional info to include in the exception. + lines: + (preferred) Dictionary in the format + {filename: [context_line, ..., error_line]} + index: + The line number of the error in the config (counting from the + shebang line *not* the first line). + line: + The line of the error in the config. + fpath: + The path to the file containing the error. + + """ + + def __init__( + self, + reason: str, + index: t.Optional[int] = None, + line: t.Optional[str] = None, + lines: t.Optional[t.Dict[str, t.List[str]]] = None, + err_type: t.Optional[str] = None, + fpath: t.Optional[str] = None, + help_lines: t.Optional[t.Iterable[str]] = None, + ): + self.reason = reason + self.line_num = index + 1 if index is not None else None + self.line = line + self.lines = lines + self.err_type = err_type + self.fpath = fpath + self.help_lines = help_lines or [] + + def __str__(self) -> str: + msg = '' + msg += self.reason + + if self.line_num is not None or self.fpath: + temp = [] + if self.fpath: + temp.append(f'in {self.fpath}') + if self.line_num is not None: + temp.append(f'line {self.line_num}') + msg += f' ({" ".join(temp)})' + if self.line: + msg += ":\n " + self.line.strip() + if self.lines: + for filename, lines in self.lines.items(): + msg += f'\nFile {filename}\n ' + '\n '.join(lines) + msg += "\t<--" + if self.err_type: + msg += ' %s' % self.err_type + help_lines = list(self.help_lines) + if self.line_num: + # TODO - make 'view' function independent of cylc: + help_lines.append("line numbers match 'cylc view -p'") + for help_line in help_lines: + msg += f'\n({help_line})' + return msg
+ + + +
+[docs] +class TemplateVarLanguageClash(FileParseError): + """Multiple workflow configuration templating engines configured."""
+ + + +
+[docs] +class EmPyError(FileParseError): + """Wrapper class for EmPy exceptions."""
+ + + +
+[docs] +class Jinja2Error(FileParseError): + """Wrapper class for Jinja2 exceptions. + + Args: + exception: + The exception being re-raised + lines: + Dictionary in the format + {filename: [context_line, ..., error_line]} + filename: + Alternative to "lines" where less detail is available. + + """ + + def __init__( + self, + exception: Exception, + lines: t.Optional[t.Dict[str, t.List[str]]] = None, + filename: t.Optional[str] = None, + ): + # extract the first sentence of exception + msg: str = str(exception) + try: + msg, tail = msg.split('. ', 1) + except ValueError: + tail = '' + else: + msg += '.' + tail = tail.strip() + + # append the filename e.g. for a Jinja2 template + if filename: + msg += f'\nError in file "{filename}"' + + # append the rest of the exception + if tail: + msg += '\n' + '\n'.join(TRACEBACK_WRAPPER.wrap(tail)) + + FileParseError.__init__( + self, + msg, + lines=lines, + err_type=exception.__class__.__name__ + )
+ + + +
+[docs] +class IncludeFileNotFoundError(ParsecError): + """Error raised for missing include files.""" + + def __init__(self, flist): + """Missing include file error. + + E.g. for [DIR/top.cylc, DIR/inc/sub.cylc, DIR/inc/gone.cylc] + "Include-file not found: inc/gone.cylc via inc/sub.cylc from + DIR/top.cylc" + """ + rflist = copy(flist) + top_file = rflist[0] + top_dir = os.path.dirname(top_file) + '/' + rflist.reverse() + msg = rflist[0].replace(top_dir, '') + for f in rflist[1:-1]: + msg += ' via %s' % f.replace(top_dir, '') + msg += ' from %s' % top_file + ParsecError.__init__(self, msg)
+ + + +
+[docs] +class UpgradeError(ParsecError): + """Error raised upon fault in an upgrade operation."""
+ + + +
+[docs] +class ValidationError(ParsecError): + """Generic exception for invalid configurations.""" + + def __init__(self, keys, value=None, msg=None, exc=None, vtype=None, + key=None): + self.keys = keys + self.value = value + self.msg = msg + self.exc = exc + self.vtype = vtype + self.key = key + + def __str__(self): + msg = '' + if self.vtype: + msg += f'(type={self.vtype}) ' + if self.key: + msg += itemstr(self.keys, self.key) + elif self.value: + msg += itemstr(self.keys[:-1], self.keys[-1], value=self.value) + if self.msg or self.exc: + msg += ( + f' - ({self.exc or ""}' + f'{": " if (self.exc and self.msg) else ""}' + f'{self.msg or ""})' + ) + return msg
+ + + +
+[docs] +class IllegalValueError(ValidationError): + """Bad setting value.""" + + def __init__(self, vtype, keys, value, exc=None, msg=None): + ValidationError.__init__( + self, keys, vtype=vtype, value=value, exc=exc, msg=msg)
+ + + +
+[docs] +class ListValueError(IllegalValueError): + """Bad setting value, for a comma separated list.""" + + def __init__(self, keys, value, msg=None, exc=None): + IllegalValueError.__init__( + self, 'list', keys, value, exc=exc, msg=msg)
+ + + +
+[docs] +class IllegalItemError(ValidationError): + """Bad setting section or option name.""" + + def __init__(self, keys, key, msg=None, exc=None): + ValidationError.__init__(self, keys, key=key, exc=exc, msg=msg)
+ +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/unicode_rules.html b/nightly_8.4/html/_modules/cylc/flow/unicode_rules.html new file mode 100644 index 00000000000..5bda6eb2d10 --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/unicode_rules.html @@ -0,0 +1,533 @@ + + + + + + cylc.flow.unicode_rules — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.unicode_rules

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""Module for unicode restrictions"""
+
+import re
+
+from cylc.flow.task_id import (
+    _TASK_NAME_CHARACTERS,
+    _TASK_NAME_PREFIX,
+)
+from cylc.flow.task_qualifiers import TASK_QUALIFIERS
+from cylc.flow.task_state import TASK_STATUSES_ORDERED
+
+ENGLISH_REGEX_MAP = {
+    r'\w': 'alphanumeric',
+    r'a-zA-Z0-9': 'latin letters and numbers',
+    r'\d': 'numbers',
+    r'\-': '``-``',
+    r'\.': '``.``',
+    r'\/': '``/``'
+}
+
+
+def regex_chars_to_text(chars):
+    r"""Return a string representing a regex component.
+
+    Examples:
+        >>> regex_chars_to_text(['a', 'b', 'c'])
+        ['``a``', '``b``', '``c``']
+        >>> regex_chars_to_text([r'\-', r'\.', r'\/'])
+        ['``-``', '``.``', '``/``']
+        >>> regex_chars_to_text([r'\w'])
+        ['alphanumeric']
+        >>> regex_chars_to_text(['not_in_map'])
+        ['``not_in_map``']
+
+    """
+    return [
+        ENGLISH_REGEX_MAP.get(char, f'``{char}``')
+        for char in chars
+    ]
+
+
+def length(minimum, maximum):
+    """Restrict character length.
+
+    Example:
+        >>> regex, message = length(0, 5)
+        >>> message
+        'must be between 0 and 5 characters long'
+        >>> bool(regex.match('abcde'))
+        True
+        >>> bool(regex.match('abcdef'))
+        False
+
+    """
+    return (
+        re.compile(r'^.{%d,%d}$' % (minimum, maximum)),
+        f'must be between {minimum} and {maximum} characters long'
+    )
+
+
+def allowed_characters(*chars):
+    """Restrict permitted characters.
+
+    Example:
+        >>> regex, message = allowed_characters('a', 'b', 'c')
+        >>> message
+        'can only contain: ``a``, ``b``, ``c``'
+        >>> bool(regex.match('abc'))
+        True
+        >>> bool(regex.match('def'))
+        False
+
+    """
+    return (
+        re.compile(r'^[%s]+$' % ''.join(chars)),
+        f'can only contain: {", ".join(regex_chars_to_text(chars))}'
+    )
+
+
+def disallowed_characters(*chars):
+    """Restrict permitted characters.
+
+    Example:
+        >>> regex, message = disallowed_characters('&', '~')
+        >>> message
+        'cannot contain: ``&``, ``~``'
+        >>> bool(regex.match('abc01'))
+        True
+        >>> bool(regex.match('abc&01'))
+        False
+
+    """
+    return (
+        re.compile(r'^[^%s]*$' % ''.join(chars)),
+        f'cannot contain: {", ".join(regex_chars_to_text(chars))}'
+    )
+
+
+def starts_with(*chars):
+    """Restrict first character.
+
+    Example:
+        >>> regex, message = starts_with('a', 'b', 'c')
+        >>> message
+        'must start with: ``a``, ``b``, ``c``'
+        >>> bool(regex.match('def'))
+        False
+        >>> bool(regex.match('adef'))
+        True
+
+    """
+    return (
+        re.compile(r'^[%s]' % ''.join(chars)),
+        f'must start with: {", ".join(regex_chars_to_text(chars))}'
+    )
+
+
+def not_starts_with_char(*chars):
+    """Restrict first character.
+
+    Example:
+        >>> regex, message = not_starts_with_char('a', 'b', 'c')
+        >>> message
+        'cannot start with: ``a``, ``b``, ``c``'
+        >>> bool(regex.match('def'))
+        True
+        >>> bool(regex.match('adef'))
+        False
+
+    """
+    return (
+        re.compile(r'^[^%s]' % ''.join(chars)),
+        f'cannot start with: {", ".join(regex_chars_to_text(chars))}'
+    )
+
+
+def not_starts_with(string):
+    """Restrict strings starting with ___.
+
+    Example:
+        Regular usage:
+        >>> regex, message = not_starts_with('foo')
+        >>> message
+        'cannot start with: ``foo``'
+        >>> bool(regex.match('tfoo'))
+        True
+        >>> bool(regex.match('foot'))
+        False
+
+        Note regex chars are escaped automatically:
+        >>> regex, message = not_starts_with('...')
+        >>> bool(regex.match('aaa b'))
+        True
+        >>> bool(regex.match('... b'))
+        False
+
+    """
+    return (
+        re.compile(rf'^(?!{re.escape(string)})'),
+        f'cannot start with: ``{string}``'
+    )
+
+
+def _human_format_list(lst):
+    """Write a list in plain text.
+
+    Examples:
+        >>> _human_format_list(['a'])
+        'a'
+        >>> _human_format_list(['a', 'b'])
+        'a or b'
+        >>> _human_format_list(['a', 'b', 'c'])
+        'a, b or c'
+
+    """
+    if len(lst) > 1:
+        return ', '.join(lst[:-1]) + f' or {lst[-1]}'
+    return lst[0]
+
+
+def _re_format_list(lst):
+    """Write a list in regex format.
+
+    Examples:
+        >>> _re_format_list('a')
+        '(a)'
+        >>> _re_format_list(['a', 'b'])
+        '(a|b)'
+        >>> _re_format_list(['a', 'b', 'c'])
+        '(a|b|c)'
+
+    """
+    return f"({'|'.join(map(re.escape, lst))})"
+
+
+def not_equals(*strings):
+    r"""Restrict entire string.
+
+    Example:
+        Regular usage:
+        >>> regex, message = not_equals('foo')
+        >>> message
+        'cannot be: ``foo``'
+        >>> bool(regex.match('foot'))  # "foot" shouldn't match
+        True
+        >>> bool(regex.match('a\nb'))  # newlines should be tolerated
+        True
+        >>> bool(regex.match('foo'))   # "foo" should match
+        False
+
+        Regular use (multi):
+        >>> regex, message = not_equals('foo', 'bar', 'baz')
+        >>> regex.pattern
+        '^(?!^(foo|bar|baz)$).*$'
+        >>> message
+        'cannot be: ``foo``, ``bar`` or ``baz``'
+
+        Note regex chars are escaped automatically:
+        >>> regex, message = not_equals('...')
+        >>> bool(regex.match('...'))
+        False
+        >>> bool(regex.match('aaa'))
+        True
+
+    """
+    return (
+        re.compile(rf'^(?!^{_re_format_list(strings)}$).*$', re.M),
+        'cannot be: ' + _human_format_list([f'``{s}``' for s in strings])
+    )
+
+
+def disallow_char_if_not_at_end_of_first_word(char):
+    """Prevent use of a (non-alphanumeric) character unless it occurs directly
+    after first word (in which case there is no limit on subsequent
+    occurances).
+
+    Example:
+        >>> regex, message = disallow_char_if_not_at_end_of_first_word(':')
+        >>> message
+        'cannot contain ``:`` unless it occurs at the end of the first word'
+        >>> bool(regex.match('Foo: bar'))
+        True
+        >>> bool(regex.match('INFO: Foo: bar'))
+        True
+        >>> bool(regex.match('Foo bar: baz'))
+        False
+        >>> bool(regex.match('Foo bar'))
+        True
+
+    """
+    return (
+        re.compile(fr'^(\w+{char}.*|[^{char}]+)$', flags=re.S),
+        f'cannot contain ``{char}`` unless it occurs at the end of the '
+        'first word'
+    )
+
+
+class UnicodeRuleChecker():
+
+    RULES: list = []
+
+    @classmethod
+    def __init_subclass__(cls):
+        cls.__doc__ = cls.__doc__ + '\n' if cls.__doc__ else ''
+        cls.__doc__ += '\n' + '\n'.join([
+            f'* {message}'
+            for regex, message in cls.RULES
+        ])
+
+    @classmethod
+    def validate(cls, string):
+        """Run this collection of rules against the given string.
+
+        Args:
+            string (str):
+                String to validate.
+
+        Returns:
+            tuple - (outcome, message)
+            outcome (bool) - True if all patterns match.
+            message (str) - User-friendly error message.
+
+        """
+        for rule, message in cls.RULES:
+            if not rule.match(string):
+                return (
+                    False,
+                    # convert RST style literals to Markdown for error messages
+                    # (RST used in docs)
+                    message.replace('``', '`'),
+                )
+        return (True, None)
+
+
+
+[docs] +class WorkflowNameValidator(UnicodeRuleChecker): + """The rules for valid workflow names:""" + + RULES = [ + length(1, 254), + not_starts_with_char(r'\.', r'\-', r'\d'), + allowed_characters(r'\w', r'\/', '_', '+', r'\-', r'\.', '@'), + ]
+ + + +
+[docs] +class XtriggerNameValidator(UnicodeRuleChecker): + """The rules for valid xtrigger labels:""" + + RULES = [ + allowed_characters(r'a-zA-Z0-9', '_'), + not_starts_with('_cylc'), + ]
+ + + +
+[docs] +class TaskMessageValidator(UnicodeRuleChecker): + """The rules for valid task messages:""" + + RULES = [ + # <severity>:<message> e.g. "WARN: something went wrong + disallow_char_if_not_at_end_of_first_word(':'), + # blacklist built-in qualifiers + # (technically we need only blacklist task messages, however, to avoid + # confusion it's best to blacklist qualifiers too) + not_equals(*TASK_QUALIFIERS), + not_starts_with('_cylc'), + ]
+ + + +
+[docs] +class TaskOutputValidator(UnicodeRuleChecker): + """The rules for valid task outputs/message triggers:""" + + RULES = [ + # restrict outputs to sensible characters + allowed_characters(r'\w', r'\d', r'\-'), + # blacklist the _cylc prefix + not_starts_with('_cylc'), + # blacklist keywords + not_equals('required', 'optional', 'all', 'and', 'or'), + # blacklist built-in task qualifiers and statuses (e.g. "waiting") + not_equals(*sorted({*TASK_QUALIFIERS, *TASK_STATUSES_ORDERED})), + ]
+ + + +
+[docs] +class TaskNameValidator(UnicodeRuleChecker): + """The rules for valid task and family names:""" + + RULES = [ + starts_with(_TASK_NAME_PREFIX), + allowed_characters(*_TASK_NAME_CHARACTERS), + not_starts_with('_cylc'), + not_equals('root'), + ]
+ +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/xtriggers/echo.html b/nightly_8.4/html/_modules/cylc/flow/xtriggers/echo.html new file mode 100644 index 00000000000..1b113bbce3e --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/xtriggers/echo.html @@ -0,0 +1,218 @@ + + + + + + cylc.flow.xtriggers.echo — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.xtriggers.echo

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""A Cylc xtrigger function."""
+
+from typing import Any, Dict, Tuple
+from cylc.flow.exceptions import WorkflowConfigError
+
+
+
+[docs] +def echo(*args, **kwargs) -> Tuple: + """Print arguments to stdout, return kwargs['succeed'] and kwargs. + + This may be a useful aid to understanding how xtriggers work. + + Args: + succeed: Set the success of failure of this xtrigger. + *args: Print to stdout. + **kwargs: Print to stdout, and return as output. + + Returns: + (True/False, kwargs) + + Examples: + + >>> echo('Breakfast Time', succeed=True, egg='poached') + echo: ARGS: ('Breakfast Time',) + echo: KWARGS: {'succeed': True, 'egg': 'poached'} + (True, {'succeed': True, 'egg': 'poached'}) + + """ + print("echo: ARGS:", args) + print("echo: KWARGS:", kwargs) + + return kwargs["succeed"], kwargs
+ + + +def validate(all_args: Dict[str, Any]): + """ + Validate the xtrigger function arguments parsed from the workflow config. + + This is separate from the xtrigger to allow parse-time validation. + + """ + # NOTE: with (*args, **kwargs) pattern, all_args looks like: + # { + # 'args': (arg1, arg2, ...), + # 'kwargs': {kwarg1: val, kwarg2: val, ...} + # } + succeed = all_args['kwargs'].get("succeed") + if not isinstance(succeed, bool): + raise WorkflowConfigError("Requires 'succeed=True/False' arg") +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/xtriggers/wall_clock.html b/nightly_8.4/html/_modules/cylc/flow/xtriggers/wall_clock.html new file mode 100644 index 00000000000..c860ee81e8a --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/xtriggers/wall_clock.html @@ -0,0 +1,234 @@ + + + + + + cylc.flow.xtriggers.wall_clock — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for cylc.flow.xtriggers.wall_clock

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""xtrigger function to trigger off of a wall clock time."""
+
+from time import time
+from typing import Any, Dict
+from cylc.flow.cycling.iso8601 import interval_parse
+from cylc.flow.exceptions import WorkflowConfigError
+
+
+
+[docs] +def wall_clock(offset: str = 'PT0S', sequential: bool = True): + """Trigger at a specific real "wall clock" time relative to the cycle point + in the graph. + + Clock triggers, unlike other trigger functions, are executed synchronously + in the main process. + + Args: + offset: + ISO 8601 interval to wait after the cycle point is reached in real + time before triggering. May be negative, in which case it will + trigger before the real time reaches the cycle point. + sequential: + Wall-clock xtriggers are run sequentially by default. + See :ref:`Sequential Xtriggers` for more details. + + .. versionchanged:: 8.3.0 + + The ``sequential`` argument was added. + """ + # NOTE: This is just a placeholder for the actual implementation. + # This is only used for validating the signature and for autodocs. + ...
+ + + +def _wall_clock(trigger_time: int) -> bool: + """Actual implementation of wall_clock. + + Return True after the desired wall clock time, or False before. + + Args: + trigger_time: + Trigger time as seconds since Unix epoch. + sequential (bool): + Used by the workflow to flag corresponding xtriggers as sequential. + """ + return time() > trigger_time + + +def validate(args: Dict[str, Any]): + """Validate and manipulate args parsed from the workflow config. + + NOTE: the xtrigger signature is different to the function signature above + + wall_clock() # infer zero interval + wall_clock(PT1H) + wall_clock(offset=PT1H) + + The offset must be a valid ISO 8601 interval. + """ + try: + interval_parse(args["offset"]) + except (ValueError, AttributeError): + raise WorkflowConfigError( + f"Invalid offset: {args['offset']}" + ) from None +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/xtriggers/workflow_state.html b/nightly_8.4/html/_modules/cylc/flow/xtriggers/workflow_state.html new file mode 100644 index 00000000000..ae7a88e3a9d --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/xtriggers/workflow_state.html @@ -0,0 +1,421 @@ + + + + + + cylc.flow.xtriggers.workflow_state — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for cylc.flow.xtriggers.workflow_state

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from typing import Dict, Optional, Tuple, Any
+import asyncio
+from inspect import signature
+
+from cylc.flow.scripts.workflow_state import WorkflowPoller
+from cylc.flow.id import tokenise
+from cylc.flow.exceptions import WorkflowConfigError, InputError
+from cylc.flow.task_state import TASK_STATUS_SUCCEEDED
+from cylc.flow.dbstatecheck import check_polling_config
+
+
+DEFAULT_STATUS = TASK_STATUS_SUCCEEDED
+
+
+
+[docs] +def workflow_state( + workflow_task_id: str, + offset: Optional[str] = None, + flow_num: Optional[int] = None, + is_trigger: bool = False, + is_message: bool = False, + alt_cylc_run_dir: Optional[str] = None, +) -> Tuple[bool, Dict[str, Any]]: + """Connect to a workflow DB and check a task status or output. + + If the status or output has been achieved, return {True, result}. + + Args: + workflow_task_id: + ID (workflow//point/task:selector) of the target task. + offset: + Offset from cycle point as an ISO8601 or integer duration, + e.g. PT1H (1 hour) or P1 (1 integer cycle) + flow_num: + Flow number of the target task. + is_message: + Interpret the task:selector as a task output message + (the default is a task status or trigger) + is_trigger: + Interpret the task:selector as a task trigger name + (only needed if it is also a valid status name) + alt_cylc_run_dir: + Alternate cylc-run directory, e.g. for another user. + + Returns: + tuple: (satisfied, result) + + satisfied: + True if ``satisfied`` else ``False``. + result: + Dict containing the keys: + + * ``workflow`` + * ``task`` + * ``point`` + * ``offset`` + * ``status`` + * ``message`` + * ``trigger`` + * ``flow_num`` + * ``run_dir`` + + .. versionchanged:: 8.3.0 + + The ``workflow_task_id`` argument was introduced to replace the + separate ``workflow``, ``point``, ``task``, ``status``, and ``message`` + arguments (which are still supported for backwards compatibility). + The ``flow_num`` argument was added. The ``cylc_run_dir`` argument + was renamed to ``alt_cylc_run_dir``. + """ + poller = WorkflowPoller( + workflow_task_id, + offset, + flow_num, + alt_cylc_run_dir, + DEFAULT_STATUS, + is_trigger, is_message, + old_format=False, + condition=workflow_task_id, + max_polls=1, # (for xtriggers the scheduler does the polling) + interval=0, # irrelevant for 1 poll + args=[] + ) + + # NOTE the results dict item names remain compatible with older usage. + + if asyncio.run(poller.poll()): + results = { + 'workflow': poller.workflow_id, + 'task': poller.task, + 'point': poller.cycle, + } + if poller.alt_cylc_run_dir is not None: + results['cylc_run_dir'] = poller.alt_cylc_run_dir + + if offset is not None: + results['offset'] = poller.offset + + if flow_num is not None: + results["flow_num"] = poller.flow_num + + if poller.is_message: + results['message'] = poller.selector + elif poller.is_trigger: + results['trigger'] = poller.selector + else: + results['status'] = poller.selector + + return (True, results) + else: + return (False, {})
+ + + +def validate(args: Dict[str, Any]): + """Validate workflow_state xtrigger function args. + + Arguments: + workflow_task_id: + full workflow//cycle/task[:selector] + offset: + must be a valid status + flow_num: + must be an integer + alt_cylc_run_dir: + must be a valid path + + """ + tokens = tokenise(args["workflow_task_id"]) + + if any( + tokens[token] is None + for token in ("workflow", "cycle", "task") + ): + raise WorkflowConfigError( + "Full ID needed: workflow//cycle/task[:selector].") + + if ( + args["flow_num"] is not None and + not isinstance(args["flow_num"], int) + ): + raise WorkflowConfigError("flow_num must be an integer if given.") + + try: + check_polling_config( + tokens['cycle_sel'] or tokens['task_sel'] or DEFAULT_STATUS, + args['is_trigger'], + args['is_message'], + ) + except InputError as exc: + raise WorkflowConfigError(str(exc)) from None + + +# BACK COMPAT: workflow_state_backcompat +# from: 8.0.0 +# to: 8.3.0 +# remove at: 8.x +def _workflow_state_backcompat( + workflow: str, + task: str, + point: str, + offset: Optional[str] = None, + status: str = 'succeeded', + message: Optional[str] = None, + cylc_run_dir: Optional[str] = None +) -> Tuple[bool, Optional[Dict[str, Optional[str]]]]: + """Back-compat wrapper for the workflow_state xtrigger. + + Note Cylc 7 DBs only stored custom task outputs, not standard ones. + + Arguments: + workflow: + The workflow to interrogate. + task: + The name of the task to query. + point: + The cycle point. + offset: + The offset between the cycle this xtrigger is used in and the one + it is querying for as an ISO8601 time duration. + e.g. PT1H (one hour). + status: + The task status required for this xtrigger to be satisfied. + message: + The custom task output required for this xtrigger to be satisfied. + + .. note:: + + This cannot be specified in conjunction with ``status``. + + cylc_run_dir: + Alternate cylc-run directory, e.g. for another user. + + Returns: + tuple: (satisfied, results) + + satisfied: + True if ``satisfied`` else ``False``. + results: + Dictionary containing the args / kwargs which were provided + to this xtrigger. + + """ + args = { + 'workflow': workflow, + 'task': task, + 'point': point, + 'offset': offset, + 'status': status, + 'message': message, + 'cylc_run_dir': cylc_run_dir + } + upg_args = _upgrade_workflow_state_sig(args) + satisfied, _results = workflow_state(**upg_args) + + return (satisfied, args) + + +# BACK COMPAT: workflow_state_backcompat +# from: 8.0.0 +# to: 8.3.0 +# remove at: 8.x +def _upgrade_workflow_state_sig(args: Dict[str, Any]) -> Dict[str, Any]: + """Return upgraded args for workflow_state, given the deprecated args.""" + is_message = False + workflow_task_id = f"{args['workflow']}//{args['point']}/{args['task']}" + status = args.get('status') + message = args.get('message') + if status is not None: + workflow_task_id += f":{status}" + elif message is not None: + is_message = True + workflow_task_id += f":{message}" + return { + 'workflow_task_id': workflow_task_id, + 'offset': args.get('offset'), + 'alt_cylc_run_dir': args.get('cylc_run_dir'), + 'is_message': is_message, + } + + +# BACK COMPAT: workflow_state_backcompat +# from: 8.0.0 +# to: 8.3.0 +# remove at: 8.x +def _validate_backcompat(args: Dict[str, Any]): + """Validate old workflow_state xtrigger function args. + """ + bound_args = signature(workflow_state).bind( + **_upgrade_workflow_state_sig(args) + ) + bound_args.apply_defaults() + validate(bound_args.arguments) +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/flow/xtriggers/xrandom.html b/nightly_8.4/html/_modules/cylc/flow/xtriggers/xrandom.html new file mode 100644 index 00000000000..a355fc94374 --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/flow/xtriggers/xrandom.html @@ -0,0 +1,280 @@ + + + + + + cylc.flow.xtriggers.xrandom — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.flow.xtriggers.xrandom

+# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from random import random, randint
+from time import sleep
+from typing import Any, Dict, Tuple
+
+from cylc.flow.exceptions import WorkflowConfigError
+
+
+COLORS = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]
+SIZES = ["tiny", "small", "medium", "large", "huge", "humongous"]
+
+
+
+[docs] +def xrandom( + percent: float, secs: int = 0, _: Any = None +) -> Tuple[bool, Dict[str, str]]: + """Random xtrigger, with configurable sleep and percent success. + + Sleep for ``sec`` seconds, and report satisfied with ``percent`` + likelihood. + + The ``_`` argument is not used in the function code, but can be used to + specialize the function signature to cycle point or task. + + Args: + percent: + Percent likelihood of passing. + secs: + Seconds to sleep before starting the trigger. + _: + Used to allow users to specialize the trigger with extra + parameters. + + Returns: + tuple: (satisfied, results) + + satisfied: + True if ``satisfied`` else ``False``. + results: + A dictionary containing the following keys: + + ``COLOR`` + A random colour (e.g. red, orange, ...). + ``SIZE`` + A random size (e.g. small, medium, ...). + + Examples: + If the percent is zero, it returns that the trigger condition was + not satisfied, and an empty dictionary. + + >>> xrandom(0, 0) + (False, {}) + + If the percent is not zero, but the random percent success is not met, + then it also returns that the trigger condition was not satisfied, + and an empty dictionary. + + >>> import sys + >>> mocked_random = lambda: 0.3 + >>> sys.modules[__name__].random = mocked_random + >>> xrandom(15.5, 0) + (False, {}) + + Finally, if the percent is not zero, and the random percent success is + met, then it returns that the trigger condition was satisfied, and a + dictionary containing random colour and size as result. + + >>> import sys + >>> mocked_random = lambda: 0.9 + >>> sys.modules[__name__].random = mocked_random + >>> mocked_randint = lambda x, y: 1 + >>> sys.modules[__name__].randint = mocked_randint + >>> xrandom(99.99, 0) + (True, {'COLOR': 'orange', 'SIZE': 'small'}) + + """ + sleep(float(secs)) + results = {} + satisfied = random() < float(percent) / 100 # nosec: B311 + if satisfied: + results = { + 'COLOR': COLORS[randint(0, len(COLORS) - 1)], # nosec: B311 + 'SIZE': SIZES[randint(0, len(SIZES) - 1)] # nosec: B311 + } + return satisfied, results
+ + + +
+[docs] +def validate(args: Dict[str, Any]): + """Validate the args that xrandom is called with. + + Cylc calls this function automatically when parsing the workflow. + + Here we specify the rules for args are: + + * percent: Must be 0 ≤ x ≤ 100 + * secs: Must be an integer. + """ + percent = args['percent'] + if ( + not isinstance(percent, (float, int)) + or not (0 <= percent <= 100) + ): + raise WorkflowConfigError( + "'percent' should be a float between 0 and 100" + ) + + secs = args['secs'] + if not isinstance(secs, int): + raise WorkflowConfigError("'secs' should be an integer")
+ +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/uiserver/app.html b/nightly_8.4/html/_modules/cylc/uiserver/app.html new file mode 100644 index 00000000000..7766781cdae --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/uiserver/app.html @@ -0,0 +1,762 @@ + + + + + + cylc.uiserver.app — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.uiserver.app

+#!/usr/bin/env python3
+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Cylc UI Server can be configured using a ``jupyter_config.py`` file, loaded
+from a hierarchy of locations. This hierarchy includes the prepackaged
+configuration, the site directory (which defaults to ``/etc/cylc/uiserver`` but
+can be set with the environment variable ``$CYLC_SITE_CONF_PATH``) and
+the user directory (``~/.cylc/uiserver``).
+For example, at Cylc UI Server version 0.6.0, the hierarchy (highest priority
+at the bottom) would be:
+
+* ``cylc/uiserver/jupyter_config.py`` (pre-packaged default)
+* ``/etc/cylc/uiserver/jupyter_config.py``
+* ``/etc/cylc/uiserver/0/jupyter_config.py``
+* ``/etc/cylc/uiserver/0.6/jupyter_config.py``
+* ``/etc/cylc/uiserver/0.6.0/jupyter_config.py``
+* ``~/.cylc/uiserver/jupyter_config.py``
+* ``~/.cylc/uiserver/0/jupyter_config.py``
+* ``~/.cylc/uiserver/0.6/jupyter_config.py``
+* ``~/.cylc/uiserver/0.6.0/jupyter_config.py``
+
+
+An example configuration might look like this:
+
+.. code-block:: python
+
+   # scan for workflows every 10 seconds
+   c.CylcUIServer.scan_interval = 10
+
+The Cylc UI Server is a `Jupyter Server`_ extension. For generic configuration
+options see the Jupyter Servers documentation:
+:external+jupyter_server:ref:`other-full-config`.
+Cylc specific configurations are documented here.
+
+.. note::
+
+   ``c.CylcUIServer.site_authorization`` should be defined in
+   ``/etc/cylc/uiserver/jupyter_config.py``, or, alternatively, via
+   the environment variable ``CYLC_SITE_CONF_PATH``.
+"""
+
+import getpass
+import os
+import sys
+from concurrent.futures import ProcessPoolExecutor
+from pathlib import Path, PurePath
+from textwrap import dedent
+from types import SimpleNamespace
+from typing import List, Optional, Union
+
+from jupyter_server.extension.application import ExtensionApp
+from pkg_resources import parse_version
+from tornado import ioloop
+from tornado.web import RedirectHandler
+from traitlets import (
+    Bool,
+    Dict,
+    Float,
+    Int,
+    TraitError,
+    TraitType,
+    Undefined,
+    Unicode,
+    default,
+    validate,
+)
+from traitlets.config.loader import LazyConfigValue
+
+from cylc.flow.network.graphql import (
+    CylcGraphQLBackend, IgnoreFieldMiddleware
+)
+from cylc.flow.profiler import Profiler
+from cylc.uiserver import (
+    __file__ as uis_pkg,
+)
+from cylc.uiserver.authorise import (
+    Authorization,
+    AuthorizationMiddleware
+)
+from cylc.uiserver.data_store_mgr import DataStoreMgr
+from cylc.uiserver.handlers import (
+    CylcStaticHandler,
+    CylcVersionHandler,
+    SubscriptionHandler,
+    UIServerGraphQLHandler,
+    UserProfileHandler,
+)
+from cylc.uiserver.config_util import (
+    get_conf_dir_hierarchy,
+    SITE_CONF_ROOT,
+    USER_CONF_ROOT
+)
+from cylc.uiserver.resolvers import Resolvers
+from cylc.uiserver.schema import schema
+from cylc.uiserver.websockets.tornado import TornadoSubscriptionServer
+from cylc.uiserver.workflows_mgr import WorkflowsManager
+
+
+INFO_FILES_DIR = Path(USER_CONF_ROOT / "info_files")
+
+
+class PathType(TraitType):
+    """A pathlib traitlet type which allows string and undefined values."""
+
+    @property
+    def info_text(self):
+        return 'a pathlib.PurePath object'
+
+    def validate(self, obj, value):
+        if isinstance(value, str):
+            return Path(value).expanduser()
+        if isinstance(value, PurePath):
+            return value
+        if value == Undefined:
+            return value
+        self.error(obj, value)
+
+
+
+[docs] +class CylcUIServer(ExtensionApp): + + name = 'cylc' + app_name = 'cylc-gui' + load_other_extensions = True + description = ''' + Cylc gui - A user interface for monitoring and controlling Cylc workflows. + ''' # type: ignore[assignment] + examples = dedent(''' + cylc gui # Start the Cylc GUI (at the dashboard page) + cylc gui [workflow] # Start the Cylc GUI (at the workflow page) + cylc gui --new [workflow] # Start a new Cylc server instance if an old one + # has become unresponsive. + cylc gui --no-browser # Start the server but don't open the browser + + ''') # type: ignore[assignment] + # TODO: Add a link to the access group table mappings in cylc documentation + # https://github.com/cylc/cylc-uiserver/issues/466 + AUTH_DESCRIPTION = ''' + Authorization can be granted at operation (mutation) level, i.e. + specifically grant user access to execute Cylc commands, e.g. + ``play``, ``pause``, ``edit``, ``trigger`` etc. For your + convenience, these operations have been mapped to access groups + ``READ``, ``CONTROL`` and ``ALL``. + + To remove permissions, prepend the access group or operation with + ``!``. + + Permissions are additive but negated permissions take precedence + above additions e.g. ``CONTROL, !stop`` will permit all operations + in the ``CONTROL`` group except for ``stop``. + + .. note:: + + Any authorization permissions granted to a user will be + applied to all workflows. + + For more information, including the access group mappings, see + :ref:`cylc.uiserver.multi-user`. + ''' + + site_authorization = Dict( + config=True, + help=''' + Dictionary containing site limits and defaults for authorization. + + This configuration should be placed only in the site set + configuration file and not the user configuration file (use + ``c.CylcUIServer.user_authorization`` for user defined + authorization). + + If this configuration is empty, site authorization defaults to no + configurable authorization and users will be unable to set any + authorization. + + ''' + AUTH_DESCRIPTION + ''' + + .. rubric:: Example Configuration: + + .. code-block:: python + + c.CylcUIServer.site_authorization = { + "*": { # For all ui-server owners, + "*": { # Any authenticated user + "default": "READ", # Has default read access + }, + "user1": { # user1 + "default": ["!ALL"], # No privileges for all + # ui-server owners. + }, # No limit set, so all ui-server owners + }, # limit is also "!ALL" for user1 + "server_owner_1": { # For specific UI Server owner, + "group:group_a": { # Any member of group_a + "default": "READ", # Will have default read access + "limit": ["ALL", "!play"], # server_owner_1 can + }, # grant All privileges, except play. + }, + "group:grp_of_svr_owners": { # Group of UI Server owners + "group:group_b": { + "limit": [ # can grant groupB users up to READ and + "READ", # CONTROL privileges, without stop and + "CONTROL", # kill + "!stop", + "!kill", # No default, so default is no access + ], + }, + }, + } + + ''') + + user_authorization = Dict( + config=True, + help=''' + Dictionary containing authorized users and permission levels for + authorization. + + Use this setting to share control of your workflows + with other users. + + Note that you are only permitted to give away permissions up to + your limit for each user, as defined in the site_authorization + configuration. + + ''' + AUTH_DESCRIPTION + ''' + + Example configuration, residing in + ``~/.cylc/uiserver/jupyter_config.py``: + + .. code-block:: python + + c.CylcUIServer.user_authorization = { + "*": ["READ"], # any authenticated user has READ access + "group:group2": ["ALL"], # Any user in system group2 has + # access to all operations + "userA": ["ALL", "!stop"], # userA has ALL operations, not + # stop + } + + ''' + ) + + ui_path = PathType( + config=False, + help=''' + Path to the UI build to serve. + + Internal config derived from ui_build_dir and ui_version. + ''' + ) + ui_build_dir = PathType( + config=True, + help=''' + The directory containing the UI build. + + This can be a directory containing a single UI build e.g:: + + dir/ + index.html + + Or a tree of builds where each build has a version number e.g:: + + dir/ + 1.0/ + index.html + 2.0/ + index.html + + By default this points at the UI build tree which was bundled with + the UI Server. Change this if you want to pick up a different + build e.g. for development or evaluation purposes. + + Takes effect on (re)start. + ''' + ) + ui_version = Unicode( + config=True, + help=''' + Hardcodes the UI version to serve. + + If the ``ui_build_dir`` is a tree of builds, this config can be + used to determine which UI build is used. + + By default the highest version is chosen according to PEP440 + version sorting rules. + + Takes effect on (re)start. + ''' + ) + scan_interval = Float( + config=True, + help=''' + Set the interval between workflow scans in seconds. + + Workflow scans allow a UI server to detect workflows which have + been started from the CLI since the last update. + + This involves a number of filesystem operations, to reduce + system load set a higher value. + ''', + default_value=5.0 # default values as kwargs correctly display in docs + ) + max_workers = Int( + config=True, + help=''' + Set the maximum number of workers for process pools. + ''', + default_value=1 + ) + max_threads = Int( + config=True, + help=''' + Set the maximum number of threads the Cylc UI Server can use. + + This determines the maximum number of active workflows that the + server can track. + ''', + default_value=100, + ) + profile = Bool( + config=True, + help=''' + Turn on Python profiling. + + The profile results will be saved to ~/.cylc/uiserver/profile.prof + in cprofile format. + ''', + default_value=False, + ) + + @validate('ui_build_dir') + def _check_ui_build_dir_exists(self, proposed): + if proposed['value'].exists(): + return proposed['value'] + raise TraitError(f'ui_build_dir does not exist: {proposed["value"]}') + + @validate('site_authorization') + def _check_site_auth_dict_correct_format(self, proposed): + # TODO: More advanced auth dict validating + if isinstance(proposed['value'], dict): + return proposed['value'] + raise TraitError( + f'Error in site authorization config: {proposed["value"]}') + + @staticmethod + def _list_ui_versions(path: Path) -> List[str]: + """Return a list of UI build versions detected in self.ui_path.""" + return sorted( + ( + version.name + for version in path.glob('[0-9][0-9.]*') + if version + ), + key=parse_version + ) + + @default('ui_path') + def _get_ui_path(self): + build_dir = self.ui_build_dir + version = self.ui_version + + if build_dir and build_dir != Undefined: + # ui path has been configured, check if the path is a build + # (rather than a dir of builds e.g. development build) + if (build_dir / 'index.html').exists(): + return build_dir + else: + # default UI build base directory + build_dir = Path(uis_pkg).parent / 'ui' + + if not version: + # pick the highest installed version by default + try: + version = self._list_ui_versions(build_dir)[-1] + except IndexError: + raise Exception( + f'Could not find any UI builds in {build_dir}.' + ) + + ui_path = build_dir / version + if (ui_path / 'index.html').exists(): + return ui_path + + raise Exception(f'Could not find UI build in {ui_path}') + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._config_file_paths: Optional[List[str]] = None + self.executor = ProcessPoolExecutor(max_workers=self.max_workers) + self.workflows_mgr = WorkflowsManager(self, log=self.log) + self.data_store_mgr = DataStoreMgr( + self.workflows_mgr, + self.log, + self.max_threads, + ) + # sub_status dictionary storing status of subscriptions + self.sub_statuses = {} + self.resolvers = Resolvers( + self.data_store_mgr, + log=self.log, + executor=self.executor, + workflows_mgr=self.workflows_mgr, + ) + + @property + def config_file_paths(self) -> List[str]: + if self._config_file_paths is None: + ret = get_conf_dir_hierarchy( + [ + SITE_CONF_ROOT, # site configuration + USER_CONF_ROOT, # user configuration + ], filename=False + ) + # Next include currently needed for directory making + ret.insert(0, str(Path(uis_pkg).parent)) # packaged config + ret.reverse() + self._config_file_paths = ret + return self._config_file_paths + + def initialize_settings(self): + """Update extension settings. + + Update the self.settings trait to pass extra settings to the underlying + Tornado Web Application. + + self.settings.update({'<trait>':...}) + """ + super().initialize_settings() + + # startup messages + self.log.info("Starting Cylc UI Server") + self.log.info(f'Serving UI from: {self.ui_path}') + self.log.debug( + 'CylcUIServer config:\n' + '\n'.join( + f' * {key} = {repr(value)}' + for key, value in self.config['CylcUIServer'].items() + ) + ) + + # start profiling + self.profiler = Profiler( + # the profiler is designed to attach to a Cylc scheduler + schd=SimpleNamespace(workflow_log_dir=USER_CONF_ROOT), + # profiling is turned on via the "profile" traitlet + enabled=self.profile, + ) + self.profiler.start() + + # start the async scan task running (do this on server start not init) + ioloop.IOLoop.current().add_callback( + self.workflows_mgr.run + ) + # configure the scan interval + ioloop.PeriodicCallback( + self.workflows_mgr.scan, + self.scan_interval * 1000 + ).start() + + def initialize_handlers(self): + self.authobj = self.set_auth() + self.set_sub_server() + + self.handlers.extend([ + ( + 'cylc/version', + CylcVersionHandler, + {'auth': self.authobj} + ), + ( + 'cylc/graphql', + UIServerGraphQLHandler, + { + 'schema': schema, + 'resolvers': self.resolvers, + 'backend': CylcGraphQLBackend(), + 'middleware': [ + AuthorizationMiddleware, + IgnoreFieldMiddleware + ], + 'auth': self.authobj, + } + ), + ( + 'cylc/graphql/batch', + UIServerGraphQLHandler, + { + 'schema': schema, + 'resolvers': self.resolvers, + 'backend': CylcGraphQLBackend(), + 'middleware': [ + AuthorizationMiddleware, + IgnoreFieldMiddleware + ], + 'batch': True, + 'auth': self.authobj, + } + ), + ( + 'cylc/subscriptions', + SubscriptionHandler, + { + 'sub_server': self.subscription_server, + 'resolvers': self.resolvers, + 'sub_statuses': self.sub_statuses + } + ), + ( + 'cylc/userprofile', + UserProfileHandler, + {'auth': self.authobj} + ), + ( + 'cylc/(.*)?', + CylcStaticHandler, + { + 'path': str(self.ui_path), + 'default_filename': 'index.html' + } + ), + ( + # redirect '/cylc' to '/cylc/' + 'cylc', + RedirectHandler, + { + 'url': 'cylc/' + } + ) + ]) + + def set_sub_server(self): + self.subscription_server = TornadoSubscriptionServer( + schema, + backend=CylcGraphQLBackend(), + middleware=[ + IgnoreFieldMiddleware, + AuthorizationMiddleware, + ], + auth=self.authobj, + ) + + def set_auth(self) -> Authorization: + """Create authorization object. + One for the lifetime of the UIServer. + """ + user_auth: Union[LazyConfigValue, dict] = ( + self.config.CylcUIServer.user_authorization + ) + site_auth: Union[LazyConfigValue, dict] = ( + self.config.CylcUIServer.site_authorization + ) + if isinstance(user_auth, LazyConfigValue): + user_auth = user_auth.to_dict() + if isinstance(site_auth, LazyConfigValue): + site_auth = site_auth.to_dict() + + return Authorization( + getpass.getuser(), + user_auth, + site_auth, + self.log, + ) + + def initialize_templates(self): + """Change the jinja templating environment.""" + + @classmethod + def launch_instance(cls, argv=None, workflow_id=None, **kwargs): + if workflow_id: + cls.default_url = f"/cylc/#/workspace/{workflow_id}" + else: + cls.default_url = "/cylc" + if argv is None: + # jupyter server isn't expecting to be launched by a Cylc command + # this patches some internal logic + argv = sys.argv[2:] + os.environ["JUPYTER_RUNTIME_DIR"] = str(INFO_FILES_DIR) + super().launch_instance(argv=argv, **kwargs) + del os.environ["JUPYTER_RUNTIME_DIR"] + + async def stop_extension(self): + # stop the async scan task + await self.workflows_mgr.stop() + + # stop active subscriptions + for sub in self.data_store_mgr.w_subs.values(): + sub.stop() + + # Shutdown the thread pool executor (used for subscription processing) + self.data_store_mgr.executor.shutdown(wait=False) + + # stop the process pool (used for background commands) + self.executor.shutdown() + + # Destroy ZeroMQ context of all sockets + self.workflows_mgr.context.destroy() + self.profiler.stop()
+ +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/cylc/uiserver/authorise.html b/nightly_8.4/html/_modules/cylc/uiserver/authorise.html new file mode 100644 index 00000000000..7ad9e93a4fc --- /dev/null +++ b/nightly_8.4/html/_modules/cylc/uiserver/authorise.html @@ -0,0 +1,824 @@ + + + + + + cylc.uiserver.authorise — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for cylc.uiserver.authorise

+# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from contextlib import suppress
+from functools import lru_cache
+from getpass import getuser
+import grp
+from inspect import iscoroutinefunction
+import os
+from typing import List, Optional, Union, Set, Tuple
+
+import graphene
+from jupyter_server.auth import Authorizer
+from tornado import web
+
+from cylc.uiserver.schema import UISMutations
+from cylc.uiserver.utils import is_bearer_token_authenticated
+
+from graphene.utils.str_converters import to_snake_case
+
+
+
+[docs] +class CylcAuthorizer(Authorizer): + """Defines a safe default authorization policy for Jupyter Server. + + `Jupyter Server`_ provides an authorisation layer which gives full + permissions to any user who has been granted permission to the Jupyter Hub + ``access:servers`` scope + (see :ref:`JupyterHub scopes reference <jupyterhub-scopes>`). This allows + the execution of arbitrary code under another user account. + + To prevent this you must define an authorisation policy using + :py:attr:`c.ServerApp.authorizer_class + <jupyter_server.serverapp.ServerApp.authorizer_class>`. + + This class defines a policy which blocks all API calls to another user's + server, apart from calls to Cylc interfaces explicitly defined in the + :ref:`Cylc authorisation configuration <cylc.uiserver.user_authorization>`. + + This class is configured as the default authoriser for all Jupyter Server + instances spawned via the ``cylc hubapp`` command. This is the default if + you started `Jupyter Hub`_ using the ``cylc hub`` command. To see where + this default is set, see this file for the appropriate release of + cylc-uiserver: + https://github.com/cylc/cylc-uiserver/blob/master/cylc/uiserver/jupyter_config.py + + If you are launching Jupyter Hub via another command (e.g. ``jupyterhub``) + or are overriding :py:attr:`jupyterhub.app.JupyterHub.spawner_class`, then + you will need to configure a safe authorisation policy e.g: + + .. code-block:: python + + from cylc.uiserver.authorise import CylcAuthorizer + c.ServerApp.authorizer_class = CylcAuthorizer + + .. note:: + + It is possible to provide read-only access to Jupyter Server extensions + such as Jupyter Lab, however, this isn't advisable as Jupyter Lab does + not apply file-system permissions to what another user is allowed to + see. + + If you wish to grant users access to other user's Jupyter Lab servers, + override this configuration with due care over what you choose to + expose. + + """ + + # This is here just to fix sphinx autodoc warning from traitlets' __init__ + # see https://github.com/cylc/cylc-uiserver/pull/560 + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def is_authorized(self, handler, user, action, resource) -> bool: + """Allow a user to access their own server. + + Note that Cylc uses its own authorization system (which is locked-down + by default) and is not affected by this policy. + """ + if is_bearer_token_authenticated(handler): + # this session is authenticated by a token or password NOT by + # Jupyter Hub -> the bearer of the token has full permissions + return True + + # the username of the user running this server + # (used for authorzation purposes) + me = getuser() + + if user.username == me: + # give the user full permissions to their own server + return True + + # block access to everyone else + return False
+ + + +class Authorization: + """Authorization configuration object. + + One instance of this class lives for the life of the UI Server. + + If authorization settings change the UI Server will need to be re-started + to pick them up. + + Authorization has access groups: `READ`, `CONTROL`, `ALL` - along with + their negations, `!READ`, `!CONTROL` and `!ALL` which indicate removal of + the permission groups. + + Args: + owner: The server owner's user name. + owner_auth_conf: The server owner's authorization configuration. + site_auth_conf: The site's authorization configuration. + log: The application logger. + + """ + + # config literals + DEFAULT = "default" + LIMIT = "limit" + GRP_IDENTIFIER = "group:" + + # Operations + + ########################################################################## + # !WARNING! # + # # + # Beware of changing these permission groups. Users may be relying on # + # these settings. Changes should be widely publicised to users. # + # # + # If adding/removing operations, ensure documentation is updated. # + # # + ########################################################################## + + READ_OPERATION = "read" + + # Access group identifiers (used in config) + READ = "READ" + CONTROL = "CONTROL" + ALL = "ALL" + NOT_READ = "!READ" + NOT_CONTROL = "!CONTROL" + NOT_ALL = "!ALL" + + # Access Groups + READ_OPS = {READ_OPERATION} + ASYNC_OPS = {"query", "mutation"} + READ_AUTH_OPS = {"query", "subscription"} + + def __init__( + self, + owner_user_name: str, + owner_auth_conf: dict, + site_auth_conf: dict, + log, + ): + self.owner_user_name: str = owner_user_name + self.owner_user_groups: List[str] = self._get_groups( + self.owner_user_name + ) + self.log = log + self.owner_auth_conf: dict = owner_auth_conf + self.site_auth_config: dict = site_auth_conf + self.owner_dict = self.build_owner_site_auth_conf() + + # lru_cache this method - see flake8-bugbear B019 + self.get_permitted_operations = lru_cache(maxsize=128)( + self._get_permitted_operations + ) + + @property + def ALL_OPS(self) -> List[str]: + """ALL OPS constant, returns list of all mutations.""" + return get_list_of_mutations() + + @property + def CONTROL_OPS(self) -> List[str]: + """CONTROL OPS constant, returns list of all control mutations.""" + return get_list_of_mutations(control=True) + + def expand_and_process_access_groups(self, permission_set: set) -> set: + """Process a permission set. + + Takes a permission set, e.g. limits, defaults. + Expands the access groups and removes negated operations. + + Args: + permission_set: set of permissions + + Returns: + processed permission set. + + """ + # Expand permission groups + # E.G. ALL -> ["read", "trigger", "broadcast", ...] + for action_group, expansion in { + Authorization.READ: Authorization.READ_OPS, + Authorization.CONTROL: self.CONTROL_OPS, + Authorization.ALL: self.ALL_OPS, + }.items(): + if action_group in permission_set: + permission_set.remove(action_group) + permission_set.update(expansion) + + # Expand negated permission groups + # E.G. !CONTROL -> ["!trigger", "!stop", "!pause", ...] + for action_group, expansion in { + Authorization.NOT_READ: [f"!{x}" for x in Authorization.READ_OPS], + Authorization.NOT_CONTROL: [ + f"!{x}" for x in self.CONTROL_OPS + ], + Authorization.NOT_ALL: [ + f"!{x}" for x in self.ALL_OPS + ], + }.items(): + if action_group in permission_set: + permission_set.remove(action_group) + permission_set.update(expansion) + + # Remove negated permissions + remove = set() + for perm in permission_set: + if perm.startswith("!"): + remove.add(perm.lstrip("!")) + remove.add(perm) + permission_set.difference_update(remove) + permission_set.discard("") + + return permission_set + + def get_owner_site_limits_for_access_user( + self, access_user_name: str, access_user_groups: List[str] + ) -> Set[str]: + """Returns limits owner can give to given access_user + + Args: + access_user_name: The username of the authenticated user. + access_user_groups: All groups the authenticated user belongs to. + + Returns: + Set of limits that the uiserver owner is allowed to give away + for given access user. + + """ + limits: Set[str] = set() + if not self.owner_dict: + return limits + items_to_check = ["*", access_user_name] + items_to_check.extend(access_user_groups) + for item in items_to_check: + permission: Union[str, List] = "" + default = "" + with suppress(KeyError): + default = self.owner_dict[item].get(Authorization.DEFAULT, "") + with suppress(KeyError): + permission = self.owner_dict[item].get( + Authorization.LIMIT, default + ) + if permission == []: + raise_auth_config_exception("site") + if isinstance(permission, str): + limits.add(permission) + else: + limits.update(permission) + limits.discard("") + return limits + + def get_access_user_permissions_from_owner_conf( + self, access_user_name: str, access_user_groups: List[str] + ) -> set: + """ + Returns set of operations specific to access user from owner user conf. + + Args: + access_user_name: The username of the authenticated user. + access_user_groups: All groups the authenticated user belongs to. + + """ + items_to_check = ["*", access_user_name] + items_to_check.extend(access_user_groups) + allowed_operations = set() + for item in items_to_check: + permission = self.owner_auth_conf.get(item, "") + # Specifiying empty list equates to removing of all permissions. + if permission == []: + raise_auth_config_exception("user") + if isinstance(permission, str): + allowed_operations.add(permission) + else: + allowed_operations.update(permission) + allowed_operations.discard("") + return allowed_operations + + # lru_cached - see __init__() + def _get_permitted_operations(self, access_user: str): + """Return permitted operations for given access_user. + + This method is cached for efficiency. + + Checks: + - site config to ensure owner is permitted to give away permissions + - user config for authorised operations related to access_user and + their groups + - if user not in user config, then returns defaults from site config. + + Args: + access_user: username to check for permitted operations + + Returns: + Set of operations permitted by given access user for this UI Server + + """ + # users have full access to their own server (ALL) + if access_user == self.owner_user_name: + return set(self.ALL_OPS) + + # all groups the authenticated user belongs to + access_user_groups = self._get_groups(access_user) + + # the maximum permissions the site permits the user to grant + limits_owner_can_give = self.get_owner_site_limits_for_access_user( + access_user, access_user_groups + ) + + # the permissions the user wishes to grant + user_conf_permitted_ops = ( + self.get_access_user_permissions_from_owner_conf( + access_user, access_user_groups + ) + ) + + if len(user_conf_permitted_ops) == 0: + # the user has not specified the permissions they wish to grant + # -> fallback to the site defaults + user_conf_permitted_ops = ( + self.return_site_auth_defaults_for_access_user( + access_user, access_user_groups + ) + ) + + # expand permission groups and remove negated permissions + user_conf_permitted_ops = self.expand_and_process_access_groups( + user_conf_permitted_ops + ) + limits_owner_can_give = self.expand_and_process_access_groups( + limits_owner_can_give + ) + + # subtract permissions that the site does not permit to be granted + allowed_operations = limits_owner_can_give.intersection( + user_conf_permitted_ops + ) + + self.log.info( + f"User {access_user} authorized permissions: " + f"{sorted(allowed_operations)}" + ) + return allowed_operations + + def is_permitted(self, access_user: str, operation: str) -> bool: + """Checks if user is permitted to action operation. + + Args: + access_user: User attempting to action given operation. + operation: operation name + + Returns: + True if access_user permitted to action operation, otherwise, + False. + + """ + if access_user == self.owner_user_name: + return True + + # convert from GraphQL camel case to Python snake case + operation = to_snake_case(operation) + + if operation in self.get_permitted_operations(access_user): + self.log.info(f"{access_user}: authorized to {operation}") + return True + + self.log.info(f"{access_user}: not authorized to {operation}") + return False + + def build_owner_site_auth_conf(self): + """Build UI Server owner permissions dictionary. + + Creates a reduced site auth dictionary for the ui-server owner. + """ + owner_dict = {} + items_to_check = ["*", self.owner_user_name] + items_to_check.extend(self.owner_user_groups) + + # dict containing user info applying to the current ui_server owner + for uis_owner_conf, access_user_dict in self.site_auth_config.items(): + if uis_owner_conf in items_to_check: + # acc_user = access_user + for acc_user_conf, acc_user_perms in access_user_dict.items(): + existing_user_conf = owner_dict.get(acc_user_conf) + if existing_user_conf: + # process limits and defaults and update dictionary + existing_default = existing_user_conf.get( + Authorization.DEFAULT, '' + ) + existing_limit = existing_user_conf.get( + Authorization.LIMIT, existing_default + ) + new_default = acc_user_perms.get( + Authorization.DEFAULT, '' + ) + new_limit = acc_user_perms.get( + Authorization.LIMIT, new_default + ) + set_defs = set() + for conf in [existing_default, new_default]: + if isinstance(conf, list): + set_defs.update(conf) + else: + set_defs.add(conf) + set_lims = set() + for conf in [existing_limit, new_limit]: + if isinstance(conf, list): + set_lims.update(conf) + else: + set_lims.add(conf) + # update and continue + owner_dict[acc_user_conf][Authorization.LIMIT] = list( + set_lims + ) + owner_dict[acc_user_conf][Authorization.DEFAULT] = ( + list(set_defs) + ) + continue + owner_dict.update(access_user_dict) + # Now we have a reduced site auth dictionary for the current owner + return owner_dict + + def return_site_auth_defaults_for_access_user( + self, access_user_name: str, access_user_groups: List[str] + ) -> Set: + """Return site authorization defaults for given access user. + + Args: + access_user_name: The username of the authenticated user. + access_user_groups: All groups the authenticated user belongs to. + + Returns: + The set of default operations permitted. + + """ + defaults: Set[str] = set() + if not self.owner_dict: + return defaults + items_to_check = ["*", access_user_name] + items_to_check.extend(access_user_groups) + for item in items_to_check: + permission: Union[str, List] = "" + with suppress(KeyError): + permission = self.owner_dict[item].get( + Authorization.DEFAULT, "" + ) + if permission == []: + raise_auth_config_exception("site") + if isinstance(permission, str): + defaults.add(permission) + else: + defaults.update(permission) + defaults.discard("") + return defaults + + def _get_groups(self, user: str) -> List[str]: + """Allows get groups to use self.logger if something goes wrong. + + Added to provide a single interface for get_groups to this class, to + avoid having to pass the logger to get_groups (and methods it calls). + """ + good_groups, bad_groups = get_groups(user) + if bad_groups: + self.log.warning( + f'{user} has the following invalid groups in their profile ' + f'{bad_groups} - these groups will be ignored.' + ) + return good_groups + + +# GraphQL middleware +class AuthorizationMiddleware: + """Authorization Middleware for authorization checking GraphQL. + + Mutations are checked against permissions from config files. + + Raises: + web.HTTPError: Unauthorized requests. + + """ + + auth = None + + def resolve(self, next_, root, info, **args): + current_user = info.context["current_user"] + # We won't be re-checking auth for return variables + if len(info.path) > 1: + return next_(root, info, **args) + op_name = self.get_op_name(info.field_name, info.operation.operation) + # It shouldn't get here but worth checking for zero trust + if not op_name: + self.auth_failed( + current_user, + op_name, + http_code=400, + msg="Operation not in schema.", + ) + try: + authorised = self.auth.is_permitted(current_user, op_name) + except Exception: + # Fail secure + authorised = False + if not authorised: + self.auth_failed(current_user, op_name, http_code=403) + if ( + info.operation.operation in Authorization.ASYNC_OPS + or iscoroutinefunction(next_) + ): + return self.async_resolve(next_, root, info, **args) + return next_(root, info, **args) + + def auth_failed( + self, + current_user: str, + op_name: str, + http_code: int, + message: Optional[str] = None, + ): + """Raise an authorization error. + + Args: + current_user: username accessing operation + op_name: operation name + http_code: http error code to raise + message: Message to log Defaults to None. + + Raises: + web.HTTPError + + """ + log_message = ( + f"Authorization failed for {current_user}" + f":requested to {op_name}." + ) + if message: + log_message = log_message + " " + message + raise web.HTTPError(http_code, reason=message) + + def get_op_name(self, field_name: str, operation: str) -> Optional[str]: + """Returns the operation name required for authorization. + + Converts queries and subscriptions to read operations. + + Args: + field_name: Field name e.g. play + operation: operation type + + Returns: + The operation name. + + """ + if operation in Authorization.READ_AUTH_OPS: + return Authorization.READ_OPERATION + + # convert from GraphQL camel case to Python snake case + field_name = to_snake_case(field_name) + + # Check it is a mutation in our schema + if self.auth and field_name in self.auth.ALL_OPS: + return field_name + + return None + + async def async_resolve(self, next_, root, info, **args): + """Return awaited coroutine""" + return await next_(root, info, **args) + + +
+[docs] +def get_groups(username: str) -> Tuple[List[str], List[str]]: + """Return a list of system groups for given user. + + Uses ``os.getgrouplist`` and ``os.NGROUPS_MAX`` to get system groups for a + given user. ``grp.getgrgid`` then parses these to return a list of group + names. + + Args: + username: username used to check system groups. + + Returns: + System groups for username given + + """ + groupmax = os.NGROUPS_MAX # type: ignore + group_ids = os.getgrouplist(username, groupmax) + group_ids.remove(groupmax) + # turn list of group_ids into group names with group identifier prepended + return parse_group_ids(group_ids)
+ + + +def parse_group_ids(group_ids: List) -> Tuple[List[str], List[str]]: + """Returns list of groups in the correct format for authorisation. + + Args: + group_ids: List of users groups, in number format + + Returns: + List of users groups, in id format with group identifier prepended. + + """ + group_list = [] + bad_group_list = [] + for x in group_ids: + try: + group_list.append( + f"{Authorization.GRP_IDENTIFIER}{grp.getgrgid(x).gr_name}" + ) + except OverflowError: + continue + except KeyError: + bad_group_list.append(x) + return group_list, bad_group_list + + +def get_list_of_mutations(control: bool = False) -> List[str]: + """Gets list of mutations""" + list_of_mutations = [ + attr + for attr in dir(UISMutations) + if isinstance(getattr(UISMutations, attr), graphene.Field) + ] + if control: + # Broadcast is an ALL mutation + list_of_mutations.remove("broadcast") + else: + # 'read' is used soley for authorization and is not a UISMutation + list_of_mutations.append(Authorization.READ_OPERATION) + return list_of_mutations + + +def raise_auth_config_exception(config_type: str): + """Error raise for empty list in auth config. + + Args: + config_type: Either site or user. + + """ + raise Exception( + f'Error in {config_type} config: ' + f'`c.CylcUIServer.{config_type}_authorization`. ' + f'"[]" is not supported. Use "{Authorization.NOT_ALL}" to remove all' + ' permissions.' + ) +
+ +
+
+ +
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_modules/index.html b/nightly_8.4/html/_modules/index.html new file mode 100644 index 00000000000..d8d9a4a9209 --- /dev/null +++ b/nightly_8.4/html/_modules/index.html @@ -0,0 +1,172 @@ + + + + + + Overview: module code — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/_sources/7-to-8/caveats.rst.txt b/nightly_8.4/html/_sources/7-to-8/caveats.rst.txt new file mode 100644 index 00000000000..0b9cf1630dc --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/caveats.rst.txt @@ -0,0 +1,58 @@ +Cylc |version| Caveats +====================== + +There are a few Cylc 7 features which do not yet have direct replacements in +Cylc 8. These features will be re-implemented in future releases. + + +Cylc Flow +--------- + +Multiple Flows + The new :term:`scheduler` can manage multiple flows in the workflow graph. + Commands and options for interacting with flows are still being refined. + + +Browser Based UI +---------------- + +The old "GUI" has been replaced by the new browser-based "UI". + +Static Graph Visualization + Not yet reimplemented for Cylc 8. As an interim measure the + ``cylc graph`` command can generate a basic PNG image of a workflow + graph if Graphviz is installed in the Cylc environment. + +Multiple Selection + Multiple selection is yet to be implemented, however, it is possible + to issue action for multiple tasks (e.g. ``kill``) without using + multiple selection: + + * From the UI click on a workflow/cycle/task/job. + * Find the action you want to call (e.g. kill). + * Click the pencil symbol next to this action. + * Edit the workflows/cycles/tasks/jobs in the form and press submit. + + * https://github.com/cylc/cylc-ui/issues/434 +Installing Workflows + At present there is no way to view or install + :term:`source workflows ` in the UI. +Rose Edit + Rose Edit is awaiting reimplementation. +Xtrigger Visibility + Xtriggers are not yet visible in the UI. + + * https://github.com/cylc/cylc-ui/issues/331 +Documentation / Orientation Guide + Some form of documentation will be provided within the UI itself. + + * https://github.com/cylc/cylc-ui/issues/155 + + +UI Server +--------- + +CLI via UIS + The ability to route Cylc commands via the UIS is planned for a future release + + * https://github.com/cylc/cylc-flow/issues/3528 diff --git a/nightly_8.4/html/_sources/7-to-8/cheat-sheet.rst.txt b/nightly_8.4/html/_sources/7-to-8/cheat-sheet.rst.txt new file mode 100644 index 00000000000..fa121afeb7b --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/cheat-sheet.rst.txt @@ -0,0 +1,345 @@ +.. _728.cheat_sheet: + +Cheat Sheet +=========== + +Quick summary of the command line changes between Cylc 7 / Rose 2019 and Cylc 8. + +.. highlight:: sub + + +Validating +---------- + +Check the workflow configuration for errors: + +.. list-table:: + :class: grid-table + + * - **Cylc 7** + - **Rose 2019** + - **Cylc 8** (Rose 2) + * - :: + + cylc validate + - :: + + # validate from $PWD + rose suite-run --validate + - :: + + cylc validate + +Installing & Running +-------------------- + +Install a workflow from source and run it: + +.. list-table:: + :class: grid-table + + * - **Cylc 7** + - **Rose 2019** + - **Cylc 8** (Rose 2) + * - :: + + # no installation capability + # run from source + cylc run + - :: + + # install from $PWD + # then run + rose suite-run + - :: + + # validate, install & play + cylc vip + cylc vip # use $PWD + + +Reloading +--------- + +To update a running workflow with changes from the source directory: + +.. list-table:: + :class: grid-table + + * - **Cylc 7** + - **Rose 2019** + - **Cylc 8** (Rose 2) + * - :: + + # update the live source + # directly, then + cylc reload + - :: + + # re-install from source + # and do ``cylc reload`` + rose suite-run --reload + - :: + + # Validate against source; + # Reinstall; + # Reload or Play + cylc vr + + +Pausing & Unpausing +------------------- + +Tell a workflow not to submit any new jobs: + +.. list-table:: + :class: grid-table + + * - **Cylc 7** & Rose 2019 + - **Cylc 8** (Rose 2) + * - :: + + cylc hold + + cylc unhold + - :: + + cylc pause + + cylc play + +Stopping +-------- + +Stop a running workflow:: + + cylc stop + +Restarting +---------- + +Restart a stopped workflow and pick up where it left off: + +.. list-table:: + :class: grid-table + + * - **Cylc 7** + - **Rose 2019** + - **Cylc 8** (Rose 2) + * - :: + + # no installation capability + # restart from source + cylc restart + - :: + + # regular restart + rose suite-restart + + Or alternatively:: + + # reinstall and restart + rose suite-run --restart + - :: + + # optionally reinstall + cylc reinstall + + # restart + cylc play + +Deleting +-------- + +Delete the workflow :term:`run directory` (leave source files untouched): + +.. list-table:: + :class: grid-table + + * - **Cylc 7** + - **Rose 2019** + - **Cylc 8** (Rose 2) + * - :: + + rm -rf ~/cylc-run/ + - :: + + rose suite-clean + - :: + + cylc clean + +Scanning +-------- + +List all running workflows:: + + cylc scan + +View A Workflow's Configuration +------------------------------- + +View the parsed workflow configuration: + +.. list-table:: + :class: grid-table + + * - **Cylc 7** + - **Rose 2019** + - **Cylc 8** (Rose 2) + * - :: + + cylc get-config --sparse \ + + - :: + + # install workflow + rose suite-run -l + + # view installed config + cylc get-config --sparse \ + + - :: + + cylc config + +Opening User Interfaces +----------------------- + +Opening the graphical user interface (GUI) or terminal user interface (TUI) +for monitoring / controlling running workflows: + +.. list-table:: + :class: grid-table + + * - + - **Cylc 7** & Rose 2019 + - **Cylc 8** (Rose 2) + * - Terminal + - :: + + cylc monitor + - :: + + cylc tui + * - Graphical + - :: + + cylc gui + - :: + + cylc gui + + * - Web Server + - :: + + cylc review start + + - :: + + cylc hub + +Static Graph Visualisation +-------------------------- + +Generate a visualisation for a workflow without running it: + +.. list-table:: + :class: grid-table + + * - **Cylc 7** & Rose 2019 + - **Cylc 8** (Rose 2) + * - :: + + cylc graph + - :: + + cylc graph + + This generates a basic image file if Graphviz is installed. + + The web UI will have full graph vis. in a future release. + +Datetime Operations +------------------- + +Datetime operations in task scripts: + +.. list-table:: + :class: grid-table + + * - **Cylc 7** & Rose 2019 + - **Cylc 8** (Rose 2) + * - :: + + rose date --offset + - :: + + isodatetime --offset + * - :: + + rose date -c + # equivalent to: + rose date "$CYLC_TASK_CYCLE_POINT" + - :: + + isodatetime ref + # equivalent to: + isodatetime "$CYLC_TASK_CYCLE_POINT" + +Rose Stem +--------- + +Run a :ref:`rose:Rose Stem` test suite. + +.. list-table:: + :class: grid-table + + * - **Rose 2019** + - **Rose 2** (Cylc 8) + * - :: + + # install and start + rose stem + - :: + + # install + rose stem + + # start + cylc play + + +Interventions +------------- + +.. note:: + + See the :ref:`user-guide.interventions` section for more details. + +Set task outputs: + +.. list-table:: + :class: grid-table + + * - **Cylc 7** + - **Cylc 8** + * - :: + + cylc reset -s=succeeded + - :: + + cylc set --out=succeeded + + +Insert a task: + +.. list-table:: + :class: grid-table + + * - **Cylc 7** + - **Cylc 8** + * - :: + + cylc insert + - Tasks are inserted automatically when you "trigger" or "set" them. diff --git a/nightly_8.4/html/_sources/7-to-8/index.rst.txt b/nightly_8.4/html/_sources/7-to-8/index.rst.txt new file mode 100644 index 00000000000..a589a85f936 --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/index.rst.txt @@ -0,0 +1,22 @@ +Cylc 8 Migration Guide +====================== + +**A quick guide for Cylc 7 (and Rose 2019) users upgrading to Cylc 8.** + +.. tip:: + + If you need help using or understanding Cylc 8 please post questions to the + `Cylc 8 Migration category `_ + on the `Cylc Forum `_ + + +Cylc 8 differs from Cylc 7 in many ways: architecture, scheduling +algorithm, security, UIs, working practices, and more. + +.. toctree:: + :maxdepth: 1 + + summary + cheat-sheet + major-changes/index + caveats diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/cli.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/cli.rst.txt new file mode 100644 index 00000000000..5cd17cb2eea --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/cli.rst.txt @@ -0,0 +1,193 @@ +.. _MajorChangesCLI: + +Command Line Interface +====================== + +.. admonition:: Does This Change Affect Me? + :class: tip + + This will affect you if you use the Cylc command line interface. + + +Overview +-------- + +* Some commands have been renamed e.g. ``cylc run`` -> ``cylc play``. +* Some tools have been added or removed. +* A new task ID format has been introduced. + +For a quick side by side comparison see the :ref:`728.cheat_sheet`. + + +Full List Of Command Changes +---------------------------- + +The command line has been simplified from Cylc 7 with some commands being +renamed or removed. + +.. _license: https://github.com/cylc/cylc-flow/blob/master/COPYING + +.. rubric:: Commands that have been removed entirely: + +``cylc checkpoint`` + - Database checkpoints are no longer needed. + - All task state changes are written to the database when they occur. + - Remaining use cases can be handled by starting a new :term:`flow` + which allow a new execution of the graph to be started from an + arbitrary point in the graph. +``cylc documentation`` + - We no longer include a command for locating this documentation. +``cylc edit`` + - Use a text editor to edit the workflow configuration file. +``cylc jobscript`` + - It is no longer possible generate a jobscript from outside of a workflow. +``cylc nudge`` + - No longer required. +``cylc register`` + - Registration is no longer required, all workflows in the ``~/cylc-run`` + directory are "registered" automatically. + - To install a workflow from a working copy use ``cylc install``. +``cylc review`` + - The read-only ``cylc review`` web GUI has been removed. + - The latest Cylc 7 version of ``cylc review`` is Cylc 8 compatible + so can still be used to monitor both Cylc 7 and Cylc 8 workflows + side by side. +``cylc search`` + - Use ``grep`` or a text editor to search the workflow configuration or + source directory. +``cylc submit`` + - It is no longer possible to submit a job from outside of a workflow. +``cylc warranty`` + - The Cylc license remains unchanged from Cylc 7. + +.. rubric:: Commands that have been replaced: + +``cylc conditions`` + - See the `license`_ file for conditions of usage, or ``cylc help license`` + - The Cylc license remains unchanged from Cylc 7. +``cylc get-config``, + - Replaced by ``cylc config``. +``cylc get-*-config`` + - (Where ``*`` is ``site``, ``suite`` or ``global``) + - Replaced by ``cylc config``. +``cylc graph-diff`` + - Replaced by ``cylc graph --diff `` +``cylc insert`` + - Task insertion is now automatic, use ``cylc trigger``. +``cylc monitor`` + - There is now a new more powerful terminal user interface (TUI). + - Try ``cylc tui``. +``cylc print`` + - Equivalent to ``cylc scan --states=all``. +``cylc reset`` + - ``cylc reset`` has been replaced by ``cylc set`` + - At Cylc 8 we override task's prerequisites & outputs rather than modifying + the task state directly. +``cylc restart`` + - Replaced by ``cylc play``. +``cylc run`` + - Replaced by ``cylc play``. +``cylc spawn`` + - Spawning is now performed automatically, on demand. Use ``cylc trigger`` to run + a task, or ``cylc set`` to spawn tasks that depend on specified outputs. +``cylc suite-state`` + - Renamed as ``cylc workflow-state``. + +.. rubric:: Commands that have changed: + +``cylc hold`` + - Now used on tasks only; use ``cylc pause`` to pause an entire workflow + (i.e. to halt all job submissions). +``cylc release`` + - Now used only to release held tasks; use ``cylc play`` to resume a paused workflow. + +.. rubric:: Graphical User Interfaces (GUIs): + +The GTK based GUI based GUIs have been removed, please use the new web based +GUI. Consequently the following commands have also been removed: + +- ``cylc gpanel`` +- ``cylc gscan`` +- ``cylc gcylc`` + +The ``cylc gui`` command remains, it launches a standalone version of the +web GUI (providing the `Cylc UI Server`_ is installed). + +Additionally, there are two +":ref:`compound commands `" +which automate common working practices, namely: + +``cylc vip`` + Validate, install and play a workflow. This is similar to what + ``rose suite-run`` did. +``cylc vr`` + Validate, reinstall, then either reload (if the workflow is running) or restart + (if it is stopped) the workflow. This is similar to what + ``rose suite-run --reload`` and ``rose suite-run --restart`` did. + + +Cylc 8 Standardised IDs +----------------------- + +In Cylc 7 there were two ways to specify a task: + +.. code-block:: none + + task.cycle + cycle/task + +In Cylc 8 the former is now deprecated, and the latter has been extended to +provide a unique identifier for all workflows, cycles, tasks and jobs using a +standard format: + +.. code-block:: none + + ~user/workflow//cycle/task/job + +Consequently task IDs have changed: + +.. code-block:: none + + # old + cycle.task + + # new + cycle/task + +An example using ``cylc trigger``: + +.. code-block:: bash + + # old + cylc trigger workflow task.cycle + + # new + cylc trigger workflow//cycle/task + +Cylc 8 still supports the old format, however, the new format unlocks extra +functionality e.g: + +.. code-block:: bash + + # stop all running workflows + cylc stop '*' + + # pause all running workflows + cylc pause '*' + + # (re-)trigger all failed tasks in all running workflows + cylc trigger '*//*:failed' + + # hold all tasks in the cycle "2000" in workflows with IDs + # beginning with "model" + cylc hold 'model*//2000' + + # delete the run directories for all workflows with IDs + # beginning with "model_a/" + cylc clean 'model_a/*' + +For more information run ``cylc help id``. + +.. _ID post on Discourse: https://cylc.discourse.group/t/cylc-8-id-changes/425 + +For a quick overview of the motivation see the `ID post on Discourse`_. diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/compatibility-mode.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/compatibility-mode.rst.txt new file mode 100644 index 00000000000..2d19dea4028 --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/compatibility-mode.rst.txt @@ -0,0 +1,238 @@ +.. _cylc_7_compat_mode: + +Cylc 7 Compatibility Mode +========================= + +.. admonition:: Does This Change Affect Me? + :class: tip + + This will affect you if you want to run Cylc 7 (``suite.rc``) workflows + using Cylc 8. + +Overview +-------- + +Cylc 8 can run most Cylc 7 workflows "as is". +The ``suite.rc`` filename triggers a backward compatibility mode in which: + +- :term:`implicit tasks ` are allowed by default + + - (unless a ``rose-suite.conf`` file is found in the :term:`run directory` + for consistency with ``rose suite-run`` behaviour) + - (Cylc 8 does not allow implicit tasks by default) + +- :term:`cycle point time zone` defaults to the local time zone + + - (Cylc 8 defaults to UTC) + +- waiting tasks are pre-spawned to mimic the Cylc 7 scheduling algorithm and + stall behaviour, and these require + :term:`suicide triggers ` + for alternate :term:`graph branching` + + - (Cylc 8 spawns tasks on demand, and suicide triggers are not needed for + branching) + +- ``succeeded`` task outputs are :ref:`required `, + so in the absence of suicide triggers the scheduler will retain other + :term:`final status` tasks in the :term:`n=0 window ` to stall the + workflow. + + - (in Cylc 8, **all** outputs are *required* unless marked as + :ref:`*optional* ` by the new ``?`` syntax) + + +.. _compat_required_changes: + +Required Changes +---------------- + +Providing your Cylc 7 workflow does not use syntax that was deprecated at Cylc 7, +you may be able to run it using Cylc 8 without any modifications while in +compatibility mode. + +First, run ``cylc validate`` **with Cylc 7** on your ``suite.rc`` workflow +to check for deprecation warnings and fix those before validating with Cylc 8. +See :ref:`below ` for an example. + +.. warning:: + + ``cylc validate`` operates on the processed ``suite.rc``, which + means it will not detect any deprecated syntax that is inside a + currently-unused Jinja2/EmPy ``if...else`` branch. + +Some workflows may require modifications to either upgrade to Cylc 8 or make +interoperable with Cylc 8 backward compatibility mode. Read on for more details. + + +Cylc commands in task scripts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Check for any use of Cylc commands in task scripting. Some Cylc 7 commands +have been removed and some others now behave differently. +However, ``cylc message`` and ``cylc broadcast`` have *not* changed. +See the :ref:`full list of command line interface changes` +and see :ref:`below ` for an example. + + +Python 2 to 3 +^^^^^^^^^^^^^ + +Whereas Cylc 7 runs using Python 2, Cylc 8 runs using Python 3. This affects: +- modules imported in Jinja2 +- Jinja2 filters, tests and globals +- custom xtrigger functions + +Note that task scripts are not affected - they run in an independent +environment. + +See :ref:`py23` for more information and examples of how to implement +interoperability if your workflows extend Cylc or Jinja2 with custom Python scripts. + + +Other caveats +^^^^^^^^^^^^^ + +- Cylc 8 cannot *restart* a partially completed Cylc 7 workflow in-place. If + possible, complete the run with Cylc 7. Otherwise, see + :ref:`compat_continuing_c7_with_c8`. + +- Cylc 8 only transfers certain files and directories by default during + remote installation. See :ref:`728.remote-install` for more information. + +- Cylc 8 does not support + :ref:`excluding/including tasks at start-up`. + If your workflow used this old functionality, it may have been used in + combination with the ``cylc insert`` command (which has been removed from + Cylc 8) and ``cylc remove`` (which still exists but is much less needed). + +- Cylc 8 does not support :ref:`specifying remote usernames <728.remote_owner>` + using :cylc:conf:`flow.cylc[runtime][][remote]owner`. + + +Examples +-------- + +.. _compat.eg.c7val: + +Validating with Cylc 7 +^^^^^^^^^^^^^^^^^^^^^^ + +Consider this configuration: + +.. code-block:: cylc + :caption: ``suite.rc`` + + [scheduling] + initial cycle point = 11000101T00 + [[dependencies]] + [[[R1]]] + graph = task + + [runtime] + [[task]] + pre-command scripting = echo "Hello World" + +Running ``cylc validate`` at **Cylc 7** we see that the +workflow is valid, but we are warned that ``pre-command scripting`` +was replaced by ``pre-script`` at 6.4.0: + +.. code-block:: console + :caption: Cylc 7 validation + + $ cylc validate . + WARNING - deprecated items were automatically upgraded in 'suite definition': + WARNING - * (6.4.0) [runtime][task][pre-command scripting] -> [runtime][task][pre-script] - value unchanged + Valid for cylc-7.8.7 + +.. note:: + + **Cylc 7** has handled this deprecation for us, but at **Cylc 8** this + workflow will fail validation. + + .. code-block:: console + :caption: Cylc 8 validation + + $ cylc validate . + IllegalItemError: [runtime][task]pre-command scripting + +You must change the configuration yourself. In this case: + +.. code-block:: diff + + - pre-command scripting = echo "Hello World" + + pre-script = echo "Hello World" + +Validation will now succeed. + + +.. _compat.eg.cylc-commands: + +Cylc commands in task scripts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You might have a task script that calls a Cylc command like so: + +.. code-block:: cylc + + [runtime] + [[foo]] + script = cylc hold "$CYLC_SUITE_NAME" + +The ``cylc hold`` command has changed in Cylc 8. It is now used for holding +tasks only; use ``cylc pause`` for entire workflows. +(Additionally, ``$CYLC_SUITE_NAME`` is deprecated in favour of +``$CYLC_WORKFLOW_ID``, though still supported.) + +In order to make this interoperable, so that you can run it with both Cylc 7 +and Cylc 8 backward compatibility mode, you could do something like this +in the bash script: + +.. code-block:: cylc + + [runtime] + [[foo]] + script = """ + if [[ "${CYLC_VERSION:0:1}" == 7 ]]; then + cylc hold "$CYLC_SUITE_NAME" + else + cylc pause "$CYLC_WORKFLOW_ID" + fi + """ + +Note this logic (and the ``$CYLC_VERSION`` environment variable) is executed +at runtime on the :term:`job host`. + +Alternatively, you could use :ref:`Jinja` like so: + +.. code-block:: cylc + + [runtime] + [[foo]] + {% if CYLC_VERSION is defined and CYLC_VERSION[0] == '8' %} + script = cylc pause "$CYLC_WORKFLOW_ID" + {% else %} + script = cylc hold "$CYLC_SUITE_NAME" + {% endif %} + +Note this logic (and the ``CYLC_VERSION`` Jinja2 variable) is executed locally +prior to Cylc parsing the workflow configuration. + + +Renaming to ``flow.cylc`` +------------------------- + +When your workflow runs successfully in backward compatibility mode, it is +ready for renaming ``suite.rc`` to ``flow.cylc``. Doing this will turn off +backward compatibility mode, and validation in Cylc 8 will show +deprecation warnings. + +.. seealso:: + + :ref:`configuration-changes` + +.. important:: + + More complex workflows (e.g. those with suicide triggers) may + fail validation once backward compatibility is off - see + :ref:`728.optional_outputs` diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/config-changes.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/config-changes.rst.txt new file mode 100644 index 00000000000..ea304c2c28a --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/config-changes.rst.txt @@ -0,0 +1,124 @@ +.. _configuration-changes: + +Configuration Changes at Cylc 8 +=============================== + +Some configurations have moved or been renamed at Cylc 8. + +The old configurations are now deprecated, but still supported. +These will be highlighted upon ``cylc validate`` after renaming ``suite.rc`` +to ``flow.cylc``. + +Because some workflows use Jinja2 or EmPy branches which may not be switched on at +the time of the initial ``cylc validate`` we have also provided +a script, :ref:`cylc lint -r 728 ` to check for Cylc 7 +syntax which may be deprecated. + +There are some examples below of how to upgrade: + + +.. _7-to-8.graph_syntax: + +Graph +----- + +Cylc 7 had unnecessarily deep nesting of graph config sections: + +.. code-block:: cylc + + [scheduling] + initial cycle point = now + [[dependencies]] + [[[R1]]] + graph = "prep => foo" + [[[R/^/P1D]]] + graph = "foo => bar => baz" + +Cylc 8 cleans this up: + +.. code-block:: cylc + + [scheduling] + initial cycle point = now + [[graph]] + R1 = "prep => foo" + R/^/P1D = "foo => bar => baz" + + +Fixing deprecation warnings +--------------------------- + +Take the following example ``flow.cylc`` file: + +.. code-block:: cylc + + [cylc] + UTC mode = True + [scheduling] + initial cycle point = 2000-01-01 + [[dependencies]] + [[[R1]]] + graph = foo => bar + [runtime] + [[foo, bar]] + +This workflow will pass validation at Cylc 8, but will give warnings: + +.. code-block:: console + + $ cylc validate . + WARNING - deprecated items were automatically upgraded in "workflow definition" + WARNING - * (8.0.0) [cylc] -> [scheduler] - value unchanged + WARNING - deprecated graph items were automatically upgraded in "workflow definition": + * (8.0.0) [scheduling][dependencies][X]graph -> [scheduling][graph]X - for X in: + R1 + Valid for cylc-8.0.0 + +The warnings explain what needs to be fixed. After making the following changes, +the workflow will validate without any warnings: + +.. code-block:: diff + + -[cylc] + +[scheduler] + UTC mode = True + [scheduling] + initial cycle point = 2000-01-01 + - [[dependencies]] + - [[[R1]]] + - graph = foo => bar + + [[graph]] + + R1 = foo => bar + [runtime] + [[foo, bar]] + +.. tip:: + + Later Cylc releases will not be able to upgrade obsolete Cylc 7 + configurations. It's a good idea to address warnings as part of routine + workflow review and maintenance to avoid problems later on. + + +Platforms +--------- + +.. seealso:: + + - :ref:`Platforms at Cylc 8. ` + - :ref:`System admin's guide to writing platforms. ` + +At Cylc 7, job hosts were defined to indicate where a job should run. +At Cylc 8, this has been replaced by Platforms. + +.. code-block:: diff + + [runtime] + [[foo]] + - [[[job]]] + - batch system = slurm + - [[[remote]]] + - host = hpc1.login.1 + + platform = hpc1 + +For a comprehensive list of valid configuration, see: :ref:`workflow-configuration` +and :ref:`global-configuration`. diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/continuing-c7-c8.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/continuing-c7-c8.rst.txt new file mode 100644 index 00000000000..1e074aad4f8 --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/continuing-c7-c8.rst.txt @@ -0,0 +1,46 @@ +.. _compat_continuing_c7_with_c8: + +Continuing a Cylc 7 Workflow with Cylc 8 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. admonition:: Does This Change Affect Me? + :class: tip + + Read this if you have a partially complete Cylc 7 workflow that you want to + continue, rather than start from scratch, with Cylc 8. Some cycling + workflows, for example, may need to run expensive "cold start" tasks and + incur a multi-cycle spin-up if started from scratch. + +.. warning:: + + Cylc 8 cannot restart a Cylc 7 workflow in-place, and continuing in a new + run directory involves some careful set up (below). So, **if possible you + should complete the run with Cylc 7**. + + +To continue a Cylc 7 workflow with Cylc 8: + +1. Stop the Cylc 7 workflow at an convenient place + + - Typically the end of a cycle point, to simplify the continuation +2. :ref:`Install ` a new instance of the workflow from + source, with Cylc 8 + + - Adapt file paths to the new run directory structure, in workflow and task + configurations + - Note Cylc 8 does :ref:`remote file installation <728.remote-install>` + when a job is first submitted to a platform +3. Copy runtime files needed by upcoming tasks from the old to the new run + directory + + - This could include external files installed by initial tasks at runtime + - Note different files could be present on different job platforms +4. Start the new Cylc 8 run at the appropriate cycle point or task(s) in the + graph + + - Don't reset the :term:`initial cycle point` (in the ``flow.cylc`` or on + the command line) to the :term:`start point ` of the + Cylc 8 run. That would result in the "cold start" that this continuation + procedure is designed to avoid. Instead use the ``--start-cycle-point`` + option (or ``--start-task``) with ``cylc play``, to start at the right + place within the graph. diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/cylc-install.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/cylc-install.rst.txt new file mode 100644 index 00000000000..361948002d2 --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/cylc-install.rst.txt @@ -0,0 +1,205 @@ +.. _MajorChangesInstall: + +Cylc Install +============ + +.. seealso:: + + :ref:`User Guide: Installing Workflows ` + +.. admonition:: Does This Change Affect Me? + :class: tip + + **Almost certainly.** + + This change will affect you: + + - If you use ``rose suite-run`` to install and run Cylc workflows. + - If you usually develop Cylc workflows in the ``~/cylc-run`` directory. + - If you develop Cylc workflows outside of the ``~/cylc-run`` directory and + manually copy the files to ``~/cylc-run``. + + +Overview +-------- + +Cylc 7 ran workflows in ``~/cylc-run/``. You could develop your +workflow in ``~/cylc-run`` or copy it after developing it elsewhere. +If you developed in the ``~/cylc-run`` directory there was a risk that +Cylc might alter your files. If you developed elsewhere you needed to +install your workflows manually with another tool. + +We designed Cylc 8 to help you keep your development and +running copies separate. By default you can now develop workflows in the +``~/cylc-src`` directory. As a result, you will not change your development +copy by running a workflow. You will, however, need to install your workflow +from ``~/cylc-src`` to ``~/cylc-run`` using the ``cylc install`` command. + +.. note:: + + If you have previously used Rose, ``cylc install`` functions in a + similar way to ``rose suite-run --install-only``. + +Examples: + +- You can install a workflow from inside the source directory: + + .. code-block:: console + + $ cd ~/cylc-src/my-workflow + $ cylc install + INSTALLED my-workflow/run1 from /home/me/cylc-src/my-workflow + +- You can install a workflow by providing the workflow source name + (if the source directory is located in any of the + :ref:`configurable source dirs`, e.g. ``~/cylc-src``): + + .. code-block:: console + + $ cylc install my-workflow + INSTALLED my-workflow/run2 from /home/me/cylc-src/my-workflow + +- You can install a workflow by providing the path to the source directory: + + .. code-block:: console + + $ cylc install ~/cylc-src/my-workflow + INSTALLED my-workflow/run3 from /home/me/cylc-src/my-workflow + +.. note:: + + Each time you run ``cylc install`` for a particular workflow, a new copy of + the workflow is installed to a new run directory. In the example above, we + created three run directories inside ``~/cylc-run/my-workflow``. + +Once you have installed a workflow you can use ``cylc play`` to run it - see +:ref:`RunningWorkflows`. + +You can delete installed workflows using ``cylc clean`` - see +:ref:`Removing-workflows`. + +A ``.cylcignore`` file can be used to control which files ``cylc install`` +transfers to the installed workflow, see :ref:`File Installation` for details. + + +.. _728.remote-install: + +Remote Installation +------------------- + +Remote file installation does not occur until running the workflow. +When the first task runs on a remote platform, Cylc will transfer files from +the :term:`run directory` to the :term:`install target`. + +If you have used Rose 2019, you may be used to all files and directories in +the run directory being included. +However, Cylc 8 will only copy the ``ana``, ``app``, ``bin``, ``etc`` and +``lib`` directories by default (in addition to authentication files in +``.service``). +If you want to include custom files and directories in remote installation, +use :cylc:conf:`flow.cylc[scheduler]install`. + +.. tip:: + + If you need to ensure your workflow is still + :ref:`interoperable ` with Cylc 7, wrap it in a + Jinja2 check like so: + + .. code-block:: cylc + + {% if CYLC_VERSION is defined and CYLC_VERSION[0] == '8' %} + [scheduler] + install = my-dir/, my-file + {% endif %} + +See :ref:`the user guide ` for more details. + +.. warning:: + + If you have tasks that mirror/copy the run directory to a remote platform + (such as `FCM make `__ tasks), this can cause conflicts with + :ref:`symlink directory setup `. + + You can find out if symlink directories are configured for the platform by + running:: + + cylc config -i '[install][symlink dirs][]' + + The recommended workaround is to use a "dummy" task that runs on the + particular platform before any such mirror tasks in order to setup symlink + directories, but without running anything. + + For example: + + .. code-block:: cylc + + [scheduling] + [[graph]] + R1 = hpc_init => fcm_make + + [runtime] + [[hpc_init]] + platform = + script = true + + +Migrating From ``rose suite-run`` +--------------------------------- + +The ``rose suite-run`` command has been replaced by ``cylc install``. + +.. code-block:: bash + + # rose 2019 / Cylc 7 + $ rose suite-run + + # rose 2 / Cylc 8 + $ cylc install + $ cylc play + +Support for the ``rose-suite.conf`` file is provided by the :ref:`Cylc Rose` +plugin which must be installed for Rose integration. + +.. spoiler:: Installation + :class: hint + + See the :ref:`installation` section for instructions. + + If Cylc Rose is installed it should appear in the list of installed + Cylc plugins: + + .. code-block:: console + + $ cylc version --long + 8.0 (/path/to/cylc-8) + + Plugins: + cylc-rose 0.1.1 /path/to/cylc-rose + +Notable differences to ``rose suite-run`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Command line options: + The ``cylc install`` command remembers any options specified on the command + line including Rose optional configurations and template variables and + automatically applies them with future re-installations. +Rose Stem: + The ``rose stem`` command is provided by Cylc Rose. Like ``rose suite-run``, + ``rose stem`` used to install and run workflows. It now only + installs the workflow which can then be run with ``cylc play``. + + See the :ref:`Rose Stem` documentation for more information. +Roses directory: + By default ``cylc install`` looks for workflows in ``~/cylc-src``, you + you may want to add ``~/roses`` to the list of + :cylc:conf:`global.cylc[install]source dirs`. +Remote Installation: + With Rose 2019 / ``rose suite-run``, files were installed on remote platforms + before the *workflow* started running. + + With Rose 2 / ``cylc install``, files are installed on remote platforms just + before the *first task* runs on that platform. + + Rose used to install the entire workflow :term:`run directory` to remote + platforms. It now only installs configured directories for efficiency. + See `Remote Installation`_ above for details. diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/excluding-tasks.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/excluding-tasks.rst.txt new file mode 100644 index 00000000000..e3cefa66cda --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/excluding-tasks.rst.txt @@ -0,0 +1,43 @@ +.. _MajorChangesExcludingTasksAtStartup: + +Excluding Tasks at Start-up is Not Supported +============================================ + +.. admonition:: Does This Change Affect Me? + :class: tip + + This will affect you if your workflows use the following configurations: + + * ``[scheduling][special tasks]include at start-up`` + * ``[scheduling][special tasks]exclude at start-up`` + + +Overview +-------- + +The Cylc 7 scheduler allowed you to exclude tasks from the scheduler at start-up: + +.. code-block:: cylc + + # Cylc 7 only + [scheduling] + [[special tasks]] + include at start-up = foo, bar, baz # Cylc 8 ERROR! + exclude at start-up = bar # Cylc 8 ERROR! + +The first config item above excludes all task names not in the include-list; +the second excludes specific tasks that would otherwise be included. + +The Cylc 7 scheduler started up with an instance of every task in its "task +pool", and the workflow evolved by each task spawning its own next-cycle +instance at the right time. So, if you excluded a task a start-up it would not +run in the workflow at all unless manually inserted later at runtime. + +The Cylc 8 scheduler starts up with only the initial tasks in the graph and the +workflow evolves by spawning new tasks on demand as dictated by the graph. +Consequently excluding a task at start up as described above would have no +effect at all on most tasks. + +This feature also predated the current Cylc dependency graph configuration. To +exclude tasks now without entirely removing them from the workflow definition, +just comment them out of the graph. diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/index.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/index.rst.txt new file mode 100644 index 00000000000..ef14eb5acfb --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/index.rst.txt @@ -0,0 +1,15 @@ +Detailed Description of Major Changes +===================================== + +This section goes into detail on some of the major changes that you may need to +understand to migrate from Cylc 7 to Cylc 8. + +.. toctree:: + :maxdepth: 1 + :glob: + + * + +.. TODO - Split into breaking changes and other Major Changes + +.. TODO - Add a page with a Cylc 7 suite needing upgrading. diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/parameters.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/parameters.rst.txt new file mode 100644 index 00000000000..c1ed14d96a7 --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/parameters.rst.txt @@ -0,0 +1,100 @@ +Parameters +========== + +.. admonition:: does this change affect me? + :class: tip + + If you use Cylc parameters with negative offsets (e.g. ``foo``). + + +Overview +-------- + +There has been a subtle change in the way negative offsets are handled in parameters. + + +Example +------- + +If you have a parameter ``x`` with the values 1, 2 & 3: + +.. code-block:: cylc + + [task parameters] + x = 1..3 + +And use it like so: + +.. code-block:: cylc-graph + + a => b => c + +There is some ambiguity about how this should be interpreted when ``x=1`` +because ```` would be ``0`` which is not a valid value for the parameter +``x``. + +Cylc 7 removed the part of the expression which was out of range resulting in a +partial evaluation of that line: + +.. code-block:: cylc-graph + + b_x1 => c_x1 # x=1 + a_x1 => b_x2 => c_x2 # x=2 + a_x2 => b_x3 => c_x3 # x=3 + +Whereas Cylc 8 will remove everything after the first out-of-range parameter - ```` (so the entire line for this example): + +.. code-block:: cylc-graph + + a_x1 => b_x2 => c_x2 # x=2 + a_x2 => b_x2 => c_x2 # x=3 + + +Migration +--------- + +If your workflow depends on the Cylc 7 behaviour, then the solution is +to break the expression into two parts which Cylc will then evaluate separately. + +.. code-block:: diff + + - a => b => c + + a => b + + b => c + +Resulting in: + +.. code-block:: cylc-graph + + # a => b + a_x1 => a_x2 # x=2 + a_x2 => a_x3 # x=3 + + # b => c + b_x1 => c_x1 # x=1 + b_x2 => c_x2 # x=2 + b_x3 => c_x3 # x=3 + + +Line Breaks +----------- + +Note that these expressions are all equivalent: + +.. list-table:: + :class: grid-table + + * - .. code-block:: + + a => b => c + + - .. code-block:: + + a => + b => + c + + - .. code-block:: + + a => b => \ + c diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/platforms.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/platforms.rst.txt new file mode 100644 index 00000000000..d97f26dbb4b --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/platforms.rst.txt @@ -0,0 +1,262 @@ +.. _MajorChangesPlatforms: + +Platforms +========= + +.. admonition:: Does This Change Affect Me? + :class: tip + + Cylc platforms are a new feature which replace the task ``job`` and + ``remote`` configuration sections: + + * :cylc:conf:`[runtime][][job]` + * :cylc:conf:`[runtime][][remote]` + + +Overview +-------- + +.. note:: + + - The terms :term:`platform` and job platform are equivalent. + - The terms :term:`job runner` (in Cylc 8 configurations) and batch system + (in Cylc 7 configurations) are equivalent. + +Submitting a job to a :term:`job runner` may require configuration. + +In Cylc 7 this configuration must be provided for each task in the workflow +configuration (``suite.rc``). + +In Cylc 8 "platforms" can be defined in the global configuration +(:cylc:conf:`global.cylc`) so that this configuration doesn't have to be +repeated for each task in each workflow. + +There may be cases where sets of platforms (for example a group of +standalone compute servers, or a pair of mirrored HPC's) might be equally +suitable for a task. Such platforms can be set up to be ``platform groups`` + +.. seealso:: + + :ref:`ListingAvailablePlatforms` for details of how to list platforms + already defined. + + :ref:`AdminGuide.PlatformConfigs` for detailed examples of platform + configurations. + +.. tip:: + + Cylc 8 contains upgrade logic (:ref:`see below `) + which handles the deprecated Cylc 7 settings in most cases. + Unless you are in :ref:`backward compatibility mode `, + you should upgrade to using platforms instead. + Deprecated settings will be removed in a later release of Cylc. + + +What is a Platform? +------------------- + +A "platform" represents one or more hosts from which jobs can be submitted to or +polled from a common job submission system. + +If a platform has multiple hosts Cylc will automatically select a host when +needed and will fallback to other hosts if it is not contactable. + +A "platform group" represents a collection of independent platforms. Cylc will +automatically select a platform and will fallback to other platforms in the +group (for appropriate operations) if the platform is not contactable. + + +Examples +-------- + +.. seealso:: + + :cylc:conf:`global.cylc[platforms]` has a detailed explanation of how + platforms and platform groups are defined. + +Simple example +^^^^^^^^^^^^^^ + +Consider this Cylc 7 syntax in a ``flow.cylc`` file: + +.. code-block:: cylc + + [runtime] + [[mytask]] + [[[job]]] + batch system = slurm + [[[remote]]] + host = login_node01 + +The Cylc 8 global config (``global.cylc``) might contain: + +.. code-block:: cylc + + [platforms] + [[our_cluster]] + hosts = login_node01, login_node02 + job runner = slurm + +.. tip:: + + You can view the platforms available at your site by running:: + + cylc config --platforms + +The platform ``our_cluster`` matches the current configuration due to having +the same job runner (batch system) and correct hosts. Thus we can replace the +deprecated syntax: + +.. code-block:: diff + + [runtime] + [[mytask]] + - [[[job]]] + - batch system = slurm + - [[[remote]]] + - host = login_node01 + + platform = our_cluster + + +A variety of other examples +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Here are some example Cylc 7 task definitions: + +.. code-block:: cylc + + [runtime] + [[mytask_cylc_server]] + + [[mytask_big_server]] + [[[remote]]] + host = linuxbox42 + + [[mytask_submit_local_to_remote_computer]] + [[[job]]] + batch system = pbs + + [[mytask_login_to_hpc_and_submit]] + [[[remote]]] + # e.g. rose host-select + host = $(supercomputer_login_node_selector_script) + [[[job]]] + batch system = slurm + + +This will result in Cylc running: + +- ``mytask_cylc_server`` on the machine the workflow is running on. +- ``mytask_big_server`` on ``linuxbox42``, using background. +- ``mytask_submit_local_to_remote_computer`` on a system where you can + use PBS to submit from the workflow server. +- ``mytask_login_to_hpc_and_submit`` on a host set by the subshelled + script using Slurm. + +At Cylc 8 the equivalent might be: + +.. code-block:: cylc + + [runtime] + [[mytask_cylc_server]] + + [[mytask_big_server]] + platform = linuxbox42 + + [[mytask_submit_local_to_remote_computer]] + platform = pbs_local + + [[mytask_login_to_hpc_and_submit]] + # Recommended: + platform = slurm_supercomputer + # ...but This is still legal: + #platform = $(selector-script) + +And the platform settings for these examples might be: + +.. code-block:: cylc + + [platforms] + [[linuxbox\d\d]] # Regex to allow any linuxboxNN to use this definition + # Without a hosts, platform name is used as a single host. + + [[pbs_local]] + # A computer with PBS, that takes local job submissions + job runner = pbs + hosts = localhost + install target = localhost + + [[slurm_supercomputer]] + # This computer with Slurm requires you to use a login node. + hosts = login_node01, login_node02 # Cylc will pick a host. + job runner = slurm + + +Note that in these examples, it is assumed that ``linuxboxNN``, ``pbs_local`` and +``slurm_supercomputer`` have distinct file systems. +Sets of platforms which share a file system must specify +a single :ref:`install target `. + +.. note:: + If an install target is not set, a platform will use its own platform name + as the install target name. If multiple platforms share a file system + but have separate :ref:`install targets ` task initialization + will fail. + +.. _host-to-platform-logic: + +How Cylc 8 handles host-to-platform upgrades +-------------------------------------------- + +If you are using the deprecated ``[remote]`` and ``[job]`` runtime sections, +Cylc 8 will attempt to find a platform which matches the task specification. + +.. important:: + + Cylc 8 needs platforms matching the Cylc 7 job configuration to be + available in :cylc:conf:`global.cylc[platforms]`. + + +Example +^^^^^^^ + +If, for example you have a **Cylc 8** ``global.cylc`` with the following +platforms section: + +.. code-block:: cylc + + [platforms] + [[supercomputer_A]] + hosts = localhost + job runner = slurm + install target = localhost + [[supercomputer_B]] + hosts = tigger, wol, eeyore + job runner = pbs + +And you have a workflow runtime configuration: + +.. code-block:: cylc + + [runtime] + [[task1]] + [[[job]]] + batch system = slurm + [[task2]] + [[[remote]]] + host = eeyore + [[[job]]] + batch system = pbs + +Then, ``task1`` will be assigned platform +``supercomputer_A`` because the specified host (implicitly ``localhost``) +is in the list of hosts for ``supercomputer_A`` **and** the batch system is the same. +Likewise, ``task2`` will run on ``supercomputer_B``. + +.. important:: + + For simplicity, and because the ``host`` key is a special case (it can + match and host in ``[platform]hosts``) we only show these two config keys + here. In reality, **Cylc 8 compares the whole of** + ``[][job]`` **and** ``[][remote]`` + **sections and all items must match to select a platform.** diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/play-pause-stop.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/play-pause-stop.rst.txt new file mode 100644 index 00000000000..b7e9d750767 --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/play-pause-stop.rst.txt @@ -0,0 +1,123 @@ +.. _728.play_pause_stop: + +Play Pause Stop +=============== + +.. admonition:: Does This Change Affect Me? + :class: tip + + Yes if you run Cylc workflows. + + +Overview +-------- + +Cylc 8 uses a simplified model for controlling workflows based on the controls +of a tape player. + +There are now three controls, play, pause and stop: + +* When a workflow is playing, the :term:`scheduler` is running. +* When a workflow is paused, no new jobs will be submitted. +* When a workflow is stopped the :term:`scheduler` is no longer running. + +These controls are available in the web GUI or on the command line with the +commands: + +* ``cylc play`` +* ``cylc pause`` +* ``cylc stop`` + +A workflow can be safely played, paused and stopped any number of times without +interrupting the workflow. + + +Re-Running Workflows +-------------------- + +The ``cylc play`` command will always pick up where it left off (a +:term:`restart`). + +If you want to re-run the entire workflow again from the start either: + +* :ref:`Install a new run`. +* Or if you want to keep the data from the old run start a new :term:`flow` at + the beginning of the graph, and stop the original flow. + +It is still possible to re-run workflows in-place in the Cylc 7 manner, however, +this is discouraged. +To do this remove the workflow database as well as any other evidence of the +previous run that is no longer desired: + +.. code-block:: bash + + # remove the workflow database, the work, share and log directories + cylc clean --rm .service/db:work:share:log + + # only remove the worflow database + $ cylc clean --rm .service/db + +Then restart with ``cylc play``. + + +Hold & Release +-------------- + +The ``cylc hold`` and ``cylc release`` commands are still present. These +work on individual tasks rather than the workflow as a whole. + + +Mapping To Old Commands +----------------------- + +.. list-table:: + :class: grid-table + + * - + - **Cylc 7** + - **Rose 2019** + - **Cylc 8** (Rose 2) + + * - Play + - :: + + cylc run + - :: + + rose suite-run + - :: + + cylc play + + * - Pause + - :: + + cylc hold + - :: + + cylc hold + - :: + + cylc pause + + * - Resume + - :: + + cylc release + - :: + + cylc release + - :: + + cylc play + + * - Stop + - :: + + cylc stop + - :: + + rose suite-shutdown + - :: + + cylc stop diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/python-2-3.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/python-2-3.rst.txt new file mode 100644 index 00000000000..aa79f79a59f --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/python-2-3.rst.txt @@ -0,0 +1,144 @@ +.. _py23: + +Python 2 => 3 +============= + +.. admonition:: Does This Change Affect Me? + :class: tip + + This change will affect you if your workflows extend Cylc or Jinja2 with + custom Python scripts. + + This does not impact :term:`task` scripts; Cylc can still run Python 2 + tasks if desired. + + +Overview +-------- + +.. _six: https://pypi.org/project/six/ + +Cylc 7 ran under Python 2; Cylc 8 runs under Python 3. + +Cylc can be extended with custom Python scripts. These scripts are run under +the same version of Python used by Cylc. + +As a result, if you are moving from Cylc 7 to Cylc 8, you must upgrade any +scripts from Python 2 to Python 3 in the process. + +If you want to support both Cylc 7 and 8, you must support both Python 2 and 3. +There are tools to help you do this, e.g. `six`_. + + +Impacted Scripts +---------------- + +The following scripts must be upgraded if used: + +:ref:`CustomJinja2Filters` + These allow you to extend Jinja2 with Python code. + + These scripts are located in the following directories within a workflow: + + * ``Jinja2Filters`` + * ``Jinja2Tests`` + * ``Jinja2Globals`` + +:ref:`Modules imported by Jinja2 ` + Python modules can be imported from Jinja2 e.g: + + .. code-block:: jinja + + {% from "os" import path %} + +:ref:`Custom Trigger Functions` + Any custom xtrigger functions. + + +Package Name Changes +-------------------- + +Three Python packages have been renamed between Cylc 7 and Cylc 8: + +* ``cylc`` => ``cylc.flow`` +* ``isodatetime`` => ``metomi.isodatetime`` +* ``rose`` => ``metomi.rose`` + +If you are importing from these packages you will need to update the package names. + +Here are some examples: + +.. rubric:: Convert Python code from Cylc 7 to Cylc 8: + +.. code-block:: diff + + - from cylc import LOG + + from cylc.flow import LOG + - from isodatetime.data import Duration + + from metomi.isodatetime.data import Duration + +.. rubric:: Python code which supports both Cylc 7 & Cylc 8: + +.. code-block:: python + + import sys + if sys.version[0] == '3': + from cylc.flow import LOG + from metomi.isodatetime.data import Duration + else: + from cylc import LOG + from isodatetime.data import Duration + +.. rubric:: Convert Jinja2 code from Cylc 7 to Cylc 8: + +.. code-block:: diff + + #!Jinja2 + - {% from "cylc" import LOG %} + + {% from "cylc.flow" import LOG %} + {% do LOG.debug("Hello World!") %} + +.. rubric:: Jinja2 code which supports both Cylc 7 & Cylc 8: + +.. code-block:: jinja + + #!Jinja2 + {% from "sys" import version -%} + {% if version[0] == '3' -%} + {% from "cylc.flow" import LOG -%} + {% else -%} + {% from "cylc" import LOG -%} + {% endif -%} + + {% do LOG.debug("Hello World!") %} + + +Jinja2 - integers with leading zeros +------------------------------------ + +Integers with leading zeros in Jinja2 expressions are now illegal and will +cause an error like ``Jinja2Error: expected token 'x', got 'integer'``. +For example: + +.. code-block:: console + + $ cylc validate my-workflow + Jinja2Error: expected token 'end of statement block', got 'integer' + File ~/cylc-run/my-workflow/flow.cylc + {% if START_HOUR == 06 or START_HOUR == 12 %} <-- TemplateSyntaxError + +The solution in this case is: + +.. code-block:: diff + + -{% if START_HOUR == 06 or START_HOUR == 12 %} + +{% if START_HOUR == 6 or START_HOUR == 12 %} + + +Rose +---- + +The same changes also impact Rose extensions: + +* :ref:`Rose Macros ` +* :ref:`Rose Ana Tasks ` diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/remote-owner.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/remote-owner.rst.txt new file mode 100644 index 00000000000..433be640e34 --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/remote-owner.rst.txt @@ -0,0 +1,40 @@ +.. _728.remote_owner: + +Remote Usernames +================ + +.. admonition:: does this change affect me? + :class: tip + + * If you set :cylc:conf:`flow.cylc[runtime][][remote]owner` + * If you use ``--owner`` on the command line + + +Overview +-------- + +If your username differs between the :term:`scheduler` host and job hosts, then +you may have configured Cylc to run jobs under the correct account using +:cylc:conf:`flow.cylc[runtime][][remote]owner` +or used the ``--owner`` Cylc command line option +with commands which access remote hosts. + +.. _SSH configuration file: https://man.openbsd.org/ssh_config + +Cylc no longer supports specifying the username in this way, we suggest +configuring your remote username using the `SSH configuration file`_ e.g: + +.. code-block:: none + + Host MyHost + User root + +SSH will then automatically use the configured username when connecting to the +remote machine. + +Since Cylc uses SSH and Rsync to manage job hosts, the SSH config also configures +Cylc. + +.. note:: + + This approach using the SSH configuration file also works with Cylc 7. diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/scheduling.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/scheduling.rst.txt new file mode 100644 index 00000000000..1da463951d3 --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/scheduling.rst.txt @@ -0,0 +1,47 @@ +.. _728.scheduling_algorithm: + +Scheduling Algorithm +==================== + +.. seealso:: + + Migration Guide: + + * :ref:`728.optional_outputs` + + User Guide: + + * :ref:`User Guide Required Outputs` + * :ref:`User Guide Optional Outputs` + * :ref:`user-guide-reflow` + * :ref:`n-window` + +Cylc can manage infinite workflows of repeating tasks: + +.. image:: ../../img/cycling.png + :align: center + +Cylc 8 has a new scheduling algorithm that: + +- Is much more efficient because it only has to manage active tasks + + - waiting tasks are not pre-spawned before they are needed + - succeeded tasks are not kept across the active task window + - no costly indiscriminate dependency matching is done +- Distinguishes between :term:`optional ` and + :term:`required ` task outputs, to support: + + - :term:`graph branching` without :term:`suicide triggers ` + - correct diagnosis of :term:`workflow completion` +- Causes no implicit dependence on previous-instance job submit + + - instances of same task can run out of cycle point order + - the workflow will not unnecessarily stall downstream of failed tasks +- Provides a sensible active-task based window on the evolving workflow + + - (to fully understand which tasks appeared in the Cylc 7 GUI you had to + understand the scheduling algorithm) +- Supports multiple concurrent :term:`flows` within the same workflow. +- Can start a workflow from any task or tasks in the graph (no need for + checkpoint restart) +- Can limit activity within as well as across cycles, without risking a stall diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/suicide-triggers.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/suicide-triggers.rst.txt new file mode 100644 index 00000000000..c24e925b4c5 --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/suicide-triggers.rst.txt @@ -0,0 +1,110 @@ +.. _728.optional_outputs: + +Graph branching, optional outputs and suicide triggers +====================================================== + +Cylc 8 has a :ref:`new scheduling algorithm <728.scheduling_algorithm>` and +a new syntax for dealing with tasks that may not necessarily complete. +It handles :term:`graphs ` in an event-driven manner which means +that a workflow can follow different paths in different eventualities (without +the need for suicide triggers). This is called :term:`graph branching`. + +.. admonition:: Does This Change Affect Me? + :class: tip + + This change affects you if you are upgrading a Cylc 7 workflow that + contains graph branches that are not necessarily expected to complete + at runtime. You might get a ``GraphParseError`` during validation with + Cylc 8. + + Typically this will be the case if you are using + :term:`suicide triggers ` (marked by ``!`` before the + task name in the graph, e.g. ``foo:fail => !foo``). + + You should *not* perform this upgrade if still in :ref:`cylc_7_compat_mode` + (``suite.rc`` filename). + + +Required Changes +^^^^^^^^^^^^^^^^ + +Any :term:`task outputs ` that are not necessarily expected to +complete must be marked as :term:`optional ` using ``?``. +Suicide triggers can then be removed. + +Example +^^^^^^^ + +Here is an example Cylc 7 :term:`graph`: + +.. code-block:: cylc-graph + + foo:fail => recover + + foo | recover => bar + + # Remove the "recover" task in the success case. + foo => ! recover + # Remove the "foo" task in the fail case. + recover => ! foo + +.. digraph:: Example + :align: center + + subgraph cluster_1 { + label = ":fail" + color = "red" + fontcolor = "red" + style = "dashed" + recover + } + + foo -> recover + recover -> bar [arrowhead="onormal"] + foo -> bar [arrowhead="onormal" weight=2] + +Validating this with Cylc 8 will give an error: + +.. code-block:: console + + $ cylc validate . + GraphParseError: Opposite outputs foo:succeeded and foo:failed must both be optional if both are used + +In Cylc 8, all task outputs are :term:`required ` to complete +unless otherwise indicated. However, it is impossible for both ``:succeed`` +and ``:fail`` to occur when a task runs. + +The solution is to mark the outputs which are :term:`optional ` +(in this case ``foo:succeed`` and ``foo:fail``) with a ``?`` in the graph. +Also, the suicide triggers can be removed. + +.. code-block:: diff + + - foo:fail => recover + + foo:fail? => recover + + - foo | recover => bar + + foo? | recover => bar + + - # Remove the "recover" task in the success case. + - foo => ! recover + - # Remove the "foo" task in the fail case. + - recover => ! foo + +In Cylc 7, suicide triggers were used to remove tasks that did not complete +during runtime. Cylc 8's event-driven graph handling allows such graph +branching using optional output syntax, without the need for suicide triggers. +(Suicide triggers are still supported in Cylc 8; however, they are most +likely unnecessary.) + +.. tip:: + + Remember: ``foo?`` is short for ``foo:succeed?``. It is the *output* + that is optional, not the task itself. + +.. seealso:: + + - :ref:`Required ` and + :ref:`optional ` outputs in the User Guide. + + - :ref:`Graph Branching` in the user guide. diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/task-job-states.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/task-job-states.rst.txt new file mode 100644 index 00000000000..3265b1c2710 --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/task-job-states.rst.txt @@ -0,0 +1,24 @@ +.. _728.task_job_states: + +Task/Job States +=============== + +.. seealso:: + + - User Guide :ref:`task-job-states` + +:term:`Tasks ` are nodes in the abstract workflow graph representing +processes that should run once their prerequisites are satisfied. :term:`Jobs +` are the real processes submitted to execute these tasks (or at least, at +the submission stage, real job scripts). A task can have multiple jobs, by +automatic retries and manual re-triggering. + +Cylc 7 had 13 task/job states. The GUI only showed tasks, with job data +from the latest job. + +Cylc 8 has only 8 task/job states. The Cylc 8 UI shows both task and jobs. +Task icons are monochrome circles; job icons are coloured squares. The running +task icon incorporates a radial progress indicator. + +.. image:: ../../img/task-job.png + :align: center diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/template-vars.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/template-vars.rst.txt new file mode 100644 index 00000000000..a97836badaf --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/template-vars.rst.txt @@ -0,0 +1,95 @@ +Template Variables +================== + +.. admonition:: Does This Change Affect Me? + :class: tip + + Read this section if you set Cylc template variables on the command line + using the ``-s``, ``--set`` or ``-set-file`` options. + + This does *not* affect the Rose ``jinja2:suite.rc`` and + ``empy:suite.rc`` variables set using the ``-S`` option to the + ``rose suite-run`` command. + + +Overview +-------- + +Template variables are passed to :ref:`Jinja2 ` or +:ref:`EmPy ` for parsing the workflow definition in the +:cylc:conf:`flow.cylc` file. + +In Cylc 7 template variables could only be strings, in Cylc 8 they can be any +valid Python literal including numbers, booleans, and lists. + + +Changes +------- + +Strings must be explicitly quoted i.e. ``key="value"`` rather than ``key=value``. + + +Example +------- + +.. rubric:: Setting template variables on the command line: + +.. code-block:: bash + + # Cylc 7 + cylc run -s 'FOO=abc' + # Cylc 8 + cylc play -s 'FOO="abc"' + + +.. rubric:: Setting template variables in a "set file" (using ``--set-file``): + +.. code-block:: python + + # Cylc 7 + FOO = abc + BAR = bcd + + # Cylc 8 + FOO = "abc" + BAR = "bcd" + + +New Features +------------ + +Any valid Python literals +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Template variables can now be any valid Python literals e.g: + +.. code-block:: python + + "string" # string + 123 # integer + 12.34 # float + True # boolean + None # None type + [1, 2, 3] # list + (1, 2, 3) # tuple + {1, 2, 3} # set + {"a": 1, "b": 2, "c": 3} # dictionary + +See :ref:`jinja2-template-variables` for more information. + +Shorthand for list of strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: 8.2 + +A new shorthand argument (``-z``/``--set-list``/``--set-template``) +has been introduced allowing easier definition of template +variables containing lists of strings on the command line: + +.. code-block:: shell + + # Before (still works) + cylc --set "X=['a', 'b', 'c']" + + # After + cylc --set-list X=a,b,c diff --git a/nightly_8.4/html/_sources/7-to-8/major-changes/ui.rst.txt b/nightly_8.4/html/_sources/7-to-8/major-changes/ui.rst.txt new file mode 100644 index 00000000000..f867e529c72 --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/major-changes/ui.rst.txt @@ -0,0 +1,87 @@ +.. _728.ui: + +Cylc 8 UIs +========== + +There are two UI options available to monitor and control workflows at Cylc 8. + + +Cylc Tui +-------- + +Cylc Tui (TUI = Terminal User Interface) is a command line version of the GUI +which comes packaged with the Cylc scheduler. + +It can be used to monitor and control any workflows running under your user +account, trigger tasks, access log files and perform other common activities. + +Start Tui by running the ``cylc tui`` command. + +.. figure:: ../../img/tui-1.png + :figwidth: 80% + :align: center + + Tui showing the details of a failed job. + +.. figure:: ../../img/tui-2.png + :figwidth: 80% + :align: center + + A list of actions that can be performed on the selected task. + +.. figure:: ../../img/tui-3.png + :figwidth: 80% + :align: center + + Tui displaying the workflow configuration. It can also show scheduler and + job log files. + +Tui replaces the Cylc 7 ``cylc monitor`` command. + + +Cylc Web GUI +------------ + +The Cylc GUI application is a monitoring and control application which runs in +a web browser, it is distributed in the `Cylc UI Server`_ package which comes +separately from the core scheduler. + +Start the GUI server and open the web app in your browser by running +``cylc gui``. + +.. figure:: ../../img/cylc-ui-dash.png + :figwidth: 80% + :align: center + + The GUI homepage. + +.. figure:: ../../img/cylc-ui-tree.png + :figwidth: 80% + :align: center + + The GUI displaying a workflow using the "tree" view. + +See :ref:`UI_Server_config` for how to configure the GUI. + +As some workflows can be very large, or even infinite, the GUI uses a "window" +system to determine what to display. For more information, see :ref:`n-window`. + + +Cylc Hub +-------- + +The Cylc 8 GUI can be deployed with Jupyter Hub to support multi-user access +where it is possible to grant users the permission to view and interact with +workflows running under other user accounts. In these deployments, users will +have to authenticate when they open the GUI in the browser. + +The central server is started by the ``cylc hub`` command. + +.. figure:: ../../img/hub.png + :figwidth: 80% + :align: center + + The Jupyter Hub authentication page in a multi-user setup. + +Multi-user setups need to be configured by site administrators, for more +information see :ref:`cylc.uiserver.multi-user`. diff --git a/nightly_8.4/html/_sources/7-to-8/summary.rst.txt b/nightly_8.4/html/_sources/7-to-8/summary.rst.txt new file mode 100644 index 00000000000..9852eb92130 --- /dev/null +++ b/nightly_8.4/html/_sources/7-to-8/summary.rst.txt @@ -0,0 +1,264 @@ +.. _728.overview: + +Summary Of Major Changes +======================== + +Terminology +----------- + +Cylc now uses more widely understood terms for several core concepts. + +.. table:: + + ============= ============== + Cylc 7 Term Cylc 8 Term + ============= ============== + suite *workflow* + batch system *job runner* + suite daemon *scheduler* + ``suite.rc`` ``flow.cylc`` + ============= ============== + +Note the configuration filename is now ``flow.cylc``, not ``suite.rc``. + +Cylc 7 Compatibility Mode +------------------------- + +Continuing to use the old ``suite.rc`` filename triggers a :ref:`backward +compatibility mode` in Cylc 8 which supports Cylc 7 +workflow configurations out of the box, with +:ref:`some caveats `. However, to future-proof +your workflow and take full advantage of Cylc 8 you should upgrade to Cylc 8 syntax. + +Upgrading To Cylc 8 +------------------- +.. seealso:: + + * Major Changes: :ref:`configuration-changes` + * Major Changes: :ref:`cylc_7_compat_mode` + +There have been some configuration changes at Cylc 8. +To upgrade your Cylc 7 suite to a Cylc 8 workflow, first make sure it validates +in Cylc 7 without any warnings, then rename the workflow configuration file +from ``suite.rc`` to ``flow.cylc``, then run ``cylc validate`` in Cylc 8 and +take action on any warnings. + +.. TODO Add ref to breaking changes section within Major changes, once created, + including optional ouputs. + +.. note:: + + Validation warnings use a :ref:`shorthand notation` + to refer to nested configuration settings on a single line, like this: + ``[section][sub-section]item``. + + +New Web and Terminal UIs +------------------------ +.. seealso:: + + * Major Changes: :ref:`728.ui` + +At Cylc 8, there are two UIs available to monitor and control your workflows: + +- a terminal UI application + + .. code-block:: bash + + cylc tui + +- a web based UI application (requires `Cylc UI Server`_) + + .. code-block:: bash + + cylc gui + +Command Changes +--------------- + +``cylc run `` at Cylc 7 has become ``cylc play ``. + +.. seealso:: + + * User Guide: :ref:`WorkflowStartUp` + * Major Changes: :ref:`728.play_pause_stop` + * Major Changes: :ref:`MajorChangesCLI` + +At Cylc 8, use ``cylc pause `` to pause a workflow, halting all job +submission. To restart the workflow, use ``cylc play ``. + +To start a fresh run, use ``cylc install`` and play it safely in the new run +directory. + +(Note that ``cylc hold`` and ``cylc release`` pause and release individual tasks.) + +Task/Job States +--------------- + +:term:`Tasks ` are nodes in the abstract workflow graph, representing +applications to run at the appropriate point in the workflow. A :term:`job ` +is the script (and subsequent process) submitted by Cylc to +actually run the application. A task can have multiple jobs as the result of +automatic retries or manual re-triggering. + + +The 13 task/job states in Cylc 7 have been simplified to 8. Tasks and jobs have been +separated and states of both can be viewed in the GUI. + +.. image:: ../img/task-job.png + :align: center + +For more information, see :ref:`728.task_job_states`. + + +Optional and Required Task Outputs +---------------------------------- + +.. seealso:: + + * Major Changes::ref:`728.optional_outputs` + * User Guide::ref:`User Guide Required Outputs` + * User Guide::ref:`User Guide Optional Outputs` + +By default, all Cylc 8 tasks are required to succeed - i.e., success is +a :term:`required output`. Tasks with :term:`final status` and incomplete +outputs get retained in the :term:`n=0 window ` pending user +intervention, which will :term:`stall` the workflow. + +Alternatively, outputs can be marked as :term:`optional `, +which allows :term:`optional graph branching `. + +This allows the scheduler to correctly diagnose :term:`workflow completion`. + + +Platform Awareness +------------------ + +.. seealso:: + + :ref:`Platforms at Cylc 8.` + +Cylc 7 was aware of individual job hosts - one selected a host using: +``[runtime][][remote]host``. + +Cylc 8 is aware of sets of host settings called +:term:`[job] platforms `. To choose a platform for a task use +``[runtime][]platform`` + +Hosts of a platform must share a file system and :term:`job runner`: +If one host is unavailable Cylc 8 can use other hosts +on the same platform to interact with jobs. + +The same hosts can belong to multiple platforms, for example +you might be able to use the same host to launch both background and Slurm +jobs. + +.. note:: + + Cylc 8 will pick a sensible platform for your Cylc 7 settings, + These deprecated settings will be removed in a future release. + + +Workflow Installation +--------------------- + +Cylc 8 supports workflow installation. + +For users of `Rose`_, this replaces the functionality of ``rose suite-run``. + +Cylc Install +^^^^^^^^^^^^ + +.. seealso:: + + * Major Changes: :ref:`Moving to Cylc Install` + +Cylc install cleanly separates workflow :term:`source directory` from +:term:`run directory`. It installs workflow files ready for ``cylc play``. + +.. code-block:: console + + $ pwd + ~/cylc-src/demo + + $ ls + flow.cylc + + $ cylc install + INSTALLED demo/run1 from /home/oliverh/cylc-src/demo + + $ cylc play demo + ... + demo/run1: oliver.niwa.local PID=6702 + +By default, run numbers increment with each install. + + +File Installation +^^^^^^^^^^^^^^^^^ +When the first job runs on a remote platform (after start-up, or after a ``cylc reload``), a +remote initialization process is triggered to install workflow files there. + +Symlink Dirs +^^^^^^^^^^^^ + +.. seealso:: + + * User Guide: :ref:`SymlinkDirs` + * User Guide: :ref:`RemoteInit` + +Symlinking the workflow directories used by Cylc provides a useful way of +managing disk space. + +These symlinks are created on a per install target basis, as configured in +:cylc:conf:`global.cylc[install][symlink dirs]`. Install targets are managed on +a site level, for more information see :ref:`Install Targets` + +This functionality replaces the Rose ``root dir`` configuration +for Cylc 7 (however, note it does not allow per-workflow configuration). + + +Removing Workflows +------------------ + +Workflows can be deleted with ``cylc clean`` - see :ref:`Removing-workflows`. This +replaces the ``rose suite-clean`` functionality. + +Architecture +------------ + +There have been fundamental changes to the architecture of Cylc. You can read +about the new system design here :ref:`architecture-reference`. + +Scheduling Algorithm +-------------------- + +The scheduling algorithm has been changed, more information is available: +:ref:`728.scheduling_algorithm`. + +Other Changes +------------- + +There are an assortment of other features implemented at Cylc 8. Some noteworthy +minor changes include: + +Runahead Limit + The default runahead limit has been increased from three cycles to five. +Queues + :ref:`InternalQueues` are now more efficient (for the :term:`scheduler`), + we now recommend using queues to restrict the number of running tasks in + situations where graphing may have been used previously. +Time Zones + :cylc:conf:`[scheduler]cycle point time zone` now defaults to UTC, unless you + are working in :ref:`cylc_7_compat_mode`. +Job Scripts + All user-defined task scripting now runs in a subshell, so you can safely + switch Python environments inside tasks without affecting Cylc. + Further information is available in the User Guide: :ref:`JobScripts`. +Packaging + Cylc 8 (and its package dependencies) is now available from Conda Forge and PyPI + for installations into a Python 3 virtual environment. +Remote usernames + If usernames differ on remote job hosts they must now be configured using + an SSH config file rather than the via Cylc 7 ``[remote]owner`` configuration. + See :ref:`728.remote_owner`. diff --git a/nightly_8.4/html/_sources/glossary.rst.txt b/nightly_8.4/html/_sources/glossary.rst.txt new file mode 100644 index 00000000000..bd1aaa8b348 --- /dev/null +++ b/nightly_8.4/html/_sources/glossary.rst.txt @@ -0,0 +1,1769 @@ +.. Glossary Conventions - for consistency + + 1) Linking to other glossary items in the text: + - there's no need to link multiple instances of the same term in the same + paragraph + - but duplicate links may be desirable if further apart + + 2) Examples can be given but should be brief and on point + + 3) "seealso" blocks should contain, in order: + - config reference links + - glossary items not linked in the main text + - documentation links (e.g. User Guide) + - external web site links + + To avoid unnecessarily long lists and repetition don't duplicate glossary + links from the main text + + 4) To avoid surprising users by jumping out of the page, non-glossary links + should: + - primarily be in the "seealso" list + - not look like another glossary term, + e.g. :ref:`Cylc User Guide ` not just :ref:`blah`. + + 5) Use singular rather than plural terms for glossary definitions (e.g. task rather than tasks). + + +.. TODO Add more user guide and config links to all items, where appropriate. + +Glossary +======== + +.. glossary:: + :sorted: + + validation + workflow validation + Validation parses a ``flow.cylc`` file to report any illegal items, + syntax errors, deprecation warnings, and other problems. + + It is done automatically at start up, and should be done manually with + the ``cylc validate`` command after making changes. + + + retry + task retry + try number + Tasks can be configured to retry automatically on failure, one or more + times. They return to the ``waiting`` state with a :term:`clock trigger` + to delay the retry, and only go to the ``failed`` :term:`state ` once the final try fails. + + The task try number increments with every automatic retry, and is + passed to the job environment as ``$CYLC_TASK_TRY_NUMBER``. + + .. seealso:: + + * :ref:`Cylc User Guide ` + + + submit number + task submit number + Every time a task re-runs, whether by automatic :term:`retry` or manual + triggering, its submit number increments. It is passed to + the job environment as ``$CYLC_TASK_SUBMIT_NUMBER``. + + Submit number also appears in the job log path so that job log files + don't get overwritten. + + + active + active task + An active task is a task which is near ready to run, in the process of + running, or which requires user intervention. These are all the tasks + being actively managed by the scheduler at this point in the run. + + Active tasks are: + + - Tasks which have some, but not all of their + :term:`prerequisites ` satisfied. + - ``waiting`` tasks, that are actively waiting on: + + - :term:`xtriggers `. + - :ref:`internal queues ` + - :ref:`runahead limit ` + + - ``preparing`` tasks - i.e. tasks in the process of submitting jobs + - ``submitted`` and ``running`` tasks - i.e. those with active jobs + - tasks that reached a :term:`final status` without completing their + :term:`required outputs ` + (e.g. a task failed where success was required). + + Active tasks are in the ``n=0`` :term:`window ` which means they + will always be displayed in the GUI and Tui. + + The distinction between active and non-active tasks is important for + the computing of the :term:`runahead limit`. + + + active cycle + A cycle point is active if it contains any :term:`active tasks `. + + Active cycles are counted towards the :term:`runahead limit`. + + + window + n-window + active window + The GUI provides a :term:`graph`-based window or view of the workflow at + runtime, including tasks out to ``n`` graph edges from current + :term:`active tasks `. + + Active tasks form the ``n=0`` window. + + .. seealso:: + + * :ref:`Cylc User Guide ` + + + artificial dependency + An artificial :term:`dependency` in the :term:`graph` does not reflect + real dependence between the tasks involved. This can sometimes be + useful but should be avoided if possible. Artificial dependencies muddy + the real dependencies of the workflow and they may unnecessarily + constrain the scheduler. + + In the following :term:`cycling` workflow, if the task ``foo`` does not + actually depend on any real outputs of ``baz`` in the previous cycle, + then the intercycle dependence is artificial. + + .. code-block:: cylc-graph + + P1 = """ + foo => bar => baz + baz[-P1] => foo + """ + + + workflow + cylc workflow + A workflow is a collection of :term:`tasks ` with + :term:`dependencies ` between them that govern the order in + which they can run. + + Cylc workflows are defined in :cylc:conf:`flow.cylc` files. + + For example, the following workflow represents the beer brewing process: + + .. code-block:: cylc + :caption: flow.cylc + + [scheduling] + cycling mode = integer + initial cycle point = 1 + [[graph]] + # repeat this for each batch + P1 = """ + # the stages of brewing in the order they must occur in: + malt => mash => sparge => boil => chill => ferment => rack + # finish the sparge of one batch before starting the next: + sparge[-P1] => mash + """ + + .. admonition:: Cylc 7 + :class: tip + + In Cylc 7 and earlier, "workflows" were referred to as "suites". + + + workflow name + The workflow name is a path relative to the cylc-run directory which + contains one or more workflow :term:`run directories `. + + Tasks can get the workflow name from ``$CYLC_WORKFLOW_NAME`` in their + runtime environment. + + Unlike :term:`workflow id` the name is not always a unique identifier. In + the example below ``run1`` and ``run2`` would both have the same name, + ``my_workflow``: + + .. code-block:: bash + + `- my_workflow + |- runN + |- run1 + `- run2 + + .. note:: + If you are not using named or numbered runs, the workflow name will be + the same as :term:`workflow id`. + + + external trigger + xtrigger + External triggers allow :term:`tasks ` in the :term:`graph` to + depend on external events, such as a file being delivered to some + location, or a database being updated in some way. + + The :term:`scheduler` can repeatedly call a user-supplied Python function + to check that the external event has occurred. + + Cylc has a built in external trigger for triggering off of events in + other workflows. + + .. seealso:: + + * :cylc:conf:`[scheduling][xtriggers]` + * :term:`clock trigger` + * :ref:`Cylc User Guide
` + * :ref:`Cylc User Guide ` + + + queue + internal queue + Internal queues (so called to distinguish them from external batch + queueing systems) limit how many :term:`jobs ` can be + active at once, across defined groups of tasks. + + Use queues prevent large or busy workflows from swamping their + :term:`job platforms ` with too many jobs at once. + + .. seealso:: + + * :cylc:conf:`[scheduling][queues]` + * :ref:`Cylc User Guide ` + + + workflow id + A workflow can be uniquely identified by the relative path between the :term:`cylc-run directory` + (``~/cylc-run``) and its :term:`run directory`. + + This ID is used on the command line and in the GUI, to target the right + workflow. + + For example, the ID of the workflow in ``~/cylc-run/foo/bar/run1`` + is ``foo/bar/run1``. + + Unlike :term:`workflow name` the ID is always a unique identifier. In the + example below each run has a different ID despite sharing the same + :term:`workflow name` (``my_workflow``). + + .. code-block:: bash + + `- my_workflow + |- runN + |- run1 # CYLC_WORKFLOW_ID = my_workflow/run1 + `- run2 # CYLC_WORKFLOW_ID = my_workflow/run2 + + + graph + A workflow graph is defined by one or more :term:`graph strings` + under the :cylc:conf:`[scheduling][graph]` section of a :term:`workflow` definition. + + For example, the following is, collectively, a graph: + + .. code-block:: cylc-graph + + P1D = foo => bar + PT12H = baz + + .. digraph:: Example + :align: center + + size = "7,15" + + subgraph cluster_1 { + label = "2000-01-01T00:00Z" + style = dashed + "01T00/foo" [label="foo\n2000-01-01T00:00Z"] + "01T00/bar" [label="bar\n2000-01-01T00:00Z"] + "01T00/baz" [label="baz\n2000-01-01T00:00Z"] + } + + subgraph cluster_2 { + label = "2000-01-01T12:00Z" + style = dashed + "b01T12/az" [label="baz\n2000-01-01T12:00Z"] + } + + subgraph cluster_3 { + label = "2000-01-02T00:00Z" + style = dashed + "02T00/foo" [label="foo\n2000-01-02T00:00Z"] + "02T00/bar" [label="bar\n2000-01-02T00:00Z"] + "02T00/baz" [label="baz\n2000-01-02T00:00Z"] + } + + "01T00/foo" -> "01T00/bar" + "02T00/foo" -> "02T00/bar" + + + graph string + A graph string is a collection of task :term:`dependencies ` + in the :cylc:conf:`[scheduling][graph]` section of a workflow definition, + with an associated recurrence that defines its sequence of cycle points. + + The example below shows one graph string in a datetime cycling workflow, + with a daily cycle point sequence: + + .. code-block:: cylc-graph + + R/^/P1D = """ + foo => bar => baz & pub => qux + pub => bool + """ + + + cycle + In a :term:`cycling workflow`, cycles are repetitions of a :term:`graph + string`. Each cycle is identified by a :term:`cycle point`. The sequence + of cycle points is defined by the graph string's :term:`recurrence` + pattern. + + This defines the structure of the :term:`graph`. At runtime, however, + Cylc does not impose a global loop over cycles. Each individual task, + with its own cycle point, advances according to its own + :term:`dependencies `. + + For example, in the following workflow each dotted box represents a cycle + and the :term:`tasks` within it are the :term:`tasks` + belonging to that cycle. The numbers (i.e. ``1``, ``2``, ``3``) are the + :term:`cycle points `. + + .. digraph:: Example + :align: center + + size = "3,5" + + subgraph cluster_1 { + label = "1" + style = dashed + "1/foo" [label="foo\n1"] + "1/bar" [label="bar\n1"] + "1/baz" [label="baz\n1"] + } + + subgraph cluster_2 { + label = "2" + style = dashed + "2/foo" [label="foo\n2"] + "2/bar" [label="bar\n2"] + "2/baz" [label="baz\n2"] + } + + subgraph cluster_3 { + label = "3" + style = dashed + "3/foo" [label="foo\n3"] + "3/bar" [label="bar\n3"] + "3/baz" [label="baz\n3"] + } + + "1/foo" -> "1/bar" -> "1/baz" + "2/foo" -> "2/bar" -> "2/baz" + "3/foo" -> "3/bar" -> "3/baz" + "1/bar" -> "2/bar" -> "3/bar" + + + + .. seealso:: + + * :ref:`tutorial-integer-cycling` + * :ref:`tutorial-datetime-cycling` + + + cycling + cycling workflow + A cycling :term:`workflow` in Cylc is defined by a graph of + repeating tasks with individual :term:`cycle points `. + + .. seealso:: + + * :term:`cycle` + + + cycle point + The unique label given to tasks that belong to a particular :term:`cycle`. + For :term:`integer cycling` these will be integers, e.g. ``1``, ``2``, + ``3``, etc. + For :term:`datetime cycling` they will be :term:`ISO 8601` datetimes, + e.g. ``2000-01-01T00:00Z``. + + .. seealso:: + + * :term:`initial cycle point` + * :term:`final cycle point` + * :term:`start cycle point` + + + cycle point time zone + The time zone used for task :term:`cycle points `. + + .. seealso:: + + * :cylc:conf:`flow.cylc[scheduler]cycle point time zone` + + + initial cycle point + In a :term:`cycling workflow ` the initial cycle point is the + first :term:`cycle point` in the :term:`graph`. + + .. seealso:: + + * :cylc:conf:`[scheduling]initial cycle point`. + * :term:`start cycle point` + + + final cycle point + In a :term:`cycling workflow ` the final cycle point, if there + is one, is the last :term:`cycle point` in the :term:`graph`. + + .. seealso:: + + * :cylc:conf:`[scheduling]final cycle point`. + * :term:`stop cycle point` + + + start cycle point + In a :term:`cycling workflow ` the start cycle point is the + :term:`cycle point` where the :term:`scheduler` :term:`starts ` + running the workflow. + + This may be at or after the :term:`initial cycle point`. + + .. seealso:: + + * :term:`stop cycle point` + * :ref:`Cylc User Guide ` + + + stop cycle point + The stop cycle point is the :term:`cycle point` where :term:`scheduler` + stops running the workflow and :term:`shuts down `. + + This may be at or before the :term:`final cycle point`. + + .. seealso:: + + * :term:`start cycle point` + * :ref:`Cylc User Guide ` + + + integer cycling + An integer :term:`cycling workflow` uses integer :term:`cycle points + ` and :term:`recurrences ` (e.g. ``P3`` means + every third cycle). + + .. seealso:: + + * :cylc:conf:`[scheduling]cycling mode` + * :term:`datetime cycling` + * :ref:`Cylc tutorial ` + + + datetime cycling + A datetime :term:`cycling` workflow uses + :term:`ISO 8601 datetime` :term:`cycle points ` + (e.g. ``2000-01-01T00:00Z``) and :term:`recurrences ` + (e.g. ``P3D`` means every third day). + + .. seealso:: + + * :cylc:conf:`[scheduling]cycling mode` + * :term:`integer cycling` + * :ref:`Cylc tutorial ` + + + wallclock time + The actual time (in the real world). + + .. seealso:: + + * :term:`datetime cycling` + * :term:`clock trigger` + + + ISO 8601 + ISO8601 + ISO 8601 is an international standard for writing datetimes, durations, + and :term:`recurrences ` (sequences of datetimes). Cylc uses + ISO 8601 for :term:`datetime cycling`. + + .. seealso:: + + * :term:`ISO 8601 datetime` + * `Wikipedia (ISO 8601) `_ + * `International Organisation For Standardisation + `_ + * `a summary of the international standard date and time notation + `_ + + + ISO 8601 datetime + ISO8601 datetime + A datetime written in the :term:`ISO 8601` format, e.g: + + * ``2000-01-01T00:00Z``: midnight on the 1st of January 2000, UTC. + + .. seealso:: + + * :ref:`Cylc tutorial ` + + + ISO 8601 duration + ISO8601 duration + A duration written in the ISO 8601 format e.g: + + * ``PT1H30M``: one hour and thirty minutes. + + .. seealso:: + + * :term:`ISO 8601` + * :ref:`Cylc tutorial ` + + + recurrence + In a :term:`cycling workflow` a recurrence determines the + sequence of cycle points given to task instances that appear in the + associated :term:`graph string`. + + Recurrences for :term:`datetime cycling` are based on the :term:`ISO8601` + standard. Those for :term:`integer cycling` are designed to have similar + syntax, but are much simpler. + + + exact datetime unit + An exact datetime unit is any unit of a datetime that has a fixed + duration, which does not depend on its position in the calendar. + In Cylc, the following are exact units: + + * second: SI base unit + * minute: 60 seconds + * hour: 60 minutes + * day: 24 hours + * week: 7 days + + .. note:: + Although the :term:`ISO 8601` standard specifies that weeks and days + are :term:`inexact ` due to the possibility of + daylight saving time, leap seconds etc., they are always exact in + Cylc because workflows always maintain the same time zone, and leap + seconds are not supported. + + .. seealso:: + + * :term:`inexact datetime unit` + + + inexact datetime unit + nominal duration + An inexact datetime unit is any unit of a datetime that does not have + a fixed duration; it instead depends on its position in the calendar. + In Cylc, the following are inexact units (when using the Gregorian + calendar): + + * year: either 365 or 366 days depending on whether it is a leap year + * month: between 28 - 31 days depending on the specific month and year + + .. seealso:: + + * :term:`exact datetime unit` + + + clock expire + expired task + Tasks in :term:`datetime cycling` workflows can be configured to *expire* + if the :term:`wallclock time` exceeds some offset from the cycle point. + + Expired is a :term:`final status` - an expired task will not run + even if its :term:`prerequisites ` get satisfied. + + The associated ``:expire`` :term:`output ` can be used to + trigger other tasks. It must be marked as an :term:`optional output`, + i.e. expiry cannot be :term:`required `. + + .. seealso:: + + * :ref:`Cylc User Guide ` + + + clock trigger + Clock triggers connect cycle points to the :term:`wallclock time`, in + :term:`datetime cycling` workflows. Tasks that depend on a clock trigger + will not trigger until the wallclock time is equal to their cycle point + plus or minus some offset. + + .. seealso:: + + * :ref:`Cylc User Guide ` + * :ref:`Cylc Tutorial ` + + + intercycle dependence + intercycle dependency + intercycle trigger + In a :term:`cycling workflow `, intercycle dependence refers to + a :term:`task` depending on other tasks at different cycle points. + + For example, in the following workflow the task ``bar`` depends on + its own previous instance: + + .. code-block:: cylc + + [scheduling] + initial cycle point = 1 + cycling mode = integer + [[graph]] + P1 = """ + foo => bar => baz + bar[-P1] => bar + """ + + .. digraph:: Example + :align: center + + size = "3,5" + + subgraph cluster_1 { + label = "1" + style = dashed + "1/foo" [label="foo\n1"] + "1/bar" [label="bar\n1"] + "1/baz" [label="baz\n1"] + } + + subgraph cluster_2 { + label = "2" + style = dashed + "2/foo" [label="foo\n2"] + "2/bar" [label="bar\n2"] + "2/baz" [label="baz\n2"] + } + + subgraph cluster_3 { + label = "3" + style = dashed + "3/foo" [label="foo\n3"] + "3/bar" [label="bar\n3"] + "3/baz" [label="baz\n3"] + } + + "1/foo" -> "1/bar" -> "1/baz" + "2/foo" -> "2/bar" -> "2/baz" + "3/foo" -> "3/bar" -> "3/baz" + "1/bar" -> "2/bar" -> "3/bar" + + + qualifier + A qualifier is what follows :term:`task` or family :term:`family` names + after a colon ``:`` in :term:`triggers `, in the :term:`graph`, + to specify exactly which :term:`task outputs ` must be + completed for the :term:`dependency` to be satisfied. + + For example, in ``foo:start => bar``, the ``:start`` qualifier means that + the ``started`` output of task ``foo`` must be completed to satisfy the + dependency. + + .. seealso:: + + * :term:`task triggers ` + * :term:`family triggers ` + * :ref:`Cylc tutorial ` + + + future trigger + A future trigger expresses dependence on a task in a "future" + (higher-valued) :term:`cycle point`. + + Here, ``1/bar`` triggers off of ``2/foo``; ``2/bar`` triggers off of + ``3/foo``; and so on: + + .. code-block:: cylc + + [scheduling] + initial cycle point = 1 + cycling mode = integer + [[graph]] + P1 = "foo[+P1] => bar" + + .. seealso:: + + * :term:`intercycle trigger` + + + task + A task represents an activity in a :term:`workflow`. The workflow + definition specifies how tasks depends on other tasks, what they + should do, how and where to run them, and details of their + runtime environment. + + Task definitions are used to create a :term:`job script` that is + executed as a :term:`job` on behalf of the task. + + Tasks submit :term:`jobs `. Each :term:`job` belongs to one task, + but one task can submit multiple :term:`jobs `. + + + task state + A :term:`task` progresses through a series of states in its lifetime. + These include the ``submitted`` state after :term:`job` submission; + ``running`` after execution commences, and ``succeeded`` after + successful job execution. + + .. seealso:: + + * :ref:`Cylc User Guide ` + * :ref:`Cylc tutorial ` + + + implicit task + Implicit tasks are :term:`tasks ` which are not defined in + the :cylc:conf:`[runtime]` section. + + Like regular tasks they :term:`inherit ` from the ``root`` + :term:`family`. + + Implicit tasks submit real jobs that just exit without doing anything + useful. They may be useful placeholders during workflow development but + are not allowed by default because they can be created accidentally by + simply misspelling a task name in the graph or under ``[runtime]``. + + Here ``bar`` is implicit: + + .. code-block:: cylc + + [scheduling] + [[graph]] + R1 = foo & bar + [runtime] + [[foo]] + # eof + + .. seealso:: + + * :cylc:conf:`flow.cylc[scheduler]allow implicit tasks` + * :ref:`Cylc User Guide ` + + .. admonition:: Cylc 7 + :class: tip + + In Cylc 7 and earlier, implicit tasks were known as "naked dummy tasks". + + + work directory + Cylc executes task :term:`jobs ` inside a job-specific working + directory, automatically created under the workflow :term:`run + directory`. + + .. code-block:: sub + + /work// + + Tasks can get their own work directory path at runtime from + the ``CYLC_TASK_WORK_DIR`` environment variable or the Posix ``pwd`` + command. + + .. seealso:: + + * :term:`run directory` + * :term:`share directory` + + + share directory + Cylc automatically creates a share directory inside the workflow + :term:`run directory` as a place to store files that need to be + shared between tasks. + + .. code-block:: sub + + /share + + Tasks can get their own share directory path at runtime from + the ``CYLC_WORKFLOW_SHARE_DIR`` environment variable. + + In cycling workflows files are typically stored in cycle point + sub-directories of the share directory. + + .. seealso:: + + * :term:`run directory` + * :term:`work directory` + + + workflow log + scheduler log + workflow log directory + At runtime the scheduler logs timestamped events and other information to + files under the workflow :term:`run directory`. These logs take the format + --.log, with the latest log being + automatically symlinked to ``/log/scheduler/log`` + + .. code-block:: sub + + /log/scheduler/ + + You can print the scheduler log at the terminal with ``cylc cat-log + ``. + + + job log + job log directory + Task :term:`job` log files are stored in job specific log directories + under the workflow :term:`run directory`. These include: + + ``job`` + The task :term:`job script`. + ``job.out`` + Job stdout. + ``job.err`` + Job stderr. + ``job.status`` + Job status data in case of lost contact with the scheduler. + ``job-activity.log`` + Job data logged by the scheduler, rather than + the job itself, such as output from the job submission command. + ``job.xtrace`` + Debugging information from Bash captured when Cylc is run in + ``--debug`` mode. + + .. code-block:: sub + + /log/job/// + + + You can print job logs at the terminal with ``cylc cat-log + ``. By default this prints ``job.out``. + There are command options to select the other logs. + + + service directory + The hidden service directory, under the workflow :term:`run directory`, + stores information for internal use by Cylc. It is created at + :term:`install` time. + + .. code-block:: sub + + /.service/ + + + contact file + The contact file, in the :term:`service directory`, records information + about a running :term:`scheduler` such as host, TCP port, and process ID. + It is read by Cylc client commands so they can target the right scheduler. + + The contact file is created at scheduler startup and removed on clean + shutdown. If you delete it, the scheduler will (after a delay) notice + this and shut down. + + .. code-block:: sub + + /.service/contact + + .. warning:: + If the scheduler dies in an uncontrolled way, for example if the + process is killed or the host goes down, the contact file may be + left behind. Some Cylc commands automatically detect these files + and remove them, otherwise they should be manually removed. + + + job + Jobs are the real processes that :term:`tasks ` represent in + a :term:`workflow`. In Cylc, they are implemented by :term:`job scripts + ` prepared by the :term:`scheduler`. + + + job script + A Cylc job script is a file containing bash code to implement a task + definition in a workflow. It prepared and submitted to run by the + :term:`scheduler` when the task is ready to run. + + Job scripts can be found in the task :term:`job log directory`. + + + job host + A job host is a compute resource that a :term:`job` runs on. For + example ``node_1`` would be one of two possible job hosts on the + :term:`platform` ``my_hpc`` for the task ``solver`` in the + following workflow: + + .. code-block:: cylc + :caption: global.cylc + + [platforms] + [[my_hpc]] + hosts = node_1, node_2 + job runner = slurm + + .. code-block:: cylc + :caption: flow.cylc + + [runtime] + [[solver]] + platform = my_hpc + + + job submission number + A single :term:`task` may run multiple :term:`jobs ` as a result of + automatic :term:`retries ` or manually retriggering. + The job submission number is incremented each time, starting from 1. + + + job runner + A job runner is a system for submitting task :term:`jobs ` to run on + a :term:`job platform `. + + Cylc supports various job runners, from direct background process + execution to HPC batch queueing systems like PBS and Slurm (these are + also known as *job schedulers* and *resource managers*). + + Job runners are configured on a per-platform basis in ``global.cylc``. + + .. seealso:: + + * :cylc:conf:`global.cylc[platforms][]job runner`. + * :term:`directive` + * `Wikipedia (job scheduler) `_ + + .. admonition:: Cylc 7 + :class: tip + + In Cylc 7 and earlier, job runners were referred to as "batch systems". + + + directive + Directives request task :term:`jobs ` resources such as memory and + node count from external :term:`job runners `. They are job + runner-specific. + + .. seealso:: + + * :cylc:conf:`[runtime][][directives]` + + + platform + job platform + A platform for running Cylc task :term:`jobs ` is primarily defined + by the combination of a :term:`job runner` and a group of :term:`hosts + ` that share a file system. + + For example ``my_hpc`` could be the platform for the task ``solver`` + in the following workflow: + + .. code-block:: cylc + :caption: Global configuration (``global.cylc``) + + [platforms] + [[my_hpc]] + hosts = node_1, node_2 + job runner = slurm + + .. code-block:: cylc + :caption: Workflow configuration (``flow.cylc``) + + [runtime] + [[solver]] + platform = my_hpc + + .. seealso:: + + * :term:`platform group` + + + platform group + A set of :term:`platforms ` grouped under a common name. + + Platforms are configured by :cylc:conf:`global.cylc[platform groups]`. + + + scheduler + The Cylc scheduler is a program responsible for managing a single + Cylc :term:`workflow`. It determines when each :term:`tasks ` is + ready to run, submits its :term:`jobs ` to selected job runners, + tracks job status, maintains the workflow state, and listens for queries + and commands from the user. + + By default, Cylc schedulers run as daemons (and potentially on a remote + host) so they won't be killed if you log out. + + .. seealso:: + + * `Wikipedia: daemon `_ + + .. admonition:: Cylc 7 + :class: tip + + In Cylc 7 and earlier, schedulers were known as "suite daemons". + + + start + startup + This refers to starting a new instance of the Cylc :term:`scheduler` + program to manage a particular :term:`workflow`. This can be from + scratch, for installed workflows that haven't run previously, or to + restart one that shut down prior to :term:`completion `. + + .. seealso:: + + * :term:`cold start` + * :term:`warm start` + * :term:`start task` + * :term:`restart` + * :term:`reload` + * :term:`shutdown` + + + cold start + A cold start is when the :term:`scheduler` :term:`starts ` a + :term:`workflow` at the beginning of :term:`graph`. In a :term:`cycling + workflow` this is determined by the :term:`initial cycle point`. + + This is the default behaviour of ``cylc play`` for an installed workflow + that hasn't run yet. + + To satisfy unbounded :term:`intercycle dependence` in the graph, tasks + prior to the initial cycle point are treated as if they have succeeded. + + .. seealso:: + + * :cylc:conf:`[scheduling]initial cycle point` + * :term:`warm start` + * :term:`start task` + * :term:`restart` + * :term:`shutdown` + + + warm start + A warm start is when the :term:`scheduler` :term:`starts ` a + :term:`cycling workflow` running from a :term:`start cycle point` after + the :term:`initial cycle point`. + + To satisfy unbounded :term:`intercycle dependence` in the graph, tasks + prior to the start cycle point are treated as if they have succeeded. + + .. seealso:: + + * :term:`cold start` + * :term:`start task` + * :term:`restart` + * :term:`shutdown` + + + start task + A start task is :term:`task` in the :term:`graph` from which the + :term:`scheduler` :term:`starts ` running a :term:`workflow` from + scratch. + + Earlier tasks depended on by start tasks are treated as if they have + succeeded. + + .. seealso:: + + * :term:`cold start` + * :term:`warm start` + * :term:`start cycle point` + * :term:`shutdown` + + .. admonition:: Cylc 7 + :class: tip + + Cylc 7 and earlier did not have the capability to start from any task + in the graph. + + + cylc-run directory + This refers to the top level directory for :term:`installed ` workflows: ``~/cylc-run``. + + Cylc can be configured to symlink cylc-run sub-directories to + other locations. + + .. seealso:: + + * :cylc:conf:`global.cylc[install][symlink dirs]`. + * :term:`run directory` + + .. caution:: + + The cylc-run directory should not be confused with specific + :term:`workflow run directories ` below it. + + install + installation + workflow installation + The ``cylc install`` command installs workflow :term:`source files + ` into a new :term:`run directory` under the + :term:`cylc-run directory`. + + .. seealso:: + + * :term:`reinstall` + + install target + Cylc uses install targets to determine which platforms share file systems. + Install targets should normally be managed at site level. They are configured in + :cylc:conf:`global.cylc[platforms][]install target`. + + .. seealso:: + + * :ref:`Install Targets` + + reinstall + reinstallation + The ``cylc reinstall`` command reinstalls workflow :term:`source files + ` into an existing :term:`run directory` under the + :term:`cylc-run directory`. + + .. seealso:: + + * :term:`install` + + + source directory + source workflow + A source directory is any location where :term:`workflows ` are + written and stored in preparation for installation with ``cylc install`` + or reinstallation with ``cylc reinstall``. + + These locations are configurable. The default is ``~/cylc-src``. + + .. seealso:: + + * :term:`run directory` + * :cylc:conf:`global.cylc[install]source dirs` + * :ref:`Installing-workflows` + + + run directory + workflow run directory + This is a location under the :term:`cylc-run directory` that contains the + :term:`installed ` configuration used to run a :term:`workflow`. + + At runtime, task :term:`jobs ` can get their workflow run + directory from the environment variable ``CYLC_WORKFLOW_RUN_DIR``. + + .. seealso:: + + * :term:`source directory` + * :term:`work directory` + * :term:`share directory` + * :term:`job log directory` + + + play + The ``cylc play`` command runs an instance of the :term:`scheduler` + program to :term:`start` or :term:`restart` a :term:`workflow`. + + You can :term:`play`, :term:`pause` and :term:`stop` a :term:`workflow`, + Cylc will always carry on where it left off. + + + pause + When a :term:`workflow` is "paused" the :term:`scheduler` is still + running but it will not submit any new jobs. + + This can be useful if you want to make a change to a running workflow. + + Pause a workflow with ``cylc pause`` and resume it with ``cylc play``. + + .. seealso:: + + * :term:`play` + * :term:`stop` + * :term:`hold` + + + stop + shutdown + A :term:`scheduler` can shut down on request, or automatically on + :term:`workflow completion`. The :term:`workflow` is then stopped and no + further :term:`jobs ` will be submitted. + + By default, the scheduler waits for any submitted or running task + :term:`jobs ` to finish (either succeed or fail) before shutting + down. + + .. seealso:: + + * :term:`play` + * :term:`pause` + * :term:`start` + * :term:`restart` + * :term:`reload` + * :ref:`Tutorial `. + + + restart + When a :term:`stopped ` :term:`workflow` is :term:`played ` + again, the :term:`scheduler` picks up where it left off rather than + starting again from scratch. It also detects any orphaned :term:`jobs + ` that changed state (e.g. succeeded) while the system was down. + + Changes made to the :term:`installed ` :cylc:conf:`flow.cylc` + file will be picked at restart. We recommend that changes are + :term:`reinstalled ` from the workflow :term:`source + directory` before restart, rather than made by editing the installed + files directly. + + .. seealso:: + + * :term:`start` + * :term:`stop` + * :term:`reload` + * :ref:`Tutorial `. + + + reload + :term:`Schedulers ` can reload their :term:`workflow` + configuration from the :term:`installed ` :cylc:conf:`flow.cylc` + file, to pick up changes made at runtime. + + We recommend that changes are :term:`reinstalled ` from the + workflow :term:`source directory` before reload, rather than made by + editing the installed files directly. + + :ref:`RemoteInit` will be redone for each job platform, when the first job is submitted there after a reload. + + Any :term:`task` that is :term:`active ` at reload + will continue with its pre-reload configuration. + The next instance of the task (at the next cycle point) + will adopt the new configuration. + + Reloading changes is safe providing they don't affect the + :term:`workflow's ` :term:`graph`. Changes to the graph have + certain caveats attached, see the + :ref:`Cylc User Guide ` + for details. + + .. seealso:: + + * :term:`restart` + + + hold + held task + hold after cycle point + A :term:`task` held with ``cylc hold`` will not submit its :term:`jobs + ` when ready to run. + + It is also possible to set a "hold after cycle point"; all tasks after + this cycle point will be held. + + .. note:: + :term:`Workflows ` can be :term:`paused ` with ``cylc + pause``, and unpaused/resumed with ``cylc play``. + + :term:`Tasks ` can be :term:`held ` with ``cylc hold`` and + :term:`released ` with ``cylc release``. + + When a workflow is resumed, any held tasks remain held. + + + release + :term:`Held tasks ` can be released with ``cylc release``, + allowing submission of task :term:`jobs ` once again. + + It is also possible to remove the "hold after cycle point" if set, + using ``cylc release --all``. This will also release all held tasks. + + + task parameters + parameterization + Task parameterization is one way of consolidating configuration in the + :cylc:conf:`flow.cylc` file. Cylc implicitly loops over ranges or lists + of pre-defined parameters to automatically generate sets of similar + tasks. + + Other ways of consolidating configuration include :term:`runtime + inheritance` and templating with :ref:`Jinja2 ` or :ref:`Empy + `. + + .. code-block:: cylc + + [task parameters] + m = 1..3 + [scheduling] + [[graph]] + R1 = bar => baz + + .. minicylc:: + :theme: none + + bar_m1 => baz_m1 + bar_m2 => baz_m2 + bar_m3 => baz_m3 + + .. seealso:: + + * :ref:`Cylc User Guide ` + * :ref:`Cylc tutorial ` + + + family + In Cylc a family is a collection of :term:`tasks ` that share + common configuration and which can be referred to collectively in the + :term:`graph`. + + By convention, family names are upper case, with the exception of the + special ``root`` family that all tasks inherit from. + + .. seealso:: + + * :term:`family inheritance` + * :term:`family trigger` + * :ref:`Cylc User Guide ` + * :ref:`Cylc tutorial ` + + + runtime inheritance + family inheritance + A :term:`task` is a member of a :term:`family` if it inherits the + family configuration via :cylc:conf:`[runtime][]inherit`. + + For example the :term:`task` ``cheddar`` "belongs" to the :term:`family` + ``CHEESE`` in the following snippet: + + .. code-block:: cylc + + [runtime] + [[CHEESE]] + [[[environment]]] + COLOR = yellow + [[cheddar]] + inherit = FAMILY + + Families can also inherit from other families. All tasks implicitly + inherit from a special ``root`` family at the base of the inheritance + hierarchy. + + Tasks can inherit from multiple families at once using a comma-separated + list: + + .. code-block:: cylc + + inherit = foo, bar, baz + + .. seealso:: + + * :term:`family trigger` + * :ref:`Cylc User Guide ` + * :ref:`Cylc Tutorial ` + + + family trigger + :term:`Tasks ` that belong to a :term:`family` can be + referred to collectively in the :term:`graph` using a family + :term:`trigger`. + + Family triggers take the form ``family-name:qualifier``, where + the :term:`qualifier` describes the collective state of member tasks + needed for the dependency to be met. Some commonly used qualifiers + are: + + ``succeed-all`` + All members succeeded. + ``succeed-any`` + Any one member succeeded. + ``fail-all`` + All members failed. + ``finish-all`` + All members finished (succeeded or failed). + + .. seealso:: + + * :term:`dependency` + * :ref:`Cylc Tutorial ` + * :ref:`Cylc User Guide ` + + + final status + A task that has achieved a final status (expired, submit-failed, + succeeded, or failed) will not change state in the workflow, except by + manual intervention. + + + standard output + Every :term:`task` has a set of standard :term:`outputs ` + that trigger :term:`task state` changes: + + - ``:expired``` + - ``:submitted``, or ``:submit-failed`` + - ``:started`` + - ``:succeeded``, or ``:failed`` + + + output + task output + Task outputs mark the progression of a :term:`task` from waiting (for + :term:`prerequisites ` to be satisfied) through to success + or failure at run time. Tasks can trigger off of upstream task outputs in + the :term:`graph`. + + Outputs are written as ``task-name:output`` in the :term:`graph`, and can + be :term:`required ` or :term:`optional `. + + Tasks may have :term:`custom outputs ` as well as + :term:`standard outputs `. + + Here the task ``bar`` depends on the standard ``:started`` output of + ``foo``: + + .. code-block:: cylc-graph + + foo:started => bar + + The standard ``:succeeded`` output is usually implicit: + + .. code-block:: cylc-graph + + foo => bar # means foo:succeeded => bar + + + output completion + output completion condition + A task's outputs are *complete* if its *output completion condition* + is satisfied. + + The completion condition can be defined by the user in + :cylc:conf:`flow.cylc[runtime][]completion`, + otherwise it is automatically generated according to the rules: + + - All :term:`required outputs ` (referenced in the graph) + must be completed. + - Or, if success is optional, then the outputs are complete if it fails. + - Or, if submission is optional, then the outputs are complete if it + submit-fails. + - Or, if expiry is optional, then the outputs are complete if it expires. + + Tasks that achieve a :term:`final status` with complete outputs have done + their job, allowing the workflow to move on. + + Tasks that achieve a final status with incomplete outputs are retained in + :term:`n=0 ` pending user intervention, and will :term:`stall` + the workflow. + + + prerequisite + dependence + dependency + Dependencies in the :term:`graph` show how :term:`tasks ` depend on + some combination of the :term:`outputs ` of other tasks. + + For example, in the following dependency the task ``baz`` depends on both + ``foo`` and ``bar`` succeeding: + + .. code-block:: cylc-graph + + foo & bar => baz + + .. seealso:: + + * :term:`task trigger` + * :term:`conditional dependence` + * :term:`intercycle dependence` + + Tasks can also depend on :term:`external triggers `. + + + conditional dependence + conditional dependency + conditional trigger + Conditional :term:`dependence` is when a :term:`task` depends on a + combination of multiple upstream :term:`task outputs `. + + .. code-block:: cylc-graph + + a & (b:fail | c) => d + + The left hand side of a conditional dependency can be called a + conditional :term:`trigger`. + + + trigger + task trigger + A trigger is the left-hand side of a :term:`dependency` in the + :term:`graph`. It defines the combination of :term:`task outputs ` that must be completed before downstream tasks can run. + + In this example, the task ``bar`` can be said to trigger off of + completion of the ``foo:started`` output: + + .. code-block:: cylc-graph + + foo:started => bar + + Triggers can be based on :term:`standard ` or + :term:`custom ` task outputs. In the latter case they + are known as :term:`message triggers `. + + + message trigger + A message trigger is a :term:`trigger` based on a + :term:`custom task output `. The task :term:`job` must + send a user-defined message to the scheduler to complete the output. + + For brevity, the trigger in the :term:`graph` uses the output name, not + the full message: + + .. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + foo:out1 => proc-out-1 + foo:out2 => proc-out-2 + """ + [runtime] + [[foo]] + script = """ + # ... + cylc message "Output 1 completed" + # ... + cylc message "Output 2 completed" + """ + [[[outputs]]] + # output name = output message + out1 = "Output 1 completed" + out2 = "Output 2 completed" + + However, if you don't need a descriptive message for the workflow + log, you can make the message the same as its name: + + .. code-block:: cylc + + [[[outputs]]] + out1 = out1 + + + custom output + A custom task output is a user-defined :term:`task output` that marks + an event runtime event between task :term:`job` start and finish. To + complete a custom output, the job must send a message defined in the + :cylc:conf:`flow.cylc` file to the :term:`scheduler`. + + Triggers based on custom outputs are called :term:`message triggers + `. + + .. code-block:: cylc + + [runtime] + [[foo]] + [[[outputs]]] + # output name = output message + out1 = "Output 1 completed" + out2 = "Output 2 completed" + + .. seealso:: + + * :term:`standard output` + * :ref:`Cylc Tutorial ` + * :ref:`Cylc User Guide ` + + + optional output + Optional :term:`task outputs ` are marked with a question + mark in the :term:`graph`, e.g. ``foo:x?``, or ``foo:fail?``, or + ``foo?`` (short for ``foo:succeed?``). The may or may not be completed at + runtime. Optional outputs are primarily used for :term:`graph branching`. + + .. seealso:: + + * :term:`required output` + * :ref:`Cylc User Guide ` + + + required output + expected output + Task outputs that are not marked as :term:`optional ` + in the :term:`graph` must be completed at runtime. If a task + achieves a :term:`final status` without completing its required + outputs, the :term:`scheduler` will keep it in the + :term:`n=0 window ` pending user intervention. + + .. seealso:: + + * :ref:`Cylc User Guide ` + + + stall + stalled workflow + A stalled workflow has not run to :term:`completion ` + but cannot continue without manual intervention. + + A stalled scheduler stays alive for a configurable timeout period + pending manual intervention. If it shuts down (on the stall timeout + or otherwise) it will remain in the stalled state on restart. + + Stalls are usually caused by unexpected task failures: + + .. digraph:: Example + :align: center + + foo [style="filled" color="#ada5a5"] + bar [style="filled" color="#ff0000" fontcolor="white"] + baz [color="#88c6ff"] + + foo -> bar -> baz + + In this example the task ``bar`` has failed, so that ``baz`` cannot + run, but ``bar:fail`` was not marked as an :term:`optional output`. + + User intervention is required to fix a stall, e.g. by retriggering + tasks after fixing the problems that caused them to fail. + + + suicide trigger + Suicide triggers remove :term:`tasks ` from the + :term:`active window ` at runtime. + + They are denoted by exclamation marks, and are triggered like normal + dependencies. For instance, the following suicide trigger will remove the + task ``bar`` if ``foo`` succeeds: + + .. code-block:: cylc-graph + + foo => ! bar + + .. warning:: + Suicide triggers are not needed in Cylc 8 for :term:`graph branching`. + They are retained for backward compatibility and rare edge cases. + + .. seealso:: + + * :ref:`Cylc User Guide ` + + branching + graph branching + Cylc handles workflow :term:`graphs ` in an event-driven way. + It can automatically follow different paths depending on events at + runtime. This relies on :term:`optional outputs ` and is + called *branching*. + + For example, the following workflow follows one of two possible paths + depending on the outcome of task ``b``: + + .. code-block:: cylc-graph + + # the success branch + a => b? => c + # the fail branch + b:fail? => r + # joining the two branches together + c | r => d + + .. digraph:: example + :align: center + + subgraph cluster_success { + label = ":succeed" + color = "green" + fontcolor = "green" + style = "dashed" + + c + } + + subgraph cluster_failure { + label = ":fail" + color = "red" + fontcolor = "red" + style = "dashed" + + r + } + + a -> b -> c -> d + b -> r -> d + + .. seealso:: + + * :term:`optional output` + * :ref:`Cylc User Guide ` + + + flow + A flow is a self-propagating run through the a Cylc :term:`workflow` + :term:`graph` starting from some initial task or tasks. + + Cylc :term:`schedulers ` can manage multiple flows at once. + + Flows are identified by a :term:`flow number`. The original flow + started automatically by ``cylc play`` has flow number ``1``. + + .. seealso:: + * :ref:`user-guide-reflow` + + + flow number + Flow numbers are integers passed down from parent task to child task in + the :term:`graph` as a flow progresses, to identify which :term:`flow` + (or flows) the tasks belong to. They are passed to job environments as + ``$CYLC_TASK_FLOW_NUMBERS``. + + + flow front + :term:`Active tasks `, i.e. tasks in the + :term:`n=0 window `, with a common :term:`flow number` + comprise the active front of the flow. + + + flow merge + When a :term:`flow` tries to spawn a child task and finds an instance + with the same task ID already exists in the ``n=0`` :term:`active + window`, one merged task will carry both flow numbers forward. + + + event + An event is a milestone in the lifecycle of a :term:`workflow` or + :term:`task` at which the :term:`scheduler` provides a hook for + attaching :term:`event handlers `. + + Workflow events include :term:`startup`, :term:`stall`, and + :term:`shutdown`. + + Task events include :term:`task state` changes, to ``running`` or + ``failed``, for example, or when the scheduler receivers CRITICAL or + WARNING messages from a task :term:`job`. + + + handler + event handler + event handlers + An event handler is a user-defined executable that the + :term:`scheduler` runs when selected :term:`task` or :term:`workflow` + :term:`events ` occur. + + Use-cases include: + + - Send an email message. + - Run a Cylc command. + - Run *any* user-specified script or command. + + .. seealso:: + + - :ref:`user_guide.scheduler.workflow_event_handling` + - :ref:`user_guide.runtime.task_event_handling` + + + runahead limit + runahead + In a :term:`cycling workflow`, the runahead limit determines how far + ahead of the oldest :term:`active cycle` the workflow is permitted + to run. + + The "oldest active cycle point" is the first cycle in the workflow to contain + any :term:`active tasks ` (e.g. running tasks). + + .. seealso:: + + * :cylc:conf:`[scheduling]runahead limit` + * :ref:`Runahead Limiting` + * :term:`active cycle` + + + workflow completion + A workflow is complete, and the scheduler will automatically + :term:`shut down `, if no tasks remain in the + :term:`n=0 `. + + That is, all active tasks have finished, and no tasks remain waiting on + :term:`prerequisites ` or "external" constraints (such as + :term:`xtriggers ` or task :term:`hold`). + + If no active tasks remain and all external constraints are satisfied, + but the n=0 window contains tasks waiting with partially satisfied + :term:`prerequisites `, or tasks with :term:`final status` and + :term:`incomplete outputs `, then the workflow is + not complete and the scheduler will :term:`stall` pending manual intervention. + diff --git a/nightly_8.4/html/_sources/index.rst.txt b/nightly_8.4/html/_sources/index.rst.txt new file mode 100644 index 00000000000..df67a04afce --- /dev/null +++ b/nightly_8.4/html/_sources/index.rst.txt @@ -0,0 +1,25 @@ +Cylc Documentation +================== + +Cylc ("*silk*") is a workflow engine for cycling systems - it orchestrates +distributed workflows of interdependent cycling tasks that may continue to run +indefinitely. + +.. image:: https://img.shields.io/discourse/users?label=Join%20the%20community%20on%20Discourse&logo=discourse&server=https%3A%2F%2Fcylc.discourse.group&style=socia0l + :align: center + :width: 50% + :target: https://cylc.discourse.group + +| + +.. toctree:: + :maxdepth: 2 + + 7-to-8/index + installation + tutorial/index + user-guide/index + plugins/index + workflow-design-guide/index + reference/index + glossary diff --git a/nightly_8.4/html/_sources/installation.rst.txt b/nightly_8.4/html/_sources/installation.rst.txt new file mode 100644 index 00000000000..0b72501bf98 --- /dev/null +++ b/nightly_8.4/html/_sources/installation.rst.txt @@ -0,0 +1,328 @@ +.. _installation: + +Installation +============ + +Cylc 8 and its core software dependencies can be installed quickly from Conda +Forge, into a conda environment; or from PyPI, into a Python 3 virtual environment. + + +Quick Installation +------------------ + +Cylc runs on Unix-like systems including Linux and Mac OS. + +Via Conda (recommended) +^^^^^^^^^^^^^^^^^^^^^^^ + +.. note:: + + We recommend using the fast Mamba environment solver to install Cylc. + Mamba can be used as `a drop-in replacement for the conda command + `_, + or as `a conda command plugin + `_. + The classic conda environment solver may be too slow for a complex package + like Cylc. + + +.. code-block:: sub + + $ conda install -c conda-forge cylc-flow + + # Install the browser-GUI (optional) + $ conda install -c conda-forge cylc-uiserver + + # Install Rose support (optional) + $ conda install -c conda-forge cylc-rose metomi-rose + +Via Pip (+npm) +^^^^^^^^^^^^^^ + +.. note:: + + Requires Python 3.7 - 3.9 + +.. important:: + + We recommend installing Cylc versions into virtual environments. + This avoids software dependency conflicts and allows multiple + Cylc versions to be installed on your system. + + Without virtual environments, users can inadvertently break Cylc (or other + Python programs) by ``pip``-installing conflicting package versions to + ``$HOME/.local``, which takes precedence over central library locations. + +.. code-block:: sub + + $ pip install cylc-flow + + # Install the browser-GUI (optional) + # (requires nodejs & npm) + $ pip install cylc-uiserver + + # Install Rose support (optional) + $ pip install cylc-rose metomi-rose + +There are also certain optional extra requirements which you may choose to +install: + +.. code-block:: sub + + # EmPy support + $ pip install 'cylc-flow[empy]' + + # Support for running the tutorial workflows + $ pip install 'cylc-flow[tutorial]' + + # The GUI with multi-user (hub) support + $ pip install 'cylc-uiserver[hub]' + $ npm install configurable-http-proxy + +You might also want to configure: + +* :ref:`Shell auto-completion ` +* :ref:`Text editor support ` + + +.. _non-python-requirements: + +Non-Python Requirements +----------------------- + +.. _Graphviz: https://graphviz.org/download/ +.. _configurable-http-proxy: https://anaconda.org/conda-forge/configurable-http-proxy + +These dependencies are not installed by Conda or pip: + +* ``bash`` +* GNU `coreutils`_ +* ``ssh`` +* ``rsync`` +* ``mail`` (optional - for automated email functionality) + +These dependencies are installed by Conda but not by pip: + +* `Graphviz`_ (optional - used by ``cylc graph`` for displaying workflow + graphs) +* `configurable-http-proxy`_ (optional - for multi-user setups; can also be + installed using npm) + +.. seealso:: + + :ref:`SyntaxHighlighting` + + +Installing On Mac OS +-------------------- + +.. _Homebrew: https://formulae.brew.sh/ +.. _atrun: https://man.freebsd.org/cgi/man.cgi?query=atrun&sektion=8&format=html + +Cylc requires some extra packages to function on Mac OS. We recommend +installing them using the `Homebrew`_ package manager: + +.. code-block:: console + + $ brew install bash coreutils gnu-sed + +You will need to prepend the ``coreutils`` and ``gnu-sed`` installations to +your ``$PATH``, follow the instructions in the ``brew install`` output. + +.. note:: + + `atrun`_ (the ``at`` command) does not run out-of-the-box on Mac OS + for security reasons and must be manually enabled. + +.. note:: + + Newer version of Mac OS set ``zsh`` as the default shell (as opposed to + ``bash``). You do not need to change this but be aware that Cylc uses + ``bash`` (for job scripts) which has a subtly different syntax. + +.. warning:: + + For Mac OS Versions 10.15.0 (Catalina) and higher SSH is disabled by + default. The ability to SSH into your Mac OS box may be required for + certain Cylc installations. + + See the `Apple support page + `_ + for instructions on enabling SSH. + + +Advanced Installation +--------------------- + +For distributed and multi-user installation we recommend using Conda and +installing Cylc components only where required. + +.. tip:: + + For examples of Conda environments and installation options see + :ref:`conda environments` for examples and details. + +The Cylc Components +^^^^^^^^^^^^^^^^^^^ + +Cylc is split into a number of components providing different functionality: + +`Cylc Flow`_ + Provides the scheduler "kernel" of Cylc along with the command line interface. +`Cylc UI Server`_ + Provides the "Cylc Hub" and the browser-based "Cylc GUI". +:ref:`Cylc Rose` + Provides support for `Rose`_ suite configurations in Cylc workflows. + +Installation Types +^^^^^^^^^^^^^^^^^^ + +Cylc install locations may fall into the following "roles": + +User Machines + Where users write workflows and interact with the command line. +Cylc Servers + Where Cylc schedulers run to manage workflows. +Job Hosts + Where jobs run, e.g. supercomputers or clusters + +.. note:: + + These roles may overlap. For example, Cylc servers can also be job hosts. + +Recommended Installation +^^^^^^^^^^^^^^^^^^^^^^^^ + +User Machines + * `Cylc Flow`_ + * :ref:`Cylc Rose` (if using `Rose`_) +Cylc Servers + * `Cylc Flow`_ + * :ref:`Cylc Rose` (if using `Rose`_) + * `Cylc UI Server`_ +Job Hosts: + * `Cylc Flow`_ + * `Rose`_ (if running Rose applications on the job host) + +.. _managing environments: + +Managing Environments +^^^^^^^^^^^^^^^^^^^^^ + +For Cylc to run, the correct environment must be activated. Cylc can +not do this automatically. You may need to have multiple Cylc versions +available too. + +We recommend using a wrapper script named ``cylc`` to activate the correct +environment before calling the environment's ``cylc`` command. + +Cylc comes with a wrapper that can be adapted to point at your Cylc +environments. Extract it to a directory in your ``$PATH`` like this: + +.. code-block:: bash + + cylc get-resources cylc /path/to/cylc # should be in $PATH + chmod +x /path/to/cylc + +You may need to modify this file for your local installation e.g: + +.. code-block:: diff + + - CYLC_HOME_ROOT="${CYLC_HOME_ROOT:-/opt}" + + CYLC_HOME_ROOT="${CYLC_HOME_ROOT:-/path/to}" + +.. note:: + + Developers can set ``$CYLC_HOME_ROOT_ALT`` to point + to their development environments. For example: + + .. code-block:: bash + + CYLC_HOME_ROOT_ALT=${HOME}/.conda/envs + +You may wish to use the same approach for the ``isodatetime`` command, and, if using +`Rose`_ for the ``rose`` and ``rosie`` commands. + +To do so create a symbolic link to the wrapper, for each of these commands: + +.. code-block:: bash + + cd /path/to # Using the path where you installed the wrapper script + ln -s cylc rose + ln -s cylc rosie + ln -s cylc isodatetime + + +Configuration +------------- + +Cylc uses sane and safe defaults and is suitable for use "out of the box", +if all you need to do is run jobs locally in the background. +However, many things may need to be configured, e.g: + +* :ref:`AdminGuide.PlatformConfigs` (jobs hosts, runners, etc) +* :ref:`Scheduler Hosts` +* :ref:`Default Event Handlers`. + +Cylc Flow +^^^^^^^^^ + +`Cylc Flow`_ is configured by the :cylc:conf:`global.cylc` file which supports +configuration of the system on both a site and user basis. + +.. note:: + + Prior to Cylc 8, ``global.cylc`` was named ``global.rc``, but that name is + no longer supported. + +The global.cylc file should be available on user machines (where users interact +with Cylc on the command line) and on cylc servers (where Cylc schedulers run). +It is not required to be available on job hosts. + +More information about supported configuration items and defaults can be found: +:ref:`global-configuration`. + +Cylc UI Server +^^^^^^^^^^^^^^ +The `Cylc UI Server`_ can be configured on a site and user basis. +Guidance for configuration file storage, configuration variables and defaults +can be found: :ref:`UI_Server_config`. + +Bash Profile +^^^^^^^^^^^^ + +Cylc :term:`job scripts ` are bash scripts, which is good for +manipulating files and processes, They invoke ``bash -l`` to allow environment +configuration in login scripts. + +.. warning:: + + Sites and users should ensure their bash login scripts configure the + environment correctly for Cylc and *do not write anything to stdout*. + +.. _installation.shell_auto_completion: + +Shell Auto-Completion +^^^^^^^^^^^^^^^^^^^^^ + +Cylc provides auto-completion for the Bash shell which can save you typing: + +* Cylc commands +* Workflow IDs +* Cycle points +* Task names + +To extract the auto-completion file run the following command: + +.. code-block:: sub + + cylc get-resources cylc-completion.bash + +Then follow the comments in the file to install it. + +Text Editors +^^^^^^^^^^^^ + +There is support for the ``.cylc`` file format in various text editors. + +See :ref:`SyntaxHighlighting` for more details. diff --git a/nightly_8.4/html/_sources/plugins/cylc-rose.rst.txt b/nightly_8.4/html/_sources/plugins/cylc-rose.rst.txt new file mode 100644 index 00000000000..dd9a6928211 --- /dev/null +++ b/nightly_8.4/html/_sources/plugins/cylc-rose.rst.txt @@ -0,0 +1,6 @@ +.. _Cylc Rose: + +Cylc Rose +========= + +.. automodule:: cylc.rose diff --git a/nightly_8.4/html/_sources/plugins/index.rst.txt b/nightly_8.4/html/_sources/plugins/index.rst.txt new file mode 100644 index 00000000000..8d16ab7d3e1 --- /dev/null +++ b/nightly_8.4/html/_sources/plugins/index.rst.txt @@ -0,0 +1,20 @@ +Plugins +======= + +Cylc supports plugins for providing additional functionality. + +The following are "core" plugins maintained by the Cylc team: + +.. toctree:: + :maxdepth: 1 + + cylc-rose + main-loop/index + install/index + job-runners/index + xtriggers/index + +.. warning:: + + Plugins are a new feature of Cylc 8 and the interface is likely to change in + future releases. diff --git a/nightly_8.4/html/_sources/plugins/install/built-in/cylc.flow.install_plugins.log_vc_info.rst.txt b/nightly_8.4/html/_sources/plugins/install/built-in/cylc.flow.install_plugins.log_vc_info.rst.txt new file mode 100644 index 00000000000..899d297bbd6 --- /dev/null +++ b/nightly_8.4/html/_sources/plugins/install/built-in/cylc.flow.install_plugins.log_vc_info.rst.txt @@ -0,0 +1,4 @@ +cylc.flow.install\_plugins.log\_vc\_info +======================================== + +.. automodule:: cylc.flow.install_plugins.log_vc_info \ No newline at end of file diff --git a/nightly_8.4/html/_sources/plugins/install/index.rst.txt b/nightly_8.4/html/_sources/plugins/install/index.rst.txt new file mode 100644 index 00000000000..335c07b3c4f --- /dev/null +++ b/nightly_8.4/html/_sources/plugins/install/index.rst.txt @@ -0,0 +1,162 @@ +Pre-Configure And Post-Install Plugins +====================================== + +Pre-configure plugins allow Cylc to take additional actions before running +Cylc utilities such as ``cylc install``, ``cylc graph`` and ``cylc config``. + +Post-install plugins allow Cylc to take additional actions after +running ``cylc install``. + + +Built In Plugins +---------------- + +Cylc Flow provides the following pre-configure and post-install plugins: + +.. autosummary:: + :toctree: built-in + :template: docstring_only.rst + + cylc.flow.install_plugins.log_vc_info + +.. Note: Autosummary generates files in this directory, these are cleaned + up by `make clean`. + +Developing ``pre_configure`` and ``post_install`` plugins +--------------------------------------------------------- + +Cylc uses entry points registered by setuptools to search for pre-configure +and post-install plugins. + +Hello World +^^^^^^^^^^^ + +In this example a pre-configure plugin which logs a "Hello World" message +and, after installation, logs some info about the installation: + +.. code-block:: python + :caption: ``my_plugin.py`` + + from cylc.flow import LOG + + def pre_configure(srcdir=None, opts=None, rundir=None): + # write Hello to the Cylc log. + LOG.info(f'Hello World') + return {} + + def post_install(srcdir=None, opts=None, rundir=None): + LOG.info(f'installed from {srcdir}') + LOG.info(f'installed to {rundir}') + LOG.info(f'installation options were {options}') + return {} + +Plugins are registered by registering them with the ``cylc.pre_configure`` +and ``cylc.post_install`` entry points: + +.. code-block:: python + :caption: ``setup.py`` + + # plugins must be properly installed, in-place PYTHONPATH meddling will + # not work. + + from setuptools import setup + + setup( + name='my-plugin', + version='1.0', + py_modules=['my_plugin'], + entry_points={ + # register this plugin with Cylc + 'cylc.pre_configure': [ + # name = python.namespace.of.module + 'my_plugin=my_plugin.my_plugin:pre_configure' + ] + 'cylc.post_install': [ + # name = python.namespace.of.module + 'my_plugin=my_plugin.my_plugin:post_install' + ] + } + ) + +API Reference +^^^^^^^^^^^^^ + +Cylc will pass following arguments to pre-configure and post-install plugins: + +``srcdir`` (Path or string) + The directory from which ``cylc install`` is installing a workflow, + or the directory passed to ``cylc validate``, ``cylc graph`` and other + CLI commands which work without installing a workflow. +``opts`` (``optparse.Values``) + CLI options set for a Cylc script. +``rundir`` (Path or string) + The destination of a ``cylc install`` or ``reinstall`` command. + +The pre-configure plugin should return a dictionary which may contain the +following keys: + +``env`` + A dictionary of environment variables to be exported to the scheduler + environment. +``template_variables`` + A dictionary of template variables to be used by Jinja2 or EmPy when + templating the workflow configuration files. +``templating_detected`` + ``jinja2`` | ``empy`` to be used when templating. N.b: This will result in + failure if the templating language set does not match the shebang line of + the ``flow.cylc`` file. + +The post-install entry point does not return any data used by Cylc. + +More advanced example +^^^^^^^^^^^^^^^^^^^^^ + +.. seealso:: + + For the implementation of a more fully featured "real-world" example see + :ref:`Cylc Rose`. + +The example below looks for a file in the workflow source directory called +``template.json`` and activates if it exists. + +At ``pre_configure`` template variables are extracted from a ``template.json`` +file and provided to Cylc as both template and environment variables. + +At ``post_install`` an additional log file is provided recording the version +of this plugin used. + +.. code-block:: python + :caption: An example json reading plugin + + import json + from pathlib import Path + + VERSION = '0.0.1' + + def pre_configure(srcdir=None, opts=None, rundir=None): + # Look for a 'template.json' file in the srcdir and make template + # variables from it available as jinja2. + template_file = (Path(srcdir) / 'template.json') + + # Trigger the plugin if some condition is met: + if (template_file).exists(): + # You could retrieve info from a file: + template = json.loads(template_file.read_text()) + + # You can add variables programmatically: + template['plugin_set_var'] = str(__file__) + + # Return a dict: + return { + 'env': template, + 'template_variables': template, + 'templating_detected': 'jinja2' + } + else: + return {} + + def post_install(srcdir=None, opts=None, rundir=None): + # record plugin version in a file + (Path(rundir) / 'log/json-plugin.info').write_text( + f"Installed with Simple JSON reader plugin version {VERSION}\\n") + return None diff --git a/nightly_8.4/html/_sources/plugins/job-runners/index.rst.txt b/nightly_8.4/html/_sources/plugins/job-runners/index.rst.txt new file mode 100644 index 00000000000..827ed6707b6 --- /dev/null +++ b/nightly_8.4/html/_sources/plugins/job-runners/index.rst.txt @@ -0,0 +1,7 @@ +.. _CustomJobSubmissionMethods: + +Custom Job Submission Methods +----------------------------- + +.. autoclass:: cylc.flow.job_runner_handlers.documentation.ExampleHandler + :members: diff --git a/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.auto_restart.rst.txt b/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.auto_restart.rst.txt new file mode 100644 index 00000000000..542fa58b177 --- /dev/null +++ b/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.auto_restart.rst.txt @@ -0,0 +1,28 @@ +cylc.flow.main\_loop.auto\_restart +================================== + +.. automodule:: cylc.flow.main_loop.auto_restart + :members: auto_restart + + .. set members so that we only document what is actually defined + otherwise you can end up with imported modules and mess like that + + + + Python API + ---------- + + + .. rubric:: Coroutines + + .. write out a table of functions (coroutines in this context) + for quick reference + + .. autosummary:: + :nosignatures: + + + auto_restart + + + \ No newline at end of file diff --git a/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.health_check.rst.txt b/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.health_check.rst.txt new file mode 100644 index 00000000000..5a44d343771 --- /dev/null +++ b/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.health_check.rst.txt @@ -0,0 +1,28 @@ +cylc.flow.main\_loop.health\_check +================================== + +.. automodule:: cylc.flow.main_loop.health_check + :members: health_check + + .. set members so that we only document what is actually defined + otherwise you can end up with imported modules and mess like that + + + + Python API + ---------- + + + .. rubric:: Coroutines + + .. write out a table of functions (coroutines in this context) + for quick reference + + .. autosummary:: + :nosignatures: + + + health_check + + + \ No newline at end of file diff --git a/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.log_data_store.rst.txt b/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.log_data_store.rst.txt new file mode 100644 index 00000000000..a6fd7db214b --- /dev/null +++ b/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.log_data_store.rst.txt @@ -0,0 +1,30 @@ +cylc.flow.main\_loop.log\_data\_store +===================================== + +.. automodule:: cylc.flow.main_loop.log_data_store + :members: init, log_data_store, report + + .. set members so that we only document what is actually defined + otherwise you can end up with imported modules and mess like that + + + + Python API + ---------- + + + .. rubric:: Coroutines + + .. write out a table of functions (coroutines in this context) + for quick reference + + .. autosummary:: + :nosignatures: + + + init + log_data_store + report + + + \ No newline at end of file diff --git a/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.log_main_loop.rst.txt b/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.log_main_loop.rst.txt new file mode 100644 index 00000000000..266ac5a897b --- /dev/null +++ b/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.log_main_loop.rst.txt @@ -0,0 +1,29 @@ +cylc.flow.main\_loop.log\_main\_loop +==================================== + +.. automodule:: cylc.flow.main_loop.log_main_loop + :members: init, report + + .. set members so that we only document what is actually defined + otherwise you can end up with imported modules and mess like that + + + + Python API + ---------- + + + .. rubric:: Coroutines + + .. write out a table of functions (coroutines in this context) + for quick reference + + .. autosummary:: + :nosignatures: + + + init + report + + + \ No newline at end of file diff --git a/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.log_memory.rst.txt b/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.log_memory.rst.txt new file mode 100644 index 00000000000..6b7007e4d11 --- /dev/null +++ b/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.log_memory.rst.txt @@ -0,0 +1,30 @@ +cylc.flow.main\_loop.log\_memory +================================ + +.. automodule:: cylc.flow.main_loop.log_memory + :members: init, report, take_snapshot + + .. set members so that we only document what is actually defined + otherwise you can end up with imported modules and mess like that + + + + Python API + ---------- + + + .. rubric:: Coroutines + + .. write out a table of functions (coroutines in this context) + for quick reference + + .. autosummary:: + :nosignatures: + + + init + report + take_snapshot + + + \ No newline at end of file diff --git a/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.reset_bad_hosts.rst.txt b/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.reset_bad_hosts.rst.txt new file mode 100644 index 00000000000..fad5d72d738 --- /dev/null +++ b/nightly_8.4/html/_sources/plugins/main-loop/built-in/cylc.flow.main_loop.reset_bad_hosts.rst.txt @@ -0,0 +1,28 @@ +cylc.flow.main\_loop.reset\_bad\_hosts +====================================== + +.. automodule:: cylc.flow.main_loop.reset_bad_hosts + :members: reset_bad_hosts + + .. set members so that we only document what is actually defined + otherwise you can end up with imported modules and mess like that + + + + Python API + ---------- + + + .. rubric:: Coroutines + + .. write out a table of functions (coroutines in this context) + for quick reference + + .. autosummary:: + :nosignatures: + + + reset_bad_hosts + + + \ No newline at end of file diff --git a/nightly_8.4/html/_sources/plugins/main-loop/index.rst.txt b/nightly_8.4/html/_sources/plugins/main-loop/index.rst.txt new file mode 100644 index 00000000000..8ef83f81513 --- /dev/null +++ b/nightly_8.4/html/_sources/plugins/main-loop/index.rst.txt @@ -0,0 +1,4 @@ +Main Loop Plugins +================= + +.. automodule:: cylc.flow.main_loop diff --git a/nightly_8.4/html/_sources/plugins/xtriggers/index.rst.txt b/nightly_8.4/html/_sources/plugins/xtriggers/index.rst.txt new file mode 100644 index 00000000000..5a920f79cdb --- /dev/null +++ b/nightly_8.4/html/_sources/plugins/xtriggers/index.rst.txt @@ -0,0 +1,70 @@ +Xtrigger Plugins +====================================== + +.. versionadded:: 8.3 + + Xtrigger plugins allow you to install and use + :ref:`xtriggers
` without them being + in ``/lib/python/`` or ``$CYLC_PYTHONPATH``. + +.. seealso:: + + * :ref:`Built-in Clock Triggers` + * :ref:`Built-in Workflow State Triggers` + * :ref:`Built-in Toy Xtriggers` + + +.. _developing.xtrigger.plugins: + +Developing ``xtrigger`` plugins +------------------------------- + +Cylc uses the ``cylc.xtriggers`` entry point registered by setuptools to search +for xtrigger plugins. Each xtrigger is registered individually. + +Example +^^^^^^^ + +Consider a package called ``my_package`` with the following structure: + +.. code-block:: python + :caption: ``my_package/foo.py`` + + def foo(): + ... + + def bar(): + ... + +.. code-block:: python + :caption: ``my_package/baz.py`` + + def baz(): + ... + +These xtriggers can be registered in the package's ``setup.cfg`` or +``pyproject.toml`` file. + +.. code-block:: ini + :caption: ``setup.cfg`` + + [options.entry_points] + cylc.xtriggers = + foo = my_package.foo + bar = my_package.foo + baz = my_package.baz + +.. code-block:: toml + :caption: ``pyproject.toml`` + + [project.entry-points."cylc.xtriggers"] + foo = "my_package.foo" + bar = "my_package.foo" + baz = "my_package.baz" + +.. tip:: + + It is recommended to implement only one xtrigger per module. This allows + you to write a ``validate`` function for each xtrigger - see + :ref:`user-guide.xtrigger-validation-functions`. + diff --git a/nightly_8.4/html/_sources/reference/api/exceptions.rst.txt b/nightly_8.4/html/_sources/reference/api/exceptions.rst.txt new file mode 100644 index 00000000000..1287d644468 --- /dev/null +++ b/nightly_8.4/html/_sources/reference/api/exceptions.rst.txt @@ -0,0 +1,8 @@ +Exceptions +========== + +.. automodule:: cylc.flow.exceptions + :members: + +.. automodule:: cylc.flow.parsec.exceptions + :members: diff --git a/nightly_8.4/html/_sources/reference/api/index.rst.txt b/nightly_8.4/html/_sources/reference/api/index.rst.txt new file mode 100644 index 00000000000..7dab90244df --- /dev/null +++ b/nightly_8.4/html/_sources/reference/api/index.rst.txt @@ -0,0 +1,10 @@ +Cylc API +======== + + +.. toctree:: + :maxdepth: 2 + + scan + zmq + exceptions diff --git a/nightly_8.4/html/_sources/reference/api/scan.rst.txt b/nightly_8.4/html/_sources/reference/api/scan.rst.txt new file mode 100644 index 00000000000..a882ad8a97a --- /dev/null +++ b/nightly_8.4/html/_sources/reference/api/scan.rst.txt @@ -0,0 +1,4 @@ +Scan API +======== + +.. automodule:: cylc.flow.network.scan diff --git a/nightly_8.4/html/_sources/reference/api/zmq.rst.txt b/nightly_8.4/html/_sources/reference/api/zmq.rst.txt new file mode 100644 index 00000000000..d98800ec877 --- /dev/null +++ b/nightly_8.4/html/_sources/reference/api/zmq.rst.txt @@ -0,0 +1,39 @@ +Workflow Runtime Interface +========================== + +Cylc workflows are TCP servers which use the ZeroMQ protocol to communicate with +clients and jobs. + +Cylc provides a Python client to communicate with this server +:py:class:`cylc.flow.network.client.WorkflowRuntimeClient` + +.. code-block:: python + + >>> from cylc.flow.network.client import WorkflowRuntimeClient + >>> client = WorkflowRuntimeClient('my-workflow') + >>> client('ping_workflow') + True + +Cylc also provides sub-command called ``cylc client`` which is a simple +wrapper of the Python client. + +.. code-block:: console + + $ cylc client generic ping_workflow -n + true + +The available "commands" or ("endpoints") are contained in +:py:class:`cylc.flow.network.server.WorkflowRuntimeServer` class. + + +Client +------ + +.. autoclass:: cylc.flow.network.client.WorkflowRuntimeClient + + +Server +------ + +.. autoclass:: cylc.flow.network.server.WorkflowRuntimeServer + :members: diff --git a/nightly_8.4/html/_sources/reference/architecture/data-flow.rst.txt b/nightly_8.4/html/_sources/reference/architecture/data-flow.rst.txt new file mode 100644 index 00000000000..985eb7db20b --- /dev/null +++ b/nightly_8.4/html/_sources/reference/architecture/data-flow.rst.txt @@ -0,0 +1,201 @@ +Data Flow +========= + +This section looks at how Cylc synchronises data between its different +components, the transports, security and formats used to do so. + +.. digraph:: _ + :align: center + + Jobs -> Scheduler [label=" ZMQ\n GraphQL\n (default)"] + + Scheduler -> UIS [label=" ZMQ\n GraphQL (control)\n Protobuf (data)"] + + UIS -> UI [label=" Websocket\n GraphQL"] + + +.. _arch protocols: + +Protocols, Transport & Security +------------------------------- + +Cylc uses the following schemes for data and control: + + +.. _arch zmq: + +ZMQ (Over TCP) +^^^^^^^^^^^^^^ + +Cylc uses `ZMQ`_ over TCP for most server side interaction. + +All `ZMQ`_ connections are secured by `CurveZMQ`_ which uses security keys +which are stored on the filesystem with appropriate permissions. + +Where remote communication is involved Cylc synchronises the relevant keys +to the appropriate platforms. + +For more information on the key files see :ref:`Authentication Files`. + +.. _arch ssh: + +SSH +^^^ + +SSH connections are used for some purposes such as installing the key files +required for :ref:`arch zmq` transport. + +.. _arch https: + +HTTPS (Hypertext Transfer Protocol Secure) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +HTTPS connections are used in the browser-based `Cylc UI`_. The certificate +used must be configured with the `Cylc UI Server`_ / `Jupyter Server`_. + +.. _arch wss: + +WSS (WebSocket Secure) +^^^^^^^^^^^^^^^^^^^^^^ +Websocket connections are used in the browser-based `Cylc UI`_. These +connections are upgraded from HTTPS connections and share the same security. + +.. _arch formats: + +Formats +------- + +Cylc uses the following transports to communicate over these protocols. + +.. _arch protobuf: + +Protobuf +^^^^^^^^ + +Protobuf is both a storage utility and transport. + +Protobuf is used for internal data stores and the synchronisation of those data +stores. + + +.. _arch graphql: + +GraphQL +^^^^^^^ + +`GraphQL`_ is a query language which is intended to be the user-facing +data and control interface for Cylc workflows. + +It contains both data and mutations (actions) defined by a self-documenting +schema. + +The GraphQL servers get their data from :ref:`arch protobuf` data stores. + + +Component Interactions +---------------------- + +Here are some additional details on how the components interact. + +Job -> Scheduler +^^^^^^^^^^^^^^^^ + +:Default Protocol: :ref:`arch zmq` +:Format: :ref:`arch graphql` + +Jobs can communicate status updates back to the Scheduler using different +methods. The method used is configured on a per-platform basis by the +:cylc:conf:`global.cylc[platforms][]communication method`. + + +Client -> Scheduler +^^^^^^^^^^^^^^^^^^^ + +:Protocol: :ref:`arch zmq` +:Format: :ref:`arch protobuf` + +The subcommands in the Cylc command line interface map onto `GraphQL`_ +mutations. + +Mutations are issued through `ZMQ`_ connections. + +Scheduler -> UI Server +^^^^^^^^^^^^^^^^^^^^^^ + +:Protocol: :ref:`arch zmq` +:Formats: :ref:`arch protobuf` (data) and :ref:`arch graphql` (control) + +The :term:`Scheduler` maintains an in-memory `Protobuf`_ data store which is +backed up by a SQLite3 database. + +The database provides crash resilience and restart capability. + +The `UI Server`_ also maintains an in-memory `Protobuf`_ data store containing +relevant data for the workflows it is actively monitoring. + +The synchronisation of the :term:`Scheduler` and `UI Server`_ data stores is +done using one :ref:`arch zmq` connection per :term:`Scheduler`. + +The :term:`Schedulers ` that the `UI Server`_ connects to are +determined by the active subscriptions registered. If there are no active +subscriptions the `UI Server`_ will have no active :term:`Scheduler` +connections. + + +UI Server -> UI +^^^^^^^^^^^^^^^ + +:Protocols: :ref:`arch wss`, :ref:`arch https` +:Format: :ref:`arch graphql` + +Most UI functionality involves subscribing to "delta" updates. For these +subscriptions the `UI Server`_ sends only the added/removed/updated data +(a delta) to the UI enabling it to update its internal data store. + +The UI maintains a flat "lookup" which contains all objects in the store +indexed by their ID. It also maintains a "tree" which contains references +to the data in the "lookup" (but does not duplicate it) which it holds in a +hierarchical structure more suitable for presentation purposes. + +The Cylc Web UI uses `Apollo Client`_ to handle `GraphQL`_ requests. +It will have one `WebSocket`_ per user session. + +.. figure:: img/websocket-communication.png + :align: center + +Every message received by the server is added to a queue, and processed +by the server as soon as possible. + +It uses the Cylc UI Server schema and resolvers to validate the +query and to fetch data from the data store for the query response. + +The query result is then serialized as JSON and sent back to the client. +The work of the Apollo Client ends after it pushes the data to the Vuex +store. + +The communication between client and server follows a protocol +called `graphql-ws protocol`_. + +.. figure:: img/websocket-graphql-ws-protocol.png + :align: center + +After a channel between client and server is open, the messages +follow that protocol, starting by the ``connection init`` message, +that simply expects an ``ack`` message back from the server, +where the ``ack`` is an acknowledgement to the client - note +that the protocol does not define an ``ack`` as a MUST, but +rather as a MAY, so a client may interpret not receiving an +error as an acknowledgement to proceed as well. + +The next message will be a ``start``, which will contain the +GraphQL query subscription. If there were no errors, the client and +server subscription is established, and the client will start +receiving the GraphQL responses. + +The protocol also supports other messages, such as ``stop``, to +tell the server it doesn't need to send any more data as that +subscription is now cancelled. + + +.. _`GraphQL subscription`: https://www.apollographql.com/docs/react/data/subscriptions/ +.. _`graphql-ws protocol`: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md diff --git a/nightly_8.4/html/_sources/reference/architecture/index.rst.txt b/nightly_8.4/html/_sources/reference/architecture/index.rst.txt new file mode 100644 index 00000000000..d5184c2ee49 --- /dev/null +++ b/nightly_8.4/html/_sources/reference/architecture/index.rst.txt @@ -0,0 +1,58 @@ +.. _architecture-reference: + +Architecture +============ + +This section provides an in-depth explanation of the architecture of the +Cylc components intended for developers and system administrators. + +The main Cylc 8 system components are: + +Cylc Scheduler +-------------- + +- The workflow engine core, Python 3 based +- Includes the **CLI** (Command Line Interface) +- And **TUI**, a new Terminal UI application + +Cylc UI +------- + +- In-browser web UI, includes: +- A dashboard with summary information and documentation links +- Integrated gscan (multi-workflow) side-panel +- Responsive web design (from desktop to table to mobile) +- Tabbed interface to display multiple workflow views +- Command integration for interacting with task, jobs, and schedulers + +Cylc UI Server +-------------- + +- Interacts with Schedulers and the filesystem +- Serves the UI to users +- Can be launched by the privileged Hub, for multi-user installations +- Or run standalone for use by a single user +- (The UI Server is a `Jupyter Server + `_ extension) + +Cylc Hub +-------- + +- For proving the UI in multi-user setups. +- Authenticates users, spawns and proxies Cylc UI Servers +- Can run as a regular or privileged user +- (The Hub is a `Jupyterhub `_ instance) + +Network layers +-------------- + +- Incremental push updates (c.f. polled full-state updates in Cylc 7) + +Further Reading +--------------- + +.. toctree:: + :maxdepth: 2 + + ui-server + data-flow diff --git a/nightly_8.4/html/_sources/reference/architecture/ui-server.rst.txt b/nightly_8.4/html/_sources/reference/architecture/ui-server.rst.txt new file mode 100644 index 00000000000..0af147b37d8 --- /dev/null +++ b/nightly_8.4/html/_sources/reference/architecture/ui-server.rst.txt @@ -0,0 +1,117 @@ +.. _CylcUIServer.architecture: + +Cylc UI Server +============== + +`Cylc Flow`_ + Provides a command line utility for monitoring and controlling + Cylc workflows called ``cylc tui``. +`Cylc UI Server`_ + Provides a graphical utility for use in a web browser. + +The `Cylc UI Server`_ connects to running workflows to provide "live" data +and accesses workflow databases and the filesystem to provide "offline" data. + + +Jupyter Server +-------------- + +The `Cylc UI Server`_ is a `Jupyter Server`_ extension like `Jupyter Lab`_. + +`Jupyter Server`_ provides the web server infrastructure which is shared by +its extensions which can used to run multiple extensions simultaneously. + +If desired other extensions (e.g. `Jupyter Lab`_) can be installed and +configured to run in the same server as the `Cylc UI Server`_. + +See :ref:`managing-multiple-extensions` for details on managing which +extensions are run by `Jupyter Server`_. + +`Jupyter Server`_ can be run in two ways, single-user (token authenticated) +and multi-user (hub authenticated). + + +.. _single-user mode: + +Single-User Mode +---------------- + +In single-user mode users must start their own UI Servers from the command line. + +`Jupyter Server`_ will provide them with a URL to access their server including +a secure token which provides authentication. + +.. admonition:: Authentication Overview + :class: hint + + See :ref:`server_security`: + +Users can only monitor and control their own workflows. + +.. image:: img/gui-arch-single-user.svg + :width: 70% + :align: center + + +Jupyter Hub +----------- + +.. _Cylc Hub configuration file: https://github.com/cylc/cylc-uiserver/blob/master/cylc/uiserver/jupyter_config.py + +`Jupyter Hub`_ is a multi-user server which spawns and manages a configured +service for authenticated users. + +The "Cylc Hub" is a Jupyter Hub instance which is pre-configured to spawn +Cylc UI Servers, launched by the ``cylc hub`` command. +It is also possible to configure Jupyter Hub yourself, see the Cylc Hub +configuration file for more information. + +Jupyter Hub supports a variety of different implementations and plugin interfaces +for: + +* `Authenticating users `_ +* `Spawning user's servers `_ +* `Proxying user's servers `_ + + +.. _multi-user mode: + +Multi-User Mode +---------------- + +Multi-user mode requires `Jupyter Hub`_ to be installed. + +An administrator must start `Jupyter Hub`_ under a user account with +the required privileges to spawn UI Servers on behalf of the user. + +Users then visit `Jupyter Hub`_ where they authenticate. `Jupyter Hub`_ +spawns UI Servers on behalf of users and provides each with a fixed URL +(derived from the user name) using the configured proxy +(usually `Configurable HTTP Proxy`_). + +Users can access each other's UI Servers providing they have been granted +permission. + +*Authentication* is provided by either `Jupyter Server`_ or `Jupyter Hub`_. + +*Authorization* in the `Cylc UI Server`_ is provided by Cylc. In +multi-user mode this allows users to connect to each other's UI Servers for +monitoring or control purposes. + +For more information on security and configuration see +:ref:`cylc.uiserver.multi-user`. + +.. _Jupyter Hub technical overview: https://jupyterhub.readthedocs.io/en/stable/reference/technical-overview.html + +For information on the architecture of `Jupyter Hub`_ and the +`Configurable HTTP Proxy`_ see the `Jupyter Hub technical overview`_. + +.. admonition:: Authentication Overview + :class: hint + + .. _Security In Jupyter Hub: https://jupyterhub.readthedocs.io/en/stable/reference/websecurity.html + + See `Security In Jupyter Hub`_. + +.. image:: img/gui-arch-multi-user.svg + :width: 100% diff --git a/nightly_8.4/html/_sources/reference/changes.rst.txt b/nightly_8.4/html/_sources/reference/changes.rst.txt new file mode 100644 index 00000000000..0138bd8c26d --- /dev/null +++ b/nightly_8.4/html/_sources/reference/changes.rst.txt @@ -0,0 +1,437 @@ +Changes +======= + +.. _cylc-flow-changelog: https://github.com/cylc/cylc-flow/blob/master/CHANGES.md +.. _cylc-uiserver-changelog: https://github.com/cylc/cylc-uiserver/blob/master/CHANGES.md +.. _cylc-ui-changelog: https://github.com/cylc/cylc-ui/blob/master/CHANGES.md +.. _cylc-rose-changelog: https://github.com/cylc/cylc-rose/blob/master/CHANGES.md +.. _metomi-rose-changelog: https://github.com/metomi/rose/blob/master/CHANGES.md +.. _metomi-isodatetime-changelog: https://github.com/metomi/isodatetime/blob/master/CHANGES.md + +This page contains a summary of significant changes across all Cylc components for each +release. + +For more detail see the component changelogs: + +* `cylc-flow-changelog`_ +* `cylc-uiserver-changelog`_ +* `cylc-ui-changelog`_ +* `cylc-rose-changelog`_ +* `metomi-rose-changelog`_ +* `metomi-isodatetime-changelog`_ + +---------- + +Cylc 8.3 +-------- + +.. admonition:: Cylc Components + :class: hint + + :cylc-flow: `8.3 `__ + :cylc-ui: `2.5 `__ + :cylc-uiserver: `1.5 `__ + :cylc-rose: `1.4 `__ + :rose: `2.3 `__ + + +Manually setting task outputs and prerequisites +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +At Cylc 8.3.0, the ``cylc set-outputs`` command has been replaced by the new +``cylc set`` command. + +The ``cylc set-outputs`` command made it look like an output had been generated +to downstream tasks, but did not update the task status to match. As a result, +it was often necessary to use ``cylc remove`` in combination with ``cylc +set-outputs``. + +The new ``cylc set`` command is able to directly set task outputs as if they +had completed naturally, making the command more intuitive and avoiding the +need for ``cylc remove``. It can also set prerequisites, as if they were satisfied naturally. + +For example, say there's a failed task holding up your workflow and you want +Cylc to continue as if the task had succeeded. Here are the interventions +you would need to perform with Cylc 8.2 and 8.3 side-by-side. + +.. list-table:: + :class: grid-table + :widths: 50 50 + + * - **Cylc 8.2** (set-outputs) + - **Cylc 8.3** (set) + * - .. code-block:: bash + + # let downstream tasks run: + cylc set-outputs + # remove the failed task: + cylc remove + + - .. code-block:: bash + + # tell Cylc that the task succeeded: + cylc set + + * - .. image:: changes/cylc-set-outputs.gif + :align: center + :width: 100% + + - .. image:: changes/cylc-set.gif + :align: center + :width: 100% + + +Tui +^^^ + +The Tui (terminal user interface) is a command line version of the Gui. +You can use it to monitor and control your workflows. + +There has been a major update to Tui at Cylc 8.3.0: + +* Larger workflows will no longer cause Tui to time out. +* You can now browse all your workflows including stopped workflows. +* You can monitor multiple workflows at the same time. +* The workflow and job logs are now available from within Tui. + +.. image:: changes/tui-1.gif + :width: 100% + + +N-Window selector in the GUI +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The :term:`n-window` determines how much of a workflow is visible in the GUI / Tui. + +The ``n=0`` window contains only the active tasks +(i.e. queued, preparing, submitted or running tasks). + +The ``n=1`` window, also contains tasks one "edge" out from active tasks +(i.e. the tasks immediately upstream or downstream of active tasks). + +The ``n=2`` window, also contains tasks two "edges" out from active tasks, +and so on. + +It is now possible to change the window extent in the GUI via a button in the +toolbar allowing you to see tasks further back in the workflow's history. + +.. image:: changes/gui-n-window-selector.gif + :width: 100% + +.. note:: + + This is currently a per-workflow setting so changing the n-window in one + browser tab will also change it in other browser tabs and Tui sessions. + +.. warning:: + + Using high n-window values with complex workflows may have performance + impacts. + + +Group by cycle point in the graph view +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The graph view now has an option to group tasks by cycle point. + +.. image:: changes/cylc-graph-group-by-cycle-point.png + :width: 100% + +Gantt View +^^^^^^^^^^ + +The GUI now has a `Gantt `_ view option: + +.. image:: changes/gantt_view.png + :width: 100% + :alt: A picture of the Gantt view in operation. + +Analysis View +^^^^^^^^^^^^^ + +New Analysis added - a layout which plots run times against cycle points. + + +.. image:: changes/time_series.png + :width: 100% + :alt: A picture of the Time Series task analysis in operation. + + +Completion Expressions +^^^^^^^^^^^^^^^^^^^^^^ + +When a task achieves a final status, its outputs are validated against a "completion +expression" to ensure that it has produced all of its +:term:`required outputs `. +If a task fails this validation check it is said to have "incomplete outputs" +and will be retained in the :term:`active window` pending user intervention. + +This completion expression is generated automatically from the graph. +By default, tasks are expected to succeed, if you register any additional +required output in the graph, then these must also +be produced. + +At Cylc 8.3.0 it is now possible to manually configure this completion +expression for finer control. This is particularly useful for anyone using +:term:`custom outputs `. + +For example, ``mytask`` must produce one of the outputs ``x`` or ``y`` to pass +the completion expression configured here: + +.. code-block:: cylc + + [runtime] + [[mytask]] + completion = succeeded and (x or y) + [[[outputs]]] + x = output-x + y = output-y + +For more information, see the reference for the +:cylc:conf:`[runtime][]completion` configuration. + + +Workflow State Triggers & Commands +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Workflow state xtriggers and command now take Cylc universal IDs instead of +separate arguments: + +For example, you can (and should) now write: + +.. code-block:: diff + + # On the command line + - cylc workflow-state my-workflow --point 20240101 --task mytask --message "succeeded" + + cylc workflow-state my-workflow//20240101/mytask:succeeded --triggers + + # In the flow.cylc file + - my_xtrigger = workflow_state( + - workflow="my-workflow", + - task="mytask", + - point="20240101", + - message="succeeded" + - ) + + my_xtrigger = workflow_state('my-workflow//20240101/mytask:succeeded', is_trigger=True) + +.. important:: + + The new workflow state trigger syntax can use either the trigger or message from + ``trigger=message`` in :cylc:conf:`[runtime][][outputs]`. + + The trigger and message are the same for the most common use cases (``succeeded`` and ``started``) + but may differ for other outputs, namely :term:`custom outputs `. + +.. note:: + + The ``suite-state`` xtrigger has been reimplemented for compatibility with + Cylc 7 workflows. + +---------- + +Cylc 8.2 +-------- + +.. admonition:: Cylc Components + :class: hint + + :cylc-flow: `8.2 `__ + :cylc-uiserver: `1.4 `__ + :cylc-rose: `1.3 `__ + + +UI now remembers workspace tab layout +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: cylc-uiserver 1.4.4 + +The UI now remembers the layout of your workspace tabs when you navigate away +from that workflow. Note that this only applies per browser session. + +.. image:: changes/ui-workspace-tabs.gif + :width: 100% + +Cylc ignores ``$PYTHONPATH`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Cylc now ignores ``$PYTHONPATH`` to make it more robust to task +environments which set this value. If you want to add to the Cylc +environment itself, e.g. to install a Cylc extension, +use a custom xtrigger, or event handler use ``$CYLC_PYTHONPATH``. + +Upgrade To The Latest Jupyter Releases +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: cylc-uiserver 1.4.0 + +The Cylc UI Server has been updated to work with the latest releases of +`Jupyter Server`_ and `Jupyter Hub`_. + +If you are utilising Cylc's multi-user functionality then your configuration +will require some changes to work with these releases. + +See :ref:`cylc.uiserver.multi-user` for more details + +.. versionadded:: cylc-uiserver 1.3.0 + +You can now configure the view which is opened by default when you navigate to +a new workflow in the GUI. Navigate to the settings page to select your chosen +view. + +.. image:: changes/ui-view-selector.jpg + :width: 100% + +In the future we plan to support configuring a layout of multiple views and +configuring certain options on those views. + + +Reload +^^^^^^ + +.. versionadded:: cylc-flow 8.2.0 + +When workflows are +:ref:`reloaded `, +(e.g. by ``cylc reload``), Cylc will now pause the workflow and wait for any +preparing tasks to be submitted before proceeding with the reload. +Once the reload has been completed, the workflow will be resumed. + +You can now see more information about the status of the reload in the +workflow status message which appears at the top of the GUI and Tui interfaces. + +---------- + +Cylc 8.1 +-------- + +.. admonition:: Cylc Components + :class: hint + + :cylc-flow: `8.1 `__ + :cylc-uiserver: `1.2 `__ + :cylc-rose: `1.1 `__ + +.. warning:: + + Workflows started with Cylc 8.0 which contain multiple :term:`flows ` + **cannot** be restarted with Cylc 8.1 due to database changes. + + +Analysis View +^^^^^^^^^^^^^ + +.. versionadded:: cylc-uiserver 1.2.2 + +The web UI also has a new view for displaying task queue & run time statistics. + +.. image:: changes/analysis_view.gif + :width: 80% + + +Graph View +^^^^^^^^^^ + +.. versionadded:: cylc-uiserver 1.2.0 + +The web UI now has a graph view which displays a visualisation of a workflow's graph: + +.. image:: changes/cylc-graph.gif + :width: 80% + +Family & cycle grouping as well as the ability to view graphs for stopped workflows +will be added in later releases. + + +Log View +^^^^^^^^ + +.. versionadded:: cylc-uiserver 1.2.0 + +The web UI now has a log view which displays workflow and job log files: + +.. image:: changes/log-view-screenshot.png + :width: 80% + +Support for viewing more log files, syntax highlighting, searching and line +numbers are planned for future releases. + + +Edit Runtime +^^^^^^^^^^^^ + +.. versionadded:: cylc-uiserver 1.2.0 + +The web UI now has a command for editing the :cylc:conf:`[runtime]` section +of a task or family. + +.. image:: changes/edit-runtime-screenshot.png + :width: 80% + +Any changes made are :ref:`broadcast ` to the running workflow. + + +Combined Commands +^^^^^^^^^^^^^^^^^ + +.. versionadded:: cylc-flow 8.1.0 + +Two new commands have been added as short-cuts for common working patterns: + +``cylc vip`` + Validate, install and plays a workflow, equivalent to: + + .. code-block:: bash + + cylc validate + cylc install + cylc play + +``cylc vr`` + Validate and reinstall a workflow, then either: + - reload the workflow if it is running. + - restart the workflow if it is stopped. + +.. image:: changes/vip-vr.gif + :width: 100% + +For more information see the command line help: + +.. code-block:: bash + + cylc vip --help + cylc vr --help + + +Bash Completion +^^^^^^^^^^^^^^^ + +.. versionadded:: cylc-flow 8.1.0 + +Cylc now provides a high performance Bash completion script which saves you typing: + +* Cylc commands & options +* Workflow IDs +* Cycle points +* Task names +* Job numbers + +.. image:: changes/cylc-completion.bash.gif + :width: 80% + +:ref:`Installation instructions `. + +---------- + +Cylc 8.0 +-------- + +.. admonition:: Cylc Components + :class: hint + + :cylc-flow: `8.0 `__ + :cylc-uiserver: `1.1 `__ + :cylc-rose: `1.1 `__ + +The first official release of Cylc 8. + +For a summary of changes see the :ref:`migration guide<728.overview>`. diff --git a/nightly_8.4/html/_sources/reference/config/file-format.rst.txt b/nightly_8.4/html/_sources/reference/config/file-format.rst.txt new file mode 100644 index 00000000000..88ab7fe0d16 --- /dev/null +++ b/nightly_8.4/html/_sources/reference/config/file-format.rst.txt @@ -0,0 +1,176 @@ +.. _file-format: + +The .cylc File Format +===================== + +Cylc global and workflow configuration files are written in a nested +`INI`_-based format. + +.. _syntax: + +Syntax +------ + +Comments + Comments follow a ``#`` character. + +Settings + Configuration items (settings) are written as ``key = value`` pairs, and can + be contained within sections. Setting names (the keys) may contain spaces. + +String Values + Quoting single-line string values is optional: + + .. code-block:: cylc + + [animals] + cat = dusty + dog = "fido" # or single quotes: 'fido' + + Multiline string values must be triple-quoted: + + .. code-block:: cylc + + [song] + lyrics = """ # (or triple single-quotes: '''value''') + No stop signs + Speed limit + Nobody's gonna slow me down + """ + +List Values + List values are comma-separated: + + .. code-block:: cylc + + animals = dusty, fido, cujo + + +Boolean Values + Booleans are capitalized: + + .. code-block:: cylc + + ice cream is good = True # or False + + +Sections and Sub-sections + Settings have a level-dependent number of square brackets: + + .. code-block:: cylc + + [section] + [[sub-section]] + [[[sub-sub-section]]] + + +Indentation + It is advisable to indent sections and subsections, for clarity. However, + Cylc ignores indentation, so this: + + .. code-block:: cylc + + [section] + a = A + [[sub-section]] + b = B + b = C # WARNING: this is still in sub-section! + + is equivalent to this: + + .. code-block:: cylc + + [section] + a = A + [[sub-section]] + b = C + + +Duplicate Sections and Items + Duplicate sections get merged into one. Duplicate settings overwrite + previously defined values. So this: + + .. code-block:: cylc + + [animals] + cat = fluffy + [animals] + dog = fido + cat = dusty + + is equivalent to this: + + .. code-block:: cylc + + [animals] + cat = dusty + dog = fido + + + The only exception to this rule is :term:`graph strings `, + which get merged. So these graph strings: + + .. code-block:: cylc-graph + + R1 = "foo => bar" + R1 = "foo => baz" + + merge to this: + + .. code-block:: cylc-graph + + R1 = "foo => bar & baz" + + +Continuation lines + If necessary, you can continue on the next line after a backslash character: + + .. code-block:: cylc + + verse = "the quick \ + brown fox" + + However, backslash line continuation is fragile (trailing invisible + whitespace breaks it). Long :term:`graph strings ` strings + should be split on graph symbols instead: + + .. code-block:: cylc-graph + + R1 = """ + (foo & bar ) | + baz => + qux + """ + # Equivalent to: + R1 = """ + (foo & bar ) | baz => qux + """ + +Include-files + ``flow.cylc`` fragments can be included verbatim with the ``%include`` + directive. Include-files can be included multiple times, and even nested. + Include-file paths should relative to the ``flow.cylc`` location: + + .. code-block:: + + %include "inc/site-a.cylc" + + :ref:`Jinja2's ` template inclusion mechanism can be used with Cylc + too. + +.. _config_item_shorthand: + +Shorthand +--------- + +.. include:: shorthand.rst + +.. code-block:: cylc + + # This: + # [runtime][task-a][environment]FOO = foo + # Means: + [runtime] + [[task-a]] + [[[environment]]] + FOO = foo diff --git a/nightly_8.4/html/_sources/reference/config/global.rst.txt b/nightly_8.4/html/_sources/reference/config/global.rst.txt new file mode 100644 index 00000000000..292d7ce4ef5 --- /dev/null +++ b/nightly_8.4/html/_sources/reference/config/global.rst.txt @@ -0,0 +1,8 @@ +.. _global-configuration: + +Global Configuration +==================== + +Cylc global configurations use the :ref:`.cylc file format `. + +.. auto-cylc-conf:: cylc.flow.cfgspec.globalcfg.SPEC diff --git a/nightly_8.4/html/_sources/reference/config/index.rst.txt b/nightly_8.4/html/_sources/reference/config/index.rst.txt new file mode 100644 index 00000000000..b103617d703 --- /dev/null +++ b/nightly_8.4/html/_sources/reference/config/index.rst.txt @@ -0,0 +1,13 @@ +Configuration +============= + +.. toctree:: + :maxdepth: 2 + + file-format + workflow + global + ui-server + sharing-access-to-workflows + types + writing-platform-configs diff --git a/nightly_8.4/html/_sources/reference/config/sharing-access-to-workflows.rst.txt b/nightly_8.4/html/_sources/reference/config/sharing-access-to-workflows.rst.txt new file mode 100644 index 00000000000..637d2e70c33 --- /dev/null +++ b/nightly_8.4/html/_sources/reference/config/sharing-access-to-workflows.rst.txt @@ -0,0 +1,438 @@ +.. _cylc.uiserver.multi-user: + +Authorizing Others to Access Your Workflows +=========================================== + +For multi-user setups, the Cylc web GUI can be deployed as part of a +`Jupyter Hub`_ setup where a central service spawns servers on behalf of users. + +The Cylc UI Server can be configured to allow specified users to monitor and +optionally control workflows running under other user accounts. + +This has many use cases including: + +* Collaborative research setups where multiple users need to access the same + workflow. +* Production systems where different levels of support may have different + levels of access. +* Support where administrators may require access to users workflows. + +A multi-user Cylc setup consists of three components: + +1. `Jupyter Hub`_ +2. `Jupyter Server`_ +3. `Cylc UI Server`_ + +And may additionally include other Jupyter Server extensions such as +`Jupyter Lab`_ to provide a full interactive virtual workstation in the +browser. + +In order to allow access to other users servers, to permit the monitoring and +optionally control of other users workflows, each of these three components +must be configured: + +1. `Jupyter Hub`_ must be configured to allow connections to other users servers. +2. The `Jupyter Server`_ authorisation policy must be set. +3. Cylc must be configured with user permissions. + +This configuration can all be performed in the same Jupyter / Cylc UI Server +configuration file. See :ref:`UI_Server_config` for more details. + +.. rubric:: Quick Example: + +.. code-block:: python + + # /etc/cylc/uiserver/jupyter_config.py + + # 1. Jupyter Hub + # Allow all authenticated users to access, start and stop + # each other's servers + c.JupyterHub.load_roles = [ + { + "name": "user", + "scopes": ["self", "access:servers", "servers"], + } + ] + + + # 2. Jupyter Server + # Set a safe authorisation policy for multi-user setups + # Note: This is ONLY necessary if you are deploying the Cylc UI Server + # using commands other than `cylc hub` and `cylc hubapp`, + # otherwise, it is the default. + from cylc.uiserver.authorise import CylcAuthorizer + c.ServerApp.authorizer_class = CylcAuthorizer + + + # 3. Cylc + # Delegate permissions to users + c.CylcUIServer.user_authorization = { + # provide all authenticated users with read-only access to each other's + # servers + "*": ["READ"], + } + +The rest of this document takes you through each of these configurations, some +of the key options and how they relate to their respective systems. + + +.. _jupyterhub.authorization: + +Jupyter Hub Authorisation +------------------------- + +By default, `Jupyter Hub`_ only allows users to access their own servers. + +In order to allow access to other users' servers, two scopes must be configured: + +``access:servers`` + Permits us to connect to another user's server. +``servers`` + Permits us to start another user's server. + +This is done using the +:py:attr:`c.JupyterHub.load_roles ` +configuration. +For more information see the +:ref:`JupyterHub scopes reference `. + +Example: + +.. code-block:: python + + # /etc/cylc/uiserver/jupyter_config.py + + c.JupyterHub.load_roles = [ + { + # allow all authenticated users to access, start and stop + # each other's servers + "name": "user", + "scopes": ["self", "access:servers", "servers"], + } + ] + + +.. _jupyterserver.authorization: + +Jupyter Server Authorisation +---------------------------- + +.. tip:: + + You can skip this section if you are starting Jupyter Hub using ``cylc hub`` + command and have not overridden the + :py:attr:`c.JupyterHub.spawner_class ` + configuration (so are spawning the ``cylc hubapp`` command). + +.. autoclass:: cylc.uiserver.authorise.CylcAuthorizer + + +.. _cylc.uiserver.user_authorization: + +Cylc User Authorisation +----------------------- + +Cylc Authorisation is configurable on a per-user and per-command basis but +not on a per-workflow basis. + +By default users can only see and interact with their own workflows. + +Sites can restrict the permissions that users are allowed to grant each +other and can configure default permissions (see :ref:`site_configuration`). + +Authorization is configured by these two configurations: + +* :py:attr:`c.CylcUIServer.user_authorization + ` (user configuration) +* :py:attr:`c.CylcUIServer.site_authorization + ` (site configuration) + +.. rubric:: Example: + +.. code-block:: python + + # ~/.cylc/uiserver/jupyter_config.py + + c.CylcUIServer.user_authorization = { + # : [, ...], + + # allow "user1" to monitor my workflows + "user1": ["READ"], + + # allow "user2" to monitor and trigger tasks in my workflows + "user2": ["READ", "Trigger"], + } + + +Users +^^^^^ + +There are three methods of identifying a user to grant access to: + +```` + Configures permissions for a single user. +``group:`` + Configures a user group. For more information, see :ref:`group_support`. +``*`` + Configures permissions for any authenticated user (see + :ref:`Jupyter Hub authenticators reference ` + for details). + +.. note:: + + Using glob patterns to match user and group names is + not currently supported. + + +Permissions +^^^^^^^^^^^ + +.. TODO: autogenerate this permission list + https://github.com/cylc/cylc-uiserver/issues/466 + +Permissions can be granted for each Cylc command individually. For convenience, +commands are arranged into groups to avoid having to list them individually: + +``READ`` (i.e. read-only access) + A user with read permissions may view workflows, monitor tasks states and + open log files, but they cannot interact with the workflows. + + * ``Read`` +``CONTROL`` (e.g. start & stop workflows) + A user with control permissions may issue commands to interact with workflows + and can start/stop workflows but cannot redefine the workflow configuration + itself (without direct filesystem access). + + * ``Clean`` + * ``Ext-trigger`` + * ``Hold`` + * ``Kill`` + * ``Message`` + * ``Pause`` + * ``Play`` + * ``Poll`` + * ``Release`` + * ``ReleaseHoldPoint`` + * ``Reload`` + * ``Remove`` + * ``Resume`` + * ``SetGraphWindowExtent`` + * ``SetHoldPoint`` + * ``SetOutputs`` + * ``SetVerbosity`` + * ``Stop`` + * ``Trigger`` +``ALL`` (i.e. full control) + A user with all permissions may alter task configuration so may inject + arbitrary code into the workflow. + + * ``Broadcast`` + +.. note:: + + With the exception of ``Read`` all of the above permissions map onto the + Cylc GraphQL mutations which themselves map onto the command line. + + E.G. the ``Play`` permission maps onto ``mutation play`` in the GraphQL + schema and ``cylc play`` on the command line. + + To find out more about a command, see the GraphQL or CLI documentation. + +By default, users have full permissions (``READ``, ``CONTROL`` and ``ALL``) for their own workflows and no +permissions for other users' workflows. + +Permissions are additive, so for example, granting ``READ`` and ``CONTROL`` +would provide all of the permissions from those two groups. + +The ``!`` character can be used to subtract permissions, e.g. delegating +``CONTROL`` and ``!Stop`` would provide all control permissions except stop. + +.. note:: + + Granting access to a group does not automatically grant access to lower + groups e.g. granting ``CONTROL`` access does not automatically grant + ``READ`` access. + + +Examples +^^^^^^^^ + +.. code-block:: python + + # ~/.cylc/uiserver/jupyter_config.py + + c.CylcUIServer.user_authorization = { + "*": ["READ"], + "group:groupA": ["CONTROL"], + "user1": ["read", "pause", "!play"], + "user2": ["!ALL"] + } + +In this scenario: + +- ``"*"`` represents any authenticated user. They have permission to view all + workflows on the GUI. +- ``"group:groupA"`` applies ``CONTROL`` permissions to any member of system + ``groupA``. + Note that, since permissions are inherited, these users will gain ``READ`` access + from the ``"*":["READ"]`` assignment. +- ``"user1"`` will have permission to view workflows, ``pause`` but not ``play`` + workflows, even if ``user1`` is a member of the system ``groupA``. This is due + to negations taking precedence over additions. +- ``"user2"`` is not permitted to view workflows, or perform any operations. + + +.. _site_configuration: + +Cylc Site Configuration +----------------------- + +The :py:attr:`c.CylcUIServer.site_authorization +` configuration allows sites +to configure sensible defaults and limits for the permissions users can +grant. + +It takes the form: + +.. code-block:: python + + { + "": { + "": { + "default": [], + "limit": [] + } + } + } + +Where ```` is the username of the account that is running a server and +```` is the username of an account trying to connect to it. + +Sites can set both limits and defaults for users: + +``limit`` + Determines the maximum access users can grant to their workflows. +``default`` + Sets a default access level, which applies if the user does not appear in + the user_authorization configuration (via explicit user name or group). + + Note, these defaults apply only if a user does not appear in + :py:attr:`c.CylcUIServer.user_authorization + `. + +* If a limit is not set but a default is, then the limit is the default. +* If a default is not set but a limit is, then the default is no access. + +.. note:: + + As the UI Server runs as the workflow owner, the owner has full control over + it and in theory may bypass these restrictions in a variety of ways. As an + extreme example, a workflow owner could pass their account credentials to + another person. This cannot be prevented by technical means. However, a + workflow owner cannot unilaterally gain access to any other user's account + or workflows by configuring their own UI Server. + +.. note:: + + Changes to the Cylc authorization configuration will take effect when the + Cylc UI Server is restarted. + + +.. _group_support: + +Group Support +^^^^^^^^^^^^^ + +Unix-like systems support user groups. Cylc authorization supports granting +access by membership of these system groups. You can indicate a system group +by using the ``group:`` indicator. + +System groups are found by +:py:mod:`get_groups` + +.. autofunction:: cylc.uiserver.authorise.get_groups + + +Example Site Authorization Configuration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Whilst most site configurations will be simpler than the example below, this +example provides an indication of the combinations available. + +.. code-block:: python + + # /etc/cylc/uiserver/jupyter_config.py + + c.CylcUIServer.site_authorization = { + "*": { # For all ui-server owners, + "*": { # Any authenticated user + "default": "READ", # Will have default read-only access + }, + "user1": { # for all ui-server owners, user1 + "default": ["!ALL"], # has no privileges by default + }, # No limit set, so all ui-server owners are unable to permit user1 + }, + "server_owner_1": { # For specific UI Server owner, server_owner_1 + "*": { # Any authenticated user + "default": "READ", # Will have default read-only access + "limit": ["READ", "CONTROL"], # server_owner_1 is able to give away + }, # READ and CONTROL privileges. + }, + "server_owner_2": { # For specific UI Server owner, + "user2": { # Specific user2 + "limit": "ALL" # Can only be granted a maximum of ALL by + }, # server_owner2, default access for user2 falls back to + # standard READ only (if server_owner_2/user2 are + # included in other auth config e.g. the top example), + # or none if not in any other auth config sections. + "group:groupA": { # group denoted with a `group:` + "default": [ + "READ", + "CONTROL", + ] # groupA has default READ, CONTROL access to server_owner_2's + }, # workflows + }, + "group:grp_of_svr_owners": { # Group of users who own UI Servers + "group:groupB": { + "default": "READ", # can grant groupB users up to READ and CONTROL + "limit": [ # privileges, without stop and kill + "READ", + "CONTROL", + "!stop", # operations + "!kill", + ], + }, + }, + } + + +Interacting with Others' Workflows +---------------------------------- + +.. spelling:word-list:: + + userA + userB + +If you have been granted access to another user's workflows, you can view and +interact with these workflows. +Say, you, userA, wish to interact with userB's workflows. +You can do this by navigating to the URL ``https:///user/userB``, using +the hub of userB. You should authenticate as yourself (userA) and, provided you +have the correct permissions, you will see userB's workflows for interaction. + +.. note:: + + Operations that are not authorized will appear greyed out on the UI. + + +Troubleshooting Authorization +----------------------------- + +If authorization is not performing as expected, check + +- you are permitted by the site configuration to give away access. +- you have provided ``read`` permissions, which enables the user to see your + workflows. +- check the spelling in your configuration. The correct spelling is + ``c.CylcUIServer.user_authorization`` diff --git a/nightly_8.4/html/_sources/reference/config/shorthand.rst.txt b/nightly_8.4/html/_sources/reference/config/shorthand.rst.txt new file mode 100644 index 00000000000..2239ba890b4 --- /dev/null +++ b/nightly_8.4/html/_sources/reference/config/shorthand.rst.txt @@ -0,0 +1,12 @@ +We often use a compact single-line notation to refer to nested config items: + +``[section]`` + An entire section. +``[section]setting`` + A setting within a section. +``[section]setting=value`` + The value of a setting within a section. +``[section][sub-section]another-setting`` + A setting within a sub-section. + +In the file, however, section headings need additional brackets at each level. diff --git a/nightly_8.4/html/_sources/reference/config/types.rst.txt b/nightly_8.4/html/_sources/reference/config/types.rst.txt new file mode 100644 index 00000000000..2ad2011ec97 --- /dev/null +++ b/nightly_8.4/html/_sources/reference/config/types.rst.txt @@ -0,0 +1,8 @@ +Cylc Configuration Data Types +============================= + +The Cylc configuration file format supports the following data types. + +.. auto-cylc-type:: + cylc.flow.parsec.validate.ParsecValidator.V_TYPE_HELP + cylc.flow.parsec.validate.CylcConfigValidator.V_TYPE_HELP diff --git a/nightly_8.4/html/_sources/reference/config/ui-server.rst.txt b/nightly_8.4/html/_sources/reference/config/ui-server.rst.txt new file mode 100644 index 00000000000..87e0b222491 --- /dev/null +++ b/nightly_8.4/html/_sources/reference/config/ui-server.rst.txt @@ -0,0 +1,16 @@ +.. _UI_Server_config: + +UI Server Configuration +======================= + +Cylc UI Server can be configured using a ``jupyter_config.py``. + +Site level configuration, such as ``c.CylcUIServer.site_authorization`` should +be defined in ``/etc/cylc/uiserver/jupyter_config.py``, or, alternatively, the +environment variable ``CYLC_SITE_CONF_PATH``. +User level configuration should be located in ``~/.cylc/uiserver/jupyter_config.py``. + +.. automodule:: cylc.uiserver.app + +.. autoconfigurable:: cylc.uiserver.app.CylcUIServer + :inherited-members: False diff --git a/nightly_8.4/html/_sources/reference/config/workflow.rst.txt b/nightly_8.4/html/_sources/reference/config/workflow.rst.txt new file mode 100644 index 00000000000..37bb0a8e73a --- /dev/null +++ b/nightly_8.4/html/_sources/reference/config/workflow.rst.txt @@ -0,0 +1,8 @@ +.. _workflow-configuration: + +Workflow Configuration +====================== + +Cylc workflow configurations use the :ref:`.cylc file format `. + +.. auto-cylc-conf:: cylc.flow.cfgspec.workflow.SPEC diff --git a/nightly_8.4/html/_sources/reference/config/writing-platform-configs.rst.txt b/nightly_8.4/html/_sources/reference/config/writing-platform-configs.rst.txt new file mode 100644 index 00000000000..3343587ba2d --- /dev/null +++ b/nightly_8.4/html/_sources/reference/config/writing-platform-configs.rst.txt @@ -0,0 +1,443 @@ + +.. _AdminGuide.PlatformConfigs: + +Platform Configuration +====================== + +Writing Platform Configurations +------------------------------- + +.. versionadded:: 8.0.0 + +.. seealso:: + + - :ref:`Platforms Cylc 7 to 8 user upgrade guide `. + - :cylc:conf:`flow.cylc[runtime][]platform` + - :cylc:conf:`global.cylc[platforms]` + - :cylc:conf:`global.cylc[platforms][]install target` + +.. _ListingAvailablePlatforms: + +Listing available platforms +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you are working on an institutional network, platforms may already +have been configured for you. + +To see a list of available platforms:: + + cylc config --platform-names + +To see the full configuration of available platforms:: + + cylc config --platforms + +This is equivalent to ``cylc config -i 'platforms' -i 'platform groups'`` + +What Are Platforms? +^^^^^^^^^^^^^^^^^^^ + +Platforms define settings, most importantly: + + - A set of ``hosts``. + - A ``job runner`` (formerly a ``batch system``) where Cylc can submit a job. + - An ``install target`` for Cylc to install job files on. + +Why Were Platforms Introduced? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Allow a compute cluster with multiple login nodes to be treated as a single + unit. +- Allow Cylc to elegantly handle failure to communicate with login nodes. +- Reduce the number of ssh connections required for job submission and polling. + +.. _Install Targets: + +What Are Install Targets? +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Install targets represent file systems. More than one platform can use the +same file system. Cylc relies on the site configuration file ``global.cylc`` to determine +which platforms share install targets. + +Cylc will setup each remote install target once. During setup it will: + + - Install workflow files + - Symlink directories + - Copy authentication keys (to allow secure communication) + +Note, if missing from configuration, the install target will default to the +platform name. If incorrectly configured, this will cause errors in +:ref:`RemoteInit`. + +If you log into one system and see the same files as on another, then these two +platforms will require the same install target in ``global.cylc`` config file. + +Example Platform Configurations +------------------------------- + +Detailed below are some examples of common platform configurations. + +Submit PBS Jobs from Localhost +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- **The** :term:`scheduler` **runs on the** ``localhost`` **platform.** +- **Platforms can share hosts without sharing job runners.** + +.. admonition:: Scenario + + You have a cluster where you can submit jobs from the Cylc scheduler host + using PBS. + +The ``localhost`` platform is the Cylc Scheduler host, as configured in +:cylc:conf:`global.cylc[scheduler][run hosts]available`. This is the host that +the workflow will start on. For more information, see +:ref:`Platform Configuration`. + +Our platform ``pbs_cluster`` shares this ``localhost`` host and setting the +install target to ``localhost`` ensures that Cylc knows this platform does not +require remote initialization. + +.. code-block:: cylc + :caption: part of a ``global.cylc`` config file + + [platforms] + # The localhost platform is available by default + # [[localhost]] + # hosts = localhost + # install target = localhost + [[pbs_cluster]] + hosts = localhost + job runner = pbs + install target = localhost + +Our Cylc scheduler does not have a job runner defined. Any job submitted to +this ``localhost`` platform will run as a background job. Users can now set +:cylc:conf:`flow.cylc[runtime][]platform` = ``pbs_cluster`` to run +pbs jobs. + +.. note:: + + Both ``hosts`` and ``install target`` default to the platform name. + +Multiple Platforms Sharing File System with Cylc Scheduler +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- **Platform names can be defined as regular expressions.** + +.. admonition:: Scenario + + Everyone in your organization has a computer called ``desktopNNN``, + all with a file system shared with the scheduler host. Many users + will want their desktop set up as a platform to run small jobs. + +In this scenario, Cylc does not need to install files on the desktop, since +required files which are on the scheduler host will be accessible on the +desktop. From Cylc's point of view, the desktop and scheduler hosts are +considered different platforms but must share an :term:`install target`. +Cylc needs to be told that these platforms share an install target and so we +configure this using the designated configuration item: +:cylc:conf:`global.cylc[platforms][]install target`. + +:cylc:conf:`global.cylc[platforms][]` has optional configuration +``[[[meta]]]`` which users can view with ``cylc config --platforms``. We will add +a description designed to help users in this example. + +The following platform definition is simplified, taking advantage of defaults +for ``hosts`` and ``install targets``. + +.. code-block:: cylc + :caption: the ``global.cylc`` config file for this scenario could look like: + + [platforms] + [[desktop\d\d\d]] + install target = localhost + [[[meta]]] + description = "Background job on a desktop system" + +As before, a ``localhost`` platform is available by default. +``desktop\d\d\d`` is a pattern which defines multiple platforms. +When using a pattern the "hosts" setting must be left unset so that it defaults +to the platform name. This ensures each of the matching platforms is unique. + +.. note:: + + Cylc carries out a "fullmatch" regular expression comparison with the + the platform name so ``desktop\d\d\d`` is effectively the same as + ``^desktop\d\d\d$``. + +If a user wants to run a job on their local desktop, e.g. "desktop123", they should +set: + + .. code-block:: cylc + + [runtime] + [[mytask]] + platform = desktop123 + +in their workflow configuration. +If ``[runtime][mytask]platform`` is unset, the job will run on the Cylc +Scheduler host using this default ``localhost`` platform. + +Neither platforms will require remote initialization as the ``install target`` +is set to ``localhost``. + +Cluster with Multiple Login Nodes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- **Platforms with multiple hosts require job runner to be set** +- **Platforms can group multiple hosts together.** + +.. admonition:: Scenario + + You have a cluster where users submit jobs to Slurm from + either of a pair of identical login nodes which share a file system. + +.. code-block:: cylc + :caption: part of a ``global.cylc`` config file + + [platforms] + [[slurm_cluster]] + hosts = login_node_1, login_node_2 + job runner = slurm + retrieve job logs = True + +The ``slurm_cluster`` hosts do not share a file system with the scheduler, +therefore ``slurm_cluster`` is a remote platform. +As the ``install target`` setting for this platform has been omitted, this will +default to the platform name. +Cylc will initiate a remote installation, to transfer required files to +``slurm_cluster`` which will commence before job submission for the first job +on that platform. + +Cylc will attempt to communicate with jobs via the other login node if either +of the login_nodes becomes unavailable. + +With multiple hosts defined under ``slurm_cluster``, a job runner is required. + +.. note:: + + The "background" and "at" job runners require single-host platforms, + because the job ID is only valid on the submission host. + +We have set ``retrieve job logs = True``. This will ensure our job logs are +fetched from the ``slurm_cluster`` platform. This setting is recommended for +all remote platforms (i.e. where install target is not localhost). + + +Grouping Platforms +^^^^^^^^^^^^^^^^^^ + +- **Platform groups allow users to ask for jobs to be run on any + suitable computer.** + +.. admonition:: Scenario + + Extending the example from above, we now wish to set the ``slurm_cluster`` + up such that ``slurm_cluster`` nodes can accept background jobs. + We would like to group these background platforms together so users can set + :cylc:conf:`flow.cylc[runtime][]platform` = ``slurm_cluster_bg``. + +.. code-block:: cylc + :caption: part of a ``global.cylc`` config file + + [platforms] + [[slurm_cluster, slurm_cluster_bg1, slurm_cluster_bg2]] # settings that apply to all: + install target = slurm_cluster + retrieve job logs = True + [[slurm_cluster]] + batch system = slurm + hosts = login_node_1, login_node_2 + [[slurm_cluster_bg1]] + hosts = login_node_1 + [[slurm_cluster_bg2]] + hosts = login_node_2 + [platform groups] + [[slurm_cluster_bg]] + platforms = slurm_cluster_bg1, slurm_cluster_bg2 + +Group platforms together using the configuration item +:cylc:conf:`global.cylc[platform groups]`. In the above example, the +``slurm_cluster_bg`` platforms all share a file system +(install target = ``slurm_cluster``). We advise caution when grouping platforms +with different install targets as users could encounter a scenario whereby +files (created by a previous task using the same platform group) are +not available to them. + +With the above configuration, users can now run background jobs on either of +the login nodes, without the concern of selecting a specific platform. + +.. warning:: + + Platforms and platform groups are both configured by + :cylc:conf:`flow.cylc[runtime][]platform`. + Therefore a platform group cannot be given the same name as a platform. + The :cylc:conf:`global.cylc` file will fail validation if the same name is + used for both. + + +.. _SymlinkDirsSetup: + +Symlinking Directories +---------------------- + +To minimize the disk space used by ``~/cylc-run``, set +:cylc:conf:`global.cylc[install][symlink dirs]` to offload files onto other +locations. The entire :term:`run directory` can be symlinked, as well as +certain sub-directories. + +* ``run`` - the :term:`run directory` itself +* ``log`` +* ``share`` (see :term:`share directory`) +* ``share/cycle`` (typically used by `Rose`_ tasks) +* ``work`` (see :term:`work directory`) + +These should be configured per :term:`install target`. + +For example, to configure workflow ``log`` directories (on the +:term:`scheduler` host) so that they symlink to a different location, +you could write the following in ``global.cylc``: + +.. code-block:: cylc + + [install] + [[symlink dirs]] + [[[localhost]]] + log = /somewhere/else + +This would result in the following file structure on the Cylc scheduler host: + +.. code-block:: none + + ~/cylc-run + └── myflow + ├── flow.cylc + ├── log -> /somewhere/else/cylc-run/myflow/log + ... + + /somewhere + └── else + └── cylc-run + └── myflow + └── log + ├── flow-config + ├── install + ... + +These ``localhost`` symlinks are created during the cylc install process. +Symlinks for remote install targets are created during :ref:`RemoteInit` following +``cylc play``. + + +Advanced Platform Examples +-------------------------- + +Platform with no ``$HOME`` directory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. admonition:: Scenario + + You are trying to run jobs on a platform where the compute nodes don't + have a configured ``HOME`` directory. + +So long as the login and compute nodes share a filesystem the workflow can be +installed on the shared filesystem using +:cylc:conf:`global.cylc[install][symlink dirs]`. + +The ``$CYLC_RUN_DIR`` variable can then be set on the compute node to point +at the ``cylc-run`` directory on the shared filesystem using +:cylc:conf:`global.cylc[platforms][]global init-script`. + + .. code-block:: cylc + :caption: part of a ``global.cylc`` config file + + [platforms] + [[homeless-hpc]] + job runner = my-job-runner + install target = homeless-hpc + global init-script = """ + export CYLC_RUN_DIR=/shared/filesystem/cylc-run + """ + + [install] + [[symlink dirs]] + [[[homeless-hpc]]] + run = /shared/filesystem/ + +In this example Cylc will install workflows into +``/shared/filesystem/cylc-run``. + +.. note:: + + If you are running :term:`schedulers ` directly on the login node + and submitting jobs locally then the platform name and install target should + be ``localhost``. + +Sharing environment variables with the Cylc server +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. admonition:: Scenario + + An environment variable on the computer where you're running ``cylc play`` + needs to be shared with the Cylc server (e.g. to set up storage paths) + +Normally if a Cylc server is running on a remote host it will not keep +environment variables that are present when you run ``cylc play``. You can +whitelist variables to be sent to remote servers using +:cylc:conf:`global.cylc[platforms][]ssh forward environment variables`. + +These variables are forwarded to the Cylc server and may be used in the +`global.cylc` file templating. + + .. code-block:: cylc + :caption: part of a ``global.cylc`` config file + + [install] + [[symlink dirs]] + [[[hpc]]] + # Here the environment variable on the server is used + run = {{ environ['LUSTRE_DISK'] }} + + [platforms] + # 'localhost' platform is used when communicating with the server + [[localhost]] + ssh forward environment variables = LUSTRE_DISK, PROJECT + + [[hpc]] + submit method = pbs + [[[directives]]] + -P = {{ environ['PROJECT'] }} + +In this example Cylc will install workflows into the directory specified by +``$LUSTRE_DISK`` and use the project specified by ``$PROJECT`` in the +environment where you run ``cylc play``, e.g. + + .. code-block:: sh + + export LUSTRE_DISK=/g/data/foo + export PROJECT=bar + cylc play + +will store the workflow under ``/g/data/foo`` and submit jobs under project +``bar``. + +You can also forward variables from the server to other platforms. You should +first ensure the variable is available on the server, e.g. by also forwarding +the variable to ``[[localhost]]``. + +This setting only affects the task submission (e.g. ``qsub``) which may use +environment variables to set default directives. To set a variable once the +task has started see +:cylc:conf:`global.cylc[platforms][]copyable environment variables`. + + .. code-block:: cylc + :caption: part of a ``global.cylc`` config file + + [platforms] + [[localhost]] + ssh forward environment variables = PROJECT + + [[hpc]] + # Here qsub has been configured to read from $PROJECT + ssh forward environment variables = PROJECT + submit method = pbs diff --git a/nightly_8.4/html/_sources/reference/dev-history-major-changes.rst.txt b/nightly_8.4/html/_sources/reference/dev-history-major-changes.rst.txt new file mode 100644 index 00000000000..1ed49d0bd1e --- /dev/null +++ b/nightly_8.4/html/_sources/reference/dev-history-major-changes.rst.txt @@ -0,0 +1,55 @@ +Cylc Development History - Major Changes +======================================== + +- **pre-cylc-3** + + - early versions focused on the new + scheduling algorithm. A suite was a collection of "task definition files" + that encoded the prerequisites and outputs of each task, + exposing Cylc's self-organising nature. Tasks could be transferred + from one suite to another by simply copying their taskdef files over + and checking prerequisite and output consistency. Global suite + structure was not easy to discern until run time (although cylc-2 + could generate resolved run time dependency graphs). + +- **cylc-3** + + - a new suite design interface: dependency graph and task runtime properties + defined in a single structured, validated, configuration file + - graphical user interface + - suite graphing + +- **cylc-4** + + - refined and organized the suite config file structure + - task runtime properties defined by an efficient inheritance hierarchy + - support for the Jinja2 template processor in suite configurations + +- **cylc-5** + + - multi-threading for continuous network request handling and job submission + - more task states to distinguish job submission from execution + - dependence between suites via new run databases + - polling and killing of real jobs + - polling as task communications option + +- **cylc-6** + + - specification of all datetimes and cycling suites via ISO8601 + datetimes, durations, and recurrence expressions + - integer cycling + - a multi-process pool to execute job submissions, event handlers, and poll + and kill commands + +- **cylc-7** + + - Replaced the Pyro communications layer with RESTful HTTPS + - Removed deprecated pre cylc-6 syntax and features + +- **cylc-8** + + - Migrated to Python 3 + - New architecture, network layers, security + - New web UI + - New efficient scheduling algorithm + - Removed deprecated pre cylc-6 syntax and features diff --git a/nightly_8.4/html/_sources/reference/environments/conda.rst.txt b/nightly_8.4/html/_sources/reference/environments/conda.rst.txt new file mode 100644 index 00000000000..7e37b8d065f --- /dev/null +++ b/nightly_8.4/html/_sources/reference/environments/conda.rst.txt @@ -0,0 +1,123 @@ +.. _conda environments: + +Conda Environments +================== + +Cylc consists of multiple components. + +This Conda environment will provide you with the "recommended" installation of +all components: + +.. literalsubinclude:: envs/cylc-all.yml + :language: YAML + :substitutions: + +The following sections outline alternatives for finer control over installation. + + +Cylc Flow +--------- + +The simplest Cylc installation consists only of `Cylc Flow`_: + +.. literalsubinclude:: envs/cylc-flow.yml + :language: YAML + :substitutions: + +.. tip:: + + We suggest installing `Cylc Flow`_ at a "minor" version (e.g. ``8.1`` rather + than ``8.1.2``) to pick up the latest "maintenance" release. + +If you do not specify your Python version you will be provided with the most +recent compatible one. + +If you are installing Cylc on multiple machines across a network it is +advisable to keep the Python versions consistent. + +You can do this by adding Python into the environment at a particular version: + +.. literalsubinclude:: envs/cylc-flow-with-python.yml + :language: YAML + :substitutions: + +`Cylc Flow`_ provides a cut-down package containing only the bare essentials +called ``cylc-flow-base``. + +This may be useful for installing onto job hosts where client-facing extra +features are not of interest: + +.. literalsubinclude:: envs/cylc-flow-base.yml + :language: YAML + :substitutions: + + +Cylc UIServer +------------- + +The default `Cylc UIServer`_ package comes with `Jupyter Hub`_ and the +`Configurable HTTP Proxy`_ (required by `Jupyter Hub`_) bundled: + +.. literalsubinclude:: envs/cylc-uiserver.yml + :language: YAML + :substitutions: + +.. tip:: + + We suggest *not* specifying the version of other Cylc components to + (i.e. `Cylc UIServer`_ and `Cylc Rose`_). This will pick up the most recent + version compatible with the specified `Cylc Flow`_ version. + +`Jupyter Hub`_ is only required for multi-user setups, the `Cylc UIServer`_ +can be run as a standalone application. + +To exclude `Jupyter Hub`_ from the installation use ``cylc-uiserver-base``: + +.. literalsubinclude:: envs/cylc-uiserver-without-jupyterhub.yml + :language: YAML + :substitutions: + +If you want to use `Jupyter Hub`_ with an alternative proxy use +``cylc-uiserver-hub-base`` (this depends on ``jupyterhub-base``, see the +`Jupyter Hub`_ documentation for details): + +.. literalsubinclude:: envs/cylc-uiserver-with-traefik-proxy.yml + :language: YAML + :substitutions: + + +Cylc Rose +--------- + +For working with Rose add ``metomi-rose`` and ``cylc-rose`` (the bridge +between Cylc & Rose): + +.. literalsubinclude:: envs/cylc-rose.yml + :language: YAML + :substitutions: + +We will look at providing more installation options for Rose in the near +future. + + +Adding Cylc To Your Conda Package +--------------------------------- + +If you want to publish a package (e.g. to Conda Forge) that depends on Cylc, +consider using the minimal package (e.g. ``cylc-flow-base``) as a dependency +to allow the installer to maintain flexibility over the installation. + + +Working With Other Conda Channels +--------------------------------- + +Cylc projects are published to Conda Forge and the above environments install +all dependencies from Conda Forge. + +If you want to install other dependencies (e.g. Python), from other channels +(e.g. Anaconda), list the dependency explicitly and place the channel *above* +the Conda Forge channel. + +.. literalsubinclude:: envs/cylc-flow-anaconda.yml + :language: YAML + :substitutions: diff --git a/nightly_8.4/html/_sources/reference/index.rst.txt b/nightly_8.4/html/_sources/reference/index.rst.txt new file mode 100644 index 00000000000..890fa4891a9 --- /dev/null +++ b/nightly_8.4/html/_sources/reference/index.rst.txt @@ -0,0 +1,16 @@ +.. _reference: + +Reference +========= + + +.. toctree:: + :maxdepth: 2 + + changes + config/index + job-script-vars/index + architecture/index + api/index + environments/conda.rst + dev-history-major-changes diff --git a/nightly_8.4/html/_sources/reference/job-script-vars/index.rst.txt b/nightly_8.4/html/_sources/reference/job-script-vars/index.rst.txt new file mode 100644 index 00000000000..4f48d1260c7 --- /dev/null +++ b/nightly_8.4/html/_sources/reference/job-script-vars/index.rst.txt @@ -0,0 +1,13 @@ +Job Script Environment Variables +================================ + +These environment variables provided by the :term:`scheduler` are available +to Cylc job scripts at run time: + +.. literalinclude:: var-list.txt + :language: sub + + +.. seealso:: + + :ref:`Task Job Script Variables` diff --git a/nightly_8.4/html/_sources/tutorial/furthertopics/broadcast.rst.txt b/nightly_8.4/html/_sources/tutorial/furthertopics/broadcast.rst.txt new file mode 100644 index 00000000000..55848ed567b --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/furthertopics/broadcast.rst.txt @@ -0,0 +1,137 @@ +.. _broadcast-tutorial: + +Broadcast Tutorial +================== + +This tutorial walks you through using ``cylc broadcast`` which can be used +to change :ref:`task runtime configuration ` in a +running workflow, on-the-fly. + + +Purpose +------- + +``cylc broadcast`` can be used to change any ``[runtime]`` setting whilst the +workflow is running. + +The standard use of ``cylc broadcast`` is to update the workflow to an +unexpected change in configuration, for example modifying the host a task +runs on. + + +Standalone Example +------------------ + +Create a new workflow in the ``cylc-src`` directory called +``tutorial-broadcast``:: + + mkdir ~/cylc-src/tutorial-broadcast + cd ~/cylc-src/tutorial-broadcast + +Copy the following configuration into a :cylc:conf:`flow.cylc` file: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 1012 + [[graph]] + R1 = wipe_log => announce + PT1H = announce[-PT1H] => announce + + [runtime] + [[wipe_log]] + # Delete any files in the workflow's "share" directory. + script = rm "${CYLC_WORKFLOW_SHARE_DIR}/knights" || true + + [[announce]] + script = echo "${CYLC_TASK_CYCLE_POINT} - ${MESSAGE}" >> "${FILE}" + [[[environment]]] + WORD = ni + MESSAGE = We are the knights who say \"${WORD}\"! + FILE = "${CYLC_WORKFLOW_SHARE_DIR}/knights" + +We now have a workflow with an ``announce`` task which runs every hour, writing a +message to a log file (``share/knights``) when it does so. For the first cycle +the log entry will look like this:: + + 10120101T0000Z - We are the knights who say "ni"! + +The ``cylc broadcast`` command enables us to change runtime configuration +whilst the workflow is running. For instance we could change the value of the +``WORD`` environment variable using the command:: + + cylc broadcast tutorial-broadcast -n announce -s "[environment]WORD=it" + +* ``tutorial-broadcast`` is the name of the workflow. +* ``-n announce`` tells Cylc we want to change the runtime configuration of the + ``announce`` task. +* ``-s "[environment]WORD=it"`` changes the value of the ``WORD`` environment + variable to ``it``. + +Run the workflow then try using the ``cylc broadcast`` command to change the +message:: + + cylc validate . + cylc install + cylc play tutorial-broadcast + cylc broadcast tutorial-broadcast -n announce -s "[environment]WORD=it" + +Inspect the ``share/knights`` file, you should see the message change at +certain points. + +Stop the workflow:: + + cylc stop tutorial-broadcast + + +In-Situ Example +--------------- + +We can call ``cylc broadcast`` from within a task's script. This effectively +provides the ability for tasks to communicate between themselves. + +It is almost always better for tasks to communicate using files but there are +some niche situations where communicating via ``cylc broadcast`` is justified. +This tutorial walks you through using ``cylc broadcast`` to communicate between +tasks. + +.. TODO - examples of this? + +Add the following recurrence to the ``graph`` section: + +.. code-block:: cylc + + PT3H = announce[-PT1H] => change_word => announce + +The ``change_word`` task runs the ``cylc broadcast`` command to randomly +change the ``WORD`` environment variable used by the ``announce`` task. + +Add the following runtime configuration to the ``runtime`` section: + +.. code-block:: cylc + + [[change_word]] + script = """ + # Select random word. + IFS=',' read -r -a WORDS <<< $WORDS + WORD=${WORDS[$(date +%s) % ${#WORDS[@]}]} + + # Broadcast random word to the announce task. + cylc broadcast $CYLC_WORKFLOW_ID -n announce -s "[environment]WORD=${WORD}" + """ + [[[environment]]] + WORDS = ni, it, ekke ekke ptang zoo boing + +Re-install and run the workflow, and inspect the log. +You should see the message change randomly +after every third entry (because the ``change_word`` task runs every 3 hours) +e.g:: + + 10120101T0000Z - We are the knights who say "ni"! + 10120101T0100Z - We are the knights who say "ni"! + 10120101T0200Z - We are the knights who say "ni"! + 10120101T0300Z - We are the knights who say "ekke ekke ptang zoo boing!" + +Stop the workflow:: + + cylc stop tutorial-broadcast diff --git a/nightly_8.4/html/_sources/tutorial/furthertopics/clock-triggered-tasks.rst.txt b/nightly_8.4/html/_sources/tutorial/furthertopics/clock-triggered-tasks.rst.txt new file mode 100644 index 00000000000..f3bb85ddfe6 --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/furthertopics/clock-triggered-tasks.rst.txt @@ -0,0 +1,178 @@ +.. _tutorial-cylc-clock-trigger: + +Clock Triggered Tasks +===================== + +In a :term:`datetime cycling` workflow the time represented by the +:term:`cycle points ` bear no relation to the real-world time. +Using clock-triggers we can make tasks wait until their cycle point time before +running. + +Clock-triggering effectively enables us to tether the "cycle time" to the +"real world time" which we refer to as the :term:`wallclock time`. + +.. note:: + + Clock triggers are :ref:`Section External Triggers`. They differ from + custom external triggers only in that they are provided with Cylc, and + that the ``:interval`` suffix has no effect. + + +Clock Triggering +---------------- + +When clock-triggering tasks we can use different +:ref:`offsets ` to the cycle time as follows: + +.. code-block:: cylc + + my_clock_trigger = wall_clock(offset=) + +.. note:: + + Regardless of the offset used, the task still belongs to the cycle from + which the offset has been applied. + + +Example +------- + +Our example workflow will simulate a clock chiming on the hour. + +Within your ``~/cylc-src`` directory create a new directory called +``clock-trigger``:: + + mkdir ~/cylc-src/clock-trigger + cd ~/cylc-src/clock-trigger + +Paste the following code into a ``flow.cylc`` file: + +.. code-block:: cylc + + [scheduler] + UTC mode = True # Ignore DST + + [scheduling] + initial cycle point = TODO + final cycle point = +P1D # Run for one day + [[graph]] + PT1H = bell + + [runtime] + [[root]] + [[[events]]] + mail events = failed + [[bell]] + script = printf 'bong%.02d\n' $(seq 1 $(cylc cyclepoint --print-hour)) + +Change the initial cycle point to 00:00 this morning (e.g. if it was +the first of January 2000 we would write ``2000-01-01T00Z``). + +We now have a simple workflow with a single task that prints "bong" a number +of times equal to the (cycle point) hour. + +Run your workflow using:: + + cylc validate . + cylc install + cylc play clock-trigger + +Stop the workflow after a few cycles using ``cylc stop --now --now clock-trigger``. +Notice how the tasks run as soon as possible rather than +waiting for the actual time to be equal to the cycle point. + + +Clock-Triggering Tasks +---------------------- + +We want our clock to only ring in real-time rather than the simulated +cycle time. + +To do this, modify the ``[scheduling][graph]`` section of +your ``flow.cylc``: + +.. code-block:: cylc + + PT1H = @wall_clock => bell + +This tells the workflow to clock trigger the ``bell`` task with a cycle +offset of ``0`` hours. + +Save your changes, install and run your workflow. + +Your workflow should now be running the ``bell`` task in real-time. Any cycle times +that have already passed (such as the one defined by ``initial cycle time``) +will be run as soon as possible, while those in the future will wait for that +time to pass. + +At this point you may want to leave your workflow running until the next hour +has passed in order to confirm the clock triggering is working correctly. +Once you are satisfied, stop your workflow. + +By making the ``bell`` task a clock triggered task we have made it run in +real-time. Thus, when the wallclock time caught up with the cycle time, the +``bell`` task triggered. + + +Adding More Clock-Triggered Tasks +--------------------------------- + +Running clock triggered tests at the cycle time is a special case: +We will now modify our workflow to run tasks at quarter-past, half-past and +quarter-to the hour. + +Open your ``flow.cylc`` and modify the ``[runtime]`` section by adding the +following: + +.. code-block:: cylc + + [[quarter_past, half_past, quarter_to]] + script = echo 'chimes' + +Edit the ``[[scheduling]]`` section to read: + +.. code-block:: cylc + + initial cycle point = now + final cycle point = +P1D # Run for one day + [[xtriggers]] + quarter_past_trigger = wall_clock(offset=PT15M) + half_past_trigger = wall_clock(offset=PT30M) + quarter_to_trigger = wall_clock(offset=PT45M) + [[graph]] + PT1H = """ + @wall_clock => bell + @quarter_past_trigger => quarter_past + @half_past_trigger => half_past + @quarter_to_trigger => quarter_to + """ + +Note the different values used for the cycle offsets of the clock-trigger tasks. + +Save your changes, install and run your workflow using:: + + cylc validate . + cylc install + cylc play clock-trigger + +.. note:: + + Setting ``initial cycle point = now`` will run your workflow using the + current time at startup as the initial cycle point. + +Again, notice how the tasks trigger until the current time is reached. + +Leave your workflow running for a while to confirm it is working as expected +before stopping it. + + +Summary +------- + +* Clock triggers are a type of :term:`dependency` which cause + :term:`tasks ` to wait for the :term:`wallclock time` to reach the + :term:`cycle point` time. +* Clock triggers are a built in example of :ref:`Section External Triggers`. +* Clock triggers can only be used in datetime cycling workflows. + +For more information see the `Cylc User Guide`_. diff --git a/nightly_8.4/html/_sources/tutorial/furthertopics/family-triggers.rst.txt b/nightly_8.4/html/_sources/tutorial/furthertopics/family-triggers.rst.txt new file mode 100644 index 00000000000..c19cd93217b --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/furthertopics/family-triggers.rst.txt @@ -0,0 +1,213 @@ +.. _tutorial-cylc-family-triggers: + +Family Triggers +=============== + +To reduce duplication in the :term:`graph` is is possible to write +:term:`dependencies ` using collections of tasks called +:term:`families `). + +This tutorial walks you through writing such dependencies using family +:term:`triggers `. + + +Explanation +----------- + +Dependencies between tasks can be written using a :term:`qualifier` to describe +the :term:`task state` that the dependency refers to (e.g. ``succeed`` +``fail``, etc). If a dependency does not use a qualifier then it is assumed +that the dependency refers to the ``succeed`` state e.g: + +.. code-block:: cylc-graph + + bake_bread => sell_bread # sell_bread is dependent on bake_bread succeeding. + bake_bread:succeed => sell_bread? # sell_bread is dependent on bake_bread succeeding. + sell_bread:fail? => throw_away # throw_away is dependent on sell_bread failing. + +The left-hand side of a :term:`dependency` (e.g. ``sell_bread:fail``) is +referred to as the :term:`trigger `. + +.. note:: + + ``sell_bread(:succeed)`` and ``sell_bread:fail`` are mutually exclusive + outcomes. As both appear in the graph above, it is + necessary to use the ``?`` syntax to mark them as + :ref:`optional outputs`. + +When we write a trigger involving a family, special qualifiers are required +to specify whether the dependency is concerned with *all* or *any* of the tasks +in that family reaching the desired :term:`state ` e.g: + +* ``succeed-all`` +* ``succeed-any`` +* ``fail-all`` + +Such :term:`triggers ` are referred to as +:term:`family triggers ` + + +Example +------- + +Create a new workflow called ``tutorial-family-triggers``:: + + mkdir ~/cylc-src/tutorial-family-triggers + cd ~/cylc-src/tutorial-family-triggers + +Paste the following configuration into the :cylc:conf:`flow.cylc` file: + +.. code-block:: cylc + + [scheduler] + UTC mode = True # Ignore DST + [scheduling] + [[graph]] + R1 = visit_mine => MINERS + [runtime] + [[visit_mine]] + script = sleep 5; echo 'off to work we go' + + [[MINERS]] + script = """ + sleep 5; + if (($RANDOM % 2)); then + echo 'Diamonds!'; true; + else + echo 'Nothing...'; false; + fi + """ + [[doc, grumpy, sleepy, happy, bashful, sneezy, dopey]] + inherit = MINERS + +You have now created a workflow that: + +* Has a ``visit_mine`` task that sleeps for 5 seconds then outputs a + message. +* Contains a ``MINERS`` family with a command in it that randomly succeeds + or fails. +* Has 7 tasks that inherit from the ``MINERS`` family. + +Validate, install and run the workflow:: + + cylc validate . + cylc install + cylc play tutorial-family-triggers + +You should see the ``visit_mine`` task run, then trigger the members of the +``MINERS`` family. Note that some of the ``MINERS`` tasks may fail so you +will need to stop your workflow using the "stop" button in the UI, or:: + + cylc stop tutorial-family-triggers + + +Family Triggering: Success +-------------------------- + +As you will have noticed by watching the workflow run, some of the tasks in the +``MINERS`` family succeed and some fail. + +We would like to add a task to sell any diamonds we find, but wait for all +the miners to report back first so we only make the one trip. + +We can address this by using *family triggers*. In particular, we are going +to use the ``finish-all`` trigger to check for all members of the ``MINERS`` +family finishing, and the ``succeed-any`` trigger to check for any of the +tasks in the ``MINERS`` family succeeding. + +Open your :cylc:conf:`flow.cylc` file and change the ``[[graph]]`` to look like +this: + +.. code-block:: cylc + + [[graph]] + R1 = """ + visit_mine => MINERS? + MINERS:finish-all & MINERS:succeed-any? => sell_diamonds + """ + +Then, add the following task to the ``[runtime]`` section: + +.. code-block:: cylc + + [[sell_diamonds]] + script = sleep 5 + +These changes add a ``sell_diamonds`` task to the workflow which is run once +all the ``MINERS`` tasks have finished and if any of them have succeeded. + +Save your changes and run your workflow. You should see the new +``sell_diamonds`` task being run once all the miners have finished and at +least one of them has succeeded. Stop your workflow as described above. + +.. seealso:: + + User guide on + :ref:`family triggers and optional outputs`. + +Family Triggering: Failure +-------------------------- + +Cylc also allows us to trigger off failure of tasks in a particular family. + +We would like to add another task to close down unproductive mineshafts once +all the miners have reported back and had time to discuss their findings. + +To do this we will make use of family triggers in a similar manner to before. + +Open your :cylc:conf:`flow.cylc` file and change the ``[[graph]]`` to look like +this: + +.. code-block:: cylc + + [[graph]] + R1 = """ + visit_mine => MINERS? + MINERS:finish-all & MINERS:succeed-any? => sell_diamonds + MINERS:finish-all & MINERS:fail-any? => close_shafts + """ + +Alter the ``[[sell_diamonds]]`` section to look like this: + +.. code-block:: cylc + + [[close_shafts, sell_diamonds]] + script = sleep 5 + +These changes add a ``close_shafts`` task which is run once all the +``MINERS`` tasks have finished and any of them have failed. + +Save your changes and run your workflow. You should see the new +``close_shafts`` run should any of the ``MINERS`` tasks be in the failed +state once they have all finished. + + +Different Triggers +------------------ + +Other family :term:`qualifiers ` beyond those covered in the +example are also available. + +The following types of "all" qualifier are available: + +* ``:start-all`` - all the tasks in the family have started +* ``:succeed-all`` - all the tasks in the family have succeeded +* ``:fail-all`` - all the tasks in the family have failed +* ``:finish-all`` - all the tasks in the family have finished + +The following types of "any" qualifier are available: + +* ``:start-any`` - at least one task in the family has started +* ``:succeed-any`` - at least one task in the family has succeeded +* ``:fail-any`` - at least one task in the family has failed +* ``:finish-any`` - at least one task in the family has finished + + +Summary +------- + +* Family triggers allow you to write dependencies for collections of tasks. +* Like :term:`task triggers `, family triggers can be based on + success, failure, starting and finishing of tasks in a family. +* Family triggers can trigger off either *all* or *any* of the tasks in a + family. diff --git a/nightly_8.4/html/_sources/tutorial/furthertopics/index.rst.txt b/nightly_8.4/html/_sources/tutorial/furthertopics/index.rst.txt new file mode 100644 index 00000000000..b8d40cc66e6 --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/furthertopics/index.rst.txt @@ -0,0 +1,18 @@ +.. _tutorials.furthertopics: + +Further Topics +============== + +This section looks at further topics in cylc. + +.. toctree:: + :name: cylc-further-topics + :maxdepth: 1 + + clock-triggered-tasks + broadcast + family-triggers + inheritance + queues + retries + message-triggers diff --git a/nightly_8.4/html/_sources/tutorial/furthertopics/inheritance.rst.txt b/nightly_8.4/html/_sources/tutorial/furthertopics/inheritance.rst.txt new file mode 100644 index 00000000000..7335f1c1ed2 --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/furthertopics/inheritance.rst.txt @@ -0,0 +1,614 @@ +.. _tutorial-inheritance: + +Inheritance +=========== + +We have seen in the :ref:`runtime tutorial ` how +tasks can be grouped into families. + +In this tutorial we will look at nested families, inheritance order and +multiple inheritance. + + +Inheritance Hierarchy +--------------------- + +Within your ``~/cylc-src`` directory create a new directory called +``inheritance-tutorial``:: + + mkdir ~/cylc-src/inheritance-tutorial + cd ~/cylc-src/inheritance-tutorial + +And paste the following code into a ``flow.cylc`` file. This +defines two tasks each representing different aircraft, the Airbus A380 jumbo +jet and the Robson R44 helicopter: + +.. image:: https://upload.wikimedia.org/wikipedia/commons/0/09/A6-EDY_A380_Emirates_31_jan_2013_jfk_%288442269364%29_%28cropped%29.jpg + :width: 49% + :alt: A380 + +.. image:: https://upload.wikimedia.org/wikipedia/commons/2/2f/Robinson-R44_1.jpg + :width: 49% + :alt: R44 + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = a380 & r44 + + [runtime] + [[VEHICLE]] + init-script = echo 'Boarding' + pre-script = echo 'Departing' + post-script = echo 'Arriving' + + [[AIR_VEHICLE]] + inherit = VEHICLE + [[[meta]]] + description = A vehicle which can fly. + [[AIRPLANE]] + inherit = AIR_VEHICLE + [[[meta]]] + description = An air vehicle with fixed wings. + [[[environment]]] + CAN_TAKE_OFF_VERTICALLY = false + [[HELICOPTER]] + inherit = AIR_VEHICLE + [[[meta]]] + description = An air vehicle with rotors. + [[[environment]]] + CAN_TAKE_OFF_VERTICALLY = true + + [[a380]] + inherit = AIRPLANE + [[[meta]]] + title = Airbus A380 Jumbo-Jet. + [[r44]] + inherit = HELICOPTER + [[[meta]]] + title = Robson R44 Helicopter. + +.. note:: + + The ``[meta]`` section is a freeform section where we can define metadata + to be associated with a task, family or the workflow itself. + + This metadata should not be mistaken for Rose :ref:`conf-meta`. + +.. admonition:: Reminder + :class: hint + + By convention we write family names in upper case (with the exception of the + special ``root`` family) and task names in lower case. + +These two tasks sit at the bottom of an inheritance tree. The ``cylc graph`` +command has an option (``-n``) for drawing such inheritance hierarchies:: + + cylc graph -n . & + +Running this command will generate the following output: + +.. digraph:: Example + :align: center + + AIRPLANE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + a380 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + AIRPLANE -> a380 [color=royalblue]; + HELICOPTER [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + r44 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + HELICOPTER -> r44 [color=royalblue]; + root [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + root -> VEHICLE [color=royalblue]; + AIR_VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + VEHICLE -> AIR_VEHICLE [color=royalblue]; + AIR_VEHICLE -> AIRPLANE [color=royalblue]; + AIR_VEHICLE -> HELICOPTER [color=royalblue]; + +.. note:: + + The ``root`` family sits at the top of the inheritance tree as all + tasks/families automatically inherit it: + +Cylc handles inheritance by starting with the root family and working down the +inheritance tree applying each section in turn. + +To see the resulting configuration for the ``a380`` task use the +``cylc config`` command:: + + cylc config . -i "[runtime][a380]" + +You should see some settings which have been inherited from the ``VEHICLE`` and +``AIRPLANE`` families as well as a couple defined in the ``a380`` task. + +.. code-block:: cylc + + init-script = echo 'Boarding' # Inherited from VEHICLE + pre-script = echo 'Departing' # Inherited from VEHICLE + post-script = echo 'Arriving' # Inherited from VEHICLE + inherit = AIRPLANE # Defined in a380 + [[[meta]]] + description = An air vehicle with fixed wings. # Inherited from AIR_VEHICLE - overwritten by AIRPLANE + title = Airbus A380 Jumbo-Jet. # Defined in a380 + [[[environment]]] + CAN_TAKE_OFF_VERTICALLY = false # Inherited from AIRPLANE + +Note that the ``description`` setting is defined in the ``AIR_VEHICLE`` +family but is overwritten by the value specified in the ``AIRPLANE`` family. + + +Multiple Inheritance +-------------------- + +Next we want to add a vehicle called the V-22 Osprey to the workflow. The V-22 +is a cross between a plane and a helicopter - it has wings but can take-off and +land vertically. + +.. image:: https://upload.wikimedia.org/wikipedia/commons/e/e3/MV-22_mcas_Miramar_2014.JPG + :width: 300px + :align: center + +As the V-22 can be thought of as both a plane and a helicopter we want it to +inherit from both the ``AIRPLANE`` and ``HELICOPTER`` families. In Cylc we can +inherit from multiple families by separating their names with commas: + +Add the following task to your :cylc:conf:`flow.cylc` file. + +.. code-block:: cylc + + [[v22]] + inherit = AIRPLANE, HELICOPTER + [[[meta]]] + title = V-22 Osprey Military Aircraft. + +Re-run the ``cylc graph`` command. + +The inheritance hierarchy should now look like this: + +.. digraph:: Example + :align: center + + AIRPLANE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + v22 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + AIRPLANE -> v22 [color=royalblue]; + a380 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + AIRPLANE -> a380 [color=royalblue]; + HELICOPTER [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + HELICOPTER -> v22 [color=royalblue]; + r44 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + HELICOPTER -> r44 [color=royalblue]; + root [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + root -> VEHICLE [color=royalblue]; + AIR_VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + VEHICLE -> AIR_VEHICLE [color=royalblue]; + AIR_VEHICLE -> AIRPLANE [color=royalblue]; + AIR_VEHICLE -> HELICOPTER [color=royalblue]; + +Inspect the configuration of the ``v22`` task using the ``cylc config`` +command. + +.. spoiler:: Hint warning + + .. code-block:: bash + + cylc config . -i "[runtime][v22]" + +You should see that the ``CAN_TASK_OFF_VERTICALLY`` environment variable has +been set to ``false`` which isn't right. This is because of the order in which +inheritance is applied. + +Cylc handles multiple-inheritance by applying each family from right to left. +For the ``v22`` task we specified ``inherit = AIRPLANE, HELICOPTER`` so the +``HELICOPTER`` family will be applied first and the ``AIRPLANE`` family after. + +The inheritance order would be as follows: + +.. code-block:: bash + + root + VEHICLE + AIR_VEHICLE + HELICOPTER # sets "CAN_TAKE_OFF_VERTICALLY to "true" + AIRPLANE # sets "CAN_TAKE_OFF_VERTICALLY to "false" + v22 + +We could fix this problem by changing the order of inheritance: + +.. code-block:: cylc + + inherit = HELICOPTER, AIRPLANE + +Now the ``HELICOPTER`` family is applied second so its values will override any +in the ``AIRPLANE`` family. + +.. code-block:: bash + + root + VEHICLE + AIR_VEHICLE + AIRPLANE # sets "CAN_TAKE_OFF_VERTICALLY to "false" + HELICOPTER # sets "CAN_TAKE_OFF_VERTICALLY to "true" + v22 + +Inspect the configuration of the ``v22`` task using ``cylc config`` to +confirm this. + + +More Inheritance +---------------- + +We will now add some more families and tasks to the workflow. + +Engine Type +^^^^^^^^^^^ + +Next we will define four families to represent three different types of engine. + +.. digraph:: Example + :align: center + + size = "5,5" + + ENGINE [color=royalblue, fillcolor=powderblue, shape=box, style=filled, + margin="0.3,0.055"] + TURBINE_ENGINE [color=royalblue, fillcolor=powderblue, shape=box, + style=filled, margin="0.3,0.055"] + INTERNAL_COMBUSTION_ENGINE [color=royalblue, fillcolor=powderblue, + shape=box, style=filled, margin="0.3,0.055"] + HUMAN_ENGINE [color=royalblue, fillcolor=powderblue, shape=box, + style=filled, margin="0.3,0.055"] + + "ENGINE" -> "TURBINE_ENGINE" + "ENGINE" -> "INTERNAL_COMBUSTION_ENGINE" + "ENGINE" -> "HUMAN_ENGINE" + +Each engine type should set an environment variable called ``FUEL`` which we +will assign to the following values: + +* Turbine - kerosene +* Internal Combustion - petrol +* Human - pizza + +Add lines to the ``runtime`` section to represent these four families. + +.. spoiler:: Solution warning + + .. code-block:: cylc + + [[ENGINE]] + [[TURBINE_ENGINE]] + inherit = ENGINE + [[[environment]]] + FUEL = kerosene + [[INTERNAL_COMBUSTION_ENGINE]] + inherit = ENGINE + [[[environment]]] + FUEL = petrol + [[HUMAN_ENGINE]] + inherit = ENGINE + [[[environment]]] + FUEL = pizza + +We now need to make the three aircraft inherit from one of the three engines. +The aircraft use the following types of engine: + +* A380 - turbine +* R44 - internal combustion +* V22 - turbine + +Modify the three tasks so that they inherit from the relevant engine families. + +.. spoiler:: Solution warning + + .. code-block:: cylc + + [[a380]] + inherit = AIRPLANE, TURBINE_ENGINE + [[[meta]]] + title = Airbus A380 Jumbo-Jet. + [[r44]] + inherit = HELICOPTER, INTERNAL_COMBUSTION_ENGINE + [[[meta]]] + title = Robson R44 Helicopter. + [[v22]] + inherit = AIRPLANE, HELICOPTER, TURBINE_ENGINE + [[[meta]]] + title = V-22 Ofsprey Military Aircraft. + +Penny Farthing +^^^^^^^^^^^^^^ + +Next we want to add a new type of vehicle, an old-fashioned bicycle called a +penny farthing. + +.. image:: https://upload.wikimedia.org/wikipedia/commons/a/a7/Ordinary_bicycle01.jpg + :width: 300px + :alt: Penny Farthing Bicycle + :align: center + +To do this we will need to add two new families, ``LAND_VEHICLE`` and +``BICYCLE`` as well as a new task, ``penny_farthing`` related in the +following manner: + +.. digraph:: Example + :align: center + + VEHICLE [color=royalblue, fillcolor=powderblue, shape=box, style=filled] + LAND_VEHICLE [color=royalblue, fillcolor=powderblue, shape=box, + style=filled] + BICYCLE [color=royalblue, fillcolor=powderblue, shape=box, style=filled] + HUMAN_ENGINE [color=royalblue, fillcolor=powderblue, shape=box, + style=filled, margin="0.3,0.055"] + penny_farthing [color=royalblue, fillcolor=powderblue, shape=box, + style=filled, margin="0.3,0.055"] + VEHICLE -> LAND_VEHICLE -> BICYCLE -> penny_farthing + HUMAN_ENGINE -> penny_farthing + +Add lines to the ``runtime`` section to represent the two new families and one +task outlined above. + +Add a description (``[meta]description``) to the ``LAND_VEHICLE`` and +``BICYCLE`` families and a title (``[meta]title``) to the ``penny_farthing`` +task. + +.. spoiler:: Solution warning + + .. code-block:: cylc + + [[LAND_VEHICLE]] + inherit = VEHICLE + [[[meta]]] + description = A vehicle which can travel over the ground. + + [[BICYCLE]] + inherit = LAND_VEHICLE + [[[meta]]] + description = A small two-wheeled vehicle. + + [[penny_farthing]] + inherit = BICYCLE, HUMAN_ENGINE + [[[meta]]] + title = An old-fashioned bicycle. + + +Using ``cylc config`` to inspect the configuration of the ``penny_farthing`` +task we can see that it inherits settings from the ``VEHICLE``, +``BICYCLE`` and ``HUMAN_ENGINE`` families. + +.. code-block:: cylc + + inherit = BICYCLE, HUMAN_ENGINE + init-script = echo 'Boarding' # Inherited from VEHICLE + pre-script = echo 'Departing' # Inherited from VEHICLE + post-script = echo 'Arriving' # Inherited from VEHICLE + [[[environment]]] + FUEL = pizza # Inherited from HUMAN_ENGINE + [[[meta]]] + description = A small two-wheeled vehicle. # Inherited from LAND_VEHICLE - overwritten by BICYCLE + title = An old-fashioned bicycle. # Defined in penny_farthing + +.. spoiler:: Hint hint + + .. code-block:: bash + + cylc config . -i "[runtime]penny_farthing" + +Hovercraft +^^^^^^^^^^ + +We will now add a hovercraft called the Hoverwork BHT130, better known to some +as the Isle Of Wight Ferry. + +.. image:: https://upload.wikimedia.org/wikipedia/commons/e/e7/Hovercraft_leaving_Ryde.JPG + :width: 300px + :align: center + :alt: Hoverwork BHT130 Hovercraft + +Hovercraft can move over both land and water and in some respects can be thought +of as flying vehicles. + +.. digraph:: Example + :align: center + + size = "7,5" + + VEHICLE [color=royalblue, fillcolor=powderblue, shape=box, style=filled] + AIR_VEHICLE [color=royalblue, fillcolor=powderblue, shape=box, style=filled] + LAND_VEHICLE [color=royalblue, fillcolor=powderblue, shape=box, + style=filled] + WATER_VEHICLE [color=royalblue, fillcolor=powderblue, shape=box, + style=filled] + HOVERCRAFT [color=royalblue, fillcolor=powderblue, shape=box, style=filled] + bht130 [color=royalblue, fillcolor=powderblue, shape=box, style=filled] + ENGINE [color=royalblue, fillcolor=powderblue, shape=box, style=filled] + INTERNAL_COMBUSTION_ENGINE [color=royalblue, fillcolor=powderblue, + shape=box, style=filled, margin="0.3,0.055"] + VEHICLE -> AIR_VEHICLE -> HOVERCRAFT + VEHICLE -> LAND_VEHICLE -> HOVERCRAFT + VEHICLE -> WATER_VEHICLE -> HOVERCRAFT + HOVERCRAFT -> bht130 + ENGINE -> INTERNAL_COMBUSTION_ENGINE -> bht130 + +Write new families and one new task to represent the above structure. + +Add a description (``[meta]description``) to the ``WATER_VEHICLE`` and +``HOVERCRAFT`` families and a title (``[meta]title``) to the ``bht130`` task. + +.. spoiler:: Solution warning + + .. code-block:: cylc + + [[WATER_VEHICLE]] + inherit = VEHICLE + [[[meta]]] + description = A vehicle which can travel over water. + + [[HOVERCRAFT]] + inherit = LAND_VEHICLE, AIR_VEHICLE, WATER_VEHICLE + [[[meta]]] + description = A vehicle which can travel over ground, water and ice. + + [[bht130]] + inherit = HOVERCRAFT, INTERNAL_COMBUSTION_ENGINE + [[[meta]]] + title = Griffon Hoverwork BHT130 (Isle Of Whight Ferry). + + +Finished Workflow +----------------- + +You should now have a workflow with an inheritance hierarchy which looks like +this: + +.. digraph:: Example + + size = "7, 5" + + root [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + ENGINE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + root -> ENGINE [color=royalblue]; + VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + root -> VEHICLE [color=royalblue]; + INTERNAL_COMBUSTION_ENGINE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled, + margin="0.3,0.055"]; + ENGINE -> INTERNAL_COMBUSTION_ENGINE [color=royalblue]; + TURBINE_ENGINE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled, + margin="0.3,0.055"]; + ENGINE -> TURBINE_ENGINE [color=royalblue]; + HUMAN_ENGINE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled, + margin="0.3,0.055"]; + ENGINE -> HUMAN_ENGINE [color=royalblue]; + LAND_VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + VEHICLE -> LAND_VEHICLE [color=royalblue]; + WATER_VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + VEHICLE -> WATER_VEHICLE [color=royalblue]; + AIR_VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + VEHICLE -> AIR_VEHICLE [color=royalblue]; + r44 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + INTERNAL_COMBUSTION_ENGINE -> r44 [color=royalblue]; + bht130 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + INTERNAL_COMBUSTION_ENGINE -> bht130 [color=royalblue]; + v22 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + TURBINE_ENGINE -> v22 [color=royalblue]; + a380 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + TURBINE_ENGINE -> a380 [color=royalblue]; + penny_farthing [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled, + margin="0.3,0.055"]; + HUMAN_ENGINE -> penny_farthing [color=royalblue]; + AIRPLANE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + AIRPLANE -> v22 [color=royalblue]; + AIRPLANE -> a380 [color=royalblue]; + HELICOPTER [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + HELICOPTER -> v22 [color=royalblue]; + HELICOPTER -> r44 [color=royalblue]; + HOVERCRAFT [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + HOVERCRAFT -> bht130 [color=royalblue]; + LAND_VEHICLE -> HOVERCRAFT [color=royalblue]; + BICYCLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; + LAND_VEHICLE -> BICYCLE [color=royalblue]; + WATER_VEHICLE -> HOVERCRAFT [color=royalblue]; + AIR_VEHICLE -> AIRPLANE [color=royalblue]; + AIR_VEHICLE -> HELICOPTER [color=royalblue]; + AIR_VEHICLE -> HOVERCRAFT [color=royalblue]; + BICYCLE -> penny_farthing [color=royalblue]; diff --git a/nightly_8.4/html/_sources/tutorial/furthertopics/message-triggers.rst.txt b/nightly_8.4/html/_sources/tutorial/furthertopics/message-triggers.rst.txt new file mode 100644 index 00000000000..af31724cd73 --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/furthertopics/message-triggers.rst.txt @@ -0,0 +1,432 @@ +.. _tutorial-cylc-message-triggers: + +Message Triggers +================ + +:term:`Message triggers ` allow us to trigger dependent tasks +before the upstream task has completed. + +Explanation +----------- + +We have seen :ref:`before ` that tasks can have +:term:`qualifiers ` for different +:term:`task states `. +:term:`Message triggers ` are essentially custom qualifiers. +We can produce a bespoke output while our task is still running. +This output could be, for example, a report or perhaps another task. + +Usage +----- + +:term:`Message triggers ` are particularly useful if we have +a long running task and we want to produce multiple tailored outputs whilst +this task is running, rather than having to wait for the task to +complete. + +We could also set up :term:`message triggers ` to, for example, +send an email to inform us that a submission has failed, making use of Cylc's +task event handling system. More information is available on these in the +`Cylc User Guide`_. + + +:term:`Message triggers ` provide a superior solution to +the problem of file system polling. We could, for example, design our workflow +such that we check if our task is finished by polling at intervals. +It is inefficient to 'spam' task hosts with polling commands, it is preferable +to set up a message trigger. + +How to create a message trigger +------------------------------- + +In order to get our workflow to trigger messages, we need to: + +* specify our custom message in a section called ``[[outputs]]`` within the + ``[runtime]`` section of our workflow, + +* add ``cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" "YOUR CHOSEN TRIGGER MESSAGE"`` + to the ``script`` section of ``[runtime]``, your chosen trigger message + should be unique and should exactly match the message defined in + ``[[outputs]]``. + +* Refer to these messages in the ``[dependencies]`` section of our workflow. + +.. note:: + + The message will be recorded in the workflow's scheduler log. + See :ref:`scheduler logs.cylc message` for details of how messages appear. + +These outputs are then triggered during the running of the task. +We can use these to manage tasks dependent on partially completed tasks. + +So, a basic example, where we have a task foo, that when partially completed +triggers another task bar and when fully completed triggers another task, baz. + + .. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + foo:out1 => bar + foo => baz + """ + [runtime] + [[foo]] + script = """ + sleep 5 + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" "file 1 done" + sleep 10 + """ + [[[outputs]]] + out1 = "file 1 done" + + [[bar, baz]] + script = sleep 10 + +.. _message triggers practical: + +.. practical:: + + .. rubric:: In this practical example, we will create a workflow to demonstrate + :term:`message triggers `. We will use message triggers + to both produce a report and trigger a new task from a partially completed + task. + + #. **Create a new directory.** + + Within your ``~/cylc-src`` directory create a new directory called + + ``message-triggers`` and move into it: + + .. code-block:: bash + + mkdir ~/cylc-src/message-triggers + cd ~/cylc-src/message-triggers + + #. **Install the script needed for our workflow** + + The workflow we will be designing requires a bash script, ``random.sh``, + to produce our report. It will simply create a text file ``report.txt`` + with some random numbers in it. This will be executed when the associated + task is run. + + Scripts should be kept in the ``bin`` sub-directory within the + :term:`run directory `. If a ``/bin`` + exists in the run directory, it will be prepended $PATH at run + time. + + Create a ``/bin`` directory. + + .. code-block:: bash + + mkdir ~/cylc-src/message-triggers/bin + + Create a bash script in the bin directory: + + .. code-block:: bash + + touch bin/random.sh + + We will need to make this script executable. + + .. code-block:: bash + + chmod +x bin/random.sh + + Open the file and paste the following basic bash script into it: + + .. code-block:: bash + + #!/usr/bin/env bash + set -eu # Prevent bash script failing quietly. + + counter=1 + + while [ $counter -le 10 ]; do + newrand=$(( (( RANDOM % 40) + 1 ) )); + echo $newrand >> report.txt; + counter=$((counter + 1)); + done + + + #. **Create a new workflow.** + + Create a :cylc:conf:`flow.cylc` file and paste the following basic workflow into it: + + .. code-block:: cylc + + [meta] + title = "test workflow to demo message triggers" + + [scheduler] + UTC mode = True + + [scheduling] + initial cycle point = 2019-06-27T00Z + final cycle point = 2019-10-27T00Z + [[graph]] + P2M = """ + long_forecasting_task => another_weather_task + long_forecasting_task => different_weather_task + long_forecasting_task[-P2M] => long_forecasting_task + """ + + This is a basic workflow, currently it does not have any message triggers + attached to any task. + + + #. **Define our tasks in the runtime section.** + + Next we want to create our ``runtime`` section of our workflow. + First we define what the tasks do. In this example + ``long_forecasting_task`` will sleep, create a file containing some + random numbers and produce a message. + (Note that the random number generator bash script has already been + preloaded into your ``bin`` directory.) + ``another_weather_task`` and ``different_weather_task`` simply sleep. + + Add the following code to the :cylc:conf:`flow.cylc` file. + + .. code-block:: cylc + + [runtime] + + [[long_forecasting_task]] + script = """ + sleep 2 + random.sh + + sleep 2 + random.sh + + sleep 2 + random.sh + """ + + [[another_weather_task, different_weather_task]] + script = sleep 1 + + + #. **Create message triggers.** + + We now have a workflow with a task, ``long_forecasting_task`` which, after + it has fully completed, triggers two more tasks, ``another_weather_task`` + and ``different_weather_task``. + + Suppose we want ``another_weather_task`` and ``different_weather_task`` + to start before ``long_forecasting_task`` has fully completed, perhaps + after some data has become available. + + In this case, we shall trigger ``another_weather_task`` after one set of + random numbers has been created + and ``different_weather_task`` after a second set of random numbers has + been created. + + There are three aspects of creating message triggers. + The first is to create the messages. Within ``runtime``, ``TASK`` in our + workflow, we need to create a sub-section called ``outputs``. Here we create + our custom outputs. + + .. code-block:: diff + + + [[[outputs]]] + + update1 = "Task partially complete, report ready to view" + + update2 = "Task partially complete, report updated" + + The second thing we need to do is to create a cylc message in our script. + This should be placed where you want the message to be called. In our + case, this is after each of the first two set of random numbers are + generated. + + .. tip:: + Remember that the ``cylc message`` should exactly match the outputs + stated in our ``[[[outputs]]]`` section. + + Modify the ``[[long_forecasting_task]]`` script in the :cylc:conf:`flow.cylc` file + as follows: + + .. code-block:: diff + + [runtime] + + [[long_forecasting_task]] + script = """ + sleep 2 + random.sh + + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \ + + "Task partially complete, report ready to view" + sleep 2 + random.sh + + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \ + + "Task partially complete, report updated" + sleep 2 + random.sh + """ + + Lastly, we need to make reference to the messages in the + graph section. + This will ensure your tasks trigger off of the messages correctly. + + Adapt the ``[[dependencies]]`` section in the :cylc:conf:`flow.cylc` file to read as + follows: + + .. code-block:: diff + + [[[P2M]]] + graph = """ + - long_forecasting_task => another_weather_task + - long_forecasting_task => different_weather_task + + long_forecasting_task:update1 => another_weather_task + + long_forecasting_task:update2 => different_weather_task + long_forecasting_task[-P2M] => long_forecasting_task + """ + + This completes our :cylc:conf:`flow.cylc` file. + + Our final workflow should look like this: + + .. spoiler:: Solution warning + + .. code-block:: cylc + + [meta] + title = "test workflow to demo message triggers" + + [scheduler] + UTC mode = True + + [scheduling] + initial cycle point = 2019-06-27T00Z + final cycle point = 2019-10-27T00Z + + [[graph]] + P2M = """ + long_forecasting_task:update1 => another_weather_task + long_forecasting_task:update2 => different_weather_task + long_forecasting_task[-P2M] => long_forecasting_task + """ + + [runtime] + [[long_forecasting_task]] + script = """ + sleep 2 + random.sh + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \ + "Task partially complete, report ready to view" + sleep 2 + random.sh + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \ + "Task partially complete, report updated" + sleep 2 + random.sh + """ + [[[outputs]]] + update1 = "Task partially complete, report ready to view" + update2 = "Task partially complete, report updated" + + [[another_weather_task, different_weather_task]] + script = sleep 1 + + #. **Validate the workflow.** + + It is a good idea to check that our :cylc:conf:`flow.cylc` file does not have any + configuration issues. + + Run ``cylc validate`` to check for any errors: + + .. code-block:: bash + + cylc validate . + + #. **Install and Play the workflow.** + + Now we are ready to run our workflow. Validate, install, then open + the :ref:`GUI ` or :ref:`TUI ` and play + the workflow. + + .. code-block:: bash + + cylc validate . + cylc install + cylc play message-triggers + + Your workflow should now run, the tasks should succeed. + + #. **Inspect the work directory.** + + You can now check for your report outputs. These should appear in the + :term:`work directory` of the workflow. All being well, our first cycle + point should produce a test file with some random numbers, and each + subsequent cycle point file should have more random numbers added. + + #. **Extension.** + + Suppose now we would like to send an email alerting us to the reports + being ready to view. + + We will need to add to our :cylc:conf:`flow.cylc` file. + + In the ``runtime`` section, add a sub-section called ``[[[events]]]``. + Within this section we will make use of the built-in setting + ``mail events``. + Here, we specify a list of events for which notifications should be sent. + + The events we are interested in are, in this case, our outputs. + + Add the following code to your ``[[[events]]]`` section. + + .. code-block:: cylc + + [[[events]]] + mail events = update1, update2 + + Our updated workflow should look like this: + + .. spoiler:: Solution warning + + .. code-block:: cylc + + [scheduler] + UTC mode = True + [meta] + title = "test workflow to demo message triggers" + [scheduling] + initial cycle point = 2019-06-27T00Z + final cycle point = 2019-10-27T00Z + [[graph]] + P2M = """ + long_forecasting_task:update1 => another_weather_task + long_forecasting_task:update2 => different_weather_task + long_forecasting_task[-P2M] => long_forecasting_task + """ + [runtime] + [[long_forecasting_task]] + script = """ + sleep 2 + random.sh + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \ + "Task partially complete, report ready to view" + sleep 2 + random.sh + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \ + "Task partially complete, report updated" + sleep 2 + random.sh + """ + + [[[outputs]]] + update1 = "Task partially complete, report ready to view" + update2 = "Task partially complete, report updated" + + [[[events]]] + mail events = update1, update2 + + [[another_weather_task, different_weather_task]] + script = sleep 1 + + Save your changes and run your workflow. + Check your emails and you should have, one email for the first update and, + a second email alerting you to the subsequent updated reports being ready. + + Note that the second email automatically bundles the messages to prevent + your inbox from being flooded. diff --git a/nightly_8.4/html/_sources/tutorial/furthertopics/queues.rst.txt b/nightly_8.4/html/_sources/tutorial/furthertopics/queues.rst.txt new file mode 100644 index 00000000000..2f52eb19196 --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/furthertopics/queues.rst.txt @@ -0,0 +1,119 @@ +.. _tutorial.furthertopics.queues: + +Queues +====== + +Queues are used to put a limit on the number of tasks that will be active at +any one time, even if their dependencies are satisfied. This avoids swamping +systems with too many tasks at once. + + +Example +------- + +In this example, our workflow manages a particularly understaffed restaurant. + +Create a new workflow called ``queues-tutorial``:: + + mkdir -p ~/cylc-src/queues-tutorial + cd ~/cylc-src/queues-tutorial + +And paste the following into :cylc:conf:`flow.cylc`: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + open_restaurant => steak1 & steak2 & pasta1 & pasta2 & pasta3 & \ + pizza1 & pizza2 & pizza3 & pizza4 + steak1 => ice_cream1 + steak2 => cheesecake1 + pasta1 => ice_cream2 + pasta2 => sticky_toffee1 + pasta3 => cheesecake2 + pizza1 => ice_cream3 + pizza2 => ice_cream4 + pizza3 => sticky_toffee2 + pizza4 => ice_cream5 + """ + + [runtime] + [[open_restaurant]] + [[MAINS]] + [[DESSERT]] + [[steak1,steak2,pasta1,pasta2,pasta3,pizza1,pizza2,pizza3,pizza4]] + inherit = MAINS + [[ice_cream1,ice_cream2,ice_cream3,ice_cream4,ice_cream5]] + inherit = DESSERT + [[cheesecake1,cheesecake2,sticky_toffee1,sticky_toffee2]] + inherit = DESSERT + +.. note:: + + In graph sections, lines can be split on ``&``, i.e. the + following two examples are equivalent: + + .. code-block:: cylc-graph + + foo => bar & + baz + + .. code-block:: cylc-graph + + foo => bar & baz + + ``|`` (or), and ``=>`` act in the same way. + +Validate, install and play the workflow:: + + cylc validate . + cylc install --run-name without-queues + +Look at the workflow with :ref:`tutorial.gui` or :ref:`tutorial.tui` + +Play the workflow, either from the GUI or the command line:: + + cylc play queues-tutorial/without-queues + +You will see that all the ``steak``, ``pasta``, and ``pizza`` tasks are run +at once, swiftly followed by all the ``ice_cream``, ``cheesecake``, +``sticky_toffee`` tasks as the customers order from the dessert menu. + + +This will overwhelm our restaurant staff! The chef responsible for ``MAINS`` +can only handle 3 tasks at any given time, and the ``DESSERT`` chef can only +handle 2. + +We need to add some queues. Add a ``[queues]`` section to the ``[scheduling]`` +section like so: + +.. code-block:: cylc + + [scheduling] + [[queues]] + [[[mains_chef_queue]]] + limit = 3 # Only 3 mains dishes at one time. + members = MAINS + [[[dessert_chef_queue]]] + limit = 2 # Only 2 dessert dishes at one time. + members = DESSERT + +Install and play the workflow:: + + cylc validate . + cylc install --run-name tutorial-with-queues + +Play the workflow using the :ref:`GUI ` +or :ref:`TUI `. + +You should see that there are now never more than 3 active ``MAINS`` tasks +running and never more than 2 active ``DESSERT`` tasks running. + +The customers will obviously have to wait! + + +Further Reading +--------------- + +For more information, see the `Cylc User Guide`_. diff --git a/nightly_8.4/html/_sources/tutorial/furthertopics/retries.rst.txt b/nightly_8.4/html/_sources/tutorial/furthertopics/retries.rst.txt new file mode 100644 index 00000000000..5b04f81ab2e --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/furthertopics/retries.rst.txt @@ -0,0 +1,164 @@ +Retries +======= + +Retries allow us to automatically re-submit tasks which have failed due to +failure in submission or execution. + + +Purpose +------- + +Retries can be useful for tasks that occasionally fail for known, fixable +reasons. Cylc can rerun a failing job multiple times, with user-defined delays +between tries. + +Tasks that fail because of temporary hardware or network outages may succeed if +simply resubmitted after a delay. Others might succeed if configured differently +on the retry. + +A job environment variable ``$CYLC_TASK_TRY_NUMBER`` increments with each try, +to allow try-dependent behaviour in the task script. + +.. note:: + + Tasks only enter the ``submit-failed`` state if job submission fails with no + retries left. Otherwise they return to the waiting state, to wait on the + next try. + + Tasks only enter the ``failed`` state if job execution fails with no retries + left. Otherwise they return to the waiting state, to wait on the next try. + + +Example +------- + +.. image:: https://upload.wikimedia.org/wikipedia/commons/7/73/Double-six-dice.jpg + :width: 200px + :align: right + :alt: Two dice both showing the number six + +Create a new workflow by running the following commands:: + + mkdir -p ~/cylc-src/retries-tutorial + cd ~/cylc-src/retries-tutorial + +And paste the following code into a ``flow.cylc`` file. This workflow has a +``roll_doubles`` task that simulates trying to roll doubles using two dice: + +.. code-block:: cylc + + [scheduler] + UTC mode = True # Ignore DST + + [scheduling] + [[graph]] + R1 = start => roll_doubles => win + + [runtime] + [[start]] + [[win]] + [[roll_doubles]] + script = """ + sleep 10 + RANDOM=$$ # Seed $RANDOM + DIE_1=$((RANDOM%6 + 1)) + DIE_2=$((RANDOM%6 + 1)) + echo "Rolled $DIE_1 and $DIE_2..." + if (($DIE_1 == $DIE_2)); then + echo "doubles!" + else + exit 1 + fi + """ + + +Running Without Retries +----------------------- + +Let's see what happens when we run the workflow as it is. +Look at the workflow with :ref:`tutorial.gui` or :ref:`tutorial.tui` + +Then validate install and run the workflow:: + + cylc validate . + cylc install + cylc play retries-tutorial + +Unless you're lucky, the workflow should fail at the roll_doubles task. + +Stop the workflow:: + + cylc stop retries-tutorial + + +Configuring Retries +------------------- + +We need to tell Cylc to retry it a few times. To do this, add the following +to the end of the ``[[roll_doubles]]`` task section in the :cylc:conf:`flow.cylc` file: + +.. code-block:: cylc + + execution retry delays = 5*PT6S + +This means that if the ``roll_doubles`` task fails, Cylc expects to +retry running it 5 times before finally failing. Each retry will have +a delay of 6 seconds. + +We can apply multiple retry periods with the ``execution retry delays`` setting +by separating them with commas, for example the following line would tell Cylc +to retry a task four times, once after 15 seconds, then once after 10 minutes, +then once after one hour then once after three hours. + +.. code-block:: cylc + + execution retry delays = PT15S, PT10M, PT1H, PT3H + + +Running With Retries +-------------------- + +Look at the workflow with :ref:`tutorial.gui` or :ref:`tutorial.tui` + +Re-install and run the workflow:: + + cylc validate . + cylc install + cylc play retries-tutorial + +What you should see is Cylc retrying the ``roll_doubles`` task. Hopefully, +it will succeed (there is only about a 1 in 3 chance of every task +failing) and the workflow will continue. + + +Altering Behaviour +------------------ + +We can alter the behaviour of the task based on the number of retries, using +``$CYLC_TASK_TRY_NUMBER``. + +Change the ``script`` setting for the ``roll_doubles`` task to this:: + + sleep 10 + RANDOM=$$ # Seed $RANDOM + DIE_1=$((RANDOM%6 + 1)) + DIE_2=$((RANDOM%6 + 1)) + echo "Rolled $DIE_1 and $DIE_2..." + if (($DIE_1 == $DIE_2)); then + echo "doubles!" + elif (($CYLC_TASK_TRY_NUMBER >= 2)); then + echo "look over there! ..." + echo "doubles!" # Cheat! + else + exit 1 + fi + +If your workflow is still running, stop it, then run it again. + +This time, the task should definitely succeed before the third retry. + + +Further Reading +--------------- + +For more information see the `Cylc User Guide`_. diff --git a/nightly_8.4/html/_sources/tutorial/index.rst.txt b/nightly_8.4/html/_sources/tutorial/index.rst.txt new file mode 100644 index 00000000000..4eb13712687 --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/index.rst.txt @@ -0,0 +1,15 @@ +.. _Cylc Tutorial: + +Tutorial +======== + +This tutorial shows how to write and run basic Cylc workflows. + +.. toctree:: + :name: cylc-tutorial + :maxdepth: 2 + + introduction + scheduling/index + runtime/index + furthertopics/index diff --git a/nightly_8.4/html/_sources/tutorial/introduction.rst.txt b/nightly_8.4/html/_sources/tutorial/introduction.rst.txt new file mode 100644 index 00000000000..ebaada27d8b --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/introduction.rst.txt @@ -0,0 +1,100 @@ +.. _cylc-introduction: + +Introduction +============ + +.. _cylc-what-is-a-workflow: + +What Is A Workflow? +------------------- + +.. epigraph:: + + A workflow consists of an orchestrated and repeatable pattern of business + activity enabled by the systematic organization of resources into processes + that transform materials, provide services, or process information. + + -- Wikipedia + +.. ifnotslides:: + + In research, business and other fields we may need to repeat processes in + the course of our work. At its simplest a workflow is a set of steps that + must be followed in a particular order to achieve some end goal. + + We can represent each "step" in a workflow as a node in a graph, and the + order with arrows between them. + +.. nextslide:: + +.. digraph:: bakery + :align: center + + "purchase ingredients" -> "make dough" -> "bake bread" -> "sell bread" + "bake bread" -> "clean oven" + "pre-heat oven" -> "bake bread" + + +.. _cylc-what-is-cylc: + +What Is Cylc? +------------- + +.. ifnotslides:: + + Cylc (pronounced silk) is a workflow engine, a system that automatically + executes tasks according to schedules and dependencies. + + In a Cylc workflow each step is a computational task that runs a script or + application of some kind. Cylc runs each task as soon as it is appropriate + to do so. + +.. minicylc:: + :align: center + :theme: demo + + a => b => c + b => d => f + e => f + +.. nextslide:: + +Cylc can automatically: + +- Submit tasks across computer systems and resource managers. +- Recover from failures. +- Repeat workflows. + +.. ifnotslides:: + + Cylc was originally developed at NIWA (The National Institute of Water and + Atmospheric Research, New Zealand) for running their weather forecasting + workflows. It is now developed by an international partnership including + NIWA, the Met Office (UK), and members of the Unified Model Consortium. + Though initially developed for meteorological purposes Cylc is a general + purpose tool as applicable in business as it is in scientific research. + +.. nextslide:: + +.. ifslides:: + + * Originally developed at NIWA (New Zealand) + * Now developed by an international partnership including the + Met Office (UK). + * General purpose tool as applicable in business as in + scientific research. + +.. nextslide:: + +Cylc provides a variety of command line and GUI tools for visualising, +monitoring, and controlling workflows. The Cylc TUI (Terminal +User Interface), web GUI, and ``cylc scan`` (bottom left) are shown below. + +.. image:: /tutorial/img/cylc-tools.png + :alt: A screenshot of several Cylc tools. + +.. nextslide:: + +.. ifslides:: + + :ref:`tutorial-cylc-graphing` diff --git a/nightly_8.4/html/_sources/tutorial/runtime/configuration-consolidation/families.rst.txt b/nightly_8.4/html/_sources/tutorial/runtime/configuration-consolidation/families.rst.txt new file mode 100644 index 00000000000..d4899905dd6 --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/runtime/configuration-consolidation/families.rst.txt @@ -0,0 +1,333 @@ +.. _tutorial-cylc-families: + +Families +======== + +:term:`Families ` provide a way of grouping tasks together so they can +be treated as one. + + +Runtime +------- + +.. ifnotslides:: + + :term:`Families ` are groups of tasks which share a common + configuration. In the present example the common configuration is: + + .. code-block:: cylc + + script = get-observations + [[[environment]]] + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + We define a family as a new task consisting of the common configuration. By + convention families are named in upper case: + +.. code-block:: cylc + + [[GET_OBSERVATIONS]] + script = get-observations + [[[environment]]] + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +.. ifnotslides:: + + We "add" tasks to a family using the ``inherit`` setting: + +.. code-block:: cylc + + [[get_observations_heathrow]] + inherit = GET_OBSERVATIONS + [[[environment]]] + SITE_ID = 3772 + +.. ifnotslides:: + + When we add a task to a family in this way it :term:`inherits ` the configuration from the family, i.e. the above example is + equivalent to: + +.. code-block:: cylc + + [[get_observations_heathrow]] + script = get-observations + [[[environment]]] + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + SITE_ID = 3772 + +.. nextslide:: + +.. ifnotslides:: + + It is possible to override inherited configuration within the task. For + example if we wanted the ``get_observations_heathrow`` task to use a + different API key we could write: + +.. code-block:: cylc + :emphasize-lines: 4 + + [[get_observations_heathrow]] + inherit = GET_OBSERVATIONS + [[[environment]]] + API_KEY = special-api-key + SITE_ID = 3772 + +.. nextslide:: + +.. ifnotslides:: + + Using families the ``get_observations`` tasks could be written like so: + +.. code-block:: cylc + + [runtime] + [[GET_OBSERVATIONS]] + script = get-observations + [[[environment]]] + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + [[get_observations_heathrow]] + inherit = GET_OBSERVATIONS + [[[environment]]] + SITE_ID = 3772 + [[get_observations_camborne]] + inherit = GET_OBSERVATIONS + [[[environment]]] + SITE_ID = 3808 + [[get_observations_shetland]] + inherit = GET_OBSERVATIONS + [[[environment]]] + SITE_ID = 3005 + [[get_observations_aldergrove]] + inherit = GET_OBSERVATIONS + [[[environment]]] + SITE_ID = 3917 + + +Graphing +-------- + +.. ifnotslides:: + + :term:`Families ` can be used in the workflow's :term:`graph`, e.g: + +.. code-block:: cylc-graph + + GET_OBSERVATIONS:succeed-all => consolidate_observations + +.. ifnotslides:: + + The ``:succeed-all`` is a special :term:`qualifier` which in this example + means that the ``consolidate_observations`` task will run once *all* of the + members of the ``GET_OBSERVATIONS`` family have succeeded. This is + equivalent to: + +.. code-block:: cylc-graph + + get_observations_heathrow => consolidate_observations + get_observations_camborne => consolidate_observations + get_observations_shetland => consolidate_observations + get_observations_aldergrove => consolidate_observations + +.. ifnotslides:: + + The ``GET_OBSERVATIONS:succeed-all`` part is referred to as a + :term:`family trigger`. Family triggers use special qualifiers which are + non-optional. The most commonly used ones are: + + ``succeed-all`` + Run if all of the members of the family have succeeded. + ``succeed-any`` + Run as soon as any one family member has succeeded. + ``finish-all`` + Run as soon as all of the family members have completed (i.e. have each + either succeeded or failed). + + For more information on family triggers see the `Cylc User Guide`_. + +.. ifslides:: + + * ``succeed-all`` + * ``succeed-any`` + * ``finish-all`` + + +The ``root`` Family +------------------- + +.. ifnotslides:: + + There is a special family called ``root`` (in lowercase) which is used only + in the runtime to provide configuration which will be inherited by all + tasks. + + In the following example the task ``bar`` will inherit the environment + variable ``FOO`` from the ``[root]`` section: + +.. code-block:: cylc + + [runtime] + [[root]] + [[[environment]]] + FOO = foo + [[bar]] + script = echo $FOO + + +.. TODO - Replace once the new GUI supports this. + + Families and ``cylc graph`` + --------------------------- + + + .. ifnotslides:: + + By default, ``cylc graph`` groups together all members of a family + in the :term:`graph`. To un-group a family right click on it and select + :menuselection:`UnGroup`. + + For instance if the tasks ``bar`` and ``baz`` both + inherited from ``BAR`` ``cylc graph`` would produce: + + .. digraph:: Example + :align: center + + subgraph cluster_1 { + label = "Grouped" + "1/foo" [label="foo"] + "1/BAR" [label="BAR", shape="doubleoctagon"] + } + + subgraph cluster_2 { + label = "Un-Grouped" + "2/foo" [label="foo"] + "2/bar" [label="bar"] + "2/baz" [label="baz"] + } + + "1/foo" -> "1/BAR" + "2/foo" -> "2/bar" + "2/foo" -> "2/baz" + + +.. nextslide:: + +.. ifslides:: + + .. rubric:: In this practical we will consolidate the configuration of the + :ref:`weather-forecasting workflow ` + from the previous section. + + Next section: :ref:`Jinja2 ` + + +.. _cylc-tutorial-families-practical: + +.. practical:: + + .. rubric:: In this practical we will consolidate the configuration of the + :ref:`weather-forecasting workflow ` + from the previous section. + + 1. **Create A New Workflow.** + + To make a new copy of the forecasting workflow run the following commands: + + .. code-block:: bash + + cylc get-resources tutorial/consolidation-tutorial + cd ~/cylc-src/consolidation-tutorial + + 2. **Move Site-Wide Settings Into The** ``root`` **Family.** + + The following two environment variables are used by multiple tasks: + + .. code-block:: none + + RESOLUTION = 0.2 + DOMAIN = -12,48,5,61 # Do not change! + + Rather than manually adding them to each task individually we could put + them in the ``root`` family, making them accessible to all tasks. + + Add a ``root`` section containing these two environment variables. + Remove the variables from any other task's ``environment`` sections: + + .. code-block:: diff + + [runtime] + + [[root]] + + [[[environment]]] + + # The dimensions of each grid cell in degrees. + + RESOLUTION = 0.2 + + # The area to generate forecasts for (lng1, lat1, lng2, lat2). + + DOMAIN = -12,48,5,61 # Do not change! + + .. code-block:: diff + + [[consolidate_observations]] + script = consolidate-observations + - [[[environment]]] + - # The dimensions of each grid cell in degrees. + - RESOLUTION = 0.2 + - # The area to generate forecasts for (lng1, lat1, lng2, lat2). + - DOMAIN = -12,48,5,61 # Do not change! + + [[get_rainfall]] + script = get-rainfall + [[[environment]]] + # The key required to get weather data from the DataPoint service. + # To use archived data comment this line out. + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + - # The dimensions of each grid cell in degrees. + - RESOLUTION = 0.2 + - # The area to generate forecasts for (lng1, lat1, lng2, lat2). + - DOMAIN = -12,48,5,61 # Do not change! + + [[forecast]] + script = forecast 60 5 # Generate 5 forecasts at 60 minute intervals. + [[[environment]]] + - # The dimensions of each grid cell in degrees. + - RESOLUTION = 0.2 + - # The area to generate forecasts for (lng1, lat1, lng2, lat2) + - DOMAIN = -12,48,5,61 # Do not change! + # The path to the files containing wind data (the {variables} will + # get substituted in the forecast script). + WIND_FILE_TEMPLATE = $CYLC_WORKFLOW_WORK_DIR/{cycle}/consolidate_observations/wind_{xy}.csv + # List of cycle points to process wind data from. + WIND_CYCLES = 0, -3, -6 + + # The path to the rainfall file. + RAINFALL_FILE = $CYLC_WORKFLOW_WORK_DIR/$CYLC_TASK_CYCLE_POINT/get_rainfall/rainfall.csv + # Create the html map file in the task's log directory. + MAP_FILE = "${CYLC_TASK_LOG_ROOT}-map.html" + # The path to the template file used to generate the html map. + MAP_TEMPLATE = "$CYLC_WORKFLOW_RUN_DIR/lib/template/map.html" + + [[post_process_exeter]] + # Generate a forecast for Exeter 60 minutes into the future. + script = post-process exeter 60 + - [[[environment]]] + - # The dimensions of each grid cell in degrees. + - RESOLUTION = 0.2 + - # The area to generate forecasts for (lng1, lat1, lng2, lat2). + - DOMAIN = -12,48,5,61 # Do not change! + + To ensure that the environment variables are being inherited correctly + by the tasks, inspect the ``[runtime]`` section using ``cylc config`` + by running the following command: + + .. code-block:: bash + + cylc config . -i "[runtime]" + + You should see the environment variables from the ``[root]`` section + in the ``[environment]`` section for all tasks. + + .. tip:: + + You may find it easier to open the output of this command in a text + editor, e.g:: + + cylc config . -i "[runtime]" | gvim - diff --git a/nightly_8.4/html/_sources/tutorial/runtime/configuration-consolidation/index.rst.txt b/nightly_8.4/html/_sources/tutorial/runtime/configuration-consolidation/index.rst.txt new file mode 100644 index 00000000000..30a0287c791 --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/runtime/configuration-consolidation/index.rst.txt @@ -0,0 +1,187 @@ +.. _tutorial-cylc-consolidating-configuration: + +Consolidating Configuration +=========================== + +.. ifnotslides:: + + In the last section we wrote out the following code in the + :cylc:conf:`flow.cylc` file: + +.. slide:: Weather Forecasting Workflow + :level: 2 + :inline-contents: True + + .. code-block:: cylc + + [runtime] + [[get_observations_heathrow]] + script = get-observations + [[[environment]]] + SITE_ID = 3772 + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + [[get_observations_camborne]] + script = get-observations + [[[environment]]] + SITE_ID = 3808 + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + [[get_observations_shetland]] + script = get-observations + [[[environment]]] + SITE_ID = 3005 + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + [[get_observations_aldergrove]] + script = get-observations + [[[environment]]] + SITE_ID = 3917 + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +.. ifnotslides:: + + In this code the ``script`` item and the ``API_KEY`` environment variable have + been repeated for each task. This is bad practice as it makes the + configuration lengthy and harder to maintain. + + Likewise the graph relating to the ``get_observations`` tasks is highly + repetitive: + +.. ifslides:: + + .. slide:: Weather Forecasting Workflow + :level: 2 + + Repetition + + * ``script`` + * ``API_KEY`` + +.. slide:: Weather Forecasting Workflow + :level: 2 + :inline-contents: True + + .. code-block:: cylc + + [scheduling] + [[graph]] + T00/PT3H = """ + get_observations_aldergrove => consolidate_observations + get_observations_camborne => consolidate_observations + get_observations_heathrow => consolidate_observations + get_observations_shetland => consolidate_observations + """ + +.. nextslide:: + +Cylc offers three ways of consolidating configurations to help improve the +structure of a workflow and avoid duplication. + +.. toctree:: + :maxdepth: 1 + + families + jinja2 + parameters + + +The ``cylc config`` Command +--------------------------- + +.. ifnotslides:: + + The ``cylc config`` command reads in either the + :cylc:conf:`global.cylc` file, or a specific workflow's :cylc:conf:`flow.cylc` + file, and it prints the parsed configuration out to the terminal. + + Throughout this section as we introduce methods for consolidating + the :cylc:conf:`flow.cylc` file, the ``cylc config`` command can be used to + "expand" the file back to its full form. + + .. note:: + + A primary use of ``cylc config`` is inspecting the + ``[runtime]`` section of a workflow. However, the command does not + expand :term:`parameterizations ` and + :term:`families ` in the workflow :term:`graph`. To see the + expanded graph use the ``cylc graph`` command. + + Call ``cylc config`` with the path of the workflow (or ``.`` if you are + already in the :term:`source directory` or the :term:`run directory`). + +.. code-block:: sub + + cylc config + +.. ifnotslides:: + + To view the configuration of a particular section or setting refer to it by + name using the ``-i`` option (see :ref:`Cylc file format` for details), e.g: + +.. code-block:: sub + + # Print the contents of the [scheduling] section. + cylc config -i '[scheduling]' + # Print the contents of the get_observations_heathrow task. + cylc config -i '[runtime][get_observations_heathrow]' + # Print the value of the script setting in the get_observations_heathrow task + cylc config -i '[runtime][get_observations_heathrow]script' + +.. nextslide:: + +.. ifslides:: + + Note that ``cylc config`` doesn't expand families or parameterizations + in the :term:`graph`. Use ``cylc graph`` to visualise these. + + .. TODO - Raise and issue for this, note cylc config and cylc view. + + +The Three Approaches +-------------------- + +.. ifnotslides:: + + The next three sections cover the three consolidation approaches and how we + could use them to simplify the workflow from the previous tutorial. *Work + through them in order!* + +* :ref:`families ` +* :ref:`jinja2 ` +* :ref:`parameters ` + + +.. _cylc-tutorial-consolidation-conclusion: + +Which Approach To Use +--------------------- + +.. ifnotslides:: + + Each approach has its uses. Cylc permits mixing approaches, allowing us to + use what works best for us. As a rule of thumb: + + * :term:`Families ` work best consolidating runtime configuration by + collecting tasks into broad groups, e.g. groups of tasks which run on a + particular machine or groups of tasks belonging to a particular system. + * `Jinja2`_ is good at configuring settings which apply to the entire workflow + rather than just a single task, as we can define variables then use them + throughout the workflow. + * :term:`Parameterization ` works best for describing tasks + which are very similar but which have subtly different configurations + (e.g. different arguments or environment variables). + +.. ifslides:: + + As a rule of thumb each method works best for: + + Families + Collecting tasks into broad groups. + Jinja2 + Configuration settings which apply to the entire workflow. + Parameterization + Tasks which are similar. + +.. nextslide:: + +.. ifslides:: + + Next section: :ref:`Rose Tutorial ` diff --git a/nightly_8.4/html/_sources/tutorial/runtime/configuration-consolidation/jinja2.rst.txt b/nightly_8.4/html/_sources/tutorial/runtime/configuration-consolidation/jinja2.rst.txt new file mode 100644 index 00000000000..606e2a406fd --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/runtime/configuration-consolidation/jinja2.rst.txt @@ -0,0 +1,237 @@ +.. _shebang: https://en.wikipedia.org/wiki/Shebang_(Unix) + + +.. _tutorial-cylc-jinja2: + +Jinja2 +====== + + +`Jinja2`_ is a templating language often used in web design, with some +similarities to Python. It can be used to make a workflow definition more +dynamic. + + +The Jinja2 Language +------------------- + +In Jinja2 statements are wrapped with ``{%`` characters, i.e: + +.. code-block:: none + + {% ... %} + +Variables are initialised with the ``set`` statement, e.g: + +.. code-block:: css+jinja + + {% set foo = 3 %} + +.. nextslide:: + +Expressions wrapped with ``{{`` characters will be replaced with +the evaluated expression, e.g: + +.. code-block:: css+jinja + + There are {{ foo }} methods for consolidating the flow.cylc file + +Would result in:: + + There are 3 methods for consolidating the flow.cylc file + +.. nextslide:: + +Loops are written with ``for`` statements, e.g: + +.. code-block:: css+jinja + + {% for x in range(foo) %} + {{ x }} + {% endfor %} + +Would result in: + +.. code-block:: none + + 0 + 1 + 2 + +.. nextslide:: + +To enable Jinja2 in the :cylc:conf:`flow.cylc` file, add the following `shebang`_ to the +top of the file: + +.. code-block:: cylc + + #!Jinja2 + +For more information see the `Jinja2`_ documentation. + + +Example +------- + +To consolidate the configuration for the ``get_observations`` tasks we could +define a dictionary of station and ID pairs: + +.. code-block:: css+jinja + + {% set stations = {'aldergrove': 3917, + 'camborne': 3808, + 'heathrow': 3772, + 'shetland': 3005} %} + +.. nextslide:: + +We could then loop over the stations like so: + +.. code-block:: css+jinja + + {% for station in stations %} + {{ station }} + {% endfor %} + +After processing, this would result in: + +.. code-block:: none + + aldergrove + camborne + heathrow + shetland + +.. nextslide:: + +We could also loop over both the stations and corresponding IDs like so: + +.. code-block:: css+jinja + + {% for station, id in stations.items() %} + {{ station }} - {{ id }} + {% endfor %} + +This would result in: + +.. code-block:: none + + aldergrove - 3917 + camborne - 3808 + heathrow - 3772 + shetland - 3005 + +.. nextslide:: + +.. ifnotslides:: + + Putting this all together, the ``get_observations`` configuration could be + written as follows: + +.. code-block:: cylc + + #!Jinja2 + + {% set stations = {'aldergrove': 3917, + 'camborne': 3808, + 'heathrow': 3772, + 'shetland': 3005} %} + + [scheduler] + allow implicit tasks = True + + [scheduling] + [[graph]] + T00/PT3H = """ + {% for station in stations %} + get_observations_{{station}} => consolidate_observations + {% endfor %} + """ + +.. nextslide:: + +.. code-block:: cylc + + [runtime] + {% for station, id in stations.items() %} + [[get_observations_{{station}}]] + script = get-observations + [[[environment]]] + SITE_ID = {{ id }} + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + {% endfor %} + +.. nextslide:: + +.. ifslides:: + + .. rubric:: This practical continues on from the + :ref:`families practical `. + + Next section: :ref:`tutorial-cylc-parameterization` + + +.. _cylc-tutorial-jinja2-practical: + +.. practical:: + + .. rubric:: This practical continues on from the + :ref:`families practical `. + + 3. **Use Jinja2 To Avoid Duplication.** + + The ``API_KEY`` environment variable is used by both the + ``get_observations`` and ``get_rainfall`` tasks. Rather than writing it + out multiple times we will use Jinja2 to centralise this configuration. + + At the top of the :cylc:conf:`flow.cylc` file add the Jinja2 shebang line. Then + copy the value of the ``API_KEY`` environment variable and use it to + define an ``API_KEY`` Jinja2 variable: + + .. code-block:: cylc + + #!Jinja2 + + {% set API_KEY = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' %} + + Next replace the key, where it appears in the workflow, with + ``{{ API_KEY }}``: + + .. code-block:: diff + + [runtime] + [[get_observations_heathrow]] + script = get-observations + [[[environment]]] + SITE_ID = 3772 + - API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + API_KEY = {{ API_KEY }} + [[get_observations_camborne]] + script = get-observations + [[[environment]]] + SITE_ID = 3808 + - API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + API_KEY = {{ API_KEY }} + [[get_observations_shetland]] + script = get-observations + [[[environment]]] + SITE_ID = 3005 + - API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + API_KEY = {{ API_KEY }} + [[get_observations_aldergrove]] + script = get-observations + [[[environment]]] + SITE_ID = 3917 + - API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + API_KEY = {{ API_KEY }} + [[get_rainfall]] + script = get-rainfall + [[[environment]]] + # The key required to get weather data from the DataPoint service. + # To use archived data comment this line out. + - API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + API_KEY = {{ API_KEY }} + + Check the result with ``cylc config``. The Jinja2 will be processed + so you should not see any difference after making these changes. diff --git a/nightly_8.4/html/_sources/tutorial/runtime/configuration-consolidation/parameters.rst.txt b/nightly_8.4/html/_sources/tutorial/runtime/configuration-consolidation/parameters.rst.txt new file mode 100644 index 00000000000..09780b0bddc --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/runtime/configuration-consolidation/parameters.rst.txt @@ -0,0 +1,344 @@ +.. _tutorial-cylc-parameterization: + + +Parameterized Tasks +=================== + + +Parameterized tasks (see :term:`parameterization`) provide a way of implicitly +looping over tasks without the need for Jinja2. + + +Cylc Parameters +--------------- + +.. ifnotslides:: + + Parameters are defined in their own section, e.g: + +.. code-block:: cylc + + [task parameters] + world = Mercury, Venus, Earth + + +.. ifnotslides:: + + They can then be referenced by writing the name of the parameter in angle + brackets, e.g: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = start => hello => end + [runtime] + [[hello]] + script = echo 'Hello World!' + +.. nextslide:: + +.. ifnotslides:: + + When the :cylc:conf:`flow.cylc` file is read by Cylc, the parameters will be expanded. + For example the code above is equivalent to: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + start => hello_Mercury => end + start => hello_Venus => end + start => hello_Earth => end + """ + [runtime] + [[hello_Mercury]] + script = echo 'Hello World!' + [[hello_Venus]] + script = echo 'Hello World!' + [[hello_Earth]] + script = echo 'Hello World!' + +.. nextslide:: + +.. ifnotslides:: + + We can refer to a specific parameter by writing it after an ``=`` sign: + +.. code-block:: cylc + + [runtime] + [[hello]] + script = echo 'Greetings Earth!' + + +Environment Variables +--------------------- + +.. ifnotslides:: + + The name of the parameter is provided to the job as an environment variable + called ``CYLC_TASK_PARAM_`` where ```` is the name of + the parameter (in the present case ``world``): + +.. code-block:: cylc + + [runtime] + [[hello]] + script = echo "Hello ${CYLC_TASK_PARAM_world}!" + + +Parameter Types +--------------- + +Parameters can be either strings or integers: + +.. code-block:: cylc + + [task parameters] + foo = 1..5 + bar = 1..5..2 + baz = pub, qux, bol + +.. nextslide:: + +.. hint:: + + Remember that by default Cylc automatically inserts an underscore between the task and + the parameter, e.g. the following lines are equivalent: + + .. code-block:: cylc-graph + + task + task_pub + +.. nextslide:: + +.. hint:: + + .. ifnotslides:: + + When using integer parameters, to prevent confusion, Cylc prefixes the + parameter value with the parameter name. For example: + + .. ifslides:: + + Cylc prefixes integer parameters with the parameter name: + + .. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + # task would result in: + task_bar1 + task_bar3 + task_bar5 + + # task would result in: + task_pub + task_qux + task_bol + """ + +.. nextslide:: + +.. ifnotslides:: + + Using parameters the ``get_observations`` configuration could be written like + so: + +.. code-block:: cylc + + [scheduling] + [[graph]] + T00/PT3H = """ + get_observations => consolidate_observations + """ + [runtime] + [[get_observations]] + script = get-observations + [[[environment]]] + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + [[get_observations]] + [[[environment]]] + SITE_ID = 3917 + [[get_observations]] + [[[environment]]] + SITE_ID = 3808 + [[get_observations]] + [[[environment]]] + SITE_ID = 3772 + [[get_observations]] + [[[environment]]] + SITE_ID = 3005 + +.. nextslide:: + +.. ifnotslides:: + + For more information see the `Cylc User Guide`_. + +.. ifslides:: + + .. rubric:: This practical continues on from the + :ref:`Jinja2 practical `. + + Next section: :ref:`Which approach to use + ` + + +.. _cylc-tutorial-parameters-practical: + +.. practical:: + + .. rubric:: This practical continues on from the + :ref:`Jinja2 practical `. + + 4. **Use Parameterization To Consolidate The** ``get_observations`` + **Tasks**. + + Next we will parameterize the ``get_observations`` tasks. + + Add a parameter called ``station``: + + .. code-block:: diff + + +[task parameters] + + station = aldergrove, camborne, heathrow, shetland + + [scheduler] + UTC mode = True + + Remove the four ``get_observations`` tasks and insert the following code + in their place: + + .. code-block:: cylc + + [[get_observations]] + script = get-observations + [[[environment]]] + API_KEY = {{ API_KEY }} + + Using ``cylc config`` you should see that Cylc replaces the + ```` with each of the stations in turn, creating a new task for + each: + + .. code-block:: bash + + cylc config . -i "[runtime]" + + The ``get_observations`` tasks are now missing the ``SITE_ID`` + environment variable. Add a new section for each station with a + ``SITE_ID``: + + .. code-block:: cylc + + [[get_observations]] + [[[environment]]] + SITE_ID = 3772 + + .. hint:: + + The relevant IDs are: + + * Aldergrove - ``3917`` + * Camborne - ``3808`` + * Heathrow - ``3772`` + * Shetland - ``3005`` + + .. spoiler:: Solution warning + + .. code-block:: cylc + + [[get_observations]] + [[[environment]]] + SITE_ID = 3917 + [[get_observations]] + [[[environment]]] + SITE_ID = 3808 + [[get_observations]] + [[[environment]]] + SITE_ID = 3772 + [[get_observations]] + [[[environment]]] + SITE_ID = 3005 + + Using ``cylc config`` you should now see four ``get_observations`` + tasks, each with a ``script``, an ``API_KEY`` and a ``SITE_ID``: + + .. code-block:: bash + + cylc config . -i "[runtime]" + + Finally we can use this parameterization to simplify the workflow's + graphing. Replace the ``get_observations`` lines in the graph with + ``get_observations``: + + .. code-block:: diff + + # Repeat every three hours starting at the initial cycle point. + PT3H = """ + - get_observations_aldergrove => consolidate_observations + - get_observations_camborne => consolidate_observations + - get_observations_heathrow => consolidate_observations + - get_observations_shetland => consolidate_observations + + get_observations => consolidate_observations + """ + + .. hint:: + + The ``cylc config`` command does not expand parameters or families + in the graph so you must use ``cylc graph`` to inspect changes to the + graphing. + + #. **Use Parameterization To Consolidate The** ``post_process`` **Tasks**. + + At the moment we only have one ``post_process`` task + (``post_process_exeter``), but suppose we wanted to add a second task for + Edinburgh. + + Create a new parameter called ``site`` and set it to contain ``exeter`` + and ``edinburgh``. Parameterize the ``post_process`` task using this + parameter. + + .. hint:: + + The first argument to the ``post-process`` task is the name of the + site. We can use the ``CYLC_TASK_PARAM_site`` environment variable to + avoid having to write out this section twice. + + .. TODO - use parameter environment templates instead of + CYLC_TASK_PARAM. + + .. spoiler:: Solution warning + + First we must create the ``site`` parameter: + + .. code-block:: diff + + [scheduler] + UTC mode = True + [task parameters] + station = aldergrove, camborne, heathrow, shetland + + site = exeter, edinburgh + + Next we parameterize the task in the graph: + + .. code-block:: diff + + + -get_rainfall => forecast => post_process_exeter + +get_rainfall => forecast => post_process + + And also the runtime: + + .. code-block:: diff + + -[[post_process_exeter]] + +[[post_process]] + # Generate a forecast for Exeter 60 minutes in the future. + - script = post-process exeter 60 + + script = post-process $CYLC_TASK_PARAM_site 60 diff --git a/nightly_8.4/html/_sources/tutorial/runtime/index.rst.txt b/nightly_8.4/html/_sources/tutorial/runtime/index.rst.txt new file mode 100644 index 00000000000..84c48c3257e --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/runtime/index.rst.txt @@ -0,0 +1,20 @@ +.. _tutorial-runtime: + +Runtime +======= + +This section covers: + +* Associating workflow tasks with executable applications (scripts and + programs). +* Providing executables with runtime configurations, within the workflow. +* Running Cylc workflows. + +.. toctree:: + :name: rug-runtime-toc + :maxdepth: 2 + + introduction + runtime-configuration + configuration-consolidation/index + summary diff --git a/nightly_8.4/html/_sources/tutorial/runtime/introduction.rst.txt b/nightly_8.4/html/_sources/tutorial/runtime/introduction.rst.txt new file mode 100644 index 00000000000..8a8e11fae6d --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/runtime/introduction.rst.txt @@ -0,0 +1,597 @@ +.. _tutorial-cylc-runtime-introduction: + +Introduction +============ + +.. ifnotslides:: + + So far we have worked with the ``[scheduling]`` section of the ``flow.cylc`` + file, where workflow :term:`tasks ` and :term:`dependencies + ` are defined. + + Now, in the ``[runtime]`` section, we need to associate each task with a + script or application to run when its dependencies are met. + +.. ifslides:: + + ``[scheduling]`` + Defines the workflow in terms of :term:`tasks ` and + :term:`dependencies `. + ``[runtime]`` + Determines what runs, where, and how it runs, for each task. + +Task Definitions +---------------- + +.. ifnotslides:: + + The runtime settings for each task are stored in a sub-section of the + ``[runtime]`` section. E.g. for a task called ``hello_world`` we would write + settings inside the following section: + +.. code-block:: cylc + + [runtime] + [[hello_world]] + +.. note:: + + A runtime sub-section for each task is normally required, even if it is + empty. However, in the previous tutorials we disabled this requirement + with :cylc:conf:`flow.cylc[scheduler]allow implicit tasks`. + See :ref:`ImplicitTasks` for more details. + + +The ``script`` Setting +---------------------- + +.. ifnotslides:: + + The task ``script`` setting tells Cylc *what* to execute when a task is + ready to run. + + This value of this setting is interpreted as a bash script. The following + example defines a task called ``hello_world`` which simply writes ``Hello + World!`` to standard output. + +.. code-block:: cylc + + [runtime] + [[hello_world]] + script = echo 'Hello World!' + +.. note:: + + A task with no ``script`` defined will run a job that does nothing but + communicate its status back to the scheduler before exiting immediately. + + +We can also call other scripts or executables in this way, e.g: + +.. code-block:: cylc + + [runtime] + [[hello_world]] + script = ~/foo/bar/baz/hello_world + + +``PATH`` and :envvar:`PYTHONPATH` +--------------------------------- + +.. ifnotslides:: + + Keeping task scripts with the workflow, rather than leaving them elsewhere on + the system, helps isolate the workflow from external changes. + + To help with this, Cylc automatically adds a ``bin/`` sub-directory of the + workflow :term:`source directory` to the executable search path (``$PATH``) + in task environments. + +.. code-block:: bash + :caption: bin/hello_world + + #!/bin/bash + echo 'Hello World!' + +.. code-block:: cylc + :caption: flow.cylc + + [runtime] + [[hello_world]] + script = hello_world + +.. nextslide:: + +.. ifnotslides:: + + Similarly the ``lib/python/`` directory gets prepended to the + :envvar:`PYTHONPATH` variable. + +.. code-block:: python + :caption: lib/python/hello.py + + def world(): + print('Hello World!') + +.. code-block:: cylc + :caption: flow.cylc + + [runtime] + [[hello_world]] + script = python -c 'import hello; hello.world()' + + +.. _tutorial-tasks-and-jobs: + +Tasks And Jobs +-------------- + +.. ifnotslides:: + + When a :term:`task` is ready to run Cylc creates a :term:`job script` for + it: a bash file containing the scripting defined for the task along with + other configuration and error trapping code. This is what actually executes + as the job. + + :term:`Tasks` typically go through the following states as a workflow + runs: + + Waiting + Waiting for dependencies to be met. + Preparing + Dependencies met; preparing the task :term:`job script` for submission. + Submitted + Job script submitted to the :term:`job runner`; waiting on execution. + Running + Job script executing. + Succeeded + Job completed successfully (i.e. exited with 0 return status). + + There are several other task states as well, such as **failed**. + + See the :ref:`next section for more about running jobs `. + + +.. ifslides:: + + When a :term:`task` is ready to run, Cylc creates a :term:`job`. + + The life-cycle of a task: + + * Waiting + * Preparing + * Submitted + * Running + * Succeeded / Failed + +The Cylc User Interfaces +------------------------ + +.. ifnotslides:: + + To help you to keep monitor and control running workflows Cylc has + + - A graphical user interface (Cylc GUI). + - A terminal-based user interface (Cylc TUI). + - A comprehensive command line interface (Cylc CLI). + + +.. _tutorial.cli: + +The Cylc CLI +^^^^^^^^^^^^ + +.. ifnotslides:: + + You can start, stop, query, and control workflow, in every possible way, + from the command line. + + All Cylc commands have built-in help information: + +.. code-block:: bash + + cylc help + cylc play --help # etc. + + +.. _tutorial.tui: + +The Cylc TUI +^^^^^^^^^^^^ + +.. ifnotslides:: + + The Cylc TUI (Terminal User Interface) enables you to view and interact + with your workflows. + + To start the Cylc TUI: + +.. code-block:: bash + + cylc tui + +.. _tutorial.gui: + +The Cylc GUI +^^^^^^^^^^^^ + +.. ifnotslides:: + + The Cylc GUI has different views you can use to examine your workflows, + including a Cylc scan menu allowing you to switch between workflows. + + .. note:: + + You only need to have one instance of the Cylc GUI open - you can + easily switch between workflows. + + To start the Cylc UI, open a new terminal window or tab, then type: + +.. code-block:: bash + + cylc gui + +.. nextslide:: + +Task & Job States +^^^^^^^^^^^^^^^^^ + +.. ifnotslides:: + + - Task states have grey icons. + - Job states have colour coded squares. + +.. csv-table:: + :header: Task Icon, Job Icon, Description + :align: left + :widths: 25, 25, 50 + + |task-waiting|, , Task waiting + |task-submitted|, |job-submitted|, Job submitted + |task-running|, |job-running|, Job running + |task-succeeded|, |job-succeeded|, Job ran successfully + |task-failed|, |job-failed|, Job failed + +.. ifnotslides:: + + .. seealso:: + + Full list of :ref:`task-job-states`. + +.. nextslide:: + +.. ifnotslides:: + + This is the "tree" view: + +.. figure:: ../img/cylc-gui-tree-view.png + :figwidth: 75% + :align: center + + Screenshot of the Cylc GUI in "Tree" view mode. + +.. nextslide:: + +This is the "table" view: + +.. figure:: ../img/cylc-gui-table-view.png + :figwidth: 75% + :align: center + + Screenshot of the Cylc GUI in "Table" view mode. + +.. nextslide:: + +.. ifnotslides:: + + You can navigate between workflows using the list on the left (the + screenshot shows only one, however). + + +.. figure:: ../img/cylc-gui-scan-view.png + :figwidth: 75% + :align: center + + Screenshot of the Cylc GUI "Scan" bar. + + + +Validating A Workflow +--------------------- + +.. ifnotslides:: + + We recommend using ``cylc validate`` to check a workflow definition for + errors before running it. + +.. code-block:: console + + $ cylc validate ~/cylc-src/my_workflow + + +Installing A Workflow +--------------------- + +.. ifnotslides:: + + .. seealso:: + + :ref:`The full guide to Cylc install `. + + To separate the development and running of workflows, use the + :term:`cylc install ` command. + +.. code-block:: bash + + cylc install my_workflow + +.. ifnotslides:: + + This will install ``~/cylc-src/my_workflow`` to ``~/cylc-run/my_workflow/runN``. + + +Running a workflow +------------------ + +.. ifnotslides:: + + Now we have installed the workflow we can run it + using the ``cylc play`` command: + +.. code-block:: console + + $ cylc play my_workflow + +.. ifnotslides:: + + +Generated Workflow Files +------------------------ + +Numbered run directories +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. ifnotslides:: + + .. seealso:: + + :ref:`Installing-workflows` for a fuller description of Cylc install, + including the option of naming rather than numbering runs. + + By default ``cylc install`` will create a new numbered run directory each + time you run it: + +.. code-block:: console + + $ cylc install my_workflow + INSTALLED my_workflow/run1 from ... + $ cylc install my_workflow + INSTALLED my_workflow/run2 from ... + + # The most recent ``runX`` directory is symlinked to ``runN`` + $ ls -l ~/cylc-run/my_workflow/runN + ~/cylc-run/baz/runN -> run2 + +.. nextslide:: + +.. ifnotslides:: + + You can run cylc commands using a specific run number, but if you don't, + ``runN`` will be used: + +.. code-block:: console + + $ cylc play my_workflow + # is the same as + $ cylc play my_workflow/runN + # and the same as (in this case) + $ cylc play my_workflow/run2 + + +Files Generated at Runtime +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. ifnotslides:: + + Cylc generates files and directories when it runs a workflow, namely: + + ``log`` + ``db`` + The database which Cylc uses to record the state of the workflow; + ``job`` + The directory where all :term:`job log files ` live, + primarily the job script itself (``job``) and the job output logs + (``job.out`` and ``job.err``); + ``scheduler`` + The directory where :term:`scheduler log files ` live. + These are written as the workflow runs and are useful when troubleshooting. + ``config/flow.cylc.processed`` + A copy of the :cylc:conf:`flow.cylc` file made after any `Jinja2`_ has been + processed - we will cover this in the + :ref:`tutorial-cylc-consolidating-configuration` section. + ``remote-install`` + Information related to :ref:`RemoteInit` file installation can be found + here. A separate file is created per install target. + + ``share/`` + The :term:`share directory` is where :term:`tasks ` can + read or write files shared with other tasks. + ``work/`` + Contains task :term:`work directories `, i.e. the + *current working directories* of running tasks. These are + removed automatically if empty when a task finishes. + + The job log directory path ends in ``///``, + where the :term:`job submission number` starts at 1 and increments each time a + task re-runs. + + You can use the command line to view scheduler or job logs without + having to find them yourself on the filesystem: + + .. code-block:: bash + + cylc cat-log + cylc cat-log /// + + +.. ifslides:: + + * ``log/`` + * ``db`` + * ``job`` + * ``scheduler`` + * ``config/flow.cylc.processed`` + * ``share/`` + * ``work/`` + + .. nextslide:: + + .. rubric:: In this practical we will add some scripts to, and run, the + :ref:`weather forecasting workflow ` + from the :ref:`scheduling tutorial `. + + Next section: :ref:`tutorial-cylc-runtime-configuration` + +.. ifnotslides:: + + .. note:: + If you used pip to install Cylc, you will need to run + + .. code-block:: bash + + pip install 'cylc-flow[tutorial]' + + to install extra dependencies needed for running the following + tutorial workflows. + +.. practical:: + + .. rubric:: In this practical we will add some scripts to, and run, the + :ref:`weather forecasting workflow ` + from the :ref:`scheduling tutorial `. + + #. **Create A New Workflow.** + + The following command will copy some workflow files into + a new source directory called ``runtime-introduction``: + + .. code-block:: bash + + cylc get-resources tutorial/runtime-introduction + cd ~/cylc-src/runtime-introduction + + This includes the :cylc:conf:`flow.cylc` file from the + :ref:`weather forecasting workflow ` + with some runtime configuration added to it. + + There is also a script called ``get-observations`` located in the bin + directory. + + Take a look at the ``[runtime]`` section in the :cylc:conf:`flow.cylc` file. + + #. **Run The Workflow.** + + First validate the workflow by running: + + .. code-block:: bash + + cylc validate . + + Then install the workflow: + + .. code-block:: bash + + cylc install + + Open a user interface (:ref:`tutorial.tui` or :ref:`tutorial.gui`) to view + your workflow. + + Finally run the workflow by executing: + + .. code-block:: bash + + cylc play runtime-introduction + + The tasks will start to run - you should see them going through the + *waiting*, *running* and *succeeded* states. The *preparing* and + *submitted* states may be too quick to notice. + + When the workflow reaches the final cycle point and all tasks have succeeded + the scheduler will shutdown automatically. + + .. tip:: + + You can run a workflow from the Cylc GUI by pressing the "play" + button at the top. + + #. **Inspect A Job Log.** + + Try opening the ``job.out`` log for one of the + ``get_observations`` tasks in a text editor. The file will be + in the :term:`job log directory`: + + .. code-block:: sub + + cd ~/cylc-run/runtime-introduction/runN + cat log/job//get_observations_heathrow/01/job.out + + You should see something like this: + + .. code-block:: none + + Workflow : runtime-introduction + Job : 20000101T0000Z/get_observations_heathrow/01 (try 1) + User@Host: username@hostname + + Guessing Weather Conditions + Writing Out Wind Data + + 1970-01-01T00:00:00Z NORMAL - started + 2038-01-19T03:14:08Z NORMAL - succeeded + + * The first three lines are identifying information written by Cylc. + * *The lines in the middle are the job stdout.* + * The last two lines are written by Cylc, to record job start and finish + times. The started message would be above the job stdout for a + longer-running job. + + #. **Inspect A Work Directory.** + + The ``get_rainfall`` task should create a file called ``rainfall`` in its + :term:`work directory`. Try opening this file, recalling that the + format of the relevant path from within the work directory will be: + + .. code-block:: sub + + work//get_rainfall/rainfall + + .. hint:: + + The ``get_rainfall`` task only runs every third cycle. + + #. **Extension: Explore The Cylc GUI** + + * Try re-installing the workflow and running it from the GUI. + + * Try adding a new view(s). + + .. tip:: + + You can do this from the "Add View" button (top-right): + + .. image:: ../img/cylc-gui-views-button.png + :align: center + :scale: 75% + + * Try pressing the "Pause" button which is found in the top left-hand + corner of the GUI. + + * Try clicking on a task state icon. From the menu you could try: + + * "Trigger" + * "Hold" + * "Release" + + .. seealso:: + + See guide to :ref:`task-job-states` for a guide to the icons. diff --git a/nightly_8.4/html/_sources/tutorial/runtime/runtime-configuration.rst.txt b/nightly_8.4/html/_sources/tutorial/runtime/runtime-configuration.rst.txt new file mode 100644 index 00000000000..7aeac8d75b7 --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/runtime/runtime-configuration.rst.txt @@ -0,0 +1,524 @@ +.. _tutorial-cylc-runtime-configuration: + +Runtime Configuration +===================== + +In the last section we associated tasks with scripts and ran a simple workflow. In +this section we will look at how to configure these tasks. + + +Environment Variables +--------------------- + +.. ifnotslides:: + + We can define environment variables in task ``[environment]`` sections, + to be provided to task :term:`jobs ` at runtime. + +.. code-block:: cylc + + [runtime] + [[countdown]] + script = seq $START_NUMBER + [[[environment]]] + START_NUMBER = 5 + +.. ifnotslides:: + + Each job is also provided with some standard environment variables e.g: + + ``CYLC_WORKFLOW_RUN_DIR`` + The path to the :term:`run directory` + *(e.g. ~/cylc-run/workflow)*. + ``CYLC_TASK_WORK_DIR`` + The path to the associated task's :term:`work directory` + *(e.g. run-directory/work/cycle/task)*. + ``CYLC_TASK_CYCLE_POINT`` + The :term:`cycle point` for the associated task + *(e.g. 20171009T0950)*. + + .. seealso:: + + There are many more environment variables - see + :ref:`Task Job Script Variables` for more information. + +.. ifslides:: + + * ``CYLC_WORKFLOW_RUN_DIR`` + * ``CYLC_TASK_WORK_DIR`` + * ``CYLC_TASK_CYCLE_POINT`` + + +.. _tutorial-job-runner: + +Job Submission +-------------- + +.. ifnotslides:: + + By default Cylc runs :term:`jobs ` on the same machine as + the scheduler. It can run them on other machines too if we set the + :term:`platform` like this: + +.. code-block:: cylc + + [runtime] + [[hello_computehost]] + script = echo "Hello Compute Host" + platform = powerful_computer + +.. _background processes: https://en.wikipedia.org/wiki/Background_process +.. _job scheduler: https://en.wikipedia.org/wiki/Job_scheduler + +.. nextslide:: + +.. ifnotslides:: + + By default Cylc also executes jobs as `background processes`_. + We often want to submit jobs to a :term:`job runner` instead, + particularly on shared compute resources. Cylc supports the following + job runners: + +* at +* loadleveler +* lsf +* pbs +* sge +* slurm +* moab + +.. nextslide:: + +.. ifnotslides:: + + :term:`Job runners ` typically require + :term:`directives ` in some form, to specify + job requirements such as memory use and number of CPUs to run on. For + example: + +.. code-block:: cylc + + [runtime] + [[big_task]] + script = big-executable + + # Submit to the host "big-computer". + platform = slurm_platform + + # job requires 500MB of RAM & 4 CPUs + [[[directives]]] + --mem = 500 + --ntasks = 4 + + +Time Limits +----------- + +.. ifnotslides:: + + We can specify an execution time limit, as an :term:`ISO8601 duration`, after + which a job will be terminated. Cylc automatically translates this to + the correct :term:`job runner` directives. + +.. code-block:: cylc + + [runtime] + [[some_task]] + script = some-executable + execution time limit = PT15M # 15 minutes. + + +Retries +------- + +Jobs can fail for several reasons: + +.. nextslide:: + +* Something went wrong with job submission, e.g: + + * A network problem; + * The :term:`job host` became unavailable or overloaded; + * The job runner rejected your job directives. + +.. nextslide:: + +* Something went wrong with job execution, e.g: + + * A bug; + * A system error; + * The job hitting the ``execution time limit``. + + +.. nextslide:: + +.. ifnotslides:: + + We can configure Cylc to automatically retry tasks that fail, + by setting ``submission retry delays`` and/or ``execution retry delays`` + to a list of :term:`ISO8601 durations `. + For example, setting ``execution retry delays = PT10M`` + will cause the job to retry every 10 minutes on execution failure. + + Use a multiplier to limit the number of retries: + +.. code-block:: cylc + + [runtime] + [[some-task]] + script = some-script + + # On execution failure + # retry up to 3 times every 15 minutes. + execution retry delays = 3*PT15M + # On submission failure + # retry up to 2 times every 10 min, + # then every 30 mins thereafter. + submission retry delays = 2*PT10M, PT30M + +.. note:: + + Tasks only enter the ``submit-failed`` state if job submission fails with no + retries left. Otherwise they return to the waiting state, to wait on the + next try. + + Tasks only enter the ``failed`` state if job execution fails with no retries + left. Otherwise they return to the waiting state, to wait on the next try. + + + +.. _tutorial.start_stop_restart: + +Start, Stop, Restart +-------------------- + +.. ifnotslides:: + + We have seen how to start and stop Cylc workflows with ``cylc play`` and + ``cylc stop``. By default ``cylc stop`` causes the scheduler to wait + for running jobs to finish before it shuts down. There are several + other stop options, however. For example: + + ``cylc stop --kill`` + Kill all running jobs before stopping. (Cylc can kill jobs on remote + hosts, via the configured :term:`job runner`). + ``cylc stop --now --now`` + stop right now, leaving any jobs running. + + Once a workflow has stopped you can restart it with ``cylc play``. + The scheduler will pick up where it left off, and carry on as normal. + + .. code-block:: bash + + # Run the workflow "name". + cylc play + # Stop the workflow "name", killing any running tasks. + cylc stop --kill + # Restart the workflow "name", picking up where it left off. + cylc play + +.. ifslides:: + + .. code-block:: sub + + cylc play + cylc stop + cylc play + + cylc stop --kill + cylc stop --now --now + + .. nextslide:: + + .. rubric:: In this practical we will add runtime configuration to the + :ref:`weather-forecasting workflow ` + from the :ref:`scheduling tutorial `. + + Next section: :ref:`tutorial-cylc-consolidating-configuration` + + +.. _tutorial-cylc-runtime-forecasting-workflow: + +.. practical:: + + .. TODO - is this Met Office specific? + + .. rubric:: In this practical we will add runtime configuration to the + :ref:`weather-forecasting workflow ` + from the :ref:`scheduling tutorial `. + + #. **Create A New Workflow.** + + Create a new workflow by running the command: + + .. code-block:: bash + + cylc get-resources tutorial/runtime-tutorial + cd ~/cylc-src/runtime-tutorial + + You will now have a copy of the weather-forecasting workflow along with some + executables and python modules. + + #. **Set The Initial And Final Cycle Points.** + + We want the workflow to run for 6 hours, starting at least 7 hours ago, on + the hour. + + We could work out the dates and times manually, or we could let Cylc do + the maths for us. + + Set the :term:`initial cycle point`: + + .. code-block:: cylc + + initial cycle point = previous(T-00) - PT7H + + * ``previous(T-00)`` returns the current time ignoring minutes and + seconds. + + *e.g. if the current time is 12:34 this will return 12:00* + + * ``-PT7H`` subtracts 7 hours from this value. + + Set the :term:`final cycle point`: + + .. code-block:: cylc + + final cycle point = +PT6H + + This sets the :term:`final cycle point` six hours after the + :term:`initial cycle point`. + + Run ``cylc validate`` to check for any errors:: + + cylc validate . + + #. **Add Runtime Configuration For The** ``get_observations`` **Tasks.** + + In the ``bin`` directory is a script called ``get-observations``. This + script gets weather data from the MetOffice `DataPoint`_ service. + It requires two environment variables: + + ``SITE_ID``: + A four digit numerical code which is used to identify a + weather station, e.g. ``3772`` is Heathrow Airport. + ``API_KEY``: + An authentication key required for access to the service. + + .. TODO: Add instructions for offline configuration + + Generate a Datapoint API key:: + + cylc get-resources api-key + + Add the following lines to the bottom of the :cylc:conf:`flow.cylc` file replacing + ``xxx...`` with your API key: + + .. code-block:: cylc + + [runtime] + [[get_observations_heathrow]] + script = get-observations + [[[environment]]] + SITE_ID = 3772 + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + + Add three more ``get_observations`` tasks for each of the remaining + weather stations. + + You will need the codes for the other three weather stations, which are: + + * Camborne - ``3808`` + * Shetland - ``3005`` + * Aldergrove - ``3917`` + + .. spoiler:: Solution warning + + .. code-block:: cylc + + [runtime] + [[get_observations_heathrow]] + script = get-observations + [[[environment]]] + SITE_ID = 3772 + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + [[get_observations_camborne]] + script = get-observations + [[[environment]]] + SITE_ID = 3808 + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + [[get_observations_shetland]] + script = get-observations + [[[environment]]] + SITE_ID = 3005 + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + [[get_observations_aldergrove]] + script = get-observations + [[[environment]]] + SITE_ID = 3917 + API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + Check the :cylc:conf:`flow.cylc` file is valid by running the command: + + .. code-block:: bash + + cylc validate . + + .. TODO: Add advice on what to do if the command fails. + + #. **Test the** ``get_observations`` **tasks.** + + Next we will test the ``get_observations`` tasks. + + Install the workflow: + + .. code-block:: bash + + cylc install + + Open a user interface (:ref:`tutorial.tui` or :ref:`tutorial.gui`) to view + your workflow. Run the workflow either from the UI or command line. + + .. spoiler:: Hint hint + + .. code-block:: bash + + cylc tui runtime-tutorial + # or + cylc gui # If you haven't already got an instance running. + + Run the workflow either by: + + * GUI: selecting the runtime-tutorial workflow in the sidebar and + pressing the play button. + * Tui: pressing enter on the workflow and selecting "play". + * Command line: running ``cylc play runtime-tutorial``. + + If all goes well the workflow will startup and the tasks will run and + succeed. Note that the tasks which do not have a ``[runtime]`` section + will still run though they will not do anything as they do not call any + scripts. + + Once the workflow has reached the final cycle point and all tasks have + succeeded the scheduler will shut down automatically. + + .. TODO: Advise on what to do if all does not go well. + + The ``get-observations`` script produces a file called ``wind.csv`` which + specifies the wind speed and direction. This file is written in the task's + :term:`work directory`. + + Try and open one of the ``wind.csv`` files. Note that the path to the + :term:`work directory` is: + + .. code-block:: sub + + work// + + You should find a file containing four numbers: + + * The longitude of the weather station; + * The latitude of the weather station; + * The wind direction (*the direction the wind is blowing towards*) + in degrees; + * The wind speed in miles per hour. + + .. spoiler:: Hint hint + + If you run ``ls work`` you should see a + list of cycles. Pick one of them and open the file:: + + work//get_observations_heathrow/wind.csv + + #. **Add runtime configuration for the other tasks.** + + The runtime configuration for the remaining tasks has been written out + for you in the ``runtime`` file which you will find in the + :term:`run directory`. Copy the code in the ``runtime`` file to the + bottom of the :cylc:conf:`flow.cylc` file. + + Now that all the tasks have runtime sections, remove + :cylc:conf:`[scheduler]allow implicit tasks`: + + .. code-block:: diff + + [scheduler] + UTC mode = True + - allow implicit tasks = True # TODO: remove at end of exercise + + Removing this ensures that any tasks in the graph without a corresponding + runtime section will cause validation to fail (e.g. due to a typo). + + Check the :cylc:conf:`flow.cylc` file is valid by running the command: + + .. code-block:: bash + + cylc validate . + + Now install a new run of the workflow: + + .. code-block:: bash + + cylc install + + .. TODO: Add advice on what to do if the command fails. + + #. **Run The Workflow.** + + Open a user interface (:ref:`tutorial.tui` or :ref:`tutorial.gui`) and + run the workflow. + + .. tip:: + + Make sure you play the latest run that was newly installed. + + #. **View The Forecast Summary.** + + The ``post_process_exeter`` task will produce a one-line summary of the + weather in Exeter, as forecast two hours ahead of time. This summary can + be found in the ``summary.txt`` file in the :term:`work directory`. + + Try opening the summary file - it will be in the last cycle. The path to + the :term:`work directory` is: + + .. code-block:: sub + + work// + + .. spelling:word-list:: + + exeter + + .. spoiler:: Hint hint + + * ``cycle-point`` - this will be the last cycle of the workflow, + i.e. the final cycle point. + * ``task-name`` - set this to "post_process_exeter". + + #. **View The Rainfall Data.** + + .. TODO: Skip this if you don't have internet connection. + + The ``forecast`` task will produce a html page where the rainfall + data is rendered on a map. This html file is called ``job-map.html`` and + is saved alongside the :term:`job log`. + + Try opening this file in a web browser, e.g via: + + .. code-block:: sub + + firefox & + + The path to the :term:`job log directory` is: + + .. code-block:: sub + + log/job/// + + .. spoiler:: Hint hint + + * ``cycle-point`` - this will be the last cycle of the workflow, + i.e. the final cycle point. + * ``task-name`` - set this to "forecast". + * ``submission-number`` - set this to "01". diff --git a/nightly_8.4/html/_sources/tutorial/runtime/summary.rst.txt b/nightly_8.4/html/_sources/tutorial/runtime/summary.rst.txt new file mode 100644 index 00000000000..98ec62a6298 --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/runtime/summary.rst.txt @@ -0,0 +1,38 @@ +Tutorial Summary +================ + +You've made it to the end of the Cylc tutorial! + +The Cylc tutorial aims to introduce you to the main concepts in Cylc to +prepare you for working with and writing Cylc workflows. +But there is so much more we didn't have time for. + +:ref:`Rose Tutorial ` + `Rose`_ is a tool for creating configurable applications. It's often used + with Cylc to configure more complex tasks, or even the workflow itself. + + Rose configurations can have metadata, support validation and can be edited + using a GUI. + + You might want to try the :ref:`Rose Tutorial` if these things are of interest. +:ref:`Further Topics ` + There some extra tutorials which cover some of the things the main tutorial + doesn't in the :ref:`further topics section `. +`Discourse`_ + If you get stuck, encounter an issue, have a question, or just fancy a chat + about Cylc, feel free to reach out to the Cylc community on our `Discourse`_ + forum. + + We also make announcements (e.g. new Cylc releases) on the forum, so it's a + good to keep an eye on it. +:ref:`User Guide ` + There is a comprehensive :ref:`user guide` which goes into Cylc's + capabilities in detail. +:ref:`Workflow Design Guide ` + This covers recommended code style and best practice. +:ref:`Reference ` + The reference section contains all sorts of technical details. + + It also lists all of the configurations Cylc supports for workflow + definition :cylc:conf:`flow.cylc`, and for site/user setup + :cylc:conf:`global.cylc`. diff --git a/nightly_8.4/html/_sources/tutorial/scheduling/datetime-cycling.rst.txt b/nightly_8.4/html/_sources/tutorial/scheduling/datetime-cycling.rst.txt new file mode 100644 index 00000000000..43ee9adffeb --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/scheduling/datetime-cycling.rst.txt @@ -0,0 +1,632 @@ +.. _nowcasting: https://en.wikipedia.org/wiki/Nowcasting_(meteorology) + +.. _tutorial-datetime-cycling: + +Datetime Cycling +================ + +.. admonition:: Aims + :class: aims + + | You should be able to: + | ✅ Write workflows with datetime cycle points. + + +In the last section we created an :term:`integer cycling` workflow +with numbered :term:`cycle points `. + +.. ifnotslides:: + + Workflows may need to be repeated at a regular time intervals, say every day + or every few hours. To support this Cylc can generate datetime sequences + as :term:`cycle points ` instead of integers. + + .. admonition:: Reminder + :class: tip + + In Cylc, :term:`cycle points ` are task labels that anchor the + dependencies between individual tasks: this task depends on that task in + that cycle. Tasks can run as soon as their individual dependencies are met, + so cycles do not necessarily run in order, or at the real world time + corresponding to the cycle point value (to do that, see + :ref:`tutorial-clock-triggers`). + + +.. _tutorial-iso8601: + +ISO8601 +------- + +Cylc uses the :term:`ISO8601` datetime standard to represent datetimes and durations. + +.. _tutorial-iso8601-datetimes: + +ISO8601 Datetimes +^^^^^^^^^^^^^^^^^ + +.. ifnotslides:: + + ISO8601 datetimes are written from the largest unit to the smallest + (year, month, day, hour, minute, second) with a ``T`` separating the date + and time components. For example, midnight on the 1st of January 2000 is + written ``20000101T000000``. + + For brevity we can omit seconds (or minutes) from the time: + ``20000101T0000`` (or ``20000101T00``). + + .. note:: + + The smallest interval for a datetime cycling sequence in Cylc is 1 minute. + + For readability we can add hyphens (``-``) between the date components + and colons (``:``) between the time components. + This is optional, but if you do it you must use both hyphens *and* colons. + + Time-zone information can be added onto the end. UTC is written ``Z``, + UTC+1 is written ``+01``, etc. E.G: ``2000-01-01T00:00Z``. + +.. Diagram of an iso8601 datetime's components. + +.. image:: ../img/iso8601-dates.svg + :width: 75% + :align: center + +.. _tutorial-iso8601-durations: + +ISO8601 Durations +^^^^^^^^^^^^^^^^^ + +.. ifnotslides:: + + ISO8601 durations are prefixed with a ``P`` (for "period") and + special characters following each unit: + +* ``Y`` for year. +* ``M`` for month. +* ``D`` for day. +* ``W`` for week. +* ``H`` for hour. +* ``M`` for minute. +* ``S`` for second. + +.. nextslide:: + +.. ifnotslides:: + + As for datetimes, duration components are written in order from largest to + smallest, and the date and time components are separated by a ``T``: + +* ``P1D``: one day. +* ``PT1H``: one hour. +* ``P1DT1H``: one day and one hour. +* ``PT1H30M``: one and a half hours. +* ``P1Y1M1DT1H1M1S``: a year and a month and a day and an hour and a + minute and a second. + + +Datetime Recurrences +-------------------- + +In :term:`integer cycling`, workflows, recurrences are written ``P1``, ``P2``, +etc. + +In :term:`datetime cycling ` workflows, there are two ways to +write recurrences: + +1. Using ISO8601 durations (e.g. ``P1D``, ``PT1H``). +2. Using ISO8601 datetimes with inferred recurrence. + +.. _tutorial-inferred-recurrence: + +Inferred Recurrence +^^^^^^^^^^^^^^^^^^^ + +.. ifnotslides:: + + Recurrence can be inferred from a datetime by omitting components from the + front. For example, if the year is omitted then the recurrence can be + inferred to be annual. E.g.: + +.. csv-table:: + :header: Recurrence, Description + :align: left + :widths: 30, 70 + + ``2000-01-01T00``, Midnight on the 1st of January 2000 + ``01-01T00``, Every year on the 1st of January + ``01T00``, Every month on the first of the month + ``T00``, Every day at midnight + ``T-00``, Every hour at zero minutes past (i.e. every hour on the hour) + +.. note:: + + To omit hours from a date time, place a ``-`` after the ``T`` character. + + +Recurrence Formats +^^^^^^^^^^^^^^^^^^ + +.. ifnotslides:: + + As with integer cycling, recurrences start at the :term:`initial cycle + point` by default. We can override this in two ways: + +.. rubric:: + By giving an arbitrary start cycle point (``datetime/recurrence``): + +``2000/P4Y`` + Every fourth year, starting with the year 2000. +``2000-01-01T00/P1D`` + Every day at midnight, starting on the 1st of January 2000. + +.. nextslide:: + +.. _tutorial-cylc-datetime-offset-icp: + +.. rubric:: + By offset, relative to the initial cycle point (``offset/recurrence``). + +The offset must be an ISO8601 duration preceded by a plus character: + +``+PT1H/PT1H`` + Every hour starting one hour after the initial cycle point. +``+P1Y/P1Y`` + Every year starting one year after the initial cycle point. + +Durations and the Initial Cycle Point +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When using durations, beware that a change in the initial cycle point +might produce different results for the recurrences. + +.. nextslide:: + +.. list-table:: + :class: grid-table + :width: 50% + + * - .. code-block:: cylc + :emphasize-lines: 3 + + [scheduling] + initial cycle point = \ + 2000-01-01T00 + [[graph]] + P1D = foo[-P1D] => foo + + - .. code-block:: cylc + :emphasize-lines: 3 + + [scheduling] + initial cycle point = \ + 2000-01-01T12 + [[graph]] + P1D = foo[-P1D] => foo + + * - .. digraph:: Example + :align: center + + size = "3,3" + + "1/foo" [label="foo\n2000-01-01T00"] + "2/foo" [label="foo\n2000-01-02T00"] + "3/foo" [label="foo\n2000-01-03T00"] + + "1/foo" -> "2/foo" -> "3/foo" + + - .. digraph:: Example + :align: center + + size = "3,3" + + "1/foo" [label="foo\n2000-01-01T12"] + "2/foo" [label="foo\n2000-01-02T12"] + "3/foo" [label="foo\n2000-01-03T12"] + + "1/foo" -> "2/foo" -> "3/foo" + +.. nextslide:: + +We could write the recurrence "every midnight" independent of the initial +cycle point by: + +* Using an `inferred recurrence`_ instead (i.e. ``T00``). +* Overriding the recurrence start point (i.e. ``T00/P1D``) +* Using ``[scheduling]initial cycle point constraints`` to + constrain the initial cycle point (e.g. to a particular time of day). See + the `Cylc User Guide`_ for details. + +The Initial and Final Cycle Points +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. ifnotslides:: + + There are two special recurrences for the initial and final cycle points: + +* ``R1``: run once at the initial cycle point. +* ``R1/P0Y``: run once at the final cycle point. + +.. TODO - change terminology as done in the cylc user guide, "repeat" can be + confusing. Use occur? + +Intercycle Dependencies +^^^^^^^^^^^^^^^^^^^^^^^ + +.. ifnotslides:: + + Intercycle dependencies are written as ISO8601 durations, e.g: + +* ``foo[-P1D]``: the task ``foo`` from the cycle one day before. +* ``bar[-PT1H30M]``: the task ``bar`` from the cycle 1 hour 30 minutes before. + +.. ifnotslides:: + + The initial cycle point can be referenced using a caret character ``^``, e.g: + +* ``baz[^]``: the task ``baz`` from the initial cycle point. + + +.. _tutorial-cylc-datetime-utc: + +Cycle Point Time Zone +--------------------- + +Cylc can generate datetime cycle points in any time zone, but "daylight saving" +boundaries can cause confusion, so the default is UTC, i.e. the ``+00`` time +zone. You can override this by setting :cylc:conf:`[scheduler]cycle point time zone`. + +.. note:: + + UTC is sometimes also labelled ``Z`` ("Zulu" from the NATO phonetic alphabet) + according to the + `military time zone convention `_. + +.. _tutorial-datetime-cycling-practical: + +Putting It All Together +----------------------- + +.. ifslides:: + + We will now develop a simple weather forecasting workflow. + +.. ifnotslides:: + + Cylc was originally developed for running operational weather forecasting. In + this section we will outline how to implement a basic weather-forecasting workflow. + + .. note:: + + Technically this example is a `nowcasting`_ workflow, + but the distinction doesn't matter here. + + A basic weather forecasting workflow has three main steps: + +1. Gathering Observations +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. ifnotslides:: + + We gather observations from different weather stations to build a picture of + the current weather. Our dummy weather forecast will get wind observations + from four weather stations: + + * Aldergrove (Near Belfast in NW of the UK) + * Camborne (In Cornwall, the far SW of England) + * Heathrow (Near London in the SE) + * Shetland (The northernmost part of the UK) + + The tasks that retrieve observation data will be called + ``get_observations_`` where ``site`` is the name of the weather + station. + + Next we need to consolidate the observations so that our forecasting + system can work with them. To do this we have a + ``consolidate_observations`` task. + + We will fetch wind observations **every three hours, starting from the + initial cycle point**. + + The ``consolidate_observations`` task must run after the + ``get_observations`` tasks. + +.. digraph:: example + :align: center + + size = "7,4" + + get_observations_aldergrove -> consolidate_observations + get_observations_camborne -> consolidate_observations + get_observations_heathrow -> consolidate_observations + get_observations_shetland -> consolidate_observations + + hidden [style="invis"] + get_observations_aldergrove -> hidden [style="invis"] + get_observations_camborne -> hidden [style="invis"] + hidden -> consolidate_observations [style="invis"] + +.. ifnotslides:: + + We will also use the UK radar network to get rainfall data with a task + called ``get_rainfall``. + + We will fetch rainfall data *every six hours, from six hours after the + initial cycle point*. + +2. Running Computer Models to Generate Forecast Data +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. ifnotslides:: + + We will do this with a task called ``forecast`` that runs + *every six hours, from six hours after the initial cycle point*. + The ``forecast`` task will depend on: + + * The ``consolidate_observations`` task from the previous two cycles and + the present cycle. + * The ``get_rainfall`` task from the present cycle. + +.. digraph:: example + :align: center + + size = "7,4" + + subgraph cluster_T00 { + label="+PT0H" + style="dashed" + "observations.t00" [label="consolidate observations\n+PT0H"] + } + + subgraph cluster_T03 { + label="+PT3H" + style="dashed" + "observations.t03" [label="consolidate observations\n+PT3H"] + } + + subgraph cluster_T06 { + label="+PT6H" + style="dashed" + "forecast.t06" [label="forecast\n+PT6H"] + "get_rainfall.t06" [label="get_rainfall\n+PT6H"] + "observations.t06" [label="consolidate observations\n+PT6H"] + } + + "observations.t00" -> "forecast.t06" + "observations.t03" -> "forecast.t06" + "observations.t06" -> "forecast.t06" + "get_rainfall.t06" -> "forecast.t06" + +3. Processing the data output to produce user-friendly forecasts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. ifnotslides:: + + This will be done with a task called ``post_process_`` where + ``location`` is the place we want to generate the forecast for. For + the moment we will use Exeter. + + The ``post_process_exeter`` task will run *every six hours starting six + hours after the initial cycle point* and will be dependent on the + ``forecast`` task. + +.. digraph:: example + :align: center + + size = "2.5,2" + + "forecast" -> "post_process_exeter" + +.. nextslide:: + +.. ifslides:: + + .. rubric:: Next Steps + + 1. Read through the "Putting It All Together" section. + 2. Complete the practical. + + Next section: :ref:`tutorial-cylc-further-scheduling` + + +.. _datetime cycling practical: + +.. practical:: + + .. rubric:: In this practical we will create a dummy forecasting workflow + using datetime cycling. + + #. **Create A New Workflow.** + + Create a new source directory ``datetime-cycling`` under ``~/cylc-src``, + and move into it: + + .. code-block:: bash + + mkdir ~/cylc-src/datetime-cycling + cd ~/cylc-src/datetime-cycling + + Create a :cylc:conf:`flow.cylc` file and paste the following code into it: + + .. code-block:: cylc + + [scheduler] + UTC mode = True + allow implicit tasks = True + [scheduling] + initial cycle point = 20000101T00Z + [[graph]] + + #. **Add The Recurrences.** + + The weather-forecasting workflow will require two + recurrences. Add these under the ``graph`` section + based on the information given above. + + .. hint:: + + See :ref:`Datetime Recurrences`. + + .. spoiler:: Solution warning + + The two recurrences you need are + + * ``PT3H``: repeat every three hours starting from the initial cycle + point. + * ``+PT6H/PT6H``: repeat every six hours starting six hours after the + initial cycle point. + + .. code-block:: diff + + [scheduler] + UTC mode = True + allow implicit tasks = True + [scheduling] + initial cycle point = 20000101T00Z + [[graph]] + + PT3H = + + +PT6H/PT6H = + + #. **Write The Graph.** + + With the help of the the information above add the tasks and dependencies to + to implement the weather-forecasting workflow. + + You will need to consider the intercycle dependencies between tasks as well. + + Use ``cylc graph`` to inspect your work. + + .. spoiler:: Hint hint + + The dependencies you will need to formulate are as follows: + + * The ``consolidate_observations`` task depends on ``get_observations_``. + * The ``forecast`` task depends on: + + * the ``get_rainfall`` task; + * the ``consolidate_observations`` tasks from: + + * the same cycle; + * the cycle 3 hours before (``-PT3H``); + * the cycle 6 hours before (``-PT6H``). + + * The ``post_process_exeter`` task depends on the ``forecast`` + task. + + To visualise your workflow run the command: + + .. code-block:: sub + + cylc graph + + .. spoiler:: Solution warning + + .. code-block:: cylc + + [scheduler] + UTC mode = True + allow implicit tasks = True + [scheduling] + initial cycle point = 20000101T00Z + [[graph]] + PT3H = """ + get_observations_aldergrove => consolidate_observations + get_observations_camborne => consolidate_observations + get_observations_heathrow => consolidate_observations + get_observations_shetland => consolidate_observations + """ + +PT6H/PT6H = """ + consolidate_observations => forecast + consolidate_observations[-PT3H] => forecast + consolidate_observations[-PT6H] => forecast + get_rainfall => forecast => post_process_exeter + """ + + #. **Intercycle Offsets.** + + To ensure the ``forecast`` tasks run in the right order (one cycle + after another) they each need to depend on their own previous run: + + .. digraph:: example + :align: center + + size = "4,1.5" + rankdir=LR + + subgraph cluster_T06 { + label="T06" + style="dashed" + "forecast.t06" [label="forecast\nT06"] + } + + subgraph cluster_T12 { + label="T12" + style="dashed" + "forecast.t12" [label="forecast\nT12"] + } + + subgraph cluster_T18 { + label="T18" + style="dashed" + "forecast.t18" [label="forecast\nT18"] + } + + "forecast.t06" -> "forecast.t12" -> "forecast.t18" + + We can express this dependency as ``forecast[-PT6H] => forecast``. + + .. TODO - re-enable this: https://github.com/cylc/cylc-flow/issues/4638 + + Try adding this line to your workflow then visualising it with ``cylc + graph``. + + .. hint:: + + Try adjusting the number of cycles displayed by ``cylc graph``: + + .. code-block:: console + + $ cylc graph . 2000 20000101T12Z & + + You will notice that there is a dependency which looks like this: + + + .. digraph:: example + :align: center + + size = "4,1" + rankdir=LR + + "forecast.t00" [label="forecast\n20000101T0000Z" + color="#888888" + fontcolor="#888888"] + "forecast.t06" [label="forecast\n20000101T0600Z"] + + + "forecast.t00" -> "forecast.t06" + + Note in particular that the ``forecast`` task in the 00:00 cycle is + grey. The reason for this is that this task does not exist. Remember + the forecast task runs every six hours + **starting 6 hours after the initial cycle point**, so the + dependency is only valid from 12:00 onwards. To fix the problem we + must add a new dependency section which repeats every six hours + **starting 12 hours after the initial cycle point**. + + Make the following changes to your workflow and the grey task should + disappear: + + However, the forecast task runs every six hours + *starting 6 hours after the initial cycle point*, so the + dependency is only valid from 12:00 onwards. To fix the problem we + must add a new dependency section which repeats every six hours + *starting 12 hours after the initial cycle point*: + + .. code-block:: diff + + +PT6H/PT6H = """ + ... + - forecast[-PT6H] => forecast + """ + + +PT12H/PT6H = """ + + forecast[-PT6H] => forecast + + """ diff --git a/nightly_8.4/html/_sources/tutorial/scheduling/further-scheduling.rst.txt b/nightly_8.4/html/_sources/tutorial/scheduling/further-scheduling.rst.txt new file mode 100644 index 00000000000..b2f9f87b962 --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/scheduling/further-scheduling.rst.txt @@ -0,0 +1,115 @@ +.. _tutorial-cylc-further-scheduling: + +Further Scheduling +================== + +.. admonition:: Aims + :class: aims + + | You should be aware of some more advanced scheduling features: + | ✅ Task state qualifiers. + | ✅ Clock triggers. + | ✅ Alternative calendars. + + +.. _tutorial-qualifiers: + +Qualifiers +---------- + +.. ifnotslides:: + + So far we have written dependencies like ``foo => bar``. This is, in fact, + shorthand for ``foo:succeed => bar``. It means that the task ``bar`` will run + once ``foo`` has finished successfully. If ``foo`` were to fail then ``bar`` + would not run. We will talk more about these :term:`task states ` + in the :ref:`Runtime Section `. + + We refer to the ``:succeed`` descriptor as a :term:`qualifier`. + There are qualifiers for different :term:`task states ` e.g: + +.. ifslides:: + + .. code-block:: cylc-graph + + foo => bar + foo:succeed => bar + foo:fail => bar + +``:start`` + When the task has started running. +``:fail`` + When the task finishes if it fails (produces non-zero return code). +``:finish`` + When the task has completed (either succeeded or failed). + +.. nextslide:: + +It is also possible to create your own :term:`qualifiers ` +to handle events within your code (custom outputs). + +.. ifnotslides:: + + *For more information see the* `Cylc User Guide`_. + + +.. _tutorial-clock-triggers: + +Clock Triggers +-------------- + +.. ifnotslides:: + + In Cylc, :term:`cycle points ` are just task labels. Tasks are + triggered when their dependencies are met, regardless of cycle point. + But *clock triggers* can be used to force tasks to wait for a particular + real time, relative to their cycle point, before running. + This is necessary for certain operational and monitoring systems, e.g. for + tasks that process real-time data. + + For example in the following workflow the cycle ``2000-01-01T12Z`` will wait + until 11:00 on the 1st of January 2000 before running: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2000-01-01T00Z + [[xtriggers]] + PT1H_trigger = wall_clock(offset=-PT1H) + [[graph]] + # "daily" will run, at the earliest, one hour before midday. + T12 = @PT1H_trigger => daily + +.. tip:: + + See the :ref:`tutorial-cylc-clock-trigger` tutorial for more information. + + +Alternative Calendars +--------------------- + +.. ifnotslides:: + + By default Cylc uses the Gregorian calendar for :term:`datetime cycling`, + but it also supports: + + - Integer cycling. + - 360-day calendar (12 months of 30 days each in a year). + - 365-day calendar (never a leap year). + - 366-day calendar (always a leap year). + +.. code-block:: cylc + + [scheduling] + cycling mode = 360day + +.. ifnotslides:: + + .. seealso:: :cylc:conf:`[scheduling]cycling mode` + +.. nextslide:: + +.. ifslides:: + + Next section: :ref:`Runtime Introduction + ` diff --git a/nightly_8.4/html/_sources/tutorial/scheduling/graphing.rst.txt b/nightly_8.4/html/_sources/tutorial/scheduling/graphing.rst.txt new file mode 100644 index 00000000000..ec2df1cadf0 --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/scheduling/graphing.rst.txt @@ -0,0 +1,431 @@ +.. _Cylc file format: + +The :cylc:conf:`flow.cylc` File Format +====================================== + +.. admonition:: Aims + :class: aims + + | You will be able to: + | ✅ Recognise the ``flow.cylc`` file format. + | ✅ Write simple chains of dependencies. + + +.. ifnotslides:: + + A :term:`Cylc workflow` is defined by a :cylc:conf:`flow.cylc` configuration + file, which uses a nested `INI`_ format: + +.. ifslides:: + + * A Cylc workflow is defined by a :cylc:conf:`flow.cylc` file + * It is written in a nested `INI`_-based format + +.. ifnotslides:: + + * Comments start with a ``#`` character. + * Settings are written as ``key = value`` pairs. + * Settings can be contained within sections. + * Sections are written inside square brackets i.e. ``[section-name]``. + * Sections can be nested, by adding an extra square bracket with each level, + so a sub-section would be written ``[[sub-section]]``, a sub-sub-section + ``[[[sub-sub-section]]]``, and so on. + + .. note:: + + Prior to Cylc 8, :cylc:conf:`flow.cylc` was named ``suite.rc``, + but that name is now deprecated. + + See :ref:`cylc_7_compat_mode` for information on compatibility with + existing Cylc 7 ``suite.rc`` files. + +Example +^^^^^^^ + +.. code-block:: cylc + + # Comment + [section] + key = value + [[sub-section]] + another-key = another-value # Inline comment + yet-another-key = """ + A + Multi-line + String + """ + +Shorthand +^^^^^^^^^ + +.. include:: ../../reference/config/shorthand.rst + +Duplicate Items +^^^^^^^^^^^^^^^ + +Duplicate sections get merged: + +.. list-table:: + :class: grid-table + + * - + .. code-block:: cylc + :caption: input + + [a] + c = C + [b] + d = D + [a] # duplicate + e = E + + - + .. code-block:: cylc + :caption: result + + [a] + c = C + e = E + [b] + d = D + +.. nextslide:: + +Duplicate settings get overwritten: + +.. list-table:: + :class: grid-table + + * - + .. code-block:: cylc + :caption: input + + a = foo + a = bar # duplicate + + - + .. code-block:: cylc + :caption: result + + a = bar + +Except for duplicate graph string items, which get merged: + +.. list-table:: + :class: grid-table + + * - + .. code-block:: cylc + :caption: input + + R1 = "foo => bar" + R1 = "foo => baz" + + - + .. code-block:: cylc + :caption: result + + R1 = "foo => bar & baz" + + +Indentation +^^^^^^^^^^^ + +It is a good idea to indent :cylc:conf:`flow.cylc` files for readability. + +However, Cylc ignores indentation, so the following examples are equivalent: + +.. list-table:: + :class: grid-table + + * - + .. code-block:: cylc + :caption: input + + [section] + a = A + [[sub-section]] + b = B + b = C + # this setting is still + # in [[sub-section]] + + + - + .. code-block:: cylc + :caption: result + + [section] + a = A + [[sub-section]] + b = C + + +.. _tutorial-cylc-graphing: + + +The Dependency Graph +^^^^^^^^^^^^^^^^^^^^ + +Graph Strings +------------- + +Cylc workflows are defined in terms of :term:`tasks ` and +:term:`dependencies `. + +.. ifnotslides:: + + Task have names, and dependencies are represented by arrows + (``=>``) between them. For example, here's a task ``make_dough`` that should + run after another task ``buy_ingredients`` has succeeded: + +.. minicylc:: + :align: center + :snippet: + :theme: demo + + buy_ingredients => make_dough + +.. nextslide:: + +.. ifnotslides:: + + These :term:`dependencies ` can be chained together in + :term:`graph strings`: + +.. minicylc:: + :align: center + :snippet: + :theme: demo + + buy_ingredients => make_dough => bake_bread => sell_bread + +.. nextslide:: + +.. ifnotslides:: + + Graph strings can be combined to form more complex graphs: + +.. minicylc:: + :align: center + :snippet: + :theme: demo + + buy_ingredients => make_dough => bake_bread => sell_bread + pre_heat_oven => bake_bread + bake_bread => clean_oven + +.. nextslide:: + +.. ifnotslides:: + + Graphs can also contain logical operators ``&`` (*and*) and ``|`` (*or*). + For example, the following lines are equivalent to those just above: + +.. code-block:: cylc-graph + + buy_ingredients => make_dough + pre_heat_oven & make_dough => bake_bread => sell_bread & clean_oven + + +.. nextslide:: + +Collectively, all the graph strings make up the workflow dependency :term:`graph`. + +.. admonition:: Note + :class: tip + + .. ifnotslides:: + + The order of lines in the graph doesn't matter, so + the following examples are equivalent: + + .. list-table:: + :class: grid-table + + * - + .. code-block:: cylc-graph + + foo => bar + bar => baz + + - + .. code-block:: cylc-graph + + bar => baz + foo => bar + + +Cylc Graphs +----------- + +.. ifnotslides:: + + A *non-cycling* :term:`graph` can be defined with ``[scheduling][graph]R1``, + where ``R1`` means *run once*: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + buy_ingredients => make_dough + pre_heat_oven & make_dough => bake_bread + bake_bread => sell_bread & clean_oven + """ + +.. nextslide:: + +.. ifnotslides:: + + This is a minimal :term:`Cylc workflow` that defines a :term:`graph` of + tasks to run, but does not yet say what scripts or applications to run + for each task. We will cover that later in the :ref:`runtime tutorial + `. + + Cylc provides a command line utility + for visualising :term:`graphs `, ``cylc graph ``, where + ``path`` is the location of the :cylc:conf:`flow.cylc` file. + It generates diagrams similar to the ones you have seen so far. The number + ``1`` below each task is the :term:`cycle point`. We will explain what this + means in the next section. + +.. image:: ../img/cylc-graph.png + :align: center + +.. nextslide:: + +.. hint:: + + .. ifnotslides:: + + A graph can be drawn in multiple ways, for instance the following two + examples are equivalent: + + .. ifslides:: + + A graph can be drawn in multiple ways: + + .. image:: ../img/cylc-graph-reversible.svg + :align: center + + .. ifnotslides:: + + Graphs drawn by ``cylc graph`` may vary slightly from one run to + another, but the tasks and dependencies will always be the same. + +.. nextslide:: + +.. ifslides:: + + .. rubric:: In this practical we will create a new Cylc workflow and write a + graph of tasks for it to run. + + Next session: :ref:`tutorial-integer-cycling` + +.. practical:: + + .. rubric:: In this practical we will create a new Cylc workflow and write a + graph of tasks for it to run. + + #. **Create a Cylc workflow.** + + A :term:`Cylc workflow` is defined by a :cylc:conf:`flow.cylc` file. + + If you don't have one already, create a ``cylc-src`` directory in your + user space: + + .. code-block:: + + mkdir ~/cylc-src + + Now create a new workflow :term:`source directory` called + ``graph-introduction`` under ``cylc-src`` and move into it: + + .. code-block:: bash + + mkdir ~/cylc-src/graph-introduction + cd ~/cylc-src/graph-introduction + + In your new source directory create a :cylc:conf:`flow.cylc` + file and paste the following text into it: + + .. code-block:: cylc + + [scheduler] + allow implicit tasks = True + [scheduling] + [[graph]] + R1 = """ + # Write graph strings here! + """ + + #. **Write a graph.** + + We now have a blank Cylc workflow. Next we need to define a graph. + + Edit your :cylc:conf:`flow.cylc` file to add graph strings representing the + following graph: + + .. digraph:: graph_tutorial + :align: center + + a -> b -> d -> e + c -> b -> f + + #. **Visualise the workflow.** + + Once you have written some graph strings try using ``cylc graph`` to + display the workflow. Run the following command: + + .. code-block:: bash + + cylc graph . + + .. admonition:: Note + :class: hint + + ``cylc graph`` takes the path to the workflow as an argument. Inside + the :term:`source directory` we can just run ``cylc graph .``. + + If the results don't match the diagram above try to correct the graph + in your :cylc:conf:`flow.cylc` file. + + + .. spoiler:: Solution warning + + There are multiple correct ways to write this graph. So long as what + you see from ``cylc graph`` matches the above diagram then you have a + correct solution. + + + Two valid examples: + + .. list-table:: + :class: grid-table + + * - + .. code-block:: cylc-graph + + a & c => b => d & f + d => e + + - + .. code-block:: cylc-graph + + a => b => d => e + c => b => f + + + The whole workflow should look something like this: + + .. code-block:: cylc + + [scheduler] + allow implicit tasks = True + [scheduling] + [[graph]] + R1 = """ + a & c => b => d & f + d => e + """ diff --git a/nightly_8.4/html/_sources/tutorial/scheduling/index.rst.txt b/nightly_8.4/html/_sources/tutorial/scheduling/index.rst.txt new file mode 100644 index 00000000000..0d3a917a8f3 --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/scheduling/index.rst.txt @@ -0,0 +1,15 @@ +.. _tutorial-scheduling: + +Scheduling +========== + +This section shows how to create basic Cylc workflows. + +.. toctree:: + :name: rug-scheduling-toc + :maxdepth: 2 + + graphing + integer-cycling + datetime-cycling + further-scheduling diff --git a/nightly_8.4/html/_sources/tutorial/scheduling/integer-cycling.rst.txt b/nightly_8.4/html/_sources/tutorial/scheduling/integer-cycling.rst.txt new file mode 100644 index 00000000000..26d0af6c1df --- /dev/null +++ b/nightly_8.4/html/_sources/tutorial/scheduling/integer-cycling.rst.txt @@ -0,0 +1,609 @@ +.. _tutorial-integer-cycling: + +Basic Cycling +============= + +.. admonition:: Aims + :class: aims + + | You will be able to: + | ✅ Write simple :term:`cycling` (repeating) workflows. + + +Repeating Workflows +------------------- + +.. ifnotslides:: + + You may want to repeat the same workflow multiple times. In Cylc this + is called :term:`cycling`, and each repetition is called a :term:`cycle`. + + Each :term:`cycle` is given a unique label, called a + :term:`cycle point`. For now these will be integers, but *they can also be + datetimes* as we will see in the next section. + +To make a workflow repeat we must tell Cylc three things: + +.. ifslides:: + + * :term:`recurrence` + * :term:`initial cycle point` + * :term:`final cycle point` (Optional) + +.. ifnotslides:: + + The :term:`recurrence`. + How often to repeat the workflow (or part of it). + The :term:`initial cycle point`. + The cycle point to start from. + The :term:`final cycle point` (optional). + We can also tell Cylc where to stop the workflow. + +.. nextslide:: + +.. ifnotslides:: + + Let's take the bakery example from the previous section. Bread is + baked in batches so the bakery will repeat this workflow for each + batch. We can make the workflow repeat by adding three lines: + +.. code-block:: diff + + [scheduler] + allow implicit tasks = True + [scheduling] + + cycling mode = integer + + initial cycle point = 1 + [[graph]] + - R1 = """ + + P1 = """ + buy_ingredients => make_dough + pre_heat_oven & make_dough => bake_bread + bake_bread => sell_bread & clean_oven + """ + +.. nextslide:: + +.. ifnotslides:: + + * ``cycling mode = integer`` tells Cylc to give our :term:`cycle points + ` integer labels. + * ``initial cycle point = 1`` tells Cylc to start counting cycle points + from 1. + * ``P1`` is the :term:`recurrence`; a ``P1`` :term:`graph string` + repeats at every integer :term:`cycle point`. + + The first three :term:`cycles` look like this, with the entire + workflow repeated at each cycle point: + +.. digraph:: example + :align: center + + size = "7,15" + + subgraph cluster_1 { + label = 1 + style = dashed + "1/pur" [label="buy_ingredients\n1"] + "1/mak" [label="make_dough\n1"] + "1/bak" [label="bake_bread\n1"] + "1/sel" [label="sell_bread\n1"] + "1/cle" [label="clean_oven\n1"] + "1/pre" [label="pre_heat_oven\n1"] + } + + subgraph cluster_2 { + label = 2 + style = dashed + "2/pur" [label="buy_ingredients\n2"] + "2/mak" [label="make_dough\n2"] + "2/bak" [label="bake_bread\n2"] + "2/sel" [label="sell_bread\n2"] + "2/cle" [label="clean_oven\n2"] + "2/pre" [label="pre_heat_oven\n2"] + } + + subgraph cluster_3 { + label = 3 + style = dashed + "3/pur" [label="buy_ingredients\n3"] + "3/mak" [label="make_dough\n3"] + "3/bak" [label="bake_bread\n3"] + "3/sel" [label="sell_bread\n3"] + "3/cle" [label="clean_oven\n3"] + "3/pre" [label="pre_heat_oven\n3"] + } + + "1/pur" -> "1/mak" -> "1/bak" -> "1/sel" + "1/pre" -> "1/bak" -> "1/cle" + "2/pur" -> "2/mak" -> "2/bak" -> "2/sel" + "2/pre" -> "2/bak" -> "2/cle" + "3/pur" -> "3/mak" -> "3/bak" -> "3/sel" + "3/pre" -> "3/bak" -> "3/cle" + +.. ifnotslides:: + + The number under each task shows which :term:`cycle point` it belongs to. + + +Intercycle Dependencies +----------------------- + +.. ifnotslides:: + + We've just seen how to write a workflow that repeats every :term:`cycle`. + + Cylc runs tasks as soon as their dependencies are met, regardless of cycle + point, so cycles will not necessarily run in order. This can be efficient, + but it could also cause problems. For instance we could find ourselves + pre-heating the oven in one cycle while still cleaning it in another. + + To resolve this we can add :term:`dependencies` *between* + cycles, to the graph. To ensure that ``clean_oven`` completes before + ``pre_heat_oven`` starts in the next cycle, we can write this: + + .. code-block:: cylc-graph + + clean_oven[-P1] => pre_heat_oven + + In a ``P1`` recurrence, the suffix ``[-P1]`` means *the previous cycle point*, + Similarly, ``[-P2]`` refers back two cycles. The new dependency can be added + to the workflow graph like this: + +.. code-block:: diff + + [scheduling] + cycling mode = integer + initial cycle point = 1 + [[graph]] + P1 = """ + buy_ingredients => make_dough + pre_heat_oven & make_dough => bake_bread + bake_bread => sell_bread & clean_oven + + clean_oven[-P1] => pre_heat_oven + """ + +.. nextslide:: + +.. ifnotslides:: + + And the resulting workflow looks like this: + +.. digraph:: example + :align: center + + size = "7,15" + + subgraph cluster_1 { + label = 1 + style = dashed + "1/pur" [label="buy_ingredients\n1"] + "1/mak" [label="make_dough\n1"] + "1/bak" [label="bake_bread\n1"] + "1/sel" [label="sell_bread\n1"] + "1/cle" [label="clean_oven\n1"] + "1/pre" [label="pre_heat_oven\n1"] + } + + subgraph cluster_2 { + label = 2 + style = dashed + "2/pur" [label="buy_ingredients\n2"] + "2/mak" [label="make_dough\n2"] + "2/bak" [label="bake_bread\n2"] + "2/sel" [label="sell_bread\n2"] + "2/cle" [label="clean_oven\n2"] + "2/pre" [label="pre_heat_oven\n2"] + } + + subgraph cluster_3 { + label = 3 + style = dashed + "3/pur" [label="buy_ingredients\n3"] + "3/mak" [label="make_dough\n3"] + "3/bak" [label="bake_bread\n3"] + "3/sel" [label="sell_bread\n3"] + "3/cle" [label="clean_oven\n3"] + "3/pre" [label="pre_heat_oven\n3"] + } + + "1/pur" -> "1/mak" -> "1/bak" -> "1/sel" + "1/pre" -> "1/bak" -> "1/cle" + "1/cle" -> "2/pre" + "2/pur" -> "2/mak" -> "2/bak" -> "2/sel" + "2/pre" -> "2/bak" -> "2/cle" + "2/cle" -> "3/pre" + "3/pur" -> "3/mak" -> "3/bak" -> "3/sel" + "3/pre" -> "3/bak" -> "3/cle" + +.. nextslide:: + +.. ifnotslides:: + + The :term:`intercycle dependency` forces the connected tasks, in + different cycle points, to run in order. + + Note that the ``buy_ingredients`` task has no arrows pointing at it. + This means it has no *parent tasks* to wait on, upstream in the graph. + Consequently all ``buy_ingredients`` tasks (out to a configurable + :term:`runahead limit`) want to run straight away. + This could cause our bakery to run into cash-flow problems by purchasing + ingredients too far in advance of using them. + + To solve this problem without running out of ingredients, the bakery wants + to purchase ingredients two batches ahead. This can be achieved by adding + the following dependency: + +.. ifslides:: + + We need ``buy_ingredients`` to be dependent on ``sell_bread`` from + two cycles before. + +.. nextslide:: + +.. code-block:: diff + + [scheduling] + cycling mode = integer + initial cycle point = 1 + [[graph]] + P1 = """ + buy_ingredients => make_dough + pre_heat_oven & make_dough => bake_bread + bake_bread => sell_bread & clean_oven + clean_oven[-P1] => pre_heat_oven + + sell_bread[-P2] => buy_ingredients + """ + +.. nextslide:: + +.. ifnotslides:: + + This means that ``buy_ingredients`` will run after the ``sell_bread`` task + two cycles earlier. + +.. note:: + + The ``[-P2]`` suffix references a task two cycles back. For the first two + cycles this doesn't make sense, so those dependencies (and indeed any before + the initial cycle point) will be ignored. + +.. digraph:: example + :align: center + + size = "4.5,15" + + subgraph cluster_1 { + label = 1 + style = dashed + "1/pur" [label="buy_ingredients\n1"] + "1/mak" [label="make_dough\n1"] + "1/bak" [label="bake_bread\n1"] + "1/sel" [label="sell_bread\n1"] + "1/cle" [label="clean_oven\n1"] + "1/pre" [label="pre_heat_oven\n1"] + } + + subgraph cluster_2 { + label = 2 + style = dashed + "2/pur" [label="buy_ingredients\n2"] + "2/mak" [label="make_dough\n2"] + "2/bak" [label="bake_bread\n2"] + "2/sel" [label="sell_bread\n2"] + "2/cle" [label="clean_oven\n2"] + "2/pre" [label="pre_heat_oven\n2"] + } + + subgraph cluster_3 { + label = 3 + style = dashed + "3/pur" [label="buy_ingredients\n3"] + "3/mak" [label="make_dough\n3"] + "3/bak" [label="bake_bread\n3"] + "3/sel" [label="sell_bread\n3"] + "3/cle" [label="clean_oven\n3"] + "3/pre" [label="pre_heat_oven\n3"] + } + + subgraph cluster_4 { + label = 4 + style = dashed + "4/pur" [label="buy_ingredients\n4"] + "4/mak" [label="make_dough\n4"] + "4/bak" [label="bake_bread\n4"] + "4/sel" [label="sell_bread\n4"] + "4/cle" [label="clean_oven\n4"] + "4/pre" [label="pre_heat_oven\n4"] + } + + "1/pur" -> "1/mak" -> "1/bak" -> "1/sel" + "1/pre" -> "1/bak" -> "1/cle" + "1/cle" -> "2/pre" + "1/sel" -> "3/pur" + "2/pur" -> "2/mak" -> "2/bak" -> "2/sel" + "2/pre" -> "2/bak" -> "2/cle" + "2/cle" -> "3/pre" + "2/sel" -> "4/pur" + "3/pur" -> "3/mak" -> "3/bak" -> "3/sel" + "3/pre" -> "3/bak" -> "3/cle" + "3/cle" -> "4/pre" + "4/pur" -> "4/mak" -> "4/bak" -> "4/sel" + "4/pre" -> "4/bak" -> "4/cle" + + +Recurrence Sections +------------------- + +.. ifnotslides:: + + In the previous examples we used a + ``P1``:term:`recurrence` to make the workflow repeat at successive integer + cycle points. Similarly ``P2`` means repeat every *other* cycle, and so + on. We can use multiple recurrences to build more complex workflows: + + .. code-block:: cylc + + [scheduling] + cycling mode = integer + initial cycle point = 1 + [[graph]] + # Repeat every cycle. + P1 = foo + # Repeat every second cycle. + P2 = bar + # Repeat every third cycle. + P3 = baz + + .. image:: ../../img/recurrence-sections.svg + :align: center + +.. ifslides:: + + .. code-block:: cylc + + [scheduling] + cycling mode = integer + initial cycle point = 1 + [[graph]] + # Repeat every cycle. + P1 = foo + # Repeat every second cycle. + P2 = bar + # Repeat every third cycle. + P3 = baz + + .. image:: ../../img/recurrence-sections.svg + :align: center + +.. nextslide:: + +.. ifnotslides:: + + We can also tell Cylc where to start a recurrence sequence. + + From the initial cycle point: + By default, recurrences start at the: :term:`initial cycle point`. + + From an arbitrary cycle point: + We can give a different start point like this: + ``5/P3`` means repeat every third cycle, starting from cycle number 5. + To run a graph at every other cycle point, use ``2/P2``. + + Offset from the initial cycle point: + The start point of a recurrence can also be defined as an offset from the + :term:`initial cycle point` For example, ``+P5/P3`` means repeat every + third cycle from 5 cycles *after* the initial cycle point. + +.. ifslides:: + + ``2/P2`` + Repeat every even cycle (Even if your initial cycle point was odd) + + .. image:: ../../img/recurrence-sections2.svg + :align: center + + ``+P5/P3`` + Repeat every third cycle starting 5 cycles *after* the initial cycle + point. + + .. nextslide:: + + .. rubric:: In this practical we will turn the :term:`workflow ` + of the previous section into a :term:`cycling workflow `. + + Next section: :ref:`tutorial-datetime-cycling` + +.. _basic cycling practical: + +.. practical:: + + .. rubric:: In this practical we will turn the :term:`workflow ` + of the previous section into a :term:`cycling workflow `. + + If you have not completed the previous practical use the following code for + your :cylc:conf:`flow.cylc` file. + + .. code-block:: cylc + + [scheduler] + allow implicit tasks = True + [scheduling] + [[graph]] + R1 = """ + a & c => b => d & f + d => e + """ + + #. **Create a new workflow.** + + Create a new source directory ``integer-cycling`` under ``~/cylc-src/``, + and move into it: + + .. code-block:: bash + + mkdir -p ~/cylc-src/integer-cycling + cd ~/cylc-src/integer-cycling + + Copy the above code into a :cylc:conf:`flow.cylc` file in that directory. + + #. **Make the workflow cycle.** + + Add the following lines to your ``flow.cylc`` file: + + .. code-block:: diff + + [scheduling] + + cycling mode = integer + + initial cycle point = 1 + [[graph]] + - R1 = """ + + P1 = """ + a & c => b => d & f + d => e + """ + + #. **Visualise the workflow.** + + Try visualising your workflow using ``cylc graph``. + + .. code-block:: none + + cylc graph . + + .. tip:: + + You can use the ``-c`` (``--cycles``) option + to draw a box around each cycle: + + + .. code-block:: none + + cylc graph -c . + + .. tip:: + + By default ``cylc graph`` displays the first three cycles of the graph, + but you can specify the range of cycles on the command line. + Here's how to display cycles ``1`` through ``5``: + + .. code-block:: none + + cylc graph . 1 5 + + #. **Add another recurrence.** + + Suppose we wanted the ``e`` task to run every *other* cycle + as opposed to every cycle. We can do this by adding another + recurrence. + + Make the following changes to your :cylc:conf:`flow.cylc` file. + + .. code-block:: diff + + [scheduling] + cycling mode = integer + initial cycle point = 1 + [[graph]] + P1 = """ + a & c => b => d & f + - d => e + """ + + P2 = """ + + d => e + + """ + + Use ``cylc graph`` to see the effect this has on the workflow. + + #. **intercycle dependencies.** + + Now we will add + three intercycle dependencies: + + #. Between ``f`` from the previous cycle and ``c``. + #. Between ``d`` from the previous cycle and ``a`` + *every odd cycle* (e.g. 2/d => 3/a). + #. Between ``e`` from the previous cycle and ``a`` + *every even cycle* (e.g. 1/e => 2/a). + + Try adding these to your :cylc:conf:`flow.cylc` file to + make your workflow match the diagram below. + + .. hint:: + + * ``P2`` means every other cycle, from the initial cycle point. + * ``2/P2`` means every other cycle, from cycle point 2. + + .. digraph:: example + :align: center + + size = "4.5,7" + + subgraph cluster_1 { + label = 1 + style = dashed + "1/a" [label="a\n1"] + "1/b" [label="b\n1"] + "1/d" [label="d\n1"] + "1/f" [label="f\n1"] + "1/c" [label="c\n1"] + "1/e" [label="e\n1"] + } + + subgraph cluster_2 { + label = 2 + style = dashed + "2/a" [label="a\n2"] + "2/b" [label="b\n2"] + "2/d" [label="d\n2"] + "2/f" [label="f\n2"] + "2/c" [label="c\n2"] + } + + subgraph cluster_3 { + label = 3 + style = dashed + "3/a" [label="a\n3"] + "3/b" [label="b\n3"] + "3/d" [label="d\n3"] + "3/f" [label="f\n3"] + "3/c" [label="c\n3"] + "3/e" [label="e\n3"] + } + + "1/a" -> "1/b" -> "1/f" + "1/b" -> "1/d" + "1/c" -> "1/b" + "2/a" -> "2/b" -> "2/f" + "2/b" -> "2/d" + "2/c" -> "2/b" + "3/a" -> "3/b" -> "3/f" + "3/b" -> "3/d" + "3/c" -> "3/b" + "1/d" -> "1/e" -> "2/a" + "3/d" -> "3/e" + "2/d" -> "3/a" + "1/f" -> "2/c" + "2/f" -> "3/c" + + .. spoiler:: Solution warning + + .. code-block:: cylc + + [scheduler] + allow implicit tasks = True + [scheduling] + cycling mode = integer + initial cycle point = 1 + [[graph]] + P1 = """ + a & c => b => d & f + f[-P1] => c # (1) + """ + P2 = """ + d => e + d[-P1] => a # (2) + """ + 2/P2 = """ + e[-P1] => a # (3) + """ diff --git a/nightly_8.4/html/_sources/user-guide/cheat-sheet.rst.txt b/nightly_8.4/html/_sources/user-guide/cheat-sheet.rst.txt new file mode 100644 index 00000000000..ef388e2fc56 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/cheat-sheet.rst.txt @@ -0,0 +1,297 @@ +.. _user-guide.cheat_sheet: + +Cheat Sheet +=========== + +A cheat sheet covering most of the major Cylc commands. For a full list see +``cylc help all``. + +See also the :ref:`Cylc 7 to 8 migration cheat sheet <728.cheat_sheet>`. + +.. contents:: + :depth: 2 + :local: + :backlinks: none + +.. highlight:: sub + + +Working with Workflows +---------------------- + +``cylc validate`` + Validates the workflow configuration (will tell you if there are any problems). +``cylc install`` + Install a workflow (i.e. copy its files into the ``~/cylc-run`` directory). +``cylc play`` + Start a workflow running. + +Install and start a workflow:: + + # validate a workflow + cylc validate + + # install a workflow + cylc install + + # start a workflow + cylc play + +For convenience, these three operations can be combined with the ``cylc vip`` command +(vip = validate + install + play):: + + # validate, install and play a workflow + cylc vip + +When you're done with a workflow run, remove it with ``cylc clean``:: + + # delete a workflow installation + cylc clean + + +Starting and Stopping Workflows +------------------------------- + +Start workflows with ``cylc play``, stop them with ``cylc stop``. + +Workflows can be started or stopped multiple times, Cylc will always continue +where it left off:: + + # start a workflow + cylc play + + # stop a workflow + cylc stop + + # restart a workflow + cylc play + +You can also "pause" a workflow. A paused workflow will not submit any new +jobs. Pausing workflows can be handy if you need to perform +:ref:`interventions ` on them. Use ``cylc play`` to +resume a workflow:: + + # pause a workflow + cylc pause + + # resume a workflow + cylc play + +The Cylc play, pause and stop commands work similarly to the play, pause and +stop buttons on an old tape player. You can play, pause or stop a workflow as +many times as you like; Cylc will never lose its place in the workflow. + + +List Workflows +-------------- + +The ``cylc scan`` command can list your installed workflows:: + + # list all running workflows + cylc scan + + # get information about running workflows + cylc scan --format=rich + + # list all installed workflows + cylc scan --states=all + +You can also view your workflows in the GUI or Tui. + + +Opening the GUI/Tui +------------------- + +Cylc has an in-terminal utility for monitoring and controlling workflows:: + + # view all workflows + cylc tui + + # open a specific workflow + cylc tui + +There is also a GUI which opens in a web browser:: + + # open the GUI to the homepage + cylc gui + + # open the GUI to a specific workflow + cylc gui + + +Making Changes To Running Workflows +----------------------------------- + +You can make changes to a workflow without having to shut it down and restart it. + +First, make your required changes to the files in the workflow's +:term:`source directory`, then run the ``cylc vr`` command +(:ref:`more information `):: + + # validate, reinstall and reload the workflow + cylc vr + +If you want to quickly edit a task's configuration, e.g. whilst developing a +workflow or testing changes, the +:ref:`"Edit Runtime" feature ` +in the GUI can be convenient. + + +Inspecting Workflows +-------------------- + +Validate the workflow configuration (good for spotting errors):: + + cylc validate + +Check the workflow for common problems and code style:: + + cylc lint + +View the workflow configuration *before* Cylc has parsed it +(but after pre-processing - good for debugging Jinja2 errors):: + + cylc view -p + +View the workflow configuration *after* Cylc has parsed it +(good for debugging family inheritance):: + + cylc config + + # view a specific task's configuration + cylc config -i '[runtime][]' + + # view the workflow configuration with defaults applied + cylc config --defaults + +Generate a graphical representation of the workflow's :term:`graph` +(a useful tool for developing workflow graphs):: + + cylc graph + + # render the graph between two cycle points + cylc graph + + # render the graph transposed (can make it easier to read) + cylc graph --transpose + + # group tasks by cycle point + cylc graph --cycles + + # collapse tasks within a family (can reduce the number of tasks displayed) + cylc graph --group= + +List all tasks and families defined in a workflow:: + + cylc list + + +Running Rose Stem Workflows +--------------------------- + +Currently, Rose stem workflows are installed using a different command to +regular workflows:: + + # install a rose-stem workflow + rose stem + + # start a rose-stem workflow + cylc play + +Once a workflow is installed you can run regular Cylc commands against it, e.g +``cylc stop``. + +We may be able to automatically activate ``rose stem`` functionality as part +of ``cylc install`` in the future which would allow you to install and start +a Rose Stem workflow with ``cylc vip``. + + +Interventions +------------- + +You can intervene in the running a workflow, e.g. to re-run a task. + +Interventions are written up in :ref:`user-guide.interventions`. Here is a +quick summary: + +Run or re-run a task (:ref:`more info `):: + + cylc trigger /// + +Mark a task as "succeeded" +(:ref:`more info `):: + + cylc set /// + +Kill a running job:: + + cylc kill /// + + +Running Workflows in Debug Mode +------------------------------- + +When a workflow is in debug mode, more information gets written to the +workflow's :ref:`log file `. +Jobs also get run in Bash "xtrace" mode (``set -x``) which can help to diagnose +the line in a task's script that caused the error. + +Start a workflow in debug mode:: + + $ cylc vip --debug + + # OR + $ cylc play --debug + +Switch an already running workflow into debug mode:: + + cylc verbosity DEBUG + +For more information, see :ref:`troubleshooting`. + + +Managing Multiple Workflows +--------------------------- + +Many Cylc commands can operate over multiple workflows:: + + # stop all workflows + cylc stop '*' + + # pause all workflows + cylc pause '*' + + # re-run all failed tasks in all workflows + cylc trigger "*//*/*:failed" + +The ``*`` characters in these examples are "globs". Make sure you put quotes +around them to prevent the shell from trying to expand them. + +For more information on globs or the Cylc ID format, run ``cylc help id``. + + +Working With Cylc IDs +--------------------- + +Everything in a Cylc workflow has an ID. We use these IDs on the command line +and in the GUI. + +Cylc Ids take the format:: + + //// + +E.G:: + + # a workflow + my-workflow + + # a cycle within a workflow + my-workflow//20000101T00Z + + # a task instance + my-workflow//20000101T00Z/mytask + + # a job submission + my-workflow//20000101T00Z/mytask/01 + +For more information on the Cylc ID format, run ``cylc help id``. diff --git a/nightly_8.4/html/_sources/user-guide/examples/1-hello-world/index.rst.txt b/nightly_8.4/html/_sources/user-guide/examples/1-hello-world/index.rst.txt new file mode 100644 index 00000000000..a73afdf1e44 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/examples/1-hello-world/index.rst.txt @@ -0,0 +1,21 @@ +Hello World +----------- + +.. admonition:: Get a copy of this example + :class: hint + + .. code-block:: console + + $ cylc get-resources examples/hello-world + +In the time honoured tradition, this is the minimal Cylc workflow: + +.. literalinclude:: flow.cylc + :language: cylc + +It writes the phrase "Hello World!" to standard output (captured to the +``job.out`` log file). + +Run it with:: + + $ cylc vip hello-world diff --git a/nightly_8.4/html/_sources/user-guide/examples/2-integer-cycling/index.rst.txt b/nightly_8.4/html/_sources/user-guide/examples/2-integer-cycling/index.rst.txt new file mode 100644 index 00000000000..89be2bb0871 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/examples/2-integer-cycling/index.rst.txt @@ -0,0 +1,16 @@ +Integer Cycling +=============== + +.. admonition:: Get a copy of this example + :class: hint + + .. code-block:: console + + $ cylc get-resources examples/integer-cycling + +.. literalinclude:: flow.cylc + :language: cylc + +Run it with:: + + $ cylc vip integer-cycling diff --git a/nightly_8.4/html/_sources/user-guide/examples/3-datetime-cycling/index.rst.txt b/nightly_8.4/html/_sources/user-guide/examples/3-datetime-cycling/index.rst.txt new file mode 100644 index 00000000000..803a532551f --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/examples/3-datetime-cycling/index.rst.txt @@ -0,0 +1,16 @@ +Datetime Cycling +================ + +.. admonition:: Get a copy of this example + :class: hint + + .. code-block:: console + + $ cylc get-resources examples/datetime-cycling + +.. literalinclude:: flow.cylc + :language: cylc + +Run it with:: + + $ cylc vip datetime-cycling diff --git a/nightly_8.4/html/_sources/user-guide/examples/converging-workflow/index.rst.txt b/nightly_8.4/html/_sources/user-guide/examples/converging-workflow/index.rst.txt new file mode 100644 index 00000000000..27da079d58f --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/examples/converging-workflow/index.rst.txt @@ -0,0 +1,39 @@ +Converging Workflow +=================== + +.. admonition:: Get a copy of this example + :class: hint + + .. code-block:: console + + $ cylc get-resources examples/converging-workflow + +A workflow which runs a pattern of tasks over and over until a convergence +condition has been met. + +* The ``increment`` task runs some kind of model or process which increments + us toward the solution. +* The ``check_convergence`` task, checks if the convergence condition has been + met. + +.. literalinclude:: flow.cylc + :language: cylc + +Run it with:: + + $ cylc vip converging-workflow + +.. admonition:: Example - Genetic algorithms + :class: hint + + .. _genetic algorithm: https://en.wikipedia.org/wiki/Genetic_algorithm + + An example of a converging workflow might be a `genetic algorithm`_, where you + "breed" entities, then test their "fitness", and breed again, over and over + until you end up with an entity which is able to satisfy the requirement. + + .. digraph:: Example + + random_seed -> breed -> test_fitness + test_fitness -> breed + test_fitness -> stop diff --git a/nightly_8.4/html/_sources/user-guide/examples/event-driven-cycling/README.rst.txt b/nightly_8.4/html/_sources/user-guide/examples/event-driven-cycling/README.rst.txt new file mode 100644 index 00000000000..d1e112374f1 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/examples/event-driven-cycling/README.rst.txt @@ -0,0 +1,49 @@ +Cylc is good at orchestrating tasks to a schedule, e.g: + +* ``PT1H`` - every hour +* ``P1D`` - every day +* ``P1M`` - every month +* ``PT1H ! (T00, T12)`` - every hour, except midnight and midday. + +But sometimes the things you want to run don't have a schedule. + +This example uses ``cylc ext-trigger`` to establish a pattern where Cylc waits +for an external signal and starts a new cycle every time a signal is received. + +The signal can carry data using the ext-trigger ID, this example sets the ID +as a file path containing some data that we want to make available to the tasks +that run in the cycle it triggers. + +To use this example, first start the workflow as normal:: + + cylc vip event-driven-cycling + +Then, when you're ready, kick off a new cycle, specifying any +environment variables you want to configure this cycle with:: + + ./bin/trigger WORLD=earth + +Replacing ```` with the ID you installed this workflow as. + +.. admonition:: Example - CI/CD + :class: hint + + This pattern is good for CI/CD type workflows where you're waiting on + external events. This pattern is especially powerful when used with + sub-workflows where it provides a solution to two-dimensional cycling + problems. + +.. admonition:: Example - Polar satellite data processing + :class: hint + + Polar satellites pass overhead at irregular intervals. This makes it tricky + to schedule data processing because you don't know when the satellite will + pass over the receiver station. With the event driven cycling approach you + could start a new cycle every time data arrives. + +.. note:: + + * The number of parallel cycles can be adjusted by changing the + :cylc:conf:`[scheduling]runahead limit`. + * To avoid hitting the runahead limit, ensure that failures are handled in + the graph. diff --git a/nightly_8.4/html/_sources/user-guide/examples/event-driven-cycling/index.rst.txt b/nightly_8.4/html/_sources/user-guide/examples/event-driven-cycling/index.rst.txt new file mode 100644 index 00000000000..5980591f0fd --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/examples/event-driven-cycling/index.rst.txt @@ -0,0 +1,14 @@ +Event Driven Cycling +==================== + +.. admonition:: Get a copy of this example + :class: hint + + .. code-block:: console + + $ cylc get-resources examples/event-driven-cycling + +.. include:: README.rst + +.. literalinclude:: flow.cylc + :language: cylc diff --git a/nightly_8.4/html/_sources/user-guide/examples/extending-workflow/index.rst.txt b/nightly_8.4/html/_sources/user-guide/examples/extending-workflow/index.rst.txt new file mode 100644 index 00000000000..036438ff466 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/examples/extending-workflow/index.rst.txt @@ -0,0 +1,105 @@ +Extending Workflow +------------------ + +.. cylc-scope:: flow.cylc[scheduling] + +Sometimes we may run a workflow to :term:`completion `, +but subsequently wish to run it for a few more cycles. + +With Cylc 7 this was often done by changing the `final cycle point` and +restarting the workflow. This approach worked, but was a little awkward. +It's possible with Cylc 8, but we would recommend moving away from this +pattern instead. + +The recommended approach to this problem (Cylc 6+) is to use the +`stop after cycle point` rather than the `final cycle point`. + +The `stop after cycle point` tells Cylc to **stop** after the workflow passes +the specified point, whereas the `final cycle point` tells Cylc that the +workflow **finishes** at the specified point. + +When a workflow **finishes**, it is a little awkward to restart as you have to +tell Cylc which tasks to continue on from. The `stop after cycle point` +solution avoids this issue. + + +Example +^^^^^^^ + +.. admonition:: Get a copy of this example + :class: hint + + .. code-block:: console + + $ cylc get-resources examples/extending-workflow/simple + +This workflow will stop at the end of the ``2002`` cycle: + +.. literalinclude:: simple/flow.cylc + :language: cylc + +After it has run and shut down, change the `stop after cycle point` to +the desired value and restart it. E.g: + +.. code-block:: bash + + # install and run the workflow: + cylc vip + + # then later edit "stop after cycle point" to "2004" + + # then reinstall and restart the workflow: + cylc vr + +The workflow will continue from where it left off and run until the end of the +``2004`` cycle. Because the workflow never hit the `final cycle point` it +never "finished" so no special steps are required to restart the workflow. + +You can also set the `stop after cycle point` when you start the workflow: + +.. code-block:: bash + + cylc play --stop-cycle-point=2020 myworkflow + +Or change it at any point whilst the workflow is running: + +.. code-block:: bash + + cylc stop myworkflow//2030 # change the stop after cycle point to 2030 + +.. note:: + + If you set the `stop after cycle point` on the command line, this value will + take precedence over the one in the workflow configuration. Use + ``cylc play --stop-cycle-point=reload`` to restart the workflow using the + `stop after cycle point` configured in the workflow configuration. + + +Running Tasks At The `stop after cycle point` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you have tasks that you want to run before the workflow shuts down at the +`stop after cycle point`, use the recurrence ``R1/`` to schedudule +them, e.g: + +.. code-block:: cylc + + #!Jinja2 + + {% set stop_cycle = '3000' %} + + [scheduling] + initial cycle point = 2000 + stop after cycle point = {{ stop_cycle }} + [[graph]] + R1/{{ stop_cycle }} = """ + # these tasks will run *before* the workflow shuts down + z => run_me => and_me + """ + +When the workflow is subsequently restarted with a later +`stop after cycle point`, these tasks will be re-scheduled at the new +stop point. + + +.. cylc-scope:: diff --git a/nightly_8.4/html/_sources/user-guide/examples/index.rst.txt b/nightly_8.4/html/_sources/user-guide/examples/index.rst.txt new file mode 100644 index 00000000000..d784275ff19 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/examples/index.rst.txt @@ -0,0 +1,11 @@ +.. _user-guide.examples: + +Examples +======== + +These examples cover some of the main patterns for implementing Cylc workflows. + +.. toctree:: + :glob: + + */index diff --git a/nightly_8.4/html/_sources/user-guide/examples/inter-workflow-triggers/README.rst.txt b/nightly_8.4/html/_sources/user-guide/examples/inter-workflow-triggers/README.rst.txt new file mode 100644 index 00000000000..8aa8d7d7b6f --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/examples/inter-workflow-triggers/README.rst.txt @@ -0,0 +1,14 @@ +This example shows how one workflow can "trigger off" of tasks in another +workflow. + +In this example, there are two workflows: + +* "upstream" writes a file. +* "downstream" reads this file. + +Run both workflows simultaneously to see this in action: + +.. code-block:: console + + $ cylc vip inter-workflow-triggers/upstream + $ cylc vip inter-workflow-triggers/downstream diff --git a/nightly_8.4/html/_sources/user-guide/examples/inter-workflow-triggers/index.rst.txt b/nightly_8.4/html/_sources/user-guide/examples/inter-workflow-triggers/index.rst.txt new file mode 100644 index 00000000000..0fd70b17d21 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/examples/inter-workflow-triggers/index.rst.txt @@ -0,0 +1,28 @@ +Inter-Workflow Triggering +========================= + +.. admonition:: Get a copy of this example + :class: hint + + .. code-block:: console + + $ cylc get-resources examples/inter-workflow-triggers + +.. include:: README.rst + +.. literalinclude:: upstream/flow.cylc + :language: cylc + :caption: Upstream Workflow + +.. literalinclude:: downstream/flow.cylc + :language: cylc + :caption: Downstream Workflow + +.. admonition:: Example - Decoupled workflows + :class: hint + + This pattern is useful where you have workflows that you want to keep decoupled + from one another, but still need to exchange data. E.G. in operational + meteorology we might have a global model (covering the whole Earth) and a + regional model (just covering a little bit of it) where the regional model + obtains its boundary condition from the global model. diff --git a/nightly_8.4/html/_sources/user-guide/index.rst.txt b/nightly_8.4/html/_sources/user-guide/index.rst.txt new file mode 100644 index 00000000000..3cbcf5efd69 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/index.rst.txt @@ -0,0 +1,19 @@ +.. _user guide: + +User Guide +========== + + +.. toctree:: + :maxdepth: 2 + + introduction + writing-workflows/index + installing-workflows + running-workflows/index + task-implementation/index + interventions/index + removing-workflows + cheat-sheet + examples/index + troubleshooting diff --git a/nightly_8.4/html/_sources/user-guide/installing-workflows.rst.txt b/nightly_8.4/html/_sources/user-guide/installing-workflows.rst.txt new file mode 100644 index 00000000000..decef413c6b --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/installing-workflows.rst.txt @@ -0,0 +1,504 @@ +.. _Installing-workflows: + +Installing Workflows +==================== + +Cylc commands identify workflows via their names, which are relative path names +under the :term:`cylc-run directory`, ``~/cylc-run/`` by default. + +Workflows can be grouped together under sub-directories. E.g. there are three +workflows in the example below: ``nwp/oper/region1``, ``nwp/oper/region2`` and +``nwp/test/region1``. + +.. code-block:: console + + $ cylc scan --state=all --name nwp --format=tree + nwp + ├─oper + │ ├─ region1 + │ └─ region2 + └─test + └─ region1 + +This chapter will demonstrate how to install a workflow from an arbitrary +location, called a :term:`source directory`. +``cylc install`` will create a new run directory in the :term:`cylc-run directory` +for each installation of a workflow. + +.. contents:: Contents + :depth: 2 + :local: + + +.. _Install-Workflow: + +The Cylc Install Command +------------------------ + +Workflows can be installed with the ``cylc install`` command, which creates +the :term:`run directory` structure and some service files underneath it. + +.. note:: + + It is possible to run a workflow without installation by writing it + directly in the run directory. + However, we recommend that you write your workflow in a source + directory and use ``cylc install`` to create a fresh run directory. + + +.. _Using Cylc Install: + +Using Cylc Install +------------------ + +``cylc install`` accepts as its only argument either: + +* a workflow source name (see :ref:`configurable source dirs` below) e.g. + ``foo/bar`` +* a path to the source directory e.g. ``./foo/bar`` or ``/path/to/foo/bar`` + (note that relative paths must begin with ``./`` to distinguish them from + workflow source names) + +If no argument is supplied, the current working directory is used as the +source directory. + +.. note:: + + To avoid confusion, ``cylc install`` does not permit any of the following + reserved directory names: |reserved_filenames| + + +Options +^^^^^^^ + +The table below illustrates several command line options that control naming +of run directories for installed workflows (the current working directory in +these examples is ``~/cylc-src/my-flow``): + +.. csv-table:: + :header: Command, Results in Installation in Directory + :align: left + + ``cylc install``, ``~/cylc-run/my-flow/run1`` + ``cylc install --no-run-name``, ``~/cylc-run/my-flow`` + ``cylc install --run-name=new-run``, ``~/cylc-run/my-flow/new-run`` + ``cylc install --workflow-name=new-name``, ``~/cylc-run/new-name/run1`` + + +.. _configurable source dirs: + +Configurable Source Directories +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can configure a list of directories that ``cylc install SOURCE_NAME`` +and the GUI will search for source directories inside, using +:cylc:conf:`global.cylc[install]source dirs`. For example, if you have + +.. code-block:: cylc + + # global.cylc + [install] + source dirs = ~/cylc-src, ~/roses + +then ``cylc install dogs/fido`` will search for a workflow source directory +``~/cylc-src/dogs/fido``, or, failing that, ``~/roses/dogs/fido``, and install +the first match (into ``~/cylc-run/dogs/fido/run1``). + + +Numbered Runs +^^^^^^^^^^^^^ + +By default, ``cylc install`` creates numbered run directories, i.e. +``~/cylc-run//run``, provided the options +``--run-name`` or ``--no-run-name`` are not used. The run number automatically +increments each time ``cylc install`` is run, and a symlink ``runN`` is +created/updated to point to the run. + +Example: A typical run directory structure, after three executions of +``cylc install`` will look as follows. + +.. code-block:: none + + ├── _cylc-install + │ └── source -> /home/cylc-src/test-flow + ├── run1 + │ ├── flow.cylc + │ └── log + │ └── install + │ └── -install.log + ├── run2 + │ ├── flow.cylc + │ └── log + │ └── install + │ └── -install.log + ├── run3 + │ ├── flow.cylc + │ └── log + │ └── install + │ └── -install.log + └── runN -> /home/cylc-run/test-flow/run3 + +The numbered runs option may be overridden, using either the ``--no-run-name`` +or the ``--run-name`` options. + + +Named Runs +^^^^^^^^^^ + +As an alternative to numbered runs, it is possible to name the runs, using the +``--run-name`` option. +In this case, the ``runN`` symlink will not be created. +This option cannot be used if numbered runs are already present. Likewise, +numbered runs cannot be used if named runs are already present. + + +.. _SymlinkDirs: + +Symlink Directories +^^^^^^^^^^^^^^^^^^^ + +You can configure workflow :term:`run directories ` and certain +sub-directories as symlinks to other locations. This is a useful way of +offloading data onto other drives to limit the disk space taken up by +``~/cylc-run``. + +The symlink targets are configured per install target in +:cylc:conf:`global.cylc[install][symlink dirs]`. For more information see +:ref:`SymlinkDirsSetup` + + +The Cylc Install Process +------------------------ + +There are two main parts of the ``cylc install`` process. + +1. File Installation + +2. Symlinking of Directories + +.. _File Installation: + +1. File Installation +^^^^^^^^^^^^^^^^^^^^ + +Installation will involve copying the files found in the source directory into +a new run directory. If you wish to install files into an existing run +directory, use ``cylc reinstall``, see :ref:`Reinstalling a Workflow`. + +Excluding Items From Installation +""""""""""""""""""""""""""""""""" + +By default, cylc install will exclude ``.git``, ``.svn`` directories. +To configure excluded files and directories from the file installation, +create a ``.cylcignore`` file in your source directory, this supports +pattern matching. + +The following example will detail how to install a workflow, including +configuring files to be excluded from the installation. + +.. _Example Installation: + +Example Installation +"""""""""""""""""""" + +For example: +We will look at running the cylc install command inside the directory +``~/cylc-src/test-flow`` with the following directory structure: + +.. code-block:: console + + $ pwd + /home/cylc-src/test-flow + +.. code-block:: console + + $ tree -all + ├── .cylcignore + ├── dir1 + │ ├── another-file + │ └── file + ├── dir2 + │ ├── another-file + │ └── file + ├── file1 + ├── file2 + ├── file3 + ├── flow.cylc + ├── textfile1.txt + └── textfile2.txt + +We wish to omit any files matching the pattern ``*.txt``, the file +``file1``, the contents of ``dir1`` and the contents of ``dir2`` including the +directory itself. + +.. code-block:: console + + $ cat .cylcignore + *.txt + file1 + dir1/* + dir2 + + +Now we are ready to install our workflow. + +.. code-block:: console + + $ cylc install + INSTALLED test-flow from home/cylc-src/test-flow -> home/cylc-run/test-flow/run1 + +Looking at the directory structure that has been created + +.. code-block:: console + + $ tree -all home/cylc-run/test-flow/run1 + ├── dir1 + ├── file2 + ├── file3 + ├── flow.cylc + ├── log + │ └── install + │ └── -install.log + └── .service + + +.. _Symlinking of Directories: + +2. Symlinking of Directories +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If symlink directories are configured in the ``[[[localhost]]]`` section in +:cylc:conf:`global.cylc[install][symlink dirs]`, +``cylc install`` will create these symlinks and their target locations +(symlinks for remote install targets do not get created until +:term:`starting ` the workflow). + +Override default symlink locations +"""""""""""""""""""""""""""""""""" + +You can override the default locations set in +:cylc:conf:`global.cylc[install][symlink dirs]` by using the ``--symlink-dirs`` +option with ``cylc install``. + +For example, using the command line option +``--symlink-dirs="log=$DIR, run=/path/to/dir,..."`` will symlink: + +- ``$DIR -> ~/cylc-run/workflow/log`` +- ``/path/to/dir -> ~/cylc-run/workflow/run`` + +.. note:: + + If configuring symlink dirs on the command line, the global configured + symlink dirs will not be used to source directories not included in + the command line list. + + +To skip making localhost symlinks +""""""""""""""""""""""""""""""""" + +Use ``--symlink-dirs=""`` with the ``cylc install`` command. + + + +Automatically Generated Directories and Files +--------------------------------------------- + +Running ``cylc install`` will generate some extra files in your workflow run +directory. + +- The :term:`service directory` will be created in preparation for running the + workflow. This is needed to store essential files used by Cylc. + +- A ``_cylc-install`` directory containing a ``source`` symlink to the + :term:`source directory`. + This is needed to enable Cylc to determine the original workflow source + for ``cylc reinstall``. + +- A new ``install`` directory in the workflow's log directory, with a + time-stamped install log file containing information about the installation. + +Cylc plugins (such as :ref:`Cylc Rose`) may generate additional files. + + +.. _Reinstalling a Workflow: + +Reinstalling a Workflow +----------------------- + +To apply changes from your source directory to the installed run directory, +use ``cylc reinstall``. Changes made will be recorded in the workflow log +directory. + +For example: + +.. code-block:: console + + $ cylc reinstall myflow/run1 + +Cylc will determine the source directory and update your workflow. + +Returning to the example from above (see :ref:`Example Installation`). + +The source directory, ``~/cylc-src/test-flow`` has been altered as follows: + +.. code-block:: console + + $ tree -all ~/cylc-src/test-flow + ├── .cylcignore + ├── dir1 + │ ├── another-file + │ └── file + ├── dir2 + │ ├── another-file + │ └── file + ├── dir3 + │ ├── another-file + │ └── file + ├── file1 + ├── file2 + ├── file3 + ├── flow.cylc + ├── textfile1.txt + └── textfile2.txt + +.. code-block:: console + + $ cat .cylcignore + *.txt + file1 + dir2 + +We wish to update our ``~/cylc-run/test-flow/run1`` with the directories ``dir1`` +and ``dir3``: + +.. code-block:: console + + $ cylc reinstall test-flow/run1 + +The run directory now looks as follows: + +.. code-block:: console + + $ tree -all home/cylc-run/test-flow/run1 + ├── dir1 + │ ├── another-file + │ └── file + ├── dir3 + │ ├── another-file + │ └── file + ├── file2 + ├── file3 + ├── flow.cylc + ├── log + │ └── install + │ └── -install.log + │ └── -reinstall.log + └── .service + +.. note:: + + If your workflow needs to create or install scripts or executables at runtime + and you don't want Cylc to delete them on re-installation, you can use + ``bin`` and ``lib/python`` directories in the + :ref:`workflow share directory`. + + +Expected Errors +--------------- + +There are some occasions when installation is expected to fail: + +- ``log``, ``share``, ``work`` or ``_cylc-install`` directories exist in the + :term:`source directory` + +- Neither :cylc:conf:`flow.cylc` nor the deprecated ``suite.rc`` are found in + the :term:`source directory` + +- Both :cylc:conf:`flow.cylc` and the deprecated ``suite.rc`` are found in + the :term:`source directory`. Only one should be present. + +- The workflow name is an absolute path or invalid + + Workflow names are validated by + :py:class:`cylc.flow.unicode_rules.WorkflowNameValidator`. + + .. autoclass:: cylc.flow.unicode_rules.WorkflowNameValidator + +- The workflow name contains a directory name that is any of these reserved + filenames: |reserved_filenames| + +- The install would create nested install directories. Neither a new + installation in a subdirectory of an existing one, nor a directory containing + an existing installation are permitted. For example, having installed a + workflow in ``bar`` you would be unable to install one in ``foo`` + or ``foo/bar/baz``. + + .. code-block:: none + + foo + └── bar + ├── _cylc-install + ├── baz + ├── run1 + └── runN + + This means you cannot install using ``--no-run-name`` for a workflow that + has installed numbered/named runs, nor can you install numbered/named runs + for a workflow where ``--no-run-name`` was used. + +- Trying to install a workflow into an already existing run directory. + ``cylc reinstall`` should be used for this, see + :ref:`Reinstalling a Workflow`. + +- The source directory path does not match the source directory path of a + previous installation. i.e. running ``cylc install`` in + ``~/cylc-src/my-flow``, followed by running ``cylc install`` from + ``~/different/my-flow``. + + +.. _installing_workflows.compound_commands: + +Compound Commands +----------------- + +Cylc provides compound commands which carry out multiple operations. + +For example Cylc provides a command to validate, install and play a workflow. + +Compound commands make common ways of working easier. + +.. tip:: + + Use ``cylc command --help`` to get help for each compound command, + including a full list of available options. + + +``cylc vip`` (Validate, Install and Play) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``cylc vip /home/me/cylc-src/my-workflow`` is the same as running: + +.. code-block:: bash + + $ cylc validate /home/me/cylc-src/my-workflow + $ cylc install /home/me/cylc-src/my-workflow + INSTALLED my-workflow/run1 from /home/me/cylc-src/my-workflow + $ cylc play my-workflow + +``cylc vr`` (Validate, Reinstall and Reload or Play) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``cylc vr my-workflow`` is the same as running: + +.. code-block:: bash + + # Check that the changes you want to + # make will be valid after installation: + $ cylc validate my-workflow --against-source + $ cylc reinstall my-workflow + + # If workflow is running: + $ cylc reload my-workflow + + # If workflow is stopped: + $ cylc play my-workflow diff --git a/nightly_8.4/html/_sources/user-guide/interventions/index.rst.txt b/nightly_8.4/html/_sources/user-guide/interventions/index.rst.txt new file mode 100644 index 00000000000..7e90d28c445 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/interventions/index.rst.txt @@ -0,0 +1,490 @@ +.. _user-guide.interventions: + +Interventions +============= + +Sometimes things don't go to plan! + +So Cylc allows you to take manual control of your workflow whilst it's running +allowing you to do things like edit a task's configuration, re-run a section +of your graph or override task outputs. + +This section of the documentation covers some of the common interventions you +might want to perform in various scenarios. + +You can perform these interventions in multiple ways: + +.. tab-set:: + + .. tab-item:: GUI + :sync: gui + + The Cylc web app (GUI) can be launched with the ``cylc gui`` command. + + Some sites provide a central deployment for you where you log in via the + web browser rather than launching it yourself. + + .. tab-item:: With the Tui + :sync: tui + + Cylc Tui is an interactive in-terminal application, like a minimal + version of the GUI. Start it with the ``cylc tui`` command. + + Launch it with the ``cylc tui`` command. + + .. tab-item:: On the CLI + :sync: cli + + The Cylc command line interface (CLI) can do everything the GUI can. + + To see the full list of available commands run ``cylc help all``. + +.. Write out a local table of contents: + +.. contents:: Contents + :depth: 1 + :local: + +.. NOTE - Creating screen recordings + + * Use the dimensions 650x720 for your recording area. + * On my setup that works out as 72 cols by 40 rows in the terminal. + * Keep it as short as possible without being disorientating. + * Document top-level use cases, don't attempt to cover every + possible intervention. + * I've been installing workflows as "myworkflow". + + +.. _interventions.re-run-a-task: + +Re-Run a Task +------------- + +:Example: + A task failed and I want to give it another try. + +:Solution: + Trigger the failed task. + +.. tab-set:: + + .. tab-item:: GUI + :sync: gui + + .. image:: re-run-a-task.gui.gif + :width: 75% + + .. tab-item:: Tui + :sync: tui + + .. image:: re-run-a-task.tui.gif + :width: 75% + + .. tab-item:: CLI + :sync: cli + + .. code-block:: console + + $ cylc trigger // + + +Re-Run Multiple Tasks +--------------------- + +:Example: + I need to make changes to a task, then re-run it and everything downstream + of it. + +:Solution: + :ref:`Edit the tasks configuration `, + then trigger it in a new :term:`flow`. + +.. tab-set:: + + .. tab-item:: GUI + :sync: gui + + .. image:: re-run-multiple-tasks.gui.gif + :width: 75% + + .. tab-item:: CLI + :sync: cli + + .. code-block:: console + + $ cylc trigger --flow=new /// + + +Re-Run All Failed Tasks +----------------------- + +:Example: + Multiple tasks failed due to factors external to the workflow. + I've fixed the problem, now I want them to run again. + +:Solution: + Trigger all failed tasks. + +.. note:: + + You can use this intervention with other states too, e.g. "submit-failed". + +.. tab-set:: + + .. tab-item:: GUI + :sync: gui + + .. image:: re-run-all-failed-tasks.gui.gif + :width: 75% + + .. tab-item:: CLI + :sync: cli + + .. code-block:: console + + $ cylc trigger :failed + + +.. _interventions.set-task-outputs: + +Set Task Outputs +---------------- + +:Example: + My task failed, I've gone and fixed the problem, now I want to tell Cylc + that the task succeeded. + +:Solution: + Set the "succeeded" :term:`output ` on the failed task. + +.. tab-set:: + + .. tab-item:: GUI + :sync: gui + + .. image:: set-task-outputs.gui.gif + :width: 75% + + By default this sets the "succeeded" output, press the pencil icon next + to the trigger command to specify a different output. + + .. tab-item:: Tui + :sync: tui + + .. image:: set-task-outputs.tui.gif + :width: 75% + + By default, this sets the "succeeded" output. Use ``cylc set --output`` + to specify a different output. + + .. tab-item:: CLI + :sync: cli + + .. code-block:: console + + $ cylc set // + + By default, this sets the "succeeded" output. Use the ``--output`` option + to specify a different output. + +You can also :ref:`set task prerequisites `. +Should I set task outputs or prerequisites? + +* If you set a task's outputs, then tasks downstream of it may start to run. +* If you set a task's prerequisites, the task itself may start to run. + + +.. _interventions.set-task-prerequisites: + +Set Task Prerequisites +---------------------- + +.. workflow config: + + [scheduler] + allow implicit tasks = True + + [scheduling] + [[graph]] + R1 = """ + a => z1 & z2 + b1 => b2 => z1 & z2 + c => z1 & z2 + + # set prereqs "1/b2:succeeded" and "1/c:succeeded" on 1/z1 + # set prereqs "all" on 1/z2 + """ + + [runtime] + [[b1]] + script = sleep 600 + [[c]] + script = false + +:Example: + A task is not running yet, because one or more of its + :term:`prerequisites ` are not satisfied (e.g. upstream tasks + have not run yet or have failed). I want it to ignore one or more of these + prerequisites. + +:Solution: + Set the task's prerequisites as satisfied. + +.. note:: + + If you want the task to run right away, then trigger it using the same + intervention as :ref:`interventions.re-run-a-task`. + +.. tab-set:: + + .. tab-item:: GUI + :sync: gui + + .. image:: set-task-prerequisites.gui.gif + :width: 75% + + .. tab-item:: CLI + :sync: cli + + .. code-block:: console + + $ cylc set \ + > --pre /: \ + > // + +You can also :ref:`set task outputs `. +Should I set task outputs or prerequisites? + +* If you set a task's outputs, then tasks downstream of it may start to run. +* If you set a task's prerequisites, the task itself may start to run. + + +Set a Switch Task +----------------- + +.. workflow config: + + [scheduling] + cycling mode = integer + initial cycle point = 1 + runahead limit = P1 + [[graph]] + P1 = """ + start => switch + switch:normal? => normal + switch:alternate? => alternate + normal | alternate => end + + end[-P1] => start + """ + + [runtime] + [[start]] + script = """ + if [[ $CYLC_TASK_CYCLE_POINT -eq 1 ]]; then + sleep 3 + fi + """ + [[switch]] + script = cylc message -- normal + [[[outputs]]] + normal = normal + alternate = alternate + [[normal, alternate]] + [[end]] + +:Example: + I have a :term:`branched workflow `, I want to direct it to + take a particular path ahead of time: + + .. code-block:: cylc-graph + + start => switch + + # by default, the workflow follows the "normal" path + switch:normal? => normal + + # but it can follow an alternate route if desired + switch:alternate? => alternate + + normal | alternate => end + +:Solution: + Set "succeeded" as well as the desired output(s) on the task and use the + ``-wait`` option. Cylc will follow the desired path when it gets there. + + .. note:: + + We set the "succeeded" output to prevent the task from being re-run when the + flow approaches it. + +.. tab-set:: + + .. tab-item:: GUI + :sync: gui + + .. image:: set-a-switch-task.gui.gif + :width: 75% + + .. tab-item:: CLI + :sync: cli + + .. code-block:: console + + $ cylc set --wait --output=succeeded,alternate + + +.. _interventions.edit-a-tasks-configuration: + +Edit a Task's Configuration and Re-Run It +----------------------------------------- + +:Example: + I'm developing a task and need to be able to quickly make changes and re-run + the task. + +:Solution: + Edit the task's definition and trigger it. + +.. tab-set:: + + .. tab-item:: GUI + :sync: gui + + .. image:: edit-a-tasks-configuration.gui.gif + :width: 75% + + .. note:: + + Any changes you make apply only to this one instance of the task, not + to any future instances. + + To change future instances, either use "broadcast" or see + :ref:`interventions.edit-the-workflow-configuration`. + + .. tab-item:: CLI + :sync: cli + + .. code-block:: console + + $ cylc broadcast -p -n -s 'script=true' + $ cylc trigger /// + +.. the "|" character adds some vertical whitespace + +| + +.. _interventions.edit-the-workflow-configuration: + +Edit The Workflow Configuration +------------------------------- + +:Example: + I want to change the configuration of multiple tasks or add/remove tasks + without stopping the workflow or starting it from the beginning again. + +:Solution: + Edit the workflow configuration in the :term:`source directory`, then + :term:`reinstall` and :term:`reload` the workflow. + +.. tab-set:: + + .. tab-item:: Tui + :sync: tui + + .. image:: edit-the-workflow-configuration.tui.gif + :width: 75% + + .. tab-item:: CLI + :sync: cli + + .. code-block:: console + + $ vim ~/cylc-src/myworkflow # edit the workflow configuration + $ cylc vr myworkflow # reinstall and reload the workflow + +.. note:: + + For information on how graph changes (e.g. the adding or removing of tasks) + are applied, see + :ref:`user-guide.restarting-or-reloading-after-graph-changes`. + + +Orphan a "Stuck" Job Submission +------------------------------- + +:Example: + I have a job which cannot be killed (e.g. the platform has gone down), I + want Cylc to forget about it. + +:Solution: + Set the "failed" output on the task. + +Use the same intervention as :ref:`interventions.set-task-outputs`, +but you will probably want to specify the "failed" output rather than +"succeeded". + + +Terminate a Chain of Automatic Retries +-------------------------------------- + +:Example: + I have a failed task which has been configured to automatically + :term:`retry`, I want to cancel these retries because I know it can't + succeed. + +:Solution: + Set the "failed" output on the task. + +Use the same intervention as :ref:`interventions.set-task-outputs`, +but specify the "failed" output rather than +"succeeded". + + +Hold The Workflow And Trigger Tasks One By One +---------------------------------------------- + +:Example: + I want to hold back the workflow whilst I manually run one or more tasks + to fix a problem or test a task. + +:Solution: + * Hold all tasks after a specified cycle. + * Trigger the task(s) you want to run. + * When you're done triggering, release the held tasks to allow the workflow + to continue. + +.. tab-set:: + + .. tab-item:: GUI + :sync: gui + + .. image:: set-and-release-hold-point.gif + :width: 75% + + .. tab-item:: CLI + :sync: cli + + .. code-block:: console + + $ # hold all tasks after the cycle "2000" + $ cylc hold --after=2000 + + $ # trigger the task(s) you want to run + $ cylc trigger /// + + $ # release the "hold point" to allow the workflow to continue + $ cylc release --all + +.. note:: + + The difference between the workflow "paused" state and the task "held" state: + + Workflow Pause + When a workflow is :term:`paused `, no new jobs will be submitted. + This gives you an opportunity to make changes to the workflow, however, if + you trigger tasks, they will not run until the workflow is resumed. + + Task Hold + When a task is :term:`held `, then it will not submit (if ready to + submit) until released. diff --git a/nightly_8.4/html/_sources/user-guide/introduction.rst.txt b/nightly_8.4/html/_sources/user-guide/introduction.rst.txt new file mode 100644 index 00000000000..0df90f96ca8 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/introduction.rst.txt @@ -0,0 +1,102 @@ +Introduction +============ + + +What is a Workflow? +------------------- + +.. epigraph:: + + A workflow consists of an orchestrated and repeatable pattern of business + activity enabled by the systematic organization of resources into processes + that transform materials, provide services, or process information. + + -- Wikipedia + + +.. tutorial:: What is a Workflow? + + +What is Cylc? +------------- + +Cylc (pronounced silk) is a workflow engine, a system that automatically +executes tasks according to schedules and dependencies. + +In a Cylc workflow each step is an application: an executable command, script, +or program. Cylc runs each task as soon as it is appropriate to do so. + + +.. tutorial:: What is Cylc? + + +Cylc and Cycling Workflows +-------------------------- + +A *cycling workflow* is a repetitive process involving many interdependent +tasks. Cylc tasks wrap arbitrary applications: executable commands, +scripts, or programs. Example use cases include: + +- Processing many similar datasets, through a pipeline or graph of tasks +- Forecasting systems that generate new forecasts at regular intervals +- Splitting a long model run and associated processing tasks into many smaller runs +- Iterative tuning of model parameters by model, processing, and validation tasks + +Cycling systems were traditionally managed by repeat-running the single-cycle +workflow, finishing each new cycle before starting the next. Sometimes, however, +it can be much more efficient to run multiple cycles at once. Even in real time +forecasting systems that normally have a gap between cycles waiting on new +data, this can greatly speed catch up from delays or downtime. But it can't +be done if the workflow manager has a global loop that handles only one cycle +at a time and does not understand any intercycle dependence that may be present. + +.. important:: + + Cylc handles inter- and intra-cycle dependence equally, and it unrolls the + cycle loop to create a single non-cycling workflow of repeating tasks, each + with its own individual *cycle point*. + +.. image:: ../img/cycling.png + :align: center + +This removes the artificial barrier between cycles. Cylc tasks can advance +constrained only by their individual dependencies, for maximum concurrency +across as well as within cycles. This allows fast catch-up from delays in +real time systems, and sustained high throughput off the clock. + + +How to Run User Guide Examples +------------------------------ + +Many Cylc concepts and features in this document are illustrated with minimal +snippets of workflow configuration. Most of these can be turned into a complete +workflow that you can actually run, with a few easy steps: + +- Add scheduling section headings, if missing, above the graph +- Use ``[scheduler]allow implicit tasks = True`` to automatically create dummy definitions + for each task +- Configure the ``root`` task family to make the dummy jobs take a little time + to run, so the workflow doesn't evolve too quickly +- For cycling graphs, configure an initial cycle point to start at + +For example, here is a small cycling workflow graph: + +.. code-block:: cylc-graph + + # Avoid caffeine withdrawal + PT6H = "grind_beans => make_coffee => drink_coffee" + +And here it is as a complete runnable workflow: + +.. code-block:: cylc + + [scheduler] + allow implicit tasks = True + [scheduling] + initial cycle point = now + [[graph]] + # Avoid caffeine withdrawal + PT6H = "grind_beans => make_coffee => drink_coffee" + [runtime] + [[root]] + script = "sleep 10" diff --git a/nightly_8.4/html/_sources/user-guide/removing-workflows.rst.txt b/nightly_8.4/html/_sources/user-guide/removing-workflows.rst.txt new file mode 100644 index 00000000000..3286f5b5a51 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/removing-workflows.rst.txt @@ -0,0 +1,117 @@ +.. _Removing-workflows: + +Removing Workflows +================== + +To delete an installed workflow :term:`run directory`, we recommend using +the ``cylc clean`` command. ``cylc clean`` takes care of deleting workflows +on the local filesystem and any remote install targets. +It follows any symlink directories specified in +:cylc:conf:`global.cylc[install][symlink dirs]` +(see :ref:`CleanSymlinkDirsNote` below). You can also use ``cylc clean`` to +just delete certain files or subdirectories (see :ref:`TargetedClean` below). + +If you've used ``rose suite-clean`` before, the functionality is similar, but +not identical. + +.. note:: + + ``cylc clean`` only affects workflow :term:`run directories ` + (located in the :term:`cylc-run directory`). It will not affect + workflow :term:`source directories `. + +.. warning:: + + ``cylc clean`` is intended for use on workflows installed with + ``cylc install``. If you clean a workflow that was instead written + directly in the cylc-run directory and not backed up elsewhere, + it will be lost. + +Simple example of using ``cylc clean``: + +.. code-block:: console + + $ cylc clean myflow/run1 + INFO - Removing directory: ~/cylc-run/myflow/run1 + + +Cleaning on remote install targets +---------------------------------- + +If any jobs in your workflow ran on a remote :term:`platform`, Cylc will +automatically remove the workflow files on there in addition to the local +filesystem. + +.. code-block:: console + + $ cylc clean remote-example + INFO - Cleaning on install target: enterprise1701 + INFO - [enterprise1701] + INFO - Removing directory: /home/user/cylc-run/remote-example/run1 + INFO - Removing directory: ~/cylc-run/remote-example/run1 + +.. note:: + + This relies on determining which platforms were used from the workflow + database. If the platforms recorded in the database are out of date with + the global configuration, or if the database is missing altogether, you will + have to manually remove the files on remote install targets. + +You can also clean on just the local filesystem using the ``--local`` option, +or just the remote install target using the ``--remote`` option. + + +.. _TargetedClean: + +Cleaning specific subdirectories or files +----------------------------------------- + +You can clean specific subdirectories or files inside a run directory using +the ``--rm`` option (we refer to this as a targeted clean). +For example, to remove the ``log`` and ``work`` directories: + +.. code-block:: console + + $ cylc clean myflow --rm log --rm work + +Colons can be used to delimit the items to clean, so the following is +equivalent: + +.. code-block:: console + + $ cylc clean myflow --rm log:work + +You can also use globs. E.g., to remove all job logs for cycle points +beginning with ``2020``: + +.. code-block:: console + + $ cylc clean myflow --rm 'log/job/2020*' + +.. note:: + + Make sure to place glob patterns in quotes. + +.. _CleanSymlinkDirsNote: + +A note on symlink directories +----------------------------- + +.. admonition:: Does this affect me? + :class: tip + + If you use symlink directories specified in + :cylc:conf:`global.cylc[install][symlink dirs]`, you might want to read + this explanation of how Cylc handles them during cleaning. + +If you manually delete a run directory (e.g., using the ``rm`` command or the +file manager), only the symlinks themselves will be deleted, not the actual +targets. In contrast, ``cylc clean`` follows the symlinks and deletes the +targets. + +- It only does this for the symlinks that can be set in + :cylc:conf:`global.cylc[install][symlink dirs]`, not any custom + user-created symlinks. +- It does not actually look up the global configuration at time of cleaning; + it simply detects what symlinks are present out of the possible ones. +- It also does this for targeted clean (using the ``--rm`` option). diff --git a/nightly_8.4/html/_sources/user-guide/running-workflows/authentication-files.rst.txt b/nightly_8.4/html/_sources/user-guide/running-workflows/authentication-files.rst.txt new file mode 100644 index 00000000000..e34f80e641b --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/running-workflows/authentication-files.rst.txt @@ -0,0 +1,54 @@ + +.. _ConnectionAuthentication: + +Client-Server Interaction +------------------------- + +:term:`Schedulers ` listen on dedicated network ports for +TCP communications from Cylc clients (jobs and user-invoked commands). + +Use ``cylc scan`` to see which workflows are listening on which ports on +scanned hosts. + +Cylc generates public-private key pairs on the workflow server and job hosts +which are used for authentication. + + +.. _Authentication Files: + +Authentication Files +-------------------- + +Cylc uses `CurveZMQ`_ to ensure that +any data, sent between the :term:`scheduler ` and the client, +remains protected during transmission. Public keys are used to encrypt the +data, private keys for decryption. + +Authentication files will be created in your +``$HOME/cylc-run//.service/`` directory at start-up. You can +expect to find one client public key per file system for remote jobs. + +On the workflow host, the directory structure should contain: + +.. code-block:: none + + ~/cylc-run/workflow_x + `-- .service + |-- client_public_keys + | |-- client_localhost.key + | `-- + |-- client.key_secret + |-- server.key + `-- server.key_secret + +On the remote job host, the directory structure should contain: + +.. code-block:: none + + ~/cylc-run/workflow_x + `-- .service + |-- client.key + |-- client.key_secret + `-- server.key + +Keys are removed as soon as they are no longer required. diff --git a/nightly_8.4/html/_sources/user-guide/running-workflows/dynamic-behaviour.rst.txt b/nightly_8.4/html/_sources/user-guide/running-workflows/dynamic-behaviour.rst.txt new file mode 100644 index 00000000000..0b892513b3a --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/running-workflows/dynamic-behaviour.rst.txt @@ -0,0 +1,21 @@ +.. _cylc-broadcast: + +Cylc Broadcast +-------------- + +The ``cylc broadcast`` command overrides task :cylc:conf:`[runtime]` +settings in a running scheduler. You can think of it as communicating +new configuration settings (including information via environment variables) to +selected upcoming tasks via the scheduler. + +See ``cylc broadcast --help`` for detailed information. + +Broadcast settings targeting a specific cycle point expire as the workflow +moves on. Otherwise they persist for lifetime of the run, and across restarts, +unless cleared with another invocation of the command. + +.. seealso:: + + :ref:`broadcast-tutorial` + +.. TODO: document sub-workflows diff --git a/nightly_8.4/html/_sources/user-guide/running-workflows/handling-job-preemption.rst.txt b/nightly_8.4/html/_sources/user-guide/running-workflows/handling-job-preemption.rst.txt new file mode 100644 index 00000000000..b37063992e9 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/running-workflows/handling-job-preemption.rst.txt @@ -0,0 +1,20 @@ +.. _PreemptionHPC: + +Handling Job Preemption +----------------------- + +Some HPC facilities allow job preemption: the resource manager can kill +or suspend running low priority jobs in order to make way for high +priority jobs. The preempted jobs may then be automatically restarted +by the resource manager, from the same point (if suspended) or requeued +to run again from the start (if killed). + +Suspended jobs will poll as still running (their job status file says they +started running, and they still appear in the resource manager queue). +Loadleveler jobs that are preempted by kill-and-requeue ("job vacation") are +automatically returned to the submitted state by Cylc. This is possible +because Loadleveler sends the SIGUSR1 signal before SIGKILL for preemption. +Other :term:`job runners ` just send SIGTERM before SIGKILL as normal, so Cylc +cannot distinguish a preemption job kill from a normal job kill. After this the +job will poll as failed (correctly, because it was killed, and the job status +file records that). diff --git a/nightly_8.4/html/_sources/user-guide/running-workflows/index.rst.txt b/nightly_8.4/html/_sources/user-guide/running-workflows/index.rst.txt new file mode 100644 index 00000000000..18665c24c13 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/running-workflows/index.rst.txt @@ -0,0 +1,20 @@ +.. _RunningWorkflows: + +Running Workflows +================= + +.. toctree:: + :maxdepth: 2 + + scheduler-start-up + tasks-jobs-ui + retrying-tasks + tracking-task-state + workflow-completion + reflow + simulation-modes + scheduler-log-files + dynamic-behaviour + authentication-files + workflow-databases + handling-job-preemption diff --git a/nightly_8.4/html/_sources/user-guide/running-workflows/reflow.rst.txt b/nightly_8.4/html/_sources/user-guide/running-workflows/reflow.rst.txt new file mode 100644 index 00000000000..0f7dc7b1227 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/running-workflows/reflow.rst.txt @@ -0,0 +1,233 @@ +.. _user-guide-reflow: + +Concurrent Flows +================ + +.. versionadded:: 8.0.0 + +In Cylc, a *flow* is a single self-consistent run through the workflow +:term:`graph` from some initial task(s). + +As a flow advances, upcoming tasks run only if they have not already run in +the same flow. + +At start-up the :term:`scheduler` automatically triggers the first flow from +the start of the graph. + +By default, manually triggered tasks "belong to" the existing flow(s), but you +can also choose to start new flows by triggering tasks anywhere in the graph. + +.. note:: + A flow does not have to be contiguous in the graph because different graph + branches can evolve at different rates, and tasks can be manually triggered + anywhere in the graph. + +See :ref:`below` for uses, and an +:ref:`example`, of concurrent flows. + +.. note:: + Flows :ref:`merge` where (and if) tasks collide in the ``n=0`` + :term:`active window`. Downstream of a merge, tasks are considered to belong + to all of their constituent flows. + + +Flow Numbers +------------ + +Flows are identified by numbers passed down from parent task to child task in +the graph. + +Flow number ``1`` is triggered automatically by ``cylc play`` at :term:`scheduler` +start-up. The next flow started by :ref:`manual triggering` +gets the number ``2``, then ``3``, and so on. + +Tasks can carry multiple flow numbers as a result of :ref:`flow +merging`. + +.. note:: + Flow numbers are not yet exposed in the UI, but they are logged with task + events in the :term:`scheduler log`. + + +.. _triggering-flows: + +Triggering & Flows +------------------ + +By default, manual triggering (with ``cylc trigger`` or the UI) starts a new +:term:`front of activity` in current flows. +But it can also start new flows and trigger flow-independent single tasks. + +In the diagrams below, the grey tasks run in the original flow (``1``), and the +blue ones run as a result of a manual triggering event. They may be triggered +as part of flow ``1``, or as a new flow ``2``, or with no flow number. + +Triggering in Current Flows + ``cylc trigger [--wait] ID`` + + This is the default action. The triggered task gets all current active flow + numbers. Subsequently, each of those flows will consider the task to have + run already. + + **Ahead of active flows** this starts a new front of activity for the + existing flows, which by default can continue on without waiting for them to + catch up: + + .. image:: ../../img/same-flow-n.png + + With ``--wait``, action downstream of the triggered task is delayed until + the first flow catches up: + + .. image:: ../../img/same-flow-wait-n.png + + **Behind active flows** the triggered task will run, but nothing more will + happen if any of the original flows already passed by there: + + .. image:: ../../img/same-flow-behind.png + +Triggering in Specific Flows + ``cylc trigger --flow=1,2 ID`` + + This triggers the task with flow numbers ``1`` and ``2``. + + The result is like the default above, except that tasks in the new front + belong only to the specified flow(s), regardless of which flows are + :term:`active` at triggering time. + +Triggering a New Flow + ``cylc trigger --flow=new ID`` + + This triggers the task with a new, incremented flow number. + + The new flow will re-run tasks that already ran in previous flows: + + .. image:: ../../img/new-flow-n.png + + +Triggering a Flow-Independent Single Task + ``cylc trigger --flow=none ID`` + + This triggers a task with no flow numbers. + + It will not spawn children, and other flows that come by will re-run it. + + .. image:: ../../img/no-flow-n.png + +Triggering with No Active Flows + ``cylc trigger [--wait] ID`` + + By default, triggered tasks will be given the flow numbers of the most + recent active task. This can happen, for instance, if you restart a + completed workflow and then trigger a task in it. The result will be the + same as if you had triggered the task just before the workflow completed. + +Special Case: Triggering ``n=0`` Tasks + Tasks in the ``n=0`` window are :term:`active tasks `. + Their flow membership is already determined - that of + the parent tasks that spawned them. + + - Triggering a task with a submitted or running job has no effect + (it is already triggered). + - Triggering other :term:`n=0 tasks `, including tasks with + :term:`incomplete outputs ` queues them to run in + the flow that they already belong to. + + +.. _flow-merging: + +Flow Merging in ``n=0`` +----------------------- + +If a task spawning into the :term:`n=0 window ` finds another instance +of itself (same task ID) already there, the two will merge and carry both +(sets of) flow numbers forward. Downstream tasks will belong to both flows. + +Flow merging is necessary because :term:`active ` task IDs +must be unique. + +If the original task instance has a :term:`final status` (and has been retained +in the :term:`n=0 window ` with +:term:`incomplete outputs `) the merged task will be reset to +run again without manual intervention. + + +Stopping Flows +-------------- + +By default, ``cylc stop`` halts the workflow and shuts the scheduler down. + +It can also stop specific flows: ``cylc stop --flow=N`` removes the flow number +``N`` from :term:`active tasks `. Tasks that have no flow +numbers left as a result do not spawn children at all. If there are no active +flows left, the scheduler shuts down. + +.. TODO update this section post https://github.com/cylc/cylc-flow/issues/4741 + + +.. _flow-trigger-use-cases: + +Some Use Cases +-------------- + +Running Tasks Ahead of Time + To run a task within the existing flow(s) even though its prerequisites are + not yet satisfied, just trigger it. Use ``--wait`` if you don't want the new + flow front to continue immediately. Triggered task(s) will not re-run when + the main front catches up. + +Regenerating Outputs Behind a Flow + To re-run a sub-graph (e.g. because the original run was affected by a + corrupt file), just trigger the task(s) at the top of the sub-graph with + ``--flow=new``. + + You may need to manually stop the new flow if it leads into the main trunk + of the graph, and you do not want it to carry on indefinitely. + +Rewinding a Workflow + To rewind the workflow to an earlier point, perhaps to regenerate data and/or + allow the workflow to evolve a new path into the future, trigger a new + flow at the right place and then stop the original flow. + +Test-running Tasks in a Live Workflow + You can trigger individual tasks as many times as you like with + ``--flow=none``, without affecting the workflow. The task :term:`submit + number` will increment each time. + +Processing Flow-Specific Data? + :term:`Flow numbers` are passed to job environments, so it is + possible for tasks to process flow-specific data. Every task would have to + be capable of processing multiple datasets at once, however, in case of + :term:`flow merging`. Generally, you should use :term:`cycling` + for this kind of use case. + +.. _new-flow-example: + +Example: Rerun a Sub-Graph +--------------------------- + +The following :term:`cycling workflow` runs a :term:`task` called ``model`` in +every cycle, followed by a postprocessing task, two product-generating tasks, +and finally a task that publishes results for the cycle point: + +.. code-block:: cylc + + [scheduling] + cycling mode = integer + initial cycle point = 1 + [[graph]] + P1 = model[-P1] => model => post => prod1 & prod2 => publish + +Let's say the workflow has run to cycle 8, but we have just noticed that +a corrupted ancillary file resulted in bad products at cycle 5. + +To rectify this we could fix the corrupted file and trigger a new flow at +``5/post``: + +.. code-block:: cylc + + cylc trigger --flow=new //5/post + +The new flow will regenerate and republish cycle 5 products before naturally +coming to a halt, because the triggered tasks do not feed into the next cycle. + +Meanwhile, the original flow will carry on unaffected, from cycle point 8. diff --git a/nightly_8.4/html/_sources/user-guide/running-workflows/retrying-tasks.rst.txt b/nightly_8.4/html/_sources/user-guide/running-workflows/retrying-tasks.rst.txt new file mode 100644 index 00000000000..363f5b1cfeb --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/running-workflows/retrying-tasks.rst.txt @@ -0,0 +1,50 @@ +Retrying Tasks +============== + +.. versionchanged:: 8.0.0 + +Tasks that fail but are configured to :term:`retry` return to the ``waiting`` +state, with a new clock trigger to handle the configured retry delay. + +.. note:: + + A task that is waiting on a retry will already have one or more failed jobs + associated with it. + + +.. note:: + + Tasks only enter the ``submit-failed`` state if job submission fails with no + retries left. Otherwise they return to the waiting state, to wait on the + next try. + + Tasks only enter the ``failed`` state if job execution fails with no retries + left. Otherwise they return to the waiting state, to wait on the next try. + + + +Aborting a Retry Sequence +------------------------- + +To prevent a waiting task from retrying, remove it from the scheduler's +:term:`active window`. For a task ``3/foo`` in workflow ``brew``: + +.. code-block:: console + + $ cylc remove brew//3/foo + +If you *kill* a running task that has more retries configured, it goes to the +``held`` state so you can decide whether to release it and continue the retry +sequence, or remove it. + +.. code-block:: console + + $ cylc kill brew//3/foo # 3/foo goes to held state post kill + $ cylc release brew//3/foo # release to continue retrying... + $ cylc remove brew//3/foo # ... OR remove the task to stop retries + + +If you want trigger downstream tasks despite ``3/foo`` being removed before it +could succeed, use ``cylc set`` to artificially mark its ``succeeded`` +output as complete (and with the ``--flow`` option, to make the :term:`flow` +continue on from there). diff --git a/nightly_8.4/html/_sources/user-guide/running-workflows/scheduler-log-files.rst.txt b/nightly_8.4/html/_sources/user-guide/running-workflows/scheduler-log-files.rst.txt new file mode 100644 index 00000000000..62ebc190b1a --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/running-workflows/scheduler-log-files.rst.txt @@ -0,0 +1,67 @@ +.. _Scheduler Logs: + +Scheduler Logs +-------------- + +Each workflow maintains its own log of time-stamped events in the +:term:`workflow log directory` (``$HOME/cylc-run//log/scheduler/``). + +The information logged here includes: + +- Event timestamps, at the start of each line +- Workflow server host, port and process ID +- Workflow initial and final cycle points +- Workflow (re)start number (1 for the first play, 2 or more for restarts) +- Task events (task started, succeeded, failed, etc.) +- Workflow stalled warnings. +- Client commands (e.g. ``cylc hold``) +- Job IDs. +- Information relating to the remote file installation is contained in a + separate log file, which can be found in + ``$HOME/cylc-run//log/remote-install/``. + +.. note:: + + Workflow log files are primarily intended for human eyes. If you need + to have an external system to monitor workflow events automatically, use: + + * Event hooks (see :cylc:conf:`flow.cylc[scheduler][events]` and + :cylc:conf:`flow.cylc[runtime][][events]`). + * The GraphQL interface (can be accessed via GraphiQL in the Cylc GUI). + * The sqlite *workflow run database* + (see :ref:`Workflow Run Databases`) + + Rather than parse the log files. + + +.. _scheduler Logs.Cylc message: + +Cylc Message +^^^^^^^^^^^^ + +The Scheduler Log also records messages sent by ``cylc message`` allowing you +to add custom messages to this log. + +For example, if your task contained the following code: + +.. code-block:: shell + + cylc message -- "ERROR:some_function failed." + +Your log should produce output similar to: + +.. code-block:: none + + ERROR - [21491012T0410Z/mytask running job:01 flows:1] (received)some_function failed ERROR at 2023-04-14T11:36:35+01:00 + +Severity levels are the same as those used by +`Python's logger `_: + +- CRITICAL +- ERROR +- WARNING +- INFO +- DEBUG + +Messages logged at "DEBUG" will only appear in the scheduler log if the +workflow is played with ``cylc play --debug``. diff --git a/nightly_8.4/html/_sources/user-guide/running-workflows/scheduler-start-up.rst.txt b/nightly_8.4/html/_sources/user-guide/running-workflows/scheduler-start-up.rst.txt new file mode 100644 index 00000000000..9882a3612ca --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/running-workflows/scheduler-start-up.rst.txt @@ -0,0 +1,297 @@ +.. _WorkflowStartUp: + +Start, Restart, Reload +====================== + +The ``cylc play`` command starts a new instance of the Cylc scheduler program +to manage a workflow, for the duration of the run. It also resumes paused +workflows. + +There are several ways to start a workflow that is not running: + +* ``cylc play`` **from the initial cycle point** + + - This is the default for a workflow that has not run yet + - The ``initial cycle point`` is taken from ``flow.cylc`` or the command line + - Dependence on earlier tasks is ignored, for convenience + - (In Cylc 7, this was called a *cold start*) + + +* ``cylc play --start-cycle-point=POINT`` **from a later start cycle point** + + - This is an option for a workflow that has not run yet + - The start point must be given on the command line + - Dependence on earlier tasks is ignored, for convenience + - The initial cycle point value defined in :cylc:conf:`flow.cylc` is preserved + - (In Cylc 7, this was called a *warm start*) + + +* ``cylc play --start-task=TASK-ID`` **from any task(s) in the graph** + + - This is an option for a workflow that has not run yet + - The start task(s) must be given on the command line + - The flow will follow the graph onward from the start task(s) + - (In Cylc 7, this was not possible) + - (This makes Cylc 7 restart-from-checkpoint obsolete) + + +* ``cylc play`` to **restart from previous state** + + - This is automatic for a workflow that previously ran + - The scheduler will carry on from exactly where it got to before + - At start-up, it will automatically find out what happened to any active + tasks that were orphaned during shutdown + - Failed tasks are not automatically resubmitted at restart, in case the + underlying problem has not been addressed + - (In Cylc 7, this used the now-obsolete restart command) + + +.. note:: + + If a workflow gets stopped or killed it can be restarted, but to avoid + corrupting an existing run directory it cannot be started again from scratch + (unless you delete certain files from the run directory). To start from + scratch again, install a new copy of the workflow to a new run directory. + +.. seealso:: + * :ref:`Installing-workflows` + +.. _start_stop_cycle_point: + +Start and Stop vs Initial and Final Cycle Points +------------------------------------------------ + +All workflows have an :term:`initial cycle point` and some may have a +:term:`final cycle point`. These define extent of the graph of tasks that Cylc +can schedule to run. + +Start and stop cycle points, if used, define a sub-section of the graph that +the scheduler actually does run. For example: + +.. code-block:: cylc + + [scheduling] + cycling mode = integer + initial cycle point = 1 + final cycle point = 5 + [[graph]] + # every cycle: 1, 2, 3, 4, 5 + P1 = foo + # every other cycle: 1, 3, 5 + P2 = bar + +With a :term:`start cycle point` of ``2`` and a :term:`stop cycle point` of +``4``, the task ``foo`` would run at cycles 2, 3 & 4 and the task ``bar`` +would only run at cycle ``3``. + +.. image:: ../../img/initial-start-stop-final-cp.svg + :align: center + + +Restarts and the Initial, Final, Start and Stop Cycle Points +------------------------------------------------------------ + +.. cylc-scope:: flow.cylc + +When a workflow is restarted or reloaded, any changes to +:cylc:conf:`[scheduling]final cycle point` or +:cylc:conf:`[scheduling]stop after cycle point` are normally picked up by Cylc. + +However, this is not the case if you used the ``--final-cycle-point`` or +``--stop-cycle-point`` options in a prior run. If you use either of these +options, the values you specify are stored in the workflow database, so the +original values will be used if you restart the workflow later on. +You can override these original values using the options again, and the new +value will persist over restarts. Or, you can pick up the workflow config +values by passing ``reload`` to the options +(e.g. ``--final-cycle-point=reload``); this will remove the stored value from +the database so future restarts will go back to picking up any changes +to the config. + +.. note:: + + If the workflow reached the final cycle point and shut down, it is finished + and cannot be restarted; the ``--final-cycle-point`` option will have + no effect. + +The ``--initial-cycle-point`` and ``--start-cycle-point`` options cannot be used +in a restart; workflows always start from the cycle point where they +previously stopped. + +.. cylc-scope:: + + +.. _Reloading The Workflow Configuration At Runtime: + +Reloading the Workflow Configuration at Runtime +----------------------------------------------- + +The ``cylc reload`` command tells the target :term:`scheduler` to reload its +workflow configuration at run time. This is an alternative to shutting a +workflow down and restarting it after making changes. + +.. note:: + If writing your workflows in a :term:`source directory`, then be sure to + :ref:`reinstall ` your changes to the + :term:`run directory` before doing a reload. + +If you make an error in the ``flow.cylc`` file before a reload, the workflow +log will report an error and the reload will have no effect. + +Note, :ref:`RemoteInit` will be redone for each job platform, when the first +job is submitted there after a reload. + + +.. _user-guide.restarting-or-reloading-after-graph-changes: + +Restarting or Reloading after Graph Changes +------------------------------------------- + +If dependencies have changed, tasks that were already active will spawn +children according to their original outputs. Subsequent instances will have +the new settings. + +If tasks were removed from the graph, any active instances will be left to +finish, but they will not spawn children. They can be removed manually if +necessary, with ``cylc remove``. + +If new tasks were added to the graph, instances will be spawned automatically +as upstream tasks complete the outputs that they depend on. If they have no +parents to do that, you can trigger the first ones manually with ``cylc trigger``. + + +.. _RemoteInit: + +Remote Initialization +--------------------- + +For workflows that run on remote platforms, i.e. using a host other than +``localhost``, Cylc performs an initialization process. This involves transferring +files and directories required to run jobs, including authentication keys +(see :ref:`Authentication Files` for more information). + +The default directories included in the remote install are: + +``ana/`` + For workflow-level :ref:`builtin.rose_ana` analysis modules. +``app/`` + For :ref:`Rose Applications`. +``bin/`` + For scripts and executables to be run by tasks. +``etc/`` + For miscellaneous resources. +``lib/`` + For shared libraries e.g. :ref:`CustomJinja2Filters`. + +These will be transferred from the workflow run directory on the +:term:`scheduler` host to the remote host. +In addition, custom file and directories configured in +:cylc:conf:`flow.cylc[scheduler]install` will be included in the transfer. + +This remote initialization process also creates symlinks on the remote +platform, if these are configured using +:cylc:conf:`global.cylc[install][symlink dirs]`. This provides a +way to manage disk space. + + +A log file is created on the scheduler to report information relating to the +remote file installation process. There will be a separate log created per install +target. These can be found in ``$HOME/cylc-run//log/remote-install/``. + +Installing Custom Files At Start-up +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Cylc supports adding custom directories and files to the file installation. + +If, for example, you wished to install directories ``dir1``, ``dir2``, and +files ``file1``, ``file2``, add the following configuration to your +:cylc:conf:`flow.cylc`, under the section +:cylc:conf:`[scheduler]install`. +To mark an item as a directory, add a trailing slash. + +.. code-block:: cylc + + [scheduler] + install = dir1/, dir2/, file1, file2 + +.. note:: + + Ensure files and directories to be installed are located in the top + level of your workflow. + +Install tasks are preferred for time-consuming installations because +they don't slow the workflow start-up process, they can be monitored, +they can run directly on target platforms, and you can rerun them later without +restarting the workflow. + +.. note:: + + Files configured for installation to remote job platforms can be reinstalled by doing a reload. The reinstallation is done when the first job submits to a platform after the reload. + +Troubleshooting +^^^^^^^^^^^^^^^ + +There are certain scenarios where remote initialization may fail. Cylc will return +a ``REMOTE INIT FAILED`` message. + +Timeout +""""""" + +Remote initialization has a timeout set at 10 minutes, after which remote +initialization will fail. If you have particularly large files files to +transfer, which you expect to exceed the 10 minute timeout, consider using an +install task in your workflow. + +Misconfiguration +"""""""""""""""" + +Platforms must be correctly configured to ensure authentication keys, which are +responsible for secure communication between the :term:`scheduler` and the +platform, are correctly in place. +Sites can configure these platforms, insuring they match up with the correct +install target. Cylc uses install targets as a way of recognising which platforms +share the same file system. For more information, see :ref:`Install Targets`. + + + +Files created at workflow start +------------------------------- + +Configuration Logs +^^^^^^^^^^^^^^^^^^ + +A folder ``log/config`` is created where the workflow configuration is +recorded, with all templating expanded: + +- ``flow-processed.cylc`` - A record of the current workflow configuration + with templating expanded, but without being fully parsed: Duplicate sections + will not be merged. +- ``-`` - A record of the config at + the time a workflow was started, restarted or reloaded, parsed by Cylc: + Duplicate sections will be merged. + +.. note:: + + These are particularly useful files to look at if the workflow + configuration contains many template variables, to see how they are + filled in. + + +.. _The Workflow Contact File: + +The Workflow Contact File +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The :term:`scheduler` writes a :term:`contact file` at +``$HOME/cylc-run//.service/contact`` that records workflow host, +user, port number, process ID, Cylc version, and other information. Client +commands read this file to find the :term:`scheduler`. + +The contact file gets removed automatically at shutdown (assuming the +scheduler shuts down cleanly). + + +Authentication Files +^^^^^^^^^^^^^^^^^^^^ + +See :ref:`Authentication Files`. diff --git a/nightly_8.4/html/_sources/user-guide/running-workflows/simulation-modes.rst.txt b/nightly_8.4/html/_sources/user-guide/running-workflows/simulation-modes.rst.txt new file mode 100644 index 00000000000..d7f08914ed5 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/running-workflows/simulation-modes.rst.txt @@ -0,0 +1,101 @@ +.. _SimulationMode: + +Simulation Modes +---------------- + +Cylc can run a workflow without running the real jobs, which may be +long-running and resource-hungry. + +**Dummy mode** replaces real jobs with background ``sleep`` jobs on the +scheduler host. This avoids :term:`job runner` directives that request compute +resources for real workflow tasks, and it allows any workflow configuration to +be run locally in dummy mode. + +.. code-block:: console + + $ cylc play --mode=dummy # real dummy jobs + +.. note:: + + All configured task ``script`` items including ``init-script`` are ignored + in dummy mode. If your ``init-script`` is required to run even local dummy + jobs, the relevant environment setup should be done elsewhere. + + +**Simulation mode** does not run real jobs at all, and does not generate job +log files. + +.. code-block:: console + + $ cylc play --mode=simulation # no real jobs + + +Simulated Run Length +^^^^^^^^^^^^^^^^^^^^ + +The default dummy or simulated job run length is 10 seconds. It can be +changed with :cylc:conf:`[runtime][][simulation]default run length`. + +If :cylc:conf:`[runtime][]execution time limit` and +:cylc:conf:`[runtime][][simulation]speedup factor` are both set, +run length is computed by dividing the time limit by the speedup factor. + + +Simulated Failure +^^^^^^^^^^^^^^^^^ + +Tasks always complete custom outputs, by default they succeed. + +.. warning:: + + In simulation mode a succeeded output may not imply that + submitted and/or started outputs are generated - so you will not + be able to test graph pathways such as ``task:started => do_something``. + +You can set some or all instances of a task to fail using +:cylc:conf:`[runtime][][simulation]fail cycle points`. +``fail cycle points`` takes either a list of cycle point strings or "all". + +Tasks set to fail will succeed on their second or following simulated +submission. If you want all submissions to fail, set +:cylc:conf:`[runtime][][simulation]fail try 1 only = False`. + +For example, to simulate a task you know to be flaky on the half +hour but not on the hour: + +.. code-block:: cylc + + [[get_observations]] + execution retry delays = PT30S + [[[simulation]]] + fail cycle points = 2022-01-01T00:30Z, 2022-01-01T01:30Z + +In another case you might not expect the retry to work, and want to test +whether your failure handling works correctly: + +.. code-block:: cylc + + [[get_data]] + execution retry delays = PT30S + [[[simulation]]] + fail try 1 only = false + fail cycle points = 2022-01-01T03:00Z + +Limitations +^^^^^^^^^^^ + +Dummy tasks run locally, so dummy mode does not test communication with remote +job platforms. However, it is easy to write a live-mode test workflow with +simple ``sleep 10`` tasks that submit to a remote platform. + +Alternate path branching is difficult to simulate effectively. You can +configure certain tasks to fail via +:cylc:conf:`[runtime][][simulation]`, but all branches based +on mutually exclusive custom outputs will run because all custom outputs get +artificially completed in dummy mode and in simulation mode. + +.. note:: + + Run mode is recorded in the workflow run database. Cylc will not let you + *restart* a dummy mode workflow in live mode, or vice versa. Instead, + install a new instance of the workflow and run it from scratch in the new mode. diff --git a/nightly_8.4/html/_sources/user-guide/running-workflows/tasks-jobs-ui.rst.txt b/nightly_8.4/html/_sources/user-guide/running-workflows/tasks-jobs-ui.rst.txt new file mode 100644 index 00000000000..813c16bfd6f --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/running-workflows/tasks-jobs-ui.rst.txt @@ -0,0 +1,153 @@ +.. _task-job-states: + +Tasks in the GUI/Tui +==================== + +Task & Job States +----------------- + +**Tasks** are a workflow abstraction; they represent future and past jobs as +well as current active jobs. In the Cylc UI, task states have monochromatic +icons like this: |task-running|. + +**Jobs** represent real job scripts submitted to run +on a :term:`job platform`. In the Cylc UI, job states have coloured icons like +this: |job-running|. + +A single task can have multiple jobs, by automatic retry or manual triggering. + + +.. table:: + + ============== ==================== =================== ==================================== + State Task Icon Job Icon Description + ============== ==================== =================== ==================================== + waiting |task-waiting| waiting on prerequisites + preparing |task-preparing| job being prepared for submission + submitted |task-submitted| |job-submitted| job submitted + running |task-running| |job-running| job running + succeeded |task-succeeded| |job-succeeded| job succeeded + failed |task-failed| |job-failed| job failed + submit-failed |task-submit-failed| |job-submit-failed| job submission failed + expired |task-expired| will not submit job (too far behind) + ============== ==================== =================== ==================================== + +The running task icon contains a clock face which shows the time elapsed +as a proportion of the average runtime. + +.. image:: ../../img/task-job-icons/task-running-0.png + :width: 50px + :height: 50px + :align: left + +.. image:: ../../img/task-job-icons/task-running-25.png + :width: 50px + :height: 50px + :align: left + +.. image:: ../../img/task-job-icons/task-running-50.png + :width: 50px + :height: 50px + :align: left + +.. image:: ../../img/task-job-icons/task-running-75.png + :width: 50px + :height: 50px + :align: left + +.. image:: ../../img/task-job-icons/task-running-100.png + :width: 50px + :height: 50px + :align: left + +.. NOTE: these pipe characters are functional! They create a line break. + +| + +| + + +Task Modifiers +-------------- + +Tasks are run as soon as their dependencies are satisfied, however, there are +some other conditions which can prevent tasks from being run. These are +given "modifier" icons which appear to the top-left of the task icon: + +.. list-table:: + :class: grid-table + :align: left + :widths: 20, 80 + + * - .. image:: ../../img/task-job-icons/task-isHeld.png + :width: 60px + :height: 60px + - **Held:** Task has been manually :term:`held ` back from + running. + * - .. image:: ../../img/task-job-icons/task-isRunahead.png + :width: 60px + :height: 60px + - **Runahead:** Task is held back by the :term:`runahead limit`. + * - .. image:: ../../img/task-job-icons/task-isQueued.png + :width: 60px + :height: 60px + - **Queued:** Task has been held back by an :term:`internal queue`. + + + +.. _n-window: + +The "n" Window +-------------- + +.. versionchanged:: 8.0.0 + +Cylc workflow :term:`graphs ` can be very large, even infinite for +:term:`cycling workflows ` with no :term:`final cycle point`. + +Consequently the GUI often can't display "all of the tasks" at once. Instead +it displays all :term:`active tasks ` (e.g. running tasks) +as well as any tasks which are a configurable number of tasks away from +them in the task dependency :term:`graph`. + +.. image:: ../../img/n-window.png + :align: center + + +n=0: + The ``n=0`` window contains :term:`active tasks `. An active + task is a task which is near ready to run, in the process of running, or + which requires user intervention (see the :term:`glossary ` + for a more detailed description). +n=1: + The ``n=1`` window contains all "active tasks" as well as any tasks one + "edge" out from them, i.e. their dependencies (the tasks that come immediately + before them in the graph) and their descendants (the tasks that come + immediately after them in the graph). +n=2: + The ``n=2`` window contains all "active tasks" as well as any tasks *two* + edges out from them, and so on. + +This animation shows how the n-window advances as a workflow runs, tasks are +colour coded according to their n-window value with the colours changing from +``n=0`` (blue) to ``n=8`` (pink): + +.. image:: ../../img/n-window.gif + :align: center + +| + +By default the GUI/Tui displays the ``n=1`` window. You can change this using +the "Set Graph Window Extent" command which is currently only available in the +GUI. + +.. note:: + + The "graph window extent" is a property of the workflow not a property of + the GUI so persists between sessions. Better visibility and easier control + over the n-window are planned in future releases of Cylc. + +.. warning:: + + High "graph window extent" values can cause a Cylc scheduler and the GUI + to run slowly. diff --git a/nightly_8.4/html/_sources/user-guide/running-workflows/tracking-task-state.rst.txt b/nightly_8.4/html/_sources/user-guide/running-workflows/tracking-task-state.rst.txt new file mode 100644 index 00000000000..a73c11abd8a --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/running-workflows/tracking-task-state.rst.txt @@ -0,0 +1,122 @@ +.. _TaskComms: + +Tracking Job Status +------------------- + +Cylc supports three ways of tracking task state on job hosts: + +- task-to-scheduler messaging via TCP (using ZMQ protocol) +- task-to-scheduler messaging via non-interactive SSH to the workflow host, then + local TCP. +- regular polling by the :term:`scheduler` + +These can be configured per platform using +:cylc:conf:`global.cylc[platforms][]communication method`. + +If your site prohibits TCP and SSH back from job hosts to workflow hosts, +before resorting to the polling method you should consider installing dedicated +Cylc servers or VMs inside the HPC trust zone (where TCP and SSH should be +allowed). + +It is possible to run Cylc :term:`schedulers ` on HPC login nodes, +but be aware of scheduler resource requirements (which depend on workflow size +and run duration). + +Port forwarding could potentially provide another solution, but the idea has +been rejected at this stage. Organisations often disable port forwarding for +security reasons. + +.. note:: + Use Cylc 8 platform configuration via + :cylc:conf:`flow.cylc[runtime][]platform`, not the + deprecated ``host`` setting, to ensure the intended task communication + method is applied. + +TCP Task Messaging +^^^^^^^^^^^^^^^^^^ + +Cylc :term:`job scripts ` automatically invoke ``cylc message`` to +report progress back to the :term:`scheduler` when they begin executing, at +normal exit (success) and abnormal exit (failure). + +By default job status messaging goes by an authenticated TCP connection to the +:term:`scheduler`, using the ZMQ protocol. This is the preferred task +communications method because it is efficient and direct. + +Schedulers automatically install workflow :term:`contact information +` and credentials on job hosts. + + +.. obsolete? Users only need to do this manually for remote access to workflows + on other hosts, or workflows owned by other users - see :ref:`RemoteControl`. + + +SSH Task Communication +^^^^^^^^^^^^^^^^^^^^^^ + +Cylc can be configured to re-invoke task messaging commands on the workflow +host via non-interactive SSH (from job platform to workflow host). + +User-invoked client commands also support this communication method, when +:cylc:conf:`global.cylc[platforms][]communication method` is +configured to ``ssh``. + +This is less efficient than direct ZMQ protocol messaging, but it may be useful at +sites where the ZMQ ports are blocked but non-interactive SSH is allowed. + +.. warning:: + + Ensure SSH keys are in place for the remote task platform(s) before enabling + this feature. Failure to do so, will result in ``Host key verification + failed`` errors. + + +.. _Polling To Track Job Status: + +Polling to Track Job Status +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Schedulers can actively poll jobs at configured intervals, via +non-interactive SSH to the job platform. + +This is the least efficient communication method because task status updates +are delayed by up to the polling interval. However, it may be needed at sites +that do not allow TCP or non-interactive SSH from job host to workflow host. + +Be careful to avoid spamming task hosts with polling operations. Each poll +opens (and then closes) a new SSH connection. + +Polling intervals are configured by +:cylc:conf: +`global.cylc[platforms][]submission polling intervals` +and +:cylc:conf: +`global.cylc[platforms][]execution polling intervals`. + +A common use case is to poll: + +- frequently at first, to check that a job has started running properly; +- frequently near the expected end of its run time, to get a timely task finished update; +- infrequently in the intervening period. + +Configured intervals are used in sequence until +the last value, which is used repeatedly until the job is finished: + +.. code-block:: cylc + :caption: global.cylc + + [platforms] + [[my_platform]] + # poll every minute in the 'submitted' state: + submission polling intervals = PT1M + + # poll one minute after foo starts running, then every 10 + # minutes for 50 minutes, then every minute until finished: + execution polling intervals = PT1M, 5*PT10M, PT1M + +.. code-block:: cylc + :caption: flow.cylc + + [runtime] + [[task]] + platform = my_platform diff --git a/nightly_8.4/html/_sources/user-guide/running-workflows/workflow-completion.rst.txt b/nightly_8.4/html/_sources/user-guide/running-workflows/workflow-completion.rst.txt new file mode 100644 index 00000000000..147dca239c0 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/running-workflows/workflow-completion.rst.txt @@ -0,0 +1,48 @@ +.. _workflow completion: + +Workflow Completion +=================== + +A workflow is complete, and the scheduler will automatically +:term:`shut down `, if no tasks remain in the +:term:`n=0 `. + +That is, all active tasks have finished, and no tasks remain waiting on +:term:`prerequisites ` or "external" constraints (such as +:term:`xtriggers ` or task :term:`hold`). + +If no active tasks remain and all external constraints are satisfied, +but the n=0 window contains tasks waiting with partially satisfied +:term:`prerequisites `, or tasks with :term:`final status` and +:term:`incomplete outputs `, then the workflow is +not complete and the scheduler will :term:`stall` pending manual intervention. + + +.. _scheduler stall: + +Scheduler Stall +=============== + +A stalled workflow has not run to :term:`completion ` +but cannot continue without manual intervention. + +A stalled scheduler stays alive for a configurable timeout period +pending manual intervention. If it shuts down (on the stall timeout +or otherwise) it will remain in the stalled state on restart. + +Stalls are often caused by unexpected task failures, either directly (tasks +with :term:`final status` and :term:`incomplete outputs `) +or indirectly (tasks with partially satisfied :term:`prerequisites `, +downstream of an unexpected failure). + +.. warning:: + + At present you have to consult the :term:`scheduler log` to see the reason + for a stall. + + +.. seealso:: + + * :cylc:conf:`[scheduler][events]stall timeout` + * :cylc:conf:`[scheduler][events]abort on stall timeout` + * :cylc:conf:`[scheduler][events]stall handlers` diff --git a/nightly_8.4/html/_sources/user-guide/running-workflows/workflow-databases.rst.txt b/nightly_8.4/html/_sources/user-guide/running-workflows/workflow-databases.rst.txt new file mode 100644 index 00000000000..5c0cf4f28e1 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/running-workflows/workflow-databases.rst.txt @@ -0,0 +1,45 @@ +.. _Workflow Run Databases: + +Workflow Run Databases +---------------------- + +Schedulers maintain two ``sqlite`` databases to record +information on run history: + +.. code-block:: console + + $HOME/cylc-run//log/db # public workflow DB + $HOME/cylc-run//.service/db # private workflow DB + +The private DB is for use only by the :term:`scheduler`. The identical +public DB is provided for use by external commands such as +``cylc workflow-state``, and ``cylc report-timings``. +If the public DB gets locked for too long by +an external reader, the :term:`scheduler` will eventually delete it and +replace it with a new copy of the private DB, to ensure that both correctly +reflect the workflow state. + +You can interrogate the public DB with the ``sqlite3`` command line tool, +the ``sqlite3`` module in the Python standard library, or any other +sqlite interface. + +.. code-block:: console + + $ sqlite3 ~/cylc-run/foo/log/db << _END_ + > .headers on + > select * from task_events where name is "foo"; + > _END_ + name|cycle|time|submit_num|event|message + foo|1|2017-03-12T11:06:09Z|1|submitted| + foo|1|2017-03-12T11:06:09Z|1|output completed|started + foo|1|2017-03-12T11:06:09Z|1|started| + foo|1|2017-03-12T11:06:19Z|1|output completed|succeeded + foo|1|2017-03-12T11:06:19Z|1|succeeded| + +The diagram shown below contains the database tables, their columns, +and how the tables are related to each other. For more details on how +to interpret the diagram, refer to the +`Entity–relationship model Wikipedia article `_. + +.. cylc-db-graph:: + :align: center diff --git a/nightly_8.4/html/_sources/user-guide/task-implementation/index.rst.txt b/nightly_8.4/html/_sources/user-guide/task-implementation/index.rst.txt new file mode 100644 index 00000000000..4e161367589 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/task-implementation/index.rst.txt @@ -0,0 +1,18 @@ +Task Implementation +------------------- + +This section covers the technical detail of how Cylc runs :term:`tasks `. + +In Cylc :term:`tasks ` represent activities within the workflow. +:term:`Tasks ` submit :term:`jobs ` when they are run. + +Tasks are the "abstract" workflow component. Jobs are the concrete +representation of a task. One task could submit many jobs (for example if the +job fails and the task is re-run). + +.. toctree:: + :maxdepth: 2 + + job-scripts + job-submission + ssh-job-management diff --git a/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.at.rst.txt b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.at.rst.txt new file mode 100644 index 00000000000..d8995767516 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.at.rst.txt @@ -0,0 +1,4 @@ +at +== + +.. automodule:: cylc.flow.job_runner_handlers.at \ No newline at end of file diff --git a/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.background.rst.txt b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.background.rst.txt new file mode 100644 index 00000000000..9bdaafe2c03 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.background.rst.txt @@ -0,0 +1,4 @@ +background +========== + +.. automodule:: cylc.flow.job_runner_handlers.background \ No newline at end of file diff --git a/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.loadleveler.rst.txt b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.loadleveler.rst.txt new file mode 100644 index 00000000000..a291f686d2d --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.loadleveler.rst.txt @@ -0,0 +1,4 @@ +loadleveler +=========== + +.. automodule:: cylc.flow.job_runner_handlers.loadleveler \ No newline at end of file diff --git a/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.lsf.rst.txt b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.lsf.rst.txt new file mode 100644 index 00000000000..f5df61a6a4c --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.lsf.rst.txt @@ -0,0 +1,4 @@ +lsf +=== + +.. automodule:: cylc.flow.job_runner_handlers.lsf \ No newline at end of file diff --git a/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.moab.rst.txt b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.moab.rst.txt new file mode 100644 index 00000000000..daa9e10de28 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.moab.rst.txt @@ -0,0 +1,4 @@ +moab +==== + +.. automodule:: cylc.flow.job_runner_handlers.moab \ No newline at end of file diff --git a/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.pbs.rst.txt b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.pbs.rst.txt new file mode 100644 index 00000000000..b7cff4ca9b8 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.pbs.rst.txt @@ -0,0 +1,4 @@ +pbs +=== + +.. automodule:: cylc.flow.job_runner_handlers.pbs \ No newline at end of file diff --git a/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.sge.rst.txt b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.sge.rst.txt new file mode 100644 index 00000000000..d8b1e11e9cd --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.sge.rst.txt @@ -0,0 +1,4 @@ +sge +=== + +.. automodule:: cylc.flow.job_runner_handlers.sge \ No newline at end of file diff --git a/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm.rst.txt b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm.rst.txt new file mode 100644 index 00000000000..bed789bf008 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm.rst.txt @@ -0,0 +1,4 @@ +slurm +===== + +.. automodule:: cylc.flow.job_runner_handlers.slurm \ No newline at end of file diff --git a/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm_packjob.rst.txt b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm_packjob.rst.txt new file mode 100644 index 00000000000..266d11a8fd5 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm_packjob.rst.txt @@ -0,0 +1,4 @@ +slurm\_packjob +============== + +.. automodule:: cylc.flow.job_runner_handlers.slurm_packjob \ No newline at end of file diff --git a/nightly_8.4/html/_sources/user-guide/task-implementation/job-scripts.rst.txt b/nightly_8.4/html/_sources/user-guide/task-implementation/job-scripts.rst.txt new file mode 100644 index 00000000000..ea53520864d --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/task-implementation/job-scripts.rst.txt @@ -0,0 +1,301 @@ +.. _TaskImplementation: + +Task Implementation +=================== + +Existing scripts and executables can be used as Cylc tasks without +modification so long as they return standard exit status - zero on success, +non-zero for failure - and do not spawn detaching processes internally (see +:ref:`DetachingJobs`). + + +.. _JobScripts: + +Job Scripts +----------- + +When the :term:`scheduler` determines that a task is ready to run it +generates a *job script* for the task, and submits it to run (see +:ref:`TaskJobSubmission`). + +.. cylc-scope:: flow.cylc[runtime][] + +:term:`Job scripts ` encapsulate configured task runtime settings: +:cylc:conf:`script` and :cylc:conf:`[environment]` items, if defined, are just +concatenated in the order shown below, to make the job script. + +The job script is separated into two parts. User scripts and environment +(:cylc:conf:`env-script`, :cylc:conf:`[environment]`, :cylc:conf:`pre-script`, +:cylc:conf:`script` and :cylc:conf:`post-script`) are isolated and executed in +a separate subshell process. Any changes to environment, traps, etc., done in +any of them are visible in subsequent parts, but will not interfere with the +parent shell process. This parent shell executes and shares environment with +:cylc:conf:`init-script`, :cylc:conf:`exit-script` and :cylc:conf:`err-script`. +In particular, any environment changes in :cylc:conf:`init-script` will be +visible in the parent shell, as well as in the subshell hosting user scripts. + +The parent shell sets trap handlers for some signals (the exact list depends on +a particular batch system being used) and typically resends any received signal +to the subshell and its children (the whole process group, to be precise), unless +the batch system doesn't execute the job script as process leader, in which case +the signal is resent to the subshell process only. Immediately after that +:cylc:conf:`err-script` is executed without waiting for the subshell process to +finish, unless you start it with the ``wait`` command to prevent that. + +.. digraph:: example + + rankdir="TB" + packmode="array_u"; + + subgraph cluster_legend { + style="dashed" + label="Legend" + + "user defined script" + "cylc defined script" [shape="rect"] + + "user defined script" -> "cylc defined script" [style="invis"] + } + + subgraph cluster_diagram { + style="invis" + margin=20 + + "cylc-env" [shape="rect"] + "user-env" [shape="rect"] + + "init-script" -> + "cylc-env" -> + "env-script" + + subgraph cluster_subshell { + style="dashed" + label="Subshell process" + + "env-script" -> + "user-env" -> + "pre-script" -> + "script" -> + "post-script" + } + + "post-script" -> "err-script" + "post-script" -> "exit-script" + } + +The two "Cylc defined scripts" are: + +``cylc-env`` + Which provides default ``CYLC_*`` environment variables e.g. + ``CYLC_TASK_NAME``. +``user-env`` + Which is the contents of the :cylc:conf:`[environment]` section. + +Job scripts are written to the workflow's job log directory. They can be +printed with ``cylc cat-log``. + +.. cylc-scope:: + + +Inlined Tasks +------------- + +Task *script* items can be multi-line strings of ``bash`` code, so many tasks +can be entirely inlined in the :cylc:conf:`flow.cylc` file. + +For anything more than a few lines of code, however, we recommend using +external shell scripts to allow independent testing, re-use, and shell mode +editing. + + +Interpreter +----------- + +The job script (which incorporates the ``*-script`` items) runs in the +``bash`` interpreter. + +Cylc searches for ``bash`` in the ``$PATH`` by first running a login bash +shell which means you can choose the bash interpreter used by modifying +the ``$PATH`` in your bash configuration files (e.g. ``.bashrc``). + + +Task Messages +------------- + +Jobs send status messages back to the :term:`scheduler` to report that +execution has started, succeeded, or failed. Custom messages can also be sent +by the same mechanism, with various severity levels. These can be used to +trigger other tasks off specific task outputs (see :ref:`MessageTriggers`), or +to trigger execution of event handlers by the scheduler (see +:ref:`user_guide.runtime.task_event_handling`) +or just to write information to the scheduler log. + +.. cylc-scope:: global.cylc[platforms][] + +(If polling is configured as the :cylc:conf:`communication method` for a +:cylc:conf:`platform <[..]>`, the messaging system just writes messages to the +local job status file for recovery by the scheduler at the next poll). + +.. cylc-scope:: + +Normal severity messages are printed to ``job.out`` and logged by the scheduler: + +.. code-block:: bash + + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \ + "Hello from ${CYLC_TASK_ID}" + +"CUSTOM" severity messages are printed to ``job.out``, logged by the +:term:`scheduler`, and can be used to trigger *custom* +event handlers: + +.. code-block:: bash + + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \ + "CUSTOM:data available for ${CYLC_TASK_CYCLE_POINT}" + +These can be used to signal special events that are neither routine +information nor an error condition, such as production of a particular data +file (a "data availability" event). + +"WARNING" severity messages are printed to ``job.err``, logged by the +:term:`scheduler`, and can be passed to *warning* event handlers: + +.. code-block:: bash + + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \ + "WARNING:Uh-oh, something's not right here." + +"CRITICAL" severity messages are printed to ``job.err``, logged by the +:term:`scheduler`, and can be passed to *critical* event handlers: + +.. code-block:: bash + + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \ + "CRITICAL:ERROR occurred in process X!" + +Jobs no longer (since Cylc 8) attempt to resend messages if the server +cannot be reached. Send failures normally imply a network or Cylc +configuration problem that will not recover by itself, in which case a series +of messaging retries just holds up job completion unnecessarily. If a job +status message does not get through, the server will recover the correct task +status by polling on job timeout (or earlier if regular polling is +configured). + +Task messages are validated by: + +.. autoclass:: cylc.flow.unicode_rules.TaskMessageValidator + :noindex: + +.. _job-scripts.aborting-on-error: + +Aborting Job Scripts on Error +----------------------------- + +Job scripts use ``set -e`` to abort on any error, and trap ERR, EXIT, and +SIGTERM to send task failed messages back to the :term:`scheduler` before +aborting. Other scripts called from job scripts should therefore abort with +standard non-zero exit status on error, to trigger the job script error trap. + +To prevent a command that is expected to generate a non-zero exit status from +triggering the exit trap, protect it with a control statement such as: + +.. code-block:: bash + + if cmp FILE1 FILE2; then + : # success: do stuff + else + : # failure: do other stuff + fi + +Job scripts also use ``set -u`` to abort on referencing any +undefined variable (useful for picking up typos); and ``set -o pipefail`` +to abort if any part of a pipe fails (by default the shell only returns the +exit status of the final command in a pipeline). + + +Custom Failure Messages +^^^^^^^^^^^^^^^^^^^^^^^ + +Critical events normally warrant aborting a job script rather than just +sending a message. As described just above, ``exit 1`` or any failing command +not protected by the surrounding scripting will cause a job script to abort +and report failure to the :term:`scheduler`, potentially triggering a +*failed* task event handler. + +For failures detected by the scripting you could send a critical message back +before aborting, potentially triggering a *critical* task event handler: + +.. code-block:: bash + + if ! /bin/false; then + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \ + "CRITICAL:ERROR: /bin/false failed!" + exit 1 + fi + +To abort a job script with a custom message that can be passed to a +*failed* task event handler, use the built-in ``cylc__job_abort`` shell +function: + +.. code-block:: bash + + if ! /bin/false; then + cylc__job_abort "ERROR: /bin/false failed!" + fi + + +.. _DetachingJobs: + +Avoid Detaching Processes +------------------------- + +If a task script starts background sub-processes and does not wait on them, or +internally submits jobs to a :term:`job runner` and then exits immediately, the +detached processes will not be visible to Cylc and the task will appear to +finish when the top-level script finishes. You will need to modify scripts +like this to make them execute all sub-processes in the foreground (or use the +shell ``wait`` command to wait on them before exiting) and to prevent job +submission commands from returning before the job completes (e.g. +``llsubmit -s`` for Loadleveler, +``qsub -sync yes`` for Sun Grid Engine, and +``qsub -W block=true`` for PBS). + +If this is not possible - perhaps you don't have control over the script +or can't work out how to fix it - one alternative approach is to use another +task to repeatedly poll for the results of the detached processes: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = "model => checker => post-proc" + [runtime] + [[model]] + # Uh-oh, this script does an internal job submission to run model.exe: + script = "run-model.sh" + [[checker]] + # Fail and retry every minute (for 10 tries at the most) if model's + # job.done indicator file does not exist yet. + script = "[[ ! -f $RUN_DIR/job.done ]] && exit 1" + execution retry delays = 10 * PT1M + + +.. _PipeInJobScripts: + +Use of Pipes in Job Scripts +--------------------------- + +In bash, the return status of a pipeline is normally the exit status of the +last command. This is unsafe, because if any command in the pipeline fails, the +script will continue nevertheless. + +For safety, a Cylc job script running in bash will have the +``set -o pipefail`` option turned on automatically. If a pipeline +exists in a task's ``script``, etc section, the failure of any part of +a pipeline will cause the command to return a non-zero code at the end, which +will be reported as a job failure. Due to the unique nature of a pipeline, +the job file will trap the failure of the individual commands, as well as the +whole pipeline, and will attempt to report a failure back to the workflow twice. +The second message is ignored by the workflow, and so the behaviour can be safely +ignored. (You should probably still investigate the failure, however!) diff --git a/nightly_8.4/html/_sources/user-guide/task-implementation/job-submission.rst.txt b/nightly_8.4/html/_sources/user-guide/task-implementation/job-submission.rst.txt new file mode 100644 index 00000000000..07a3bbe2e79 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/task-implementation/job-submission.rst.txt @@ -0,0 +1,315 @@ +.. _TaskJobSubmission: + +Job Submission and Management +============================= + +This section explains how the Cylc scheduler submits :term:`jobs ` +when they are ready to run, and how to define new :term:`job runner` handlers. + +.. note:: + + For the requirements a command, script, or program, must fulfil in order to + function as a Cylc task, see :ref:`TaskImplementation`. + +When a task is ready Cylc generates a :term:`job script` (see :ref:`JobScripts`). +The job script is submitted to be run by the job runner from the +:term:`platform` chosen for the task. +Like other runtime properties, you can set a workflow default platform and +override it for specific tasks or families: + +.. code-block:: cylc + + [runtime] + [[root]] # workflow defaults + platform = platform_with_loadleveler + [[foo]] # just task foo + platform = platform_with_at + + +.. _AvailableMethods: + +Supported Job Submission Methods +-------------------------------- + +Cylc provided built-in support for the following batch submission systems: + +.. NOTE this builds and links stub-pages for each of the job runners + +.. automodule:: cylc.flow.job_runner_handlers + +See :ref:`CustomJobSubmissionMethods` for how to add new job +submission methods. + +Default Directives Provided +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For :term:`job runners ` that use job file directives (PBS, Loadleveler, +etc.) default directives are provided to set the job name, stdout and stderr +file paths, and the execution time limit (if specified). + +.. tip:: + + Use :cylc:conf:`[runtime][]execution time limit` to set + time limits, rather than setting this as a directive yourself. + + This allows Cylc to identify execution timeout even if the + job runner cannot be contacted. + + See :ref:`ExecutionTimeLimit` + +Cylc constructs the job name string using a combination of the task ID and the +workflow name. PBS fails a job submit if the job name in ``-N name`` is +too long. For version 12 or below, this is 15 characters. For version 13, this +is 236 characters. The default setting will truncate the job name string to 236 +characters. If you have PBS 12 or older at your site, you should modify your +site's global configuration file to allow the job name to be truncated at 15 +characters using +:cylc:conf:`global.cylc[platforms][]job name length maximum`. + +Directives Section Quirks (PBS, SGE, ...) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To specify an option with no argument, such as ``-V`` in PBS or +``-cwd`` in SGE you must give a null string as the directive value in +the :cylc:conf:`flow.cylc` file. + +The left hand side of a setting (i.e. the string before the first equal sign) +must be unique. To specify multiple values using an option such as +``-l`` option in PBS, SGE, etc., either specify all items in a single +line: + +.. code-block:: none + + -l=select=28:ncpus=36:mpiprocs=18:ompthreads=2 + +(Left hand side is ``-l``. A second ``-l=...`` line will override the first.) + +Or separate the items: + +.. code-block:: none + + -l select=28 + -l ncpus=36 + -l mpiprocs=18 + -l ompthreads=2 + +.. note:: + + There is no equal sign after ``-l``. + +(Left hand sides are now ``-l select``, ``-l ncpus``, etc.) + + +.. _WhitherStdoutAndStderr: + +Task stdout and stderr Logs +--------------------------- + +When a task is ready to run Cylc generates a filename root to be used +for the job script and log files. The file path contains the task +name, cycle point, and a submit number that increments if the same task is +re-triggered multiple times: + +.. code-block:: sub + + # job script: + ~/cylc-run/my-workflow/basic/log/job/1/hello/01/job + # stdout: + ~/cylc-run/my-workflow/basic/log/job/1/hello/01/job.out + # stderr: + ~/cylc-run/my-workflow/basic/log/job/1/hello/01/job.err + +How the stdout and stderr streams are directed into these files depends on the +:term:`job runner`. The +:py:mod:`background ` method just +uses appropriate output redirection on the command line, as shown above. The +:py:mod:`loadleveler ` method writes +appropriate directives to the job script that is submitted to loadleveler. + +Cylc obviously has no control over the stdout and stderr output from +tasks that do their own internal output management (e.g. tasks +that submit internal jobs and direct the associated output to other +files). For less internally complex tasks, however, the files referred +to here will be complete job logs. + +Some job runners, such as :py:mod:`PBS `, +redirect a job's stdout +and stderr streams to a separate cache area while the job is running. The +contents are only copied to the normal locations when the job completes. This +means that ``cylc cat-log`` will be unable to find the +job's stdout and stderr streams while the job is running. Some sites with these +job runners are known to provide commands for viewing and/or +tail-follow a job's stdout and stderr streams that are redirected to these +cache areas. If this is the case at your site, you can configure Cylc to make +use of the provided commands by adding some settings to the global site/user +config. E.g.: + +.. TODO - re-write this example when default directives arrive for platforms + +.. code-block:: cylc + + [hosts] + [[HOST]] # <= replace this with a real host name + [[[batch systems]]] + [[[[pbs]]]] + err tailer = qcat -f -e \%(job_id)s + out tailer = qcat -f -o \%(job_id)s + err viewer = qcat -e \%(job_id)s + out viewer = qcat -o \%(job_id)s + + +.. _CommandTemplate: + +Overriding The Job Submission Command +------------------------------------- + +To change the form of the actual command used to submit a job you +need to define a new +:cylc:conf:`global.cylc[platforms][]job runner command template`. + +.. code-block:: cylc + + [platform] + [[my_custom_platform]] + hosts = host1, host2 + job runner = loadleveler + # Use '-s' to stop llsubmit returning + # until all job steps have completed: + job runner command template = llsubmit -s %(job)s + +The template's ``%(job)s`` will be substituted by the job file path. + + +Job Polling +----------- + +For supported :term:`job runners `, jobs can be *polled* to +check that their true state matches what the scheduler expects based on received +job status messages or previous polls. The :term:`scheduler` executes a process +on the task host, by non-interactive ssh, to interrogate the job runner, and to +read the ``job.status`` file of the task which is automatically generated by the +:term:`job script` as it runs. + +Polling may be required to update the workflow state correctly after unusual +events such as + +- a job gets killed by the untrappable SIGKILL signal (e.g. ``kill -9 PID``) +- a machine being rebooted with tasks running on it +- network problems prevent task messages from getting back to the workflow host +- the :term:`scheduler` itself was down when active jobs finished + +Tasks can be polled on demand by using the +``cylc poll`` command. + +.. seealso:: + - ``cylc poll --help`` + +Tasks are polled automatically, once, if they timeout while queueing in a +job runner and submission timeout is set. +(See :cylc:conf:`[runtime][][events]` +for how to configure timeouts). + +Tasks are polled multiple times, where necessary, when they exceed their +execution time limits. These are normally set with some initial delays to allow +the job runners to kill the jobs. +(See +:cylc:conf:`execution time limit polling intervals ]execution time limit polling intervals>` +for how to configure the polling intervals). + +Any tasks recorded in the *submitted* or *running* states at workflow +restart are automatically polled to determine what happened to them while the +workflow was down. + +By default, regular polling also takes place every 15 minutes whilst a job is +submitted or running. The default polling intervals can be overridden in the +global configuration: + +* :cylc:conf:`global.cylc[platforms][]submission polling intervals` +* :cylc:conf:`global.cylc[platforms][]execution polling intervals` + +The polling intervals can also be configured for individual tasks: + +* :cylc:conf:`[runtime][]submission polling intervals` +* :cylc:conf:`[runtime][]execution polling intervals` + +Polling can be used as the sole method of determining task status on hosts that +do not allow task messages to be routed back to the workflow host. +See :ref:`Polling To Track Job Status`. + +.. note:: + + For polling to work correctly, the job runner queueing system must have a + job listing command for listing your jobs, and that the job listing must + display job IDs as they are returned by the job runner queueing system submit + command. For example, for pbs, moab and sge, the ``qstat`` command + should list jobs with their IDs displayed in exactly the same format as they + are returned by the ``qsub`` command. + + +Job Killing +----------- + +For supported :term:`job runners `, the :term:`scheduler` can execute a process on +the task host, by non-interactive ssh, to kill a submitted or running job +according to its job runner. + +Tasks can be killed on demand by using the ``cylc kill`` command. + + +.. _ExecutionTimeLimit: + +Execution Time Limit +-------------------- + +.. cylc-scope:: flow.cylc[runtime][] + +You can specify an :cylc:conf:`execution time limit` for all supported job +submission methods. E.g.: + +.. code-block:: cylc + + [runtime] + [[task-x]] + execution time limit = PT1H + +For tasks running with +:py:mod:`background ` or +:py:mod:`at `, their jobs +will be wrapped using the ``timeout`` command. For all other methods, +the relevant time limit directive will be added to their job files. + +The :cylc:conf:`execution time limit` setting will also inform the workflow when a +a job should complete by. If a job has not reported completing within +the specified time, the workflow will poll the job. (The default +setting is ``PT1M, PT2M, PT7M``. The accumulated times for these intervals will be +roughly 1 minute, 1 + 2 = 3 minutes and 1 + 2 + 7 = 10 minutes after a job +exceeds its :cylc:conf:`execution time limit`.) + +.. cylc-scope:: + + +Execution Time Limit and Execution Timeout +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. cylc-scope:: flow.cylc[runtime][] + +If you specify an :cylc:conf:`execution time limit` the +execution timeout event handler will only be called if the job has +not completed after the final poll (by default, 10 min after the time limit). +This should only happen if the submission method you are using is not enforcing +wallclock limits (unlikely) or you are unable to contact the machine to confirm +the job status. + +If you specify an :cylc:conf:`[events]execution timeout` and not an +:cylc:conf:`execution time limit` then the +execution timeout event handler will be called as soon as the +specified time is reached. The job will also be polled to check its latest +status (possibly resulting in an update in its status and the calling of the +relevant event handler). This behaviour is deprecated, which users should avoid +using. + +If you specify an :cylc:conf:`[events]execution timeout` and an +:cylc:conf:`execution time limit` then the execution timeout setting will be +ignored. + +.. cylc-scope:: diff --git a/nightly_8.4/html/_sources/user-guide/task-implementation/ssh-job-management.rst.txt b/nightly_8.4/html/_sources/user-guide/task-implementation/ssh-job-management.rst.txt new file mode 100644 index 00000000000..f0a89ba20f5 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/task-implementation/ssh-job-management.rst.txt @@ -0,0 +1,65 @@ +Remote Job Management +===================== + +Managing tasks in a workflow requires more than just job execution: Cylc +performs additional actions with ``rsync`` for file transfer, and +direct execution of ``cylc`` sub-commands over non-interactive SSH. + + +SSH-free Job Management? +------------------------ + +Some sites may want to restrict access to job hosts by whitelisting SSH +connections to allow only ``rsync`` for file transfer, and allowing job +execution only via a local :term:`job runner` that sees the job hosts [1]_ . +We are investigating the feasibility of SSH-free job management when a local +job runner is available, but this is not yet possible unless your workflow +and job hosts also share a filesystem, which allows Cylc to treat jobs as +entirely local [2]_ . + + +SSH-based Job Management +------------------------ + +Cylc does not have persistent agent processes running on job hosts to act on +instructions received over the network [3]_ so instead we execute job +management commands directly on job hosts over SSH. Reasons for this include: + +- It works equally for :term:`job runner` and background jobs. +- SSH is *required* for background jobs, and for jobs in other job runners if the + job runner is not available on the workflow host. +- Querying the job runner alone is not sufficient for full job + polling functionality. + + - This is because jobs can complete (and then be forgotten by + the job runner) while the network, workflow host, or :term:`scheduler` is + down (e.g. between workflow shutdown and restart). + - To handle this we get the automatic job wrapper code to write + job messages and exit status to *job status files* that are + interrogated by :term:`schedulers ` during job polling + operations. + - Job status files reside on the job host, so the interrogation + is done over SSH. + +- Job status files also hold job runner name and job ID; this is + written by the job submit command, and read by job poll and kill commands + + +Other Cases Where Cylc Uses SSH Directly +---------------------------------------- + +.. TODO - do a scan through the codebase to assert that this is still the only + uses of SSH in Cylc Flow. + +- To see if a workflow is running on another host with a shared + filesystem - see ``cylc/flow/workflow_files:detect_old_contact_file``. + + +.. [1] A malicious script could be ``rsync``'d and run from a batch + job, but jobs in job runners are considered easier to audit. +.. [2] The job ID must also be valid to query and kill the job via the local + :term:`job runner`. This is not the case for Slurm, unless the + ``--cluster`` option is explicitly used in job query and kill commands, + otherwise the job ID is not recognized by the local Slurm instance. +.. [3] This would be a more complex solution, in terms of implementation, + administration, and security. diff --git a/nightly_8.4/html/_sources/user-guide/troubleshooting.rst.txt b/nightly_8.4/html/_sources/user-guide/troubleshooting.rst.txt new file mode 100644 index 00000000000..3de02da0360 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/troubleshooting.rst.txt @@ -0,0 +1,616 @@ +.. _troubleshooting: + +Troubleshooting +=============== + +.. Generate a local table of contents to make it easier to skim the entries on + this page. + +.. contents:: + :depth: 3 + :local: + :backlinks: none + + +.. _troubleshooting.log_files: + +Log Files +--------- + +If things have gone wrong and you're not sure why, there are few files which +you'll find in the workflow's :term:`run directory` that should contain the +required information to work out what's going on: + +``log/scheduler/log`` + There's a log file for each workflow in + ``~/cylc-run//log/scheduler/log``. + + This records all the essential information including every job submission + and task state change. + + You can view this in the GUI, Tui or on the command line using + ``cylc cat-log ``. +``job.err`` + This contains the stderr captured when the job ran. It's useful for + debugging job failures. + + You can view this in the GUI, Tui or on the command line using + ``cylc cat-log //// -f e``. +``job-activity.log`` + This file records the interaction Cylc has had with a job, namely submission + and polling. This can be useful in determining the cause of job submission + failures. + + You can view this in the GUI, Tui or on the command line using + ``cylc cat-log //// -f a``. + +Additionally, these directories contain extra information which can be useful +for debugging some specific issues: + +``log/install/`` + Contains logging from local workflow installation (e.g.``cylc install``). + + This can be useful for inspecting Rose file installation. +``log/remote-install/`` + Records information about file installation on remote platforms + (see :ref:`RemoteInit`). +``log/config/`` + Records the workflow configuration (and the Rose suite configuration if one + is used). + + These files can allow you to see how the configuration was changed between + restarts and reloads. + + Each time a workflow is started, restarted or reloaded, + the configuration used is recorded in a file in ``log/config``. + This provides a series of snapshots of the configuration. + These files are named: + + ``--<(RE)START NUMBER>``. + + If for example we did: + + .. code-block:: console + + # Command # File created + cylc play workflow # 01-start-01.cylc + cylc vr workflow # 02-reload-01.cylc + cylc stop workflow + cylc play workflow # 03-restart-02.cylc + + +Shell Login/Profile Files +------------------------- + +Cylc runs many commands using +`Bash login shells `_. + +This allows you to configure aspects of Cylc's behaviour using login files +such as ``.bash_profile`` and ``.bashrc``. + +However, it also means that the contents of these files can interfere with +Cylc (and potentially other systems too). + +If you have things in your login files which are only intended for use in +interactive terminal sessions, wrap them inside an ``if`` block so they only +run for interactive sessions like so: + +.. code-block:: bash + + if [[ $- == *i* ]]; then + # only run this for interactive (terminal) sessions + # (and not for non-interactive login sessions) + echo "Hello $USER" + alias rsync='rsync -v' + conda activate my_env + export PS1="\$ $(tput bold)[$PREFIX]$(tput sgr 0) " + fi + + # this runs for all sessions including non-interactive login sessions + export PATH="$HOME/bin:$PATH" + export MY_LIB_PATH="$HOME/my-lib/1.0/" + +Some things to check your login files for: + +* Don't write to stdout (e.g. using ``echo`` or ``printf``), this can interfere + with command output. +* Avoid loading modules or environments by default, you can create short cuts + for loading these using functions, aliases or commands. +* Don't add non-existent directories into your ``$PATH``, this can cause + commands to hang. +* Always prepend or append to ``$PATH``, never overwrite it. +* Don't override (i.e. clobber) standard commands with aliases, functions, + scripts or the like. This can prevent tools from being able to access the + original command. + + +Problems +-------- + + +Job Status Isn't Updating +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Cylc keeps track of a job's progress in one of two ways (according to how +the platform the job was submitted to is configured): + +* Jobs send messages to the scheduler (push). +* The scheduler polls jobs (pull). + +In either case, the job will also write its updates to the ``job.status`` file. + +This is what the ``job.status`` file should look like for a successful job, +note the ``SUCCEEDED`` line: + +.. code-block:: + + CYLC_JOB_RUNNER_NAME=background + CYLC_JOB_ID=12345 + CYLC_JOB_RUNNER_SUBMIT_TIME=2000-01-01T00:00:00 + CYLC_JOB_PID=108179 + CYLC_JOB_INIT_TIME=2000-01-01T00:10:00 + CYLC_JOB_EXIT=SUCCEEDED + CYLC_JOB_EXIT_TIME=2000-01-01T01:30:00 + +If the ``job.status`` file is showing something different to what the GUI or +Tui is showing, then... + +.. rubric:: If your platform uses push communication: + +If messages aren't getting back to the scheduler, there should be some +evidence of this in the ``job.err`` file, likely either an error or a +traceback. Likely causes: + +* There is a network issue. +* TCP ports are not open (zmq communications). +* Non-interactive SSH has not been correctly configured (ssh communications). + +.. rubric:: If your platform uses pull communication: + +Firstly, check the polling interval, it's possible that the scheduler has been +configured to poll infrequently and you need to wait for the next poll, or +request a poll manually using the ``cylc poll`` command (also available in the +GUI & Tui). + +Use the ``cylc config`` command to inspect the platform's configuration to +determine the configured polling schedule. + +Then check the ``job-activity.log`` file, there may have been a problem polling +the remote platform, e.g. a network or configuration error. + +Likely causes: + +* The platform is down (e.g. all login nodes are offline). +* There is a network issue. +* Non-interactive SSH has not been correctly configured. + + +My Job Submit-Failed +^^^^^^^^^^^^^^^^^^^^ + +A submit-failed job means one of three things: + +1. There is a Bash syntax error in the task configuration. + + E.G. the following ``script`` has a syntax error, it is missing a + ``"`` character after ``$WORLD``: + + .. code-block:: cylc + + [runtime] + [[foo]] + script = """ + echo "Hello $WORLD + """ + + This will result in a submission-failure which should appear in the + ``job-activity.log`` file (and also the scheduler log) something like this: + + .. code-block:: + + [jobs-submit cmd] (prepare job file) + [jobs-submit ret_code] 1 + [jobs-submit err] + /path/to/job.tmp: line 46: unexpected EOF while looking for matching `"' + /path/to/job.tmp: line 50: syntax error: unexpected end of file + +2. There was an error submitting the job to the specified platform (including + network issues). + + See the ``job-activity.log`` and the scheduler log. Diagnostic information + should be in one or both of those files. + +3. The platform is not correctly configured. + + See also :ref:`troubleshooting.remote_init_did_not_complete`. + + +.. _troubleshooting.my_job_failed: + +My Job Failed +^^^^^^^^^^^^^ + +This means something went wrong executing the job. +To find out more, see the ``job.err`` file. + +.. note:: + + To ensure Cylc jobs fail when they are supposed to, Cylc configures Bash + to be stricter than it is by default by running ``set -euo pipefail``. + + .. cylc-scope:: flow.cylc[runtime][] + + This only applies to scripts you've configured in the Cylc script + settings (i.e. `script`, `pre-script`, `post-script`, etc), not to any + Bash scripts to call *from* the job script. + + .. cylc-scope:: + +.. tip:: + + One particularly common issue when developing a workflow is failure + to make a script executable. Use ``ls -l`` to check. + +If you're struggling to track down the error, you might want to put the +workflow into debug mode:: + + cylc verbosity DEBUG + +When a workflow is running in debug mode, all jobs will create a ``job.xtrace`` +file when run in addition to ``job.err``. This can help you to locate the error +within the job script. + +You can also start workflows in debug mode:: + + cylc play --debug + + +My workflow shut down unexpectedly +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a Cylc scheduler shuts down, it should leave behind a log message explaining why. + +E.G. this message means that a workflow shut down because it was told to: + +.. code-block:: + + Workflow shutting down - REQUEST(CLEAN) + +If a workflow shut down due to a critical problem, you should find some +traceback in this log. If this traceback doesn't look like it comes from your +system, please report it to the Cylc developers for investigation (on +GitHub or Discourse). + +In some extreme cases, Cylc might not be able to write a log message e.g: + +* There's not enough disk space for Cylc to write a log message. +* If the scheduler was killed in a nasty way e.g. ``kill -9``. +* If the scheduler host goes down (e.g. power off). + +If the issue is external to the workflow, once the issue is resolved it should +be possible to restart it as you would normally using ``cylc play``. Cylc +will pick up where it left off. + + +Why isn't my task running? +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To find out why a task is not being run, use the ``cylc show`` command. +This will list the task's prerequisites and xtriggers. + +Note, at present ``cylc show`` can only display +:term:`active tasks `. Waiting tasks beyond the +:term:`n=0 window ` have no satisfied prerequisites. + +Note, tasks which are held |task-held| will not be run, use ``cylc release`` +to release a held task. + +Note, Cylc will not submit jobs if the scheduler is paused, use ``cylc play`` +to resume a paused workflow. + + +Required files are not being installed on remote platforms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Cylc installs selected workflow files onto remote platforms when the first task +submits to it. + +See :ref:`RemoteInit` for the list of directories installed and how to +configure them. + +If something has gone wrong during installation, an error should have been +logged a file in this directory: +``$HOME/cylc-run//log/remote-install/``. + +If you need to access files from a remote platform (e.g. 2-stage ``fcm_make``), +ensure that a task has submitted to it before you do so. If needed you can use +a blank "dummy" task to ensure that remote installation is completed *before* +you run any tasks which require this e.g: + +.. code-block:: cylc-graph + + dummy => fetch_files + + +Conda / Mamba environment activation fails +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some Conda packages rely on activation scripts which are run when you call the +activate command. + +Unfortunately, some of these scripts don't defend against command failure or +unset environment variables causing them to fail when configured in Cylc +``*script`` (see also :ref:`troubleshooting.my_job_failed` for details). + +To avoid this, run ``set +eu`` before activating your environment. This turns +off some Bash safety features, allowing environment activation to complete. +Remember to run ``set -eu`` afterwards to turn these features back on. + +.. code-block:: cylc + + [runtime] + [[my_task]] + script = """ + set +eu + conda activate + set -eu + + do-something + do-something-else + """ + + +Error Messages +-------------- + +Cylc should normally present you with a simple, short error message when things +go wrong. + +To see the full traceback, run the command / workflow in debug mode, e.g. using +the ``--debug`` option. + +If you are presented with traceback when you are *not* running in debug mode, +then this is not an expected error, please report the traceback to us. + + +``FileNotFoundError: No such file or directory`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This is the error message Python gives when you try to call an executable which +does not exist in the ``$PATH``. It means there's something wrong with the Cylc +installation, or something missing from the environment or system in which Cylc has been installed. + +E.G. the following error: + +.. code-block:: + + FileNotFoundError: [Errno 2] No such file or directory: 'ssh' + +Means that ``ssh`` is not installed or not in your ``$PATH``. + +See :ref:`non-python-requirements` for details on system requirements. + + +.. _troubleshooting.remote_init_did_not_complete: + +``platform: - initialisation did not complete`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This means that Cylc was unable to install the required workflow files onto +a remote platform. + +This either means that: + +1. The platform is down (e.g. all login nodes are offline). +2. Or, there is a network problem (e.g. you cannot connect to the login nodes). +3. Or, the platform is not correctly configured. + +Check the scheduler log, you might find some stderr associated with this +message. + +If your site has configured this platform for you, it's probably (1) or (2), +check you are able to access the platform and notify the site administrator as +appropriate. + +If you are in the progress of setting up a new platform, it's probably (3). +You might want to check that you've configured the +:cylc:conf:`global.cylc[platforms][]install target` correctly, +note that this defaults to the platform name if not explicitly set. + + +``OperationalError: disk I/O error`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This means that Cylc was unable to write to the database. + +This error usually occurs if when you have exceeded your filesystem quota. + +If a Cylc scheduler cannot write to the filesystem, it will shut down. Once +you've cleared out enough space for the workflow to continue you should be able +to safely restart it as you would normally using ``cylc play``. The workflow +will continue from where it left off. + + +``socket.gaierror`` +^^^^^^^^^^^^^^^^^^^ + +This usually means that a host could not be found on the network. The likely +cause is DNS configuration. + +Cylc is a distributed system so needs to be able to identify the hosts it has +been configured to use (e.g. the servers where you run Cylc workflows or any +login nodes you submit jobs to). +Cylc expects each host to have a unique and stable fully qualified domain name +(FQDN) and to be identifiable from other hosts on the network using this name. + +I.e., If a host identifies itself with an FQDN, then we should be able to look it +from another host by this FQDN. If we can't, then Cylc can't tell which host is +which and will not be able to function properly. + +If the FQDN of a host is reported differently from different hosts on the +network, then Cylc commands will likely fail. To fix the issue, ensure that the +DNS setup is consistent. + +Sometimes we do not have control over the platforms we use and it is not +possible to compel system administrators to address these issues. If this is +the case, you can fall back to IP address based host identification which may +work (i.e. use IP addresses rather than host names, which makes logs less human +readable). As a last resort you can also hard-code the host name for each host. + +For more information, see +:cylc:conf:`global.cylc[scheduler][host self-identification]`. + + +``failed/XCPU`` +^^^^^^^^^^^^^^^ + +``XCPU`` is the signal that most batch systems will use when a job hits its +execution time limit. + +Use :cylc:conf:`flow.cylc[runtime][]execution time limit` to +increase this limit. + + +``Cannot determine whether workflow is running on `` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When Cylc runs a workflow, it creates a :term:`contact file` which tells us on +which host and port it can be contacted. + +If the scheduler cannot be contacted, Cylc will attempt to check whether the +process is still running to ensure it hasn't crashed. + +If you are seeing this error message, it means that Cylc was unable to +determine whether the workflow is running. Likely cause: + +* SSH issues. +* Network issues. +* Cylc server is down. + +It's possible that this check might not work correctly in some containerised +environments. If you encounter this issue in combination with containers, +please let us know. + + +Debugging Workflow Configurations +--------------------------------- + +Cylc Debugging Utilities +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. seealso:: + + :ref:`user-guide.cheat_sheet` + + +Cylc comes with a number of utilities designed to allow inspection of +workflows: + +``cylc view`` + Prints workflow configurations before full parsing by Cylc. This + can include :ref:`Jinja2 ` (use ``-j``) + or Empy template processing. + + Include files can be inlined (use ``-i``). + +``cylc config`` + Prints all or part of the workflow configuration after Cylc has parsed the file + and expanded the runtime inheritance hierarchy. For example: + + .. code-block:: cylc + + [runtime] + [[root]] + execution time limit = PT5S + [[FAMILY]] + pre-script = sleep 15 + [[foo, bar]] + script = echo 'Hello' + [[bar]] + inherit = FAMILY + post-script = echo 'World' + + would be shown as (revealing in this example why task ``bar`` + always fails): + + .. code-block:: cylc + + [runtime] + [[root]] + execution time limit = PT5S + [[FAMILY]] + execution time limit = PT5S + pre-script = sleep 15 + [[foo]] + execution time limit = PT5S + script = echo 'Hello' + [[bar]] + execution time limit = PT5S + pre-script = sleep 15 + script = echo 'Hello' + inherit = FAMILY + post-script = echo 'World' + + +``cylc lint`` + #. Checks the config against the :ref:`style_guide`. + #. Looks for deprecated Cylc 7 configurations and recommends + Cylc 8 configurations to replace them. + + .. seealso:: + + :ref:`cylc_lint_script` + +``cylc validate`` + + Validates the workflow configuration. + + .. seealso:: + + :ref:`Validation` + +.. _troubleshooting.jinja2: + +See what the Jinja2 is doing +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It can sometimes be difficult to understand what Jinja2 +templating is doing to a workflow configuration. + +``cylc view --process`` (or ``-p``) shows you what the +configuration will look like after Jinja2 processing. + +For example: + +.. code-block:: + + {% for n in my_function(3) %} + R/1983/P{{n}}Y = cicada_{{n}}[-P{{n}}Y] => cicada_{{n}} + {% endfor %} + +is much easier to understand as: + +.. code-block:: cylc-graph + + R/1983/P2Y = cicada_2[-P2Y] => cicada_2 + R/1983/P3Y = cicada_3[-P3Y] => cicada_3 + R/1983/P5Y = cicada_5[-P5Y] => cicada_5 + +If you have installed and played a workflow +(even using ``play --pause``) this processed content +is shown in ``log/config/flow-processed.cylc``. + + +Getting Help +------------ + +If your site has deployed and configured Cylc for you and your issue appears +related to the platforms you are using or the Cylc setup, please contact your +site's administrator. + +For general Cylc issues, create a post on the Cylc `Discourse`_ forum. +Please include any relevant error messages, workflow configuration and sections +of logs to help us debug your issue. + +For Cylc / plugin development issues, you might prefer to contact us on the +`developer's chat `_. diff --git a/nightly_8.4/html/_sources/user-guide/writing-workflows/configuration.rst.txt b/nightly_8.4/html/_sources/user-guide/writing-workflows/configuration.rst.txt new file mode 100644 index 00000000000..fe0a9a5ad2f --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/writing-workflows/configuration.rst.txt @@ -0,0 +1,277 @@ +.. _User Guide Configuration: + +Workflow Configuration +====================== + +.. _FlowConfigFile: + +The ``flow.cylc`` File +---------------------- + +Cylc workflows are defined in :cylc:conf:`flow.cylc` files that specify the +tasks to be managed by the Cylc scheduler, the dependencies between them, +and the schedules to run them to. + +The ``.cylc`` file syntax is described in the :ref:`File Format Reference +`. + +The configurations you can use are documented in :ref:`workflow-configuration`. + +.. _template processors: https://en.wikipedia.org/wiki/Template_processor + +Cylc also supports two `template processors`_ for use in the ``flow.cylc`` file: + +* `Jinja2`_ +* `EmPy`_ + + +.. _WorkflowDefinitionDirectories: + +Workflow Configuration Directories +---------------------------------- + +A Cylc :term:`source directory` contains: + +:cylc:conf:`flow.cylc` + The file which configures the workflow. + +``bin/`` (optional) + A directory for scripts and executables used by workflow tasks. It is + added to ``$PATH`` in job environments. + + Jobs can also run scripting defined in the :cylc:conf:`flow.cylc` file, + executables installed to user-defined locations of the workflow run + directory, and external executables. + +``lib/python/`` (optional) + A directory for Python modules. It is added to ``$PYTHONPATH`` in + the scheduler and job execution environments. It can be used by: + + - Tasks + - Custom :ref:`job runners ` + - Custom :ref:`Jinja2 Filters` + +Other files and folders may be placed in the :term:`source directory` too: +documentation, configuration files, etc. When the workflow is :ref:`installed +` these will be copied over to the :term:`run directory`. + +.. note:: + + If your workflow needs to create or install scripts or executables at runtime + and you don't want Cylc to delete them on re-installation, you can use + equivalent directories in the :ref:`workflow_share_directories`. + + +.. _UnderstandingCodeInCylcConfigurations: + +Understanding Code in Workflow Configurations +--------------------------------------------- + +A workflow configuration is not executable code. It configures the scheduler +program to run your workflow. A `flow.cylc` file may contain: + +- Embedded Python-like Jinja2 or EmPy templating code, such as + ``{% set PLANET = "earth" %}`` +- Bash shell variable assignments and scripting, such as + ``script = "run-model.exe /path/to/data"`` + +Jinja2 (or EmPy) templating code gets executed as a preprocessing step, to +programmatically generate the workflow configuration for the scheduler. +To see the result after template processing: + +.. code-block:: shell + + # print the workflow configuration, processed but not parsed: + $ cylc view --process + + # print the workflow configuration, processed and parsed: + $ cylc config + + +The scheduler does not interpret shell syntax, but certain string-valued +config items may contain shell code that gets written verbatim to job scripts, +to be executed by the running job. + +Some things to be aware of: + +- Jinja2 code is evaluated once when the workflow is started. +- Jinja2 code can only reference Jinja2 variables, not Cylc config items. +- Jinja2 (like Python) has its own syntax for reading environment variables. +- Jinja2 code that reads the environment or the filesystem will do so + during config file parsing on the scheduler run host, not on job hosts. + Beware of doing this in task definitions - do you want the scheduler + environment to affect shell code that runs in the job environment? +- Shell code destined for the job script can read the environment or + access the filesystem as the job runs on the job host, not on the + scheduler host. + + +.. _SyntaxHighlighting: + +Syntax Highlighting For Workflow Configuration +---------------------------------------------- + +Cylc provides syntax plugins for the following editors: + +.. _language-cylc: https://github.com/cylc/language-cylc +.. _Cylc.tmbundle: https://github.com/cylc/Cylc.tmbundle +.. _vscode-cylc: https://marketplace.visualstudio.com/items?itemName=cylc.vscode-cylc + +Atom + install the `language-cylc`_ extension. +Emacs + The syntax file can be obtained from the Cylc library by + running the following command + ``cylc get-resources syntax/cylc-mode.el .`` + installation instructions are at the top of the file. +Gedit + The syntax file can be obtained from the Cylc library by + running the following command + ``cylc get-resources syntax/cylc.lang .`` + installation instructions are at the top of the file. +Kate + The syntax file can be obtained from the Cylc library by + running the following command + ``cylc get-resources syntax/cylc.xml .`` + installation instructions are at the top of the file. +PyCharm + Install the `Cylc.tmbundle`_. +Vim + The syntax file can be obtained from the Cylc library by + running the following command + ``cylc get-resources syntax/cylc.vim .`` + installation instructions are at the top of the file. +Visual Studio Code + Install the `vscode-cylc`_ extension. +Sublime Text 3 + Install the `Cylc.tmbundle`_. +TextMate + Install the `Cylc.tmbundle`_. +WebStorm + Install the `Cylc.tmbundle`_. +Nano + The syntax file can be obtained from the Cylc library by + running the following command + ``cylc get-resources syntax/cylc.nanorc ~/.config/nano`` + installation instructions are at the top of the file. + + +Gross File Structure +-------------------- + +Cylc :cylc:conf:`flow.cylc` files consist of configuration items grouped under +several top level section headings: + +:cylc:conf:`[meta]` + Information about the workflow e.g. title and description. +:cylc:conf:`[scheduler]` + Non task-specific workflow configuration. +:cylc:conf:`[task parameters]` + Parameters for use when defining graphs and tasks. + See :ref:`user guide param`. +:cylc:conf:`[scheduling]` + Determines when tasks are ready to run. + + - special scheduling constraints e.g. + :ref:`external triggers
`. + - the dependency graph, which defines the relationships + between tasks +:cylc:conf:`[runtime]` + Determines how, where, and what to execute when tasks are ready + + - script, environment, job submission, remote hosting, etc. + - workflow-wide defaults in the *root* family + - a nested family hierarchy with common properties + inherited by related tasks + +.. _Validation: + +Validation +---------- + +The ``cylc validate`` command evaluates the :cylc:conf:`flow.cylc` file +against a specification that defines all legal entries, values and options. +It also performs some integrity checks designed to catch certain configuration +issues and impossible scheduling constraints. + +These checks are also performed by ``cylc play`` before starting a workflow. + +All legal entries are documented in the :cylc:conf:`flow.cylc` reference. + +If a :cylc:conf:`flow.cylc` file uses include-files ``cylc view`` will +show an inlined copy of the workflow with correct line numbers. + +.. _cylc_lint_script: + +Linting +------- + +The ``cylc lint`` command checks code style, deprecated syntax and other +issues in Cylc configuration files. + +.. seealso:: + + :ref:`How to configure Cylc lint at project level ` + using a ``pyproject.toml``. + +``cylc lint`` +^^^^^^^^^^^^^ + +.. automodule:: cylc.flow.scripts.lint + +.. _lint.pyproject.toml: + +Configure ``cylc lint`` at project level +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can configure ``cylc lint`` for each workflow using a +``pyproject.toml`` file. + +To define settings for ``cylc lint`` use a ``[tool.cylc.lint]`` section. +Within the ``[tool.cylc.lint]`` section you may define the following: + +``rulesets`` + A list of rulesets to use. + + Allowed values: ``'728'``, ``'style'``, ``'all'``. + + (You can override this on the command line.) + +``ignore`` + Individual rules to ignore: A list of rule codes, such as ``S007``. + +``exclude`` + A list of files or glob patterns for files which will not be checked. + +``max-line-length`` + Set longest line length to permit in Cylc configs for this project. + + Default: ``130``. + + +.. note:: + + .. versionchanged:: 8.3.0 + + The ``[cylc-lint]`` section has been deprecated in favour of + ``[tool.cylc.lint]``. + +An example ``pyproject.toml`` might look like this: + +.. code-block:: toml + + [tool.cylc.lint] + # Enforce a line limit of 99 chars + max-line-length = 99 + + # Ignore style [S] rule 007 (It's good practice comment with a reason) + ignore = ['S007'] # Family names start with lowercase in this workflow + + # Don't check files matching these globs + exclude = ['history/*.old.cylc', 'someother.cylc'] + + # By default check for style + rulesets = ['style'] + + [some-other-section] + # Cylc lint won't pay any attention to this. diff --git a/nightly_8.4/html/_sources/user-guide/writing-workflows/empy.rst.txt b/nightly_8.4/html/_sources/user-guide/writing-workflows/empy.rst.txt new file mode 100644 index 00000000000..c006107e21e --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/writing-workflows/empy.rst.txt @@ -0,0 +1,58 @@ +.. _User Guide EmPy: + +EmPy +==== + +Cylc also supports the EmPy template processor in workflow configurations. +Like :ref:`User Guide Jinja2`, EmPy provides variables, mathematical +expressions, loop control structures, conditional logic, etc., that gets +expanded to generate the final workflow configuration seen - which must must be +valid Cylc syntax. See `EmPy`_ documentation +for details of its templating features and how to use them. + +.. note:: + + EmPy is not included in the standard Cylc installation. If installing + with ``pip`` run ``pip install cylc-flow[empy]`` to install it. + +.. TODO: update this when the conda instructions change + +To enable EmPy place an ``empy`` hash-bang comment on the first line of +the ``flow.cylc`` file: + +.. code-block:: cylc + + #!empy + + +As an example, here is the "cities" workflow from the previous section, +implemented with Empy instead of Jinja2. + +.. literalinclude:: ../../workflows/empy/cities/flow.cylc + :language: cylc + +For basic usage, the difference between Jinja2 and EmPy amounts to little more than +a different markup syntax. EmPy might be preferable, however, in cases needing +more complicated processing logic. + +*EmPy is a system for embedding Python expressions and statements in template +text. It makes the full power of Python language and its ecosystem easily +accessible from within the template. This might be desirable for several +reasons:* + +- No need to learn a different language just for writing template logic +- Availability of lambda functions, lists, and dictionary comprehensions + can make template code smaller and more readable compared to Jinja2 +- Natural and straightforward integration with the Python package ecosystem +- No two-language barrier between writing template logic and processing + extensions makes it easier to refactor and maintain the template code + as its complexity grows. Inline Python code can be gathered into subroutines + and eventually into separate modules and packages in a seamless manner. + + +Workflow files and Context Variables +------------------------------------ + +The EmPy processor has the same access as Jinja2 to +:ref:`workflow files ` and +:ref:`workflow context variables `. diff --git a/nightly_8.4/html/_sources/user-guide/writing-workflows/external-triggers.rst.txt b/nightly_8.4/html/_sources/user-guide/writing-workflows/external-triggers.rst.txt new file mode 100644 index 00000000000..92320639d13 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/writing-workflows/external-triggers.rst.txt @@ -0,0 +1,659 @@ +.. _Section External Triggers: + +External Triggers +================= + +External triggers allow tasks to trigger directly off of external events, which +is often preferable to implementing long-running polling tasks in the workflow. +The triggering mechanism described in this section is intended to replace the one +one documented in :ref:`Old-Style External Triggers` (however, that one is a push +mechanism, whereas this one involves regular polling by the scheduler). + +If you can write a Python function to check the status of an external +condition or event, the :term:`scheduler` can call it at configurable +intervals until it reports success, at which point dependent tasks can trigger +and data returned by the function will be passed to the job environments of +those tasks. Functions can be written for triggering off of almost anything, +such as delivery of a new dataset, creation of a new entry in a database +table, or appearance of new data availability notifications in a message +broker. + +.. TODO - update this once we have static visualisation + + External triggers are visible in workflow visualizations as bare graph nodes (just + the trigger names). They are plotted against all dependent tasks, not in a + cycle point specific way like tasks. This is because external triggers may or + may not be cycle point (or even task name) specific - it depends on the + arguments passed to the corresponding trigger functions. For example, if an + external trigger does not depend on task name or cycle point it will only be + called once - albeit repeatedly until satisfied - for the entire workflow run, + after which the function result will be remembered for all dependent tasks + throughout the workflow run. + +.. TODO - auto-document these once we have a python endpoint for them + +Cylc has several built-in external trigger functions: + +- :ref:`Built-in Clock Triggers` +- :ref:`Built-in Workflow State Triggers` + +Trigger functions are normal Python functions, with certain constraints as +described below in :ref:`Custom Trigger Functions`. + +External triggers are configured in the +:cylc:conf:`flow.cylc[scheduling][xtriggers]` section. + +.. NOTE - from here on all references can start [xtriggers] + +.. cylc-scope:: flow.cylc[scheduling] + + +.. _Built-in Clock Triggers: + +Built-in Clock Triggers +----------------------- + +These are more transparent (exposed in the graph) and efficient (shared among +dependent tasks) than the older clock triggers described +in :ref:`ClockTriggerTasks`. + +Clock triggers, unlike other trigger functions, are executed synchronously in +the main process. The clock trigger function signature looks like this: + +.. autofunction:: cylc.flow.xtriggers.wall_clock.wall_clock + +The ``offset`` argument is a datetime duration (``PT1H`` is 1 +hour) relative to the dependent task's cycle point (automatically passed to the +function via a second argument not shown above). + +In the following workflow, task ``foo`` has a daily cycle point sequence, +and each task instance can trigger once the wallclock time has passed its +cycle point value by one hour: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2018-01-01 + [[xtriggers]] + clock_1 = wall_clock(offset=PT1H) + [[graph]] + P1D = "@clock_1 => foo" + [runtime] + [[foo]] + script = run-foo.sh + +Notice that the short label ``clock_1`` is used to represent the +trigger function in the graph. + +Argument keywords can be omitted if called in the right order, so the +``clock_1`` trigger can also be declared like this: + +.. code-block:: cylc + + [[xtriggers]] + clock_1 = wall_clock(PT1H) + +A zero-offset clock trigger does not need to be declared under +the :cylc:conf:`[xtriggers]` section: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2018-01-01 + [[graph]] + # zero-offset clock trigger: + P1D = "@wall_clock => foo" + [runtime] + [[foo]] + script = run-foo.sh + +However, when xtriggers are declared the name used must adhere to the following +rules: + +.. autoclass:: cylc.flow.unicode_rules.XtriggerNameValidator + + +.. _Built-in Workflow State Triggers: + +Built-in Workflow State Triggers +-------------------------------- + +These can be used instead of the older workflow state polling tasks described +in :ref:`WorkflowStatePolling` for inter-workflow triggering - i.e. to trigger local +tasks off of remote task statuses or messages in other workflows. + +The workflow state trigger function signature looks like this: + +.. autofunction:: cylc.flow.xtriggers.workflow_state.workflow_state + +The first argument identifies the target workflow, cycle, task, and status or +output trigger name. The function arguments mirror the arguments and options of +the ``cylc workflow-state`` command - see ``cylc workflow-state --help``. + +As a simple example, consider the following "upstream" +workflow (which we want to trigger off of): + +.. literalinclude:: ../../workflows/xtrigger/workflow_state/upstream/flow.cylc + :language: cylc + +It must be installed and run under the name *up*, as referenced in the +"downstream" workflow that depends on it: + +.. literalinclude:: ../../workflows/xtrigger/workflow_state/downstream/flow.cylc + :language: cylc + +Try starting the downstream workflow first, then the upstream, and +watch what happens. +In each cycle point the ``@upstream`` trigger in the downstream workflow +waits on the task ``foo`` (with the same cycle point) in the upstream +workflow to emit the *data ready* message. + +Some important points to note about this: + +- The function call interval, which determines how often the scheduler + checks the clock, is optional. Here it is + ``PT10S`` (i.e. 10 seconds, which is also the default value). +- The ``workflow_state`` trigger function, like the + ``cylc workflow-state`` command, must have read-access to the upstream + workflow's public database. +- The cycle point is supplied by a string template + ``%(point)s``. The string templates available to trigger functions + arguments are described in :ref:`Custom Trigger Functions`). + +The return value of the ``workflow_state`` trigger function looks like +this: + +.. code-block:: python + + results = { + 'workflow': workflow_id, + 'task': task_name, + 'point': cycle_point, + 'status': task_status, # or + 'trigger': task_output_trigger, # or + 'message': task_output_message, + 'flow_num': flow_num # if given + } + return (satisfied, results) + +The ``satisfied`` variable is boolean (value True or False, depending +on whether or not the trigger condition was found to be satisfied). The +``results`` dictionary contains the names and values of the +target workflow state parameters. Each name gets qualified with the +unique trigger label ("upstream" here) and passed to the environment of +dependent tasks (the members of the ``FAM`` family in this case). +To see this, take a look at the job script for one of the downstream tasks: + +.. code-block:: console + + % cylc cat-log -f j dn//2011/f22011 + ... + cylc__job__inst__user_env() { + # TASK RUNTIME ENVIRONMENT: + export upstream_workflow upstream_cylc_run_dir upstream_offset \ + upstream_message upstream_status upstream_point upstream_task + upstream_workflow="up" + upstream_task="foo" + upstream_point="2011" + upstream_status="succeeded" + } + ... + +.. note:: + + The dependent task has to know the name of the xtrigger that it + depends on - "upstream" in this case - in order to use this information. + However the name could be given to the task environment in the workflow + configuration. + + +.. _Sequential Xtriggers: + +Sequential Xtriggers +--------------------------- + +Parentless tasks (which don't depend on other tasks upstream in the graph) +naturally spawn out to the runahead limit. This may cause UI clutter, and +unnecessary xtrigger checking if the xtriggers would only be satisfied in +order. + +You can use *sequential* xtriggers to avoid this problem: the next instance +of a task (i.e., at the next cycle point) that depends on a sequential xtrigger +will not be spawned until the previous xtrigger is satisfied. The +``wall_clock`` xtrigger is sequential by default. + +A trigger can be set as sequential in any or all of the following ways. + +By setting the workflow-wide :cylc:conf:`flow.cylc[scheduling]sequential xtriggers` +(defaults to ``False``) and/or keyword argument ``sequential`` to ``True``/``False`` in +the xtrigger declaration: + +.. literalinclude:: ../../workflows/xtrigger/sequential/flow.cylc + :language: cylc + +When implementing a :ref:`custom xtrigger `, you can +set the default for the ``sequential`` keyword argument in the xtrigger function +definition itself: + +.. code-block:: python + + def my_xtrigger(my_in, my_out, sequential=True) + +Xtrigger declaration takes precedence over function, and function over workflow +wide setting. So the above workflow definition would read: + +- ``foo`` spawns out to the runahead limit. +- ``FAM`` spawns only when ``@upstream`` is satisfied. +- All associated xtriggers are checked and, as expected, their satisfaction + is a prerequisite to task readiness. + + +.. _Custom Trigger Functions: + +Custom Trigger Functions +------------------------ + +Trigger functions are just normal Python functions, with a few special +properties: + +- They must: + + - Be defined in a module with the same name as the function, unless + provided using the ``cylc.xtriggers`` entry point; + - be compatible with the same Python version that runs the scheduler + (see :ref:`Requirements` for the latest version specification). + +- They can be located either: + + - In ``/lib/python/``; + - Anywhere in your ``$CYLC_PYTHONPATH``; + - Defined using the ``cylc.xtriggers`` entry point for an installed + package - see :ref:`developing.xtrigger.plugins` + +- They can take arbitrary positional and keyword arguments + (except ``sequential``, which is reserved - see :ref:`Sequential Xtriggers`) +- Workflow and task identity, and cycle point, can be passed to trigger + functions by using string templates in function arguments (see below) +- Integer, float, boolean, and string arguments will be recognized and + passed to the function as such +- If a trigger function depends on files or directories (for example) + that might not exist when the function is first called, just return +- The module can also provide a ``validate`` function for checking configured + arguments / keyword arguments, see + :ref:`user-guide.xtrigger-validation-functions` for details. + +.. note:: + + Trigger functions cannot store data Pythonically between invocations + because each call is executed in an independent process in the process + pool. If necessary the filesystem can be used for this purpose. + + +.. spelling:word-list:: + + vv + +.. autoenumvalues:: cylc.flow.xtrigger_mgr.TemplateVariables + +Function return values should be as follows: + +- if the trigger condition is *not satisfied*: + + - return ``(False, {})`` + +- if the trigger condition is *satisfied*: + + - return ``(True, results)`` + +where ``results`` is an arbitrary dictionary of information to be passed to +dependent tasks, which in terms of format must: + +- be *flat* (non-nested); +- contain *only* keys which are + `valid `_ as environment variable names. + +See :ref:`Built-in Workflow State Triggers` for an example of one such +``results`` dictionary and how it gets processed by the workflow. + +The :term:`scheduler` manages trigger functions as follows: + +- they are called asynchronously in the process pool + - (except for clock triggers, which are called from the main process) +- they are called repeatedly on a configurable interval, until satisfied + - the call interval defaults to ``PT10S`` (10 seconds) + - repeat calls are not made until the previous call has returned +- they are subject to the normal process pool command time out - if they + take too long to return, the process will be killed +- they are shared for efficiency: a single call will be made for all + triggers that share the same function signature - i.e.\ the same function + name and arguments +- their return status and results are stored in the workflow DB and persist across + workflow restarts +- their stdout, if any, is redirected to stderr and will be visible in + the workflow log in debug mode (stdout is needed to communicate return values + from the sub-process in which the function executes) + + +.. _user-guide.xtrigger-validation-functions: + +Xtrigger Validation Functions +----------------------------- + +The arguments you call the xtrigger function with are automatically validated +against the function signature, however, you might wish to add extra validation +logic to your custom xtrigger, e.g. to check argument types or values. + +If a function named ``validate`` is present alongside the xtrigger in its +module, it will be automatically called with a dictionary of all the arguments +passed to the xtrigger function in the workflow config. It should raise a +:py:obj:`cylc.flow.exceptions.WorkflowConfigError` exception if an error is +detected. + +The :py:mod:`cylc.flow.xtriggers.xrandom` xtrigger module contains an example +of an xtrigger validation function. + + +.. _Built-in Toy Xtriggers: + +Toy Examples +^^^^^^^^^^^^ + +echo +"""" + +The trivial built-in ``echo`` function takes any number of positional +and keyword arguments (from the workflow configuration) and simply prints +them to stdout, and then returns False (i.e. trigger condition not +satisfied). + +.. autofunction:: cylc.flow.xtriggers.echo.echo + +Here's an example echo trigger workflow: + +.. code-block:: cylc + + [scheduling] + initial cycle point = now + [[xtriggers]] + echo_1 = echo(hello, 99, qux=True, point=%(point)s, foo=10) + [[graph]] + PT1H = "@echo_1 => foo" + [runtime] + [[foo]] + script = exit 1 + +To see the result, run this workflow in debug mode and take a look at the +workflow log (or run ``cylc play --debug --no-detach `` and watch +your terminal). + + +xrandom +""""""" + +The built-in ``xrandom`` function sleeps for a configurable amount of +time (useful for testing the effect of a long-running trigger function +- which should be avoided) and has a configurable random chance of +success. The function signature is: + +.. automodule:: cylc.flow.xtriggers.xrandom + :members: xrandom, validate + :member-order: bysource + +An example xrandom trigger workflow: + +.. literalinclude:: ../../workflows/xtrigger/xrandom/flow.cylc + :language: cylc + +.. _Current Trigger Function Limitations: + +Current Limitations +------------------- + +The following issues may be addressed in future Cylc releases: + +- trigger labels cannot currently be used in conditional (OR) expressions + in the graph; attempts to do so will fail validation. +- aside from the predefined zero-offset ``wall_clock`` trigger, all + unique trigger function calls must be declared *with all of + their arguments* under the :cylc:conf:`[xtriggers]` section, and + referred to by label alone in the graph. It would be convenient (and less + verbose, although no more functional) if we could just declare a label + against the *common* arguments, and give remaining arguments (such as + different wallclock offsets in clock triggers) as needed in the graph. +- we may move away from the string templating method for providing workflow + and task attributes to trigger function arguments. + + +Filesystem Events? +------------------ + +Cylc does not have built-in support for triggering off of filesystem events +such as ``inotify`` on Linux. There is no cross-platform standard for +this, and in any case filesystem events are not very useful in HPC cluster +environments where events can only be detected at the specific node on which +they were generated. + + +Continuous Event Watchers? +-------------------------- + +For some applications a persistent process that continually monitors the +external world is better than discrete periodic checking. This would be more +difficult to support as a plugin mechanism in Cylc, but we may decide to do it +in the future. In the meantime, consider implementing a small daemon process as +the watcher (e.g. to watch continuously for filesystem events) and have your +Cylc trigger functions interact with it. + + +.. _Old-Style External Triggers: + +Push External Triggers +---------------------- + +.. note:: + + The external triggering mechanism described here is harder to use than the + newer method of :ref:`Section External Triggers`. The trigger is a task + property rather than something the task depends on, it requires the + external system to push a message to the scheduler, and it has a less + flexible way to pass information to downstream tasks. However, a push + mechanism may sometimes be preferred over polling by the scheduler, so we + have retained support pending something better in a future Cylc 8 release. + +These external triggers are hidden task prerequisites that must be satisfied by +using the ``cylc ext-trigger`` client command to send a pre-defined message to +the workflow along with an ID string that distinguishes one instance of the +event from another (the name of the target task and its current cycle point are +not required). The event ID is just an arbitrary string to Cylc, but it can be +used to identify something associated with the event to the workflow - such as +the filename of a new externally-generated dataset. When the :term:`scheduler` +receives the event notification it will trigger the next instance of any task +waiting on that trigger (whatever its cycle point) and then broadcast +(see :ref:`cylc-broadcast`) the event ID to the cycle point of the triggered +task as ``$CYLC_EXT_TRIGGER_ID``. Downstream tasks with the same cycle +point therefore know the new event ID too and can use it, if they need to, to +identify the same new dataset. In this way a whole workflow can be associated +with each new dataset, and multiple datasets can be processed in parallel if +they happen to arrive in quick succession. + +An externally-triggered task must register the event it waits on in the workflow +scheduling section: + +.. code-block:: cylc + + # workflow "sat-proc" + [scheduling] + cycling mode = integer + initial cycle point = 1 + [[special tasks]] + external-trigger = get-data("new sat X data avail") + [[graph]] + P1 = get-data => conv-data => products + +Then, each time a new dataset arrives the external detection system should +notify the workflow like this: + +.. code-block:: console + + $ cylc ext-trigger sat-proc "new sat X data avail" passX12334a + +where "sat-proc" is the workflow name and "passX12334a" is the ID string for +the new event. The workflow passphrase must be installed on triggering account. + +.. note:: + + Only one task in a workflow can trigger off a particular external message. + Other tasks can trigger off the externally triggered task as required, + of course. + +Here is a working example of a simulated satellite processing workflow: + +.. literalinclude:: ../../workflows/satellite/ext-trigger/flow.cylc + :language: cylc + +External triggers are not normally needed in datetime cycling workflows driven +by real time data that comes in at regular intervals. In these cases a data +retrieval task can be clock-triggered (and have appropriate retry intervals) to +submit at the expected data arrival time, so little time is wasted in polling. +However, if the arrival time of the cycle-point-specific data is highly +variable, external triggering may be used with the cycle point embedded in the +message: + +.. code-block:: cylc + + # workflow "data-proc" + [scheduling] + initial cycle point = 20150125T00 + final cycle point = 20150126T00 + [[special tasks]] + external-trigger = get-data("data arrived for $CYLC_TASK_CYCLE_POINT") + [[graph]] + T00 = init-process => get-data => post-process + +Once the variable-length waiting is finished, an external detection system +should notify the workflow like this: + +.. code-block:: console + + $ cylc ext-trigger data-proc "data arrived for 20150126T00" passX12334a + +where "data-proc" is the workflow name, the cycle point has replaced the +variable in the trigger string, and "passX12334a" is the ID string for +the new event. The workflow passphrase must be installed on the triggering +account. In this case, the event will trigger for the second cycle point but +not the first because of the cycle-point matching. + + +.. _WorkflowStatePolling: + +Triggering Off Of Tasks In Other Workflows +------------------------------------------ + +.. note:: + + Please read :ref:`Section External Triggers` before using the older + inter-workflow triggering mechanism described in this section. + +The ``cylc workflow-state`` command interrogates workflow run databases. It +has a polling mode that waits for a given task in the target workflow to achieve a +given state, or receive a given message. This can be used to make task +scripting wait for a remote task to succeed (for example). + +Automatic workflow-state polling tasks can be defined with in the graph. They get +automatically-generated task scripting that uses ``cylc workflow-state`` +appropriately (it is an error to give your own ``script`` item for these +tasks). + +Here's how to trigger a task ``bar`` off a task ``foo`` in +a remote workflow called ``other.workflow``: + +.. code-block:: cylc + + [scheduling] + [[graph]] + T00, T12 = "my-foo => bar" + +Local task ``my-foo`` will poll for the success of ``foo`` +in workflow ``other.workflow``, at the same cycle point, succeeding only when +or if it succeeds. Other task states can also be polled: + +.. code-block:: cylc + + T00, T12 = "my-foo => bar" + +The default polling parameters (e.g. maximum number of polls and the interval +between them) are printed by ``cylc workflow-state --help`` and can be +configured if necessary under the local polling task runtime section: + +.. code-block:: cylc + + [scheduling] + [[graph]] + T00,T12 = "my-foo => bar" + [runtime] + [[my-foo]] + [[[workflow state polling]]] + max-polls = 100 + interval = PT10S + +To poll for the target task to receive a message rather than achieve a state, +give the message in the runtime configuration (in which case the task status +inferred from the graph syntax will be ignored): + +.. code-block:: cylc + + [runtime] + [[my-foo]] + [[[workflow state polling]]] + message = "the quick brown fox" + +For workflows owned by others, or those with run databases in non-standard +locations, use the ``--run-dir`` option, or in-workflow: + +.. code-block:: cylc + + [runtime] + [[my-foo]] + [[[workflow state polling]]] + run-dir = /path/to/top/level/cylc/run-directory + +If the remote task has a different cycling sequence, just arrange for the +local polling task to be on the same sequence as the remote task that it +represents. For instance, if local task ``cat`` cycles 6-hourly at +``0,6,12,18`` but needs to trigger off a remote task ``dog`` +at ``3,9,15,21``: + +.. code-block:: cylc + + [scheduling] + [[graph]] + T03,T09,T15,T21 = "my-dog" + T00,T06,T12,T18 = "my-dog[-PT3H] => cat" + +For workflow-state polling, the cycle point is automatically converted to the +cycle point format of the target workflow. + +The remote workflow does not have to be running when polling commences because the +command interrogates the workflow run database, not the :term:`scheduler`. + +.. note:: + + The graph syntax for workflow polling tasks cannot be combined with + cycle point offsets, family triggers, or parameterized task notation. + This does not present a problem because workflow polling tasks can be put on + the same cycling sequence as the remote-workflow target task (as recommended + above), and there is no point in having multiple tasks (family members or + parameterized tasks) performing the same polling operation. Task state + triggers can be used with workflow polling, e.g. to trigger another task if + polling fails after 10 tries at 10 second intervals: + + .. code-block:: cylc + + [scheduling] + [[graph]] + R1 = "poller:fail => another-task" + [runtime] + [[my-foo]] + [[[workflow state polling]]] + max-polls = 10 + interval = PT10S diff --git a/nightly_8.4/html/_sources/user-guide/writing-workflows/index.rst.txt b/nightly_8.4/html/_sources/user-guide/writing-workflows/index.rst.txt new file mode 100644 index 00000000000..e1aa3351ee0 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/writing-workflows/index.rst.txt @@ -0,0 +1,15 @@ +Writing Workflows +================= + +.. toctree:: + :maxdepth: 2 + + configuration + scheduling + runtime + parameterized-tasks + jinja2 + empy + external-triggers + suicide-triggers + scheduler diff --git a/nightly_8.4/html/_sources/user-guide/writing-workflows/jinja2.rst.txt b/nightly_8.4/html/_sources/user-guide/writing-workflows/jinja2.rst.txt new file mode 100644 index 00000000000..2aaa15c57c0 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/writing-workflows/jinja2.rst.txt @@ -0,0 +1,608 @@ +.. _Jinja: +.. _User Guide Jinja2: + +Jinja2 +====== + +.. tutorial:: + Configuration Consolidation Tutorial + +Cylc supports the `Jinja2`_ template processor in workflow configurations. +Jinja2 code can appear anywhere in the file. The result after Jinja2 processing +must be valid Cylc syntax. + +To use Jinja2, put a hash-bang comment in the first line of :cylc:conf:`flow.cylc`: + +.. code-block:: cylc + + #!jinja2 + +Embedded Jinja2 code should be reasonably easy to understand for those with +coding experience; otherwise Jinja2 is documented `here `_. + +Uses of Jinja2 in Cylc include: + + - Inclusion or exclusion of config sections by logical switch, e.g. to make + portable workflows + - Computation of config values from input data + - Inclusion of files and sub-templates + - Looping over parameters to generate groups of similar tasks and associated + dependencies - but see :ref:`Parameterized Tasks ` for a + simpler alternative to this where appropriate + +.. _fig-jinja2-ensemble: + +.. figure:: ../../img/jinja2-ensemble-graph.png + :align: center + + The Jinja2 ensemble example workflow graph. + + +The graph above shows an ensemble of similar tasks generated with a Jinja2 loop: + +.. code-block:: cylc + + #!jinja2 + {% set N_MEMBERS = 5 %} + [scheduling] + [[graph]] + R1 = """ + {# generate ensemble dependencies #} + {% for I in range( 0, N_MEMBERS ) %} + foo => mem_{{ I }} => post_{{ I }} => bar + {% endfor %} + """ + +Note that Jinja2 code is encapsulated in curly braces to distinguish it from +the surrounding text. + + + ================= ====================== + Jinja2 Syntax Description + ================= ====================== + ``{# comment #}`` Comment + ``{% if true %}`` Expression + ``{{ var }}`` Print statement + ================= ====================== + +Here is the workflow configuration after Jinja2 processing: + +.. code-block:: cylc + + #!jinja2 + [scheduling] + [[graph]] + R1 = """ + foo => mem_0 => post_0 => bar + foo => mem_1 => post_1 => bar + foo => mem_2 => post_2 => bar + foo => mem_3 => post_3 => bar + foo => mem_4 => post_4 => bar + """ + +This example illustrates Jinja2 loops nicely, but note it is now easier +to generate task names automatically with built-in +:ref:`task parameters `: + +.. code-block:: cylc + + [task parameters] + m = 0..4 + [scheduling] + [[graph]] + R1 = "foo => mem => post => bar" + + +The next workflow, which generates weather forecasts over a number of cities, is +more complex. To add a new city and associated tasks and dependencies just add +the new city name to list at the top of the file. It makes use of Jinja2 +variables, loops, math, and logical flags to include or exclude tasks. + +.. tip:: + This example could also be simplified with built in + :ref:`task parameters ` + +.. literalinclude:: ../../workflows/jinja2/cities/flow.cylc + :language: cylc + +.. _fig-jinja2-cities: + +.. figure:: ../../img/jinja2-workflow-graph.png + :align: center + + Jinja2 cities example workflow graph, with the + New York City task family expanded. + + +.. _jinja2.workflow_files: + +Access to Workflow Files +------------------------ + +Your Jinja2 code can see the workflow directory by using +:ref:`Python code ` +that simply reads from the *current working directory*. + +This will be the source directory if parsing a source workflow, or the run +directory if parsing an installed workflow. + + +.. _jinja2.workflow_context: + +Workflow Context variables +-------------------------- + +Jinja2 CYLC variables available when parsing any workflow (source or installed): + +.. table:: + + ====================== ============== + CYLC_VERSION Version of Cylc parsing the configuration + CYLC_WORKFLOW_NAME Workflow name (source, or run ID minus run name) + CYLC_TEMPLATE_VARS Variables set by '--set' CLI options or plugins + ====================== ============== + + +Additional Jinja2 CYLC variables available when parsing an installed workflow: + +.. table:: + + ====================== ============== + CYLC_WORKFLOW_ID Workflow ID + CYLC_WORKFLOW_RUN_DIR Workflow run directory + ====================== ============== + + +Additional Jinja2 CYLC variables available when the scheduler is parsing an +installed workflow at run time: + +.. table:: + + ======================= ============== + CYLC_WORKFLOW_LOG_DIR Workflow log sub-directory + CYLC_WORKFLOW_SHARE_DIR Workflow share sub-directory + CYLC_WORKFLOW_WORK_DIR Workflow work sub-directory + ======================= ============== + +.. note:: + + Set default values for CYLC variables that are only defined for installed or + running workflows, to allow successful parsing in other contexts as well: + ``{{CYLC_WORKFLOW_RUN_DIR | default("not-defined")}}``. + + +Environment Variables +--------------------- + +Cylc automatically imports the parse-time environment to the template +processor's global namespace (see :ref:`CustomJinja2Filters`), +in a dictionary called ``environ``: + +.. code-block:: cylc + + #!Jinja2 + #... + [runtime] + [[root]] + [[[environment]]] + HOME_DIR_ON_WORKFLOW_HOST = {{environ['HOME']}} + +.. warning:: + + The environment is read during configuration parsing. It is not the run time + job environment. + + +.. _CustomJinja2Filters: + +Custom Jinja2 Filters, Tests and Globals +---------------------------------------- + +Jinja2 has three namespaces that separate "globals", "filters" and "tests". +Globals are template-wide variables and functions. Cylc extends this namespace +with the ``environ`` dictionary above, and +:ref:`raise ` and :ref:`assert ` +functions for raising exceptions to abort Cylc config parsing. + +Filters can be used to modify variable values and are applied using pipe +notation. For example, the built-in ``trim`` filter strips leading +and trailing white space from a string: + +.. code-block:: cylc + + {% set MyString = " dog " %} + {{ MyString | trim() }} # "dog" + +Variable values can be tested using the ``is`` keyword followed by +the name of the test, e.g. ``{% if VARIABLE is defined %}``. See Jinja2 +documentation for available built-in globals, filters and tests. + +Cylc also supports custom Jinja2 globals, filters and tests. A custom global, +filter or test is a single Python function in a source file with the same name +as the function (plus ``.py`` extension). These must be located in a +subdirectory of the :term:`run directory` called +``Jinja2Filters``, ``Jinja2Globals`` or ``Jinja2Tests`` respectively. + +In the argument list of a filter or test function, the first argument is +the variable value to be filtered or tested, and subsequent arguments can be +whatever is needed. Currently three custom filters are supplied: + +.. autosummary:: + :nosignatures: + + cylc.flow.jinja.filters.pad.pad + cylc.flow.jinja.filters.strftime.strftime + cylc.flow.jinja.filters.duration_as.duration_as + +.. autofunction:: cylc.flow.jinja.filters.pad.pad + +.. autofunction:: cylc.flow.jinja.filters.strftime.strftime + +.. autofunction:: cylc.flow.jinja.filters.duration_as.duration_as + + +Associative Arrays In Jinja2 +---------------------------- + +Associative arrays (or **dictionaries**) are very useful. For example: + +.. code-block:: cylc + + #!Jinja2 + {% set obs_types = ['airs', 'iasi'] %} + {% set resource = { 'airs':'ncpus=9', 'iasi':'ncpus=20' } %} + + [scheduling] + [[graph]] + R1 = OBS + [runtime] + [[OBS]] + platform = platform_using_pbs + {% for i in obs_types %} + [[ {{i}} ]] + inherit = OBS + [[[directives]]] + -I = {{ resource[i] }} + {% endfor %} + +Here's the result: + +.. code-block:: console + + $ cylc config -i [runtime][airs]directives + -I = ncpus=9 + + +.. _jinja2-template-variables: + +Default Values and Template Variables +------------------------------------- + +You can provide template variables to Cylc in 4 ways: + +- Using the ``--set-file`` (``-S``) option. +- Using the ``--set`` (``-s``) option. +- Using the ``--set-list`` (``-z``) option. +- `Using a plugin`_, such as :ref:`Cylc Rose`. + +.. note:: + + If the same variable is set by more than one method, the last source in the + above list is used. + + +The ``-s``, ``-z`` and ``--set-file`` Options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: console + + $ # set the Jinja2 variable "answer" to 42 + $ cylc play -s answer=42 + +A Python string-list is a valid value, but a lot to type, so ``--set-list`` +(``-z``) is provided as a convenience: + +.. code-block:: console + + # The set syntax + $ cylc play -s "answers=['mice', 'dolphins']" + # ... can be shortened to: + $ cylc play -z answers=mice,dolphins + +If you need to define a lot of variables, you can so in a file +using the ``--set-file`` option: + +.. code-block:: console + + $ # create a set file + $ cat > my-set-file <<__SET_FILE__ + question='the meaning of life, the universe and everything' + answer=42 + host='deep-thought' + __SET_FILE__ + + $ # run using the options in the set file + $ cylc play --set-file my-set-file + +Values must be Python literals e.g: + +.. code-block:: python + + "string" # string + 123 # integer + 12.34 # float + True # boolean + None # None type + [1, 2, 3] # list + (1, 2, 3) # tuple + {1, 2, 3} # set + {"a": 1, "b": 2, "c": 3} # dictionary + +.. note:: + + On the command line you may need to wrap strings with an extra + pair of quotes as the shell you are using (e.g. Bash) will strip + the outer pair of quotes. + + .. code-block:: console + + $ # wrap the key=value pair in single quotes stop the shell from + $ # stripping the inner quotes around the string: + $ cylc play -s 'my_string="a b c"' + +Here's an example: + +.. literalinclude:: ../../workflows/jinja2/defaults/flow.cylc + :language: cylc + +Here's the result: + +.. code-block:: console + + $ cylc list + Jinja2 Template Error + 'FIRST_TASK' is undefined + cylc-list failed: 1 + + $ # Note: quoting "bob" so that it is evaluated as a string + $ cylc list --set 'FIRST_TASK="bob"' + bob + baz + mem_2 + mem_1 + mem_0 + + $ cylc list --set 'FIRST_TASK="bob"' --set 'LAST_TASK="alice"' + bob + alice + mem_2 + mem_1 + mem_0 + + $ # Note: no quotes required for N_MEMBERS since it is an integer + $ cylc list --set 'FIRST_TASK="bob"' --set N_MEMBERS=10 + mem_9 + mem_8 + mem_7 + mem_6 + mem_5 + mem_4 + mem_3 + mem_2 + mem_1 + mem_0 + baz + bob + +Note also that ``cylc view --set FIRST_TASK=bob --jinja2 `` +will show the workflow with the Jinja2 variables as set. + +.. note:: + + Workflows started with template variables set on the command + line will :term:`restart` with the same settings. You can set + them again on the ``cylc play`` command line if they need to + be overridden. + + +Using a plugin +^^^^^^^^^^^^^^ + +Template plugins such as :ref:`Cylc Rose` should provide a set of template +variables which can be provided to Cylc. For example, using Cylc Rose you +add a ``rose-suite.conf`` file containing a ``[template variables]`` +section which the plugin makes available to Cylc: + +.. code-block:: ini + :caption: rose-suite.conf + + [template variables] + ICP=1068 + +.. code-block:: cylc + :caption: flow.cylc + + #!jinja2 + [scheduler] + allow implicit tasks = True + [scheduling] + initial cycle point = {{ICP}} + [[dependencies]] + P1Y = Task1 + + +.. code-block:: console + + $ cylc config . -i "[scheduling]initial cycle point" + 1068 + + + +Jinja2 Variable Scope +--------------------- + +Jinja2 variable scoping rules may be surprising. For instance, variables set +inside a ``for`` loop can't be accessed outside of the block, +so the following will not print ``# FOO is True``: + +.. code-block:: cylc + + {% set FOO = False %} + {% for item in items %} + {% if item.check_something() %} + {% set FOO = True %} + {% endif %} + {% endfor %} + # FOO is {{FOO}} + +Jinja2 documentation suggests using alternative constructs like the loop +``else`` block or the special ``loop`` variable. More complex use cases can be +handled using ``namespace`` objects that allow propagating of changes across scopes: + +.. code-block:: cylc + + {% set ns = namespace(foo=false) %} + {% for item in items %} + {% if item.check_something() %} + {% set ns.foo = true %} + {% endif %} + {% endfor %} + # FOO is {{ns.foo}} + +For detail, see +`Jinja2 Template Designer Documentation - Assignments +`_ + + +.. _Jinja2RaisingExceptions: + +Raising Exceptions +------------------ + +Cylc provides two functions for raising exceptions in Jinja2 code. These +exceptions are raised when the :cylc:conf:`flow.cylc` file is loaded and will +prevent a workflow from running. + +.. note:: + + These functions must be contained within ``{{`` Jinja2 print statements, not + ``{%`` code blocks. + +.. _jinja2-raise: + +Raise +^^^^^ + +The ``raise`` function will result in an error containing the provided text. + +.. code-block:: cylc + + {% if not VARIABLE is defined %} + {{ raise('VARIABLE must be defined for this workflow.') }} + {% endif %} + +.. _jinja2-assert: + +Assert +^^^^^^ + +The ``assert`` function will raise an exception containing the text provided in +the second argument providing that the first argument evaluates as False. The +following example is equivalent to the "raise" example above. + +.. code-block:: cylc + + {{ assert(VARIABLE is defined, 'VARIABLE must be defined for this workflow.') }} + + +.. _jinja2.importing_python_modules: + +Importing Python modules +------------------------ + +Jinja2 allows to gather variable and macro definitions in a separate template +that can be imported into (and thus shared among) other templates. + +.. code-block:: cylc + + {% import "flow-utils.cylc" as utils %} + {% from "flow-utils.cylc" import VARIABLE as ALIAS %} + {{ utils.VARIABLE is equalto(ALIAS)) }} + +Cylc extends this functionality to allow import of arbitrary Python modules. + +.. code-block:: cylc + + {% from "itertools" import product %} + [runtime] + {% for group, member in product(['a', 'b'], [0, 1, 2]) %} + [[{{group}}_{{member}}]] + {% endfor %} + +For better clarity and disambiguation Python modules can be prefixed with +``__python__``: + +.. code-block:: cylc + + {% from "__python__.itertools" import product %} + + +Logging +------- + +It is possible to output messages to the Cylc log from within Jinja2, these +messages will appear on the console when validating or starting a workflow. +This can be useful for development or debugging. + +Example :cylc:conf:`flow.cylc`: + +.. code-block:: cylc + + #!Jinja2 + {% from "cylc.flow" import LOG %} + {% do LOG.debug("Hello World!") %} + +Example output: + +.. code-block:: console + + $ cylc validate . --debug + DEBUG - Loading site/user config files + DEBUG - Reading file + DEBUG - Processing with Jinja2 + DEBUG - Hello World! + ... + Valid for cylc- + +Log messages will appear whenever the workflow configuration is loaded so it is +advisable to use the ``DEBUG`` logging level which is suppressed unless the +``--debug`` option is provided. + + +Debugging +--------- + +It is possible to run Python debuggers from within Jinja2 via the +:ref:`import mechanism `. + +.. _PDB: https://docs.python.org/3/library/pdb.html + +For example to use a `PDB`_ breakpoint you could do the following: + +.. code-block:: cylc + + #!Jinja2 + + {% set ANSWER = 42 %} + + {% from "pdb" import set_trace %} + {% do set_trace() %} + +The debugger will open within the Jinja2 code, local variables can be accessed +via the ``_Context__self`` variable e.g: + +.. code-block:: console + + $ cylc validate + (Pdb) _Context__self['ANSWER'] + 42 diff --git a/nightly_8.4/html/_sources/user-guide/writing-workflows/parameterized-tasks.rst.txt b/nightly_8.4/html/_sources/user-guide/writing-workflows/parameterized-tasks.rst.txt new file mode 100644 index 00000000000..73633344e95 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/writing-workflows/parameterized-tasks.rst.txt @@ -0,0 +1,653 @@ +.. _User Guide Param: + +Task Parameters +=============== + +Cylc can automatically generate related tasks and dependencies by expanding +:term:`parameterized ` names over lists or ranges of +values. Uses for this include: + +- Generating an ensemble of similar model runs +- Generating chains of tasks to process similar datasets +- Replicating an entire workflow, or part thereof, over several runs +- Splitting a long model run into smaller chunks +- Parameterized cycling + +.. note:: + + Cylc supports use of :ref:`Jinja2 ` and :ref:`Empy + ` templating for programmatic generation of workflow + configurations. The built-in parameterization system described here + is a cleaner and easier alternative *for generating tasks and families + over a range of parameters*, but unlike general templating it can only be + used for that specific purpose. + + +Parameter Expansion +------------------- + +Parameter values can be lists of strings, or lists of integers and +integer ranges (with inclusive bounds). Numeric values in a list of strings are +considered strings. It is not possible to mix strings with integer ranges. + +For example: + +.. code-block:: cylc + + [task parameters] + # parameters: "ship", "buoy", "plane" + # default task suffixes: _ship, _buoy, _plane + obs = ship, buoy, plane + + # parameters: 1, 2, 3, 4, 5 + # default task suffixes: _run1, _run2, _run3, _run4, _run5 + run = 1..5 + + # parameters: 1, 3, 5, 7, 9 + # default task suffixes: _idx1, _idx3, _idx5, _idx7, _idx9 + idx = 1..9..2 + + # parameters: -11, -1, 9 + # default task suffixes: _idx-11, _idx-01, _idx+09 + idx = -11..9..10 + + # parameters: 1, 3, 5, 10, 11, 12, 13 + # default task suffixes: _i01, _i03, _i05, _i10, _i11, _i12, _i13 + i = 1..5..2, 10, 11..13 + + # parameters: "0", "1", "e", "pi", "i" + # default task suffixes: _0, _1, _e, _pi, _i + item = 0, 1, e, pi, i + + # ERROR: mix strings with int range + p = one, two, 3..5 + +Then angle brackets denote use of these parameters throughout the workflow +configuration. For the values above, this parameterized name: + +.. code-block:: sub + + model # for run = 1..5 + +expands to these concrete task names: + +.. code-block:: none + + model_run1, model_run2, model_run3, model_run4, model_run5 + +and this parameterized name: + +.. code-block:: sub + + proc # for obs = ship, buoy, plane + +expands to these concrete task names: + +.. code-block:: none + + proc_ship, proc_buoy, proc_plane + +By default, to avoid any ambiguity, the parameter name appears in the expanded +task names for integer values, but not for string values. For example, +``model_run1`` for ``run = 1``, but ``proc_ship`` for +``obs = ship``. However, the default expansion templates can be +overridden if need be: + +.. code-block:: cylc + + [task parameters] + obs = ship, buoy, plane + run = 1..5 + [[templates]] + run = -R%(run)s # Make foo expand to foo-R1 etc. + +See :cylc:conf:`[task parameters][templates]` for more on the string +template syntax. + +Any number of parameters can be used at once. This parameterization: + + +.. code-block:: sub + + model # for run = 1..2 and obs = ship, buoy, plane + model # Alternatively, from Cylc 8.2.0 + +.. versionadded:: 8.2.0 + + From this version you can also use the equivalent ``model`` + syntax. This allows more flexibility in templating: You can now construct + names like ``beginningmiddleend``. + +.. note:: + + Before Cylc 8.2.0 this syntax worked in many cases, but was + not formally supported, and failed if used in the names of + :ref:`families`. + +expands to these tasks names: + +.. code-block:: none + + model_run1_ship, model_run1_buoy, model_run1_plane, + model_run2_ship, model_run2_buoy, model_run2_plane + +Here's a simple but complete example workflow: + +.. code-block:: cylc + + [task parameters] + run = 1..2 + [scheduling] + [[graph]] + R1 = "prep => model" + [runtime] + [[model]] + # ... + +The result, post parameter expansion, is this: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = "prep => model_run1 & model_run2" + [runtime] + [[model_run1]] + # ... + [[model_run2]] + # ... + +Here's a more complex graph using two parameters (:cylc:conf:`[runtime]` +omitted): + +.. code-block:: cylc + + [task parameters] + run = 1..2 + mem = cat, dog + [scheduling] + [[graph]] + R1 = """ + prep => init => model => + post => wrap => done + """ + +.. todo + + \.\.\. which expands to: + + [scheduling] + [[graph]] + R1 = """ + prep => init_run1 => model_run1_cat => post_run1_cat => wrap_run1 => done + init_run1 => model_run1_dog => post_run2_dog => wrap_run1 + prep => init_run2 => model_run2_cat => post_run2_cat => wrap_run2 => done + init_run2 => model_run2_dog => post_run2_dog => wrap_run2""" + +The result as visualized by ``cylc graph`` is: + +.. _fig-params-1: + +.. figure:: ../../img/params1.png + :align: center + + Parameter expansion example. + + +Zero-Padded Integer Values +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Integer parameter values are given a default template for generating task +suffixes that are zero-padded according to the longest size of their values. +For example, the default template for ``p = 9..10`` would be +``_p%(p)02d``, so that ``foo

`` would become ``foo_p09, foo_p10``. +If negative values are present in the parameter list, the +default template will include the sign. +For example, the default template for ``p = -1..1`` would be +``_p%(p)+02d``, so that ``foo

`` would become +``foo_p-1, foo_p+0, foo_p+1``. + +To get thicker padding and/or alternate suffixes, use a template. E.g.: + +.. code-block:: cylc + + [task parameters] + i = 1..9 + p = 3..14 + [[templates]] + i = _i%(i)02d # suffixes = _i01, _i02, ..., _i09 + # A double-percent gives a literal percent character + p = %%p%(p)03d # suffixes = %p003, %p004, ..., %p013, %p014 + + +Parameters as Full Task Names +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Parameter values can be used as full task names, but the default template +should be overridden to remove the initial underscore. For example: + +.. code-block:: cylc + + [task parameters] + i = 1..4 + obs = ship, buoy, plane + [[templates]] + i = i%(i)d # task name must begin with an alphabet + obs = %(obs)s + [scheduling] + [[graph]] + R1 = """ + foo => # foo => i1 & i2 & i3 & i4 + => bar # ship & buoy & plane => bar + """ + + +Passing Values To Tasks +----------------------- + +Parameter values are passed as environment variables to tasks generated by +parameter expansion. For example, if we have: + +.. code-block:: cylc + + [task parameters] + obs = ship, buoy, plane + run = 1..5 + [scheduling] + [[graph]] + R1 = model + +Then task ``model_run2_ship`` would get the following standard +environment variables: + +.. code-block:: bash + + # In a job script of an instance of the "model_run2_ship" task: + export CYLC_TASK_PARAM_run="2" + export CYLC_TASK_PARAM_obs="ship" + +These variables allow tasks to determine which member of a parameterized +group they are, and so to vary their behaviour accordingly. + +You can also define custom variables and string templates for parameter value +substitution. For example, if we add this to the above configuration: + +.. code-block:: cylc + + [runtime] + [[model]] + [[[environment]]] + MYNAME = %(obs)sy-mc%(obs)sface + MYFILE = /path/to/run%(run)03d/%(obs)s + +Then task ``model_run2_ship`` would get the following custom +environment variables: + +.. code-block:: bash + + # In a job script of an instance of the "model_run2_ship" task: + export MYNAME=shipy-mcshipface + export MYFILE=/path/to/run002/ship + + +Selecting Specific Values +------------------------- + +Specific parameter values can be singled out in the graph and under +:cylc:conf:`[runtime]` with the notation ```` (for example). +Here's how to make a special task trigger off just the first of a +set of model runs: + +.. code-block:: cylc + + [task parameters] + run = 1..5 + [scheduling] + [[graph]] + R1 = """ + model => post_proc # general case + model => check_first_run # special case + """ + [runtime] + [[model]] + # config for all "model" runs... + [[model]] + # special config (if any) for the first model run... + #... + + +Selecting Partial Ranges +------------------------ + +The parameter notation does not currently support partial range selection such +as ``foo``, but you can achieve the same result by defining a +second parameter that covers the partial range and giving it the same expansion +template as the full-range parameter. For example: + +.. code-block:: cylc + + [task parameters] + run = 1..10 # 1, 2, ..., 10 + runx = 1..3 # 1, 2, 3 + [[parameter templates]] + run = _R%(run)02d # _R01, _R02, ..., _R10 + runx = _R%(runx)02d # _R01, _R02, _R03 + [scheduling] + [[graph]] + R1 = """model => post + model => checkx""" + [runtime] + [[model]] + # ... + #... + + +Offsets in the Graph +--------------------- + +A negative offset notation ```` is interpreted as the previous +value in the ordered list of parameter values, while a positive offset is +interpreted as the next value. For example, to split a model run into multiple +steps with each step depending on the previous one, either of these graph lines: + +.. code-block:: cylc-graph + + model => model # for run = 1, 2, 3 + model => model # for run = 1, 2, 3 + +expands to: + +.. code-block:: cylc-graph + + model_run1 => model_run2 + model_run2 => model_run3 + + # or equivalently: + + model_run1 => model_run2 => model_run3 + +And this graph: + +.. code-block:: cylc-graph + + proc => proc # for size = small, big, huge + +expands to: + +.. code-block:: cylc-graph + + proc_small => proc_big + proc_big => proc_huge + + # or equivalently: + + proc_small => proc_big => proc_huge + +.. _families_and_parameters: + +Task Families and Parameters +---------------------------- + +Task family members can be generated by parameter expansion: + +.. code-block:: cylc + + [runtime] + [[FAM]] + [[member]] + inherit = FAM + # Result: family FAM contains member_r1, member_r2, etc. + + +Family names can be parameterized too, just like task names: + +.. code-block:: cylc + + [runtime] + [[RUN]] + [[model]] + inherit = RUN + [[post_proc]] + inherit = RUN + # Result: family RUN_r1 contains model_r1 and post_proc_r1, + # family RUN_r2 contains model_r2 and post_proc_r1, etc. + +As described in :ref:`FamilyTriggers` family names can be used to +trigger all members at once: + +.. code-block:: cylc-graph + + foo => FAMILY + +or to trigger off all members: + +.. code-block:: cylc-graph + + FAMILY:succeed-all => bar + +or to trigger off any members: + +.. code-block:: cylc-graph + + FAMILY:succeed-any => bar + +If the members of ``FAMILY`` were generated with parameters, you can +also trigger them all at once with parameter notation: + +.. code-block:: cylc-graph + + foo => member + +Similarly, to trigger off all members: + +.. code-block:: cylc-graph + + member => bar + # (member:fail etc., for other trigger types) + +Family names are still needed in the graph, however, to succinctly express +"succeed-any" triggering semantics, and all-to-all or any-to-all triggering: + +.. code-block:: cylc-graph + + FAM1:succeed-any => FAM2 + +(Direct all-to-all and any-to-all family triggering is not recommended for +efficiency reasons though - see :ref:`EfficientInterFamilyTriggering`). + +For family *member-to-member* triggering use parameterized members. +For example, if family ``OBS_GET`` has members ``get`` and +family ``OBS_PROC`` has members ``proc`` then this graph: + +.. code-block:: cylc-graph + + get => proc # for obs = ship, buoy, plane + +expands to: + +.. code-block:: cylc-graph + + get_ship => proc_ship + get_buoy => proc_buoy + get_plane => proc_plane + + +.. _Parameterized Cycling: + +Parameterized Cycling +--------------------- + +For smaller workflows of finite duration, parameter expansion can be used to +generate a sequence of pre-defined tasks as a proxy for cycling. + +Here's a cycling workflow of two-monthly model runs for one year, with +previous-instance model dependence: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2020-01 + final cycle point = 2020-12 + [[graph]] + # Run once, at the initial point. + R1 = "prep => model" + # Run at 2-month intervals between the initial and final points. + P2M = "model[-P2M] => model => post_proc & archive" + [runtime] + [[model]] + script = "run-model $CYLC_TASK_CYCLE_POINT" + + +And here's how to do the same thing with parameterized tasks instead of cycling: + +.. code-block:: cylc + + [task parameters] + chunk = 1..6 + [scheduling] + [[graph]] + R1 = """ + prep => model + model => model => + post_proc & archive + """ + [runtime] + [[model]] + script = """ + # Compute start date from chunk index and interval. + INITIAL_POINT=2020-01 + INTERVAL_MONTHS=2 + OFFSET_MONTHS=(( (CYLC_TASK_PARAM_chunk - 1)*INTERVAL_MONTHS )) + OFFSET=P${OFFSET_MONTHS}M # e.g. P4M for chunk=3 + # Run the model. + run-model $(cylc cyclepoint --offset=$OFFSET $INITIAL_POINT) + """ + +The two workflows achieve the same result, and both can include special +behaviour at the start, end, or anywhere in between. + +.. todo + Create sub-figures if possible: for now hacked as separate figures with + link and caption on final displayed figure. + +.. figure:: ../../img/eg2-static.png + :align: center + +.. _fig-eg2: + +.. figure:: ../../img/eg2-dynamic.png + :align: center + + Parameterized (top) and cycling (bottom) versions of the same + workflow. The first three cycle points are shown in the + cycling case. The parameterized case does not have cycle points (technically + all of its tasks have the cycle point 1). + +The parameterized version has several disadvantages, however: + + - The workflow must be finite in extent and not too large because every + parameterized task generates a new task definition + + - (In a cycling workflow a single task definition acts as a template for + all cycle point instances of a task) + - Datetime arithmetic has to be done manually + + - (This doesn't apply if it's not a datetime sequence; parameterized + integer cycling is straightforward.) + + +Parameterized Sub-Cycles +^^^^^^^^^^^^^^^^^^^^^^^^ + +A workflow can have multiple main cycling sequences, but sub-cycles within each +main cycle point have to be parameterized. A typical use case for this is +incremental processing of files generated sequentially during a long model run. + +Here's a workflow that uses parameters to split a long model run in each +datetime cycle point into four smaller runs: + +.. code-block:: cylc + + [task parameters] + chunk = 1..4 + [scheduling] + initial cycle point = 2020-01 + [[graph]] + P1Y = """ + model => model + model[-P1Y] => model + """ + +The intercycle trigger connects the first chunk in each cycle point to the +last chunk in the previous cycle point. However, in this particular case it +might be simpler to use a 3-monthly datetime cycle instead: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2020-01 + [[graph]] + P3M = "model[-P3M] => model" + + +For another example, here task ``model`` generates 10 files in sequence as it +runs. Task ``proc_file0`` triggers when the model starts running, to wait for +and process the first file; when that is done, ``proc_file1`` triggers to wait +for the second file; and so on. + +.. code-block:: cylc + + [task parameters] + file = 0..9 + [scheduling] + initial cycle point = 2020-01 + [[graph]] + P1Y = """ + model:start => proc + proc => proc + proc => upload_products + """ + [runtime] + [[proc]] + # ... + + +Offsets at Sequence Start +^^^^^^^^^^^^^^^^^^^^^^^^^ + +In cycling workflows, dependence on tasks prior to the start cycle point is +ignored [1]_. So this graph: + +.. code-block:: cylc + + P1D = "model[-P1D] => model" + +simplifies at the initial cycle point to this: + +.. code-block:: cylc + + P1D = "model" + +(Note this is a convenient way to bootstrap into an infinite cycle, but special +behaviour at the start point can be configured explicitly if desired). + +Similarly, parameter offsets that go out of range are ignored. So this graph: + +.. code-block:: cylc + + # for chunk = 1..4 + R1 = "model => model" + +simplifies for ``chunk=1`` to this: + +.. code-block:: cylc + + R1 = "model_chunk0" + + +.. [1] Currently this only applies to the unique workflow start cycle point, so + it may be easier to use parameterized cycling if you have multiple + (finite) sequences starting at different points. We plan to extend this + convenience to all sequences regardless of start point, but use will be + optional because delayed-start cycling tasks may need to trigger off of + earlier cycles. diff --git a/nightly_8.4/html/_sources/user-guide/writing-workflows/runtime.rst.txt b/nightly_8.4/html/_sources/user-guide/writing-workflows/runtime.rst.txt new file mode 100644 index 00000000000..6363a7248b0 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/writing-workflows/runtime.rst.txt @@ -0,0 +1,791 @@ +.. _User Guide Runtime: + +Task Configuration +================== + +.. tutorial:: Runtime Tutorial + +The :cylc:conf:`[runtime]` section of the :cylc:conf:`flow.cylc` file +defines what job each :term:`task` should run, and where and how to +submit each one to run. + +It is an inheritance hierarchy that allows common settings to be factored +out and defined once in task :term:`families ` (duplication +of configuration is a maintenance risk in a complex workflow). + + +.. _namespace-names: + +Task and Family Names +--------------------- + +Task and family names must match in the graph and runtime sections of the +workflow config file. They do not need to match the names of the external +applications wrapped by the tasks. + +.. autoclass:: cylc.flow.unicode_rules.TaskNameValidator + +.. note:: + + At runtime, tasks can access their own workflow task name as + ``$CYLC_TASK_NAME`` in the job environment :ref:`job environment + ` if needed. + + +The following runtime configuration defines one family called ``FAM`` and two +member tasks ``fm1`` and ``fm2`` that inherit settings from it. Members can +also override inherited settings and define their own private settings. + +.. code-block:: cylc + + [runtime] + [[FAM]] # <-- a family + #... settings for all FAM members + + [[fm1]] # <-- task + inherit = FAM + #... fm1-specific settings + + [[fm2]] # <-- a task + inherit = FAM + #... fm2-specific settings + +Note that families are not nested in terms of the file sub-heading structure. A +runtime subsection defines a family if others inherit from it, otherwise +it defines a task. + + +The Root Family +--------------- + +All tasks inherit implicitly from a family called ``root`` that can provide +default settings for all tasks in the workflow (non-root families require an +explicit ``inherit`` statement). + +For example, if all tasks are to run on the same platform, that could +can be specified once for all tasks under ``root``: + +.. code-block:: cylc + + [runtime] + [[root]] + # all tasks run on hpc1 (unless they override this setting) + platform = hpc1 + + + +.. _MultiTaskDef: + +Defining Multiple Tasks or Families at Once +------------------------------------------- + +Runtime sub-section headings can be a comma-separated list of task or family +names, in which case the settings below it apply to each list member. + +Here a group of three related tasks all run the same script on the same +:term:`platform`, but pass their own names to it on the command line: + +.. code-block:: cylc + + [runtime] + [[ENSEMBLE]] + platform = hpc1 + script = "run-model.sh $CYLC_TASK_NAME" + + [[m1, m2, m3]] + inherit = ENSEMBLE + + [[m1]] + #... m1-specific settings + +Particular tasks (such as ``m1`` above) can still be singled out to add +task-specific settings. + + +.. note:: + + :ref:`Task parameters ` or template processing (see + :ref:`User Guide Jinja2` and :ref:`User Guide EmPy`) can be used to + programmatically generate family members and associated dependencies. + + +Families of Families +-------------------- + +Families can inherit from other families, to any depth. + +.. code-block:: cylc + + [runtime] + [[HPC1]] + platform = hpc1 + + [[BIG-HPC1]] + inherit = HPC1 + #... add in high memory batch system directives + + [[model]] # a big task that runs on hpc1 + inherit = BIG-HPC1 + +If the same item is defined (and redefined) at several levels in the family +tree, the highest level (closest to the task) takes precedence. + + +Inheriting from Multiple Parents +-------------------------------- + +Sometimes a multi-level single-parent tree is not sufficient to avoid all +duplication of settings. Fortunately tasks can inherit from multiple parents at +once [1]_: + +.. code-block:: cylc + + [runtime] + [[HPC1]] + platform = hpc1 + + [[BIG]] # high memory batch system directives + #... + + [[model]] # a big task that runs on hpc1 + inherit = BIG, HPC1 + + + +.. tip:: + + Use ``cylc config`` to check exactly what settings a task or family ends up + with after inheritance processing: + + .. code-block:: console + + $ cylc config --item "[runtime][model]environment" + + +First-parent Family Hierarchy for Visualization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Tasks can be collapsed into first-parent families in the Cylc GUI, so first +parents should reflect the logical purpose of a task where possible, rather +than (say) shared technical settings: + +.. code-block:: cylc + + [runtime] + [[HPC]] + # technical platform settings + + [[MODEL]] + # atmospheric model tasks + + [[atmos]] + inherit = MODEL, HPC # (not HPC, MODEL) + + +If this is not what you want, given that the primary purpose of the family +hierarchy is inheritance of runtime settings, a dummy first parent ``None`` can +be used to disable the visualization usage without affecting inheritance: + +.. code-block:: cylc + + [runtime] + [[BAR]] + #... + [[foo]] + # inherit from BAR but stay under root for visualization + inherit = None, BAR + + + + +.. _TaskExecutionEnvironment: + +Job Environment +--------------- + +:term:`Job scripts ` export various environment variables before +running ``script`` blocks (see :ref:`TaskJobSubmission`). + +Scheduler-defined variables appear first to identify the workflow, the task, +and log directory locations. These are followed by user-defined variables from +:cylc:conf:`[runtime][][environment]`. Order of variable definition +is preserved so that new variable assignments can reference previous ones. + +.. note:: + + Task environment variables are evaluated at runtime, by jobs, on the + job platform. So ``$HOME`` in a task environment, for instance, evaluates at + runtime to the home directory on the job platform, not on the scheduler + platform. + + +In this example the task ``foo`` ends up with ``SHAPE=circle``, ``COLOR=blue``, +and ``TEXTURE=rough`` in its environment: + +.. code-block:: cylc + + [runtime] + [[root]] + [[[environment]]] + COLOR = red + SHAPE = circle + [[foo]] + [[[environment]]] + COLOR = blue # root override + TEXTURE = rough # new variable + +Job access to Cylc itself is configured first so that variable +assignment expressions (as well as scripting) can use Cylc commands: + +.. code-block:: cylc + + [runtime] + [[foo]] + [[[environment]]] + REFERENCE_TIME = $(cylc cyclepoint --offset-hours=6) + + +Overriding Inherited Environment Variables +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. warning:: + + If you override an inherited task environment variable the parent config + item gets *replaced* before it is ever used to define the shell variable in + the :term:`job script`. Consequently the job cannot see the parent value as + well as the task value: + +.. code-block:: cylc + + [runtime] + [[FOO]] + [[[environment]]] + COLOR = red + [[bar]] + inherit = FOO + [[[environment]]] + tmp = $COLOR # !! ERROR: $COLOR is undefined here + COLOR = dark-$tmp # !! as this overrides COLOR in FOO. + +The compressed variant of this, ``COLOR = dark-$COLOR``, is also an error for +the same reason. To achieve the desired result, use a different name for the +parent variable: + +.. code-block:: cylc + + [runtime] + [[FOO]] + [[[environment]]] + FOO_COLOR = red + [[bar]] + inherit = FOO + [[[environment]]] + COLOR = dark-$FOO_COLOR # OK + + +.. _Task Job Script Variables: + +Job Script Variables +^^^^^^^^^^^^^^^^^^^^ + +These variables provided by the :term:`scheduler` are available to +:term:`job scripts `: + +.. literalinclude:: ../../reference/job-script-vars/var-list.txt + :language: sub + +Some global shell variables are also defined in the job script, but not +exported to subshells: + +.. code-block:: sub + + CYLC_FAIL_SIGNALS # List of signals trapped by the error trap + CYLC_VACATION_SIGNALS # List of signals trapped by the vacation trap + CYLC_TASK_MESSAGE_STARTED_PID # PID of "cylc message" job started" command + CYLC_TASK_WORK_DIR_BASE # Alternate task work directory, + # relative to the workflow work directory + + +.. _workflow_share_directories: + +Workflow Share Directories +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The workflow :term:`share directory` is created automatically under the +workflow run directory as a convenient shared space for tasks. The location is +available to tasks as ``$CYLC_WORKFLOW_SHARE_DIR``. In a cycling workflow, +output files are typically held in cycle point sub-directories of this. + +The top level share directory location can be changed, e.g. to a large data +area, by global config settings under :cylc:conf:`global.cylc[install][symlink dirs]`. + +If your workflow creates or installs executables or Python libraries +as it is running, these can be placed in: + +* ``share/bin/`` - for executables. This location is automatically added to ``PATH`` + (before the top-level ``bin/`` in the run dir). +* ``share/lib/python/`` - for Python modules. This location is automatically added + to ``$PYTHONPATH`` (before the top-level ``lib/python/`` in the run dir). + +.. note:: + + Cylc will not create these folders. + +.. seealso:: + + :ref:`Top level "bin/" and "lib/python/" directories `. + + +Task Work Directories +^^^^^^^^^^^^^^^^^^^^^ + +Job scripts are executed from within :term:`work directories ` created automatically under the workflow run directory. A task can +access its own work directory via ``$CYLC_TASK_WORK_DIR`` (or simply ``$PWD`` +if it does not change to another location at runtime). By default the location +contains task name and cycle point, to provide a unique workspace for every +instance of every task. + +The top level work directory location can be changed, e.g. to a large data +area, by global config settings under :cylc:conf:`global.cylc[install][symlink dirs]`. + + +.. _RunningTasksOnARemoteHost: + +Remote Task Hosting +------------------- + +Job :term:`platforms ` are defined in ``global.cylc[platforms]``. + +If a task declares a different platform to that where the scheduler is running, +Cylc uses non-interactive SSH to submit the job to the platform :term:`job +runner` on one of the platform hosts. Workflow source files will be installed +on the platform, via the associated ``global.cylc[install targets]``, just +before the first job is submitted to run there. + +.. code-block:: cylc + + [runtime] + [[foo]] + platform = orca + +For this to work: + +- Non-interactive SSH is required from the :term:`scheduler` host + to the platform hosts +- Cylc must be installed on the hosts of the destination platform + + - If polling task communication is used, there is no other requirement + - If SSH task communication is configured, non-interactive SSH is required + from the job platform to the scheduler platform + - If TCP (default) task communication is configured, the task platform + should have access to the Cylc ports on the scheduler host + +Platforms, like other runtime settings, can be declared globally in the root +family, or in other families, or for individual tasks. + +.. note:: + + The platform known as ``localhost`` is the platform where the scheduler + is running, in many cases a dedicated server and *not* your desktop. + +Internal Platform and Host Selection +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The :cylc:conf:`[runtime][]platform` item points to either a +:cylc:conf:`platform ]>` or a +:cylc:conf:`platform group ]>`. + +:term:`Cylc platforms ` allow you to configure compute platforms +you wish Cylc to run jobs on. + +:term:`Platform groups ` allow you to group together platforms +any of which would be suitable for a given job. +Platform groups can improve robustness by allowing jobs to be submitted on +any platform in the group, as well as providing an interface for +:cylc:conf:`basic load balancing +][selection]method>`. + +:term:`Platforms ` are selected from a :term:`platform group` once, +when a job is submitted. + +Hosts within a :term:`platform` are re-selected each time the scheduler +needs to communicate with a job. + +.. seealso:: + + :ref:`AdminGuide.PlatformConfigs`: For details of how Platforms and + Platform Groups are set up and in-depth examples. + +External Platform Selection Scripts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. deprecated:: 8.0.0 + + Cylc 8 can select hosts from a group of suitable hosts listed in the + platform config, so in many cases this logic should no longer be necessary. + +Instead of hardwiring platform names into the workflow configuration you can +give a command that prints a platform name, or an environment variable, as the +value of :cylc:conf:`[runtime][]platform`. + +For example: + +.. code-block:: cylc + :caption: flow.cylc + + [runtime] + [[mytask]] + platform = $(script-which-returns-a-platform-name) + +Job hosts are always selected dynamically, for the chosen platform or +platform group. + +.. caution:: + + If ``$(script-which-returns-a-platform-name)`` returns a non-zero exit + code then the scheduler will assign the + :ref:`submit-failed ` state to this :term:`job`. + If you have submit retries set up for the job, the scheduler will retry + running your platform selection script in the same was is it would for + any other submission failure. + +Remote Job Log Directories +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Job stdout and stderr streams are written to :term:`log files ` +under the workflow :term:`run directory` (see :ref:`WhitherStdoutAndStderr`). +For remote tasks the same directory is used, on the job host. + + +.. _ImplicitTasks: + +Implicit Tasks +-------------- + +An implicit task is one that appears in the graph but is not defined under +:cylc:conf:`flow.cylc[runtime]`. + +Depending on the value of :cylc:conf:`flow.cylc[scheduler]allow implicit tasks`, +Cylc can automatically create default task definitions for these, to submit +local dummy jobs that just return the standard job status messages. + +Implicit tasks can be used to mock up functional workflows very quickly. A +default ``script`` can be added to the root family, e.g. to slow job execution +down a little. Here is a complete workflow definition using implicit tasks: + +.. code-block:: cylc + + [scheduler] + allow implicit tasks = True + [scheduling] + [[graph]] + R1 = "prep => run-a & run-b => done" + [runtime] + [[root]] + script = "sleep 10" + + +.. warning:: + Implicit tasks are somewhat dangerous because they can easily be created by + mistake: misspelling a task's name divorces it from its ``runtime`` definition. + +For this reason implicit tasks are not allowed by default, and if used they +should be turned off once the real task definitions are complete. + +You can get the convenience without the danger with a little more effort, by +adding empty runtime placeholders instead of allowing implicit tasks: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = "prep => run-a & run-b => done" + [runtime] + [[root]] + script = "sleep 10" + [[prep]] + [[run-a, run-b]] + [[done]] + + +.. _TaskRetries: + +Task Retry On Failure +--------------------- + +.. seealso:: + + :cylc:conf:`[runtime][]execution retry delays`. + +Tasks can have a list of :term:`ISO8601 durations ` as retry +intervals. If the job fails the task will return to the ``waiting`` state +with a clock-trigger configured with the next retry delay. + + +.. note:: + + Tasks only enter the ``submit-failed`` state if job submission fails with no + retries left. Otherwise they return to the waiting state, to wait on the + next try. + + Tasks only enter the ``failed`` state if job execution fails with no retries + left. Otherwise they return to the waiting state, to wait on the next try. + + + +In the following example, tasks ``bad`` and ``flaky`` each have 3 retries +configured, with a 10 second delay between. On the final try, ``bad`` fails +again and goes to the ``failed`` state, while ``flaky`` succeeds and triggers +task ``whizz`` downstream. The scheduler will then stall because +``bad`` failed (which is a :term:`final status`) with incomplete outputs. + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + bad => cheese + flaky => whizz + """ + [runtime] + [[bad]] + # retry 3 times then fail + script = """ + sleep 10 + false + """ + execution retry delays = 3*PT10S + [[flaky]] + # retry 3 times then succeed + script = """ + sleep 10 + test $CYLC_TASK_TRY_NUMBER -gt 3 + """ + execution retry delays = 3*PT10S + [[cheese, whizz]] + script = "sleep 10" + + +.. _user_guide.runtime.task_event_handling: + +Task Event Handling +------------------- + +Task event handlers allow configured commands to run when task events occur. + +.. note:: + + Cylc supports workflow events e.g. ``startup`` and ``shutdown`` + and task events e.g. ``submitted`` and ``failed``. + + See also :ref:`user_guide.scheduler.workflow_event_handling`. + +Event handlers can be used to send a message, raise an alarm, or whatever you +like. They can even call ``cylc`` commands to intervene in the workflow. + +Task event handlers are configured by +:cylc:conf:`flow.cylc[runtime][][events]`. + +.. note:: + + Task event handlers are called by the :term:`scheduler`, not by the task + jobs that generate the events - so they do not see the job environment. + +Event handlers can be stored in the workflow ``bin`` directory, or anywhere in +``$PATH`` in the :term:`scheduler` environment. + +They should return quickly to avoid tying up the scheduler process pool - +see :ref:`Managing External Command Execution`. + + +.. _user_guide.runtime.task_event_handling.event_specific_handlers: + +Event-Specific Handlers +^^^^^^^^^^^^^^^^^^^^^^^ + +Event-specific handlers are configured by `` handlers`` +under :cylc:conf:`[runtime][][events]`, where ```` +can be: + +.. |br| raw:: html + +
+ + +.. table:: + + ========================================= ================================ + Event Description + ========================================= ================================ + submitted job submitted + submission retry job submission failed but will retry later + submission failed job submission failed + started job started running + retry job failed but will retry later + failed job failed + succeeded job succeeded + submission timeout job timed out in the ``submitted`` state + execution timeout job timed out in the ``running`` state + warning scheduler received a message of severity WARNING from job + critical scheduler received a message of severity CRITICAL from job + custom scheduler received a message of severity CUSTOM from job |br| (note: literally, the word ``CUSTOM``) + expired task expired and will not submit (too far behind) + late task running later than expected + ========================================= ================================ + +Values should be a list of commands, command lines, or command line templates +(see below) to call if the specified event is triggered. + + +.. _user_guide.runtime.task_event_handling.general_event_handlers: + +General Event Handlers +^^^^^^^^^^^^^^^^^^^^^^ + +.. cylc-scope:: flow.cylc[runtime][][events] + +Alternatively you can configure a list of generic event :cylc:conf:`handlers` to be run +for configured :cylc:conf:`handler events`. + +:cylc:conf:`handler events` + A list of events which may include any of the above + events (e.g. ``submission failed`` or ``warning``) or + any of a task's :term:`custom outputs `. +:cylc:conf:`handlers` + A list of commands to be run for these events. + Information about the event can be provided using + :ref:`user_guide.runtime.event_handlers.task_event_handling.template_variables`. + +Example: + +.. code-block:: cylc + + handlers = """ + my-handler %(event)s %(workflow)s, + echo %(workflow)s-%(event)s >> my-log-file + """ + handler events = submission failed, failed, warning, my-custom-output + +.. cylc-scope:: + + +.. _user_guide.runtime.event_handlers.task_event_handling.template_variables: + +Task Event Template Variables +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoenumvalues:: cylc.flow.task_events_mgr.EventData + +Examples +^^^^^^^^ + +The following :cylc:conf:`flow.cylc` snippets illustrate the two (general and +task-specific) ways to configure event handlers: + +.. code-block:: cylc + + [runtime] + [[foo]] + script = test ${CYLC_TASK_TRY_NUMBER} -eq 2 + execution retry delays = PT0S, PT30S + [[[events]]] # event-specific handlers: + retry handlers = notify-retry.py + failed handlers = notify-failed.py + +.. code-block:: cylc + + [runtime] + [[foo]] + script = """ + test ${CYLC_TASK_TRY_NUMBER} -eq 2 + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" 'oopsy daisy' + """ + execution retry delays = PT0S, PT30S + [[[events]]] # general handlers: + handlers = notify-events.py + # Note: task output name can be used as an event in this method + handler events = retry, failed, oops + [[[outputs]]] + oops = oopsy daisy + +Built-in Email Event Handler +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To send an email on task events, configure relevant tasks with a list of events +to handle by email. Custom task output names can also be used as event names, +in which case the event triggers when the output message is received. + +E.g. to send an email on task failed, retry, and a custom message event: + +.. code-block:: cylc + + [runtime] + [[foo]] + script = """ + test ${CYLC_TASK_TRY_NUMBER} -eq 3 + cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" 'oopsy daisy' + """ + execution retry delays = PT0S, PT30S + [[[events]]] + mail events = failed, retry, oops + [[[outputs]]] + oops = oopsy daisy + +By default, event emails will be sent to the current user with: + +- ``to:`` set as ``$USER`` +- ``from:`` set as ``notifications@$(hostname)`` +- SMTP server at ``localhost:25`` + +These can be configured using the settings: + +.. cylc-scope:: flow.cylc[runtime][] + +- :cylc:conf:`[mail]to` (list of email addresses) +- :cylc:conf:`[mail]from` + +.. cylc-scope:: + +The scheduler batches events over a 5 minute interval, by default, to avoid +flooding your Inbox if many events occur in a short time. The batching interval +can be configured with :cylc:conf:`[scheduler][mail]task event batch interval`. + + +.. _Late Events: + +Late Events +^^^^^^^^^^^ + +.. warning:: + + The scheduler can only check for lateness once a task has appeared in its + active task window. In Cylc 8 this is usually when the task is actually + ready to run, which severely limits the usefulness of late events as + currently implemented. + +If a real time (clock-triggered) workflow performs fairly consistently from one +cycle to the next, you may want to be notified when certain tasks are running +late with respect the time they normally trigger in each cycle. + +Cylc can generate a *late* event if a task has not triggered by a given offset +from its cycle point in real time. For example, if a task ``forecast`` normally +triggers at 30 minutes after cycle point, a late event could be configured like this: + +.. code-block:: cylc + + [runtime] + [[forecast]] + script = run-model.sh + [[[events]]] + late offset = PT40M # allow a 10 minute delay + late handlers = my-handler %(message)s + +.. warning:: + Late offset intervals are not computed automatically so be careful to update + them after any workflow change that affects triggering times. + +.. [1] The order of precedence for inheritance from multiple parents is + determined by the `C3 algorithm + `_ used to find + the linear method resolution order for multiple inheritance in Python. diff --git a/nightly_8.4/html/_sources/user-guide/writing-workflows/scheduler.rst.txt b/nightly_8.4/html/_sources/user-guide/writing-workflows/scheduler.rst.txt new file mode 100644 index 00000000000..497ab0ccb46 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/writing-workflows/scheduler.rst.txt @@ -0,0 +1,327 @@ +Scheduler Configuration +======================= + +The :cylc:conf:`flow.cylc[scheduler]` section configures certain aspects of +:term:`scheduler` behaviour at the workflow level. + +Many of these configurations can also be defined at the site or user level in +the :cylc:conf:`global.cylc[scheduler]` section where it applies to all +workflows. + + +.. _user_guide.scheduler.workflow_event_handling: +.. _user_guide.scheduler.workflow_events: + +Workflow Events +--------------- + +There are two types of event in Cylc: + +* workflow events e.g. ``startup`` and ``shutdown``, which pertain to the :term:`scheduler` +* task events e.g. ``submitted`` and ``failed``, which pertain to :term:`tasks `. + +This section covers workflow events, for +task events see :ref:`user_guide.runtime.task_event_handling`. + +.. rubric:: Event Handlers + +Workflow events have "handlers" (i.e. hooks) which allow configured commands to +run when workflow events occur. These can be configured by: + +* :cylc:conf:`flow.cylc[scheduler][events]` (per workflow) +* :cylc:conf:`global.cylc[scheduler][events]` (user/site defaults) + +.. rubric:: Abort On Event + +As well as event handlers, you can tell the scheduler to abort (i.e., shut down +immediately with error status) on certain workflow events, using the +``abort on ...`` configurations. + +.. rubric:: Configuration + +Some workflow events have related configurations e.g. for setting the timeout. + +.. rubric:: List of workflow events: + +.. cylc-scope:: global.cylc[scheduler][events] + +.. describe:: startup + + :Event Handler: `startup handlers` + + The scheduler was started or restarted. + + E.G. using one of these commands ``cylc play``, ``cylc vip`` or ``cylc vr``. + +.. describe:: shutdown + + :Event Handler: `shutdown handlers` + + The scheduler was shut down. + + E.G. using the ``cylc stop`` command. + +.. describe:: abort + + :Event Handler: `abort handlers` + + The scheduler shut down early with error status, due to a fatal error + condition or a configured timeout. + +.. describe:: workflow timeout + + :Configuration: `workflow timeout` + :Event Handler: `workflow timeout handlers` + :Abort On Event: `abort on workflow timeout` + + The workflow run timed out. + + The timer starts counting down at scheduler startup. It resets on workflow + restart. + + Note, the ``abort`` event is not raised by "Abort On Event" handlers. + +.. describe:: stall + + :Event Handler: `stall handlers` + + The workflow :term:`stalled ` (i.e. the scheduler cannot make any + further progress due to runtime events). + + E.G. a task failure is blocking the pathway through the graph. + +.. describe:: stall timeout + + :Configuration: `stall timeout` + :Event Handler: `stall timeout handlers` + :Abort On Event: `abort on stall timeout` + + The workflow timed out after stalling. + +.. describe:: inactivity timeout + + :Configuration: `inactivity timeout` + :Event Handler: `inactivity timeout handlers` + :Abort On Event: `abort on inactivity timeout` + + The workflow timed out with no activity (i.e. a period with no job + submissions or task messages). + + This can be useful for system administrators to help catch workflows which + have become stalled on external conditions or system issues. + +.. describe:: restart timeout + + :Configuration: `restart timeout` + + If a workflow that has run to completion is restarted, the scheduler will + have nothing to do so will shut down. This timeout gives the user a grace + period in which to trigger new tasks to continue the workflow run. + +.. cylc-scope:: + +Mail Events +^^^^^^^^^^^ + +Cylc can send emails for workflow events, these are configured by +:cylc:conf:`flow.cylc[scheduler][events]mail events`. + +For example with the following configuration, emails will be sent if a +scheduler stalls or shuts down for an unexpected reason. + +.. code-block:: cylc + + [scheduler] + [[events]] + mail events = stall, abort + +Email addresses and servers are configured by +:cylc:conf:`global.cylc[scheduler][mail]`. + +Workflow event emails can be customised using +:cylc:conf:`flow.cylc[scheduler][mail]footer`, +:ref:`workflow_event_template_variables` can be used. + +For example to integrate with the Cylc 7 web interface (Cylc Review) the mail +footer could be configured with a URL: + +.. code-block:: cylc + + [scheduler] + [[events]] + mail footer = http://cylc-review/taskjobs/%(owner)s/?suite=%(workflow)s + +Custom Event Handlers +^^^^^^^^^^^^^^^^^^^^^ + +Cylc can also be configured to invoke scripts on workflow events. + +Event handler scripts can be stored in the workflow ``bin`` directory, or +anywhere in ``$PATH`` in the :term:`scheduler` environment. + +They should return quickly to avoid tying up the scheduler process pool - +see :ref:`Managing External Command Execution`. + +Contextual information can be passed to the event handler via +:ref:`workflow_event_template_variables`. + +For example the following configuration will write some information to a file +when a workflow is started: + +.. code-block:: bash + :caption: ~/cylc-run//bin/my-handler + + #!/bin/bash + + echo "Workflow $1 is running on $2:$3" > info + +.. code-block:: cylc + :caption: flow.cylc or global.cylc + + [scheduler] + [[events]] + startup handlers = my-handler %(workflow)s %(host) %(port) + + +.. note:: + + If you wish to use custom Python Libraries in an event handler you + need to add these to ``CYLC_PYTHONPATH`` rather than ``PYTHONPATH``. + +.. _workflow_event_template_variables: + +Workflow Event Template Variables +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoenumvalues:: cylc.flow.workflow_events.EventData + + +.. _Managing External Command Execution: + +External Command Execution +-------------------------- + +Job submission commands, event handlers, and job poll and kill commands, are +executed by the :term:`scheduler` in a subprocess pool. The pool is size can +be configured with :cylc:conf:`global.cylc[scheduler]process pool size`. + +Event handlers should be lightweight and quick-running because they tie up +a process pool member until complete, and the workflow will appear to stall if +the pool is saturated with long-running processes. + +To protect the scheduler, processes are killed on a timeout +(:cylc:conf:`global.cylc[scheduler]process pool timeout`). This will be +logged by the :term:`scheduler`. If a job submission gets killed, the +associated task goes to the ``submit-failed`` state. + + +.. _Submitting Workflows To a Pool Of Hosts: + +Submitting Workflows To a Pool Of Hosts +--------------------------------------- + +:Configured by: :cylc:conf:`global.cylc[scheduler][run hosts]`. + +By default ``cylc play`` will run workflows on the machine where the command +was invoked. + +Cylc supports configuring a pool of hosts for workflows to run on, +``cylc play`` will automatically pick a host and submit the workflow to it. + +Host Pool +^^^^^^^^^ + +:Configured by: :cylc:conf:`global.cylc[scheduler][run hosts]available`. + +The hosts must: + +1. Share a common ``$HOME`` directory and therefore a common file system + (with each other and anywhere the ``cylc play`` command is run). +2. Share a common Cylc global config (:cylc:conf:`global.cylc`). +3. Be set up to allow passwordless SSH between them. + +Example: + +.. code-block:: cylc + + [scheduler] + [[run hosts]] + available = host_1, host_2, host_3 + +Load Balancing +^^^^^^^^^^^^^^ + +:Configured by: :cylc:conf:`global.cylc[scheduler][run hosts]ranking`. + +Cylc can balance the load on the configured "run hosts" by ranking them in +order of available resource or by excluding hosts which fail to meet certain +criterion. + +Example: + +.. code-block:: cylc + + [scheduler] + [[run hosts]] + available = host_1, host_2, host_3 + ranking = """ + # filter out hosts with high server load + getloadavg()[2] < 5 + + # pick the host with the most available memory + virtual_memory().available + """ + +For more information see :cylc:conf:`global.cylc[scheduler][run hosts]ranking`. + +.. _auto-stop-restart: + +Workflow Migration +^^^^^^^^^^^^^^^^^^ + +:Configured by: :cylc:conf:`global.cylc[scheduler][run hosts]condemned`. + +Cylc has the ability to automatically stop workflows running on a particular +host and optionally, restart them on a different host. This can be useful if a +host needs to be taken off-line, e.g. for scheduled maintenance. + +Example: + +.. code-block:: cylc + + [scheduler] + [[run hosts]] + available = host_1, host_2, host_3 + # tell workflows on host_1 to move to another available host + condemned = host_1 + +.. note:: + + .. cylc-scope:: global.cylc[scheduler][main loop] + + This feature requires the :cylc:conf:`[auto restart]` + plugin to be enabled, e.g. in the configured list of + :cylc:conf:`plugins`. + + .. cylc-scope:: + +For more information see: :cylc:conf:`global.cylc[scheduler][run hosts]ranking`. + +.. _PlatformConfig: + +Platform Configuration +^^^^^^^^^^^^^^^^^^^^^^ + +From the perspective of a running :term:`scheduler` ``localhost`` is the +scheduler host. + +The ``localhost`` platform is configured by +:cylc:conf:`global.cylc[platforms][localhost]`. + +It configures: + +* Jobs that run on the ``localhost`` platform, i.e. any jobs which have + :cylc:conf:`[runtime][]platform=localhost` or which don't have a + platform configured. +* Connections to the scheduler hosts (e.g. the + :cylc:conf:`ssh command ]ssh command>`). diff --git a/nightly_8.4/html/_sources/user-guide/writing-workflows/scheduling.rst.txt b/nightly_8.4/html/_sources/user-guide/writing-workflows/scheduling.rst.txt new file mode 100644 index 00000000000..d0c1383e1a2 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/writing-workflows/scheduling.rst.txt @@ -0,0 +1,2319 @@ +.. _User Guide Scheduling: + +Scheduling Configuration +======================== + +.. tutorial:: Scheduling Tutorial + +The :cylc:conf:`[scheduling]` section of the :cylc:conf:`flow.cylc` file +defines what tasks exist in the workflow, in a :term:`dependency graph `, +and when they should run, relative to each other and to constraints such as +:term:`clock triggers `, :term:`external triggers `, and :term:`internal queues ` + + +The Graph +--------- + +.. tutorial:: Graph Tutorial + +The :term:`graph` defines a workflow in terms of its :term:`tasks ` and +the :term:`dependencies ` between them. + +A Cylc :term:`graph` is composed of one or more :term:`graph strings ` which use a special syntax to define the dependencies between tasks: + +* arrow symbols ``=>`` declare dependencies +* logical operators ``&`` (AND) and ``|`` (OR) can be used to write + :term:`conditional dependencies `. + +For example: + +.. code-block:: cylc-graph + + # baz will not be run until both foo and bar have succeeded + foo & bar => baz + +Graph strings are configured under the :cylc:conf:`[scheduling][graph]` section +of the :cylc:conf:`flow.cylc` file: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + foo & bar => baz + """ + +In this example ``R1`` is a :term:`recurrence expression ` that +defines how often, and on what cycle interval, to run this part of the graph. +For example, ``R1`` means run once, and ``P1D`` means run repeatedly on a 1-day +cycle. + +Graph strings may contain blank lines, arbitrary white space and comments e.g: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + foo & bar => baz # baz depends on foo and bar + + """ + +Graphs can be broken down into pairs of :term:`triggers `, where the +left side is a single task output, or a logical expression involving several of +them, and the right side is the task or family that triggers when the output +(or expression) is completed. + +In the case of cycling tasks, triggers are valid for cycle points matching the +recurrence expression for the graph string. For example this graph: + +.. code-block:: cylc + + [scheduling] + [[graph]] + T00,T12 = "A => B" + +implies that ``B`` triggers off of ``A`` (i.e. off of the ``A:succeeded`` output) +for cycle points where the hour matches ``00`` or ``12``. To define intercycle +dependencies, attach an offset indicator to the left side of a pair: + +.. code-block:: cylc + + [scheduling] + [[graph]] + T00,T12 = "A[-PT12H] => B" + +This means task ``B`` triggers off of task ``A[-PT12H]`` (12 hours before, with +respect to cycle point) at every point with hours matching ``00`` and ``12`` in +a sequence starting at the initial cycle point. +Note: current cycle point is implicit - only offsets need to be specified - +because most tasks depend only on others with the same cycle point. + +Cycle point offsets can only appear on the left side of an arrow. However, +``A => B[-PT6H]``, which is illegal, can be reformulated as a :term:`future +trigger` ``A[+PT6H] => B`` (see :ref:`InterCyclePointTriggers`). It is also +possible to combine multiple offsets within a cycle point offset e.g. + +.. code-block:: cylc + + [scheduling] + [[graph]] + T00,T12 = "A[-P1D-PT12H] => B" + +This means that ``B`` triggers off ``A[-P1D-PT12H]`` (1 day and 12 hours before) +at each cycle point. + +Triggers can be chained together. This graph: + +.. code-block:: cylc + + T00, T12 = """ + A => B # B triggers off A + B => C # C triggers off B + """ + +is equivalent to this: + +.. code-block:: cylc + + T00, T12 = "A => B => C" + +All triggers defined for the same task combine, so this: + +.. code-block:: cylc + + T00, T12 = """ + A => X # X triggers off A + B => X # X also triggers off B + """ + +is equivalent to this: + +.. code-block:: cylc + + T00, T12 = "A & B => X" # X triggers off A AND B + +In summary, the branching tree structure of a dependency graph can +be partitioned into lines (in the :cylc:conf:`flow.cylc` graph string) of +dependency pairs or chains, in any way you like. Use white space and comments +to make the graph as clear as possible. + +.. code-block:: cylc + + # B triggers if A succeeds, then C and D trigger if B succeeds: + R1 = "A => B => C & D" + + # which is equivalent to this: + R1 = """ + A => B => C + B => D + """ + + # and to this: + R1 = """ + A => B => D + B => C + """ + + # and to this: + R1 = """ + A => B + B => C + B => D + """ + + # and it can even be written like this: + R1 = """ + A => B # blank line follows: + + B => C # comment ... + B => D + """ + +Splitting Up Long Graph Lines +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It is not necessary to use the fragile line continuation marker ``\`` to split +long graph lines. You can break at dependency arrows (``=>``) and operators +(``&``, ``|``), or split long chains into smaller ones. This graph: + +.. code-block:: cylc + + R1 = "A & B => C" + +is equivalent to this: + +.. code-block:: cylc + + R1 = """ + A & B => + C + """ + +and also to this: + +.. code-block:: cylc + + R1 = """ + A & + B => C + """ + +.. note:: + + Multiple graph strings add together to make the complete workflow graph. + + +.. versionchanged:: 8.0.0 + + Graph strings can be broken on ``&`` and ``|`` as well as ``=>``. + + +.. _GraphTypes: + +Graph Types +----------- + +Non-Cycling +^^^^^^^^^^^ + +The following is a small workflow of non-cycling tasks; these all have a +single cycle point (``1``), and once they're all finished the scheduler +shuts down. + +.. Need to use a 'container' directive to get centered image with + left-aligned caption (as required for code block text). + +.. container:: twocol + + .. container:: caption + + .. code-block:: cylc + + [scheduling] + [[graph]] + R1 = "foo => bar & baz => qux" + + .. container:: image + + .. _fig-test1: + + .. figure:: ../../img/test1.png + :align: center + +Cycling Graphs +^^^^^^^^^^^^^^ + +For cycling tasks we give a *recurrence expression* that defines a sequence of +cycle points for which the graph string is valid, as demonstrated here for a +small workflow of cycling tasks: + +.. Need to use a 'container' directive to get centered image with + left-aligned caption (as required for code block text). + +.. container:: twocol + + .. container:: caption + + .. code-block:: cylc + + [scheduling] + [[graph]] + # (note no dependence between cycle points) + T00,T12 = "foo => bar & baz => qux" + + .. container:: image + + .. _fig-test2: + + .. figure:: ../../img/test2.png + :align: center + + +.. tutorial:: Datetime Tutorial + +For example in the following scenario: + +.. code-block:: cylc + + [scheduling] + [[graph]] + T06 = foo => bar + +``T06`` means "Run every day starting at 06:00 after the +initial cycle point". Cylc allows you to start (or end) at any particular +time, repeat at whatever frequency you like, and even optionally limit the +number of repetitions. + +.. _writing_flows.scheduling.syntax_rules: + +Cycling Syntax Rules +-------------------- + +:term:`Datetime cycling ` information is made up of: + +* a :term:`datetime ` that typically specifies the start + point of the sequence +* an interval between points in the sequence +* and an optional limit on the number of points in the sequence + +The time is assumed to be in UTC unless you set +:cylc:conf:`[scheduler]cycle point time zone`. + +.. attention:: + + .. versionchanged:: 8.0.0 + + At Cylc 7 the time zone was assumed to be local time unless + :cylc:conf:`[scheduler]cycle point time zone` or :cylc:conf:`[scheduler]UTC mode` + was set. If your workflow is running in + :ref:`Cylc 7 compatibility mode ` + this remains the case. + +The calendar is assumed to be the proleptic Gregorian calendar unless +you set :cylc:conf:`[scheduling]cycling mode`. + +The syntax is based on the :term:`ISO 8601` datetime standard, which includes +the representation of datetimes and intervals. Cylc (optionally) allows these +representations to be heavily condensed by omitting information that can be +inferred from context (rules below). + +.. important:: + + Cycle points in Cylc are just task labels that anchor dependence on + other tasks, and which tasks can use to determine their current cycle + point. **Datetime cycle points have no relation to wallclock (real) time** + except where specific tasks, if any, depend on :term:`clock triggers `. + +There are three ISO 8601 recurrence formats supported by Cylc, detailed below +in order from most commonly used to least commonly used. + + +.. _user_guide.cycling_format_3: + +Format 3: ``R[limit?]/[datetime]/[interval]`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The most common full form for recurrences is +``R[limit?]/[datetime]/[interval]``. This is format number 3 in the ISO 8601 +standard. The datetime specifies the start of the cycling sequence. +For example, ``R3/2000-01-01T00Z/P2D`` means "run 3 times, every 2 days, +starting at 2000-01-01T00Z (midnight, Jan 1st 2000)"; the list of points +on this sequence is: + +.. code-block:: none + + 2000-01-01T00Z + 2000-01-03T00Z + 2000-01-05T00Z + +In Cylc, this form can be condensed to: + +.. code-block:: sub + + R[limit?]/[datetime] + R[limit?]//[interval] + [datetime]/[interval] + R[limit?] # Special limit of 1 case + [datetime] + [interval] + +Here are some examples for each form: + +.. code-block:: sub + + R5/T00 # Run 5 times at 00:00 every day + R//PT1H # Run every hour (Note the R// is optional) + 20000101T06Z/P1D # Run every day starting at 06:00 1st Jan 2000 + R1 # Run once at the initial cycle point + R1/20000101T00Z # Run once at 00:00 1st Jan 2000 + P1Y # Run every year + +.. note:: + + ``T00`` is an example of ``[datetime]``, with an + inferred 1 day period and no limit (it is short for ``R/T00``). + +Where some or all datetime information is omitted, it is inferred to +be relative to the :term:`initial cycle point`. For example, ``T00`` +by itself would mean the next occurrence of midnight that follows, or is, the +initial cycle point. ``+PT6H`` means 6 hours after the initial cycle point. +``-P1D`` means 1 day before the initial cycle point. The default is the initial +cycle point itself. + +If the interval is omitted and some (but not all) datetime information is +omitted, it is inferred to be a single unit above the largest given specific +datetime unit. For example, the largest given specific unit in ``T00`` is +hours, so the inferred interval is 1 day (daily), ``P1D``. + +If the limit is omitted, unlimited cycling is assumed. This will be +bounded by the workflow's final cycle point if given. + + +.. _user_guide.cycling_format_4: + +Format 4: ``R[limit?]/[interval]/[datetime]`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Another supported recurrence form is: +``R[limit?]/[interval]/[datetime]`` (format number 4 in the ISO 8601 standard). +This uses the datetime as the end of the cycling sequence rather than the start. +For example, ``R3/P5D/2014-04-30T06`` means "run 3 times, every 5 days, ending +at 2014-04-30T06 (06:00, April 30th 2014)"; the list of points on this +sequence is: + +.. code-block:: none + + 2014-04-20T06 + 2014-04-25T06 + 2014-04-30T06 + +This form can be used to get special behaviour relative to +the final cycle point. + +We can also represent this in Cylc with a collapsed form: + +.. code-block:: none + + R[limit?]/[interval] + R[limit?]//[datetime] + [interval]/[datetime] + +So, for example, you can write: + +.. code-block:: sub + + R1//+P0D # Run once at the final cycle point + R5/P2D # Run 5 times, every 2 days, ending at the final cycle point + P2W/T00 # Run every 2 weeks ending at 00:00 before/at the final cycle point + R//T00 # Run every day ending at 00:00 before/at the final cycle point + + +.. _user_guide.cycling_format_1: + +Format 1: ``R[limit?]/[datetime]/[datetime]`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A less common recurrence form is ``R[limit?]/[datetime]/[datetime]`` +(format number 1 in the ISO 8601 standard). This uses the difference between +the first datetime and the second datetime to set the recurrence interval. +The first datetime is the start point. For example, +``R3/2020-07-10/2020-07-15`` means "run 3 times, every 5 days, starting at +2020-07-10 (midnight, July 10th 2020)"; the list of points on this sequence is: + +.. code-block:: none + + 2020-07-10 + 2020-07-15 + 2020-07-20 + +.. caution:: + + Cylc will always calculate the interval in + :term:`exact datetime units `. So for the example + of ``R/2004/2005``, the interval will be ``P366D`` (2004 is a leap year) + rather then ``P1Y``, because year is an + :term:`inexact unit `. + +.. note:: + + In versions of Cylc prior to 8.0.0, this syntax was undocumented and + behaved differently, in a way which was not in accordance with the + :term:`ISO 8601` standard. + + +.. _referencing-the-initial-and-final-cycle-points: + +Referencing The Initial And Final Cycle Points +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The caret and dollar symbols are shorthand for the initial and final cycle +points: + +.. code-block:: sub + + R1/^+PT12H # Repeat once 12 hours after the initial cycle point + # R[limit]/[datetime] + # Equivalent to R1/+PT12H + R1/$ # Repeat once at the final cycle point + # R[limit]/[datetime] + # Equivalent to R1//+P0D + $-P2D/PT3H # Repeat 3 hourly starting two days before the + # [datetime]/[interval] + # final cycle point + +.. note:: + + There are multiple ways to write the same recurrences, for instance + the following all run once at the final cycle point: + + .. code-block:: sub + + R1/P0Y # R[limit]/[interval] + R1/P0Y/$ # R[limit]/[interval]/[datetime] + R1/$ # R[limit]/[datetime] + +.. _excluding-dates: + + +The Initial Cycle Point +^^^^^^^^^^^^^^^^^^^^^^^ + +A workflow normally begins running at the :term:`initial cycle point`, which defines +the start of the workflow graph: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 20100808T06Z + +This can be overridden on the command line: + +.. code-block:: console + + $ cylc play foo --initial-cycle-point=20120808T06Z + + +.. _setting-the-icp-relative-to-now: + +Setting The Initial Cycle Point Relative To The Current Time +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +.. warning:: + + Setting the initial cycle point relative to the current time only works + for :term:`datetime cycling` workflows using the Gregorian calendar. + It does not work for alternative calendars like the 360, 365 or 366 day + calendars, or integer cycling. + +The ``next`` and ``previous`` syntax can be used with truncated ISO 8601 +representations, to set the initial cycle point: +``next(Thh:mmZ)``, ``previous(T-mm)``; e.g. + +* ``initial cycle point = next(T15:00Z)`` +* ``initial cycle point = previous(T09:00)`` +* ``initial cycle point = next(T12)`` +* ``initial cycle point = previous(T-20)`` + +A list of times, separated by semicolons, can be provided, e.g. +``next(T-00;T-15;T-30;T-45)``. At least one time is required within the +brackets, and if more than one is given, the major time unit in each (hours +or minutes) should be of the same type. + +.. note:: + + ``T-00`` means every hour, on the hour. The ``-`` is a placeholder for the hours column. + +If an offset from the specified datetime is required, this should be +of the form ``previous(Thh:mm) +/- PxTy`` as is used +for determining cycle periods, e.g. + +* ``initial cycle point = previous(T06) +P1D`` +* ``initial cycle point = next(T-30) -PT1H`` + +The next/previous syntax is interpreted first, then the offset is applied. + +Offsets used without ``next`` or ``previous`` are interpreted as offsets from "now". + +.. table:: Relative initial cycle point examples for ``now = 2018-03-14T15:12Z`` + + ==================================== ================== + Syntax Interpretation + ==================================== ================== + ``next(T-00)`` 2018-03-14T16:00Z + ``previous(T-00)`` 2018-03-14T15:00Z + ``next(T-00; T-15; T-30; T-45)`` 2018-03-14T15:15Z + ``previous(T-00; T-15; T-30; T-45)`` 2018-03-14T15:00Z + ``next(T00)`` 2018-03-15T00:00Z + ``previous(T00)`` 2018-03-14T00:00Z + ``next(T06:30Z)`` 2018-03-15T06:30Z + ``previous(T06:30) -P1D`` 2018-03-13T06:30Z + ``next(T00; T06; T12; T18)`` 2018-03-14T18:00Z + ``previous(T00; T06; T12; T18)`` 2018-03-14T12:00Z + ``next(T00; T06; T12; T18) +P1W`` 2018-03-21T18:00Z + ``PT1H`` 2018-03-14T16:12Z + ``-P1M`` 2018-02-14T15:12Z + ==================================== ================== + +Relative initial cycle points also work with truncated dates, including +weeks and ordinal date, using ISO 8601 truncated date representations. +Note that day-of-week should always be specified when using weeks. If a time +is not included, the calculation of the next or previous corresponding +point will be done from midnight of the current day. + +.. csv-table:: Relative initial cycle point examples for ``now = 2018-03-14T15:12Z`` + using ISO8601 truncated dates. + :widths: auto + + Syntax, Description, Interpretation + ``next(-00)``, Any century; next year 00, 2100-01-01 + ``previous(--01)``, Any year; next month 01, 2018-01-01 + ``next(---01)``, Any year; any month; next 1st of month, 2018-04-01 + ``previous(--1225)``, Any year; previous Dec 25, 2017-12-25 + ``next(-2006)``, Any century; next June in a year ending 20, 2020-06-01 + ``previous(-W101)``, Any century; previous week 10 day 1, 2018-03-05 + ``next(-W-1; -W-3; -W-5)``, "Any year; any week; next day 1, 3 or 5", 2018-03-14 + ``next(-001; -091; -181; -271)``, "Any year; day 1, 91, 181 or 271", 2018-04-01 + ``previous(-365T12Z)``, Any year; previous day 356 at 12Z, 2017-12-31T12:00Z + + +The Environment Variable CYLC\_WORKFLOW\_INITIAL\_CYCLE\_POINT +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +At start up the initial cycle point is passed to job environments +as ``$CYLC_WORKFLOW_INITIAL_CYCLE_POINT`` and stored in the workflow +database to persist across restarts. + +The ``$CYLC_WORKFLOW_INITIAL_CYCLE_POINT`` variable allows tasks to +check if they are running in the initial cycle point, when different behaviour +may be required. Note however that an initial ``R1`` graph section is the +preferred way to get different behaviour at workflow start-up. + + +.. _HowMultipleGraphStringsCombine: + + +How Multiple Graph Strings Combine +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Multiple graph strings add together to make the complete workflow graph. +Recurrences can overlap, and tasks can appear in multiple graph strings. It is +OK (but unnecessary) to define duplicate dependencies. + +.. code-block:: cylc + + [scheduling] + [[graph]] + T00,T06,T12,T18 = "A => B => C" + T06,T18 = "B => C => X" + # duplicate prerequisite: B => C already defined at T06, T18 + +This graph can be written more concisely, with the same result, like this: + +.. code-block:: cylc + + [scheduling] + [[graph]] + T00,T06,T12,T18 = "A => B => C" + # X triggers off C only at 6 and 18 hours + T06,T18 = "C => X" + + +Excluding Dates +^^^^^^^^^^^^^^^ + +:term:`datetimes ` can be excluded from a :term:`recurrence` +by an exclamation mark for example ``PT1D!20000101`` means run daily except on +the first of January 2000. + +This syntax can be used to exclude multiple datetimes from a recurrence, using +the syntax ``PT1D!(20000101,20000102,...)``. All datetimes listed within +the parentheses will be excluded. + +.. note:: + + The ``^`` and ``$`` symbols (shorthand for the initial + and final cycle points) are both datetimes so ``T12!$-PT1D`` + is valid. + +If using a run limit in combination with an exclusion, the recurrence might not +run the expected number of times. For example, in the following +workflow ``foo`` will only run once as its second run is excluded. + +.. code-block:: cylc + + [scheduling] + initial cycle point = 20000101T00Z + final cycle point = 20000105T00Z + [[graph]] + R2/P1D!20000102 = foo + +Excluding Recurrences +^^^^^^^^^^^^^^^^^^^^^ + +Exclusions may themselves be datetime recurrence sequences. Any partial +datetime or sequence after the exclamation mark will be excluded from the main +sequence. + +For example, partial datetimes can be excluded like this: + +.. code-block:: sub + + PT1H ! T12 # Run hourly but not at 12:00 from the initial + # cycle point. + T-00 ! (T00, T06, T12, T18) # Run hourly but not at 00:00, 06:00, + # 12:00, 18:00. + PT5M ! T-15 # Run 5-minutely but not at 15 minutes past the + # hour from the initial cycle point. + T00 ! W-1T00 # Run daily at 00:00 except on Mondays. + +And sequences can be excluded like this: + +.. code-block:: sub + + PT1H ! PT6H # Run hourly from the initial cycle point but + # not 6-hourly from the initial cycle point. + T-00 ! PT6H # Run hourly on the hour but not 6-hourly on the hour. + # Same as T-00 ! T-00/PT6H (T-00 context is implied) + # Same as T-00 ! (T00, T06, T12, T18) + # Same as PT1H ! (T00, T06, T12, T18) Initial cycle point dependent + + T12 ! T12/P15D # Run daily at 12:00 except every 15th day. + + R/^/P1H ! R5/20000101T00/P1D # Any valid recurrence may be used to + # determine exclusions. This example + # means: Repeat every hour from + # the initial cycle point, but exclude + # 00:00 for 5 days from 1 January 2000. + +You can combine exclusion sequences and single point exclusions like this: + +.. code-block:: sub + + T-00 ! (20000101T07, PT2H) # Run hourly on the hour but not at 07:00 + # on the 1st Jan, 2000 and not 2-hourly + # on the hour. + + +.. _AdvancedCycling: + +Advanced Examples +^^^^^^^^^^^^^^^^^ + +Here are several examples of Cylc graph recurrence expressions: + +.. code-block:: sub + + R1 # Run once at the initial cycle point + P1D # Run every day starting at the initial cycle point + PT5M # Run every 5 minutes starting at the initial cycle point + T00/P2W # Run every 2 weeks starting at 00:00 after the + # initial cycle point + +P5D/P1M # Run every month, starting 5 days after the initial cycle point + R1/T06 # Run once at 06:00 after the initial cycle point + R1/P0Y # Run once at the final cycle point + R1/$ # Run once at the final cycle point (alternative form) + R1/$-P3D # Run once three days before the final cycle point + R3/T0830 # Run 3 times, every day at 08:30 after the initial cycle point + R3/01T00 # Run 3 times, every month at 00:00 on the first + # of the month after the initial cycle point + R5/W-1/P1M # Run 5 times, every month starting on Monday + # following the initial cycle point + T00!^ # Run at the first occurrence of T00 that isn't the + # initial cycle point + PT1D!20000101 # Run every day days excluding 1st Jan 2000 + 20140201T06/P1D # Run every day starting at 20140201T06 + R1/min(T00,T06,T12,T18) # Run once at the first instance + # of either T00, T06, T12 or T18 + # starting at the initial cycle point + +.. _AdvancedStartingUp: + +Advanced Starting Up +^^^^^^^^^^^^^^^^^^^^ + +Dependencies that are only valid at the :term:`initial cycle point` can be +written using an ``R1`` recurrence. For example: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 20130808T00 + final cycle point = 20130812T00 + [[graph]] + R1 = "prep => foo" + T00 = "foo[-P1D] => foo => bar" + +In the example above, ``R1`` implies ``R1/20130808T00``, so +``prep`` only runs once at that cycle point (the initial cycle point). +``foo`` will depend on ``prep`` there, but not at subsequent cycle points. + +However, it is possible to have a workflow that has multiple effective initial +cycles - for example, one starting at ``T00`` and another starting +at ``T12``. What if they need to share an initial task? + +Let's suppose that we add the following section to the workflow example above: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 20130808T00 + final cycle point = 20130812T00 + [[graph]] + R1 = "prep => foo" + T00 = "foo[-P1D] => foo => bar" + T12 = "baz[-P1D] => baz => qux" + +We'll also say that there should be a starting dependence between +``prep`` and our new task ``baz`` - but we still want to have +a single ``prep`` task, at a single cycle. + +We can write this using a special case of the ``task[-interval]`` syntax - +if the interval is null, this implies the task at the initial cycle point. + +For example, we can write our workflow like so, to produce the graph as shown: + +.. Need to use a 'container' directive to get centered image with + left-aligned caption (as required for code block text). + +.. container:: twocol + + .. container:: caption + + *Staggered Start Workflow* + + .. code-block:: cylc + + [scheduling] + initial cycle point = 20130808T00 + final cycle point = 20130812T00 + [[graph]] + R1 = "prep" + # ^ implies the initial cycle point: + R1/T00 = "prep[^] => foo" + # ^ is initial cycle point, as above: + R1/T12 = "prep[^] => baz" + T00 = "foo[-P1D] => foo => bar" + T12 = "baz[-P1D] => baz => qux" + + .. container:: image + + .. _fig-test4: + + .. figure:: ../../img/test4.png + :align: center + + +Usually, we want to specify additional tasks and dependencies at the initial +cycle point. But what if we want our first cycle point to be entirely special, +with some tasks missing compared to subsequent cycle points? + +In the workflow below, ``bar`` will not run at the initial cycle point, but +will still run at subsequent cycle points. ``+PT6H/PT6H`` means start at +``+PT6H`` (6 hours after the initial cycle point) and then repeat every +``PT6H`` (6 hours): + +.. Need to use a 'container' directive to get centered image with + left-aligned caption (as required for code block text). + +.. container:: twocol + + .. container:: caption + + *Restricted First Cycle Point Workflow* + + .. code-block:: cylc + + [scheduling] + initial cycle point = 20130808T00 + final cycle point = 20130808T18 + [[graph]] + R1 = "setup_foo => foo" + +PT6H/PT6H = """ + foo[-PT6H] => foo + foo => bar + """ + + .. container:: image + + .. _fig-test5: + + .. figure:: ../../img/test5.png + :align: center + + +Some workflows may have staggered start-up sequences where different tasks need +to run once but only at specific cycle points, e.g. because of differing +data sources at different cycle points, with different possible initial cycle +points. To allow this Cylc provides a ``min( )`` function that can be +used as follows: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 20100101T03 + [[graph]] + R1/min(T00,T12) = "prep1 => foo" + R1/min(T06,T18) = "prep2 => foo" + T00,T06,T12,T18 = "foo => bar" + + +In this example the initial cycle point is ``20100101T03``, so the +``prep1`` task will run once at ``20100101T12`` and the +``prep2`` task will run once at ``20100101T06`` as these are +the first cycle points after the initial cycle point in the respective +``min( )`` entries. + +.. _IntegerCycling: + +Integer Cycling +^^^^^^^^^^^^^^^ + +.. tutorial:: Integer Cycling Tutorial + +In addition to non-cycling and :term:`datetime cycling` workflows, Cylc can do +:term:`integer cycling` for cycling workflows that are not datetime based. + +To construct an integer cycling workflow, set +:cylc:conf:`[scheduling]cycling mode = integer`, and specify integer values +for the :term:`initial cycle point` and optionally the +:term:`final cycle point`. The syntax for intervals, +offsets, and :term:`recurrences ` (sequences) is similar to the +datetime cycling syntax, except for the simple integer values. + +The full integer recurrence expressions supported are: + +- ``Rn/start-point/interval # e.g. R3/1/P2`` +- ``Rn/interval/end-point # e.g. R3/P2/9`` + +But, as for datetime cycling, sequence start and end points can be omitted +where workflow initial and final cycle points can be assumed. Some examples: + +.. code-block:: sub + + R1 # Run once at the initial cycle point + # (short for R1/initial-point/?) + P1 # Repeat with step 1 from the initial cycle point + # (short for R/initial-point/P1) + P5 # Repeat with step 5 from the initial cycle point + # (short for R/initial-point/P5) + R2//P2 # Run twice with step 3 from the initial cycle point + # (short for R2/initial-point/P2) + R/+P1/P2 # Repeat with step 2, from 1 after the initial cycle point + R2/P2 # Run twice with step 2, to the final cycle point + # (short for R2/P2/final-point) + R1/P0 # Run once at the final cycle point + # (short for R1/P0/final-point) + +Advanced Integer Cycling Syntax +""""""""""""""""""""""""""""""" + +The same syntax used to reference the initial and final cycle points +(introduced in :ref:`referencing-the-initial-and-final-cycle-points`) for +use with datetime cycling can also be used for integer cycling. For +example you can write: + +.. code-block:: sub + + R1/^ # Run once at the initial cycle point + R1/$ # Run once at the final cycle point + R3/^/P2 # Run three times with step two starting at the + # initial cycle point + +Likewise the syntax introduced in :ref:`excluding-dates` for excluding +a particular point from a recurrence also works for integer cycling. For +example: + +.. code-block:: sub + + R/P4!8 # Run with step 4, to the final cycle point but not at point 8 + R3/3/P2!5 # Run with step 2 from point 3 but not at point 5 + R/+P1/P6!14 # Run with step 6 from 1 step after the + # initial cycle point but not at point 14 + +Multiple integer exclusions are also valid in the same way as the syntax +in :ref:`excluding-dates`. Integer exclusions may be a list of single +integer points, an integer sequence, or a combination of both: + +.. code-block:: sub + + R/P1!(2,3,7) # Run with step 1 to the final cycle point, + # but not at points 2, 3, or 7. + P1 ! P2 # Run with step 1 from the initial to final + # cycle point, skipping every other step from + # the initial cycle point. + P1 ! +P1/P2 # Run with step 1 from the initial cycle point, + # excluding every other step beginning one step + # after the initial cycle point. + P1 !(P2,6,8) # Run with step 1 from the initial cycle point, + # excluding every other step, and also excluding + # steps 6 and 8. + +An Integer Cycling Example +"""""""""""""""""""""""""" + +.. _fig-integer-pipeline: + +.. figure::/img/pipe-pub.png + :align: center + +The following workflow definition, as :ref:`graphed above `, +implements a classical linear pipeline using integer cycling. The workflow +ensures that one instance each of A, B, and C runs concurrently and the +pipeline is kept full: when 1/A has finished processing the first dataset, 2/A +can start on the second one at the same time as 1/B begins processing the +output of 1/A, and so on. The artificial cross-cycle dependence ensures that +only one instance of A can run at a time; and similarly B and C. If available +compute resource supports more than three concurrent jobs, remove the +cross-cycle dependence and Cylc will run many cycles at once. Task runtime +configuration is omitted, but it would likely involve retrieving datasets by +cycle point and processing them in cycle point-specific shared workspaces under +the self-contained run directory. + +.. literalinclude:: ../../workflows/integer-pipeline/flow.cylc + :language: cylc + + +.. _TriggerTypes: + +Task Triggering +--------------- + +A task is said to :term:`trigger` when it submits its job to run, as soon as all of +its dependencies (also known as its separate "triggers") are met. Tasks can +be made to trigger off of the state of other tasks (indicated by a +``:state`` :term:`qualifier` on the upstream task (or family) +name in the graph) and, and off the clock, and arbitrary external events. + +External triggering is relatively more complicated, and is documented +separately in :ref:`Section External Triggers`. + +Success Triggers +^^^^^^^^^^^^^^^^ + +The default, with no trigger type specified, is to trigger off of the +upstream task succeeding: + +.. code-block:: cylc + + # B triggers if A SUCCEEDS: + R1 = "A => B" + +For consistency and completeness, however, the success trigger can be +explicit: + +.. code-block:: cylc + + # B triggers if A SUCCEEDS: + R1 = "A => B" + + # or: + R1 = "A:succeed => B" + + +Failure Triggers +^^^^^^^^^^^^^^^^ + +To trigger off of the upstream task failing: + +.. code-block:: cylc + + # B triggers if A FAILS: + R1 = "A:fail => B" + + +Start Triggers +^^^^^^^^^^^^^^ + +To trigger off of the upstream task starting: + +.. code-block:: cylc + + # B triggers if A STARTS EXECUTING: + R1 = "A:start => B" + +This can be used to trigger tasks that monitor the execution of other tasks, +e.g. to process their output files on the fly as they are generated. +:ref:`MessageTriggers` can also be useful for this use case. + + +Finish Triggers +^^^^^^^^^^^^^^^ + +To trigger off of the upstream task either succeeding **or** failing: + +.. code-block:: cylc + + # B triggers if A either SUCCEEDS or FAILS: + R1 = "A | A:fail => B" + + # or + R1 = "A:finish => B" + + +.. _MessageTriggers: + +Message Triggers +^^^^^^^^^^^^^^^^ + +.. tutorial:: Message Trigger Tutorial + +We can also trigger off of custom task output messages. These must be +registered in the :cylc:conf:`[runtime][][outputs]` section +of the emitting task, and sent with ``cylc message`` command. +The graph trigger syntax refers to the item name of the registered +output message. Here's an example workflow that uses message triggers: + +.. literalinclude:: ../../workflows/message-triggers/flow.cylc + :language: cylc + + +Job Submission Triggers +^^^^^^^^^^^^^^^^^^^^^^^ + +To trigger off of a task submitting, or failing to submit: + +.. code-block:: cylc + + # B triggers if A submits successfully: + R1 = "A:submit? => B" + + # D triggers if C fails to submit successfully: + R1 = "C:submit-fail? => D" + +A possible use case for submit-fail triggering: if a task fails to submit, +possibly after multiple retries, another task that inherits (mostly) the same +runtime could be triggered to submit the same job to an alternative platform. + + +Conditional Triggers +^^^^^^^^^^^^^^^^^^^^ + +:term:`Conditional triggers ` allow the configuration of +more advanced task dependencies. + +AND operators (``&``) can appear on both sides of an arrow. They +provide a concise alternative to defining multiple triggers separately: + +.. code-block:: cylc + + # 1/ this: + R1 = "A & B => C" + + # is equivalent to: + R1 = """ + A => C + B => C + """ + + # 2/ this: + R1 = "A => B & C" + + # is equivalent to: + R1 = """ + A => B + A => C + """ + + # 3/ and this: + R1 = "A & B => C & D" + + # is equivalent to this: + R1 = """ + A => C + B => C + A => D + B => D + """ + +OR operators (``|``), for conditional triggers, can only appear on the left: + +.. code-block:: cylc + + # C triggers when either A or B finishes: + R1 = "A | B => C" + +Any valid conditional expression can be used. + +.. Need to use a 'container' directive to get centered image with + left-aligned caption (as required for code block text). + +.. container:: twocol + + .. container:: caption + + *Conditional trigger example* + + .. code-block:: cylc-graph + + # D triggers if A or (B and C) succeed + A | B & C => D + # just to align the two graph sections + D => W + # Z triggers if (W or X) and Y succeed + (W|X) & Y => Z + + .. container:: image + + .. _fig-conditional: + + .. figure:: ../../img/conditional-triggers.png + :align: center + + +.. _FamilyTriggers: + +Family Triggers +^^^^^^^^^^^^^^^ + +:term:`Families ` defined by the runtime inheritance hierarchy +(:ref:`User Guide Runtime`) can be used in the graph to :term:`trigger` whole +groups of tasks at the same time (e.g. forecast model ensembles and groups of +tasks for processing different observation types at the same time) and for +triggering downstream tasks off families as a whole. Higher level families, +i.e. families of families, can also be used, and are reduced to the lowest +level member tasks. + +.. note:: + + Tasks can also trigger off individual family members if necessary. + +To trigger an entire task family at once: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = "foo => FAM" + [runtime] + [[FAM]] # a family (because others inherit from it) + [[m1,m2]] # family members (inherit from FAM) + inherit = FAM + +This is equivalent to: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = "foo => m1 & m2" + [runtime] + [[FAM]] + [[m1,m2]] + inherit = FAM + +To trigger off of a task family you must specify whether the trigger condition +applies to **all** or **any** of the member tasks: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + # all-member triggers: + FAM:start-all => one + FAM:succeed-all => one + FAM:fail-all => one + FAM:finish-all => one + # any-member triggers: + FAM:start-any => one + FAM:succeed-any => one + FAM:fail-any => one + FAM:finish-any => one + """ + +Here's how to trigger downstream processing after if one or more family +members succeed, but only after all members have finished (succeeded or +failed): + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + FAM:finish-all & FAM:succeed-any => foo + """ + + +.. _EfficientInterFamilyTriggering: + +Efficient Inter-Family Triggering +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +While Cylc allows writing :term:`dependencies ` between two +:term:`families ` it is important to consider the number of +dependencies this will generate. In the following example, each member of +``FAM2`` has dependencies pointing at all the members of ``FAM1``. + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + FAM1:succeed-any => FAM2 + """ + +Expanding this out, you generate ``N * M`` dependencies, where ``N`` is the +number of members of ``FAM1`` and ``M`` is the number of members of ``FAM2``. +This can result in high memory use as the number of family members grows. + +You can greatly reduce the number of dependencies generated here by putting +dummy tasks in the graph to represent the state of the upstream family. For +example, if ``FAM2`` should trigger off any member of ``FAM1`` succeeding you +can use a dummy task ``FAM1_done`` like this: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + FAM1:succeed-any => FAM1_done => FAM2 + """ + [runtime] + # ... + [[FAM1_done]] + script = true + # ... + +This :term:`graph` generates only ``N + M`` dependencies, which takes +significantly less memory and CPU to store and evaluate. + + +.. _InterCyclePointTriggers: + +Intercycle Triggers +^^^^^^^^^^^^^^^^^^^ + +Most tasks in a workflow typically depend on others with the same +cycle point, but some may depend on other cycle points [1]_. + +:term:`Intercycle dependence ` is expressed using +``[offset]`` syntax such as ``foo[-PT12H] => foo``, which means ``foo`` at the +current cycle point depends on a previous instance of ``foo`` at 12 hours +before the current cycle point. Unlike for recurrences (e.g. ``T00,T12``), +dependency these offsets are relative to the current cycle point, not the +initial cycle point. + +.. code-block:: cylc + + [[graph]] + # B triggers off A in the previous cycle point + PT6H = "A[-PT6H] => B" + +intercycle and trigger type (or message trigger) syntax can be +combined: + +.. code-block:: cylc + + # B triggers if A in the previous cycle point fails: + PT6H = "A[-PT6H]:fail => B" + +For convenience, Cylc automatically ignores intercycle triggers that reach back +beyond the initial cycle point. If something special has to happen at start-up, +``R1`` tasks are the recommended way to make it happen: + + .. code-block:: cylc + + [scheduling] + [[graph]] + R1 = "prep1 => prep2" + R1/T00,R1/T12 = "prep2[^] => foo" + T00,T12 = "foo[-PT12H] => foo => bar" + +Here there is a dependence on the initial ``R1`` task ``prep`` for ``foo`` at +the first ``T00`` cycle point, and at the first ``T12`` cycle point. +Thereafter, ``foo`` just depends on its previous (12 hours ago) instance. + +It can also be useful to have specific dependencies on tasks at or near +the initial cycle point. You can switch the context of the offset to be +the initial cycle point by using the caret symbol: ``^``. + +For example, ``foo[^]`` means ``foo`` at the initial cycle point, and +``foo[^+PT6H]`` means ``foo`` 6 hours after the initial cycle point. Usually, +this kind of dependency will only apply in a limited number of cycle points +near the start of the workflow, so you may want to write it in an ``R1`` graph. + +Finally, dependence on a task at a specific cycle point is also possible: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1/20200202 = "baz[20200101] => qux" + + +.. TODO is this still the case: + +.. warning:: + + However, in a long running workflow it is best to avoid a repeating cycle + that depends forever on a specific cycle point (such as the initial point) + as this can adversely affect the scheduler's performance. + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2010 + [[graph]] + # Can cause performance issue! + P1D = "baz[20200101] => qux" + + +.. _SequentialTasks: + +Special Sequential Tasks +^^^^^^^^^^^^^^^^^^^^^^^^ + +Tasks that depend on their own previous-cycle instance can be declared as +*sequential*: + +.. code-block:: cylc + + [scheduling] + [[special tasks]] + # foo depends on its previous instance: + sequential = foo # deprecated - see below! + [[graph]] + T00,T12 = "foo => bar" + +However, explicit intercycle triggers are generally preferred: + +.. code-block:: cylc + + [scheduling] + [[graph]] + # foo depends on its previous instance: + T00,T12 = "foo[-PT12H] => foo => bar" + +The sequential declaration is arguably convenient in one unusual situation +though: if a task has a non-uniform cycling sequence then multiple explicit +triggers, + +.. code-block:: cylc + + [scheduling] + [[graph]] + T00,T03,T11 = "foo => bar" + T00 = "foo[-PT13H] => foo" + T03 = "foo[-PT3H] => foo" + T11 = "foo[-PT8H] => foo" + +can be replaced by a single sequential declaration, + +.. code-block:: cylc + + [scheduling] + [[special tasks]] + sequential = foo + [[graph]] + T00,T03,T11 = "foo => bar" + + +Future Triggers +^^^^^^^^^^^^^^^ + +Cylc also supports :term:`intercycle triggering ` off +tasks "in the future" (with respect to cycle point): + +.. code-block:: cylc + + [[graph]] + T00,T06,T12,T18 = """ + # A runs in this cycle: + A + # B in this cycle triggers off A in the next cycle. + A[PT6H] => B + """ + +Future triggers present a problem at workflow shutdown rather than at start-up. +Here, ``B`` at the final cycle point wants to trigger off an instance +of ``A`` that will never exist because it is beyond the workflow stop +point. Consequently Cylc prevents tasks from spawning successors that depend on +other tasks beyond the final point. + + +.. _ClockTriggerTasks: + +Clock Triggers +^^^^^^^^^^^^^^ + +.. warning:: + + This describes a deprecated syntax for defining clock triggers in task + configuration. If used, it will be converted automatically to define + new-style :ref:`clock triggers `. + Support for the old syntax will be removed in an upcoming release. + +By default, datetime cycle points are not connected to the :term:`wallclock time`. +In real time cycling systems, however, some tasks may need to trigger at +(or at some offset from) their cycle point in real time. + +Cylc points are full datetimes, not just times of the day, so clock-triggers +provide no constraint if the workflow gets sufficiently far behind the clock, +allowing maximum concurrency until the clock-triggered tasks catch up again. + +.. code-block:: cylc + + [scheduling] + [[special tasks]] + clock-trigger = foo(PT2H) + [[graph]] + T00 = foo + +Here, ``2025-08-23T00/foo`` would trigger (other dependencies allowing) +when the wallclock time reaches ``2025-08-23T02``. Clock-trigger +offsets are normally positive, to trigger *after* the wallclock time is equal +to the task cycle point. + + +.. _ClockExpireTasks: + +Clock-Expire Triggers +^^^^^^^^^^^^^^^^^^^^^ + +Tasks can be configured to :term:`expire ` if the wall clock +time exceeds some offset from their cycle point. + + +The associated ``:expire`` :term:`output ` can be used to +trigger other tasks. It must be marked as an :term:`optional output`, +i.e. expiry cannot be :term:`required `. + +Family triggers are also provided for task expiry: + +.. code-block:: cylc-graph + + foo:expire? => bar + FAM:expire-all? => baz + FAM:expire-any? => qux + +Task expiration is configured with +:cylc:conf:`[scheduling][special tasks]clock-expire` using a syntax like +:cylc:conf:`clock-trigger <[scheduling][special tasks]clock-trigger>` +with a datetime offset relative to cycle point. + +The offset should be positive to make the task expire if the wallclock time +has gone beyond the cycle point. + +.. warning:: + + The scheduler can only determine that a task has expired once it + enters the :term:`n=0 window `. + + +.. _WorkflowConfigExternalTriggers: + +External Triggers +^^^^^^^^^^^^^^^^^ + +This is a substantial topic, documented separately +in :ref:`Section External Triggers`. + + + +.. _User Guide Required Outputs: +.. _required outputs: + +Required Outputs +---------------- + +.. versionadded:: 8.0.0 + +:term:`Task outputs ` in the :term:`graph` can be +:term:`required ` (the default) or +:term:`optional ` (marked with ``?`` in the graph). + +Tasks are expected to complete required outputs at runtime, but +they don't have to complete optional outputs. + +This allows the scheduler to correctly diagnose +:term:`workflow completion`. [2]_ + +Tasks that achieve a :term:`final status` without completing their +outputs [3]_ are retained in the :term:`n=0 window ` pending user +intervention, e.g. to be retriggered after a bug fix. + +.. note:: + Tasks that achieve a final status without completing their outputs will + raise a warning and stall the workflow when there is nothing else for + the scheduler to run (see :ref:`workflow completion`). They also count + toward the :term:`runahead limit`. + +This graph says task ``bar`` should trigger if ``foo`` succeeds: + +.. code-block:: cylc-graph + + foo => bar # short for "foo:succeed => bar" + +Additionally, ``foo`` is required to succeed, because its success is not marked +as optional. If ``foo`` achieves a :term:`final status` without succeeding the +scheduler will not run ``bar``, and ``foo`` will be retained +in :term:`n=0 ` pending user intervention. + +Here, ``foo:succeed``, ``bar:x``, and ``baz:fail`` are all required outputs: + +.. code-block:: cylc-graph + + foo + bar:x + baz:fail + +Tasks that appear with only custom outputs in the graph are also required to succeed. +Here, ``foo:succeed`` is a required output, as well as ``foo:x``, unless it is +marked as optional elsewhere in the graph: + +.. code-block:: cylc-graph + + foo:x => bar + +If a task generates multiple custom outputs, they should be "required" if you +expect them all to be completed every time the task runs. Here, +``model:file1``, ``model:file2``, and ``model:file3`` are all required outputs: + +.. code-block:: cylc-graph + + model:file1 => proc1 + model:file2 => proc2 + model:file3 => proc3 + + +.. _optional outputs: +.. _User Guide Optional Outputs: + +Optional Outputs +---------------- + +.. versionadded:: 8.0.0 + +Optional outputs are marked with ``?``. They may or may not be completed by the +task at runtime. + +Like the first example above, the following graph says task ``bar`` should +trigger if ``foo`` succeeds: + +.. code-block:: cylc-graph + + foo? => bar # short for "foo:succeed? => bar" + +But now ``foo:succeed`` is optional so we might expect it to fail sometimes. +And if it does fail, it will not be retained in the +:term:`n=0 window ` as incomplete. + +Here, ``foo:succeed``, ``bar:x``, and ``baz:fail`` are all optional outputs: + +.. code-block:: cylc-graph + + foo? + bar:x? + baz:fail? + + +Success and failure (of the same task) are mutually exclusive, so they must +both be optional if one is optional, or if they both appear in the graph: + +.. code-block:: cylc-graph + + foo? => bar + foo:fail? => baz + + +.. warning:: + + Optional outputs must be marked as optional everywhere they appear in the + graph, to avoid ambiguity. + + +If a task generates multiple custom outputs, they should all be declared optional +if you do not expect them to be completed every time the task runs: + +.. code-block:: cylc-graph + + # model:x, :y, and :z are all optional outputs: + model:x? => proc-x + model:y? => proc-y + model:z? => proc-z + +This is an example of :term:`graph branching` from optional outputs. Whether a +particular branch is taken or not depends on which optional outputs are +completed at runtime. For more information see :ref:`Graph Branching`. + +Leaf tasks (with nothing downstream of them) can have optional outputs. In the +following graph, ``foo`` is required to succeed, but it doesn't matter whether +``bar`` succeeds or fails: + +.. code-block:: cylc-graph + + foo => bar? + + +.. note:: + + Optional outputs do not affect *triggering*. They just tell the scheduler + what to do with the task if it reaches a :term:`final status` without + completing the output. + + This graph triggers ``bar`` if ``foo`` succeeds, and does not trigger + ``bar`` if ``foo`` fails: + + .. code-block:: cylc-graph + + foo => bar + + And so does this graph: + + .. code-block:: cylc-graph + + foo? => bar + + The only difference is whether or not the scheduler regards ``foo`` as + incomplete if it fails. + + +Finish Triggers +^^^^^^^^^^^^^^^ + +``foo:finish`` is a pseudo output that is short for ``foo:succeed? | +foo:fail?``. This automatically labels the real outputs as optional, because +success and failure can't both be required. + +``foo:finish?`` is illegal because it incorrectly suggests that "finishing +is optional" and that a non-optional version of the trigger makes sense. + +.. code-block:: cylc-graph + + # Good: + foo:finish => bar + foo? => baz + + # Error: + foo:finish => bar + foo => baz # ERROR : foo:succeed must be optional here! + +.. _optional outputs.family triggers: + +Family Triggers +^^^^^^^^^^^^^^^ + +.. (taken from https://github.com/cylc/cylc-flow/pull/4343#issuecomment-913901972) + +Family triggers are based on family pseudo outputs such as ``FAM:succeed-all`` +and ``FAM:fail-any`` that are short for logical expressions involving the +corresponding member task outputs. + +If the member outputs are not singled out explicitly elsewhere in the graph, +then they default to being required outputs. + +For example, if ``f1`` and ``f2`` are members of ``FAM``, then this: + +.. code-block:: cylc-graph + + FAM:fail-all => a + + +means: + +.. code-block:: cylc-graph + + f1:fail & f2:fail => a # f1:fail and f2:fail are required + + +and this: + +.. code-block:: cylc-graph + + FAM:succeed-any => a + + +means: + +.. code-block:: cylc-graph + + f1 | f2 => a # f1:succeed and f2:succeed are required + + +However, the family default can be changed to optional by using ``?`` on the +family trigger. So this: + +.. code-block:: cylc-graph + + FAM:fail-all? => a + + +means this: + +.. code-block:: cylc-graph + + f1:fail? & f2:fail? => a # f1:fail and f2:fail are optional + + +If particular member tasks are singled out elsewhere in the graph, that +overrides the family default for required/optional outputs: + +.. code-block:: cylc-graph + + # f1:fail is required, and f2:fail is optional: + FAM:fail-all => a + f2:fail? => b + + +Family Finish Triggers +^^^^^^^^^^^^^^^^^^^^^^ + +Like task ``:finish`` triggers, family ``:finish-all/any`` triggers are +different because ``:finish`` is a pseudo output involving both ``:succeed`` +and ``:fail``, which are mutually exclusive outputs that must both be optional +if both are used. + +Also like task ``:finish`` triggers, use of ``?`` is illegal on a family +finish trigger, because the underlying member outputs must already be optional. + +.. code-block:: cylc-graph + + FAM:finish-all => a # f1:succeed/fail and f2:succeed/fail are optional + FAM:finish-any => a # (ditto) + + FAM:finish-all? => b # ERROR + + +.. _Graph Branching: + +Graph Branching +--------------- + +Cylc handles workflow :term:`graphs ` in an event-driven way. It can +automatically follow different paths depending on events at runtime. This +relies on :term:`optional outputs ` and is called *branching*. + +.. note:: + + In Cylc 7 and earlier, graphs were not event-driven and needed + :term:`suicide triggers ` to clean up unused + branches at runtime. + + Cylc 8 does not need suicide triggers for branching. + +Basic Example +^^^^^^^^^^^^^ + +Here Cylc will follow one of two "branches" depending on the outcome of task ``b``: + +* If ``b`` succeeds then the task ``c`` will run. +* If ``b`` fails then the task ``r`` will run. + +Task ``d`` will run after either ``c`` or ``r`` succeeds. + +.. digraph:: example + :align: center + + subgraph cluster_success { + label = ":succeed" + color = "green" + fontcolor = "green" + style = "dashed" + + c + } + + subgraph cluster_failure { + label = ":fail" + color = "red" + fontcolor = "red" + style = "dashed" + + r + } + + a -> b -> c -> d + b -> r -> d + +.. code-block:: cylc-graph + + # the success path + a => b? => c + # the fail path + a => b:fail? => r + # either way, carry on with the rest of the workflow + c | r => d + +The ``?`` symbol denotes an :term:`optional output` which allows the graph to +branch. + +Note the last line of the graph ``c | r => d`` allows the graph to +continue on to ``d`` regardless of the path taken. This is an :term:`artificial +dependency`. + +Branching is often used for automatic failure recovery. Here's a simple +example: + +.. code-block:: cylc-graph + + foo => bar? + bar:fail? => recover + bar? | recover => baz + + +.. digraph:: Example + :align: center + + subgraph cluster_1 { + label = ":fail" + color = "red" + fontcolor = "red" + style = "dashed" + + recover + } + + foo -> bar + bar -> recover + recover -> baz [arrowhead="onormal"] + bar -> baz [arrowhead="onormal"] + + +The ``recover`` task would (presumably) analyse the failure of ``bar`` and, if +the right failure mode is confirmed, attempt to generate the right outputs +another way. Then ``baz`` can trigger off of either branch, to process the +outputs. + +A more realistic example might have several tasks on each branch. The +``recover`` task could, via inheritance, run the same underlying code as +``bar``, but configured differently to avoid the failure. + + +Custom Outputs +^^^^^^^^^^^^^^ + +Branching is particularly powerful when using +:term:`custom outputs ` to define alternate parallel paths in the +graph. + +In the following graph there is a task called ``showdown`` which produces one +of three possible custom outputs, ``good``, ``bad`` or ``ugly``. Cylc will follow +a different path depending on which of these three outputs is produced. + +As with the previous example each path begins with a different :term:`optional +output` of a particular task and ends with an "or" dependency to allow the +workflow to continue regardless of the path taken. + +.. code-block:: cylc-graph + + # branch the graph depending on the outcome of "showdown" + showdown:good? => good + showdown:bad? => bad + showdown:ugly? => ugly + # join the graph back together + good | bad | ugly => fin + + +.. digraph:: Example + :align: center + + subgraph cluster_1 { + label = ":good" + color = "green" + fontcolor = "green" + style = "dashed" + + good + } + subgraph cluster_2 { + label = ":bad" + color = "red" + fontcolor = "red" + style = "dashed" + + bad + } + subgraph cluster_3 { + label = ":ugly" + color = "purple" + fontcolor = "purple" + style = "dashed" + + ugly + } + showdown -> good + showdown -> bad + showdown -> ugly + good -> fin [arrowhead="onormal"] + bad -> fin [arrowhead="onormal"] + ugly -> fin [arrowhead="onormal"] + + +You can test run this example making ``showdown`` randomly generate one of the +three custom outputs: + +.. code-block:: cylc + + [runtime] + [[showdown]] + # Randomly return one of the three custom outputs: + script = """ + SEED=$RANDOM + if ! (( $SEED % 3 )); then + cylc message 'The Good' + elif ! (( ( $SEED + 1 ) % 3 )); then + cylc message 'The Bad' + else + cylc message 'The Ugly' + fi + """ + + # Ensure that at least one of the custom outputs is produced: + completion = succeeded and (good or bad or ugly) + + # Register the three custom outputs: + [[[outputs]]] + good = 'The Good' + bad = 'The Bad' + ugly = 'The Ugly' + +Completion Expressions +"""""""""""""""""""""" + +.. cylc-scope:: flow.cylc[runtime][] + +The :cylc:conf:`completion` configuration above is optional, it adds a basic +validation check which ensures that at least one of the three custom outputs is +produced when the task runs. This protects you against the possibility that +none of the outputs are produced e.g. due to a task implementation error. + +If the task does not produce at least one of these three outputs, then it will +be marked as having incomplete outputs and will be retained in a similar manner +to if it had failed. This provides you with an opportunity to intervene to +rectify the situation: Without intervention the workflow will :term:`stall`. + +.. cylc-scope:: flow.cylc + +Mutually Exclusive Outputs +"""""""""""""""""""""""""" + +It is not possible to enforce mutually exclusive outputs in Cylc as +tasks may be re-run multiple times and the outputs from previous runs +accumulate. + +E.g, this expression ensures that **at least one** of the three custom outputs +is produced when the task runs: + +.. code-block:: cylc + + completion = succeeded and (good or bad or ugly) + +However, it is not possible to ensure that **only** one of the three is +produced. + +Custom Output Generation Timing +""""""""""""""""""""""""""""""" + +Custom outputs are generated *before* the task succeeds or fails. This is handy +if you don't want downstream tasks to wait for upstream tasks to finish +executing, e.g: + +.. code-block:: cylc-graph + + # run "process_file_1" as soon as the output "file_1" is completed, but + # don't wait for "model" to finish first + model:file_1_ready => process_file_1 + + +.. _RunaheadLimit: + +Runahead Limiting +----------------- + +Runahead limiting prevents a workflow from getting too far ahead of the oldest +active cycle point by holding back tasks in cycles beyond a specified limit. + +The runahead limit is defined as an interval measured from the oldest active cycle. +A cycle is considered to be "active" if it contains any :term:`active` tasks +(e.g. running tasks). + +Tasks in cycles which are beyond the limit are called :term:`runahead` tasks +and are displayed in the GUI/Tui with small circle above them: + +.. image:: ../../img/task-job-icons/task-isRunahead.png + :width: 60px + :height: 60px + +As the workflow advances and active cycles complete, the runahead limit moves +forward allowing tasks in later cycles to run. + +There are two ways of defining the interval which defines the runahead limit, +as an integer number of cycles, or as a datetime interval. + + +Integer Format +^^^^^^^^^^^^^^ + +The runahead limit can be defined as an integer interval with the format +``P``, where ``N`` is an integer. + +For example the default runahead limit is ``P4`` (an interval of four cycles), +which means that up to five cycles may be active simultaneously, the oldest +active cycle and the next four after it. + +E.G. for this example workflow: + +.. code-block:: cylc + + [scheduling] + cycling mode = integer + initial cycle point = 1 + runahead limit = P4 # max 5 active points (the default) + [[graph]] + P1 = foo + +When this workflow starts, the initial cycle point is 1 and the runahead limit +is four cycles after this (i.e. cycle 4). So the task ``foo`` will immediately +submit in cycles 1, 2, 3 and 4, however, the tasks in cycles 5 onwards will +wait until earlier cycles complete, and the runahead limit advances. + +* 1 |task-submitted| - **initial cycle point** +* 2 |task-submitted| +* 3 |task-submitted| +* 4 |task-submitted| - **runahead limit** +* 5 |task-runahead-super| (held back by runahead limit) +* 6 |task-runahead-super| (held back by runahead limit) +* X |task-runahead-super| (held back by runahead limit) + +As the workflow advances and earlier cycles complete, the runahead limit +moves on. E.G. Once the cycles 1 & 2 have completed, the runahead limit will +advance to cycle 6. + +The integer format counts the number of cycles irrespective of the cycling +interval, so if we change the cycling interval from ``P1`` to ``P2Y``: + +.. code-block:: cylc + :emphasize-lines: 2,5 + + [scheduling] + initial cycle point = 2000 # date time cycling + runahead limit = P4 # max 5 active points + [[graph]] + P2Y = foo # cycle points 1, 3, 5, 7, 9, ... + +Then, the task ``foo`` would submit immediately in the cycles 1, 3, 5 and 7. +Cycles from 9 onwards will be held back. + +* 2000 |task-submitted| - **initial cycle point** +* 2002 |task-submitted| +* 2004 |task-submitted| +* 2006 |task-submitted| - **runahead limit** +* 2008 |task-runahead-super| (held back by runahead limit) +* 2010 |task-runahead-super| (held back by runahead limit) +* XXXX |task-runahead-super| (held back by runahead limit) + + +Datetime Format +^^^^^^^^^^^^^^^ + +The runahead interval can also be specified as an :term:`ISO8601 duration`. +This approach *does* depend on the cycling intervals, e.g: + +.. code-block:: cylc + :emphasize-lines: 3 + + [scheduling] + initial cycle point = 2000 + runahead limit = P4Y # max active point: base point + P4Y + [[graph]] + P2Y = foo # cycle points 2050, 2052, 2054, ... + +When this workflow starts, the task foo in the first three cycles will run: + +* 2000 |task-submitted| - **initial cycle point** +* 2002 |task-submitted| +* 2004 |task-submitted| - **runahead limit** +* 2006 |task-runahead-super| (held back by runahead limit) +* 2008 |task-runahead-super| (held back by runahead limit) +* XXXX |task-runahead-super| (held back by runahead limit) + + +Runahead Limit Notes +^^^^^^^^^^^^^^^^^^^^ + +To restrict activity to a single cycle point at a time (just the base point) +use a null runahead interval: ``P0`` or (e.g.) ``PT0H``. + +Runahead limiting does not restrict activity within a cycle point. +Workflows with a large number of tasks per cycle may need :ref:`internal +queues ` to constrain activity in absolute terms. + +The scheduler may automatically raise the runahead limit to accommodate +:term:`future triggered` tasks without stalling the workflow. + + +.. _InternalQueues: + +Internal Queues +--------------- + +Large workflows can potentially overwhelm the system by submitting too many +jobs at once. Internal queues can prevent this by limiting the number of +tasks that can be active (submitted or running) at the same time. + +Internal queues are FIFO (first-in-first-out): tasks are released in the same +order that they were queued. They are configured under +:cylc:conf:`[scheduling][queues]` with a *name*; a list of *members* assigned +by task or family name; and a *limit*, which is the maximum number of active +members allowed. + +By default every task is assigned to the ``default`` queue, which by default +has a zero limit (interpreted by Cylc as no limit). To use a single queue for +the whole workflow just set the default queue limit: + +.. code-block:: cylc + + [scheduling] + [[queues]] + # limit the entire workflow to 5 active tasks at once + [[[default]]] + limit = 5 + +To use additional queues just name them, set limits, and assign members: + +.. code-block:: cylc + + [scheduling] + [[queues]] + [[[q_foo]]] + limit = 5 + members = foo, bar, baz + +Any tasks not assigned to a particular queue will remain in the default +queue. The following example illustrates how queues work by running two task +trees side by side, limited to 2 and 3 tasks respectively: + +.. literalinclude:: ../../workflows/queues/flow.cylc + :language: cylc + + +Valid Task Cycle Points +----------------------- + +Graph triggers determine the sequence of valid cycle points (via the +recurrence value of the associated graph string) and the prerequisites, for +each downstream task in a dependency. In the absence of a cycle point offset +(intercycle trigger) they also determine the sequence of cycle points for +the upstream tasks: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2025-01-01T00 + [[graph]] + P2D = "foo & bar => baz" + +This says ``baz`` depends on ``foo`` and ``bar`` for every point in the +sequence defined by the recurrence ``P2D`` (i.e. ``R/^/P2D``). + +Cylc does not infer the cyclepoint sequence for upstream tasks in intercycle +triggers, however. All tasks must be tied to the right sequence by appearing +somewhere in the graph with no offset. This prevents unintentional creation of +off-sequence tasks by an offset error in the graph. + +For instance, the following example fails validation with *no cycling sequences +defined for* ``foo``: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2025-01-01T00 + [[graph]] + # ERROR! + P2D = "foo[-P1D] & bar" + +To fix this, ``foo`` should be explicitly tied to the ``P2D`` cycle, and the +correct offset used: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2025-01-01T00 + [[graph]] + P2D = """ + foo + foo[-P2D] & bar + """ + +Or it should be explicitly tied to the intermediate cycle, if the ``P1D`` offset +is actually correct: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2025-01-01T00 + [[graph]] + R/+P1D/P2D = foo # day 2, 4, 6, ... + P2D = "foo[-P1D] & bar" # day 1, 3, 5, ... + + +Note that validation does not detect this sort of error if the target task has +cyclepoint sequences defined but the offset does not land on them. For example, +the following graph will validate but ``bar`` will only run once in the first +cycle point (where its pre-initial dependence is ignored): + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2025-01-01T00 + [[graph]] + P2D = """ + foo + foo[-P1D] => bar # ERROR: foo doesn't exist at -P1D + """ + +To fix this, the offset ``[-P1D]`` should be changed to ``[-P2D]``, or else +another graph line is needed to generate ``foo`` instances on the ``P1D`` sequence: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2025-01-01T00 + [[graph]] + P1D = "foo" + P2D = "foo[-P1D] => bar" + + +Omitting Tasks +-------------- + +It can sometimes be useful to temporarily remove tasks by simply commenting +them out of the graph. Validation warns about tasks defined under +:cylc:conf:`[runtime]` but not used in the graph, as a reminder to restore them +or remove them. + +You can also use logical Jinja2 switches (:ref:`User Guide Jinja2`) to +include or exclude tasks (or anything else) from workflow. + +.. [1] For example, in weather forecasting workflows (and similar systems) each + new forecast depends partly on the outcome of the previous forecast. + +.. [2] By distinguishing graph branches that did not run but should have, from + those that did not run but were optional. + +.. [3] This includes failed job submission, when the ``:submit`` output is not + marked as optional. diff --git a/nightly_8.4/html/_sources/user-guide/writing-workflows/suicide-triggers.rst.txt b/nightly_8.4/html/_sources/user-guide/writing-workflows/suicide-triggers.rst.txt new file mode 100644 index 00000000000..4583558d889 --- /dev/null +++ b/nightly_8.4/html/_sources/user-guide/writing-workflows/suicide-triggers.rst.txt @@ -0,0 +1,80 @@ +.. _SuicideTriggers: + +Suicide Triggers +================ + +.. warning:: + + Suicided triggers were needed in Cylc 7 and earlier to remove pre-spawned + waiting tasks from graph branches not taken at runtime, which would stall + the workflow. + + However, **Cylc 8 does not need suicide triggers for** :term:`graph + branching `. + + They remain supported, and documented, for backward compatibility and for + a rare :ref:`edge case `. + + +Suicide triggers remove waiting :term:`tasks ` from the +:term:`scheduler's ` active :term:`active window` at runtime. + +They are activated just like normal :term:`task triggers ` but +they remove the downstream task (prefixed with ``!``) instead of triggering it +to run. + +Here, the task ``bar`` will be removed if ``foo`` succeeds: + +.. code-block:: cylc-graph + + foo => !bar + +Suicide triggers combine in the same way as normal triggers, so this graph: + +.. code-block:: cylc-graph + + foo => !baz + bar => !baz + +is equivalent to this: + +.. code-block:: cylc-graph + + foo & bar => !baz + +i.e. both ``foo`` and ``bar`` must succeed for ``baz`` to be removed. + +To remove a task after any one of several events, use an OR operator: + +.. code-block:: cylc-graph + + foo | bar => !baz + +.. note:: + + At present, only :term:`active tasks ` that are waiting + (e.g. queued tasks) can be removed by ``cylc remove``. + + +.. _remaining-use-cases: + +Remaining Use Case +------------------ + +Suicide triggers may be needed to remove a waiting :term:`active task` when it +can be inferred from the status of another task that the external trigger will +never be satisfied. + +In the following example imagine that the two xtriggers watch two locations for +the same file to appear. The file will be delivered to one location or the +other but not to both, so if one xtrigger is satisfied the other will never be. +The stuck waiting task can be removed with a suicide trigger, so that it +doesn't stall the workflow: + +.. code-block:: cylc-graph + + @xtrigger1 => A + @xtrigger2 => B + + A => !B # If A succeeds, remove B + B => !A # If B succeeds, remove A diff --git a/nightly_8.4/html/_sources/workflow-design-guide/efficiency.rst.txt b/nightly_8.4/html/_sources/workflow-design-guide/efficiency.rst.txt new file mode 100644 index 00000000000..45e84ef671d --- /dev/null +++ b/nightly_8.4/html/_sources/workflow-design-guide/efficiency.rst.txt @@ -0,0 +1,371 @@ +.. _Efficiency And Maintainability: + +Efficiency And Maintainability +============================== + +Efficiency (in the sense of *economy of workflow definition*) and +maintainability go hand in hand. This section describes techniques for clean +and efficient construction of complex workflows that are easy to understand, +maintain, and modify. + + +.. _The Task Family Hierarchy: + +The Task Family Hierarchy +------------------------- + +A properly designed family hierarchy fulfils three purposes in Cylc: + +- efficient sharing of configuration common to groups of related tasks +- efficient bulk triggering, for clear scheduling graphs +- collapsible families in workflow visualization and UI views + + +.. _Sharing By Inheritance: + +Sharing By Inheritance +^^^^^^^^^^^^^^^^^^^^^^ + +Duplication is a maintenance risk because changes have to be repeated in +multiple places without mistakes. On the other hand, unnecessary sharing of +items via global variables is also bad because it is hard to be sure which +tasks are using which variables. A properly designed runtime inheritance +hierarchy can give every task exactly what it needs, and nothing that it +doesn't need. + +If a group of related tasks has some configuration in common, it can be +factored out into a task family inherited by all. + +.. code-block:: cylc + + [runtime] + [[OBSPROC]] + # Settings common to all obs processing tasks. + [[obs1]] + inherit = OBSPROC + [[obs2]] + inherit = OBSPROC + +If several families have settings in common, they can in turn can inherit +from higher-level families. + +Multiple inheritance allows efficient sharing even for overlapping categories +of tasks. For example consider that some obs processing tasks in the following +workflow run parallel jobs and some serial: + +.. code-block:: cylc + + [runtime] + [[SERIAL]] + # Serial job settings. + [[PARALLEL]] + # Parallel job settings. + [[OBSPROC]] + # Settings for all obs processing tasks. + [[obs1, obs2, obs3]] + # Serial obs processing tasks. + inherit = OBSPROC, SERIAL + [[obs4, obs5]] + # Parallel obs processing tasks. + inherit = OBSPROC, PARALLEL + +Note that workflow parameters should really be used to define family members +efficiently - see :ref:`Generating Tasks`. + +Cylc provides tools to help make sense of your inheritance hierarchy: + +- ``cylc graph -n/--namespaces`` - plot the full multiple + inheritance graph (not the dependency graph) +- ``cylc config `` - print selected sections or items + after inheritance processing +- ``cylc graph `` - plot the dependency graph, with + collapsible first-parent families + (see :ref:`Task Families And Visualization`) +- ``cylc list -t/--tree `` - print the first-parent + inheritance hierarchy +- ``cylc list -m/--mro `` - print the inheritance + precedence order for each runtime namespace + + +Family Triggering +^^^^^^^^^^^^^^^^^ + +Task families can be used to simplify the scheduling graph wherever many +tasks need to trigger at once: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = pre => MODELS + [runtime] + [[MODELS]] + [[model1, model2, model3, ...]] + inherit = MODELS + +To trigger *off of* many tasks at once, family names need to be qualified +by ``-all`` or ``-any`` to indicate the desired +member-triggering semantics: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + pre => MODELS + MODELS:succeed-all => post + """ + +Note that this can be simplified further because Cylc ignores trigger +qualifiers like ``:succeed-all`` on the right of trigger arrows +to allow chaining of dependencies: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = pre => MODELS:succeed-all => post + + +Family-to-Family Triggering +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. TODO: Is this section still true post-SoD? + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = BIG_FAM_1:succeed-all => BIG_FAM_2 + +This means every member of ``BIG_FAM_2`` depends on every member +of ``BIG_FAM_1`` succeeding. For very large families this can create so +many dependencies that it affects the performance of Cylc at run time, as +well as cluttering graph visualizations with unnecessary edges. Instead, +interpose a blank task that signifies completion of the first family: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = BIG_FAM_1:succeed-all => big_fam_1_done => BIG_FAM_2 + +For families with ``M`` and ``N`` members respectively, this +reduces the number of dependencies from ``M*N`` to ``M+N`` +without affecting the scheduling. + +.. image:: ../img/fam-to-fam-1.png + +.. image:: ../img/fam-to-fam-2.png + + +.. _Task Families And Visualization: + +Task Families And Visualization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*First parents* in the inheritance hierarchy double as collapsible summary +groups for visualization and monitoring. Tasks should generally be grouped into +visualization families that reflect their logical purpose in the workflow rather +than technical detail such as inherited job submission or host settings. So in +the example under :ref:`Sharing By Inheritance` above all +``obs`` tasks collapse into ``OBSPROC`` but not into +``SERIAL`` or ``PARALLEL``. + +If necessary you can introduce new namespaces just for visualization: + +.. code-block:: cylc + + [runtime] + [[MODEL]] + # (No settings here - just for visualization). + [[model1, model2]] + inherit = MODEL, HOSTX + [[model3, model4]] + inherit = MODEL, HOSTY + +To stop a solo parent being used in visualization, demote it to secondary with +a null parent like this: + +.. code-block:: cylc + + [runtime] + [[SERIAL]] + [[foo]] + # Inherit settings from SERIAL but don't use it in visualization. + inherit = None, SERIAL + + +.. _Generating Tasks: + +Generating Tasks Automatically +------------------------------ + +Groups of tasks that are closely related such as an ensemble of model runs or +a family of obs processing tasks, or sections of workflow that are repeated +with minor variations, can be generated automatically by iterating over +some integer range (e.g. ``model`` for ``n = 1..10``) or +list of strings (e.g. ``obs`` for +``type = ship, buoy, radiosonde, ...``). + + +Jinja2 Loops +^^^^^^^^^^^^ + +Task generation was traditionally done in Cylc with explicit Jinja2 loops, +like this: + +.. code-block:: cylc + + # Task generation the old way: Jinja2 loops (NO LONGER RECOMMENDED!) + {% set PARAMS = range(1,11) %} + [scheduling] + [[graph]] + R1 = """ + {% for P in PARAMS %} + pre => model_p{{P}} => post + {% if P == 5 %} + model_p{{P}} => check + {% endif %} + {% endfor %} """ + [runtime] + {% for P in PARAMS %} + [[model_p{{P}}]] + script = echo "my parameter value is {{P}}" + {% if P == 1 %} + # special case... + {% endif %} + {% endfor %} + +Unfortunately this makes a mess of the workflow definition, particularly the +scheduling graph, and it gets worse with nested loops over multiple parameters. + +.. image:: ../img/param-1.png + + +.. _SDG Parameterized Tasks: + +Parameterized Tasks +^^^^^^^^^^^^^^^^^^^ + +Cylc-6.11 introduced built-in *workflow parameters* for generating tasks +without destroying the clarity of the base workflow definition. Here's the same +example using workflow parameters instead of Jinja2 loops: + +.. code-block:: cylc + + # Task generation the new way: workflow parameters. + [scheduler] + [[parameters]] + p = 1..10 + [scheduling] + [[graph]] + R1 = """ + pre => model

=> post + model => check + """ + [runtime] + [[pre, post, check]] + [[model

]] + script = echo "my parameter value is ${CYLC_TASK_PARAM_p}" + [[model]] + # special case ... + +Here ``model

`` expands to ``model_p7`` for ``p=7``, +and so on, via the default expansion template for integer-valued parameters, +but custom templates can be defined if necessary. Parameters can also be +defined as lists of strings, and you can define dependencies between different +values: ``chunk => chunk

``. Here's a multi-parameter example: + +.. code-block:: cylc + + [scheduler] + allow implicit tasks = True + [[parameters]] + run = a, b, c + m = 1..5 + [scheduling] + [[graph]] + R1 = pre => init => sim => close => post + [runtime] + [[sim]] + +.. image:: ../img/param-2.png + +If family members are defined by workflow parameters, then parameterized +trigger expressions are equivalent to family ``:-all`` triggers. +For example, this: + +.. code-block:: cylc + + [scheduler] + [[parameters]] + n = 1..5 + [scheduling] + [[graph]] + R1 = pre => model => post + [runtime] + [[pre, post]] + [[MODELS]] + [[model]] + inherit = MODELS + +is equivalent to this: + +.. code-block:: cylc + + [scheduler] + [[parameters]] + n = 1..5 + [scheduling] + [[graph]] + R1 = pre => MODELS:succeed-all => post + [runtime] + [[pre, post]] + [[MODELS]] + [[model]] + inherit = MODELS + +(but future plans for family triggering may make the second case more +efficient for very large families). + +For more information on parameterized tasks see the Cylc user guide. + + +.. _Optional App Config Files: + +Optional App Config Files +------------------------- + +Closely related tasks with few configuration differences between them - such as +multiple UM forecast and reconfiguration apps in the same workflow - should use +the same Rose app configuration with the differences supplied by optional +configs, rather than duplicating the entire app for each task. + +Optional app configs should be valid on top of the main app config and not +dependent on the use of other optional app configs. This ensures they will +work correctly with macros and can therefore be upgraded automatically. + +Optional app configs can be loaded by command line switch: + +.. code-block:: bash + + rose task-run -O key1 -O key2 + +or by environment variable: + +.. code-block:: bash + + ROSE_APP_OPT_CONF_KEYS = key1 key2 + +The environment variable is generally preferred in workflows because you don't +have to repeat and override the root-level script configuration: + +.. code-block:: cylc + + [runtime] + [[root]] + script = rose task-run -v + [[foo]] + [[[environment]]] + ROSE_APP_OPT_CONF_KEYS = key1 key2 diff --git a/nightly_8.4/html/_sources/workflow-design-guide/general-principles.rst.txt b/nightly_8.4/html/_sources/workflow-design-guide/general-principles.rst.txt new file mode 100644 index 00000000000..f41ecbc29f3 --- /dev/null +++ b/nightly_8.4/html/_sources/workflow-design-guide/general-principles.rst.txt @@ -0,0 +1,703 @@ +.. _Basic Principles: + +Basic Principles +================ + +This section covers general principles that should be kept in mind when +writing any workflow. More advanced topics are covered later: +:ref:`Efficiency And Maintainability` and :ref:`Portable Workflows Label`. + + +Cycle point time zone +--------------------- + +Cylc has full local timezone support if needed, but the default cycle point time +zone is UTC. See :cylc:conf:`flow.cylc[scheduler]cycle point time zone`. + + +Fine Or Coarse-Grained Workflows +-------------------------------- + +Workflows can have many small simple tasks, fewer large complex tasks, or anything +in between. A task that runs many distinct processes can be split into many +distinct tasks. The fine-grained approach is more transparent and it allows +more task level concurrency and quicker failure recovery - you can rerun just +what failed without repeating anything unnecessarily. + + +rose bunch +^^^^^^^^^^ + +One caveat to our fine-graining advice is that submitting a large number of +small tasks at once may be a problem on some platforms. If you have many +similar concurrent jobs you can use ``rose bunch`` to pack them into a +single task with incremental rerun capability: retriggering the task will rerun +just the component jobs that did not successfully complete earlier. + + +.. _Monolithic Or Interdependent Workflows: + +Monolithic Or Interdependent Workflows +-------------------------------------- + +When writing workflows from scratch you may need to decide between putting +multiple loosely connected sub-workflows into a single large workflow, or +constructing a more modular system of smaller workflows that depend on each other +through :ref:`inter-workflow triggering `. +Each approach has its pros and cons, depending on your requirements and +preferences with respect to the complexity and manageability of the resulting +system. + + +.. _Self-Contained Workflows: + +Self-Contained Workflows +------------------------ + +All files generated by Cylc during a workflow run are confined to the workflow +:term:`run directory` ``$HOME/cylc-run/``. However, Cylc has no +control over the locations of the programs, scripts, and files, that are +executed, read, or generated by your tasks at runtime. It is up to you to +ensure that all of this is confined to the run directory too, as far as +possible. + +Self-contained workflows are more robust, easier to work with, and more portable. +Multiple instances of the same workflow (with different workflow names) should be +able to run concurrently under the same user account without mutual +interference. + + +Avoiding External Files +^^^^^^^^^^^^^^^^^^^^^^^ + +Workflows that use external scripts, executables, and files beyond the essential +system libraries and utilities are vulnerable to external changes: someone +else might interfere with these files without telling you. + +In some case you may need to symlink to large external files anyway, if space +or copy speed is a problem, but otherwise workflows with private copies of all the +files they need are more robust. + + +Confining Output To The Run Directory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Output files should be confined to the run directory tree. Then all +output is easy to find, multiple instances of the same workflow can run +concurrently without interference, and other users should be able to copy and +run your workflow with few modifications. Cylc provides a ``share`` +directory for generated files that are used by several tasks in a workflow +(see :ref:`Shared Task IO Paths`). Archiving tasks can use ``rose arch`` +to copy or move selected files to external locations as needed (see +:ref:`Workflow Housekeeping`). + + +Task Host Selection +------------------- + +The ``rose host-select`` command is now deprecated. Workflows should migrate +to using :term:`platforms ` which provide a more efficient +solution. +See :ref:`MajorChangesPlatforms` for details. + + +Task Scripting +-------------- + +Non-trivial task scripting should be held in separate script files rather than +inlined in :cylc:conf:`flow.cylc`. This keeps the workflow definition tidy, and it +allows proper shell-mode text editing and independent testing of task scripts. + +For automatic access by jobs, task-specific scripts should be kept in +Rose app bin directories, and shared scripts kept in (or installed to) the +workflow bin directory. + + +Coding Standards +^^^^^^^^^^^^^^^^ + +When writing your own task scripts make consistent use of appropriate coding +standards such as: + +- `PEP8 for Python `_ +- `Google Shell Style Guide for + Bash `_ + + +Basic Functionality +^^^^^^^^^^^^^^^^^^^ + +In consideration of future users who may not be expert on the internals of your +workflow and its tasks, all task scripts should: + +- Print clear usage information if invoked incorrectly (and via the + standard options ``-h, --help``). +- Print useful diagnostic messages in case of error. For example, if a + file was not found, the error message should contain the full path to the + expected location. +- Always return correct shell exit status - zero for success, non-zero + for failure. This is used by Cylc job wrapper code to detect success and + failure and report it back to the :term:`scheduler`. +- In shell scripts use ``set -u`` to abort on any reference to + an undefined variable. If you really need an undefined variable to evaluate + to an empty string, make it explicit: ``FOO=${FOO:-}``. +- In shell scripts use ``set -e`` to abort on any error without + having to failure-check each command explicitly. +- In shell scripts use ``set -o pipefail`` to abort on any error + within a pipe line. Note that all commands in the pipe line will still + run, it will just exit with the right most non-zero exit status. + +.. note:: + + Examples and more details `are available `_ + for the above three ``set`` commands. + + Inline scripts (defined in the job-script section of the + workflow configuration) do not need to ``set -euo pipefail``: + It is already set as part of the + :ref:`job script's error handling `. + + +Rose Apps +--------- + +Rose apps allow all non-shared task configuration - which is not relevant to +workflow automation - to be moved from the workflow definition into app config +files. This makes workflows tidier and easier to understand, and it allows +``rose edit`` to provide a unified metadata-enhanced view of the workflow +and its apps (see :ref:`Rose Metadata Compliance`). + +Rose apps are a clear winner for tasks with complex configuration requirements. +It matters less for those with little configuration, but for consistency and to +take full advantage of ``rose edit`` it makes sense to use Rose apps +for most tasks. + +When most tasks are Rose apps, set the app-run command as a root-level default, +and override it for the occasional non Rose app task: + +.. code-block:: cylc + + [runtime] + [[root]] + script = rose task-run -v + [[rose-app1]] + #... + [[rose-app2]] + #... + [[hello-world]] # Not a Rose app. + script = echo "Hello World" + + +.. _Rose Metadata Compliance: + +Rose Metadata Compliance +------------------------ + +Rose metadata drives page layout and sort order in ``rose edit``, plus +help information, input validity checking, macros for advanced checking and app +version upgrades, and more. + +To ensure the workflow and its constituent applications are being run as intended +it should be valid against any provided metadata: launch the +``rose edit`` GUI or run ``rose macro --validate`` on the +command line to highlight any errors, and correct them prior to use. If errors +are flagged incorrectly you should endeavour to fix the metadata. + +When writing a new workflow or application, consider creating metadata to +facilitate ease of use by others. + + +Task Independence +----------------- + +Essential dependencies must be encoded in the workflow graph, but +tasks should not rely unnecessarily on the action of other tasks. +For example, tasks should create their own output directories if they don't +already exist, even if they would normally be created by an earlier task +in the workflow. This makes it is easier to run tasks alone during +development and testing. + + +.. _Clock-Triggered Tasks: + +Clock-Triggered Tasks +--------------------- + +Tasks that wait on real time data should use +:ref:`clock triggers ` +to delay job submission until the expected data arrival time: + +.. code-block:: cylc + + [scheduling] + initial cycle point = now + [[xtriggers]] + # Trigger 5 min after wallclock time is equal to cycle point. + clock = wall_clock(offset=PT5M) + [[graph]] + T00 = @clock => get-data => process-data + +.. cylc-scope:: flow.cylc[runtime][] + +Clock-triggered tasks typically have to handle late data arrival. Task +:cylc:conf:`execution retry delays` can be used to simply retrigger +the task at intervals until the data is found, but frequently retrying small +tasks is inefficient, and multiple task +failures will be logged for what is a essentially a normal condition (at least +it is normal until the data is really late). + +.. cylc-scope:: + +Rather than using task execution retry delays to repeatedly trigger a task that +checks for a file, it may be better to have the task itself repeatedly poll for +the data (see :ref:`Custom Trigger Functions`). + + +.. _Rose App File Polling: + +Rose App File Polling +--------------------- + +Rose apps have built-in polling functionality to check repeatedly for the +existence of files before executing the main app. See the ``[poll]`` +section in Rose app config documentation. This is a good way to implement +check-and-wait functionality in clock-triggered tasks +(:ref:`Clock-Triggered Tasks`), for example. + +It is important to note that frequent polling may be bad for some filesystems, +so be sure to configure a reasonable interval between polls. + + +Task Execution Time Limits +-------------------------- + +Instead of setting job wallclock limits directly in :term:`job runner` +directives, use +:cylc:conf:`flow.cylc[runtime][]execution time limit`. +Cylc automatically derives the correct job runner directives from this, +and it is also used to run ``background`` and ``at`` jobs via +the ``timeout`` command, and to poll tasks that haven't reported in +finished by the configured time limit. + + +.. _Restricting Workflow Activity: + +Restricting Workflow Activity +----------------------------- + +It may be possible for large workflows to overwhelm a job host by submitting too +many jobs at once: + +- Large workflows that are not sufficiently limited by real time clock + triggering or intercycle dependence may generate a lot of *runahead* + (this refers to Cylc's ability to run multiple cycles at once, restricted + only by the dependencies of individual tasks). +- Some workflows may have large families of tasks whose members all + become ready at the same time. + +These problems can be avoided with *runahead limiting* and *internal +queues*, respectively. + + +.. _Runahead Limiting: + +Runahead Limiting +^^^^^^^^^^^^^^^^^ + +By default Cylc allows a maximum of five cycle points to be active at the same +time, but this value is configurable: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2020-01-01T00 + # Don't allow any cycle interleaving: + runahead limit = P0 + + +Internal Queues +^^^^^^^^^^^^^^^ + +Tasks can be assigned to named internal queues that limit the number of members +that can be active (i.e. submitted or running) at the same time: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2020-01-01T00 + [[queues]] + # Allow only 2 members of BIG_JOBS to run at once: + [[[big_jobs_queue]]] + limit = 2 + members = BIG_JOBS + [[graph]] + T00 = pre => BIG_JOBS + [runtime] + [[BIG_JOBS]] + [[foo, bar, baz, ...]] + inherit = BIG_JOBS + + +.. _Workflow Housekeeping: + +Workflow Housekeeping +--------------------- + +Ongoing cycling workflows can generate an enormous number of output files and logs +so regular housekeeping is very important. Special housekeeping tasks, +typically the last tasks in each cycle, should be included to archive selected +important files and then delete everything at some offset from the current +cycle point. + +The Rose built-in apps ``rose_arch`` and ``rose_prune`` +provide an easy way to do this. They can be configured easily with +file-matching patterns and cycle point offsets to perform various housekeeping +operations on matched files. + + +Complex Jinja2 Code +------------------- + +The Jinja2 template processor provides general programming constructs, +extensible with custom Python filters, that can be used to *generate* the +workflow definition. This makes it possible to write flexible multi-use +workflows with structure and content that varies according to various input +switches. There is a cost to this flexibility however: excessive use of Jinja2 +can make a workflow hard to understand and maintain. It is difficult to say +exactly where to draw the line, but we recommend erring on the side of +simplicity and clarity: write workflows that are easy to understand and therefore +easy to modify for other purposes, rather than extremely complicated workflows +that attempt do everything out of the box but are hard to maintain and modify. + +Note that use of Jinja2 loops for generating tasks is now deprecated in favour +of built-in parameterized tasks - see :ref:`User Guide Param`. + + +Shared Configuration +-------------------- + +Configuration that is common to multiple tasks should be defined in one +place and used by all, rather than duplicated in each task. Duplication is +a maintenance risk because changes have to be made consistently in several +places at once. + + +Jinja2 Variables +^^^^^^^^^^^^^^^^ + +In simple cases you can share by passing a Jinja2 variable to all the tasks +that need it: + +.. code-block:: cylc + + {% set JOB_VERSION = 'A23' %} + [runtime] + [[foo]] + script = run-foo --version={{JOB_VERSION}} + [[bar]] + script = run-bar --version={{JOB_VERSION}} + + +Inheritance +^^^^^^^^^^^ + +Sharing by inheritance of task families is recommended when more than a few +configuration items are involved. + +The simplest application of inheritance is to set global defaults in the +``[runtime][root]`` namespace that is inherited by all tasks. +However, this should only be done for settings that really are used +by the vast majority of tasks. Over-sharing of via root, particularly of +environment variables, is a maintenance risk because it can be very +difficult to be sure which tasks are using which global variables. + +Any :cylc:conf:`[runtime]` settings can be shared - scripting, platform +configuration, environment variables, and so on - from +single items up to complete task or app configurations. At the latter extreme, +it is quite common to have several tasks that inherit the same complete +job configuration followed by minor task-specific additions: + +.. code-block:: cylc + + [runtime] + [[FILE-CONVERT]] + script = convert-netcdf + #... + [[convert-a]] + inherit = FILE-CONVERT + [[[environment]]] + FILE_IN = file-a + [[convert-b]] + inherit = FILE-CONVERT + [[[environment]]] + FILE_IN = file-b + +Inheritance is covered in more detail from an efficiency perspective in +:ref:`The Task Family Hierarchy`. + + +.. _Shared Task IO Paths: + +Shared Task IO Paths +^^^^^^^^^^^^^^^^^^^^ + +If one task uses files generated by another task (and both see the same +filesystem) a common IO path should normally be passed to both tasks via a +shared environment variable. As far as Cylc is concerned this is no different +to other shared configuration items, but there are some additional aspects +of usage worth addressing here. + +Primarily, for self-containment (see :ref:`Self-Contained Workflows`) shared IO +paths should be under the *workflow share directory*, the location of which is +passed to all tasks as ``$CYLC_WORKFLOW_SHARE_DIR``. + +The ``rose task-env`` utility can provide additional environment +variables that refer to static and cyclepoint-specific locations under the +workflow share directory. + +.. code-block:: cylc + + [runtime] + [[my-task]] + env-script = $(eval rose task-env -T P1D -T P2D) + +For a current cycle point of ``20170105`` this will make the following +variables available to tasks: + +.. code-block:: bash + + ROSE_DATA=$CYLC_WORKFLOW_SHARE_DIR/data + ROSE_DATAC=$CYLC_WORKFLOW_SHARE_DIR/cycle/20170105 + ROSE_DATACP1D=$CYLC_WORKFLOW_SHARE_DIR/cycle/20170104 + ROSE_DATACP2D=$CYLC_WORKFLOW_SHARE_DIR/cycle/20170103 + +Subdirectories of ``$ROSE_DATAC`` etc. should be agreed between +different sub-systems of the workflow; typically they are named for the +file-generating tasks, and the file-consuming tasks should know to look there. + +The share-not-duplicate rule can be relaxed for shared files whose names are +agreed by convention, so long as their locations under the share directory are +proper shared workflow variables. For instance the Unified Model uses a large +number of files whose conventional names (``glu_snow``, for example) +can reasonably be expected not to change, so they are typically hardwired into +app configurations (as ``$ROSE_DATA/glu_snow``, for example) to avoid +cluttering the workflow definition. + +Here two tasks share a workspace under the workflow share directory +by inheritance: + +.. code-block:: cylc + + # Sharing an I/O location via inheritance. + [scheduling] + [[graph]] + R1 = write_data => read_data + [runtime] + [[root]] + env-script = $(eval rose task-env) + [[WORKSPACE]] + [[[environment]]] + DATA_DIR = ${ROSE_DATA}/png + [[write_data]] + inherit = WORKSPACE + script = """ + mkdir -p $DATA_DIR + write-data.exe -o ${DATA_DIR} + """ + [[read_data]] + inherit = WORKSPACE + script = read-data.exe -i ${DATA_DIR} + +In simple cases where an appropriate family does not already exist paths can +be shared via Jinja variables: + +.. code-block:: cylc + + # Sharing an I/O location with Jinja2. + {% set DATA_DIR = '$ROSE_DATA/stuff' %} + [scheduling] + [[graph]] + R1 = write_data => read_data + [runtime] + [[write_data]] + script = """ + mkdir -p {{DATA_DIR}} + write-data.exe -o {{DATA_DIR}} + """ + [[read_data]] + script = read-data.exe -i {{DATA_DIR}} + +For completeness we note that it is also possible to configure multiple tasks +to use the same work directory so they can all share files in ``$PWD``. +(Cylc executes tasks in special work directories that by default are unique +to each task). This may simplify the workflow slightly, and it may be useful if +you are unfortunate enough to have executables that are designed for IO in +``$PWD``, *but it is not recommended*. There is a higher risk +of interference between tasks; it will break ``rose task-run`` +incremental file creation mode; and ``rose task-run --new`` will in +effect delete the work directories of tasks other than its intended target. + +.. code-block:: cylc + + # Shared work directory: tasks can read and write in $PWD - use with caution! + [scheduling] + initial cycle point = 2018 + [[graph]] + P1Y = write_data => read_data + [runtime] + [[WORKSPACE]] + work sub-directory = $CYLC_TASK_CYCLE_POINT/datadir + [[write_data]] + inherit = WORKSPACE + script = write-data.exe + [[read_data]] + inherit = WORKSPACE + script = read-data.exe + + +Varying Behaviour By Cycle Point +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To make a cycling job behave differently at different cycle points you +*could* use a single task with scripting that reacts to the cycle point it finds +itself running at, but it is better to use different tasks (in different +cycling sections) that inherit the same base job configuration. This results +in a more transparent workflow that can be understood just by inspecting the +graph: + +.. code-block:: cylc + + # Run the same job differently at different cycle points. + [scheduling] + initial cycle point = 2020-01-01T00 + [[graph]] + T00 = pre => long_fc => post + T12 = pre => short_fc => post + [runtime] + [[MODEL]] + script = run-model.sh + [[long_fc]] + inherit = MODEL + execution time limit = PT30M + [[[environment]]] + RUN_LEN = PT48H + [[short_fc]] + inherit = MODEL + execution time limit = PT10M + [[[environment]]] + RUN_LEN = PT12H + +The few differences between ``short_fc`` and ``long_fc``, +including :term:`job runner` resource requests, can be configured after common +settings are inherited. + +At Start-Up +^^^^^^^^^^^ + +Similarly, if a cycling job needs special behaviour at the initial (or any +other) cycle point, just use a different logical task in an ``R1`` graph and +have it inherit the same job as the general cycling task, not a single task +with scripting that behaves differently if it finds itself running at the +initial cycle point. + + +Automating Failure Recovery +--------------------------- + + +Job Submission Retries +^^^^^^^^^^^^^^^^^^^^^^ + +When submitting jobs to a remote host, use job submission retries to +automatically resubmit tasks in the event of network outages. + +Note that this is distinct from job retries for +job execution failure (just below). + +Job Execution Retries +^^^^^^^^^^^^^^^^^^^^^ + +Automatic retry on job execution failure is useful if you have good reason to +believe that a simple retry will usually succeed. This may be the case if the +job host is known to be flaky, or if the job only ever fails for one known +reason that can be fixed on a retry. For example, if a model fails occasionally +with a numerical instability that can be remedied with a short timestep rerun, +then an automatic retry may be appropriate. + +.. code-block:: cylc + + [runtime] + [[model]] + script = """ + if [[ $CYLC_TASK_TRY_NUMBER > 1 ]]; then + SHORT_TIMESTEP=true + else + SHORT_TIMESTEP=false + fi + model.exe + """ + execution retry delays = 1*PT0M + + +Failure Recovery Workflows +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For recovery from failures that require explicit diagnosis you can configure +alternate graph branches. In the following example, if the model fails a +diagnosis task will trigger; if it determines the cause of the failure is a +known numerical instability (e.g. by parsing model job logs) it will succeed, +triggering a short timestep run. Postprocessing can proceed from either the +original or the short-step model run. + +.. Need to use a 'container' directive to get centered image with + left-aligned caption (as required for code block text). + +.. _fig-failure-rec: + +.. container:: twocol + + .. container:: image + + .. figure:: ../img/failure-recovery.png + :align: center + + .. container:: caption + + .. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + model | model_short => postproc + model:fail => diagnose => model_short + """ + + +Include Files +------------- + +Include-files should not be overused, but they can sometimes be useful +(e.g. see :ref:`Portable Workflows Label`): + +.. code-block:: cylc + + #... + {% include 'inc/foo.cylc' %} + +(Technically this inserts a Jinja2-rendered file template). Cylc also has a +native include mechanism that pre-dates Jinja2 support and literally inlines +the include-file: + +.. code-block:: cylc + + #... + %include 'inc/foo.cylc' + +The two methods normally produce the same result, but use the Jinja2 version if +you need to construct an include-file name from a variable (because Cylc +include-files get inlined before Jinja2 processing is done): + +.. code-block:: cylc + + #... + {% include 'inc/' ~ SITE ~ '.cylc' %} diff --git a/nightly_8.4/html/_sources/workflow-design-guide/index.rst.txt b/nightly_8.4/html/_sources/workflow-design-guide/index.rst.txt new file mode 100644 index 00000000000..1fe6ff845ad --- /dev/null +++ b/nightly_8.4/html/_sources/workflow-design-guide/index.rst.txt @@ -0,0 +1,43 @@ +.. _workflow design guide: + +Workflow Design Guide +===================== + +.. rubric:: Cylc/Rose Workflow Design Best Practice Guide. + +This document provides guidance on making complex Cylc + Rose workflows that +are clear, maintainable, and portable. Note that best practice advice may +evolve over time with the capabilities of Rose and Cylc. + +Content is drawn from the Rose and Cylc user guides, earlier Met Office workflow +design and operational workflow review documents, experience with real workflows +across the Unified Model Consortium, and discussion among members of the UM +TISD (Technical Infrastructure Workflow Design) working group. + +We start with the most general topics (coding style, general principles), +move on to more advanced topics (efficiency and maintainability, portable +workflows), and end with some pointers to future developments. + +.. note:: + + A good working knowledge of Cylc and Rose is assumed. For further details, + please consult the: + + - `Cylc User Guide`_ + - `Rose Documentation`_ + +.. note:: + + For non-Rose users: this document comes out of the Unified Model + Consortium wherein Cylc is used within the Rose *workflow management + framework*. However, the bulk of the information in this guide is about + Cylc workflow design; which parts are Rose-specific should be clear from + context. + +.. toctree:: + :maxdepth: 2 + + style-guide + general-principles + efficiency + portable-workflows diff --git a/nightly_8.4/html/_sources/workflow-design-guide/portable-workflows.rst.txt b/nightly_8.4/html/_sources/workflow-design-guide/portable-workflows.rst.txt new file mode 100644 index 00000000000..e7998534aac --- /dev/null +++ b/nightly_8.4/html/_sources/workflow-design-guide/portable-workflows.rst.txt @@ -0,0 +1,494 @@ +.. _Portable Workflows Label: + +Portable Workflows +================== + +A *portable* or *interoperable* workflow can run "out of the box" at +different sites, or in different environments such as research and operations +within a site. For convenience we just use the term *site portability*. + +Lack of portability is a major barrier to collaborative development when +sites need to run more or less the same workflow, because it is very +difficult to translate changes manually between large, complicated workflows. + +Most workflows are riddled with site-specific details such as local build +configurations, file paths, host names, and batch scheduler directives, etc.; +but it is possible to cleanly factor all this out to make a portable workflow. +Significant variations in workflow structure can even be accommodated quite +easily. If the site workflows are *too different*, however, you may decide +that it is appropriate for each site to maintain separate workflows. + +The recommended way to do this, which we expand on below, is: + +- Put all site-specific settings in include-files loaded at the end + of a generic "core" workflow definition. +- Use "optional" app config files for site-specific variations + in the core workflow's Rose apps. +- (Make minimal use of inlined site switches too, if necessary). +- When referencing files, reference them within the workflow structure and + use an install task to link external files in. + +The result should actually be tidier than the original in one respect: all +the messy platform-specific resource directives etc., will be hidden away in +the site include-files. + + +The Jinja2 SITE Variable +------------------------ + +First a workflow Jinja2 variable called ``SITE`` should be set to the site +name, either in ``rose-suite.conf``, or in the workflow definition itself +(perhaps automatically, by querying the local environment in some way). + +.. code-block:: cylc + + #!Jinja2 + {% set SITE = "niwa" %} + #... + +This will be used to select site-specific configuration, as described below. + + +Site Include-Files +------------------ + +If a section heading in a :cylc:conf:`flow.cylc` file is repeated the items +under it simply add to or override those defined under the same section earlier +in the file. +For example, this task definition: + +.. code-block:: cylc + + [runtime] + [[foo]] + script = run-foo.sh + platform = niwa_hpc + +can equally be written like this: + +.. code-block:: cylc + + [runtime] # Part 1 (site-agnostic). + [[foo]] + script = run-foo.sh + [runtime] # Part 2 (site-specific). + [[foo]] + platform = niwa_hpc + +.. note:: + + If Part 2 had also defined ``script`` the new value would + override the original. It can sometimes be useful to set a widely used + default and override it in a few cases, but be aware that this can + make it more difficult to determine the origin of affected values. + +In this way all site-specific ``[runtime]`` settings, with their +respective sub-section headings, can be moved to the end of the file, and then +out into an include-file (file inclusion is essentially just literal inlining): + +.. code-block:: cylc + + #... + {% set SITE = "niwa" %} + + # Core site-agnostic settings: + #... + [runtime] + [[foo]] + script = run-foo.sh + #... + + # Site-specific settings: + {% include 'site/' ~ SITE ~ '.cylc' %} + +where the site include-file ``site/niwa.cylc`` contains: + +.. code-block:: cylc + + # site/niwa.cylc + [runtime] + [[foo]] + platform = niwa_hpc + + +Site-Specific Graphs +-------------------- + +Repeated ``graph`` strings under the same graph section headings are +always additive (graph strings are the only exception to the normal repeat item +override semantics). So, for instance, this graph: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2025 + [[graph]] + P1Y = "pre => model => post => niwa_archive" + +can be written like this: + +.. code-block:: cylc + + [scheduling] + initial cycle point = 2025 + [[graph]] + P1Y = "pre => model => post" + P1Y = "post => niwa_archive" + +and again, the site-specific part can be taken out to a site include-file: + +.. code-block:: cylc + + #... + {% set SITE = "niwa" %} + + # Core site-agnostic settings. + #... + [scheduling] + initial cycle point = 2025 + [[graph]] + P1Y = "pre => model => post" + #... + # Site-specific settings: + {% include 'site/' ~ SITE ~ '.cylc' %} + +where the site include-file ``site/niwa.cylc`` contains: + +.. code-block:: cylc + + # site/niwa.cylc + [scheduling] + [[graph]] + P1Y = "post => niwa_archive" + +Note that the site-file graph needs to define the dependencies of the +site-specific tasks, and thus their points of connection to the core +workflow - which is why the core task ``post`` appears in the graph here (if +``post`` had any site-specific runtime settings, to get it to run at +this site, they would also be in the site-file). + + +.. _Inlined Site-Switching: + +Inlined Site-Switching +---------------------- + +It may be tempting to use inlined switch blocks throughout the workflow instead of +site include-files, but *this is not recommended* - it is verbose and +untidy (the greater the number of supported sites, the bigger the +mess) and it exposes all site configuration to all users: + +.. code-block:: cylc + + #... + [runtime] + [[model]] + script = run-model.sh + {# Site switch blocks not recommended:#} + {% if SITE == 'niwa' %} + platform = niwa_loadleveler_platform + [[[directives]]] + # NIWA Loadleveler directives... + {% elif SITE == 'metoffice' %} + platform = metoffice_pbs_platform + [[[directives]]] + # Met Office PBS directives... + {% elif SITE == ... %} + #... + {% else %} + {{raise('Unsupported site: ' ~ SITE)}} + {% endif %} + #... + +Inlined switches can be used, however, to configure exceptional behaviour at +one site without requiring the other sites to duplicate the default behaviour. +But be wary of accumulating too many of these switches: + +.. code-block:: cylc + + # (core flow.cylc file) + #... + {% if SITE == 'small' %} + {# We can't run 100 members... #} + {% set ENSEMBLE_SIZE = 25 %} + {% else %} + {# ...but everyone else can! #} + {% set ENSEMBLE_SIZE = 100 %} + {% endif %} + #... + +Inlined switches can also be used to temporarily isolate a site-specific +change to a hitherto non site-specific part of the workflow, thereby avoiding the +need to update all site include-files before getting agreement from the workflow +owner and collaborators. + + +Site-Specific Workflow Variables +-------------------------------- + +It can sometimes be useful to set site-specific values of workflow variables that +aren't exposed to users via ``rose-suite.conf``. For example, consider +a workflow that can run a special post-processing workflow of some kind at sites +where IDL is available. The IDL-dependence switch can be set per site like this: + +.. code-block:: cylc + + #... + {% from SITE ~ '-vars.cylc' import HAVE_IDL, OTHER_VAR %} + R1 = """ + pre => model => post + {% if HAVE_IDL %} + post => idl-1 => idl-2 => idl-3 + {% endif %} + """ + +where for ``SITE = niwa`` the file ``niwa-vars.cylc`` contains: + +.. code-block:: cylc + + {# niwa-vars.cylc #} + {% set HAVE_IDL = True %} + {% set OTHER_VAR = "the quick brown fox" %} + +Note we are assuming there are significantly fewer options (IDL or not, in this +case) than sites, otherwise the IDL workflow should just go in the site +include-files of the sites that need it. + + +Site-Specific Optional Workflow Configs +--------------------------------------- + +During development and testing of a portable workflow you can use an optional Rose +workflow config file to automatically set site-specific workflow inputs and thereby +avoid the need to make manual changes every time you check out and run a new +version. The site switch itself has to be set of course, but there may be other +settings too such as model parameters for a standard local test domain. Just +put these settings in ``opt/rose-suite-niwa.conf`` (for site ``niwa``). + + +Site-Agnostic File Paths in App Configs +--------------------------------------- + +Where possible apps should be configured to reference files within the workflow +structure itself rather than outside of it. This makes the apps themselves +portable and it becomes the job of the install task to ensure all required +source files are available within the workflow structure e.g. via symlink into +the share directory. Additionally, by moving the responsibility of linking +files into the workflow to an install task you gain the added benefit of knowing +if a file is missing at the start of a workflow rather than part way into a run. + + +Site-Specific Optional App Configs +---------------------------------- + +Typically a few but not all apps will need some site customization, e.g. for +local archive configuration, local science options, or whatever. To avoid +explicit site-customization of individual task-run command lines use Rose's +built-in *optional app config* capability: + +.. code-block:: cylc + + [runtime] + [[root]] + script = rose task-run -v -O '({{SITE}})' + +Normally a missing optional app config is considered to be an error, but the +round parentheses here mean the named optional config is optional - i.e. +use it if it exists, otherwise ignore. + +With this setting in place we can simply add a ``opt/rose-app-niwa.conf`` to +any app that needs customization at ``SITE = niwa``. + + +An Example +---------- + +The following small workflow is not portable because all of its tasks are +submitted to a NIWA HPC host; two task are entirely NIWA-specific in that they +respectively install files from a local database and upload products to a local +distribution system; and one task runs a somewhat NIWA-specific configuration +of a model. The remaining tasks are site-agnostic apart from local job host +and batch scheduler directives. + +.. code-block:: cylc + + [scheduler] + UTC mode = True + [scheduling] + initial cycle point = 2017-01-01 + [[graph]] + R1 = install_niwa => preproc + P1D = """ + preproc & model[-P1D] => model => postproc => upload_niwa + postproc => idl-1 => idl-2 => idl-3 + """ + [runtime] + [[root]] + script = rose task-run -v + [[HPC]] # NIWA job host and batch scheduler settings. + platform = niwa_loadleveler_platform + [[[directives]]] + account_no = NWP1623 + class = General + job_type = serial # (most jobs in this workflow are serial) + [[install_niwa]] # NIWA-specific file installation task. + inherit = HPC + [[preproc]] + inherit = HPC + [[model]] # Run the model on a local test domain. + inherit = HPC + [[[directives]]] # Override the serial job_type setting. + job_type = parallel + [[[environment]]] + SPEED = fast + [[postproc]] + inherit = HPC + [[upload_niwa]] # NIWA-specific product upload. + inherit = HPC + +To make this portable, refactor it into a core :cylc:conf:`flow.cylc` file that +contains the clean site-independent workflow configuration and loads all +site-specific settings from an include-file at the end: + +.. code-block:: cylc + + # flow.cylc: CORE SITE-INDEPENDENT CONFIGURATION. + {% set SITE = 'niwa' %} + {% from 'site/' ~ SITE ~ '-vars.cylc' import HAVE_IDL %} + [scheduler] + UTC mode = True + [scheduling] + initial cycle point = 2017-01-01 + [[graph]] + P1D = """ + preproc & model[-P1D] => model => postproc + {% if HAVE_IDL %} + postproc => idl-1 => idl-2 => idl-3 + {% endif %} + """ + [runtime] + [[root]] + script = rose task-run -v -O '({{SITE}})' + [[preproc]] + inherit = HPC + [[preproc]] + inherit = HPC + [[model]] + inherit = HPC + [[[environment]]] + SPEED = fast + {% include 'site/' ~ SITE ~ '.cylc' %} + +plus site files ``site/niwa-vars.cylc``: + +.. code-block:: cylc + + # site/niwa-vars.cylc: NIWA SITE SETTINGS FOR THE EXAMPLE WORKFLOW. + {% set HAVE_IDL = True %} + +and ``site/niwa.cylc``: + +.. code-block:: cylc + + # site/niwa.cylc: NIWA SITE SETTINGS FOR THE EXAMPLE WORKFLOW. + [scheduling] + [[graph]] + R1 = install_niwa => preproc + P1D = postproc => upload_niwa + [runtime] + [[HPC]] + platform = niwa_loadleveler_platform + [[[directives]]] + account_no = NWP1623 + class = General + job_type = serial # (most jobs in this workflow are serial) + [[install_niwa]] # NIWA-specific file installation. + [[model]] + [[[directives]]] # Override the serial job_type setting. + job_type = parallel + [[upload_niwa]] # NIWA-specific product upload. + +and finally, an optional app config file for the local model domain: + +.. code-block:: bash + + app/model/rose-app.conf # Main app config. + app/model/opt/rose-app-niwa.conf # NIWA site settings. + +Some points to note: + +- It is straightforward to extend support to a new site by copying an + existing site file(s) and adapting it to the new job host and batch + scheduler etc. +- Batch system directives should be considered site-specific unless + all supported sites have the same batch system and the same host + architecture (including CPU clock speed and memory size etc.). +- We've assumed that all tasks run on a single HPC host at both + sites. If that's not a valid assumption the ``HPC`` family + inheritance relationships would have to become site-specific. +- Core task runtime configuration aren't needed in site files at all + if their job host and batch system settings can be defined in common + families that are (``HPC`` in this case). + + +.. _Collaborative Development Model: + +Collaborative Development Model +------------------------------- + +Official releases of a portable workflow should be made from the workflow trunk. + +Changes should be developed on feature branches so as not to affect other users +of the workflow. + +Site-specific changes shouldn't touch the core :cylc:conf:`flow.cylc` file, +just the relevant site include-file, and therefore should not need close +scrutiny from other sites. + +Changes to the core :cylc:conf:`flow.cylc` file should be agreed by all +stakeholders, and should be carefully checked for effects on site +include-files: + +- Changing the name of tasks or families in the core workflow may break + sites that add configuration to the original runtime namespace. +- Adding new tasks or families to the core workflow may require + corresponding additions to the site files. +- Deleting tasks or families from the core workflow may require + corresponding parts of the site files to be removed. And also, check for + site-specific triggering off of deleted tasks or families. + +However, if the owner site has to get some changes into the trunk before all +collaborating sites have time to test them, version control will of course +protect those lagging behind from any immediate ill effects. + +When a new feature is complete and tested at the developer's site, the workflow +owner should check out the branch, review and test it, and if necessary request +that other sites do the same and report back. The owner can then merge the +new feature to the trunk once satisfied. + +All planning and discussion associated with the change should be documented on +MOSRS Trac tickets associated with the workflow. + + +Research-To-Operations Transition +--------------------------------- + +Under this collaborative development model it is *possible* to use the +same workflow in research and operations, largely eliminating the difficult +translation between the two environments. Where appropriate, this can save +a lot of work. + +Operations-specific parts of the workflow should be factored out (as for site +portability) into include-files that are only loaded in the operational +environment. Improvements and upgrades can be developed on feature branches in +the research environment. Operations staff can check out completed feature +branches for testing in the operational environment before merging to trunk or +referring back to research if problems are found. After sufficient testing the +new workflow version can be deployed into operations. + +.. note:: + + This obviously glosses over the myriad complexities of the technical + and scientific testing and validation of workflow upgrades; it merely describes + what is possible from a workflow design and collaborative development + perspective. diff --git a/nightly_8.4/html/_sources/workflow-design-guide/style-guide.rst.txt b/nightly_8.4/html/_sources/workflow-design-guide/style-guide.rst.txt new file mode 100644 index 00000000000..d450755cc3d --- /dev/null +++ b/nightly_8.4/html/_sources/workflow-design-guide/style-guide.rst.txt @@ -0,0 +1,311 @@ +.. _style_guide: + +Style Guidelines +================ + +Coding style is largely subjective, but for collaborative development of +complex systems it is important to settle on a clear and consistent style to +avoid getting into a mess. The following style rules are recommended. + +.. seealso:: + + :ref:`cylc lint -r style ` is a tool designed to help + you check your code style. + +Tab Characters +-------------- + +Do not use tab characters. Tab width depends on editor settings, so a mixture +of tabs and spaces in the same file can render to a mess. + +Use ``grep -InPr "\t" *`` to find tabs recursively in files in +a directory. + +In *vim* use ``%retab`` to convert existing tabs to spaces, +and set ``expandtab`` to automatically convert new tabs. + +In *emacs* use *whitespace-cleanup*. + +In *gedit*, use the *Draw Spaces* plugin to display tabs and spaces. + + +Trailing Whitespace +------------------- + +Trailing whitespace is untidy, it makes quick reformatting of paragraphs +difficult, and it can result in hard-to-find bugs (space after intended +line continuation markers). + +To remove existing trailing whitespace in a file use a ``sed`` or +``perl`` one-liner: + +.. code-block:: console + + $ perl -pi -e "s/ +$//g" /path/to/file + # or: + $ sed --in-place 's/[[:space:]]\+$//' path/to/file + +Or do a similar search-and-replace operation in your editor. Editors like +*vim* and *emacs* can also be configured to highlight or automatically +remove trailing whitespace on the fly. + + +Indentation +----------- + +Consistent indentation makes a workflow definition more readable, it shows section +nesting clearly, and it makes block re-indentation operations easier in text +editors. Indent :cylc:conf:`flow.cylc` syntax four spaces per nesting level: + + +Settings (Config Items) +^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: cylc + + [SECTION] + # A comment. + title = the quick brown fox + [[SUBSECTION]] + # Another comment. + a short item = value1 + a very very long item = value2 + +Don't align ``item = value`` pairs on the ``=`` character +like this: + +.. code-block:: cylc + + [SECTION] # Avoid this. + a short item = value1 + a very very long item = value2 + +or like this: + +.. code-block:: cylc + + [SECTION] # Avoid this. + a short item = value1 + a very very long item = value2 + +because the whole block may need re-indenting after a single change, which will +pollute your revision history with spurious changes. + +Comments should be indented to the same level as the section or item they refer +to, and trailing comments should be preceded by two spaces, as shown above. + + +Script String Lines +^^^^^^^^^^^^^^^^^^^ + +Script strings are written verbatim to :term:`job scripts `. + +.. code-block:: cylc + + [runtime] + [[foo]] + script = echo "Hello, Mr. Thompson" + +If using a triple-quoted string, any common leading whitespace is trimmed +using the logic of :py:func:`textwrap.dedent`. As such, it is recommended to +indent like any other triple-quoted string setting in Cylc: + +.. code-block:: cylc + + [runtime] + [[foo]] + # Recommended. + script = """ + if [[ "$RESULT" == "bad" ]]; then + echo "Goodbye World!" + exit 1 + fi + """ + +The example above would result in the following being written to the job +script: + +.. code-block:: bash + + if [[ "$RESULT" == "bad" ]]; then + echo "Goodbye World!" + exit 1 + fi + +.. tip:: + + Take care when indenting here documents (aka heredocs) to match the + common leading whitespace. + + For the following example, each line in ``log.txt`` would end up with + 4 leading white spaces: + + .. code-block:: cylc + + [runtime] + [[foo]] + script = """ + cat >> log.txt <<_EOF_ + The quick brown fox jumped + over the lazy dog. + _EOF_ + """ + + The following will give you lines with no white spaces: + + .. code-block:: cylc + + [runtime] + [[foo]] + script = """ + cat >> log.txt <<_EOF_ + The quick brown fox jumped + over the lazy dog. + _EOF_ + """ + +Graph String Lines +^^^^^^^^^^^^^^^^^^ + +Whitespace is ignored in graph string parsing so internal graph lines +should be indented as if part of the :cylc:conf:`flow.cylc` syntax: + +.. code-block:: cylc + + [scheduling] + [[graph]] + R1 = """ + # Main workflow: + FAMILY:succeed-all => bar & baz => qux + + # Housekeeping: + qux => rose_arch => rose_prune + """ + + +Jinja2 Code +^^^^^^^^^^^ + +A :cylc:conf:`flow.cylc` file with embedded Jinja2 code is essentially a Jinja2 program to +generate a Cylc workflow definition. It is not possible to consistently indent the +Jinja2 as if it were part of the :cylc:conf:`flow.cylc` syntax (which to the Jinja2 processor +is just arbitrary text), so it should be indented from the left margin on +its own terms: + +.. code-block:: cylc + + [runtime] + [[OPS]] + {% for T in OPS_TASKS %} + {% for M in range(M_MAX) %} + [[ops_{{T}}_{{M}}]] + inherit = OPS + {% endfor %} + {% endfor %} + + +Comments +-------- + +Comments should be minimal, but not too minimal. If context and clear +task and variable names will do, leave it at that. Extremely verbose comments +tend to get out of sync with the code they describe, which can be worse +than having no comments. + +Avoid long lists of numbered comments - future changes may require mass +renumbering. + +Avoid page-width "section divider" comments, especially if they are not +strictly limited to the standard line length (see :ref:`Line Length`). + +Indent comments to the same level as the config items they describe. + + +Titles, Descriptions, And URLs +------------------------------ + +Document the workflow and its tasks with ``title``, +``description``, and ``url`` items instead of comments. +See the :cylc:conf:`flow.cylc[meta]` and +:cylc:conf:`flow.cylc[runtime][][meta]` sections. + + +.. _Line Length: + +Line Length And Continuation +---------------------------- + +Keep to the standard maximum line length of 79 characters where possible. Very +long lines affect readability and make side-by-side diffs hard to view. + +Backslash line continuation markers can be used anywhere in the :cylc:conf:`flow.cylc` file +but should be avoided if possible because they are easily broken by invisible +trailing whitespace. + +Continuation markers are not needed in graph strings where trailing +trigger arrows and boolean operators imply line continuation: + +.. code-block:: cylc + + [scheduling] + [[graph]] + # No line continuation marker is needed here. + R1 = """ + prep => one => two => three => + four => five six => seven => eight & + nine & ten => + eleven | + twelve + """ + [runtime] + [[MY_TASKS]] + # A line continuation marker *is* needed here: + [[one, two, three, four, five, six, seven, eight, nine, ten, \ + eleven, twelve, thirteen]] + inherit = MY_TASKS + + +Task Naming Conventions +----------------------- + +Use ``UPPERCASE`` for family names and ``lowercase`` +for tasks, so you can distinguish them at a glance. + +Choose a convention for multi-component names and use it consistently. Put the +most general name components first for natural grouping, e.g. +``obs_sonde``, ``obs_radar`` (not ``sonde_obs`` etc.) + +Within your convention keep names as short as possible. + + +UM System Task Names +^^^^^^^^^^^^^^^^^^^^ + +For UM System workflows we recommend the following full task naming convention: + +.. code-block:: none + + model_system_function[_member] + +For example, ``glu_ops_process_scatwind`` where ``glu`` refers +to the global (deterministic model) update run, ``ops`` is the system +that owns the task, and ``process_scatwind`` is the function it +performs. The optional ``member`` suffix is intended for use with +ensembles as needed. + +Within this convention keep names as short as possible, e.g. use +``fcst`` instead of ``forecast``. + +UM forecast apps should be given names that reflect their general science +configuration rather than geographic domain, to allow use on other model +domains without causing confusion. + + +Rose Config Files +----------------- + +Use ``rose config-dump`` to load and re-save new ``rose.conf`` files. This +puts the files in a standard format (ordering of lines etc.) to ensure that +spurious changes aren't generated when you next use ``rose edit``. + +See also :ref:`Optional App Config Files` on optional app config files. diff --git a/nightly_8.4/html/_sphinx_design_static/design-tabs.js b/nightly_8.4/html/_sphinx_design_static/design-tabs.js new file mode 100644 index 00000000000..b25bd6a4fa1 --- /dev/null +++ b/nightly_8.4/html/_sphinx_design_static/design-tabs.js @@ -0,0 +1,101 @@ +// @ts-check + +// Extra JS capability for selected tabs to be synced +// The selection is stored in local storage so that it persists across page loads. + +/** + * @type {Record} + */ +let sd_id_to_elements = {}; +const storageKeyPrefix = "sphinx-design-tab-id-"; + +/** + * Create a key for a tab element. + * @param {HTMLElement} el - The tab element. + * @returns {[string, string, string] | null} - The key. + * + */ +function create_key(el) { + let syncId = el.getAttribute("data-sync-id"); + let syncGroup = el.getAttribute("data-sync-group"); + if (!syncId || !syncGroup) return null; + return [syncGroup, syncId, syncGroup + "--" + syncId]; +} + +/** + * Initialize the tab selection. + * + */ +function ready() { + // Find all tabs with sync data + + /** @type {string[]} */ + let groups = []; + + document.querySelectorAll(".sd-tab-label").forEach((label) => { + if (label instanceof HTMLElement) { + let data = create_key(label); + if (data) { + let [group, id, key] = data; + + // add click event listener + // @ts-ignore + label.onclick = onSDLabelClick; + + // store map of key to elements + if (!sd_id_to_elements[key]) { + sd_id_to_elements[key] = []; + } + sd_id_to_elements[key].push(label); + + if (groups.indexOf(group) === -1) { + groups.push(group); + // Check if a specific tab has been selected via URL parameter + const tabParam = new URLSearchParams(window.location.search).get( + group + ); + if (tabParam) { + console.log( + "sphinx-design: Selecting tab id for group '" + + group + + "' from URL parameter: " + + tabParam + ); + window.sessionStorage.setItem(storageKeyPrefix + group, tabParam); + } + } + + // Check is a specific tab has been selected previously + let previousId = window.sessionStorage.getItem( + storageKeyPrefix + group + ); + if (previousId === id) { + // console.log( + // "sphinx-design: Selecting tab from session storage: " + id + // ); + // @ts-ignore + label.previousElementSibling.checked = true; + } + } + } + }); +} + +/** + * Activate other tabs with the same sync id. + * + * @this {HTMLElement} - The element that was clicked. + */ +function onSDLabelClick() { + let data = create_key(this); + if (!data) return; + let [group, id, key] = data; + for (const label of sd_id_to_elements[key]) { + if (label === this) continue; + // @ts-ignore + label.previousElementSibling.checked = true; + } + window.sessionStorage.setItem(storageKeyPrefix + group, id); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/nightly_8.4/html/_sphinx_design_static/sphinx-design.min.css b/nightly_8.4/html/_sphinx_design_static/sphinx-design.min.css new file mode 100644 index 00000000000..860c36da0fa --- /dev/null +++ b/nightly_8.4/html/_sphinx_design_static/sphinx-design.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative;font-size:var(--sd-fontsize-dropdown)}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary.sd-summary-title{padding:.5em .6em .5em 1em;font-size:var(--sd-fontsize-dropdown-title);font-weight:var(--sd-fontweight-dropdown-title);user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;list-style:none;display:inline-flex;justify-content:space-between}details.sd-dropdown summary.sd-summary-title::-webkit-details-marker{display:none}details.sd-dropdown summary.sd-summary-title:focus{outline:none}details.sd-dropdown summary.sd-summary-title .sd-summary-icon{margin-right:.6em;display:inline-flex;align-items:center}details.sd-dropdown summary.sd-summary-title .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary.sd-summary-title .sd-summary-text{flex-grow:1;line-height:1.5;padding-right:.5rem}details.sd-dropdown summary.sd-summary-title .sd-summary-state-marker{pointer-events:none;display:inline-flex;align-items:center}details.sd-dropdown summary.sd-summary-title .sd-summary-state-marker svg{opacity:.6}details.sd-dropdown summary.sd-summary-title:hover .sd-summary-state-marker svg{opacity:1;transform:scale(1.1)}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown .sd-summary-chevron-right{transition:.25s}details.sd-dropdown[open]>.sd-summary-title .sd-summary-chevron-right{transform:rotate(90deg)}details.sd-dropdown[open]>.sd-summary-title .sd-summary-chevron-down{transform:rotate(180deg)}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-bg: rgba(0, 113, 188, 0.2);--sd-color-secondary-bg: rgba(108, 117, 125, 0.2);--sd-color-success-bg: rgba(40, 167, 69, 0.2);--sd-color-info-bg: rgba(23, 162, 184, 0.2);--sd-color-warning-bg: rgba(240, 179, 126, 0.2);--sd-color-danger-bg: rgba(220, 53, 69, 0.2);--sd-color-light-bg: rgba(248, 249, 250, 0.2);--sd-color-muted-bg: rgba(108, 117, 125, 0.2);--sd-color-dark-bg: rgba(33, 37, 41, 0.2);--sd-color-black-bg: rgba(0, 0, 0, 0.2);--sd-color-white-bg: rgba(255, 255, 255, 0.2);--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem;--sd-fontsize-dropdown: inherit;--sd-fontsize-dropdown-title: 1rem;--sd-fontweight-dropdown-title: 700} diff --git a/nightly_8.4/html/_static/_sphinx_javascript_frameworks_compat.js b/nightly_8.4/html/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 00000000000..81415803ec2 --- /dev/null +++ b/nightly_8.4/html/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,123 @@ +/* Compatability shim for jQuery and underscores.js. + * + * Copyright Sphinx contributors + * Released under the two clause BSD licence + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/nightly_8.4/html/_static/basic.css b/nightly_8.4/html/_static/basic.css new file mode 100644 index 00000000000..f316efcb47b --- /dev/null +++ b/nightly_8.4/html/_static/basic.css @@ -0,0 +1,925 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/nightly_8.4/html/_static/css/addons.css b/nightly_8.4/html/_static/css/addons.css new file mode 100644 index 00000000000..dec298db63f --- /dev/null +++ b/nightly_8.4/html/_static/css/addons.css @@ -0,0 +1,129 @@ +/* ---------------------------------------------------------------------------- + * THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. + * Copyright (C) NIWA & British Crown (Met Office) & Contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- */ + +/* (1) + * Correct the behaviour of nested admonitions. Sometimes the admonition-header + * inherits its parents styling. */ +.rst-content .error .admonition-title, .rst-content .danger .admonition-title { + background: red +} +.rst-content .warning .admonition-title, +.rst-content .caution .admonition-title, +.rst-content .attention .admonition-title { + background: orange +} + + +/* (2) + * Enable theme handling of pilcrow symbols for code-block captions and + * admonitions. */ +.rst-content p.admonition-title .pull-left.headerlink, +.rst-content div.code-block-caption .pull-left.headerlink { + margin-right:.3em +} +.rst-content p.admonition-title .pull-right.headerlink, +.rst-content div.code-block-caption .pull-right.headerlink { + margin-left:.3em +} +.rst-content p.admonition-title .headerlink:before, +.rst-content div.code-block-caption .headerlink:before { + font-family:"FontAwesome"; + display:inline-block; + font-style:normal; + font-weight:normal; + line-height:1; + text-decoration:inherit; + font-size:14px; + vertical-align:-15%; + -webkit-font-smoothing:antialiased +} +.rst-content p.admonition-title .headerlink:after, +.rst-content div.code-block-caption .headerlink:after { + visibility:visible; + content:""; + font-family:FontAwesome; + display:inline-block; + color:#2980B9 +} +.rst-content p.admonition-title:hover .headerlink, +.rst-content div.code-block-caption:hover .headerlink { + display:inline-block +} +.rst-content p.admonition-title .headerlink, +.rst-content div.code-block-caption .headerlink { + font:normal normal normal 14px/1 FontAwesome; + text-rendering:auto; + -webkit-font-smoothing:antialiased; + -moz-osx-font-smoothing:grayscale; + display:none; + visibility:hidden; + color:#fcfcfc; + text-decoration:inherit +} + + +/* (3) + * Add warning symbol before deprecated items. */ +.deprecated p:before { + font-family:FontAwesome; + content:"\f071 "; + color: rgb(200, 90, 70); +} +.deprecated p { + font-weight: bold; +} + + + +/* (4) + * Make version-modified more prominent. */ +span.versionmodified{ + font-weight: bold; +} + + +/* (5) + * Restyle code-block captions. */ +.code-block-caption { + font-style: italic; + color: #808080; +} +.code-block-caption span { + font-size: 1.2em; +} + + +/* (6) + * Fix the lack of space underneath lists inside admonitions. */ +.rst-content div.admonition ul, +.rst-content div.admonition ol > li { + padding-bottom: 0.5em; +} + + +/* (7) + * Improve sidebar scrolling */ +.wy-nav-size { + overflow-x: hidden!important; + overflow-y: hidden!important; +} + +/* Remove awkward margin for config reference "Path", "Type" etc. */ +.rst-content .cylc.conf .field-list { + margin-bottom: 0; +} diff --git a/nightly_8.4/html/_static/css/badge_only.css b/nightly_8.4/html/_static/css/badge_only.css new file mode 100644 index 00000000000..c718cee4418 --- /dev/null +++ b/nightly_8.4/html/_static/css/badge_only.css @@ -0,0 +1 @@ +.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} \ No newline at end of file diff --git a/nightly_8.4/html/_static/css/custom.css b/nightly_8.4/html/_static/css/custom.css new file mode 100644 index 00000000000..0610b4714fb --- /dev/null +++ b/nightly_8.4/html/_static/css/custom.css @@ -0,0 +1,21 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) NIWA & British Crown (Met Office) & Contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- */ + +/* Fix zero height auto size of svg */ +.logo { + height: 7em !important; +} diff --git a/nightly_8.4/html/_static/css/diff_selector.css b/nightly_8.4/html/_static/css/diff_selector.css new file mode 100644 index 00000000000..38cd2807a03 --- /dev/null +++ b/nightly_8.4/html/_static/css/diff_selector.css @@ -0,0 +1,36 @@ +/* ---------------------------------------------------------------------------- + * THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. + * Copyright (C) NIWA & British Crown (Met Office) & Contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- */ + +/* Block an element from being included in text selections. */ +.noselect { + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +/* Extension to Pygments to insert the "added" and "unchanged" characters in + * a "diff" code block using CSS so that they aren't included when copied as + * text. */ +.highlight-diff .gi:before { + content: '+'; +} +.highlight-diff .gn:before { + content: ' '; +} diff --git a/nightly_8.4/html/_static/css/fonts/Roboto-Slab-Bold.woff b/nightly_8.4/html/_static/css/fonts/Roboto-Slab-Bold.woff new file mode 100644 index 00000000000..6cb60000181 Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/Roboto-Slab-Bold.woff differ diff --git a/nightly_8.4/html/_static/css/fonts/Roboto-Slab-Bold.woff2 b/nightly_8.4/html/_static/css/fonts/Roboto-Slab-Bold.woff2 new file mode 100644 index 00000000000..7059e23142a Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/Roboto-Slab-Bold.woff2 differ diff --git a/nightly_8.4/html/_static/css/fonts/Roboto-Slab-Regular.woff b/nightly_8.4/html/_static/css/fonts/Roboto-Slab-Regular.woff new file mode 100644 index 00000000000..f815f63f99d Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/Roboto-Slab-Regular.woff differ diff --git a/nightly_8.4/html/_static/css/fonts/Roboto-Slab-Regular.woff2 b/nightly_8.4/html/_static/css/fonts/Roboto-Slab-Regular.woff2 new file mode 100644 index 00000000000..f2c76e5bda1 Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/Roboto-Slab-Regular.woff2 differ diff --git a/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.eot b/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.eot new file mode 100644 index 00000000000..e9f60ca953f Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.eot differ diff --git a/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.svg b/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.svg new file mode 100644 index 00000000000..855c845e538 --- /dev/null +++ b/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.ttf b/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.ttf new file mode 100644 index 00000000000..35acda2fa11 Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.ttf differ diff --git a/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.woff b/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.woff new file mode 100644 index 00000000000..400014a4b06 Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.woff differ diff --git a/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.woff2 b/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.woff2 new file mode 100644 index 00000000000..4d13fc60404 Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/fontawesome-webfont.woff2 differ diff --git a/nightly_8.4/html/_static/css/fonts/lato-bold-italic.woff b/nightly_8.4/html/_static/css/fonts/lato-bold-italic.woff new file mode 100644 index 00000000000..88ad05b9ff4 Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/lato-bold-italic.woff differ diff --git a/nightly_8.4/html/_static/css/fonts/lato-bold-italic.woff2 b/nightly_8.4/html/_static/css/fonts/lato-bold-italic.woff2 new file mode 100644 index 00000000000..c4e3d804b57 Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/lato-bold-italic.woff2 differ diff --git a/nightly_8.4/html/_static/css/fonts/lato-bold.woff b/nightly_8.4/html/_static/css/fonts/lato-bold.woff new file mode 100644 index 00000000000..c6dff51f063 Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/lato-bold.woff differ diff --git a/nightly_8.4/html/_static/css/fonts/lato-bold.woff2 b/nightly_8.4/html/_static/css/fonts/lato-bold.woff2 new file mode 100644 index 00000000000..bb195043cfc Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/lato-bold.woff2 differ diff --git a/nightly_8.4/html/_static/css/fonts/lato-normal-italic.woff b/nightly_8.4/html/_static/css/fonts/lato-normal-italic.woff new file mode 100644 index 00000000000..76114bc0336 Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/lato-normal-italic.woff differ diff --git a/nightly_8.4/html/_static/css/fonts/lato-normal-italic.woff2 b/nightly_8.4/html/_static/css/fonts/lato-normal-italic.woff2 new file mode 100644 index 00000000000..3404f37e2e3 Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/lato-normal-italic.woff2 differ diff --git a/nightly_8.4/html/_static/css/fonts/lato-normal.woff b/nightly_8.4/html/_static/css/fonts/lato-normal.woff new file mode 100644 index 00000000000..ae1307ff5f4 Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/lato-normal.woff differ diff --git a/nightly_8.4/html/_static/css/fonts/lato-normal.woff2 b/nightly_8.4/html/_static/css/fonts/lato-normal.woff2 new file mode 100644 index 00000000000..3bf9843328a Binary files /dev/null and b/nightly_8.4/html/_static/css/fonts/lato-normal.woff2 differ diff --git a/nightly_8.4/html/_static/css/grid_table.css b/nightly_8.4/html/_static/css/grid_table.css new file mode 100644 index 00000000000..53b63b3612d --- /dev/null +++ b/nightly_8.4/html/_static/css/grid_table.css @@ -0,0 +1,43 @@ +/* ---------------------------------------------------------------------------- + * THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. + * Copyright (C) NIWA & British Crown (Met Office) & Contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- */ + +/* Implement grid-table class for plain style grid layouts. */ +.grid-table { + width: 100% !important; + border: 0 !important; /* Remove table border. */ +} +.grid-table tbody tr td:first-child { + padding-left: 0 !important; /* Grid flush with the left-hand content edge. */ +} +.grid-table tbody tr td:last-child { + padding-right: 0 !important; /* Grid flush with the right-hand edge */ +} +.grid-table tbody tr td { + background-color: rgba(255,255,255,0) !important; + border: 0 !important; /* Remove cell border. */ + vertical-align: top !important; /* All content should float to the top. */ +} +.grid-table td { + /* docutils sticks tables inside an align-center class, correct this */ + text-align: left; +} + +/* Tables handle their own margin, this prevents getting a double margin. */ +.grid-table div.highlight { + margin-bottom: 0; +} diff --git a/nightly_8.4/html/_static/css/hieroglyph_theme_addons.css b/nightly_8.4/html/_static/css/hieroglyph_theme_addons.css new file mode 100644 index 00000000000..055353e558d --- /dev/null +++ b/nightly_8.4/html/_static/css/hieroglyph_theme_addons.css @@ -0,0 +1,38 @@ +/* (1) + * Make quotations small enough to fit on the slide. */ +.slide q { + font-size: 1em; +} + + +/* (2) + * Add a bit of space between slide titles and images. */ +.slide object, .slide img { + margin: 1em 0 1em 0; +} + + +/* (3) + * Don't display glossary terms as hyperlinks. */ +.slide a.reference { + text-decoration: none +} +.slide a.reference span.std { + text-decoration: underline; +} +.slide a.reference span.xref { + text-decoration: none; + color: #909090; + font-style: italic; +} +.slide a.reference span.xref:hover { + text-decoration: underline; + color: #0066CC; +} + + +/* (4) + * Make code block captions legible. */ +.slide .code-block-caption span { + font-size: 2em; +} diff --git a/nightly_8.4/html/_static/css/theme.css b/nightly_8.4/html/_static/css/theme.css new file mode 100644 index 00000000000..19a446a0e70 --- /dev/null +++ b/nightly_8.4/html/_static/css/theme.css @@ -0,0 +1,4 @@ +html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel,.rst-content .menuselection{font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .guilabel,.rst-content .menuselection{border:1px solid #7fbbe3;background:#e7f2fa}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} \ No newline at end of file diff --git a/nightly_8.4/html/_static/css/tutorial.css b/nightly_8.4/html/_static/css/tutorial.css new file mode 100644 index 00000000000..42330f4c6da --- /dev/null +++ b/nightly_8.4/html/_static/css/tutorial.css @@ -0,0 +1,3 @@ +.admonition.tutorial-ref .admonition-title:before { + content: ""; +} diff --git a/nightly_8.4/html/_static/cylc-favicon.ico b/nightly_8.4/html/_static/cylc-favicon.ico new file mode 100644 index 00000000000..b225083b917 Binary files /dev/null and b/nightly_8.4/html/_static/cylc-favicon.ico differ diff --git a/nightly_8.4/html/_static/cylc-logo-white.svg b/nightly_8.4/html/_static/cylc-logo-white.svg new file mode 100644 index 00000000000..8fc858c401e --- /dev/null +++ b/nightly_8.4/html/_static/cylc-logo-white.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/nightly_8.4/html/_static/design-tabs.js b/nightly_8.4/html/_static/design-tabs.js new file mode 100644 index 00000000000..b25bd6a4fa1 --- /dev/null +++ b/nightly_8.4/html/_static/design-tabs.js @@ -0,0 +1,101 @@ +// @ts-check + +// Extra JS capability for selected tabs to be synced +// The selection is stored in local storage so that it persists across page loads. + +/** + * @type {Record} + */ +let sd_id_to_elements = {}; +const storageKeyPrefix = "sphinx-design-tab-id-"; + +/** + * Create a key for a tab element. + * @param {HTMLElement} el - The tab element. + * @returns {[string, string, string] | null} - The key. + * + */ +function create_key(el) { + let syncId = el.getAttribute("data-sync-id"); + let syncGroup = el.getAttribute("data-sync-group"); + if (!syncId || !syncGroup) return null; + return [syncGroup, syncId, syncGroup + "--" + syncId]; +} + +/** + * Initialize the tab selection. + * + */ +function ready() { + // Find all tabs with sync data + + /** @type {string[]} */ + let groups = []; + + document.querySelectorAll(".sd-tab-label").forEach((label) => { + if (label instanceof HTMLElement) { + let data = create_key(label); + if (data) { + let [group, id, key] = data; + + // add click event listener + // @ts-ignore + label.onclick = onSDLabelClick; + + // store map of key to elements + if (!sd_id_to_elements[key]) { + sd_id_to_elements[key] = []; + } + sd_id_to_elements[key].push(label); + + if (groups.indexOf(group) === -1) { + groups.push(group); + // Check if a specific tab has been selected via URL parameter + const tabParam = new URLSearchParams(window.location.search).get( + group + ); + if (tabParam) { + console.log( + "sphinx-design: Selecting tab id for group '" + + group + + "' from URL parameter: " + + tabParam + ); + window.sessionStorage.setItem(storageKeyPrefix + group, tabParam); + } + } + + // Check is a specific tab has been selected previously + let previousId = window.sessionStorage.getItem( + storageKeyPrefix + group + ); + if (previousId === id) { + // console.log( + // "sphinx-design: Selecting tab from session storage: " + id + // ); + // @ts-ignore + label.previousElementSibling.checked = true; + } + } + } + }); +} + +/** + * Activate other tabs with the same sync id. + * + * @this {HTMLElement} - The element that was clicked. + */ +function onSDLabelClick() { + let data = create_key(this); + if (!data) return; + let [group, id, key] = data; + for (const label of sd_id_to_elements[key]) { + if (label === this) continue; + // @ts-ignore + label.previousElementSibling.checked = true; + } + window.sessionStorage.setItem(storageKeyPrefix + group, id); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/nightly_8.4/html/_static/doctools.js b/nightly_8.4/html/_static/doctools.js new file mode 100644 index 00000000000..4d67807d17d --- /dev/null +++ b/nightly_8.4/html/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/nightly_8.4/html/_static/documentation_options.js b/nightly_8.4/html/_static/documentation_options.js new file mode 100644 index 00000000000..0ef129074c4 --- /dev/null +++ b/nightly_8.4/html/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '8.4.0.dev', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/nightly_8.4/html/_static/file.png b/nightly_8.4/html/_static/file.png new file mode 100644 index 00000000000..a858a410e4f Binary files /dev/null and b/nightly_8.4/html/_static/file.png differ diff --git a/nightly_8.4/html/_static/graphviz.css b/nightly_8.4/html/_static/graphviz.css new file mode 100644 index 00000000000..027576e34d2 --- /dev/null +++ b/nightly_8.4/html/_static/graphviz.css @@ -0,0 +1,19 @@ +/* + * graphviz.css + * ~~~~~~~~~~~~ + * + * Sphinx stylesheet -- graphviz extension. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +img.graphviz { + border: 0; + max-width: 100%; +} + +object.graphviz { + max-width: 100%; +} diff --git a/nightly_8.4/html/_static/jquery.js b/nightly_8.4/html/_static/jquery.js new file mode 100644 index 00000000000..c4c6022f298 --- /dev/null +++ b/nightly_8.4/html/_static/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="

",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0. + * ------------------------------------------------------------------------- */ + +/* (2) + * Make admonitions linkable. */ +$(document).ready(function() { + var id; + $('p.admonition-title').each(function(itt, element) { + id = 'admonition-' + itt; + $(element).attr({'id': id}); + $(element).append($('') + .attr({'href': '#' + id}) + .addClass('headerlink') + .append('¶') + ); + }); +}); diff --git a/nightly_8.4/html/_static/js/badge_only.js b/nightly_8.4/html/_static/js/badge_only.js new file mode 100644 index 00000000000..526d7234b65 --- /dev/null +++ b/nightly_8.4/html/_static/js/badge_only.js @@ -0,0 +1 @@ +!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}({4:function(e,t,r){}}); \ No newline at end of file diff --git a/nightly_8.4/html/_static/js/diff_selector.js b/nightly_8.4/html/_static/js/diff_selector.js new file mode 100644 index 00000000000..183d98b6ae1 --- /dev/null +++ b/nightly_8.4/html/_static/js/diff_selector.js @@ -0,0 +1,122 @@ +/* ---------------------------------------------------------------------------- + * THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. + * Copyright (C) NIWA & British Crown (Met Office) & Contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- */ + +/* Return a list of matches for the provided string, see also String.indexOf. */ +String.prototype.indicesOf = function (sub) { + var str = String(this); + var index = str.indexOf(sub); + var count = 0; + var ret = []; + while (index != -1) { + str = str.substr(index + 1); + ret.push(index + count); + count += index + 1; + index = str.indexOf(sub); + } + return ret; +} + + +/* Split a text node on the newline character, see also Text.splitText. */ +Text.prototype.splitLines = function () { + var indices = $(this).text().indicesOf('\n'); + if (indices && indices[0] == 0) { + // ignore leading new line characters + indices.shift(); + } + if (indices.length < 1) { + // no line breaks - skip + return []; + } + var node = this; + var offset = 0; + for (let index of indices) { + node = node.splitText(index - offset); + offset = index; + } +} + +/* Remove the leading (+| ) character from each line of a diff block and + * re-insert them with CSS so that they are not included in the copy selection. + * + * Add the ".noselect" class to lines prefixed (-) to make them disappear from + * copied text. */ +$(document).ready(function() { + $('div.highlight-diff pre').each(function () { + // Unformatted text is represented as text nodes which don't fit into + // the DOM in the way regular HTML elements do so we cannot iterate + // over .children() but must use childNodes instead. + for (let node of this.childNodes) { + if (node.nodeName == '#text') { // "unchanged" line. + // Split multi-line text nodes into separate lines so we can + // remove the leading whitespace. + node.splitLines(); + } else { + text = $(node).html().substr(1); + if ($(node).hasClass('gi')) { // "added" line. + // Remove leading character. + $(node).html($(node).html().substr(1)); + } else if ($(node).hasClass('gd')) { // "removed" line. + // Make un-selectable. + $(node).addClass('noselect'); + } + } + } + }); + + // Iterate again to remove the leading whitespace from unchanged lines. + var node, text, newnode; + $('div.highlight-diff pre').each(function () { + node = this.childNodes[0]; + while (node) { + // Skip nodes if they just contain whitespace (including new + // line characters). + if (node.nodeName == '#text' && $(node).text().trim()) { + text = $(node).text(); + if (text[0] == '\n') { + // Move leading new lines onto the end of the string. + text = text.substr(1); + node = node.splitText(1); + } + if (text[0] == ' ') { + // Remove leading whitespace, this will be provided via + // CSS. + text = text.substr(1); + } + + // Create a new span to represent this text node. Apply the 'gn' + // class which will provide leading whitespace. + $('') + .append(text) + .addClass('gn') + .insertBefore(node); + + // Move on to the next node and remove the current text node. + newnode = node.nextSibling; + $(node).remove(); + node = newnode; + } else { + // To avoid iterating over any nodes we are adding (infinite loop) + // we use node.nextSibling to get the next node and insert any + // new nodes before the current one. + node = node.nextSibling; + } + } + }); + +}); diff --git a/nightly_8.4/html/_static/js/html5shiv-printshiv.min.js b/nightly_8.4/html/_static/js/html5shiv-printshiv.min.js new file mode 100644 index 00000000000..2b43bd062e9 --- /dev/null +++ b/nightly_8.4/html/_static/js/html5shiv-printshiv.min.js @@ -0,0 +1,4 @@ +/** +* @preserve HTML5 Shiv 3.7.3-pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed +*/ +!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=y.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=y.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),y.elements=c+" "+a,j(b)}function f(a){var b=x[a[v]];return b||(b={},w++,a[v]=w,x[w]=b),b}function g(a,c,d){if(c||(c=b),q)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():u.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||t.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),q)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return y.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(y,b.frag)}function j(a){a||(a=b);var d=f(a);return!y.shivCSS||p||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),q||i(a,d),a}function k(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(l(b)));return g}function l(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(A+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function m(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+A+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function n(a){for(var b=a.length;b--;)a[b].removeNode()}function o(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,e,g=f(a),h=a.namespaces,i=a.parentWindow;return!B||a.printShived?a:("undefined"==typeof h[A]&&h.add(A),i.attachEvent("onbeforeprint",function(){b();for(var f,g,h,i=a.styleSheets,j=[],l=i.length,n=Array(l);l--;)n[l]=i[l];for(;h=n.pop();)if(!h.disabled&&z.test(h.media)){try{f=h.imports,g=f.length}catch(o){g=0}for(l=0;g>l;l++)n.push(f[l]);try{j.push(h.cssText)}catch(o){}}j=m(j.reverse().join("")),e=k(a),d=c(a,j)}),i.attachEvent("onafterprint",function(){n(e),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var p,q,r="3.7.3",s=a.html5||{},t=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,u=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="",p="hidden"in a,q=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){p=!0,q=!0}}();var y={elements:s.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:r,shivCSS:s.shivCSS!==!1,supportsUnknownElements:q,shivMethods:s.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=y,j(b);var z=/^$|\b(?:all|print)\b/,A="html5shiv",B=!q&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();y.type+=" print",y.shivPrint=o,o(b),"object"==typeof module&&module.exports&&(module.exports=y)}("undefined"!=typeof window?window:this,document); \ No newline at end of file diff --git a/nightly_8.4/html/_static/js/html5shiv.min.js b/nightly_8.4/html/_static/js/html5shiv.min.js new file mode 100644 index 00000000000..cd1c674f5e3 --- /dev/null +++ b/nightly_8.4/html/_static/js/html5shiv.min.js @@ -0,0 +1,4 @@ +/** +* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed +*/ +!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3-pre",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); \ No newline at end of file diff --git a/nightly_8.4/html/_static/js/minicylc.js b/nightly_8.4/html/_static/js/minicylc.js new file mode 100644 index 00000000000..d6f2fa90ced --- /dev/null +++ b/nightly_8.4/html/_static/js/minicylc.js @@ -0,0 +1,354 @@ +/* ---------------------------------------------------------------------------- + * THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. + * Copyright (C) NIWA & British Crown (Met Office) & Contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- */ + +/*eslint no-console: off*/ + +// Default Cylc colour theme. +var minicylc_default_theme = { + 'waiting_fill': 'none', + 'waiting_stroke': 'black', + 'running_fill': '#55c3e5ff', + 'running_stroke': 'black', + 'succeed_fill': '#64c77eff', + 'succeed_stroke': 'black' +} + +// Old Cylc 7 theme. +var minicylc_cylc7_theme = { + 'waiting_fill': 'none', + 'waiting_stroke': '#88c6ff', + 'running_fill': '#00c410', + 'running_stroke': 'black', + 'succeed_fill': '#ada5a5', + 'succeed_stroke': 'black' +} + +// Demo colour theme for demmonstrating workflow logic. +var minicylc_demo_theme = { + 'succeed_fill': '#aabbff', + 'succeed_stroke': 'black' +} + + +class MiniCylc { + /** + * Class for animating SVG graphs. + * + * Attributes: + * - nodes: A dictionary of task names against a list of SVG nodes. + * - edges: A dictionary of task edges against a list SVG nodes. + * - dependencies: A dictionary of task names against a list of + * conditional expressions. + */ + + constructor(div) { + /** + * Initiate the object. + * @param div The
element containing the SVG. + * */ + this.div = div; + this.load(); + } + + load() { + /** + * Obtain nodes and edges from svg. + * + * This function calls itself recursively until the SVG is loaded. + * + * This function starts the animation when finished. + */ + const svg = ($(this.div).find('object:first')[0]).contentDocument; + const self = this; + + if (!svg) { + console.log('Wait for SVG load: Gecko'); + // this retry loop works for Firefox, etc + setTimeout(function() { + self.load(); + }, 500) + return; + } + var eles = $(svg).find('g'); + if (!eles.length) { + console.log('Wait for SVG load: Blink'); + // this retry loop works for Chrome, etc + setTimeout(function() { + self.load(); + }, 500) + return; + } + + this._find_svg_elements(svg); + + // Parse dependencies. + var deps = this._get_dependencies_from_graph(this.div); + this._construct_dependency_map(deps); + + // Process colour theme. + this.setup_colours($(this.div).data('theme')); + + this.run() + } + + setup_colours(theme) { + /** + * Set the colour theme. + * @param theme The name of a colour theme as a string. + */ + if (!theme || theme == 'default') { + this.theme = minicylc_default_theme; + } else if (theme == 'demo') { + this.theme = minicylc_demo_theme; + } else if (theme == 'cylc7') { + this.theme = minicylc_cylc7_theme; + } else { + console.log('Warning: Invalid theme detected "' + theme + + '", defaulting to black.'); + this.theme = {}; + } + } + + _find_svg_elements(svg) { + /** + * Associate task/dependency names with SVG nodes. + * + * Associations stored as dictionaries this.nodes and this.edges. + * @param svg The element containing the workflow. + */ + var nodes = {}; + var edges = {}; + $(svg).find('g').each(function() { + var node = $(this)[0]; + var node_class = $(node).attr('class'); + if (node_class == 'node') { + nodes[node.textContent.trim().split('\n')[0]] = node; + } else if (node_class == 'edge') { + edges[node.textContent.trim().split('\n')[0]] = node; + } + }); + this.nodes = nodes; + this.edges = edges; + } + + _get_dependencies_from_graph(div) { + /** + * Extract, parse and return a list of dependencies. + * @param div The minicylc
element. + * @return A list of [left, right] lists e.g. ['a & b', 'c']. + */ + var deps = []; + var ind = 0; + var parts; + for (let dep of $(div).data('dependencies').split('//')) { + parts = dep.split('=>'); + if (parts.length == 0) { + continue; // Graph line does not contain a dependency => skip. + } + for(ind = 0; ind < parts.length-1; ind++) { + deps.push([parts[ind].trim(), parts[ind + 1].trim()]); // [left, right]. + } + } + + return deps; + } + + _construct_dependency_map(deps) { + /** + * Associate tasks with conditional expressions. + * + * Associations stored as a dictionary - this.dependencies. + * @param deps A list of dependencies in the form [[left, right], ...]. + */ + var condition; + var conditional_regex = /[()&]/; + var conditional_regex2 = /([()&|])/; + var conditional_chars = ['(', ')', '|', '&']; + this.dependencies = {}; + for (let dep of deps) { + // Build a javascript parsable conditional statement. + condition = []; + for (let left of dep[0].split(conditional_regex2)) { + left = left.trim(); + if (left) { + if (!conditional_chars.includes(left)) { + // All dependencies are :succeed by default, + // dependencies are checked using + // this.succeed.has(task). + condition.push('this.succeed.has("' + left + '")'); + } else { + // conditional character. + condition.push(left); + } + } + } + condition = condition.join(' '); + + // Associate conditional statements with tasks. + for (let right of dep[1].split(conditional_regex)) { + right = right.trim(); + if (!this.dependencies[right]) { + this.dependencies[right] = []; + } + this.dependencies[right].push(condition); + } + } + } + + evaluate_dependencies(task) { + /** + * Check if a task's dependencies are satisfied. + * @param task The name of the task to evaluate. + * @return true if satisfied else false. + */ + var deps = this.dependencies[task]; + if (!deps) { + return true; + } + for (let dep of deps) { + if (eval(dep) == 0) { + return false; + } + } + return true; + } + + _style_node(node, fill, stroke) { + /** + * Style a graphviz node. + * @param fill The fill colour for SVG e.g. 'none', '#aabbcc', 'black'. + * @param stroke The stroke colour for SVG. + */ + if (!fill) { + fill = 'none'; // Default to an unfilled node. + } + if (!stroke) { + stroke = 'black'; // Default to a black border. + } + // Style nodes. + $($(this.nodes[node]).find('ellipse:first')).attr({ + 'fill': fill, + 'stroke': stroke + }); + } + + _style() { + /** + * Refresh the style of graph nodes based on their state. + */ + for (let task of this.waiting) { + this._style_node(task, + this.theme['waiting_fill'], + this.theme['waiting_stroke']); + } + for (let task of this.running) { + this._style_node(task, + this.theme['running_fill'], + this.theme['running_stroke']); + } + for (let task of this.succeed) { + this._style_node(task, + this.theme['succeed_fill'], + this.theme['succeed_stroke']); + } + } + + _init() { + /** + * Initiate the simulation / animation. + */ + this.waiting = new Set(); + this.running = new Set(); + this.succeed = new Set(); + for (let task in this.nodes) { + this.waiting.add(task); + } + this._style(); + } + + _advance() { + /* + * To be called with each main loop. + * @return true if the task pool has changed else false. + */ + var changed = false; + for (let task of this.running) { + this.running.delete(task); + this.succeed.add(task); + changed = true; + } + for (let task of this.waiting) { + if (this.evaluate_dependencies(task)) { + this.waiting.delete(task); + this.running.add(task); + changed = true; + } + } + return changed; + } + + _main_loop(itt) { + /* + * The main loop - runs the simulation and handles restyling of nodes. + * Note function calls itself recursively. + */ + var exit = false; + + // Action. + if (this._advance()) { // Advance the task pool. + // If anything has changed restyle. + this._style(); + } else { + // If nothing has changed... + if (this.waiting.size == 0 && this.running.size == 0) { + // The simulation has ended, reset and restart. + this._init(); + } else { + // The worklfow stalled, log a console message and do nothing. + exit = true; + console.log('Workflow stalled :('); + } + } + + // Callback. + if (!exit) { + var self_ref = this; + setTimeout(function(){ + self_ref._main_loop(itt + 1); + }, 3000); + } + } + + run() { + /* + * Run this simulation. + */ + this._init(); + this._main_loop(0); + } + +} + + +// Activate minicylc. +$(document).ready(function() { + $('.minicylc').each(function() { + var obj = this; + new MiniCylc(obj); + }); +}); diff --git a/nightly_8.4/html/_static/js/spoiler.js b/nightly_8.4/html/_static/js/spoiler.js new file mode 100644 index 00000000000..55c3715010d --- /dev/null +++ b/nightly_8.4/html/_static/js/spoiler.js @@ -0,0 +1,67 @@ +/* ---------------------------------------------------------------------------- + * THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. + * Copyright (C) NIWA & British Crown (Met Office) & Contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- */ + +/* This file implements spoiler sections which are hidden by default. */ + +// sphinx_admonition_class: bootstrap_button_class +const sphinx_admonition_classes = { + 'attention': 'warning', + 'caution': 'warning', + 'error': 'danger', + 'hint': 'success', + 'important': 'success', + 'note': 'info', + 'tip': 'success', + 'warning': 'warning', + 'danger': 'danger' +} + +$(document).ready(function() { + var button_class; + var spoilers = $('.spoiler'); + for (let spoiler of spoilers) { + // Hide content. + $(spoiler).children().hide(); + $(spoiler).find('.admonition-title').show(); + + // Determine button class. + button_class = 'default'; + for (let css_class of $(spoiler).attr('class').split(' ')) { + if (css_class in sphinx_admonition_classes) { + button_class = sphinx_admonition_classes[css_class]; + break; + } + } + + // Add button + $(spoiler).append( + $(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/nightly_8.4/html/_static/minus.png b/nightly_8.4/html/_static/minus.png new file mode 100644 index 00000000000..d96755fdaf8 Binary files /dev/null and b/nightly_8.4/html/_static/minus.png differ diff --git a/nightly_8.4/html/_static/plus.png b/nightly_8.4/html/_static/plus.png new file mode 100644 index 00000000000..7107cec93a9 Binary files /dev/null and b/nightly_8.4/html/_static/plus.png differ diff --git a/nightly_8.4/html/_static/pygments.css b/nightly_8.4/html/_static/pygments.css new file mode 100644 index 00000000000..650b5270075 --- /dev/null +++ b/nightly_8.4/html/_static/pygments.css @@ -0,0 +1,72 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #ffffff; } +.highlight .c { color: #aaaaaa; font-style: italic } /* Comment */ +.highlight .err { color: #FF0000; background-color: #FFAAAA } /* Error */ +.highlight .k { color: #0000aa } /* Keyword */ +.highlight .ch { color: #aaaaaa; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #aaaaaa; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #4c8317 } /* Comment.Preproc */ +.highlight .cpf { color: #aaaaaa; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #aaaaaa; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #0000aa; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #aa0000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +.highlight .gr { color: #aa0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00aa00 } /* Generic.Inserted */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #555555 } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #aa0000 } /* Generic.Traceback */ +.highlight .kc { color: #0000aa } /* Keyword.Constant */ +.highlight .kd { color: #0000aa } /* Keyword.Declaration */ +.highlight .kn { color: #0000aa } /* Keyword.Namespace */ +.highlight .kp { color: #0000aa } /* Keyword.Pseudo */ +.highlight .kr { color: #0000aa } /* Keyword.Reserved */ +.highlight .kt { color: #00aaaa } /* Keyword.Type */ +.highlight .m { color: #009999 } /* Literal.Number */ +.highlight .s { color: #aa5500 } /* Literal.String */ +.highlight .na { color: #1e90ff } /* Name.Attribute */ +.highlight .nb { color: #00aaaa } /* Name.Builtin */ +.highlight .nc { color: #00aa00; text-decoration: underline } /* Name.Class */ +.highlight .no { color: #aa0000 } /* Name.Constant */ +.highlight .nd { color: #888888 } /* Name.Decorator */ +.highlight .ni { color: #880000; font-weight: bold } /* Name.Entity */ +.highlight .nf { color: #00aa00 } /* Name.Function */ +.highlight .nn { color: #00aaaa; text-decoration: underline } /* Name.Namespace */ +.highlight .nt { color: #1e90ff; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #aa0000 } /* Name.Variable */ +.highlight .ow { color: #0000aa } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mb { color: #009999 } /* Literal.Number.Bin */ +.highlight .mf { color: #009999 } /* Literal.Number.Float */ +.highlight .mh { color: #009999 } /* Literal.Number.Hex */ +.highlight .mi { color: #009999 } /* Literal.Number.Integer */ +.highlight .mo { color: #009999 } /* Literal.Number.Oct */ +.highlight .sa { color: #aa5500 } /* Literal.String.Affix */ +.highlight .sb { color: #aa5500 } /* Literal.String.Backtick */ +.highlight .sc { color: #aa5500 } /* Literal.String.Char */ +.highlight .dl { color: #aa5500 } /* Literal.String.Delimiter */ +.highlight .sd { color: #aa5500 } /* Literal.String.Doc */ +.highlight .s2 { color: #aa5500 } /* Literal.String.Double */ +.highlight .se { color: #aa5500 } /* Literal.String.Escape */ +.highlight .sh { color: #aa5500 } /* Literal.String.Heredoc */ +.highlight .si { color: #aa5500 } /* Literal.String.Interpol */ +.highlight .sx { color: #aa5500 } /* Literal.String.Other */ +.highlight .sr { color: #009999 } /* Literal.String.Regex */ +.highlight .s1 { color: #aa5500 } /* Literal.String.Single */ +.highlight .ss { color: #0000aa } /* Literal.String.Symbol */ +.highlight .bp { color: #00aaaa } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #00aa00 } /* Name.Function.Magic */ +.highlight .vc { color: #aa0000 } /* Name.Variable.Class */ +.highlight .vg { color: #aa0000 } /* Name.Variable.Global */ +.highlight .vi { color: #aa0000 } /* Name.Variable.Instance */ +.highlight .vm { color: #aa0000 } /* Name.Variable.Magic */ +.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/nightly_8.4/html/_static/searchtools.js b/nightly_8.4/html/_static/searchtools.js new file mode 100644 index 00000000000..92da3f8b22c --- /dev/null +++ b/nightly_8.4/html/_static/searchtools.js @@ -0,0 +1,619 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + } + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms, anchor) + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + "Search finished, found ${resultCount} page(s) matching the search query." + ).replace('${resultCount}', resultCount); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; +// Helper function used by query() to order search results. +// Each input is an array of [docname, title, anchor, descr, score, filename]. +// Order the results by score (in opposite order of appearance, since the +// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. +const _orderResultsByScoreThenName = (a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString, anchor) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + for (const removalQuery of [".headerlinks", "script", "style"]) { + htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() }); + } + if (anchor) { + const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`); + if (anchorContent) return anchorContent.textContent; + + console.warn( + `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.` + ); + } + + // if anchor not specified or not found, fall back to main content + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent) return docContent.textContent; + + console.warn( + "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + _parseQuery: (query) => { + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // Collect multiple result groups to be sorted separately and then ordered. + // Each is an array of [docname, title, anchor, descr, score, filename]. + const normalResults = []; + const nonMainIndexResults = []; + + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase().trim(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + let score = Math.round(100 * queryLower.length / title.length) + normalResults.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id, isMain] of foundEntries) { + const score = Math.round(100 * queryLower.length / entry.length); + const result = [ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]; + if (isMain) { + normalResults.push(result); + } else { + nonMainIndexResults.push(result); + } + } + } + } + + // lookup as object + objectTerms.forEach((term) => + normalResults.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) { + normalResults.forEach((item) => (item[4] = Scorer.score(item))); + nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); + } + + // Sort each group of results by score and then alphabetically by name. + normalResults.sort(_orderResultsByScoreThenName); + nonMainIndexResults.sort(_orderResultsByScoreThenName); + + // Combine the result groups in (reverse) order. + // Non-main index entries are typically arbitrary cross-references, + // so display them after other results. + let results = [...nonMainIndexResults, ...normalResults]; + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + return results.reverse(); + }, + + query: (query) => { + const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query); + const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + if (!terms.hasOwnProperty(word)) { + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + } + if (!titleTerms.hasOwnProperty(word)) { + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); + }); + } + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (!fileMap.has(file)) fileMap.set(file, [word]); + else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords, anchor) => { + const text = Search.htmlToText(htmlText, anchor); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/nightly_8.4/html/_static/sphinx-design.min.css b/nightly_8.4/html/_static/sphinx-design.min.css new file mode 100644 index 00000000000..860c36da0fa --- /dev/null +++ b/nightly_8.4/html/_static/sphinx-design.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative;font-size:var(--sd-fontsize-dropdown)}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary.sd-summary-title{padding:.5em .6em .5em 1em;font-size:var(--sd-fontsize-dropdown-title);font-weight:var(--sd-fontweight-dropdown-title);user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;list-style:none;display:inline-flex;justify-content:space-between}details.sd-dropdown summary.sd-summary-title::-webkit-details-marker{display:none}details.sd-dropdown summary.sd-summary-title:focus{outline:none}details.sd-dropdown summary.sd-summary-title .sd-summary-icon{margin-right:.6em;display:inline-flex;align-items:center}details.sd-dropdown summary.sd-summary-title .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary.sd-summary-title .sd-summary-text{flex-grow:1;line-height:1.5;padding-right:.5rem}details.sd-dropdown summary.sd-summary-title .sd-summary-state-marker{pointer-events:none;display:inline-flex;align-items:center}details.sd-dropdown summary.sd-summary-title .sd-summary-state-marker svg{opacity:.6}details.sd-dropdown summary.sd-summary-title:hover .sd-summary-state-marker svg{opacity:1;transform:scale(1.1)}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown .sd-summary-chevron-right{transition:.25s}details.sd-dropdown[open]>.sd-summary-title .sd-summary-chevron-right{transform:rotate(90deg)}details.sd-dropdown[open]>.sd-summary-title .sd-summary-chevron-down{transform:rotate(180deg)}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-bg: rgba(0, 113, 188, 0.2);--sd-color-secondary-bg: rgba(108, 117, 125, 0.2);--sd-color-success-bg: rgba(40, 167, 69, 0.2);--sd-color-info-bg: rgba(23, 162, 184, 0.2);--sd-color-warning-bg: rgba(240, 179, 126, 0.2);--sd-color-danger-bg: rgba(220, 53, 69, 0.2);--sd-color-light-bg: rgba(248, 249, 250, 0.2);--sd-color-muted-bg: rgba(108, 117, 125, 0.2);--sd-color-dark-bg: rgba(33, 37, 41, 0.2);--sd-color-black-bg: rgba(0, 0, 0, 0.2);--sd-color-white-bg: rgba(255, 255, 255, 0.2);--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem;--sd-fontsize-dropdown: inherit;--sd-fontsize-dropdown-title: 1rem;--sd-fontweight-dropdown-title: 700} diff --git a/nightly_8.4/html/_static/sphinx_highlight.js b/nightly_8.4/html/_static/sphinx_highlight.js new file mode 100644 index 00000000000..8a96c69a194 --- /dev/null +++ b/nightly_8.4/html/_static/sphinx_highlight.js @@ -0,0 +1,154 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore( + span, + parent.insertBefore( + rest, + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/nightly_8.4/html/genindex.html b/nightly_8.4/html/genindex.html new file mode 100644 index 00000000000..2d84dbec241 --- /dev/null +++ b/nightly_8.4/html/genindex.html @@ -0,0 +1,1178 @@ + + + + + + Index — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + +

Index

+ +
+ A + | B + | C + | D + | E + | F + | G + | H + | I + | J + | K + | L + | M + | N + | O + | P + | Q + | R + | S + | T + | U + | V + | W + | X + +
+

A

+ + + +
+ +

B

+ + +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

E

+ + + +
+ +

F

+ + + +
+ +

G

+ + + +
+ +

H

+ + + +
+ +

I

+ + + +
+ +

J

+ + + +
+ +

K

+ + +
+ +

L

+ + + +
+ +

M

+ + +
+ +

N

+ + + +
+ +

O

+ + + +
+ +

P

+ + + +
+ +

Q

+ + + +
+ +

R

+ + + +
+ +

S

+ + + +
+ +

T

+ + + +
+ +

U

+ + + +
+ +

V

+ + + +
+ +

W

+ + + +
+ +

X

+ + + +
+ + + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/glossary.html b/nightly_8.4/html/glossary.html new file mode 100644 index 00000000000..f5719d84e31 --- /dev/null +++ b/nightly_8.4/html/glossary.html @@ -0,0 +1,1649 @@ + + + + + + + Glossary — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Glossary

+
+
active
active task

An active task is a task which is near ready to run, in the process of +running, or which requires user intervention. These are all the tasks +being actively managed by the scheduler at this point in the run.

+

Active tasks are:

+
    +
  • Tasks which have some, but not all of their +prerequisites satisfied.

  • +
  • waiting tasks, that are actively waiting on:

    + +
  • +
  • preparing tasks - i.e. tasks in the process of submitting jobs

  • +
  • submitted and running tasks - i.e. those with active jobs

  • +
  • tasks that reached a final status without completing their +required outputs +(e.g. a task failed where success was required).

  • +
+

Active tasks are in the n=0 window which means they +will always be displayed in the GUI and Tui.

+

The distinction between active and non-active tasks is important for +the computing of the runahead limit.

+
+
active cycle

A cycle point is active if it contains any active tasks.

+

Active cycles are counted towards the runahead limit.

+
+
artificial dependency

An artificial dependency in the graph does not reflect +real dependence between the tasks involved. This can sometimes be +useful but should be avoided if possible. Artificial dependencies muddy +the real dependencies of the workflow and they may unnecessarily +constrain the scheduler.

+

In the following cycling workflow, if the task foo does not +actually depend on any real outputs of baz in the previous cycle, +then the intercycle dependence is artificial.

+
P1 = """
+   foo => bar => baz
+   baz[-P1] => foo
+"""
+
+
+
+
branching
graph branching

Cylc handles workflow graphs in an event-driven way. +It can automatically follow different paths depending on events at +runtime. This relies on optional outputs and is +called branching.

+

For example, the following workflow follows one of two possible paths +depending on the outcome of task b:

+
# the success branch
+a => b? => c
+# the fail branch
+b:fail? => r
+# joining the two branches together
+c | r => d
+
+
+
+

digraph example { +subgraph cluster_success { + label = ":succeed" + color = "green" + fontcolor = "green" + style = "dashed" + + c +} + +subgraph cluster_failure { + label = ":fail" + color = "red" + fontcolor = "red" + style = "dashed" + + r +} + +a -> b -> c -> d +b -> r -> d +}

+
+
+

See also

+ +
+
+
clock expire
expired task

Tasks in datetime cycling workflows can be configured to expire +if the wallclock time exceeds some offset from the cycle point.

+

Expired is a final status - an expired task will not run +even if its prerequisites get satisfied.

+

The associated :expire output can be used to +trigger other tasks. It must be marked as an optional output, +i.e. expiry cannot be required.

+
+

See also

+ +
+
+
clock trigger

Clock triggers connect cycle points to the wallclock time, in +datetime cycling workflows. Tasks that depend on a clock trigger +will not trigger until the wallclock time is equal to their cycle point +plus or minus some offset.

+
+

See also

+ +
+
+
cold start

A cold start is when the scheduler starts a +workflow at the beginning of graph. In a cycling +workflow this is determined by the initial cycle point.

+

This is the default behaviour of cylc play for an installed workflow +that hasn’t run yet.

+

To satisfy unbounded intercycle dependence in the graph, tasks +prior to the initial cycle point are treated as if they have succeeded.

+ +
+
conditional dependence
conditional dependency
conditional trigger

Conditional dependence is when a task depends on a +combination of multiple upstream task outputs.

+
a & (b:fail | c) => d
+
+
+

The left hand side of a conditional dependency can be called a +conditional trigger.

+
+
contact file

The contact file, in the service directory, records information +about a running scheduler such as host, TCP port, and process ID. +It is read by Cylc client commands so they can target the right scheduler.

+

The contact file is created at scheduler startup and removed on clean +shutdown. If you delete it, the scheduler will (after a delay) notice +this and shut down.

+
<run-directory>/.service/contact
+
+
+
+

Warning

+

If the scheduler dies in an uncontrolled way, for example if the +process is killed or the host goes down, the contact file may be +left behind. Some Cylc commands automatically detect these files +and remove them, otherwise they should be manually removed.

+
+
+
custom output

A custom task output is a user-defined task output that marks +an event runtime event between task job start and finish. To +complete a custom output, the job must send a message defined in the +flow.cylc file to the scheduler.

+

Triggers based on custom outputs are called message triggers.

+
[runtime]
+    [[foo]]
+        [[[outputs]]]
+            # output name = output message
+            out1 = "Output 1 completed"
+            out2 = "Output 2 completed"
+
+
+ +
+
cycle

In a cycling workflow, cycles are repetitions of a graph +string. Each cycle is identified by a cycle point. The sequence +of cycle points is defined by the graph string’s recurrence +pattern.

+

This defines the structure of the graph. At runtime, however, +Cylc does not impose a global loop over cycles. Each individual task, +with its own cycle point, advances according to its own +dependencies.

+

For example, in the following workflow each dotted box represents a cycle +and the tasks within it are the tasks +belonging to that cycle. The numbers (i.e. 1, 2, 3) are the +cycle points.

+
+

digraph Example { +size = "3,5" + +subgraph cluster_1 { + label = "1" + style = dashed + "1/foo" [label="foo\n1"] + "1/bar" [label="bar\n1"] + "1/baz" [label="baz\n1"] +} + +subgraph cluster_2 { + label = "2" + style = dashed + "2/foo" [label="foo\n2"] + "2/bar" [label="bar\n2"] + "2/baz" [label="baz\n2"] +} + +subgraph cluster_3 { + label = "3" + style = dashed + "3/foo" [label="foo\n3"] + "3/bar" [label="bar\n3"] + "3/baz" [label="baz\n3"] +} + +"1/foo" -> "1/bar" -> "1/baz" +"2/foo" -> "2/bar" -> "2/baz" +"3/foo" -> "3/bar" -> "3/baz" +"1/bar" -> "2/bar" -> "3/bar" +}

+
+
+

See also

+ +
+
+
cycle point

The unique label given to tasks that belong to a particular cycle. +For integer cycling these will be integers, e.g. 1, 2, +3, etc. +For datetime cycling they will be ISO 8601 datetimes, +e.g. 2000-01-01T00:00Z.

+ +
+
cycle point time zone

The time zone used for task cycle points.

+ +
+
cycling
cycling workflow

A cycling workflow in Cylc is defined by a graph of +repeating tasks with individual cycle points.

+
+

See also

+ +
+
+
cylc-run directory

This refers to the top level directory for installed workflows: ~/cylc-run.

+

Cylc can be configured to symlink cylc-run sub-directories to +other locations.

+ +
+

Caution

+

The cylc-run directory should not be confused with specific +workflow run directories below it.

+
+
+
datetime cycling

A datetime cycling workflow uses +ISO 8601 datetime cycle points +(e.g. 2000-01-01T00:00Z) and recurrences +(e.g. P3D means every third day).

+ +
+
directive

Directives request task jobs resources such as memory and +node count from external job runners. They are job +runner-specific.

+ +
+
event

An event is a milestone in the lifecycle of a workflow or +task at which the scheduler provides a hook for +attaching event handlers.

+

Workflow events include startup, stall, and +shutdown.

+

Task events include task state changes, to running or +failed, for example, or when the scheduler receivers CRITICAL or +WARNING messages from a task job.

+
+
exact datetime unit

An exact datetime unit is any unit of a datetime that has a fixed +duration, which does not depend on its position in the calendar. +In Cylc, the following are exact units:

+
    +
  • second: SI base unit

  • +
  • minute: 60 seconds

  • +
  • hour: 60 minutes

  • +
  • day: 24 hours

  • +
  • week: 7 days

  • +
+
+

Note

+

Although the ISO 8601 standard specifies that weeks and days +are inexact due to the possibility of +daylight saving time, leap seconds etc., they are always exact in +Cylc because workflows always maintain the same time zone, and leap +seconds are not supported.

+
+
+

See also

+ +
+
+
external trigger
xtrigger

External triggers allow tasks in the graph to +depend on external events, such as a file being delivered to some +location, or a database being updated in some way.

+

The scheduler can repeatedly call a user-supplied Python function +to check that the external event has occurred.

+

Cylc has a built in external trigger for triggering off of events in +other workflows.

+ +
+
family

In Cylc a family is a collection of tasks that share +common configuration and which can be referred to collectively in the +graph.

+

By convention, family names are upper case, with the exception of the +special root family that all tasks inherit from.

+ +
+
family trigger

Tasks that belong to a family can be +referred to collectively in the graph using a family +trigger.

+

Family triggers take the form family-name:qualifier, where +the qualifier describes the collective state of member tasks +needed for the dependency to be met. Some commonly used qualifiers +are:

+
+
succeed-all

All members succeeded.

+
+
succeed-any

Any one member succeeded.

+
+
fail-all

All members failed.

+
+
finish-all

All members finished (succeeded or failed).

+
+
+ +
+
final cycle point

In a cycling workflow the final cycle point, if there +is one, is the last cycle point in the graph.

+ +
+
final status

A task that has achieved a final status (expired, submit-failed, +succeeded, or failed) will not change state in the workflow, except by +manual intervention.

+
+
flow

A flow is a self-propagating run through the a Cylc workflow +graph starting from some initial task or tasks.

+

Cylc schedulers can manage multiple flows at once.

+

Flows are identified by a flow number. The original flow +started automatically by cylc play has flow number 1.

+
+

See also

+ +
+
+
flow front

Active tasks, i.e. tasks in the +n=0 window, with a common flow number +comprise the active front of the flow.

+
+
flow merge

When a flow tries to spawn a child task and finds an instance +with the same task ID already exists in the n=0 active +window, one merged task will carry both flow numbers forward.

+
+
flow number

Flow numbers are integers passed down from parent task to child task in +the graph as a flow progresses, to identify which flow +(or flows) the tasks belong to. They are passed to job environments as +$CYLC_TASK_FLOW_NUMBERS.

+
+
future trigger

A future trigger expresses dependence on a task in a “future” +(higher-valued) cycle point.

+

Here, 1/bar triggers off of 2/foo; 2/bar triggers off of +3/foo; and so on:

+
[scheduling]
+    initial cycle point = 1
+    cycling mode = integer
+    [[graph]]
+        P1 = "foo[+P1] => bar"
+
+
+
+

See also

+ +
+
+
graph

A workflow graph is defined by one or more graph strings +under the [scheduling][graph] section of a workflow definition.

+

For example, the following is, collectively, a graph:

+
P1D = foo => bar
+PT12H = baz
+
+
+
+

digraph Example { +size = "7,15" + +subgraph cluster_1 { + label = "2000-01-01T00:00Z" + style = dashed + "01T00/foo" [label="foo\n2000-01-01T00:00Z"] + "01T00/bar" [label="bar\n2000-01-01T00:00Z"] + "01T00/baz" [label="baz\n2000-01-01T00:00Z"] +} + +subgraph cluster_2 { + label = "2000-01-01T12:00Z" + style = dashed + "b01T12/az" [label="baz\n2000-01-01T12:00Z"] +} + +subgraph cluster_3 { + label = "2000-01-02T00:00Z" + style = dashed + "02T00/foo" [label="foo\n2000-01-02T00:00Z"] + "02T00/bar" [label="bar\n2000-01-02T00:00Z"] + "02T00/baz" [label="baz\n2000-01-02T00:00Z"] +} + +"01T00/foo" -> "01T00/bar" +"02T00/foo" -> "02T00/bar" +}

+
+
+
graph string

A graph string is a collection of task dependencies +in the [scheduling][graph] section of a workflow definition, +with an associated recurrence that defines its sequence of cycle points.

+

The example below shows one graph string in a datetime cycling workflow, +with a daily cycle point sequence:

+
R/^/P1D = """
+   foo => bar => baz & pub => qux
+   pub => bool
+"""
+
+
+
+
handler
event handler
event handlers

An event handler is a user-defined executable that the +scheduler runs when selected task or workflow +events occur.

+

Use-cases include:

+
    +
  • Send an email message.

  • +
  • Run a Cylc command.

  • +
  • Run any user-specified script or command.

  • +
+ +
+
hold
held task
hold after cycle point

A task held with cylc hold will not submit its jobs when ready to run.

+

It is also possible to set a “hold after cycle point”; all tasks after +this cycle point will be held.

+
+

Note

+

Workflows can be paused with cylc +pause, and unpaused/resumed with cylc play.

+

Tasks can be held with cylc hold and +released with cylc release.

+

When a workflow is resumed, any held tasks remain held.

+
+
+
implicit task

Implicit tasks are tasks which are not defined in +the [runtime] section.

+

Like regular tasks they inherit from the root +family.

+

Implicit tasks submit real jobs that just exit without doing anything +useful. They may be useful placeholders during workflow development but +are not allowed by default because they can be created accidentally by +simply misspelling a task name in the graph or under [runtime].

+

Here bar is implicit:

+
[scheduling]
+    [[graph]]
+        R1 = foo & bar
+[runtime]
+    [[foo]]
+# eof
+
+
+ +
+

Cylc 7

+

In Cylc 7 and earlier, implicit tasks were known as “naked dummy tasks”.

+
+
+
inexact datetime unit
nominal duration

An inexact datetime unit is any unit of a datetime that does not have +a fixed duration; it instead depends on its position in the calendar. +In Cylc, the following are inexact units (when using the Gregorian +calendar):

+
    +
  • year: either 365 or 366 days depending on whether it is a leap year

  • +
  • month: between 28 - 31 days depending on the specific month and year

  • +
+
+

See also

+ +
+
+
initial cycle point

In a cycling workflow the initial cycle point is the +first cycle point in the graph.

+ +
+
install
installation
workflow installation

The cylc install command installs workflow source files into a new run directory under the +cylc-run directory.

+
+

See also

+ +
+
+
install target

Cylc uses install targets to determine which platforms share file systems. +Install targets should normally be managed at site level. They are configured in +global.cylc[platforms][<platform name>]install target.

+
+

See also

+ +
+
+
integer cycling

An integer cycling workflow uses integer cycle points and recurrences (e.g. P3 means +every third cycle).

+ +
+
intercycle dependence
intercycle dependency
intercycle trigger

In a cycling workflow, intercycle dependence refers to +a task depending on other tasks at different cycle points.

+

For example, in the following workflow the task bar depends on +its own previous instance:

+
[scheduling]
+    initial cycle point = 1
+    cycling mode = integer
+    [[graph]]
+        P1 = """
+            foo => bar => baz
+            bar[-P1] => bar
+        """
+
+
+
+

digraph Example { +size = "3,5" + +subgraph cluster_1 { + label = "1" + style = dashed + "1/foo" [label="foo\n1"] + "1/bar" [label="bar\n1"] + "1/baz" [label="baz\n1"] +} + +subgraph cluster_2 { + label = "2" + style = dashed + "2/foo" [label="foo\n2"] + "2/bar" [label="bar\n2"] + "2/baz" [label="baz\n2"] +} + +subgraph cluster_3 { + label = "3" + style = dashed + "3/foo" [label="foo\n3"] + "3/bar" [label="bar\n3"] + "3/baz" [label="baz\n3"] +} + +"1/foo" -> "1/bar" -> "1/baz" +"2/foo" -> "2/bar" -> "2/baz" +"3/foo" -> "3/bar" -> "3/baz" +"1/bar" -> "2/bar" -> "3/bar" +}

+
+
+
ISO 8601
ISO8601

ISO 8601 is an international standard for writing datetimes, durations, +and recurrences (sequences of datetimes). Cylc uses +ISO 8601 for datetime cycling.

+ +
+
ISO 8601 datetime
ISO8601 datetime

A datetime written in the ISO 8601 format, e.g:

+
    +
  • 2000-01-01T00:00Z: midnight on the 1st of January 2000, UTC.

  • +
+
+

See also

+ +
+
+
ISO 8601 duration
ISO8601 duration

A duration written in the ISO 8601 format e.g:

+
    +
  • PT1H30M: one hour and thirty minutes.

  • +
+
+

See also

+ +
+
+
job

Jobs are the real processes that tasks represent in +a workflow. In Cylc, they are implemented by job scripts prepared by the scheduler.

+
+
job host

A job host is a compute resource that a job runs on. For +example node_1 would be one of two possible job hosts on the +platform my_hpc for the task solver in the +following workflow:

+
+
global.cylc
+
[platforms]
+    [[my_hpc]]
+        hosts = node_1, node_2
+        job runner = slurm
+
+
+
+
+
flow.cylc
+
[runtime]
+    [[solver]]
+        platform = my_hpc
+
+
+
+
+
job log
job log directory

Task job log files are stored in job specific log directories +under the workflow run directory. These include:

+
+
job

The task job script.

+
+
job.out

Job stdout.

+
+
job.err

Job stderr.

+
+
job.status

Job status data in case of lost contact with the scheduler.

+
+
job-activity.log

Job data logged by the scheduler, rather than +the job itself, such as output from the job submission command.

+
+
job.xtrace

Debugging information from Bash captured when Cylc is run in +--debug mode.

+
+
+
<run-directory>/log/job/<cycle-point>/<task-name>/<job-submit-num>
+
+
+

You can print job logs at the terminal with cylc cat-log +<workflow-name> <task-id>. By default this prints job.out. +There are command options to select the other logs.

+
+
job runner

A job runner is a system for submitting task jobs to run on +a job platform.

+

Cylc supports various job runners, from direct background process +execution to HPC batch queueing systems like PBS and Slurm (these are +also known as job schedulers and resource managers).

+

Job runners are configured on a per-platform basis in global.cylc.

+ +
+

Cylc 7

+

In Cylc 7 and earlier, job runners were referred to as “batch systems”.

+
+
+
job script

A Cylc job script is a file containing bash code to implement a task +definition in a workflow. It prepared and submitted to run by the +scheduler when the task is ready to run.

+

Job scripts can be found in the task job log directory.

+
+
job submission number

A single task may run multiple jobs as a result of +automatic retries or manually retriggering. +The job submission number is incremented each time, starting from 1.

+
+
message trigger

A message trigger is a trigger based on a +custom task output. The task job must +send a user-defined message to the scheduler to complete the output.

+

For brevity, the trigger in the graph uses the output name, not +the full message:

+
[scheduling]
+    [[graph]]
+        R1 = """
+           foo:out1 => proc-out-1
+           foo:out2 => proc-out-2
+        """
+[runtime]
+    [[foo]]
+        script = """
+            # ...
+            cylc message "Output 1 completed"
+            # ...
+            cylc message "Output 2 completed"
+        """
+        [[[outputs]]]
+            # output name = output message
+            out1 = "Output 1 completed"
+            out2 = "Output 2 completed"
+
+
+

However, if you don’t need a descriptive message for the workflow +log, you can make the message the same as its name:

+
[[[outputs]]]
+    out1 = out1
+
+
+
+
optional output

Optional task outputs are marked with a question +mark in the graph, e.g. foo:x?, or foo:fail?, or +foo? (short for foo:succeed?). The may or may not be completed at +runtime. Optional outputs are primarily used for graph branching.

+
+

See also

+ +
+
+
output
task output

Task outputs mark the progression of a task from waiting (for +prerequisites to be satisfied) through to success +or failure at run time. Tasks can trigger off of upstream task outputs in +the graph.

+

Outputs are written as task-name:output in the graph, and can +be required or optional.

+

Tasks may have custom outputs as well as +standard outputs.

+

Here the task bar depends on the standard :started output of +foo:

+
foo:started => bar
+
+
+

The standard :succeeded output is usually implicit:

+
foo => bar  # means foo:succeeded => bar
+
+
+
+
output completion
output completion condition

A task’s outputs are complete if its output completion condition +is satisfied.

+

The completion condition can be defined by the user in +flow.cylc[runtime][<namespace>]completion, +otherwise it is automatically generated according to the rules:

+
    +
  • All required outputs (referenced in the graph) +must be completed.

  • +
  • Or, if success is optional, then the outputs are complete if it fails.

  • +
  • Or, if submission is optional, then the outputs are complete if it +submit-fails.

  • +
  • Or, if expiry is optional, then the outputs are complete if it expires.

  • +
+

Tasks that achieve a final status with complete outputs have done +their job, allowing the workflow to move on.

+

Tasks that achieve a final status with incomplete outputs are retained in +n=0 pending user intervention, and will stall +the workflow.

+
+
pause

When a workflow is “paused” the scheduler is still +running but it will not submit any new jobs.

+

This can be useful if you want to make a change to a running workflow.

+

Pause a workflow with cylc pause and resume it with cylc play.

+
+

See also

+ +
+
+
platform
job platform

A platform for running Cylc task jobs is primarily defined +by the combination of a job runner and a group of hosts that share a file system.

+

For example my_hpc could be the platform for the task solver +in the following workflow:

+
+
Global configuration (global.cylc)
+
[platforms]
+    [[my_hpc]]
+        hosts = node_1, node_2
+        job runner = slurm
+
+
+
+
+
Workflow configuration (flow.cylc)
+
[runtime]
+    [[solver]]
+        platform = my_hpc
+
+
+
+
+

See also

+ +
+
+
platform group

A set of platforms grouped under a common name.

+

Platforms are configured by global.cylc[platform groups].

+
+
play

The cylc play command runs an instance of the scheduler +program to start or restart a workflow.

+

You can play, pause and stop a workflow, +Cylc will always carry on where it left off.

+
+
prerequisite
dependence
dependency

Dependencies in the graph show how tasks depend on +some combination of the outputs of other tasks.

+

For example, in the following dependency the task baz depends on both +foo and bar succeeding:

+
foo & bar => baz
+
+
+ +

Tasks can also depend on external triggers.

+
+
qualifier

A qualifier is what follows task or family family names +after a colon : in triggers, in the graph, +to specify exactly which task outputs must be +completed for the dependency to be satisfied.

+

For example, in foo:start => bar, the :start qualifier means that +the started output of task foo must be completed to satisfy the +dependency.

+ +
+
queue
internal queue

Internal queues (so called to distinguish them from external batch +queueing systems) limit how many jobs can be +active at once, across defined groups of tasks.

+

Use queues prevent large or busy workflows from swamping their +job platforms with too many jobs at once.

+ +
+
recurrence

In a cycling workflow a recurrence determines the +sequence of cycle points given to task instances that appear in the +associated graph string.

+

Recurrences for datetime cycling are based on the ISO8601 +standard. Those for integer cycling are designed to have similar +syntax, but are much simpler.

+
+
reinstall
reinstallation

The cylc reinstall command reinstalls workflow source files into an existing run directory under the +cylc-run directory.

+
+

See also

+ +
+
+
release

Held tasks can be released with cylc release, +allowing submission of task jobs once again.

+

It is also possible to remove the “hold after cycle point” if set, +using cylc release --all. This will also release all held tasks.

+
+
reload

Schedulers can reload their workflow +configuration from the installed flow.cylc +file, to pick up changes made at runtime.

+

We recommend that changes are reinstalled from the +workflow source directory before reload, rather than made by +editing the installed files directly.

+

Remote Initialization will be redone for each job platform, when the first job is submitted there after a reload.

+

Any task that is active at reload +will continue with its pre-reload configuration. +The next instance of the task (at the next cycle point) +will adopt the new configuration.

+

Reloading changes is safe providing they don’t affect the +workflow’s graph. Changes to the graph have +certain caveats attached, see the +Cylc User Guide +for details.

+
+

See also

+ +
+
+
required output
expected output

Task outputs that are not marked as optional +in the graph must be completed at runtime. If a task +achieves a final status without completing its required +outputs, the scheduler will keep it in the +n=0 window pending user intervention.

+
+

See also

+ +
+
+
restart

When a stopped workflow is played +again, the scheduler picks up where it left off rather than +starting again from scratch. It also detects any orphaned jobs that changed state (e.g. succeeded) while the system was down.

+

Changes made to the installed flow.cylc +file will be picked at restart. We recommend that changes are +reinstalled from the workflow source +directory before restart, rather than made by editing the installed +files directly.

+
+

See also

+ +
+
+
retry
task retry
try number

Tasks can be configured to retry automatically on failure, one or more +times. They return to the waiting state with a clock trigger +to delay the retry, and only go to the failed state once the final try fails.

+

The task try number increments with every automatic retry, and is +passed to the job environment as $CYLC_TASK_TRY_NUMBER.

+
+

See also

+ +
+
+
run directory
workflow run directory

This is a location under the cylc-run directory that contains the +installed configuration used to run a workflow.

+

At runtime, task jobs can get their workflow run +directory from the environment variable CYLC_WORKFLOW_RUN_DIR.

+ +
+
runahead limit
runahead

In a cycling workflow, the runahead limit determines how far +ahead of the oldest active cycle the workflow is permitted +to run.

+

The “oldest active cycle point” is the first cycle in the workflow to contain +any active tasks (e.g. running tasks).

+ +
+
runtime inheritance
family inheritance

A task is a member of a family if it inherits the +family configuration via [runtime][<namespace>]inherit.

+

For example the task cheddar “belongs” to the family +CHEESE in the following snippet:

+
[runtime]
+    [[CHEESE]]
+        [[[environment]]]
+            COLOR = yellow
+    [[cheddar]]
+        inherit = FAMILY
+
+
+

Families can also inherit from other families. All tasks implicitly +inherit from a special root family at the base of the inheritance +hierarchy.

+

Tasks can inherit from multiple families at once using a comma-separated +list:

+
inherit = foo, bar, baz
+
+
+ +
+
scheduler

The Cylc scheduler is a program responsible for managing a single +Cylc workflow. It determines when each tasks is +ready to run, submits its jobs to selected job runners, +tracks job status, maintains the workflow state, and listens for queries +and commands from the user.

+

By default, Cylc schedulers run as daemons (and potentially on a remote +host) so they won’t be killed if you log out.

+
+

See also

+ +
+
+

Cylc 7

+

In Cylc 7 and earlier, schedulers were known as “suite daemons”.

+
+
+
service directory

The hidden service directory, under the workflow run directory, +stores information for internal use by Cylc. It is created at +install time.

+
<run-directory>/.service/
+
+
+
+
share directory

Cylc automatically creates a share directory inside the workflow +run directory as a place to store files that need to be +shared between tasks.

+
<run-directory>/share
+
+
+

Tasks can get their own share directory path at runtime from +the CYLC_WORKFLOW_SHARE_DIR environment variable.

+

In cycling workflows files are typically stored in cycle point +sub-directories of the share directory.

+
+

See also

+ +
+
+
source directory
source workflow

A source directory is any location where workflows are +written and stored in preparation for installation with cylc install +or reinstallation with cylc reinstall.

+

These locations are configurable. The default is ~/cylc-src.

+ +
+
stall
stalled workflow

A stalled workflow has not run to completion +but cannot continue without manual intervention.

+

A stalled scheduler stays alive for a configurable timeout period +pending manual intervention. If it shuts down (on the stall timeout +or otherwise) it will remain in the stalled state on restart.

+

Stalls are usually caused by unexpected task failures:

+
+

digraph Example { +foo [style="filled" color="#ada5a5"] +bar [style="filled" color="#ff0000" fontcolor="white"] +baz [color="#88c6ff"] + +foo -> bar -> baz +}

+
+

In this example the task bar has failed, so that baz cannot +run, but bar:fail was not marked as an optional output.

+

User intervention is required to fix a stall, e.g. by retriggering +tasks after fixing the problems that caused them to fail.

+
+
standard output

Every task has a set of standard outputs +that trigger task state changes:

+
+
    +
  • :expired`

  • +
  • :submitted, or :submit-failed

  • +
  • :started

  • +
  • :succeeded, or :failed

  • +
+
+
+
start
startup

This refers to starting a new instance of the Cylc scheduler +program to manage a particular workflow. This can be from +scratch, for installed workflows that haven’t run previously, or to +restart one that shut down prior to completion.

+ +
+
start cycle point

In a cycling workflow the start cycle point is the +cycle point where the scheduler starts +running the workflow.

+

This may be at or after the initial cycle point.

+ +
+
start task

A start task is task in the graph from which the +scheduler starts running a workflow from +scratch.

+

Earlier tasks depended on by start tasks are treated as if they have +succeeded.

+ +
+

Cylc 7

+

Cylc 7 and earlier did not have the capability to start from any task +in the graph.

+
+
+
stop
shutdown

A scheduler can shut down on request, or automatically on +workflow completion. The workflow is then stopped and no +further jobs will be submitted.

+

By default, the scheduler waits for any submitted or running task +jobs to finish (either succeed or fail) before shutting +down.

+
+

See also

+ +
+
+
stop cycle point

The stop cycle point is the cycle point where scheduler +stops running the workflow and shuts down.

+

This may be at or before the final cycle point.

+ +
+
submit number
task submit number

Every time a task re-runs, whether by automatic retry or manual +triggering, its submit number increments. It is passed to +the job environment as $CYLC_TASK_SUBMIT_NUMBER.

+

Submit number also appears in the job log path so that job log files +don’t get overwritten.

+
+
suicide trigger

Suicide triggers remove tasks from the +active window at runtime.

+

They are denoted by exclamation marks, and are triggered like normal +dependencies. For instance, the following suicide trigger will remove the +task bar if foo succeeds:

+
foo => ! bar
+
+
+
+

Warning

+

Suicide triggers are not needed in Cylc 8 for graph branching. +They are retained for backward compatibility and rare edge cases.

+
+
+

See also

+ +
+
+
task

A task represents an activity in a workflow. The workflow +definition specifies how tasks depends on other tasks, what they +should do, how and where to run them, and details of their +runtime environment.

+

Task definitions are used to create a job script that is +executed as a job on behalf of the task.

+

Tasks submit jobs. Each job belongs to one task, +but one task can submit multiple jobs.

+
+
task parameters
parameterization

Task parameterization is one way of consolidating configuration in the +flow.cylc file. Cylc implicitly loops over ranges or lists +of pre-defined parameters to automatically generate sets of similar +tasks.

+

Other ways of consolidating configuration include runtime +inheritance and templating with Jinja2 or Empy.

+
[task parameters]
+    m = 1..3
+[scheduling]
+    [[graph]]
+        R1 = bar<m> => baz<m>
+
+
+
+

digraph Mini_Cylc { +bar_m3 -> baz_m3 +baz_m1 +bar_m2 -> baz_m2 +baz_m3 +baz_m2 +bar_m1 -> baz_m1 +}

+
+

See also

+ +
+
+
task state

A task progresses through a series of states in its lifetime. +These include the submitted state after job submission; +running after execution commences, and succeeded after +successful job execution.

+
+

See also

+ +
+
+
trigger
task trigger

A trigger is the left-hand side of a dependency in the +graph. It defines the combination of task outputs that must be completed before downstream tasks can run.

+

In this example, the task bar can be said to trigger off of +completion of the foo:started output:

+
foo:started => bar
+
+
+

Triggers can be based on standard or +custom task outputs. In the latter case they +are known as message triggers.

+
+
validation
workflow validation

Validation parses a flow.cylc file to report any illegal items, +syntax errors, deprecation warnings, and other problems.

+

It is done automatically at start up, and should be done manually with +the cylc validate command after making changes.

+
+
wallclock time

The actual time (in the real world).

+
+

See also

+ +
+
+
warm start

A warm start is when the scheduler starts a +cycling workflow running from a start cycle point after +the initial cycle point.

+

To satisfy unbounded intercycle dependence in the graph, tasks +prior to the start cycle point are treated as if they have succeeded.

+
+

See also

+ +
+
+
window
n-window
active window

The GUI provides a graph-based window or view of the workflow at +runtime, including tasks out to n graph edges from current +active tasks.

+

Active tasks form the n=0 window.

+
+

See also

+ +
+
+
work directory

Cylc executes task jobs inside a job-specific working +directory, automatically created under the workflow run +directory.

+
<run-directory>/work/<cycle-point>/<task-name>
+
+
+

Tasks can get their own work directory path at runtime from +the CYLC_TASK_WORK_DIR environment variable or the Posix pwd +command.

+
+

See also

+ +
+
+
workflow
cylc workflow

A workflow is a collection of tasks with +dependencies between them that govern the order in +which they can run.

+

Cylc workflows are defined in flow.cylc files.

+

For example, the following workflow represents the beer brewing process:

+
+
flow.cylc
+
[scheduling]
+    cycling mode = integer
+    initial cycle point = 1
+    [[graph]]
+        # repeat this for each batch
+        P1 = """
+            # the stages of brewing in the order they must occur in:
+            malt => mash => sparge => boil => chill => ferment => rack
+            # finish the sparge of one batch before starting the next:
+            sparge[-P1] => mash
+        """
+
+
+
+
+

Cylc 7

+

In Cylc 7 and earlier, “workflows” were referred to as “suites”.

+
+
+
workflow completion

A workflow is complete, and the scheduler will automatically +shut down, if no tasks remain in the +n=0.

+

That is, all active tasks have finished, and no tasks remain waiting on +prerequisites or “external” constraints (such as +xtriggers or task hold).

+

If no active tasks remain and all external constraints are satisfied, +but the n=0 window contains tasks waiting with partially satisfied +prerequisites, or tasks with final status and +incomplete outputs, then the workflow is +not complete and the scheduler will stall pending manual intervention.

+
+
workflow id

A workflow can be uniquely identified by the relative path between the cylc-run directory +(~/cylc-run) and its run directory.

+

This ID is used on the command line and in the GUI, to target the right +workflow.

+

For example, the ID of the workflow in ~/cylc-run/foo/bar/run1 +is foo/bar/run1.

+

Unlike workflow name the ID is always a unique identifier. In the +example below each run has a different ID despite sharing the same +workflow name (my_workflow).

+
`- my_workflow
+  |- runN
+  |- run1      # CYLC_WORKFLOW_ID = my_workflow/run1
+  `- run2      # CYLC_WORKFLOW_ID = my_workflow/run2
+
+
+
+
workflow log
scheduler log
workflow log directory

At runtime the scheduler logs timestamped events and other information to +files under the workflow run directory. These logs take the format +<log-number>-<start/restart>-<start-number>.log, with the latest log being +automatically symlinked to <run-directory>/log/scheduler/log

+
<run-directory>/log/scheduler/
+
+
+

You can print the scheduler log at the terminal with cylc cat-log +<workflow-name>.

+
+
workflow name

The workflow name is a path relative to the cylc-run directory which +contains one or more workflow run directories.

+

Tasks can get the workflow name from $CYLC_WORKFLOW_NAME in their +runtime environment.

+

Unlike workflow id the name is not always a unique identifier. In +the example below run1 and run2 would both have the same name, +my_workflow:

+
`- my_workflow
+  |- runN
+  |- run1
+  `- run2
+
+
+
+

Note

+

If you are not using named or numbered runs, the workflow name will be +the same as workflow id.

+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/index.html b/nightly_8.4/html/index.html new file mode 100644 index 00000000000..716c06b455b --- /dev/null +++ b/nightly_8.4/html/index.html @@ -0,0 +1,229 @@ + + + + + + + Cylc Documentation — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/installation.html b/nightly_8.4/html/installation.html new file mode 100644 index 00000000000..3499bd46876 --- /dev/null +++ b/nightly_8.4/html/installation.html @@ -0,0 +1,462 @@ + + + + + + + Installation — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Installation

+

Cylc 8 and its core software dependencies can be installed quickly from Conda +Forge, into a conda environment; or from PyPI, into a Python 3 virtual environment.

+
+

Quick Installation

+

Cylc runs on Unix-like systems including Linux and Mac OS.

+ +
+

Via Pip (+npm)

+
+

Note

+

Requires Python 3.7 - 3.9

+
+
+

Important

+

We recommend installing Cylc versions into virtual environments. +This avoids software dependency conflicts and allows multiple +Cylc versions to be installed on your system.

+

Without virtual environments, users can inadvertently break Cylc (or other +Python programs) by pip-installing conflicting package versions to +$HOME/.local, which takes precedence over central library locations.

+
+
$ pip install cylc-flow
+
+# Install the browser-GUI (optional)
+# (requires nodejs & npm)
+$ pip install cylc-uiserver
+
+# Install Rose support (optional)
+$ pip install cylc-rose metomi-rose
+
+
+

There are also certain optional extra requirements which you may choose to +install:

+
# EmPy support
+$ pip install 'cylc-flow[empy]'
+
+# Support for running the tutorial workflows
+$ pip install 'cylc-flow[tutorial]'
+
+# The GUI with multi-user (hub) support
+$ pip install 'cylc-uiserver[hub]'
+$ npm install configurable-http-proxy
+
+
+

You might also want to configure:

+ +
+
+
+

Non-Python Requirements

+

These dependencies are not installed by Conda or pip:

+
    +
  • bash

  • +
  • GNU coreutils

  • +
  • ssh

  • +
  • rsync

  • +
  • mail (optional - for automated email functionality)

  • +
+

These dependencies are installed by Conda but not by pip:

+
    +
  • Graphviz (optional - used by cylc graph for displaying workflow +graphs)

  • +
  • configurable-http-proxy (optional - for multi-user setups; can also be +installed using npm)

  • +
+ +
+
+

Installing On Mac OS

+

Cylc requires some extra packages to function on Mac OS. We recommend +installing them using the Homebrew package manager:

+
$ brew install bash coreutils gnu-sed
+
+
+

You will need to prepend the coreutils and gnu-sed installations to +your $PATH, follow the instructions in the brew install output.

+
+

Note

+

atrun (the at command) does not run out-of-the-box on Mac OS +for security reasons and must be manually enabled.

+
+
+

Note

+

Newer version of Mac OS set zsh as the default shell (as opposed to +bash). You do not need to change this but be aware that Cylc uses +bash (for job scripts) which has a subtly different syntax.

+
+
+

Warning

+

For Mac OS Versions 10.15.0 (Catalina) and higher SSH is disabled by +default. The ability to SSH into your Mac OS box may be required for +certain Cylc installations.

+

See the Apple support page +for instructions on enabling SSH.

+
+
+
+

Advanced Installation

+

For distributed and multi-user installation we recommend using Conda and +installing Cylc components only where required.

+
+

Tip

+

For examples of Conda environments and installation options see +Conda Environments for examples and details.

+
+
+

The Cylc Components

+

Cylc is split into a number of components providing different functionality:

+
+
Cylc Flow

Provides the scheduler “kernel” of Cylc along with the command line interface.

+
+
Cylc UI Server

Provides the “Cylc Hub” and the browser-based “Cylc GUI”.

+
+
Cylc Rose

Provides support for Rose suite configurations in Cylc workflows.

+
+
+
+
+

Installation Types

+

Cylc install locations may fall into the following “roles”:

+
+
User Machines

Where users write workflows and interact with the command line.

+
+
Cylc Servers

Where Cylc schedulers run to manage workflows.

+
+
Job Hosts

Where jobs run, e.g. supercomputers or clusters

+
+
+
+

Note

+

These roles may overlap. For example, Cylc servers can also be job hosts.

+
+
+ +
+

Managing Environments

+

For Cylc to run, the correct environment must be activated. Cylc can +not do this automatically. You may need to have multiple Cylc versions +available too.

+

We recommend using a wrapper script named cylc to activate the correct +environment before calling the environment’s cylc command.

+

Cylc comes with a wrapper that can be adapted to point at your Cylc +environments. Extract it to a directory in your $PATH like this:

+
cylc get-resources cylc /path/to/cylc  # should be in $PATH
+chmod +x /path/to/cylc
+
+
+

You may need to modify this file for your local installation e.g:

+
- CYLC_HOME_ROOT="${CYLC_HOME_ROOT:-/opt}"
++ CYLC_HOME_ROOT="${CYLC_HOME_ROOT:-/path/to}"
+
+
+
+

Note

+

Developers can set $CYLC_HOME_ROOT_ALT to point +to their development environments. For example:

+
CYLC_HOME_ROOT_ALT=${HOME}/.conda/envs
+
+
+
+

You may wish to use the same approach for the isodatetime command, and, if using +Rose for the rose and rosie commands.

+

To do so create a symbolic link to the wrapper, for each of these commands:

+
cd /path/to       # Using the path where you installed the wrapper script
+ln -s cylc rose
+ln -s cylc rosie
+ln -s cylc isodatetime
+
+
+
+
+
+

Configuration

+

Cylc uses sane and safe defaults and is suitable for use “out of the box”, +if all you need to do is run jobs locally in the background. +However, many things may need to be configured, e.g:

+ +
+

Cylc Flow

+

Cylc Flow is configured by the global.cylc file which supports +configuration of the system on both a site and user basis.

+
+

Note

+

Prior to Cylc 8, global.cylc was named global.rc, but that name is +no longer supported.

+
+

The global.cylc file should be available on user machines (where users interact +with Cylc on the command line) and on cylc servers (where Cylc schedulers run). +It is not required to be available on job hosts.

+

More information about supported configuration items and defaults can be found: +Global Configuration.

+
+
+

Cylc UI Server

+

The Cylc UI Server can be configured on a site and user basis. +Guidance for configuration file storage, configuration variables and defaults +can be found: UI Server Configuration.

+
+
+

Bash Profile

+

Cylc job scripts are bash scripts, which is good for +manipulating files and processes, They invoke bash -l to allow environment +configuration in login scripts.

+
+

Warning

+

Sites and users should ensure their bash login scripts configure the +environment correctly for Cylc and do not write anything to stdout.

+
+
+
+

Shell Auto-Completion

+

Cylc provides auto-completion for the Bash shell which can save you typing:

+
    +
  • Cylc commands

  • +
  • Workflow IDs

  • +
  • Cycle points

  • +
  • Task names

  • +
+

To extract the auto-completion file run the following command:

+
cylc get-resources cylc-completion.bash <path-to-copy-file>
+
+
+

Then follow the comments in the file to install it.

+
+
+

Text Editors

+

There is support for the .cylc file format in various text editors.

+

See Syntax Highlighting For Workflow Configuration for more details.

+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/objects.inv b/nightly_8.4/html/objects.inv new file mode 100644 index 00000000000..67877d06b7e Binary files /dev/null and b/nightly_8.4/html/objects.inv differ diff --git a/nightly_8.4/html/plugins/cylc-rose.html b/nightly_8.4/html/plugins/cylc-rose.html new file mode 100644 index 00000000000..a93859357cf --- /dev/null +++ b/nightly_8.4/html/plugins/cylc-rose.html @@ -0,0 +1,366 @@ + + + + + + + Cylc Rose — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Cylc Rose

+
+

Rose Suite Configurations

+

This plugin is activated by the existence of a Rose Suite Configuration file +(called rose-suite.conf) in the workflow definition directory which allows +you to:

+
    +
  • Set template variables used in the workflow definition.

  • +
  • Configure files to be installed via cylc install.

  • +
  • Define environment variables for the Cylc scheduler.

  • +
+

The following Cylc commands will read Rose Suite Configurations:

+
    +
  • cylc install

  • +
  • cylc validate

  • +
  • cylc graph

  • +
  • cylc list

  • +
  • cylc config

  • +
+
+

Note

+

Cylc Rose allows cylc install to replace the rose suite-run +command (present in Rose versions 2019.01 and earlier).

+
+
+

Configuration File

+
+

Attention

+

Although we now refer to Cylc workflows (rather than suites) we +continue to refer to the rose-suite.conf file as a Rose Suite +Configuration.

+
+

A fuller description of +Rose Suite Configuration is available here.

+

The following sections are permitted in the rose-suite.conf files:

+ + + + + + + + + + + + + + + + + + + + +

config item

description

opts=A B C

A space limited list of optional configs.

[env]

Variables which the cylc-rose plugin will export to the +environment.

[template variables]

Variables which can be used by Jinja2 or Empy +in the workflow definition.

[file:destination]

A file from one or more sources to be installed.

+
+

Note

+

For compatibility with Cylc 7, sections [suite.rc:empy] and +[suite.rc:jinja2] will be processed, but are deprecated and provided +for ease of porting Cylc 7 workflows.

+
+
+

The global.cylc file

+

The Cylc Rose Plugin forces the reloading of the global.cylc file +to allow environment variables set by Rose to change the global configuration.

+

For example you could use CYLC_SYMLINKS as a variable to control +the behaviour of cylc install:

+
#!jinja2
+# part of a global.cylc file
+[install]
+   [[symlink dirs]]
+      [[[hpc]]]
+{% if environ["CYLC_SYMLINKS"] | default("x") == "A" %}
+         run = $LOCATION_A
+{% elif environ["CYLC_SYMLINKS"] | default("x") == "B" %}
+         run = $LOCATION_B
+{% else %}
+         run = $LOCATION_C
+{% endif %}
+
+
+
+
+
+

Special Variables

+

The Cylc Rose plugin provides two environment/template variables +to the Cylc scheduler.

+
+
ROSE_ORIG_HOST

Cylc commands (such as cylc install, cylc validate and +cylc play) +will provide the name of the host on which the command is run.

+

If the workflow is installed the value of ROSE_ORIG_HOST will be +set in opt/rose-suite-cylc-install.conf and used by future commands +e.g. cylc play.

+

Using cylc install should produce a more consistent value +for ROSE_ORIG_HOST; running Cylc commands on non-installed +workflows may produce inconsistent values because the host +is identified each time you run a command.

+
+
ROSE_VERSION

When running Cylc commands such as cylc install, +cylc play and cylc validate +the plugin provides the version number of your installed Rose Version in +workflow scheduler’s environment.

+
+

Deprecated since version 8.0.0: Setting [env]ROSE_VERSION in rose-suite.conf. +With Cylc 7 / Rose2019 users could set ROSE_VERSION for their +suites. This is no longer possible, and if set in your +ROSE_VERSION in your suite configuration it will be ignored.

+
+
+
+
+

Note

+
+

Deprecated since version 8.0.0: CYLC_VERSION will be removed from your configuration by the +Cylc-Rose plugin, as it is now set by Cylc.

+
+
+
+
+

Additional CLI options

+

You can use command line options to set or override +any setting you could put in a rose-suite.conf file: If you +have Cylc Rose installed see cylc install --help.

+
+
+

Cylc Install Optional Config

+

If Cylc-Rose is installed, using cylc install with a workflow containing a +Rose Suite Configuration will write a record of command line options set in +$CYLC_RUN_DIR/workflow_name/opt/rose-suite-cylc-install.conf.

+

Example

+

For a workflow with the following definitions in the source directory:

+

rose-suite.conf

+
[template variables]
+NAME='Mars'
+
+
+

flow.cylc

+
#!jinja2
+[scheduling]
+    initial cycle point = 2020
+    [[graph]]
+        R1 = Hello_{{ NAME }}
+
+[runtime]
+    [[Hello_{{ NAME }}]]
+        script = True
+
+
+

If you then ran

+
cylc install
+
+
+

Your final workflow would have the variable NAME inserted:

+
- Before processing
++ After processing
+
+-           R1 = Hello_{{ NAME }}
++           R1 = Hello_Mars
+
+-       [[Hello_{{ NAME }}]]
++       [[Hello_Mars]]
+
+
+
+
+
+

Rose Stem

+ +

Cylc Rose provides a Rose Stem command, if FCM is installed on your system. +At Cylc 8 Rose Stem is a wrapper to cylc install rather than +rose suite-run.

+

Rose Stem is a wrapper around the cylc install command which +provides some additional Jinja2 variables.

+

Cylc 8 stores variables set by rose and rose-stem in the optional +configuration file ~/cylc-run/my_workflow/opt/rose-suite-cylc-install.conf.

+
+

Caution

+

To reinstall a rose stem suite use cylc reinstall. Cylc can get any +options you do not change from the rose-suite-cylc-install.conf` file. +Using rose stem a second time will attempt install a new copy +of your rose stem suite.

+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/plugins/index.html b/nightly_8.4/html/plugins/index.html new file mode 100644 index 00000000000..d2bf90a9612 --- /dev/null +++ b/nightly_8.4/html/plugins/index.html @@ -0,0 +1,182 @@ + + + + + + + Plugins — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Plugins

+

Cylc supports plugins for providing additional functionality.

+

The following are “core” plugins maintained by the Cylc team:

+ +
+

Warning

+

Plugins are a new feature of Cylc 8 and the interface is likely to change in +future releases.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/plugins/install/built-in/cylc.flow.install_plugins.log_vc_info.html b/nightly_8.4/html/plugins/install/built-in/cylc.flow.install_plugins.log_vc_info.html new file mode 100644 index 00000000000..f815a4a927a --- /dev/null +++ b/nightly_8.4/html/plugins/install/built-in/cylc.flow.install_plugins.log_vc_info.html @@ -0,0 +1,212 @@ + + + + + + + cylc.flow.install_plugins.log_vc_info — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

cylc.flow.install_plugins.log_vc_info

+

Record version control information to the workflow log directory on +installation.

+

If the workflow source directory is a supported repository/working copy +(git or svn), information about the working copy will be saved in +<run-dir>/log/version/vcs.json.

+

An example of this information for a git repo:

+
{
+    "version control system": "git",
+    "repository version": "2.8.0-dirty",
+    "commit": "e5dc6573dd70cabd8f973d1535c17c29c026d553",
+    "working copy root path": "~/cylc-src/my-workflow-git",
+    "status": [
+        " M flow.cylc",
+        "M  bin/thing.sh"
+    ]
+}
+
+
+

And for an svn working copy:

+
{
+    "version control system": "svn",
+    "working copy root path": "~/cylc-src/my-workflow-svn",
+    "url": "file:///home/my-workflow-svn/trunk",
+    "repository uuid": "219f5687-8eb8-44b1-beb6-e8220fa964d3",
+    "revision": "14",
+    "status": [
+        "M       readme.txt"
+    ]
+}
+
+
+

Any uncommitted changes will also be saved as a diff in +<run-dir>/log/version/uncommitted.diff.

+
+

Note

+

Git does not include untracked files in the diff.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/plugins/install/index.html b/nightly_8.4/html/plugins/install/index.html new file mode 100644 index 00000000000..f822d87abb9 --- /dev/null +++ b/nightly_8.4/html/plugins/install/index.html @@ -0,0 +1,329 @@ + + + + + + + Pre-Configure And Post-Install Plugins — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Pre-Configure And Post-Install Plugins

+

Pre-configure plugins allow Cylc to take additional actions before running +Cylc utilities such as cylc install, cylc graph and cylc config.

+

Post-install plugins allow Cylc to take additional actions after +running cylc install.

+
+

Built In Plugins

+

Cylc Flow provides the following pre-configure and post-install plugins:

+ + + + + + +

cylc.flow.install_plugins.log_vc_info

Record version control information to the workflow log directory on installation.

+
+
+

Developing pre_configure and post_install plugins

+

Cylc uses entry points registered by setuptools to search for pre-configure +and post-install plugins.

+
+

Hello World

+

In this example a pre-configure plugin which logs a “Hello World” message +and, after installation, logs some info about the installation:

+
+
my_plugin.py
+
from cylc.flow import LOG
+
+def pre_configure(srcdir=None, opts=None, rundir=None):
+    # write Hello to the Cylc log.
+    LOG.info(f'Hello World')
+    return {}
+
+def post_install(srcdir=None, opts=None, rundir=None):
+    LOG.info(f'installed from {srcdir}')
+    LOG.info(f'installed to {rundir}')
+    LOG.info(f'installation options were {options}')
+    return {}
+
+
+
+

Plugins are registered by registering them with the cylc.pre_configure +and cylc.post_install entry points:

+
+
setup.py
+
# plugins must be properly installed, in-place PYTHONPATH meddling will
+# not work.
+
+from setuptools import setup
+
+setup(
+    name='my-plugin',
+    version='1.0',
+    py_modules=['my_plugin'],
+    entry_points={
+        # register this plugin with Cylc
+        'cylc.pre_configure': [
+        # name = python.namespace.of.module
+        'my_plugin=my_plugin.my_plugin:pre_configure'
+        ]
+        'cylc.post_install': [
+        # name = python.namespace.of.module
+        'my_plugin=my_plugin.my_plugin:post_install'
+        ]
+    }
+)
+
+
+
+
+
+

API Reference

+

Cylc will pass following arguments to pre-configure and post-install plugins:

+
+
srcdir (Path or string)

The directory from which cylc install is installing a workflow, +or the directory passed to cylc validate, cylc graph and other +CLI commands which work without installing a workflow.

+
+
opts (optparse.Values)

CLI options set for a Cylc script.

+
+
rundir (Path or string)

The destination of a cylc install or reinstall command.

+
+
+

The pre-configure plugin should return a dictionary which may contain the +following keys:

+
+
env

A dictionary of environment variables to be exported to the scheduler +environment.

+
+
template_variables

A dictionary of template variables to be used by Jinja2 or EmPy when +templating the workflow configuration files.

+
+
templating_detected

jinja2 | empy to be used when templating. N.b: This will result in +failure if the templating language set does not match the shebang line of +the flow.cylc file.

+
+
+

The post-install entry point does not return any data used by Cylc.

+
+
+

More advanced example

+
+

See also

+

For the implementation of a more fully featured “real-world” example see +Cylc Rose.

+
+

The example below looks for a file in the workflow source directory called +template.json and activates if it exists.

+

At pre_configure template variables are extracted from a template.json +file and provided to Cylc as both template and environment variables.

+

At post_install an additional log file is provided recording the version +of this plugin used.

+
+
An example json reading plugin
+
import json
+from pathlib import Path
+
+VERSION = '0.0.1'
+
+def pre_configure(srcdir=None, opts=None, rundir=None):
+    # Look for a 'template.json' file in the srcdir and make template
+    # variables from it available as jinja2.
+    template_file = (Path(srcdir) / 'template.json')
+
+    # Trigger the plugin if some condition is met:
+    if (template_file).exists():
+        # You could retrieve info from a file:
+        template = json.loads(template_file.read_text())
+
+        # You can add variables programmatically:
+        template['plugin_set_var'] = str(__file__)
+
+        # Return a dict:
+        return {
+            'env': template,
+            'template_variables': template,
+            'templating_detected': 'jinja2'
+        }
+    else:
+        return {}
+
+def post_install(srcdir=None, opts=None, rundir=None):
+    # record plugin version in a file
+    (Path(rundir) / 'log/json-plugin.info').write_text(
+        f"Installed with Simple JSON reader plugin version {VERSION}\\n")
+    return None
+
+
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/plugins/job-runners/index.html b/nightly_8.4/html/plugins/job-runners/index.html new file mode 100644 index 00000000000..1d07b49674e --- /dev/null +++ b/nightly_8.4/html/plugins/job-runners/index.html @@ -0,0 +1,616 @@ + + + + + + + Custom Job Submission Methods — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Custom Job Submission Methods

+
+
+class cylc.flow.job_runner_handlers.documentation.ExampleHandler[source]
+

Documentation for writing job runner handlers.

+

Cylc can submit jobs to a number of different job runners +(aka batch systems) e.g. Slurm and PBS. For a list of built-in integrations +see Supported Job Submission Methods.

+

If the job runner you require is not on this list, Cylc provides a generic +interface for writing your own integration.

+

Defining a new job runner handler requires a little Python programming. Use +the built-in handlers +(e.g. cylc.flow.job_runner_handlers.background) as examples.

+

Installation

+

Custom job runner handlers must be installed on workflow and job +hosts in one of these locations:

+
    +
  • under WORKFLOW-RUN-DIR/lib/python/

  • +
  • under CYLC-PATH/cylc/flow/job_runner_handlers/

  • +
  • or anywhere in $PYTHONPATH

  • +
+

Each module should export the symbol JOB_RUNNER_HANDLER for the +singleton instance that implements the job system handler logic e.g:

+
+
my_handler.py
+
class MyHandler():
+    pass
+
+JOB_RUNNER_HANDLER = MyHandler()
+
+
+
+

Each job runner handler class should instantiate with no argument.

+

Usage

+

You can then define a Cylc platform using the handler:

+
+
global.cylc
+
[platforms]
+    [[my_platform]]
+        job runner = my_handler  # note matches Python module name
+        hosts = localhost
+
+
+
+

And configure tasks to submit to it:

+
+
flow.cylc
+
[runtime]
+    [[my_task]]
+        script = echo "Hello World!"
+        platform = my_platform
+
+
+
+

Common Arguments

+
+
job_conf: dict

The Cylc job configuration as a dictionary with the following fields:

+
    +
  • dependencies

  • +
  • directives

  • +
  • env-script

  • +
  • environment

  • +
  • err-script

  • +
  • execution_time_limit

  • +
  • exit-script

  • +
  • flow_nums

  • +
  • init-script

  • +
  • job_d

  • +
  • job_file_path

  • +
  • job_runner_command_template

  • +
  • job_runner_name

  • +
  • namespace_hierarchy

  • +
  • param_var

  • +
  • platform

  • +
  • post-script

  • +
  • pre-script

  • +
  • script

  • +
  • submit_num

  • +
  • task_id

  • +
  • try_num

  • +
  • uuid_str

  • +
  • work_d

  • +
  • workflow_name

  • +
+
+
submit_opts: dict

The Cylc job submission options as a dictionary which may contain +the following fields:

+
    +
  • env

  • +
  • execution_time_limit

  • +
  • execution_time_limit

  • +
  • job_runner_cmd_tmpl

  • +
  • job_runner_cmd_tmpl

  • +
+
+
+

An Example

+

The following qsub.py module overrides the built-in pbs +job runner handler to change the directive prefix from #PBS to +#QSUB:

+
#!/usr/bin/env python3
+
+from cylc.flow.job_runner_handlers.pbs import PBSHandler
+
+class QSUBHandler(PBSHandler):
+    DIRECTIVE_PREFIX = "#QSUB "
+
+JOB_RUNNER_HANDLER = QSUBHandler()
+
+
+

If this is in the Python search path (see +Installation above) you can use it by +name in your global configuration:

+
[platforms]
+    [[my_platform]]
+        hosts = myhostA, myhostB
+        job runner = qsub  # <---!
+
+
+

Then in your flow.cylc file you can use this platform:

+
# Note, this workflow will fail at run time because we only changed the
+# directive format, and PBS does not accept ``#QSUB`` directives in
+# reality.
+
+[scheduling]
+    [[graph]]
+        R1 = "a"
+[runtime]
+    [[root]]
+        execution time limit = PT1M
+        platform = my_platform
+        [[[directives]]]
+            -l nodes = 1
+            -q = long
+            -V =
+
+
+
+

Note

+

Don’t subclass this class as it provides optional interfaces which +you may not want to inherit.

+
+
+
+FAIL_SIGNALS: Tuple[str]
+

A tuple containing the names of signals to trap for reporting errors.

+

The default is ("EXIT", "ERR", "TERM", "XCPU").

+

ERR and EXIT are always recommended. +EXIT is used to report premature stopping of the job +script, and its trap is unset at the end of the script.

+
+ +
+
+KILL_CMD_TMPL: str
+

Command template for killing a job submission.

+

A Python string template for getting the job runner command to remove +and terminate a job ID. The command is formed using the logic: +job_runner.KILL_CMD_TMPL % {"job_id": job_id}.

+

For info on Python string template format see: +https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting

+
+ +
+
+POLL_CANT_CONNECT_ERR: str
+

String for detecting communication errors in poll command output.

+

A string containing an error message. If this is defined, when a poll +command returns a non-zero return code and its STDERR contains this +string, then the poll result will not be trusted, because it is assumed +that the job runner is currently unavailable. Jobs submitted to the +job runner will be assumed OK until we are able to connect to the +job runner again.

+
+ +
+
+POLL_CMD: str
+

Command for checking job submissions.

+

A list of job IDs to poll will be provided as arguments.

+

The command should write valid submitted/running job IDs to stdout.

+ +
+ +
+
+REC_ID_FROM_SUBMIT_ERR: re.Pattern
+

Regular expression to extract job IDs from submission stderr.

+

See ExampleHandler.REC_ID_FROM_SUBMIT_OUT.

+
+ +
+
+REC_ID_FROM_SUBMIT_OUT: re.Pattern
+

Regular expression to extract job IDs from submission stderr.

+

A regular expression (compiled) to extract the job “id” from the standard +output or standard error of the job submission command.

+
+ +
+
+SHOULD_KILL_PROC_GROUP: bool
+

Kill jobs by killing the process group.

+

A boolean to indicate whether it is necessary to kill a job by sending +a signal to its Unix process group. This boolean also indicates that +a job submitted via this job runner will physically run on the same +host it is submitted to.

+
+ +
+
+SHOULD_POLL_PROC_GROUP: bool
+

Poll jobs by PID.

+

A boolean to indicate whether it is necessary to poll a job by its PID +as well as the job ID.

+
+ +
+
+SUBMIT_CMD_ENV: Iterable[str]
+

Extra environment variables for the job runner command.

+

A Python dict (or an iterable that can be used to update a dict) +containing extra environment variables for getting the job runner +command to submit a job file.

+
+ +
+
+SUBMIT_CMD_TMPL: str
+

Command template for job submission.

+

A Python string template for getting the job runner command to submit a +job file. The command is formed using the logic: +job_runner.SUBMIT_CMD_TMPL % {"job": job_file_path}

+

For info on Python string template format see: +https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting

+
+ +
+
+filter_poll_many_output(out)[source]
+

Filter job ides out of poll output.

+

Called after the job runner’s poll command. The method should read +the output and return a list of job IDs that are still in the +job runner.

+
+
Parameters:
+

out (str) – Job poll stdout.

+
+
Returns:
+

List of job IDs

+
+
Return type:
+

List[str]

+
+
+
+ +
+
+filter_submit_output(out, err)[source]
+

Filter job submission stdout/err.

+

Filter the standard output and standard error of the job submission +command. This is useful if the job submission command returns +information that should just be ignored.

+

See also ExampleHandler.SUBMIT_CMD_TMPL().

+
+
Parameters:
+
    +
  • out (str) – Job submit stdout.

  • +
  • err (str) – Job submit stderr.

  • +
+
+
Returns:
+

(new_out, new_err)

+
+
Return type:
+

Tuple[str, str]

+
+
+
+ +
+
+format_directives(job_conf)[source]
+

Returns lines to be appended to the job script.

+

This method formats the job directives for a job file, if +job file directives are relevant for the job runner. The argument +“job_conf” is a dict containing the job configuration.

+
+
Parameters:
+

job_conf (dict) – The Cylc configuration.

+
+
Returns:
+

lines

+
+
Return type:
+

List[str]

+
+
+
+ +
+
+get_poll_many_cmd(job_id_list)[source]
+

Return a command to poll the specified jobs.

+

If specified, this will be called instead of +ExampleHandler.POLL_CMD.

+
+
Parameters:
+

job_id_list (List[str]) – The list of job IDs to poll.

+
+
Returns:
+

command e.g. [‘foo’, ‘–bar’, ‘baz’]

+
+
Return type:
+

List[str]

+
+
+
+ +
+
+get_submit_stdin(job_file_path, submit_opts)[source]
+

Return a 2-element tuple (proc_stdin_arg, proc_stdin_value).

+
    +
  • Element 1 is suitable for the stdin=... argument of +subprocess.Popen so it can be a file handle, subprocess.PIPE +or None.

  • +
  • Element 2 is the string content to pipe to stdin of the submit +command (relevant only if proc_stdin_arg is subprocess.PIPE.

  • +
+
+
Parameters:
+
    +
  • job_file_path (str) – The path to the job file for this submission.

  • +
  • submit_opts (dict) – Job submission options.

  • +
+
+
Returns:
+

(proc_stdin_arg, proc_stdin_value)

+
+
Return type:
+

Tuple

+
+
+
+ +
+
+get_vacation_signal(job_conf)[source]
+

Return the vacation signal.

+

If relevant, return a string containing the name of the signal that +indicates the job has been vacated by the job runner.

+
+
Parameters:
+

job_conf (dict) – The Cylc configuration.

+
+
Returns:
+

signal

+
+
Return type:
+

str

+
+
+
+ +
+
+manip_job_id(job_id)[source]
+

Modify the job ID that is returned by the job submit command.

+
+
Parameters:
+

job_id (str) – The job ID returned by the submit command.

+
+
Returns:
+

job_id

+
+
Return type:
+

str

+
+
+
+ +
+
+submit(job_file_path, submit_opts)[source]
+

Submit a job.

+

Submit a job and return an instance of the Popen object for the +submission. This method is useful if the job submission requires logic +beyond just running a system or shell command.

+

See also ExampleHandler.SUBMIT_CMD_TMPL.

+

You must pass “env=submit_opts.get(‘env’)” to Popen - see +cylc.flow.job_runner_handlers.background +for an example.

+
+
Parameters:
+
    +
  • job_file_path (str) – The job file for this submission.

  • +
  • submit_opts (dict) – Job submission options.

  • +
+
+
Returns:
+

(ret_code, out, err)

+
+
ret_code:

Subprocess return code.

+
+
out:

Subprocess standard output, note this should be newline +terminated.

+
+
err:

Subprocess standard error.

+
+
+

+
+
Return type:
+

Tuple[int, str, str]

+
+
+
+ +
+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.auto_restart.html b/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.auto_restart.html new file mode 100644 index 00000000000..e5cdbc1ddf7 --- /dev/null +++ b/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.auto_restart.html @@ -0,0 +1,254 @@ + + + + + + + cylc.flow.main_loop.auto_restart — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

cylc.flow.main_loop.auto_restart

+

Automatically restart workflows if they are running on bad servers.

+

Loads in the global configuration to check if the server a workflow is running +on is listed in global.cylc[scheduler][run hosts]condemned.

+

This is useful if a host needs to be taken off-line e.g. for scheduled +maintenance.

+

This functionality is configured via the following site configuration +settings:

+ +

The auto stop-restart feature has two modes:

+
+
Normal Mode

When a host is added to the +[scheduler][run hosts]condemned list, any workflows +running on that host will automatically shutdown then restart selecting a +new host from [scheduler][run hosts]available.

+

For safety, before attempting to stop the workflow Cylc will first wait +for any jobs running locally (under background or at) to complete.

+

In order for Cylc to be able to restart workflows the +[scheduler][run hosts]available hosts must all be on a +shared filesystem.

+
+
Force Mode

If a host is suffixed with an exclamation mark then Cylc will not attempt +to automatically restart the workflow and any local jobs (running under +background or at) will be left running.

+
+
+

For example in the following configuration any workflows running on +foo will attempt to restart on pub whereas any workflows +running on bar will stop immediately, making no attempt to restart.

+
[scheduler]
+     [[run hosts]]
+         available = pub
+         condemned = foo, bar!
+
+
+
+

Warning

+

Cylc will reject hosts with ambiguous names such as localhost or +127.0.0.1 for this configuration as +[scheduler][run hosts]condemned +are evaluated on the workflow host server.

+
+

To prevent large numbers of workflows attempting to restart simultaneously the +[scheduler]auto restart delay setting defines a period +of time in seconds. +Workflows will wait for a random period of time between zero and +[scheduler]auto restart delay seconds before +attempting to stop and restart.

+

Workflows that are started up in no-detach mode cannot auto stop-restart on a +different host - as it will still end up attached to the condemned host. +Therefore, a workflow in no-detach mode running on a condemned host will abort +with a non-zero return code. The parent process should manually handle the +restart of the workflow if desired.

+
+

Python API

+

Coroutines

+ + + + + + +

auto_restart

Automatically restart the workflow if configured to do so.

+
+
+async cylc.flow.main_loop.auto_restart.auto_restart(scheduler, _)[source]
+

Automatically restart the workflow if configured to do so.

+
+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.health_check.html b/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.health_check.html new file mode 100644 index 00000000000..4d51b0ae939 --- /dev/null +++ b/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.health_check.html @@ -0,0 +1,204 @@ + + + + + + + cylc.flow.main_loop.health_check — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

cylc.flow.main_loop.health_check

+

Checks the integrity of the workflow run directory.

+
    +
  • Ensures workflow run directory is still present.

  • +
  • Ensures contact file is present and consistent with the running workflow.

  • +
+

Shuts down the workflow in the event of inconsistency or error.

+
+

Python API

+

Coroutines

+ + + + + + +

health_check

Perform workflow health checks.

+
+
+async cylc.flow.main_loop.health_check.health_check(scheduler, _)[source]
+

Perform workflow health checks.

+
+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.log_data_store.html b/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.log_data_store.html new file mode 100644 index 00000000000..57cecdc8d65 --- /dev/null +++ b/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.log_data_store.html @@ -0,0 +1,223 @@ + + + + + + + cylc.flow.main_loop.log_data_store — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

cylc.flow.main_loop.log_data_store

+

Log the number and size of each type of object in the data store.

+
+

Note

+

This plugin is for Cylc developers debugging the data store.

+
+

If matplotlib is installed this plugin will plot results as a PDF in +the run directory when the workflow is shut down (cleanly).

+
+

Python API

+

Coroutines

+ + + + + + + + + + + + +

init

Construct the initial state.

log_data_store

Count the number of objects and the data store size.

report

Dump data to JSON, attempt to plot results.

+
+
+async cylc.flow.main_loop.log_data_store.init(scheduler, state)[source]
+

Construct the initial state.

+
+ +
+
+async cylc.flow.main_loop.log_data_store.log_data_store(scheduler, state)[source]
+

Count the number of objects and the data store size.

+
+ +
+
+async cylc.flow.main_loop.log_data_store.report(scheduler, state)[source]
+

Dump data to JSON, attempt to plot results.

+
+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.log_main_loop.html b/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.log_main_loop.html new file mode 100644 index 00000000000..588a8fd5939 --- /dev/null +++ b/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.log_main_loop.html @@ -0,0 +1,215 @@ + + + + + + + cylc.flow.main_loop.log_main_loop — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

cylc.flow.main_loop.log_main_loop

+

Main loop plugin for monitoring main loop plugins.

+
+

Note

+

This plugin is for Cylc developers debugging main loop operations.

+
+

If matplotlib is installed this plugin will plot results as a PDF in +the run directory when the workflow is shut down (cleanly).

+
+

Python API

+

Coroutines

+ + + + + + + + + +

init

Override default queue length of 1.

report

Extract plugin function timings.

+
+
+async cylc.flow.main_loop.log_main_loop.init(scheduler, _)[source]
+

Override default queue length of 1.

+

This allows timings to accumulate, normally only the most recent is kept.

+
+ +
+
+async cylc.flow.main_loop.log_main_loop.report(scheduler, _)[source]
+

Extract plugin function timings.

+
+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.log_memory.html b/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.log_memory.html new file mode 100644 index 00000000000..23e561d7412 --- /dev/null +++ b/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.log_memory.html @@ -0,0 +1,241 @@ + + + + + + + cylc.flow.main_loop.log_memory — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

cylc.flow.main_loop.log_memory

+

Log the memory usage of a running scheduler over time.

+
+

Note

+

This plugin is for Cylc developers debugging cylc memory usage.

+

For general interest memory measurement try +/usr/bin/time -v cylc play or cylc play --profile.

+
+
+

Note

+

Pympler associates memory with the first object which references it.

+

In Cylc we have some objects (e.g. the configuration) which are references +from multiple places.

+

This can result in a certain amount of “jitter” in the results where +pympler has swapper from associating memory with one object to another.

+

Watch out for matching increase/decrease in reported memory in +different objects.

+
+
+

Warning

+

This plugin can slow down a workflow significantly due to the +complexity of memory calculations.

+

Set a sensible interval before running workflows.

+
+

If matplotlib is installed this plugin will plot results as a PDF in +the run directory when the workflow is shut down (cleanly).

+
+

Python API

+

Coroutines

+ + + + + + + + + + + + +

init

Take an initial memory snapshot.

report

Take a final memory snapshot and dump the results.

take_snapshot

Take a memory snapshot

+
+
+async cylc.flow.main_loop.log_memory.init(scheduler, state)[source]
+

Take an initial memory snapshot.

+
+ +
+
+async cylc.flow.main_loop.log_memory.report(scheduler, state)[source]
+

Take a final memory snapshot and dump the results.

+
+ +
+
+async cylc.flow.main_loop.log_memory.take_snapshot(scheduler, state)[source]
+

Take a memory snapshot

+
+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.reset_bad_hosts.html b/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.reset_bad_hosts.html new file mode 100644 index 00000000000..e1dd92f27a3 --- /dev/null +++ b/nightly_8.4/html/plugins/main-loop/built-in/cylc.flow.main_loop.reset_bad_hosts.html @@ -0,0 +1,208 @@ + + + + + + + cylc.flow.main_loop.reset_bad_hosts — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

cylc.flow.main_loop.reset_bad_hosts

+

Resets the list of bad hosts.

+

The scheduler stores a set of hosts which it has been unable to contact to +save contacting these hosts again.

+

This list is cleared if a task cannot be submitted because all of the hosts it +might use cannot be reached.

+

If a task succeeds in submitting a job on the second host it tries, then the +first host remains in the set of unreachable (bad) hosts, even though the +failure might have been transitory. For this reason, this plugin periodically +clears the set.

+

Suggested interval - an hour.

+
+

Python API

+

Coroutines

+ + + + + + +

reset_bad_hosts

Empty bad_hosts.

+
+
+async cylc.flow.main_loop.reset_bad_hosts.reset_bad_hosts(scheduler, _)[source]
+

Empty bad_hosts.

+
+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/plugins/main-loop/index.html b/nightly_8.4/html/plugins/main-loop/index.html new file mode 100644 index 00000000000..6eab0cabd64 --- /dev/null +++ b/nightly_8.4/html/plugins/main-loop/index.html @@ -0,0 +1,367 @@ + + + + + + + Main Loop Plugins — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Main Loop Plugins

+

Plugins for running Python code inside of the Cylc scheduler.

+
+

Built In Plugins

+

Cylc Flow provides the following plugins:

+ + + + + + + + + + + + + + + + + + + + + +

cylc.flow.main_loop.auto_restart

Automatically restart workflows if they are running on bad servers.

cylc.flow.main_loop.health_check

Checks the integrity of the workflow run directory.

cylc.flow.main_loop.log_data_store

Log the number and size of each type of object in the data store.

cylc.flow.main_loop.log_main_loop

Main loop plugin for monitoring main loop plugins.

cylc.flow.main_loop.log_memory

Log the memory usage of a running scheduler over time.

cylc.flow.main_loop.reset_bad_hosts

Resets the list of bad hosts.

+
+
+

Configuring

+

Main loop plugins can be activated either by:

+
    +
  • Using the --main-loop option with cylc play e.g:

    +
    $ # run a workflow using the "health check" and "auto restart" plugins:
    +$ cylc play my-workflow --main-loop 'health check' --main-loop 'auto restart'
    +
    +
    +
  • +
  • Adding them to the default list of plugins in +global.cylc[scheduler][main loop]plugins e.g:

    +
    [scheduler]
    +    [[main loop]]
    +        plugins = health check, auto restart
    +
    +
    +
  • +
+

Main loop plugins can be individually configured in their +global.cylc[scheduler][main loop][<plugin name>] section e.g:

+
[scheduler]
+    [[main loop]]
+        [[[health check]]]
+            interval = PT5M  # perform check every 5 minutes
+
+
+
+
+

Developing Main Loop Plugins

+

Main loop plugins are Python modules containing asynchronous function(s) +(sometimes referred to as coroutines) which Cylc Flow executes within the +scheduler.

+
+

Hello World

+

Here is the “hello world” of main loop plugins:

+
+
my_plugin.py
+
from cylc.flow import LOG
+from cylc.flow.main_loop import startup
+
+@startup
+async def my_startup_coroutine(schd, state):
+   # write Hello <workflow name> to the Cylc log.
+   LOG.info(f'Hello {schd.workflow}')
+
+
+
+

Plugins are registered by registering them with the cylc.main_loop +entry point:

+
+
setup.py
+
# plugins must be properly installed, in-place PYTHONPATH meddling will
+# not work.
+
+from setuptools import setup
+
+setup(
+    name='my-plugin',
+    version='1.0',
+    py_modules=['my_plugin'],
+    entry_points={
+       # register this plugin with Cylc
+       'cylc.main_loop': [
+         # name = python.namespace.of.module
+         'my_plugin=my_plugin.my_plugin'
+       ]
+    }
+)
+
+
+
+

Examples

+

For examples see the built-in plugins in the cylc.flow.main_loop +module which are registered in the Cylc Flow setup.cfg file.

+
+
+

Coroutines

+

Plugins provide asynchronous functions (coroutines) which Cylc will +then run inside the scheduler.

+

Coroutines should be fast running (read as gentle on the scheduler) +and perform IO asynchronously.

+

Coroutines shouldn’t meddle with the state of the scheduler and should be +parallel-safe with other plugins.

+
+
+

Event Types

+

Coroutines must be decorated using one of the main loop decorators. The +choice of decorator effects when the coroutine is called and what +arguments are provided to it.

+

The available event types are:

+
+
+cylc.flow.main_loop.startup(fcn)[source]
+

Decorates a coroutine which is run at workflow startup.

+

The decorated coroutine should have the signature:

+
+

async coroutine(scheduler, plugin_state) -> None

+
+

Exceptions:

+
+
    +
  • Regular Exceptions are caught and logged.

  • +
  • Exceptions which subclass CylcError are re-raised as +MainLoopPluginException

  • +
+
+
+ +
+
+cylc.flow.main_loop.shutdown(fcn)[source]
+

Decorates a coroutine which is run at workflow shutdown.

+

Note shutdown refers to “clean” shutdown as opposed to workflow abort.

+

The decorated coroutine should have the signature:

+
+

async coroutine(scheduler, plugin_state) -> None

+
+

Exceptions:

+
+
    +
  • Regular Exceptions are caught and logged.

  • +
  • Exceptions which subclass CylcError are re-raised as +MainLoopPluginException

  • +
+
+
+ +
+
+cylc.flow.main_loop.periodic(fcn)[source]
+

Decorates a coroutine which is run at a set interval.

+

The decorated coroutine should have the signature:

+
+

async coroutine(scheduler, plugin_state) -> None

+
+

Exceptions:

+
+
    +
  • Regular Exceptions are caught and logged.

  • +
  • Exceptions which subclass CylcError are re-raised as +MainLoopPluginException

  • +
+
+

Configuration:

+
+
+
+
+ +
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/plugins/xtriggers/index.html b/nightly_8.4/html/plugins/xtriggers/index.html new file mode 100644 index 00000000000..4e533026048 --- /dev/null +++ b/nightly_8.4/html/plugins/xtriggers/index.html @@ -0,0 +1,239 @@ + + + + + + + Xtrigger Plugins — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Xtrigger Plugins

+
+

Added in version 8.3: Xtrigger plugins allow you to install and use +xtriggers without them being +in <workflow-dir>/lib/python/ or $CYLC_PYTHONPATH.

+
+ +
+

Developing xtrigger plugins

+

Cylc uses the cylc.xtriggers entry point registered by setuptools to search +for xtrigger plugins. Each xtrigger is registered individually.

+
+

Example

+

Consider a package called my_package with the following structure:

+
+
my_package/foo.py
+
def foo():
+    ...
+
+def bar():
+    ...
+
+
+
+
+
my_package/baz.py
+
def baz():
+    ...
+
+
+
+

These xtriggers can be registered in the package’s setup.cfg or +pyproject.toml file.

+
+
setup.cfg
+
[options.entry_points]
+cylc.xtriggers =
+    foo = my_package.foo
+    bar = my_package.foo
+    baz = my_package.baz
+
+
+
+
+
pyproject.toml
+
[project.entry-points."cylc.xtriggers"]
+foo = "my_package.foo"
+bar = "my_package.foo"
+baz = "my_package.baz"
+
+
+
+
+

Tip

+

It is recommended to implement only one xtrigger per module. This allows +you to write a validate function for each xtrigger - see +Xtrigger Validation Functions.

+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/py-modindex.html b/nightly_8.4/html/py-modindex.html new file mode 100644 index 00000000000..0310974f10d --- /dev/null +++ b/nightly_8.4/html/py-modindex.html @@ -0,0 +1,295 @@ + + + + + + Python Module Index — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + +

Python Module Index

+ +
+ c +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ c
+ cylc +
    + cylc.flow.exceptions +
    + cylc.flow.install_plugins.log_vc_info +
    + cylc.flow.job_runner_handlers +
    + cylc.flow.job_runner_handlers.at +
    + cylc.flow.job_runner_handlers.background +
    + cylc.flow.job_runner_handlers.loadleveler +
    + cylc.flow.job_runner_handlers.lsf +
    + cylc.flow.job_runner_handlers.moab +
    + cylc.flow.job_runner_handlers.pbs +
    + cylc.flow.job_runner_handlers.sge +
    + cylc.flow.job_runner_handlers.slurm +
    + cylc.flow.job_runner_handlers.slurm_packjob +
    + cylc.flow.main_loop +
    + cylc.flow.main_loop.auto_restart +
    + cylc.flow.main_loop.health_check +
    + cylc.flow.main_loop.log_data_store +
    + cylc.flow.main_loop.log_main_loop +
    + cylc.flow.main_loop.log_memory +
    + cylc.flow.main_loop.reset_bad_hosts +
    + cylc.flow.network.scan +
    + cylc.flow.parsec.exceptions +
    + cylc.flow.scripts.lint +
    + cylc.flow.xtriggers.xrandom +
    + cylc.rose +
    + cylc.uiserver.app +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/api/exceptions.html b/nightly_8.4/html/reference/api/exceptions.html new file mode 100644 index 00000000000..d2d5d4493ed --- /dev/null +++ b/nightly_8.4/html/reference/api/exceptions.html @@ -0,0 +1,724 @@ + + + + + + + Exceptions — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Exceptions

+

Exceptions for “expected” errors.

+
+
+exception cylc.flow.exceptions.ClientError(message, traceback=None, workflow=None)[source]
+

Base class for errors raised by Cylc client instances.

+

For example, the workflow you are trying to connect to is stopped.

+
+
Parameters:
+
    +
  • message (str)

  • +
  • traceback (str | None)

  • +
  • workflow (str | None)

  • +
+
+
+
+
+message
+

The exception message.

+
+ +
+
+traceback
+

The underlying exception instance if available.

+
+ +
+
+workflow
+

The workflow ID if available.

+
+ +
+ +
+
+exception cylc.flow.exceptions.ClientTimeout(message, workflow=None)[source]
+

The scheduler did not respond within the timeout.

+

This could be due to: +* Network issues. +* Scheduler issues. +* Insufficient timeout.

+

To increase the timeout, use the --comms-timeout option.

+
+
Parameters:
+
    +
  • message (str)

  • +
  • workflow (str | None)

  • +
+
+
+
+ +
+
+exception cylc.flow.exceptions.CommandFailedError(value)[source]
+

Exception for when scheduler commands fail.

+
+
Parameters:
+

value (str | Exception)

+
+
+
+ +
+
+exception cylc.flow.exceptions.ContactFileExists[source]
+

Workflow contact file exists.

+
+ +
+
+exception cylc.flow.exceptions.CyclerTypeError(*args)[source]
+

An error raised when incompatible cycling types are wrongly mixed.

+
+ +
+
+exception cylc.flow.exceptions.CyclingError[source]
+

Base class for errors in cycling configuration.

+
+ +
+
+exception cylc.flow.exceptions.CylcConfigError[source]
+

Generic exception to handle an error in a Cylc configuration file.

+
+ +
+
+exception cylc.flow.exceptions.CylcError[source]
+

Generic exception for Cylc errors.

+

This exception is raised in-place of “expected” errors where a short +message to the user is more appropriate than traceback.

+

CLI commands will catch this exception and exit with str(exception).

+
+ +
+
+exception cylc.flow.exceptions.CylcMissingContextPointError[source]
+

An error denoting a missing (but required) context cycle point.

+
+ +
+
+exception cylc.flow.exceptions.CylcMissingFinalCyclePointError[source]
+

An error denoting a missing (but required) final cycle point.

+
+ +
+
+exception cylc.flow.exceptions.CylcTimeSyntaxError[source]
+

An error denoting invalid ISO/Cylc input syntax.

+
+ +
+
+exception cylc.flow.exceptions.CylcVersionError(version=None)[source]
+

Contact file is for a Cylc Version not supported by this script.

+
+ +
+
+exception cylc.flow.exceptions.FileRemovalError(exc)[source]
+

Exception for errors during deletion of files/directories, which are +probably the filesystem’s fault, not Cylc’s.

+
+
Parameters:
+

exc (Exception)

+
+
Return type:
+

None

+
+
+
+ +
+
+exception cylc.flow.exceptions.GlobalConfigError[source]
+

Exception for configuration errors in a Cylc global configuration.

+
+ +
+
+exception cylc.flow.exceptions.GraphParseError[source]
+

Exception for errors in Cylc workflow graphing.

+
+ +
+
+exception cylc.flow.exceptions.HostSelectException(data)[source]
+

No hosts could be selected from the provided configuration.

+
+
Parameters:
+

data (Dict[str, dict])

+
+
+
+
+get_hint()[source]
+

Return a hint to explain this error for certain cases.

+
+ +
+ +
+
+exception cylc.flow.exceptions.InputError[source]
+

Exception covering erroneous user input to a Cylc interface.

+

Ideally this would be handled in the interface (e.g. argument parser). +If this isn’t possible raise InputError.

+
+ +
+
+exception cylc.flow.exceptions.IntervalParsingError(*args)[source]
+

An error raised when an interval has an incorrect value.

+
+ +
+
+exception cylc.flow.exceptions.InvalidCompletionExpression(message, expr=None)[source]
+

For the [runtime][<namespace>]completion configuration.

+

Raised when non-whitelisted syntax is present.

+
+ +
+
+exception cylc.flow.exceptions.NoHostsError(platform)[source]
+

None of the hosts of a given platform were reachable.

+
+ +
+
+exception cylc.flow.exceptions.NoPlatformsError(identity, hosts_consumed, set_type='group', place='')[source]
+

None of the platforms of a given set were reachable.

+
+
Parameters:
+
    +
  • identity (str) – The name of the platform group or install target.

  • +
  • set_type (str) – Whether the set of platforms is a platform group or an install +target.

  • +
  • place (str) – Where the attempt to get the platform failed.

  • +
  • hosts_consumed (Set[str])

  • +
+
+
+
+ +
+
+exception cylc.flow.exceptions.ParamExpandError[source]
+

Exception for errors in Cylc parameter expansion.

+
+ +
+
+exception cylc.flow.exceptions.PlatformError(message, platform_name, *, ctx=None, cmd=None, ret_code=None, out=None, err=None)[source]
+

Error in the management of a remote platform.

+

If the exception represents a command failure, provide either the ctx OR +manually populate the remaining kwargs. Otherwise leave the kwargs blank.

+
+
Parameters:
+
    +
  • message (str) – Short description.

  • +
  • platform_name (str) – Name of the platform.

  • +
  • ctx (Optional[SubFuncContext]) – SubFuncContext object if available. +The other kwargs are derived from this.

  • +
  • cmd (str | Sequence[str] | None) – The remote command.

  • +
  • ret_code (int | None) – The command’s return code.

  • +
  • out (str | None) – The command’s stdout.

  • +
  • err (str | None) – The command’s stderr.

  • +
+
+
Return type:
+

None

+
+
+
+ +
+
+exception cylc.flow.exceptions.PlatformLookupError[source]
+

Unable to determine the correct job platform from the information +given

+
+ +
+
+exception cylc.flow.exceptions.PluginError(entry_point, plugin_name, exc)[source]
+

Represents an error arising from a Cylc plugin.

+
+
Parameters:
+
    +
  • entry_point (str) – The plugin entry point as defined in setup.cfg +(e.g. ‘cylc.main_loop’)

  • +
  • plugin_name (str) – Name of the plugin

  • +
  • exc (Exception) – Original exception caught when trying to run the plugin

  • +
+
+
+
+ +
+
+exception cylc.flow.exceptions.PointParsingError(*args)[source]
+

An error raised when a point has an incorrect value.

+
+ +
+
+exception cylc.flow.exceptions.SequenceDegenerateError(*args)[source]
+

An error raised when adjacent points on a sequence are equal.

+
+ +
+
+exception cylc.flow.exceptions.SequenceParsingError[source]
+

Error on parsing an invalid sequence.

+
+ +
+
+exception cylc.flow.exceptions.ServiceFileError[source]
+

Exception for errors related to workflow service files.

+
+ +
+
+exception cylc.flow.exceptions.TaskDefError[source]
+

Exception raise for errors in TaskDef initialization.

+
+ +
+
+exception cylc.flow.exceptions.TaskProxySequenceBoundsError(msg)[source]
+

Error on TaskProxy.__init__ with out of sequence bounds start point.

+
+ +
+
+exception cylc.flow.exceptions.TriggerExpressionError[source]
+

Trigger expression syntax issue.

+
+ +
+
+exception cylc.flow.exceptions.WorkflowConfigError[source]
+

Exception for configuration errors in a Cylc workflow configuration.

+
+ +
+
+exception cylc.flow.exceptions.WorkflowEventError[source]
+

Exception for errors in Cylc event handlers.

+
+ +
+
+exception cylc.flow.exceptions.WorkflowFilesError[source]
+

Exception for errors related to workflow files/directories.

+
+ +
+
+exception cylc.flow.exceptions.WorkflowStopped(workflow)[source]
+

The Cylc scheduler you attempted to connect to is stopped.

+
+ +
+
+exception cylc.flow.exceptions.XtriggerConfigError(label, func, message)[source]
+

An error in an xtrigger.

+

For example:

+
    +
  • If the function module was not found.

  • +
  • If the function was not found in the xtrigger module.

  • +
  • If the function is not callable.

  • +
  • If any string template in the function context +arguments are not present in the expected template values.

  • +
+
+
Parameters:
+
+
+
+
+ +
+
+exception cylc.flow.parsec.exceptions.EmPyError(reason, index=None, line=None, lines=None, err_type=None, fpath=None, help_lines=None)[source]
+

Wrapper class for EmPy exceptions.

+
+
Parameters:
+
+
+
+
+ +
+
+exception cylc.flow.parsec.exceptions.FileParseError(reason, index=None, line=None, lines=None, err_type=None, fpath=None, help_lines=None)[source]
+

Error raised when attempting to read in the config file(s).

+
+
Parameters:
+
    +
  • reason (str) – Description of error.

  • +
  • err_type (str | None) – Classification of error (e.g. Jinja2Error).

  • +
  • help_lines (Iterable[str] | None) – Additional info to include in the exception.

  • +
  • lines (Dict[str, List[str]] | None) – (preferred) Dictionary in the format +{filename: [context_line, …, error_line]}

  • +
  • index (int | None) – The line number of the error in the config (counting from the +shebang line not the first line).

  • +
  • line (str | None) – The line of the error in the config.

  • +
  • fpath (str | None) – The path to the file containing the error.

  • +
+
+
+
+ +
+
+exception cylc.flow.parsec.exceptions.IllegalItemError(keys, key, msg=None, exc=None)[source]
+

Bad setting section or option name.

+
+ +
+
+exception cylc.flow.parsec.exceptions.IllegalValueError(vtype, keys, value, exc=None, msg=None)[source]
+

Bad setting value.

+
+ +
+
+exception cylc.flow.parsec.exceptions.IncludeFileNotFoundError(flist)[source]
+

Error raised for missing include files.

+
+ +
+
+exception cylc.flow.parsec.exceptions.InvalidConfigError(item, specname)[source]
+

Error raised for missing configuration items.

+
+ +
+
+exception cylc.flow.parsec.exceptions.ItemNotFoundError(item)[source]
+

Error raised for missing configuration items.

+
+ +
+
+exception cylc.flow.parsec.exceptions.Jinja2Error(exception, lines=None, filename=None)[source]
+

Wrapper class for Jinja2 exceptions.

+
+
Parameters:
+
    +
  • exception (Exception) – The exception being re-raised

  • +
  • lines (Dict[str, List[str]] | None) – Dictionary in the format +{filename: [context_line, …, error_line]}

  • +
  • filename (str | None) – Alternative to “lines” where less detail is available.

  • +
+
+
+
+ +
+
+exception cylc.flow.parsec.exceptions.ListValueError(keys, value, msg=None, exc=None)[source]
+

Bad setting value, for a comma separated list.

+
+ +
+
+exception cylc.flow.parsec.exceptions.NotSingleItemError(item)[source]
+

Error raised if an iterable is given where an item is expected.

+
+ +
+
+exception cylc.flow.parsec.exceptions.ParsecError[source]
+

Generic exception for Parsec errors.

+
+
+schd_expected: bool = False
+

Set this flag to True on the exception if it is anticipated during +Cylc Scheduler run (apart from loading of config we do not expect +ParsecErrors during runtime).

+
+ +
+ +
+
+exception cylc.flow.parsec.exceptions.TemplateVarLanguageClash(reason, index=None, line=None, lines=None, err_type=None, fpath=None, help_lines=None)[source]
+

Multiple workflow configuration templating engines configured.

+
+
Parameters:
+
+
+
+
+ +
+
+exception cylc.flow.parsec.exceptions.UpgradeError[source]
+

Error raised upon fault in an upgrade operation.

+
+ +
+
+exception cylc.flow.parsec.exceptions.ValidationError(keys, value=None, msg=None, exc=None, vtype=None, key=None)[source]
+

Generic exception for invalid configurations.

+
+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/api/index.html b/nightly_8.4/html/reference/api/index.html new file mode 100644 index 00000000000..acbe9b1317f --- /dev/null +++ b/nightly_8.4/html/reference/api/index.html @@ -0,0 +1,249 @@ + + + + + + + Cylc API — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/api/scan.html b/nightly_8.4/html/reference/api/scan.html new file mode 100644 index 00000000000..7e8098608de --- /dev/null +++ b/nightly_8.4/html/reference/api/scan.html @@ -0,0 +1,386 @@ + + + + + + + Scan API — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Scan API

+

Functionality for searching for workflows running as the current user.

+

The scan() asynchronous generator yields workflows. Iterate +over them using an async for statement:

+
async for flow in scan():
+    print(flow['name'])
+
+
+

For further functionality construct a pipe:

+
pipe = scan | is_active(True) | contact_info
+async for flow in pipe:
+    print(f'{flow["name"]} {flow["CYLC_WORKFLOW_HOST"]}')
+
+
+

There are filters which you can you to omit workflows e.g. +cylc_version() and transformers which acquire more information +e.g. contact_info().

+
+
+cylc.flow.network.scan.scan(run_dir=None, scan_dir=None, max_depth=None)
+

List flows installed on the filesystem.

+
+
Parameters:
+
    +
  • run_dir (Path | None) –

    The run dir to look for workflows in, defaults to ~/cylc-run.

    +

    All workflow registrations will be given relative to this path.

    +

  • +
  • scan_dir (Path | None) –

    The directory to scan for workflows in.

    +

    Use in combination with run_dir if you want to scan a subdir +within the run_dir.

    +

  • +
  • max_depth (int | None) –

    The maximum number of levels to descend before bailing.

    +
      +
    • max_depth=1 will pick up top-level workflows (e.g. foo).

    • +
    • max_depth=2 will pick up nested workflows (e.g. foo/bar).

    • +
    +

  • +
+
+
Yields:
+

dict - Dictionary containing information about the flow.

+
+
Return type:
+

AsyncGenerator[Dict[str, Path | str], None]

+
+
+
+ +
+
+cylc.flow.network.scan.filter_name(flow, pattern)
+

Filter flows by name.

+
+
Parameters:
+
    +
  • flow (dict) – Flow information dictionary, provided by scan through the pipe.

  • +
  • pattern (re.Pattern) – One or more regex patterns as strings. +This will return True if any of the patterns match.

  • +
+
+
+
+ +
+
+cylc.flow.network.scan.is_active(flow, is_active)
+

Filter flows by the presence of a contact file.

+
+
Parameters:
+
    +
  • flow (dict) – Flow information dictionary, provided by scan through the pipe.

  • +
  • is_active (bool) – True to filter for running flows. +False to filter for stopped and unregistered flows.

  • +
+
+
+
+ +
+
+cylc.flow.network.scan.contact_info(flow)
+

Read information from the contact file.

+
+
Requires:
    +
  • is_active(True)

  • +
+
+
+
+
Parameters:
+

flow (dict) – Flow information dictionary, provided by scan through the pipe.

+
+
+
+ +
+
+cylc.flow.network.scan.cylc_version(flow, requirement)
+

Filter by cylc version.

+
+
Requires:
    +
  • is_active(True)

  • +
  • contact_info

  • +
+
+
+
+
Parameters:
+
    +
  • flow (dict) – Flow information dictionary, provided by scan through the pipe.

  • +
  • requirement (str) – Requirement specifier in PEP 440 format e.g. > 8, < 9

  • +
+
+
+
+ +
+
+cylc.flow.network.scan.api_version(flow, requirement)
+

Filter by the cylc API version.

+
+
Requires:
    +
  • is_active(True)

  • +
  • contact_info

  • +
+
+
+
+
Parameters:
+
    +
  • flow (dict) – Flow information dictionary, provided by scan through the pipe.

  • +
  • requirement (str) – Requirement specifier in PEP 440 format e.g. > 8, < 9

  • +
+
+
+
+ +
+
+cylc.flow.network.scan.graphql_query(flow, fields, filters=None)
+

Obtain information from a GraphQL request to the flow.

+
+
Requires:
    +
  • is_active(True)

  • +
  • contact_info

  • +
+
+
+
+
Parameters:
+
    +
  • flow (dict) – Flow information dictionary, provided by scan through the pipe.

  • +
  • fields (Iterable) –

    Iterable containing the fields to request e.g:

    +
    ['id', 'name']
    +
    +
    +

    One level of nesting is supported e.g:

    +
    {'name': None, 'meta': ['title']}
    +
    +
    +

  • +
  • filters (list) –

    Filter by the data returned from the query. +List in the form [(key, ...), value], e.g:

    +
    # state must be running
    +[('state',), 'running']
    +
    +# state must be running or paused
    +[('state',), ('running', 'paused')]
    +
    +
    +

  • +
+
+
+
+ +
+
+cylc.flow.network.scan.title(flow)
+

Attempt to parse the workflow title out of the flow config file.

+
+

Warning

+

This uses a fast but dumb method which may fail to extract the workflow +title.

+

Obtaining the workflow title via graphql_query() is preferable +for running flows.

+
+
+ +
+
+cylc.flow.network.scan.workflow_params(flow)
+

Extract workflow parameter entries from the workflow database.

+
+
Requires:
    +
  • is_active(True)

  • +
+
+
+
+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/api/zmq.html b/nightly_8.4/html/reference/api/zmq.html new file mode 100644 index 00000000000..0c95beb14cf --- /dev/null +++ b/nightly_8.4/html/reference/api/zmq.html @@ -0,0 +1,533 @@ + + + + + + + Workflow Runtime Interface — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Workflow Runtime Interface

+

Cylc workflows are TCP servers which use the ZeroMQ protocol to communicate with +clients and jobs.

+

Cylc provides a Python client to communicate with this server +cylc.flow.network.client.WorkflowRuntimeClient

+
>>> from cylc.flow.network.client import WorkflowRuntimeClient
+>>> client = WorkflowRuntimeClient('my-workflow')
+>>> client('ping_workflow')
+True
+
+
+

Cylc also provides sub-command called cylc client which is a simple +wrapper of the Python client.

+
$ cylc client generic ping_workflow -n
+true
+
+
+

The available “commands” or (“endpoints”) are contained in +cylc.flow.network.server.WorkflowRuntimeServer class.

+
+

Client

+
+
+class cylc.flow.network.client.WorkflowRuntimeClient(workflow, host=None, port=None, timeout=None, context=None, srv_public_key_loc=None)[source]
+

Initiate a client to the scheduler API.

+

Initiates the REQ part of a ZMQ REQ-REP pair.

+

This class contains the logic for the ZMQ message interface and client - +server communication.

+

Determine host and port from the contact file unless provided.

+

If there is no socket bound to the specified host/port the client will +bail after timeout seconds.

+
+
Parameters:
+
    +
  • workflow (str) – Name of the workflow to connect to.

  • +
  • timeout (float | str | None) – Set the default timeout in seconds. The default is +ZMQClient.DEFAULT_TIMEOUT. +Note the default timeout can be overridden for individual requests.

  • +
  • host (str | None) –

    The host where the flow is running if known.

    +

    If both host and port are provided it is not necessary to load +the contact file.

    +

  • +
  • port (int | str | None) –

    The port on which the REQ-REP TCP server is listening.

    +

    If both host and port are provided it is not necessary to load +the contact file.

    +

  • +
  • context (Context | None)

  • +
  • srv_public_key_loc (str | None)

  • +
+
+
+
+
+host
+

Workflow host name.

+
+ +
+
+port
+

Workflow host port.

+
+ +
+
+timeout_handler
+

Optional function which runs before ClientTimeout is raised. +This provides an interface for raising more specific exceptions in +the event of a communication timeout.

+
+ +
+
+header
+

Request “header” data to attach to each request.

+
+ +
+
Usage:

Call endpoints using ZMQClient.__call__.

+
+
Message interface:
    +
  • Accepts responses of the format: {“data”: {…}}

  • +
  • Accepts error in the format: {“error”: {“message”: MSG}}

  • +
  • Returns requests of the format: {“command”: CMD, +“args”: {…}}

  • +
+
+
+
+
Raises:
+

WorkflowStopped – if the workflow is not running.

+
+
Parameters:
+
    +
  • workflow (str)

  • +
  • host (str | None)

  • +
  • port (int | str | None)

  • +
  • timeout (float | str | None)

  • +
  • context (Context | None)

  • +
  • srv_public_key_loc (str | None)

  • +
+
+
+
+
Call server “endpoints” using:
+
__call__, serial_request
+
+serial_request(command, args=None, timeout=None, req_meta=None)
+

Send a request.

+

For convenience use __call__ to call this method.

+
+
Parameters:
+
    +
  • command (str) – The name of the endpoint to call.

  • +
  • args (Dict[str, Any] | None) – Arguments to pass to the endpoint function.

  • +
  • timeout (float | None) – Override the default timeout (seconds).

  • +
  • req_meta (Dict[str, Any] | None)

  • +
+
+
Raises:
+
    +
  • ClientTimeout – If a response takes longer than timeout to arrive.

  • +
  • ClientError – Coverall for all other issues including failed auth.

  • +
+
+
Returns:
+

+
The data exactly as returned from the endpoint function,

nothing more, nothing less.

+
+
+

+
+
Return type:
+

object

+
+
+
+ +
+
async_request
+
+async async_request(command, args=None, timeout=None, req_meta=None)[source]
+

Send an asynchronous request using asyncio.

+

Has the same arguments and return values as serial_request.

+
+
Parameters:
+
+
+
Return type:
+

object

+
+
+
+ +
+
+
+
+
+ +
+
+

Server

+
+
+class cylc.flow.network.server.WorkflowRuntimeServer(schd)[source]
+

Workflow runtime service API facade exposed via zmq.

+

This class starts and coordinates the publisher and replier, and +contains the Cylc endpoints invoked by the receiver to provide a response +to incoming messages.

+
+
Parameters:
+

schd (object) – The parent object instantiating the server. In +this case, the workflow scheduler.

+
+
+
+
Usage:
    +
  • Define endpoints using the expose decorator.

  • +
  • Endpoints are called via the receiver using the function name.

  • +
+
+
Message interface:
    +
  • Accepts messages of the format: {“command”: CMD, “args”: {…}}

  • +
  • Returns responses of the format: {“data”: {…}}

  • +
  • Returns error in the format: {“error”: {“message”: MSG}}

  • +
+
+
Common Arguments:

Arguments which are shared between multiple commands.

+
+
task identifier (str):

A task identifier in the format cycle-point/task-name +e.g. 1/foo or 20000101T0000Z/bar.

+
+
+
+
task globs (list):

A list of Cylc IDs relative to the workflow.

+
    +
  • 1 - The cycle point “1”.

  • +
  • 1/foo - The task “foo” in the cycle “1”.

  • +
  • 1/foo/01 - The first job of the task “foo” from the cycle +“1”.

  • +
+

Glob-like patterns may be used to match multiple items e.g.

+
+
*

Matches everything.

+
+
1/*

Matches everything in cycle 1.

+
+
*/*:failed

Matches all failed tasks.

+
+
+
+
+
+
+
+
+api(endpoint=None, **_kwargs)[source]
+

Return information about this API.

+

Returns a list of callable endpoints.

+
+
Parameters:
+

endpoint (str | None) – If specified the documentation for the endpoint +will be returned instead.

+
+
Returns:
+

List of endpoints or string documentation of the +requested endpoint.

+
+
Return type:
+

str | List[str]

+
+
+
+ +
+
+graphql(request_string=None, variables=None, meta=None)[source]
+

Return the GraphQL schema execution result.

+
+
Parameters:
+
    +
  • request_string (str | None) – GraphQL request passed to Graphene.

  • +
  • variables (Dict[str, Any] | None) – Dict of variables passed to Graphene.

  • +
  • meta (Dict[str, Any] | None) – Dict containing auth user etc.

  • +
+
+
Returns:
+

Execution result, or a list with errors.

+
+
Return type:
+

object

+
+
+
+ +
+
+operate()[source]
+

Orchestrate the receive, send, publish of messages.

+
+
Return type:
+

None

+
+
+
+ +
+
+pb_data_elements(element_type, **_kwargs)[source]
+

Send the specified data elements in delta form.

+
+
Parameters:
+

element_type (str) – Key from DELTAS_MAP dictionary.

+
+
Return type:
+

bytes

+
+
+

Returns serialised Protobuf message

+
+ +
+
+pb_entire_workflow(**_kwargs)[source]
+

Send the entire data-store in a single Protobuf message.

+

Returns serialised Protobuf message

+
+
Return type:
+

bytes

+
+
+
+ +
+
+async publish_queued_items()[source]
+

Publish all queued items.

+
+
Return type:
+

None

+
+
+
+ +
+
+receiver(message)[source]
+

Process incoming messages and coordinate response.

+

Wrap incoming messages, dispatch them to exposed methods and/or +coordinate a publishing stream.

+
+
Parameters:
+

message (dict) – message contents

+
+
+
+ +
+
+register_endpoints()[source]
+

Register all exposed methods.

+
+ +
+
+start(barrier)[source]
+

Start the TCP servers.

+
+ +
+
+async stop(reason)[source]
+

Stop the TCP servers, and clean up authentication.

+

This method must be called/awaited from a different thread to the +server’s self.thread in order to interrupt the self.operate() loop +and wait for self.thread to terminate.

+
+
Parameters:
+

reason (BaseException | str)

+
+
Return type:
+

None

+
+
+
+ +
+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/architecture/data-flow.html b/nightly_8.4/html/reference/architecture/data-flow.html new file mode 100644 index 00000000000..f5a4850eb19 --- /dev/null +++ b/nightly_8.4/html/reference/architecture/data-flow.html @@ -0,0 +1,342 @@ + + + + + + + Data Flow — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Data Flow

+

This section looks at how Cylc synchronises data between its different +components, the transports, security and formats used to do so.

+
+

digraph _ { +Jobs -> Scheduler [label=" ZMQ\n GraphQL\n (default)"] + +Scheduler -> UIS [label=" ZMQ\n GraphQL (control)\n Protobuf (data)"] + +UIS -> UI [label=" Websocket\n GraphQL"] +}

+
+
+

Protocols, Transport & Security

+

Cylc uses the following schemes for data and control:

+
+

ZMQ (Over TCP)

+

Cylc uses ZMQ over TCP for most server side interaction.

+

All ZMQ connections are secured by CurveZMQ which uses security keys +which are stored on the filesystem with appropriate permissions.

+

Where remote communication is involved Cylc synchronises the relevant keys +to the appropriate platforms.

+

For more information on the key files see Authentication Files.

+
+
+

SSH

+

SSH connections are used for some purposes such as installing the key files +required for ZMQ (Over TCP) transport.

+
+
+

HTTPS (Hypertext Transfer Protocol Secure)

+

HTTPS connections are used in the browser-based Cylc UI. The certificate +used must be configured with the Cylc UI Server / Jupyter Server.

+
+
+

WSS (WebSocket Secure)

+

Websocket connections are used in the browser-based Cylc UI. These +connections are upgraded from HTTPS connections and share the same security.

+
+
+
+

Formats

+

Cylc uses the following transports to communicate over these protocols.

+
+

Protobuf

+

Protobuf is both a storage utility and transport.

+

Protobuf is used for internal data stores and the synchronisation of those data +stores.

+
+
+

GraphQL

+

GraphQL is a query language which is intended to be the user-facing +data and control interface for Cylc workflows.

+

It contains both data and mutations (actions) defined by a self-documenting +schema.

+

The GraphQL servers get their data from Protobuf data stores.

+
+
+
+

Component Interactions

+

Here are some additional details on how the components interact.

+
+

Job -> Scheduler

+
+
Default Protocol:
+

ZMQ (Over TCP)

+
+
Format:
+

GraphQL

+
+
+

Jobs can communicate status updates back to the Scheduler using different +methods. The method used is configured on a per-platform basis by the +global.cylc[platforms][<platform name>]communication method.

+
+
+

Client -> Scheduler

+
+
Protocol:
+

ZMQ (Over TCP)

+
+
Format:
+

Protobuf

+
+
+

The subcommands in the Cylc command line interface map onto GraphQL +mutations.

+

Mutations are issued through ZMQ connections.

+
+
+

Scheduler -> UI Server

+
+
Protocol:
+

ZMQ (Over TCP)

+
+
Formats:
+

Protobuf (data) and GraphQL (control)

+
+
+

The Scheduler maintains an in-memory Protobuf data store which is +backed up by a SQLite3 database.

+

The database provides crash resilience and restart capability.

+

The UI Server also maintains an in-memory Protobuf data store containing +relevant data for the workflows it is actively monitoring.

+

The synchronisation of the Scheduler and UI Server data stores is +done using one ZMQ (Over TCP) connection per Scheduler.

+

The Schedulers that the UI Server connects to are +determined by the active subscriptions registered. If there are no active +subscriptions the UI Server will have no active Scheduler +connections.

+
+
+

UI Server -> UI

+
+
Protocols:
+

WSS (WebSocket Secure), HTTPS (Hypertext Transfer Protocol Secure)

+
+
Format:
+

GraphQL

+
+
+

Most UI functionality involves subscribing to “delta” updates. For these +subscriptions the UI Server sends only the added/removed/updated data +(a delta) to the UI enabling it to update its internal data store.

+

The UI maintains a flat “lookup” which contains all objects in the store +indexed by their ID. It also maintains a “tree” which contains references +to the data in the “lookup” (but does not duplicate it) which it holds in a +hierarchical structure more suitable for presentation purposes.

+

The Cylc Web UI uses Apollo Client to handle GraphQL requests. +It will have one WebSocket per user session.

+
+../../_images/websocket-communication.png +
+

Every message received by the server is added to a queue, and processed +by the server as soon as possible.

+

It uses the Cylc UI Server schema and resolvers to validate the +query and to fetch data from the data store for the query response.

+

The query result is then serialized as JSON and sent back to the client. +The work of the Apollo Client ends after it pushes the data to the Vuex +store.

+

The communication between client and server follows a protocol +called graphql-ws protocol.

+
+../../_images/websocket-graphql-ws-protocol.png +
+

After a channel between client and server is open, the messages +follow that protocol, starting by the connection init message, +that simply expects an ack message back from the server, +where the ack is an acknowledgement to the client - note +that the protocol does not define an ack as a MUST, but +rather as a MAY, so a client may interpret not receiving an +error as an acknowledgement to proceed as well.

+

The next message will be a start, which will contain the +GraphQL query subscription. If there were no errors, the client and +server subscription is established, and the client will start +receiving the GraphQL responses.

+

The protocol also supports other messages, such as stop, to +tell the server it doesn’t need to send any more data as that +subscription is now cancelled.

+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/architecture/index.html b/nightly_8.4/html/reference/architecture/index.html new file mode 100644 index 00000000000..a00215e5251 --- /dev/null +++ b/nightly_8.4/html/reference/architecture/index.html @@ -0,0 +1,248 @@ + + + + + + + Architecture — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Architecture

+

This section provides an in-depth explanation of the architecture of the +Cylc components intended for developers and system administrators.

+

The main Cylc 8 system components are:

+
+

Cylc Scheduler

+
    +
  • The workflow engine core, Python 3 based

  • +
  • Includes the CLI (Command Line Interface)

  • +
  • And TUI, a new Terminal UI application

  • +
+
+
+

Cylc UI

+
    +
  • In-browser web UI, includes:

  • +
  • A dashboard with summary information and documentation links

  • +
  • Integrated gscan (multi-workflow) side-panel

  • +
  • Responsive web design (from desktop to table to mobile)

  • +
  • Tabbed interface to display multiple workflow views

  • +
  • Command integration for interacting with task, jobs, and schedulers

  • +
+
+
+

Cylc UI Server

+
    +
  • Interacts with Schedulers and the filesystem

  • +
  • Serves the UI to users

  • +
  • Can be launched by the privileged Hub, for multi-user installations

  • +
  • Or run standalone for use by a single user

  • +
  • (The UI Server is a Jupyter Server extension)

  • +
+
+
+

Cylc Hub

+
    +
  • For proving the UI in multi-user setups.

  • +
  • Authenticates users, spawns and proxies Cylc UI Servers

  • +
  • Can run as a regular or privileged user

  • +
  • (The Hub is a Jupyterhub instance)

  • +
+
+
+

Network layers

+
    +
  • Incremental push updates (c.f. polled full-state updates in Cylc 7)

  • +
+
+
+

Further Reading

+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/architecture/ui-server.html b/nightly_8.4/html/reference/architecture/ui-server.html new file mode 100644 index 00000000000..3a2dbe869bf --- /dev/null +++ b/nightly_8.4/html/reference/architecture/ui-server.html @@ -0,0 +1,256 @@ + + + + + + + Cylc UI Server — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Cylc UI Server

+
+
Cylc Flow

Provides a command line utility for monitoring and controlling +Cylc workflows called cylc tui.

+
+
Cylc UI Server

Provides a graphical utility for use in a web browser.

+
+
+

The Cylc UI Server connects to running workflows to provide “live” data +and accesses workflow databases and the filesystem to provide “offline” data.

+
+

Jupyter Server

+

The Cylc UI Server is a Jupyter Server extension like Jupyter Lab.

+

Jupyter Server provides the web server infrastructure which is shared by +its extensions which can used to run multiple extensions simultaneously.

+

If desired other extensions (e.g. Jupyter Lab) can be installed and +configured to run in the same server as the Cylc UI Server.

+

See Managing multiple extensions for details on managing which +extensions are run by Jupyter Server.

+

Jupyter Server can be run in two ways, single-user (token authenticated) +and multi-user (hub authenticated).

+
+
+

Single-User Mode

+

In single-user mode users must start their own UI Servers from the command line.

+

Jupyter Server will provide them with a URL to access their server including +a secure token which provides authentication.

+
+

Authentication Overview

+

See Security in the Jupyter Server:

+
+

Users can only monitor and control their own workflows.

+../../_images/gui-arch-single-user.svg +
+
+

Jupyter Hub

+

Jupyter Hub is a multi-user server which spawns and manages a configured +service for authenticated users.

+

The “Cylc Hub” is a Jupyter Hub instance which is pre-configured to spawn +Cylc UI Servers, launched by the cylc hub command. +It is also possible to configure Jupyter Hub yourself, see the Cylc Hub +configuration file for more information.

+

Jupyter Hub supports a variety of different implementations and plugin interfaces +for:

+ +
+
+

Multi-User Mode

+

Multi-user mode requires Jupyter Hub to be installed.

+

An administrator must start Jupyter Hub under a user account with +the required privileges to spawn UI Servers on behalf of the user.

+

Users then visit Jupyter Hub where they authenticate. Jupyter Hub +spawns UI Servers on behalf of users and provides each with a fixed URL +(derived from the user name) using the configured proxy +(usually Configurable HTTP Proxy).

+

Users can access each other’s UI Servers providing they have been granted +permission.

+

Authentication is provided by either Jupyter Server or Jupyter Hub.

+

Authorization in the Cylc UI Server is provided by Cylc. In +multi-user mode this allows users to connect to each other’s UI Servers for +monitoring or control purposes.

+

For more information on security and configuration see +Authorizing Others to Access Your Workflows.

+

For information on the architecture of Jupyter Hub and the +Configurable HTTP Proxy see the Jupyter Hub technical overview.

+
+

Authentication Overview

+

See Security In Jupyter Hub.

+
+../../_images/gui-arch-multi-user.svg +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/changes.html b/nightly_8.4/html/reference/changes.html new file mode 100644 index 00000000000..de9d991fd59 --- /dev/null +++ b/nightly_8.4/html/reference/changes.html @@ -0,0 +1,578 @@ + + + + + + + Changes — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Changes

+

This page contains a summary of significant changes across all Cylc components for each +release.

+

For more detail see the component changelogs:

+ +
+
+

Cylc 8.3

+
+

Cylc Components

+
+
cylc-flow:
+

8.3

+
+
cylc-ui:
+

2.5

+
+
cylc-uiserver:
+

1.5

+
+
cylc-rose:
+

1.4

+
+
rose:
+

2.3

+
+
+
+
+

Manually setting task outputs and prerequisites

+

At Cylc 8.3.0, the cylc set-outputs command has been replaced by the new +cylc set command.

+

The cylc set-outputs command made it look like an output had been generated +to downstream tasks, but did not update the task status to match. As a result, +it was often necessary to use cylc remove in combination with cylc +set-outputs.

+

The new cylc set command is able to directly set task outputs as if they +had completed naturally, making the command more intuitive and avoiding the +need for cylc remove. It can also set prerequisites, as if they were satisfied naturally.

+

For example, say there’s a failed task holding up your workflow and you want +Cylc to continue as if the task had succeeded. Here are the interventions +you would need to perform with Cylc 8.2 and 8.3 side-by-side.

+ ++++ + + + + + + + + + + + +

Cylc 8.2 (set-outputs)

Cylc 8.3 (set)

# let downstream tasks run:
+cylc set-outputs <task>
+# remove the failed task:
+cylc remove <task>
+
+
+
# tell Cylc that the task succeeded:
+cylc set <task>
+
+
+
../_images/cylc-set-outputs.gif +../_images/cylc-set.gif +
+
+
+

Tui

+

The Tui (terminal user interface) is a command line version of the Gui. +You can use it to monitor and control your workflows.

+

There has been a major update to Tui at Cylc 8.3.0:

+
    +
  • Larger workflows will no longer cause Tui to time out.

  • +
  • You can now browse all your workflows including stopped workflows.

  • +
  • You can monitor multiple workflows at the same time.

  • +
  • The workflow and job logs are now available from within Tui.

  • +
+../_images/tui-1.gif +
+
+

N-Window selector in the GUI

+

The n-window determines how much of a workflow is visible in the GUI / Tui.

+

The n=0 window contains only the active tasks +(i.e. queued, preparing, submitted or running tasks).

+

The n=1 window, also contains tasks one “edge” out from active tasks +(i.e. the tasks immediately upstream or downstream of active tasks).

+

The n=2 window, also contains tasks two “edges” out from active tasks, +and so on.

+

It is now possible to change the window extent in the GUI via a button in the +toolbar allowing you to see tasks further back in the workflow’s history.

+../_images/gui-n-window-selector.gif +
+

Note

+

This is currently a per-workflow setting so changing the n-window in one +browser tab will also change it in other browser tabs and Tui sessions.

+
+
+

Warning

+

Using high n-window values with complex workflows may have performance +impacts.

+
+
+
+

Group by cycle point in the graph view

+

The graph view now has an option to group tasks by cycle point.

+../_images/cylc-graph-group-by-cycle-point.png +
+
+

Gantt View

+

The GUI now has a Gantt view option:

+A picture of the Gantt view in operation. +
+
+

Analysis View

+

New Analysis added - a layout which plots run times against cycle points.

+A picture of the Time Series task analysis in operation. +
+
+

Completion Expressions

+

When a task achieves a final status, its outputs are validated against a “completion +expression” to ensure that it has produced all of its +required outputs. +If a task fails this validation check it is said to have “incomplete outputs” +and will be retained in the active window pending user intervention.

+

This completion expression is generated automatically from the graph. +By default, tasks are expected to succeed, if you register any additional +required output in the graph, then these must also +be produced.

+

At Cylc 8.3.0 it is now possible to manually configure this completion +expression for finer control. This is particularly useful for anyone using +custom outputs.

+

For example, mytask must produce one of the outputs x or y to pass +the completion expression configured here:

+
[runtime]
+    [[mytask]]
+        completion = succeeded and (x or y)
+        [[[outputs]]]
+            x = output-x
+            y = output-y
+
+
+

For more information, see the reference for the +[runtime][<namespace>]completion configuration.

+
+
+

Workflow State Triggers & Commands

+

Workflow state xtriggers and command now take Cylc universal IDs instead of +separate arguments:

+

For example, you can (and should) now write:

+
# On the command line
+- cylc workflow-state my-workflow --point 20240101 --task mytask --message "succeeded"
++ cylc workflow-state my-workflow//20240101/mytask:succeeded --triggers
+
+# In the flow.cylc file
+- my_xtrigger = workflow_state(
+-     workflow="my-workflow",
+-     task="mytask",
+-     point="20240101",
+-     message="succeeded"
+- )
++ my_xtrigger = workflow_state('my-workflow//20240101/mytask:succeeded', is_trigger=True)
+
+
+
+

Important

+

The new workflow state trigger syntax can use either the trigger or message from +trigger=message in [runtime][<namespace>][outputs].

+

The trigger and message are the same for the most common use cases (succeeded and started) +but may differ for other outputs, namely custom outputs.

+
+
+

Note

+

The suite-state xtrigger has been reimplemented for compatibility with +Cylc 7 workflows.

+
+
+
+
+
+

Cylc 8.2

+
+

Cylc Components

+
+
cylc-flow:
+

8.2

+
+
cylc-uiserver:
+

1.4

+
+
cylc-rose:
+

1.3

+
+
+
+
+

UI now remembers workspace tab layout

+
+

Added in version cylc-uiserver: 1.4.4

+
+

The UI now remembers the layout of your workspace tabs when you navigate away +from that workflow. Note that this only applies per browser session.

+../_images/ui-workspace-tabs.gif +
+
+

Cylc ignores $PYTHONPATH

+

Cylc now ignores $PYTHONPATH to make it more robust to task +environments which set this value. If you want to add to the Cylc +environment itself, e.g. to install a Cylc extension, +use a custom xtrigger, or event handler use $CYLC_PYTHONPATH.

+
+
+

Upgrade To The Latest Jupyter Releases

+
+

Added in version cylc-uiserver: 1.4.0

+
+

The Cylc UI Server has been updated to work with the latest releases of +Jupyter Server and Jupyter Hub.

+

If you are utilising Cylc’s multi-user functionality then your configuration +will require some changes to work with these releases.

+

See Authorizing Others to Access Your Workflows for more details

+
+

Added in version cylc-uiserver: 1.3.0

+
+

You can now configure the view which is opened by default when you navigate to +a new workflow in the GUI. Navigate to the settings page to select your chosen +view.

+../_images/ui-view-selector.jpg +

In the future we plan to support configuring a layout of multiple views and +configuring certain options on those views.

+
+
+

Reload

+
+

Added in version cylc-flow: 8.2.0

+
+

When workflows are +reloaded, +(e.g. by cylc reload), Cylc will now pause the workflow and wait for any +preparing tasks to be submitted before proceeding with the reload. +Once the reload has been completed, the workflow will be resumed.

+

You can now see more information about the status of the reload in the +workflow status message which appears at the top of the GUI and Tui interfaces.

+
+
+
+
+

Cylc 8.1

+
+

Cylc Components

+
+
cylc-flow:
+

8.1

+
+
cylc-uiserver:
+

1.2

+
+
cylc-rose:
+

1.1

+
+
+
+
+

Warning

+

Workflows started with Cylc 8.0 which contain multiple flows +cannot be restarted with Cylc 8.1 due to database changes.

+
+
+

Analysis View

+
+

Added in version cylc-uiserver: 1.2.2

+
+

The web UI also has a new view for displaying task queue & run time statistics.

+../_images/analysis_view.gif +
+
+

Graph View

+
+

Added in version cylc-uiserver: 1.2.0

+
+

The web UI now has a graph view which displays a visualisation of a workflow’s graph:

+../_images/cylc-graph.gif +

Family & cycle grouping as well as the ability to view graphs for stopped workflows +will be added in later releases.

+
+
+

Log View

+
+

Added in version cylc-uiserver: 1.2.0

+
+

The web UI now has a log view which displays workflow and job log files:

+../_images/log-view-screenshot.png +

Support for viewing more log files, syntax highlighting, searching and line +numbers are planned for future releases.

+
+
+

Edit Runtime

+
+

Added in version cylc-uiserver: 1.2.0

+
+

The web UI now has a command for editing the [runtime] section +of a task or family.

+../_images/edit-runtime-screenshot.png +

Any changes made are broadcast to the running workflow.

+
+
+

Combined Commands

+
+

Added in version cylc-flow: 8.1.0

+
+

Two new commands have been added as short-cuts for common working patterns:

+
+
cylc vip

Validate, install and plays a workflow, equivalent to:

+
cylc validate <path>
+cylc install <path>
+cylc play <id>
+
+
+
+
cylc vr

Validate and reinstall a workflow, then either: +- reload the workflow if it is running. +- restart the workflow if it is stopped.

+
+
+../_images/vip-vr.gif +

For more information see the command line help:

+
cylc vip --help
+cylc vr --help
+
+
+
+
+

Bash Completion

+
+

Added in version cylc-flow: 8.1.0

+
+

Cylc now provides a high performance Bash completion script which saves you typing:

+
    +
  • Cylc commands & options

  • +
  • Workflow IDs

  • +
  • Cycle points

  • +
  • Task names

  • +
  • Job numbers

  • +
+../_images/cylc-completion.bash.gif +

Installation instructions.

+
+
+
+
+

Cylc 8.0

+
+

Cylc Components

+
+
cylc-flow:
+

8.0

+
+
cylc-uiserver:
+

1.1

+
+
cylc-rose:
+

1.1

+
+
+
+

The first official release of Cylc 8.

+

For a summary of changes see the migration guide.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/config/file-format.html b/nightly_8.4/html/reference/config/file-format.html new file mode 100644 index 00000000000..9c2bab4b1d2 --- /dev/null +++ b/nightly_8.4/html/reference/config/file-format.html @@ -0,0 +1,324 @@ + + + + + + + The .cylc File Format — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

The .cylc File Format

+

Cylc global and workflow configuration files are written in a nested +INI-based format.

+
+

Syntax

+
+
Comments

Comments follow a # character.

+
+
Settings

Configuration items (settings) are written as key = value pairs, and can +be contained within sections. Setting names (the keys) may contain spaces.

+
+
String Values

Quoting single-line string values is optional:

+
[animals]
+   cat = dusty
+   dog = "fido"  # or single quotes: 'fido'
+
+
+

Multiline string values must be triple-quoted:

+
[song]
+   lyrics = """  # (or triple single-quotes: '''value''')
+      No stop signs
+      Speed limit
+      Nobody's gonna slow me down
+   """
+
+
+
+
List Values

List values are comma-separated:

+
animals = dusty, fido, cujo
+
+
+
+
Boolean Values

Booleans are capitalized:

+
ice cream is good = True  # or False
+
+
+
+
Sections and Sub-sections

Settings have a level-dependent number of square brackets:

+
[section]
+[[sub-section]]
+[[[sub-sub-section]]]
+
+
+
+
Indentation

It is advisable to indent sections and subsections, for clarity. However, +Cylc ignores indentation, so this:

+
[section]
+   a = A
+   [[sub-section]]
+      b = B
+   b = C  # WARNING: this is still in sub-section!
+
+
+

is equivalent to this:

+
[section]
+   a = A
+   [[sub-section]]
+      b = C
+
+
+
+
Duplicate Sections and Items

Duplicate sections get merged into one. Duplicate settings overwrite +previously defined values. So this:

+
[animals]
+  cat = fluffy
+[animals]
+  dog = fido
+  cat = dusty
+
+
+

is equivalent to this:

+
[animals]
+  cat = dusty
+  dog = fido
+
+
+

The only exception to this rule is graph strings, +which get merged. So these graph strings:

+
R1 = "foo => bar"
+R1 = "foo => baz"
+
+
+

merge to this:

+
R1 = "foo => bar & baz"
+
+
+
+
Continuation lines

If necessary, you can continue on the next line after a backslash character:

+
verse = "the quick \
+         brown fox"
+
+
+

However, backslash line continuation is fragile (trailing invisible +whitespace breaks it). Long graph strings strings +should be split on graph symbols instead:

+
R1 = """
+     (foo & bar ) |
+         baz =>
+             qux
+"""
+# Equivalent to:
+R1 = """
+     (foo & bar ) | baz => qux
+"""
+
+
+
+
Include-files

flow.cylc fragments can be included verbatim with the %include +directive. Include-files can be included multiple times, and even nested. +Include-file paths should relative to the flow.cylc location:

+
%include "inc/site-a.cylc"
+
+
+

Jinja2’s template inclusion mechanism can be used with Cylc +too.

+
+
+
+
+

Shorthand

+

We often use a compact single-line notation to refer to nested config items:

+
+
[section]

An entire section.

+
+
[section]setting

A setting within a section.

+
+
[section]setting=value

The value of a setting within a section.

+
+
[section][sub-section]another-setting

A setting within a sub-section.

+
+
+

In the file, however, section headings need additional brackets at each level.

+
# This:
+#   [runtime][task-a][environment]FOO = foo
+# Means:
+[runtime]
+    [[task-a]]
+        [[[environment]]]
+            FOO = foo
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/config/global.html b/nightly_8.4/html/reference/config/global.html new file mode 100644 index 00000000000..47c51d51970 --- /dev/null +++ b/nightly_8.4/html/reference/config/global.html @@ -0,0 +1,2939 @@ + + + + + + + Global Configuration — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Global Configuration

+

Cylc global configurations use the .cylc file format.

+
+
+global.cylc
+

The global configuration which defines default Cylc Flow settings +for a user or site.

+

To view your global config, run:

+
$ cylc config
+
+
+

Cylc will attempt to load the global configuration (global.cylc) from a +hierarchy of locations, including the site directory (defaults to +/etc/cylc/flow/) and the user directory (~/.cylc/flow/). For +example at Cylc version 8.0.1, the hierarchy would be, in order of +ascending priority:

+
<site-conf-path>/flow/global.cylc
+<site-conf-path>/flow/8/global.cylc
+<site-conf-path>/flow/8.0/global.cylc
+<site-conf-path>/flow/8.0.1/global.cylc
+~/.cylc/flow/global.cylc
+~/.cylc/flow/8/global.cylc
+~/.cylc/flow/8.0/global.cylc
+~/.cylc/flow/8.0.1/global.cylc
+
+
+

Where <site-conf-path> is /etc/cylc/flow/ by default but can be +changed by CYLC_SITE_CONF_PATH.

+

A setting in a file lower down in the list will override the same setting +from those higher up (but if a setting is present in a file higher up and +not in any files lower down, it will not be overridden).

+

The following environment variables can change the files which are loaded:

+
+
+CYLC_CONF_PATH
+

If set this bypasses the default site/user configuration hierarchy used +to load the Cylc Flow global configuration.

+

This should be set to a directory containing a global.cylc +file.

+
+ +
+
+CYLC_SITE_CONF_PATH
+

By default the site configuration is located in /etc/cylc/. For +installations where this is not convenient, this path can be overridden +by setting CYLC_SITE_CONF_PATH to point at another location.

+

Configuration for different Cylc components should be in sub-directories +within this location.

+

For example to configure Cylc Flow you could do the following:

+
$CYLC_SITE_CONF_PATH/
+`-- flow/
+    `-- global.cylc
+
+
+
+ +
+

Note

+

The global.cylc file can be templated using Jinja2 variables. +See Jinja2.

+
+
+

Changed in version 8.0.0: Prior to Cylc 8, global.cylc was named global.rc, but that name +is no longer supported.

+
+
+
+[hub]
+
+
Path:
+

global.cylc[hub]

+
+
+

Configure the public URL of Jupyter Hub.

+

If configured, the cylc gui command will open a web browser at this +location rather than starting a standalone server when called.

+
+

See also

+ +
+
+
+url
+
+
Path:
+

global.cylc[hub]url

+
+
Type:
+

string

+
+
+
+

Added in version 8.3.0.

+
+

Where Jupyter Hub is used a url can be provided for routing on +execution of cylc gui command.

+
+ +
+ +
+
+[scheduler]
+
+
Path:
+

global.cylc[scheduler]

+
+
Defaults For:
+

flow.cylc[scheduler].

+
+
+

Settings for the scheduler.

+
+
+UTC mode
+
+
Path:
+

global.cylc[scheduler]UTC mode

+
+
Type:
+

boolean

+
+
Default:
+

False

+
+
Default For:
+

flow.cylc[scheduler]UTC mode.

+
+
+

If True, UTC will be used as the time zone for timestamps in +the logs. If False, the local/system time zone will be used.

+
+ +
+
+process pool size
+
+
Path:
+

global.cylc[scheduler]process pool size

+
+
Type:
+

integer

+
+
Default:
+

4

+
+
+

Maximum number of concurrent processes used to execute external job +submission, event handlers, and job poll and kill commands

+ +
+

Changed in version 8.0.0: Moved into the [scheduler] section from the top level.

+
+
+ +
+
+process pool timeout
+
+
Path:
+

global.cylc[scheduler]process pool timeout

+
+
Type:
+

time interval

+
+
Default:
+

PT10M

+
+
+

After this interval Cylc will kill long running commands in the +process pool.

+ +
+

Note

+

The default is set quite high to avoid killing important +processes when the system is under load.

+
+
+

Changed in version 8.0.0: Moved into the [scheduler] section from the top level.

+
+
+ +
+
+auto restart delay
+
+
Path:
+

global.cylc[scheduler]auto restart delay

+
+
Type:
+

time interval

+
+
+

Maximum number of seconds the auto-restart mechanism will delay +before restarting workflows.

+

When a host is set to automatically +shutdown/restart it waits a random period of time +between zero and auto restart delay seconds before +beginning the process. This is to prevent large numbers of +workflows from restarting simultaneously.

+
+

See also

+

Workflow Migration

+
+
+

Changed in version 8.0.0: This item was previously called global.rc[suite servers]auto restart delay.

+
+
+ +
+
+[run hosts]
+
+
Path:
+

global.cylc[scheduler][run hosts]

+
+
+

Configure workflow hosts and ports for starting workflows.

+

Additionally configure host selection settings specifying how to +determine the most suitable run host at any given time from those +configured.

+
+

Changed in version 8.0.0: This item was previously called [suite servers].

+
+
+
+available
+
+
Path:
+

global.cylc[scheduler][run hosts]available

+
+
Type:
+

spaceless list

+
+
+

A list of workflow run hosts.

+

Cylc will choose one of these hosts for a workflow to start on. +(Unless an explicit host is provided as an option to the +cylc play --host=<myhost> command.)

+
+

Changed in version 8.0.0: This item was previously called [suite servers]run hosts.

+
+
+ +
+
+ports
+
+
Path:
+

global.cylc[scheduler][run hosts]ports

+
+
Type:
+

integer range

+
+
Default:
+

43001 .. 43101

+
+
+

The range of ports for Cylc to use to run workflows.

+

The minimum and maximum port numbers in the format +min .. max.

+
+

Changed in version 8.0.0: This item was previously called [suite servers]run ports. +It can no longer be used to define a non-contiguous port +range.

+
+
+ +
+
+condemned
+
+
Path:
+

global.cylc[scheduler][run hosts]condemned

+
+
Type:
+

absolute host list

+
+
+

These hosts will not be used to run jobs.

+

If workflows are already running on +condemned hosts, Cylc will shut them down and +restart them on different hosts.

+
+

See also

+

Workflow Migration

+
+
+

Changed in version 8.0.0: This item was previously called [suite servers]condemned hosts.

+
+
+ +
+
+ranking
+
+
Path:
+

global.cylc[scheduler][run hosts]ranking

+
+
Type:
+

string

+
+
+

Rank and filter run hosts based on system information.

+

Ranking can be used to provide load balancing to ensure no +single run host is overloaded. It also provides thresholds +beyond which Cylc will not attempt to start new schedulers on +a host.

+

This should be a multiline string containing Python expressions +to rank and/or filter hosts. All psutil attributes are +available for use in these expressions.

+

Ranking

+

Rankings are expressions which return numerical values. +The host which returns the lowest value is chosen. Examples:

+
# rank hosts by cpu_percent
+cpu_percent()
+
+# rank hosts by 15min average of server load
+getloadavg()[2]
+
+# rank hosts by the number of cores
+# (multiple by -1 because the lowest value is chosen)
+-1 * cpu_count()
+
+
+

Threshold

+

Thresholds are expressions which return boolean values. +If a host returns a False value that host will not be +selected. Examples:

+
# filter out hosts with a CPU utilisation of 70% or above
+cpu_percent() < 70
+
+# filter out hosts with less than 1GB of RAM available
+virtual_memory().available > 1000000000
+
+# filter out hosts with less than 1GB of disk space
+# available on the "/" mount
+disk_usage('/').free > 1000000000
+
+
+

Combining

+

Multiple rankings and thresholds can be combined in this +section e.g:

+
# filter hosts
+cpu_percent() < 70
+disk_usage('/').free > 1000000000
+
+# rank hosts by CPU count
+1 / cpu_count()
+# if two hosts have the same CPU count
+# then rank them by CPU usage
+cpu_percent()
+
+
+
+

Changed in version 8.0.0: This item was previously called [suite servers][run host select]rank.

+
+
+ +
+ +
+
+[host self-identification]
+
+
Path:
+

global.cylc[scheduler][host self-identification]

+
+
+

How Cylc determines and shares the identity of the workflow host.

+

The workflow host’s identity must be determined locally by cylc and +passed to running tasks (via $CYLC_WORKFLOW_HOST) so that task +messages can target the right workflow on the right host.

+
+

Changed in version 8.0.0: This item was previously called [suite host self-identification].

+
+
+
+method
+
+
Path:
+

global.cylc[scheduler][host self-identification]method

+
+
Type:
+

string

+
+
Default:
+

name

+
+
Options:
+

name, address, hardwired

+
+
+

Determines how cylc finds the identity of the +workflow host.

+

Options:

+
+
name

(The default method) Self-identified host name. +Cylc asks the workflow host for its host name. This +should resolve on task hosts to the IP address of the +workflow host; if it doesn’t, adjust network settings or +use one of the other methods.

+
+
address

Automatically determined IP address (requires target). +Cylc attempts to use a special external “target address” +to determine the IP address of the workflow host as +seen by remote task hosts.

+
+
hardwired

(only to be used as a last resort) Manually specified +host name or IP address (requires host) of the +workflow host.

+
+
+
+

Changed in version 8.0.0: This item was previously called [suite host self-identification].

+
+
+ +
+
+target
+
+
Path:
+

global.cylc[scheduler][host self-identification]target

+
+
Type:
+

string

+
+
Default:
+

google.com

+
+
+

Target for use by the address self-identification method.

+

If your workflow host sees the internet, a common +address such as google.com will do; otherwise choose a host +visible on your intranet.

+
+

Changed in version 8.0.0: This item was previously called [suite host self-identification].

+
+
+ +
+
+host
+
+
Path:
+

global.cylc[scheduler][host self-identification]host

+
+
Type:
+

string

+
+
+

The name or IP address of the workflow host used by the +hardwired self-identification method.

+
+

Changed in version 8.0.0: This item was previously called [suite host self-identification].

+
+
+ +
+ +
+
+[events]
+
+
Path:
+

global.cylc[scheduler][events]

+
+
Default For:
+

flow.cylc[scheduler][events].

+
+
+

Configure the workflow event handling system.

+
+
+handlers
+
+
Path:
+

global.cylc[scheduler][events]handlers

+
+
Type:
+

list

+
+
Default For:
+

flow.cylc[scheduler][events]handlers.

+
+
+

Configure event handlers that run when certain workflow +events occur.

+
+ +
+
+handler events
+
+
Path:
+

global.cylc[scheduler][events]handler events

+
+
Type:
+

list

+
+
Default For:
+

flow.cylc[scheduler][events]handler events.

+
+
+

Specify the events for which workflow event handlers should be invoked.

+
+ +
+
+mail events
+
+
Path:
+

global.cylc[scheduler][events]mail events

+
+
Type:
+

list

+
+
Default For:
+

flow.cylc[scheduler][events]mail events.

+
+
+

Specify the workflow events for which notification emails should +be sent.

+
+ +
+
+startup handlers
+
+
Path:
+

global.cylc[scheduler][events]startup handlers

+
+
Type:
+

list

+
+
Default For:
+

flow.cylc[scheduler][events]startup handlers.

+
+
+

Handlers to run at scheduler startup.

+
+ +
+
+shutdown handlers
+
+
Path:
+

global.cylc[scheduler][events]shutdown handlers

+
+
Type:
+

list

+
+
Default For:
+

flow.cylc[scheduler][events]shutdown handlers.

+
+
+

Handlers to run at scheduler shutdown.

+
+ +
+
+abort handlers
+
+
Path:
+

global.cylc[scheduler][events]abort handlers

+
+
Type:
+

list

+
+
Default For:
+

flow.cylc[scheduler][events]abort handlers.

+
+
+

Handlers to run if the scheduler shuts down with error status due to +a configured timeout or a fatal error condition.

+
+ +
+
+workflow timeout
+
+
Path:
+

global.cylc[scheduler][events]workflow timeout

+
+
Type:
+

time interval

+
+
Default For:
+

flow.cylc[scheduler][events]workflow timeout.

+
+
+

Workflow timeout interval. The timer starts counting down at scheduler +startup. It resets on workflow restart.

+
+ +
+
+workflow timeout handlers
+
+
Path:
+

global.cylc[scheduler][events]workflow timeout handlers

+
+
Type:
+

list

+
+
Default For:
+

flow.cylc[scheduler][events]workflow timeout handlers.

+
+
+

Handlers to run if the workflow timer times out.

+
+ +
+
+abort on workflow timeout
+
+
Path:
+

global.cylc[scheduler][events]abort on workflow timeout

+
+
Type:
+

boolean

+
+
Default:
+

False

+
+
Default For:
+

flow.cylc[scheduler][events]abort on workflow timeout.

+
+
+

Whether the scheduler should shut down immediately with error status if +the workflow timer times out.

+
+ +
+
+stall handlers
+
+
Path:
+

global.cylc[scheduler][events]stall handlers

+
+
Type:
+

list

+
+
Default For:
+

flow.cylc[scheduler][events]stall handlers.

+
+
+

Handlers to run if the scheduler stalls.

+
+ +
+
+stall timeout
+
+
Path:
+

global.cylc[scheduler][events]stall timeout

+
+
Type:
+

time interval

+
+
Default:
+

PT1H

+
+
Default For:
+

flow.cylc[scheduler][events]stall timeout.

+
+
+

The length of a timer which starts if the scheduler stalls.

+
+ +
+
+stall timeout handlers
+
+
Path:
+

global.cylc[scheduler][events]stall timeout handlers

+
+
Type:
+

list

+
+
Default For:
+

flow.cylc[scheduler][events]stall timeout handlers.

+
+
+

Handlers to run if the stall timer times out.

+
+ +
+
+abort on stall timeout
+
+
Path:
+

global.cylc[scheduler][events]abort on stall timeout

+
+
Type:
+

boolean

+
+
Default:
+

True

+
+
Default For:
+

flow.cylc[scheduler][events]abort on stall timeout.

+
+
+

Whether the scheduler should shut down immediately with error status if +the stall timer times out.

+
+ +
+
+inactivity timeout
+
+
Path:
+

global.cylc[scheduler][events]inactivity timeout

+
+
Type:
+

time interval

+
+
Default For:
+

flow.cylc[scheduler][events]inactivity timeout.

+
+
+

Scheduler inactivity timeout interval. The timer resets when any +workflow activity occurs.

+
+ +
+
+inactivity timeout handlers
+
+
Path:
+

global.cylc[scheduler][events]inactivity timeout handlers

+
+
Type:
+

list

+
+
Default For:
+

flow.cylc[scheduler][events]inactivity timeout handlers.

+
+
+

Handlers to run if the inactivity timer times out.

+
+ +
+
+abort on inactivity timeout
+
+
Path:
+

global.cylc[scheduler][events]abort on inactivity timeout

+
+
Type:
+

boolean

+
+
Default:
+

False

+
+
Default For:
+

flow.cylc[scheduler][events]abort on inactivity timeout.

+
+
+

Whether the scheduler should shut down immediately with error status if +the inactivity timer times out.

+
+ +
+
+restart timeout
+
+
Path:
+

global.cylc[scheduler][events]restart timeout

+
+
Type:
+

time interval

+
+
Default:
+

PT2M

+
+
Default For:
+

flow.cylc[scheduler][events]restart timeout.

+
+
+

How long to wait for intervention on restarting a completed workflow. +The timer stops if any task is triggered.

+
+ +
+ +
+
+[mail]
+
+
Path:
+

global.cylc[scheduler][mail]

+
+
Defaults For:
+

flow.cylc[scheduler][mail].

+
+
+

Settings for the scheduler to send event emails.

+
+
+from
+
+
Path:
+

global.cylc[scheduler][mail]from

+
+
Type:
+

string

+
+
Default For:
+

flow.cylc[scheduler][mail]from.

+
+
+

Specify an alternative from email address for workflow event notifications.

+
+ +
+
+smtp
+
+
Path:
+

global.cylc[scheduler][mail]smtp

+
+
Type:
+

string

+
+
+

Specify the SMTP server for sending workflow event email +notifications.

+

This cannot be configured in flow.cylc.

+

Example:

+
smtp.yourorg
+
+
+
+ +
+
+to
+
+
Path:
+

global.cylc[scheduler][mail]to

+
+
Type:
+

string

+
+
Default For:
+

flow.cylc[scheduler][mail]to.

+
+
+

A list of email addresses that event notifications should be sent to.

+
+ +
+
+footer
+
+
Path:
+

global.cylc[scheduler][mail]footer

+
+
Type:
+

string

+
+
Default For:
+

flow.cylc[scheduler][mail]footer.

+
+
+

Specify a string or string template for footers of emails sent for both +workflow and task events.

+
+ +
+
+task event batch interval
+
+
Path:
+

global.cylc[scheduler][mail]task event batch interval

+
+
Type:
+

time interval

+
+
Default:
+

PT5M

+
+
Default For:
+

flow.cylc[scheduler][mail]task event batch interval.

+
+
+

Gather all task event notifications in the given interval into a single email.

+
+ +
+ +
+
+[main loop]
+
+
Path:
+

global.cylc[scheduler][main loop]

+
+
Defaults For:
+

flow.cylc[scheduler][main loop].

+
+
+

Configuration of main loop plugins for the scheduler.

+
+
+plugins
+
+
Path:
+

global.cylc[scheduler][main loop]plugins

+
+
Type:
+

list

+
+
Default:
+

'health check', 'reset bad hosts'

+
+
+

Configure the default main loop plugins to use when +starting new workflows.

+

Only enabled plugins are loaded. Plugins can be enabled +in two ways:

+
+
Globally:

To enable a plugin for all workflows add it to this +setting.

+
+
Per-Run:

To enable a plugin for a one-off run of a workflow, +specify it on the command line with +cylc play --main-loop.

+
+

Hint

+

This appends to the configured list of plugins +rather than overriding it.

+
+
+
+
+

Added in version 8.0.0.

+
+
+ +
+
+[<plugin name>]
+
+
Path:
+

global.cylc[scheduler][main loop][<plugin name>]

+
+
Defaults For:
+

flow.cylc[scheduler][main loop][<plugin name>].

+
+
+

Configure a main loop plugin.

+
+
+interval
+
+
Path:
+

global.cylc[scheduler][main loop][<plugin name>]interval

+
+
Type:
+

time interval

+
+
Default:
+

PT10M

+
+
Default For:
+

flow.cylc[scheduler][main loop][<plugin name>]interval.

+
+
+

Interval at which the plugin is invoked.

+
+ +
+ +
+
+[health check]
+
+
Path:
+

global.cylc[scheduler][main loop][health check]

+
+
Inherits:
+

global.cylc[scheduler][main loop][<plugin name>]

+
+
+

Checks the integrity of the workflow run directory.

+
+

Added in version 8.0.0.

+
+
+
+interval
+
+
Path:
+

global.cylc[scheduler][main loop][health check]interval

+
+
Type:
+

time interval

+
+
Default:
+

PT10M

+
+
+

Interval at which the plugin is invoked.

+
+

Added in version 8.0.0.

+
+
+ +
+ +
+
+[auto restart]
+
+
Path:
+

global.cylc[scheduler][main loop][auto restart]

+
+
Inherits:
+

global.cylc[scheduler][main loop][<plugin name>]

+
+
+

Automatically migrates workflows between servers.

+

For more information see:

+ +
+

Added in version 8.0.0.

+
+
+
+interval
+
+
Path:
+

global.cylc[scheduler][main loop][auto restart]interval

+
+
Type:
+

time interval

+
+
Default:
+

PT10M

+
+
+

Interval at which the plugin is invoked.

+
+

Added in version 8.0.0.

+
+
+ +
+ +
+
+[reset bad hosts]
+
+
Path:
+

global.cylc[scheduler][main loop][reset bad hosts]

+
+
Inherits:
+

global.cylc[scheduler][main loop][<plugin name>]

+
+
+

Periodically clear the scheduler list of unreachable (bad) +hosts.

+
+

Added in version 8.0.0.

+
+
+
+interval
+
+
Path:
+

global.cylc[scheduler][main loop][reset bad hosts]interval

+
+
Type:
+

time interval

+
+
Default:
+

PT30M

+
+
+

Interval at which the plugin is invoked.

+
+

Added in version 8.0.0.

+
+
+ +
+ +
+ +
+
+[logging]
+
+
Path:
+

global.cylc[scheduler][logging]

+
+
+

Settings for the workflow event log.

+

The workflow event log, held under the workflow run directory, is +maintained as a rolling archive. Logs are rolled over (backed up +and started anew) when they reach a configurable limit size.

+
+

Changed in version 8.0.0: This item was previously called [suite logging].

+
+
+
+rolling archive length
+
+
Path:
+

global.cylc[scheduler][logging]rolling archive length

+
+
Type:
+

integer

+
+
Default:
+

15

+
+
+

How many rolled logs to retain in the archive.

+
+ +
+
+maximum size in bytes
+
+
Path:
+

global.cylc[scheduler][logging]maximum size in bytes

+
+
Type:
+

integer

+
+
Default:
+

1000000

+
+
+

Workflow event logs are rolled over when they reach this +file size.

+
+ +
+ +
+ +
+
+[install]
+
+
Path:
+

global.cylc[install]

+
+
+

Configure directories and files to be installed on remote hosts.

+
+

Added in version 8.0.0.

+
+
+
+max depth
+
+
Path:
+

global.cylc[install]max depth

+
+
Type:
+

integer

+
+
Default:
+

4

+
+
+

How many directory levels deep Cylc should look for installed +workflows in the cylc-run directory.

+

This also sets the limit on how deep a workflow ID can be +before cylc install will refuse to install it. For example, +if set to 4, cylc install one/two/three/four will fail, +because the resultant workflow ID would be +one/two/three/four/run1, which is 5 levels deep. (However, +cylc install one/two/three/four --no-run-name would work.)

+
+

Note

+

A high value may cause a slowdown of Cylc commands such +install, scan and clean if there are many +run directories in the +cylc-run directory for Cylc to check, or if the filesystem +is slow (e.g. NFS).

+
+
+

Added in version 8.0.0.

+
+
+ +
+
+source dirs
+
+
Path:
+

global.cylc[install]source dirs

+
+
Type:
+

list

+
+
Default:
+

~/cylc-src

+
+
+

List of paths that Cylc searches for workflows to install.

+

All workflow source directories in these locations will +also show up in the GUI, ready for installation.

+
+

Note

+

If workflow source directories of the same name exist in more +than one of these paths, only the first one will be picked up.

+
+
+

Added in version 8.0.0.

+
+
+ +
+ +
+
Path:
+

global.cylc[install][symlink dirs]

+
+
+

Configure alternate workflow run directory locations.

+

Symlinks from the the standard $HOME/cylc-run locations will be +created.

+
+

Added in version 8.0.0.

+
+
+ +
+
Path:
+

global.cylc[install][symlink dirs][<install target>]

+
+
+

Host on which to create the symlinks.

+
+ +
+
Path:
+

global.cylc[install][symlink dirs][<install target>]run

+
+
Type:
+

string

+
+
+

Alternative location for the run dir.

+

If specified, the workflow run directory will +be created in <this-path>/cylc-run/<workflow-id> +and a symbolic link will be created from +$HOME/cylc-run/<workflow-id>. +If not specified the workflow run directory will be created +in $HOME/cylc-run/<workflow-id>. +All the workflow files and the .service directory get +installed into this directory.

+
+

Added in version 8.0.0.

+
+
+ +
+ +
+
Path:
+

global.cylc[install][symlink dirs][<install target>]share

+
+
Type:
+

string

+
+
+

Alternative location for the log dir.

+

If specified the workflow share directory will +be created in +<this-path>/cylc-run/<workflow-id>/share +and a symbolic link will be created from +$HOME/cylc-run/<workflow-id>/share. +If not specified the workflow log directory will +be created in +$HOME/cylc-run/<workflow-id>/share.

+
+

Added in version 8.0.0.

+
+
+ +
+ +
+
Path:
+

global.cylc[install][symlink dirs][<install target>]share/cycle

+
+
Type:
+

string

+
+
+

Alternative location for the log dir.

+

If specified the workflow share/cycle directory will +be created in +<this-path>/cylc-run/<workflow-id>/share/cycle +and a symbolic link will be created from +$HOME/cylc-run/<workflow-id>/share/cycle. +If not specified the workflow log directory will +be created in +$HOME/cylc-run/<workflow-id>/share/cycle.

+
+

Added in version 8.0.0.

+
+
+ +
+ +
+
Path:
+

global.cylc[install][symlink dirs][<install target>]log

+
+
Type:
+

string

+
+
+

Alternative location for the log dir.

+

If specified the workflow log directory will +be created in +<this-path>/cylc-run/<workflow-id>/log +and a symbolic link will be created from +$HOME/cylc-run/<workflow-id>/log. +If not specified the workflow log directory will +be created in +$HOME/cylc-run/<workflow-id>/log.

+
+

Added in version 8.0.0.

+
+
+ +
+ +
+
Path:
+

global.cylc[install][symlink dirs][<install target>]log/job

+
+
Type:
+

string

+
+
+

Alternative location for the log dir.

+

If specified the workflow log/job directory will +be created in +<this-path>/cylc-run/<workflow-id>/log/job +and a symbolic link will be created from +$HOME/cylc-run/<workflow-id>/log/job. +If not specified the workflow log directory will +be created in +$HOME/cylc-run/<workflow-id>/log/job.

+
+

Added in version 8.4.0.

+
+
+ +
+ +
+
Path:
+

global.cylc[install][symlink dirs][<install target>]work

+
+
Type:
+

string

+
+
+

Alternative location for the log dir.

+

If specified the workflow work directory will +be created in +<this-path>/cylc-run/<workflow-id>/work +and a symbolic link will be created from +$HOME/cylc-run/<workflow-id>/work. +If not specified the workflow log directory will +be created in +$HOME/cylc-run/<workflow-id>/work.

+
+

Added in version 8.0.0.

+
+
+ +
+ +
+ +
+ +
+
+[platforms]
+
+
Path:
+

global.cylc[platforms]

+
+
+

Platforms allow you to define compute resources available at your +site.

+

A platform consists of a group of one or more hosts which share a +file system and a job runner (batch system).

+

A platform must allow interaction with the same job from any +of its hosts.

+
+

Added in version 8.0.0.

+
+
+
+[<platform name>]
+
+
Path:
+

global.cylc[platforms][<platform name>]

+
+
+

Configuration defining a platform.

+

Many of these settings have replaced those of the same name from +the old Cylc 7 suite.rc[runtime][<namespace>][job]/[remote] +and global.rc[hosts][<host>] sections.

+

Platform names can be regular expressions: If you have a set of +compute resources such as bigmachine1, bigmachine2 or +desktop0000, .., desktop9999 one would define platforms with +names [[bigmachine[12]]] and [[desktop[0-9]{4}]].

+

Cylc searches for a matching platform in the reverse +of the definition order to allow user defined platforms +to override site defined platforms. This means, for example, that +if [[a.*]] were set at the bottom of a configuration any +platform name beginning with “a” would return that platform.

+
+

Note

+

Each possible match to the definition regular expression is +considered a separate platform.

+

If you had a supercomputer with multiple login nodes this would +be a single platform with multiple hosts.

+
+
+

Warning

+

[platforms][localhost] may be set, to override default +settings, but regular expressions which match “localhost” +may not. Use comma separated lists instead:

+
[platforms]
+    [[localhost|cylc-server-..]]  # error
+    [[localhost, cylc-server-..]]  # ok
+
+
+
+
+

See also

+ +
+
+

Added in version 8.0.0.

+
+
+
+[meta]
+
+
Path:
+

global.cylc[platforms][<platform name>][meta]

+
+
+

Metadata for this platform or platform group.

+

Allows writers of platform configurations to add information +about platform usage. There are no-preset items because +Cylc does not use any platform (or group) metadata internally.

+

Users can then see information about defined platforms using:

+
cylc config -i [platforms]
+cylc config -i [platform groups]
+
+
+ +
+

Added in version 8.0.0.

+
+
+
+<custom metadata>
+
+
Path:
+

global.cylc[platforms][<platform name>][meta]<custom metadata>

+
+
Type:
+

string

+
+
+

Any user-defined metadata item.

+
+

Added in version 8.0.0.

+
+
+ +
+ +
+
+hosts
+
+
Path:
+

global.cylc[platforms][<platform name>]hosts

+
+
Type:
+

list

+
+
+

A list of hosts from which the job host can be selected using +[selection]method.

+

All hosts should share a file system.

+
+

Added in version 8.0.0.

+
+
+ +
+
+job runner
+
+
Path:
+

global.cylc[platforms][<platform name>]job runner

+
+
Type:
+

string

+
+
Default:
+

background

+
+
+

The system used to run jobs on the platform.

+

Examples:

+
+
    +
  • background

  • +
  • slurm

  • +
  • pbs

  • +
+
+ +
+

Added in version 8.0.0: (Replaces the deprecated setting flow.cylc[runtime][<namespace>][job]batch system.)

+
+
+ +
+
+job runner command template
+
+
Path:
+

global.cylc[platforms][<platform name>]job runner command template

+
+
Type:
+

string

+
+
+

Set the command used by the chosen job runner.

+

The template’s %(job)s will be +substituted by the job file path.

+
+

Added in version 8.0.0: (Replaces the deprecated setting flow.cylc[runtime][<namespace>][job]batch submit command template.)

+
+
+ +
+
+shell
+
+
Path:
+

global.cylc[platforms][<platform name>]shell

+
+
Type:
+

string

+
+
Default:
+

/bin/bash

+
+
+
+

Changed in version 8.0.0: Moved from suite.rc[runtime][<namespace>]job.

+
+
+ +
+
+communication method
+
+
Path:
+

global.cylc[platforms][<platform name>]communication method

+
+
Type:
+

string

+
+
Default:
+

zmq

+
+
Options:
+

poll, ssh, zmq

+
+
+

The means by which task progress messages are reported back to +the running workflow.

+

..rubric:: Options:

+
+
zmq

Direct client-server TCP communication via network ports

+
+
poll

The workflow polls for task status (no task messaging)

+
+
ssh

Use non-interactive ssh for task communications

+
+
+

For more information, see Tracking Job Status.

+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>]task communication +method.

+
+
+ +
+
+submission polling intervals
+
+
Path:
+

global.cylc[platforms][<platform name>]submission polling intervals

+
+
Type:
+

time interval list

+
+
Default:
+

PT15M

+
+
Default For:
+

flow.cylc[runtime][<namespace>]submission polling intervals.

+
+
+

List of intervals at which to poll status of job submission.

+
+ +
+
+submission retry delays
+
+
Path:
+

global.cylc[platforms][<platform name>]submission retry delays

+
+
Type:
+

time interval list

+
+
Default For:
+

flow.cylc[runtime][<namespace>]submission retry delays.

+
+
+

Cylc can automatically resubmit jobs after submission failures.

+
+ +
+
+execution polling intervals
+
+
Path:
+

global.cylc[platforms][<platform name>]execution polling intervals

+
+
Type:
+

time interval list

+
+
Default:
+

PT15M

+
+
Default For:
+

flow.cylc[runtime][<namespace>]execution polling intervals.

+
+
+

List of intervals at which to poll status of job execution.

+
+ +
+
+execution time limit polling intervals
+
+
Path:
+

global.cylc[platforms][<platform name>]execution time limit polling intervals

+
+
Type:
+

time interval list

+
+
Default:
+

PT1M, PT2M, PT7M

+
+
+

List of intervals after execution time limit to poll jobs.

+

If a job exceeds its execution time limit, Cylc can poll +more frequently to detect the expected job completion quickly. +The last interval in the list is used repeatedly until the job +completes. +Multipliers can be used as shorthand as in the example below.

+

Example:

+
5*PT2M, PT5M
+
+
+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>][batch systems] +[<system>]execution time limit polling.

+
+
+ +
+
+ssh command
+
+
Path:
+

global.cylc[platforms][<platform name>]ssh command

+
+
Type:
+

string

+
+
Default:
+

ssh -oBatchMode=yes -oConnectTimeout=10

+
+
+

A communication command used to invoke commands on this +platform.

+

Not used on the workflow host unless you run local tasks +under another user account. The value is assumed to be ssh +with some initial options or a command that implements a +similar interface to ssh.

+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>]ssh command.

+
+
+ +
+
+rsync command
+
+
Path:
+

global.cylc[platforms][<platform name>]rsync command

+
+
Type:
+

string

+
+
Default:
+

rsync

+
+
+

Command used for file installation.

+

This supports POSIX compliant rsync implementations e.g. GNU or +BSD.

+
+

Added in version 8.0.0.

+
+
+ +
+
+use login shell
+
+
Path:
+

global.cylc[platforms][<platform name>]use login shell

+
+
Type:
+

boolean

+
+
Default:
+

True

+
+
+

Whether to use a login shell or not for remote command +invocation.

+

By default, Cylc runs remote SSH commands using a login shell:

+
ssh user@host 'bash --login cylc ...'
+
+
+

which will source the following files (in order):

+
    +
  • /etc/profile

  • +
  • ~/.bash_profile

  • +
  • ~/.bash_login

  • +
  • ~/.profile

  • +
+

For more information on login shells see the “Invocation” +section of the Bash man pages.

+

For security reasons some institutions do not allow unattended +commands to start login shells, so you can turn off this +behaviour to get:

+
ssh user@host 'cylc ...'
+
+
+

which will use the default shell on the remote machine, +sourcing ~/.bashrc (or ~/.cshrc) to set up the +environment.

+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>]use login shell.

+
+
+ +
+
+cylc path
+
+
Path:
+

global.cylc[platforms][<platform name>]cylc path

+
+
Type:
+

string

+
+
+

The path containing the cylc executable on a remote +platform.

+

This may be necessary if the cylc executable is not in the +$PATH for an ssh call. +Test whether this is the case by using +ssh <host> command -v cylc.

+

This path is used for remote invocations of the cylc +command and is added to the $PATH in job scripts +for the configured platform.

+
+

Note

+

If use login shell=True (the default) +then an alternative approach is to add cylc to the +$PATH in the system or user Bash profile files +(e.g. ~/.bash_profile).

+
+
+

Tip

+

For multi-version installations this should point to the +Cylc wrapper script rather than the cylc executable +itself.

+

See Managing Environments for more information on +the wrapper script.

+
+
+

Changed in version 8.0.0: Moved from suite.rc[runtime][<namespace>][job] +cylc executable.

+
+
+ +
+
+global init-script
+
+
Path:
+

global.cylc[platforms][<platform name>]global init-script

+
+
Type:
+

string

+
+
+

A per-platform script which is run before other job scripts.

+

This should be used sparingly to perform any shell +configuration that cannot be performed via other means.

+
+

Changed in version 8.0.0: The global init-script now runs before any job +scripting which introduces caveats outlined below.

+
+
+

Warning

+

The global init-script has the following caveats, +as compared to the other task script-* items:

+
    +
  • The script is not covered by error trapping.

  • +
  • The job environment is not available to this script.

  • +
  • In debug mode this script will not be included in +xtrace output.

  • +
+
+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>]global init-script.

+
+
+ +
+
+copyable environment variables
+
+
Path:
+

global.cylc[platforms][<platform name>]copyable environment variables

+
+
Type:
+

list

+
+
+

A list containing the names of the environment variables to +be copied from the scheduler to a job.

+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>]copyable +environment variables.

+
+
+ +
+
+retrieve job logs
+
+
Path:
+

global.cylc[platforms][<platform name>]retrieve job logs

+
+
Type:
+

boolean

+
+
+

Whether to retrieve job logs from the job platform.

+
+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>]retrieve job logs. +(Replaces the deprecated setting flow.cylc[runtime][<namespace>][remote]retrieve job logs.)

+
+
+
+ +
+
+retrieve job logs command
+
+
Path:
+

global.cylc[platforms][<platform name>]retrieve job logs command

+
+
Type:
+

string

+
+
Default:
+

rsync -a

+
+
+

The command used to retrieve job logs from the job platform.

+
+
+

Note

+

The default command (rsync -a) means that the retrieved +files (and the directories above including job/log) get +the same permissions as on the remote host. This can cause +problems if the remote host uses different permissions to +the scheduler host (e.g. no world read access). To avoid +this problem you can set the command to +rsync -a --no-p --no-g --chmod=ugo=rwX which means the +retrieved files get the default permissions used on the +scheduler host.

+
+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>]retrieve job logs +command.

+
+
+
+ +
+
+retrieve job logs max size
+
+
Path:
+

global.cylc[platforms][<platform name>]retrieve job logs max size

+
+
Type:
+

string

+
+
+

The maximum size of job logs to retrieve.

+

Can be anything +accepted by the --max-size=SIZE option of rsync.

+
+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>]retrieve job logs +max size. +(Replaces the deprecated setting flow.cylc[runtime][<namespace>][remote]retrieve job logs max size.)

+
+
+
+ +
+
+retrieve job logs retry delays
+
+
Path:
+

global.cylc[platforms][<platform name>]retrieve job logs retry delays

+
+
Type:
+

time interval list

+
+
+

Configure retries for unsuccessful job log retrieval.

+

If there is a significant delay between job completion and +logs appearing in their final location (due to the job runner) +you can configure time intervals here to delay the first and +subsequent retrieval attempts.

+
+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>]retrieve job logs +retry delays. +(Replaces the deprecated setting flow.cylc[runtime][<namespace>][remote]retrieve job logs retry delays.)

+
+
+
+ +
+
+tail command template
+
+
Path:
+

global.cylc[platforms][<platform name>]tail command template

+
+
Type:
+

string

+
+
Default:
+

tail -n +1 --follow=name %(filename)s

+
+
+

A command template (with %(filename)s substitution) to +tail-follow job logs this platform, by cylc cat-log.

+
+

Warning

+

You are are unlikely to need to override this. Doing so may +adversely affect the UI log view.

+
+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>]tail command template.

+
+
+ +
+
+err tailer
+
+
Path:
+

global.cylc[platforms][<platform name>]err tailer

+
+
Type:
+

string

+
+
+

A command template (with %(job_id)s substitution) that can +be used to tail-follow the stderr stream of a running job if +SYSTEM does not use the normal log file location while the job +is running. This setting overrides +tail command template.

+

Examples:

+
# for PBS
+qcat -f -e %(job_id)s
+
+
+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>][batch systems] +[<system>]err tailer.

+
+
+ +
+
+out tailer
+
+
Path:
+

global.cylc[platforms][<platform name>]out tailer

+
+
Type:
+

string

+
+
+

A command template (with %(job_id)s substitution) that can +be used to tail-follow the stdout stream of a running job if +SYSTEM does not use the normal log file location while the job +is running. This setting overrides +tail command template.

+

Examples:

+
# for PBS
+qcat -f -o %(job_id)s
+
+
+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>][batch systems] +[<system>]out tailer.

+
+
+ +
+
+err viewer
+
+
Path:
+

global.cylc[platforms][<platform name>]err viewer

+
+
Type:
+

string

+
+
+

A command template (with %(job_id)s substitution) that can +be used to view the stderr stream of a running job if SYSTEM +does not use the normal log file location while the job is +running.

+

Examples:

+
# for PBS
+qcat -e %(job_id)s
+
+
+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>][batch systems] +[<system>]err viewer.

+
+
+ +
+
+out viewer
+
+
Path:
+

global.cylc[platforms][<platform name>]out viewer

+
+
Type:
+

string

+
+
+

A command template (with %(job_id)s substitution) that can +be used to view the stdout stream of a running job if SYSTEM +does not use the normal log file location while the job is +running.

+

Examples:

+
# for PBS
+qcat -o %(job_id)s
+
+
+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>][batch systems] +[<system>]out viewer.

+
+
+ +
+
+job name length maximum
+
+
Path:
+

global.cylc[platforms][<platform name>]job name length maximum

+
+
Type:
+

integer

+
+
+

The maximum length for job name acceptable by a job runner on +a given host. Currently, this setting is only meaningful for +PBS jobs. For example, PBS 12 or older will fail a job submit +if the job name has more than 15 characters; whereas PBS 13 +accepts up to 236 characters.

+
+

Changed in version 8.0.0: This item was previously called global.rc[hosts][<host>][batch systems] +[<system>]job name length maximum.

+
+
+ +
+
+install target
+
+
Path:
+

global.cylc[platforms][<platform name>]install target

+
+
Type:
+

string

+
+
+

This defaults to the platform name. This will be used as the +target for remote file installation. +For example, if Platform_A shares a file system with localhost:

+
[platforms]
+    [[Platform_A]]
+        install target = localhost
+
+
+
+

Added in version 8.0.0.

+
+
+ +
+
+clean job submission environment
+
+
Path:
+

global.cylc[platforms][<platform name>]clean job submission environment

+
+
Type:
+

boolean

+
+
Default:
+

False

+
+
+

Job submission subprocesses inherit their parent environment by +default. Remote jobs inherit the default non-interactive shell +environment for their platform. Jobs on the scheduler host +inherit the scheduler environment (unless their job runner +prevents this).

+

If, for example, the $PYTHON variable is different on the +scheduler and the remote host the same program may run in +different ways.

+

We recommend using a clean job submission environment for +consistent handling of local and remote jobs. However, +this is not the default behaviour because it prevents +local jobs from running, unless $PATH contains the +cylc wrapper script.

+

Specific environment variables can be singled out to pass +through to the clean environment, if necessary.

+

A standard set of executable paths is passed through to clean +environments, and can be added to if necessary.

+
+

Added in version 8.0.0.

+
+
+ +
+
+job submission environment pass-through
+
+
Path:
+

global.cylc[platforms][<platform name>]job submission environment pass-through

+
+
Type:
+

list

+
+
+

List of environment variable names to pass through to +job submission subprocesses.

+

$HOME is passed automatically.

+

You are unlikely to need this.

+
+

Added in version 8.0.0.

+
+
+ +
+
+job submission executable paths
+
+
Path:
+

global.cylc[platforms][<platform name>]job submission executable paths

+
+
Type:
+

list

+
+
+

Additional executable locations to pass to the job +submission subprocess beyond the standard locations +/bin, /usr/bin, /usr/local/bin, /sbin, /usr/sbin, /usr/local/sbin. +You are unlikely to need this.

+
+

Added in version 8.0.0.

+
+
+ +
+
+max batch submit size
+
+
Path:
+

global.cylc[platforms][<platform name>]max batch submit size

+
+
Type:
+

integer

+
+
Default:
+

100

+
+
+

Limits the maximum number of jobs that can be submitted at +once.

+

Where possible Cylc will batch together job submissions to +the same platform for efficiency. Submitting very large +numbers of jobs can cause problems with some submission +systems so for safety there is an upper limit on the number +of job submissions which can be batched together.

+
+

Added in version 8.0.0.

+
+
+ +
+
+ssh forward environment variables
+
+
Path:
+

global.cylc[platforms][<platform name>]ssh forward environment variables

+
+
Type:
+

list

+
+
+

A list containing the names of the environment variables to +forward with SSH connections to the workflow host from +the host running ‘cylc play’

+
+

Added in version 8.3.0.

+
+
+ +
+
+[selection]
+
+
Path:
+

global.cylc[platforms][<platform name>][selection]

+
+
+

How to select a host from the list of platform hosts.

+
+

Added in version 8.0.0.

+
+
+
+method
+
+
Path:
+

global.cylc[platforms][<platform name>][selection]method

+
+
Type:
+

string

+
+
Default:
+

random

+
+
Options:
+

random, definition order

+
+
+

Host selection method for the platform.

+

Available options

+
    +
  • random: Choose randomly from the list of hosts. +This is suitable for a pool of identical hosts.

  • +
  • definition order: Take the first host in the list +unless that host was unreachable. In many cases +this is likely to cause load imbalances, but might +be appropriate if following the pattern +hosts = main, backup, failsafe.

  • +
+
+

Added in version 8.0.0.

+
+
+ +
+ +
+
+[directives]
+
+
Path:
+

global.cylc[platforms][<platform name>][directives]

+
+
Defaults For:
+

flow.cylc[runtime][<namespace>][directives].

+
+
+

Job runner (batch scheduler) directives.

+
+

Added in version 8.0.0.

+
+
+
+<directive>
+
+
Path:
+

global.cylc[platforms][<platform name>][directives]<directive>

+
+
Type:
+

string

+
+
+

Example directives for the built-in job runner handlers are shown in +Supported Job Submission Methods.

+
+ +
+ +
+ +
+
+[localhost]
+
+
Path:
+

global.cylc[platforms][localhost]

+
+
Inherits:
+

global.cylc[platforms][<platform name>]

+
+
+

A default platform for running jobs on the the scheduler host.

+

This platform configures the host on which +schedulers run. By default this is the +host where cylc play is run, however, we often configure +Cylc to start schedulers on dedicated hosts by configuring +global.cylc[scheduler][run hosts]available.

+

This platform affects connections made to the scheduler host and +any jobs run on it.

+
+

Added in version 8.0.0.

+
+
+
+hosts
+
+
Path:
+

global.cylc[platforms][localhost]hosts

+
+
Type:
+

list

+
+
Default:
+

localhost

+
+
+

List of hosts for the localhost platform. You are unlikely to +need to change this.

+

The scheduler hosts are configured by +global.cylc[scheduler][run hosts]available. +See Submitting Workflows To a Pool Of Hosts for +more information.

+ +
+ +
+
+[selection]
+
+
Path:
+

global.cylc[platforms][localhost][selection]

+
+
Inherits:
+

global.cylc[platforms][<platform name>][selection]

+
+
+

How to select a host on the “localhost” platform.You are unlikely to need to change this.:cylc:conf:global.cylc[platforms][<platform name>][selection]

+
+
+method
+
+
Path:
+

global.cylc[platforms][localhost][selection]method

+
+
Type:
+

string

+
+
Default:
+

definition order

+
+
+

Host selection method for the “localhost” platform.

+ +
+ +
+ +
+ +
+ +
+
+[platform groups]
+
+
Path:
+

global.cylc[platform groups]

+
+
+

Platform groups allow you to group together platforms which would +all be suitable for a given job.

+

When Cylc submits a job it will pick a platform from a group. +Cylc will then use the selected platform for all interactions with +that job.

+

For example, if you have a group of computers +without a shared file system, but otherwise identical called +bigmachine01..02 you might set up a platform group +[[bigmachines]]platforms=bigmachine01, bigmachine02.

+
+

See also

+ +
+
+

Added in version 8.0.0.

+
+
+
+[<group>]
+
+
Path:
+

global.cylc[platform groups][<group>]

+
+
+

The name of a platform group.

+
+
+[meta]
+
+
Path:
+

global.cylc[platform groups][<group>][meta]

+
+
+

Metadata for this platform or platform group.

+

Allows writers of platform configurations to add information +about platform usage. There are no-preset items because +Cylc does not use any platform (or group) metadata internally.

+

Users can then see information about defined platforms using:

+
cylc config -i [platforms]
+cylc config -i [platform groups]
+
+
+ +
+

Added in version 8.0.0.

+
+
+
+<custom metadata>
+
+
Path:
+

global.cylc[platform groups][<group>][meta]<custom metadata>

+
+
Type:
+

string

+
+
+

Any user-defined metadata item.

+
+

Added in version 8.0.0.

+
+
+ +
+ +
+
+platforms
+
+
Path:
+

global.cylc[platform groups][<group>]platforms

+
+
Type:
+

list

+
+
+

A list of platforms which can be selected if +flow.cylc[runtime][<namespace>]platform matches +the name of this platform group.

+
+

Added in version 8.0.0.

+
+
+

Note

+

Some job runners (“background”, “at”) require a single-host +platform, because the job ID is only valid on the submission +host.

+
+
+ +
+
+[selection]
+
+
Path:
+

global.cylc[platform groups][<group>][selection]

+
+
+

Sets how platforms are selected from platform groups.

+
+
+method
+
+
Path:
+

global.cylc[platform groups][<group>][selection]method

+
+
Type:
+

string

+
+
Default:
+

random

+
+
Options:
+

random, definition order

+
+
+

Method for selecting platform from group.

+

options:

+
    +
  • random: Suitable for an identical pool of platforms.

  • +
  • definition order: Pick the first available platform +from the list.

  • +
+
+

Added in version 8.0.0.

+
+
+ +
+ +
+ +
+ +
+
+[task events]
+
+
Path:
+

global.cylc[task events]

+
+
Defaults For:
+

flow.cylc[runtime][<namespace>][events].

+
+
+

Configure the task event handling system.

+
+

Added in version 8.0.0.

+
+
+
+execution timeout
+
+
Path:
+

global.cylc[task events]execution timeout

+
+
Type:
+

time interval

+
+
Default For:
+

flow.cylc[runtime][<namespace>][events]execution timeout.

+
+
+

If a task has not finished after the specified interval, the execution +timeout event handler(s) will be called.

+
+ +
+
+handlers
+
+
Path:
+

global.cylc[task events]handlers

+
+
Type:
+

list

+
+
Default For:
+

flow.cylc[runtime][<namespace>][events]handlers.

+
+
+

Commands to run on task handler events.

+
+ +
+
+handler events
+
+
Path:
+

global.cylc[task events]handler events

+
+
Type:
+

list

+
+
Default For:
+

flow.cylc[runtime][<namespace>][events]handler events.

+
+
+

A list of events for which handlers are run.

+
+ +
+
+handler retry delays
+
+
Path:
+

global.cylc[task events]handler retry delays

+
+
Type:
+

time interval list

+
+
Default For:
+

flow.cylc[runtime][<namespace>][events]handler retry delays.

+
+
+

Specify an initial delay before running an event handler command and +any retry delays in case the command returns a non-zero code.

+
+ +
+
+mail events
+
+
Path:
+

global.cylc[task events]mail events

+
+
Type:
+

list

+
+
Default For:
+

flow.cylc[runtime][<namespace>][events]mail events.

+
+
+

Specify the events for which notification emails should be sent.

+
+ +
+
+submission timeout
+
+
Path:
+

global.cylc[task events]submission timeout

+
+
Type:
+

time interval

+
+
Default For:
+

flow.cylc[runtime][<namespace>][events]submission timeout.

+
+
+

If a task has not started after the specified interval, the submission +timeout event handler(s) will be called.

+
+ +
+ +
+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/config/index.html b/nightly_8.4/html/reference/config/index.html new file mode 100644 index 00000000000..049be620307 --- /dev/null +++ b/nightly_8.4/html/reference/config/index.html @@ -0,0 +1,210 @@ + + + + + + + Configuration — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/config/sharing-access-to-workflows.html b/nightly_8.4/html/reference/config/sharing-access-to-workflows.html new file mode 100644 index 00000000000..8764395d767 --- /dev/null +++ b/nightly_8.4/html/reference/config/sharing-access-to-workflows.html @@ -0,0 +1,615 @@ + + + + + + + Authorizing Others to Access Your Workflows — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Authorizing Others to Access Your Workflows

+

For multi-user setups, the Cylc web GUI can be deployed as part of a +Jupyter Hub setup where a central service spawns servers on behalf of users.

+

The Cylc UI Server can be configured to allow specified users to monitor and +optionally control workflows running under other user accounts.

+

This has many use cases including:

+
    +
  • Collaborative research setups where multiple users need to access the same +workflow.

  • +
  • Production systems where different levels of support may have different +levels of access.

  • +
  • Support where administrators may require access to users workflows.

  • +
+

A multi-user Cylc setup consists of three components:

+
    +
  1. Jupyter Hub

  2. +
  3. Jupyter Server

  4. +
  5. Cylc UI Server

  6. +
+

And may additionally include other Jupyter Server extensions such as +Jupyter Lab to provide a full interactive virtual workstation in the +browser.

+

In order to allow access to other users servers, to permit the monitoring and +optionally control of other users workflows, each of these three components +must be configured:

+
    +
  1. Jupyter Hub must be configured to allow connections to other users servers.

  2. +
  3. The Jupyter Server authorisation policy must be set.

  4. +
  5. Cylc must be configured with user permissions.

  6. +
+

This configuration can all be performed in the same Jupyter / Cylc UI Server +configuration file. See UI Server Configuration for more details.

+

Quick Example:

+
# /etc/cylc/uiserver/jupyter_config.py
+
+# 1. Jupyter Hub
+#    Allow all authenticated users to access, start and stop
+#    each other's servers
+c.JupyterHub.load_roles = [
+    {
+        "name": "user",
+        "scopes": ["self", "access:servers", "servers"],
+    }
+]
+
+
+# 2. Jupyter Server
+#    Set a safe authorisation policy for multi-user setups
+#    Note: This is ONLY necessary if you are deploying the Cylc UI Server
+#          using commands other than `cylc hub` and `cylc hubapp`,
+#          otherwise, it is the default.
+from cylc.uiserver.authorise import CylcAuthorizer
+c.ServerApp.authorizer_class = CylcAuthorizer
+
+
+# 3. Cylc
+#    Delegate permissions to users
+c.CylcUIServer.user_authorization = {
+    # provide all authenticated users with read-only access to each other's
+    # servers
+    "*": ["READ"],
+}
+
+
+

The rest of this document takes you through each of these configurations, some +of the key options and how they relate to their respective systems.

+
+

Jupyter Hub Authorisation

+

By default, Jupyter Hub only allows users to access their own servers.

+

In order to allow access to other users’ servers, two scopes must be configured:

+
+
access:servers

Permits us to connect to another user’s server.

+
+
servers

Permits us to start another user’s server.

+
+
+

This is done using the +c.JupyterHub.load_roles +configuration. +For more information see the +JupyterHub scopes reference.

+

Example:

+
# /etc/cylc/uiserver/jupyter_config.py
+
+c.JupyterHub.load_roles = [
+    {
+        # allow all authenticated users to access, start and stop
+        # each other's servers
+        "name": "user",
+        "scopes": ["self", "access:servers", "servers"],
+    }
+]
+
+
+
+
+

Jupyter Server Authorisation

+
+

Tip

+

You can skip this section if you are starting Jupyter Hub using cylc hub +command and have not overridden the +c.JupyterHub.spawner_class +configuration (so are spawning the cylc hubapp command).

+
+
+
+class cylc.uiserver.authorise.CylcAuthorizer(**kwargs)[source]
+

Defines a safe default authorization policy for Jupyter Server.

+

Jupyter Server provides an authorisation layer which gives full +permissions to any user who has been granted permission to the Jupyter Hub +access:servers scope +(see JupyterHub scopes reference). This allows +the execution of arbitrary code under another user account.

+

To prevent this you must define an authorisation policy using +c.ServerApp.authorizer_class.

+

This class defines a policy which blocks all API calls to another user’s +server, apart from calls to Cylc interfaces explicitly defined in the +Cylc authorisation configuration.

+

This class is configured as the default authoriser for all Jupyter Server +instances spawned via the cylc hubapp command. This is the default if +you started Jupyter Hub using the cylc hub command. To see where +this default is set, see this file for the appropriate release of +cylc-uiserver: +https://github.com/cylc/cylc-uiserver/blob/master/cylc/uiserver/jupyter_config.py

+

If you are launching Jupyter Hub via another command (e.g. jupyterhub) +or are overriding jupyterhub.app.JupyterHub.spawner_class, then +you will need to configure a safe authorisation policy e.g:

+
from cylc.uiserver.authorise import CylcAuthorizer
+c.ServerApp.authorizer_class = CylcAuthorizer
+
+
+
+

Note

+

It is possible to provide read-only access to Jupyter Server extensions +such as Jupyter Lab, however, this isn’t advisable as Jupyter Lab does +not apply file-system permissions to what another user is allowed to +see.

+

If you wish to grant users access to other user’s Jupyter Lab servers, +override this configuration with due care over what you choose to +expose.

+
+
+ +
+
+

Cylc User Authorisation

+

Cylc Authorisation is configurable on a per-user and per-command basis but +not on a per-workflow basis.

+

By default users can only see and interact with their own workflows.

+

Sites can restrict the permissions that users are allowed to grant each +other and can configure default permissions (see Cylc Site Configuration).

+

Authorization is configured by these two configurations:

+ +

Example:

+
# ~/.cylc/uiserver/jupyter_config.py
+
+c.CylcUIServer.user_authorization = {
+    # <user/group>: [<permission>, ...],
+
+    # allow "user1" to monitor my workflows
+    "user1": ["READ"],
+
+    # allow "user2" to monitor and trigger tasks in my workflows
+    "user2": ["READ", "Trigger"],
+}
+
+
+
+

Users

+

There are three methods of identifying a user to grant access to:

+
+
<username>

Configures permissions for a single user.

+
+
group:<groupname>

Configures a user group. For more information, see Group Support.

+
+
*

Configures permissions for any authenticated user (see +Jupyter Hub authenticators reference +for details).

+
+
+
+

Note

+

Using glob patterns to match user and group names is +not currently supported.

+
+
+
+

Permissions

+

Permissions can be granted for each Cylc command individually. For convenience, +commands are arranged into groups to avoid having to list them individually:

+
+
READ (i.e. read-only access)

A user with read permissions may view workflows, monitor tasks states and +open log files, but they cannot interact with the workflows.

+
    +
  • Read

  • +
+
+
CONTROL (e.g. start & stop workflows)

A user with control permissions may issue commands to interact with workflows +and can start/stop workflows but cannot redefine the workflow configuration +itself (without direct filesystem access).

+
    +
  • Clean

  • +
  • Ext-trigger

  • +
  • Hold

  • +
  • Kill

  • +
  • Message

  • +
  • Pause

  • +
  • Play

  • +
  • Poll

  • +
  • Release

  • +
  • ReleaseHoldPoint

  • +
  • Reload

  • +
  • Remove

  • +
  • Resume

  • +
  • SetGraphWindowExtent

  • +
  • SetHoldPoint

  • +
  • SetOutputs

  • +
  • SetVerbosity

  • +
  • Stop

  • +
  • Trigger

  • +
+
+
ALL (i.e. full control)

A user with all permissions may alter task configuration so may inject +arbitrary code into the workflow.

+
    +
  • Broadcast

  • +
+
+
+
+

Note

+

With the exception of Read all of the above permissions map onto the +Cylc GraphQL mutations which themselves map onto the command line.

+

E.G. the Play permission maps onto mutation play in the GraphQL +schema and cylc play on the command line.

+

To find out more about a command, see the GraphQL or CLI documentation.

+
+

By default, users have full permissions (READ, CONTROL and ALL) for their own workflows and no +permissions for other users’ workflows.

+

Permissions are additive, so for example, granting READ and CONTROL +would provide all of the permissions from those two groups.

+

The ! character can be used to subtract permissions, e.g. delegating +CONTROL and !Stop would provide all control permissions except stop.

+
+

Note

+

Granting access to a group does not automatically grant access to lower +groups e.g. granting CONTROL access does not automatically grant +READ access.

+
+
+
+

Examples

+
# ~/.cylc/uiserver/jupyter_config.py
+
+c.CylcUIServer.user_authorization = {
+    "*": ["READ"],
+    "group:groupA": ["CONTROL"],
+    "user1": ["read", "pause", "!play"],
+    "user2": ["!ALL"]
+}
+
+
+

In this scenario:

+
    +
  • "*" represents any authenticated user. They have permission to view all +workflows on the GUI.

  • +
  • "group:groupA" applies CONTROL permissions to any member of system +groupA. +Note that, since permissions are inherited, these users will gain READ access +from the "*":["READ"] assignment.

  • +
  • "user1" will have permission to view workflows, pause but not play +workflows, even if user1 is a member of the system groupA. This is due +to negations taking precedence over additions.

  • +
  • "user2" is not permitted to view workflows, or perform any operations.

  • +
+
+
+
+

Cylc Site Configuration

+

The c.CylcUIServer.site_authorization configuration allows sites +to configure sensible defaults and limits for the permissions users can +grant.

+

It takes the form:

+
{
+  "<owner>": {
+    "<user>": {
+      "default": [],
+      "limit": []
+    }
+  }
+}
+
+
+

Where <owner> is the username of the account that is running a server and +<user> is the username of an account trying to connect to it.

+

Sites can set both limits and defaults for users:

+
+
limit

Determines the maximum access users can grant to their workflows.

+
+
default

Sets a default access level, which applies if the user does not appear in +the user_authorization configuration (via explicit user name or group).

+

Note, these defaults apply only if a user does not appear in +c.CylcUIServer.user_authorization.

+
+
+
    +
  • If a limit is not set but a default is, then the limit is the default.

  • +
  • If a default is not set but a limit is, then the default is no access.

  • +
+
+

Note

+

As the UI Server runs as the workflow owner, the owner has full control over +it and in theory may bypass these restrictions in a variety of ways. As an +extreme example, a workflow owner could pass their account credentials to +another person. This cannot be prevented by technical means. However, a +workflow owner cannot unilaterally gain access to any other user’s account +or workflows by configuring their own UI Server.

+
+
+

Note

+

Changes to the Cylc authorization configuration will take effect when the +Cylc UI Server is restarted.

+
+
+

Group Support

+

Unix-like systems support user groups. Cylc authorization supports granting +access by membership of these system groups. You can indicate a system group +by using the group: indicator.

+

System groups are found by +get_groups

+
+
+cylc.uiserver.authorise.get_groups(username)[source]
+

Return a list of system groups for given user.

+

Uses os.getgrouplist and os.NGROUPS_MAX to get system groups for a +given user. grp.getgrgid then parses these to return a list of group +names.

+
+
Parameters:
+

username (str) – username used to check system groups.

+
+
Returns:
+

System groups for username given

+
+
Return type:
+

Tuple[List[str], List[str]]

+
+
+
+ +
+
+

Example Site Authorization Configuration

+

Whilst most site configurations will be simpler than the example below, this +example provides an indication of the combinations available.

+
# /etc/cylc/uiserver/jupyter_config.py
+
+c.CylcUIServer.site_authorization = {
+    "*": {  # For all ui-server owners,
+        "*": {  # Any authenticated user
+            "default": "READ",  # Will have default read-only access
+        },
+        "user1": {  # for all ui-server owners, user1
+            "default": ["!ALL"],  # has no privileges by default
+        },  # No limit set, so all ui-server owners are unable to permit user1
+    },
+    "server_owner_1": {  # For specific UI Server owner, server_owner_1
+        "*": {  # Any authenticated user
+            "default": "READ",  # Will have default read-only access
+            "limit": ["READ", "CONTROL"],  # server_owner_1 is able to give away
+        },  # READ and CONTROL privileges.
+    },
+    "server_owner_2": {  # For specific UI Server owner,
+        "user2": {  # Specific user2
+            "limit": "ALL"  # Can only be granted a maximum of ALL by
+        },  # server_owner2, default access for user2 falls back to
+        # standard READ only (if server_owner_2/user2 are
+        # included in other auth config e.g. the top example),
+        # or none if not in any other auth config sections.
+        "group:groupA": {  # group denoted with a `group:`
+            "default": [
+                "READ",
+                "CONTROL",
+            ]  # groupA has default READ, CONTROL access to server_owner_2's
+        },  # workflows
+    },
+    "group:grp_of_svr_owners": {  # Group of users who own UI Servers
+        "group:groupB": {
+            "default": "READ",  # can grant groupB users up to READ and CONTROL
+            "limit": [  # privileges, without stop and kill
+                "READ",
+                "CONTROL",
+                "!stop",  # operations
+                "!kill",
+            ],
+        },
+    },
+}
+
+
+
+
+
+

Interacting with Others’ Workflows

+

If you have been granted access to another user’s workflows, you can view and +interact with these workflows. +Say, you, userA, wish to interact with userB’s workflows. +You can do this by navigating to the URL https://<hub>/user/userB, using +the hub of userB. You should authenticate as yourself (userA) and, provided you +have the correct permissions, you will see userB’s workflows for interaction.

+
+

Note

+

Operations that are not authorized will appear greyed out on the UI.

+
+
+
+

Troubleshooting Authorization

+

If authorization is not performing as expected, check

+
    +
  • you are permitted by the site configuration to give away access.

  • +
  • you have provided read permissions, which enables the user to see your +workflows.

  • +
  • check the spelling in your configuration. The correct spelling is +c.CylcUIServer.user_authorization

  • +
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/config/shorthand.html b/nightly_8.4/html/reference/config/shorthand.html new file mode 100644 index 00000000000..0e45f783997 --- /dev/null +++ b/nightly_8.4/html/reference/config/shorthand.html @@ -0,0 +1,163 @@ + + + + + + + <no title> — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

We often use a compact single-line notation to refer to nested config items:

+
+
[section]

An entire section.

+
+
[section]setting

A setting within a section.

+
+
[section]setting=value

The value of a setting within a section.

+
+
[section][sub-section]another-setting

A setting within a sub-section.

+
+
+

In the file, however, section headings need additional brackets at each level.

+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/config/types.html b/nightly_8.4/html/reference/config/types.html new file mode 100644 index 00000000000..e94b47b77d4 --- /dev/null +++ b/nightly_8.4/html/reference/config/types.html @@ -0,0 +1,407 @@ + + + + + + + Cylc Configuration Data Types — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Cylc Configuration Data Types

+

The Cylc configuration file format supports the following data types.

+
+
+absolute host list
+

A comma separated list of hostnames which does not contain any self references (i.e. does not contain localhost, 127.0.0.1, 0.0.0.0)

+

Examples:

+
    +
  • foo

  • +
  • bar

  • +
  • baz

  • +
+
+ +
+
+boolean
+

A boolean in Python format

+

Examples:

+
    +
  • True

  • +
  • False

  • +
+
+ +
+
+cycle point
+

An integer or date-time cycle point as appropriate.

+

Examples:

+
    +
  • 1 - An integer cycle point.

  • +
  • 2000-01-01T00:00Z - A date-time cycle point.

  • +
  • now - The current date-time.

  • +
  • next(T-00) - The current date-time rounded up to the nearest whole hour.

  • +
+

See Also:

+ +
+ +
+
+cycle point format
+

An time format for date-time cycle points in isodatetime “print” or “parse” format. See isodatetime --help for more information.

+

Examples:

+
    +
  • CCYYMM - isodatetime print format.

  • +
  • %Y%m - isodatetime parse format.

  • +
+
+ +
+
+cycle point time zone
+

A time zone for date-time cycle points in ISO8601 format.

+

Examples:

+
    +
  • Z - UTC / GMT.

  • +
  • +13 - UTC plus 13 hours.

  • +
  • -0830 - UTC minus 8 hours and 30 minutes.

  • +
+
+ +
+
+cycle point with support for offsets
+

An integer or date-time cycle point, with optional offset(s).

+

Examples:

+
    +
  • 1 - An integer cycle point.

  • +
  • 1 +P5 - An integer cycle point with an offset (this evaluates as 6).

  • +
  • +P5 - An integer cycle point offset. This offset is added to the initial cycle point

  • +
  • 2000-01-01T00:00Z - A date-time cycle point.

  • +
  • 2000-02-29T00:00Z +P1D +P1M - A date-time cycle point with offsets (this evaluates as 2000-04-01T00:00Z).

  • +
+
+ +
+
+float
+

A number in integer, decimal or exponential format

+

Examples:

+
    +
  • 1

  • +
  • 1.1

  • +
  • 1.1e11

  • +
+
+ +
+
+float list
+

A comma separated list of floats.

+

Examples:

+
    +
  • 1, 1.1, 1.1e11

  • +
+
+ +
+
+integer
+

An integer.

+

Examples:

+
    +
  • 1

  • +
  • 2

  • +
  • 3

  • +
+
+ +
+
+integer list
+

A comma separated list of integers.

+

Examples:

+
    +
  • 1, 2, 3

  • +
  • 1..3

  • +
  • 1..3, 7

  • +
+
+ +
+
+time interval
+

An ISO8601 duration.

+

Examples:

+
    +
  • P1Y - Every year.

  • +
  • PT6H - Every six hours.

  • +
+

See Also:

+ +
+ +
+
+time interval list
+

A comma separated list of time intervals. These can include multipliers.

+

Examples:

+
    +
  • P1Y, P2Y, P3Y - After 1, 2 and 3 years.

  • +
  • PT1M, 2*PT1H, P1D - After 1 minute, 1 hour, 1 hour and 1 day

  • +
+

See Also:

+ +
+ +
+
+parameter list
+

A comma separated list of Cylc parameter values. This can include strings, integers and integer ranges.

+

Examples:

+
    +
  • foo, bar, baz - List of string parameters.

  • +
  • 1, 2, 3 - List of integer parameters.

  • +
  • 1..3 - The same as 1, 2, 3.

  • +
  • 1..5..2 - The same as 1, 3, 5.

  • +
  • 1..5..2, 8 - Range and integers can be mixed.

  • +
+

See Also:

+ +
+ +
+
+integer range
+

An integer range specified by a minimum and maximum value.

+

Examples:

+
    +
  • 1..5 - The numbers 1 to 5 inclusive.

  • +
+
+ +
+
+spaceless list
+

A comma separated list of strings which cannot contain spaces.

+

Examples:

+
    +
  • a, b, c

  • +
+
+ +
+
+string
+

Plain text.

+

Examples:

+
    +
  • Hello World!

  • +
+
+ +
+
+list
+

A comma separated list of strings.

+

Examples:

+
    +
  • a, b c, d

  • +
+
+ +
+
+xtrigger function signature
+

A function signature similar to how it would be written in Python. +<function>(<arg>, <kwarg>=<value>):<interval>

+

Examples:

+
    +
  • mytrigger(42, cycle_point=%(point)):PT10S - Run function mytrigger every 10 seconds.

  • +
+

See Also:

+ +
+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/config/ui-server.html b/nightly_8.4/html/reference/config/ui-server.html new file mode 100644 index 00000000000..36b315bed97 --- /dev/null +++ b/nightly_8.4/html/reference/config/ui-server.html @@ -0,0 +1,391 @@ + + + + + + + UI Server Configuration — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

UI Server Configuration

+

Cylc UI Server can be configured using a jupyter_config.py.

+

Site level configuration, such as c.CylcUIServer.site_authorization should +be defined in /etc/cylc/uiserver/jupyter_config.py, or, alternatively, the +environment variable CYLC_SITE_CONF_PATH. +User level configuration should be located in ~/.cylc/uiserver/jupyter_config.py.

+

Cylc UI Server can be configured using a jupyter_config.py file, loaded +from a hierarchy of locations. This hierarchy includes the prepackaged +configuration, the site directory (which defaults to /etc/cylc/uiserver but +can be set with the environment variable $CYLC_SITE_CONF_PATH) and +the user directory (~/.cylc/uiserver). +For example, at Cylc UI Server version 0.6.0, the hierarchy (highest priority +at the bottom) would be:

+
    +
  • cylc/uiserver/jupyter_config.py (pre-packaged default)

  • +
  • /etc/cylc/uiserver/jupyter_config.py

  • +
  • /etc/cylc/uiserver/0/jupyter_config.py

  • +
  • /etc/cylc/uiserver/0.6/jupyter_config.py

  • +
  • /etc/cylc/uiserver/0.6.0/jupyter_config.py

  • +
  • ~/.cylc/uiserver/jupyter_config.py

  • +
  • ~/.cylc/uiserver/0/jupyter_config.py

  • +
  • ~/.cylc/uiserver/0.6/jupyter_config.py

  • +
  • ~/.cylc/uiserver/0.6.0/jupyter_config.py

  • +
+

An example configuration might look like this:

+
# scan for workflows every 10 seconds
+c.CylcUIServer.scan_interval = 10
+
+
+

The Cylc UI Server is a Jupyter Server extension. For generic configuration +options see the Jupyter Servers documentation: +Config file and command line options. +Cylc specific configurations are documented here.

+
+

Note

+

c.CylcUIServer.site_authorization should be defined in +/etc/cylc/uiserver/jupyter_config.py, or, alternatively, via +the environment variable CYLC_SITE_CONF_PATH.

+
+
+
+class cylc.uiserver.app.CylcUIServer(**kwargs)[source]
+
+
+max_threads c.CylcUIServer.max_threads = Int(100)
+

Set the maximum number of threads the Cylc UI Server can use.

+

This determines the maximum number of active workflows that the +server can track.

+
+ +
+
+max_workers c.CylcUIServer.max_workers = Int(1)
+

Set the maximum number of workers for process pools.

+
+ +
+
+profile c.CylcUIServer.profile = Bool(False)
+

Turn on Python profiling.

+

The profile results will be saved to ~/.cylc/uiserver/profile.prof +in cprofile format.

+
+ +
+
+scan_interval c.CylcUIServer.scan_interval = Float(5.0)
+

Set the interval between workflow scans in seconds.

+

Workflow scans allow a UI server to detect workflows which have +been started from the CLI since the last update.

+

This involves a number of filesystem operations, to reduce +system load set a higher value.

+
+ +
+
+site_authorization c.CylcUIServer.site_authorization = Dict()
+

Dictionary containing site limits and defaults for authorization.

+

This configuration should be placed only in the site set +configuration file and not the user configuration file (use +c.CylcUIServer.user_authorization for user defined +authorization).

+

If this configuration is empty, site authorization defaults to no +configurable authorization and users will be unable to set any +authorization.

+

Authorization can be granted at operation (mutation) level, i.e. +specifically grant user access to execute Cylc commands, e.g. +play, pause, edit, trigger etc. For your +convenience, these operations have been mapped to access groups +READ, CONTROL and ALL.

+

To remove permissions, prepend the access group or operation with +!.

+

Permissions are additive but negated permissions take precedence +above additions e.g. CONTROL, !stop will permit all operations +in the CONTROL group except for stop.

+
+

Note

+

Any authorization permissions granted to a user will be +applied to all workflows.

+
+

For more information, including the access group mappings, see +Authorizing Others to Access Your Workflows.

+

Example Configuration:

+
c.CylcUIServer.site_authorization = {
+    "*": {  # For all ui-server owners,
+        "*": {  # Any authenticated user
+            "default": "READ",  # Has default read access
+        },
+        "user1": {  # user1
+            "default": ["!ALL"],  # No privileges for all
+            # ui-server owners.
+        },  # No limit set, so all ui-server owners
+    },  # limit is also "!ALL" for user1
+    "server_owner_1": {  # For specific UI Server owner,
+        "group:group_a": {  # Any member of group_a
+            "default": "READ",  # Will have default read access
+            "limit": ["ALL", "!play"],  # server_owner_1 can
+        },  # grant All privileges, except play.
+    },
+    "group:grp_of_svr_owners": {  # Group of UI Server owners
+        "group:group_b": {
+            "limit": [  # can grant groupB users up to READ and
+                "READ",  # CONTROL privileges, without stop and
+                "CONTROL",  # kill
+                "!stop",
+                "!kill",  # No default, so default is no access
+            ],
+        },
+    },
+}
+
+
+
+ +
+
+ui_build_dir c.CylcUIServer.ui_build_dir = PathType()
+

The directory containing the UI build.

+

This can be a directory containing a single UI build e.g:

+
dir/
+    index.html
+
+
+

Or a tree of builds where each build has a version number e.g:

+
dir/
+    1.0/
+        index.html
+    2.0/
+        index.html
+
+
+

By default this points at the UI build tree which was bundled with +the UI Server. Change this if you want to pick up a different +build e.g. for development or evaluation purposes.

+

Takes effect on (re)start.

+
+ +
+
+ui_version c.CylcUIServer.ui_version = Unicode('')
+

Hardcodes the UI version to serve.

+

If the ui_build_dir is a tree of builds, this config can be +used to determine which UI build is used.

+

By default the highest version is chosen according to PEP440 +version sorting rules.

+

Takes effect on (re)start.

+
+ +
+
+user_authorization c.CylcUIServer.user_authorization = Dict()
+

Dictionary containing authorized users and permission levels for +authorization.

+

Use this setting to share control of your workflows +with other users.

+

Note that you are only permitted to give away permissions up to +your limit for each user, as defined in the site_authorization +configuration.

+

Authorization can be granted at operation (mutation) level, i.e. +specifically grant user access to execute Cylc commands, e.g. +play, pause, edit, trigger etc. For your +convenience, these operations have been mapped to access groups +READ, CONTROL and ALL.

+

To remove permissions, prepend the access group or operation with +!.

+

Permissions are additive but negated permissions take precedence +above additions e.g. CONTROL, !stop will permit all operations +in the CONTROL group except for stop.

+
+

Note

+

Any authorization permissions granted to a user will be +applied to all workflows.

+
+

For more information, including the access group mappings, see +Authorizing Others to Access Your Workflows.

+

Example configuration, residing in +~/.cylc/uiserver/jupyter_config.py:

+
c.CylcUIServer.user_authorization = {
+    "*": ["READ"],  # any authenticated user has READ access
+    "group:group2": ["ALL"],  # Any user in system group2 has
+                              # access to all operations
+    "userA": ["ALL", "!stop"],  # userA has ALL operations, not
+                                # stop
+}
+
+
+
+ +
+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/config/workflow.html b/nightly_8.4/html/reference/config/workflow.html new file mode 100644 index 00000000000..2a62f7a377a --- /dev/null +++ b/nightly_8.4/html/reference/config/workflow.html @@ -0,0 +1,3907 @@ + + + + + + + Workflow Configuration — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Workflow Configuration

+

Cylc workflow configurations use the .cylc file format.

+
+
+flow.cylc
+

Defines a Cylc workflow configuration.

+

After processing any embedded templating code +(see Jinja2) the resultant raw flow.cylc file +must be valid. See also The flow.cylc File for a descriptive +overview of flow.cylc files, including syntax (Syntax).

+
+

Changed in version 8.0.0: The configuration file was previously named suite.rc, but that +name is now deprecated. +The suite.rc file name now activates Cylc 7 Compatibility Mode. +Rename to flow.cylc to turn off compatibility mode.

+
+
+
+[meta]
+
+
Path:
+

flow.cylc[meta]

+
+
+

Metadata for this workflow.

+

Cylc defines and uses +the terms “title”, “description” and “URL”. +Users can define more terms, and use these in event handlers.

+

Example:

+
A user could define "workflow-priority". An event handler
+would then respond to failure events in a way set by
+"workflow-priority".
+
+
+
+
+description
+
+
Path:
+

flow.cylc[meta]description

+
+
Type:
+

string

+
+
+

A multi-line description of the workflow.

+

It can be retrieved at run time with the cylc show command.

+
+ +
+
+title
+
+
Path:
+

flow.cylc[meta]title

+
+
Type:
+

string

+
+
+

A single line description of the workflow.

+

It can be retrieved at run time with the cylc show command.

+
+ +
+
+URL
+
+
Path:
+

flow.cylc[meta]URL

+
+
Type:
+

string

+
+
+

A web URL to workflow documentation.

+

The URL can be retrieved at run time with the cylc show +command.

+

The template variable %(workflow)s will be replaced with the +actual workflow ID.

+
+

Deprecated since version 8.0.0: The %(suite_name)s template variable is deprecated, please +use %(workflow)s.

+
+ +

Example:

+

http://my-site.com/workflows/%(workflow)s/index.html

+
+ +
+
+<custom metadata>
+
+
Path:
+

flow.cylc[meta]<custom metadata>

+
+
Type:
+

string

+
+
+

Any user-defined metadata item.

+

Like title, description and URL these can be +passed to workflow event handlers to be interpreted according to +your needs.

+

For example, a user could define an item called +“workflow-priority”. An event handler could then respond to +failure events in a way set by “workflow-priority”.

+
+ +
+ +
+
+[scheduler]
+
+
Path:
+

flow.cylc[scheduler]

+
+
+

Settings for the scheduler.

+

The default value is set in the global config: global.cylc[scheduler].

+
+

Note

+

Not to be confused with flow.cylc[scheduling].

+
+
+

Changed in version 8.0.0: This item was previously called [cylc]

+
+
+
+UTC mode
+
+
Path:
+

flow.cylc[scheduler]UTC mode

+
+
Type:
+

boolean

+
+
+

If True, UTC will be used as the time zone for timestamps in +the logs. If False, the local/system time zone will be used.

+

The default value is set in the global config: global.cylc[scheduler]UTC mode.

+
+

See also

+

To set a time zone for cycle points, see +flow.cylc[scheduler]cycle point time zone.

+
+
+ +
+
+allow implicit tasks
+
+
Path:
+

flow.cylc[scheduler]allow implicit tasks

+
+
Type:
+

boolean

+
+
Default:
+

False

+
+
+

Allow tasks in the graph that are not defined in +flow.cylc[runtime].

+

Implicit tasks are tasks without explicit +definitions in flow.cylc[runtime]. By default, +these are not allowed, as they are often typos. However, +this setting can be set to True to allow implicit tasks. +It is recommended to only set this to True if required during +development/prototyping of a workflow graph, but set it to +False after finishing the flow.cylc[runtime] +section.

+
+

Cylc 7 compatibility mode

+

In Cylc 7 Compatibility Mode, implicit tasks are still +allowed unless you explicitly set this to False, or +unless a rose-suite.conf file is present (to maintain +backward compatibility with Rose 2019).

+
+
+

Added in version 8.0.0.

+
+
+ +
+
+install
+
+
Path:
+

flow.cylc[scheduler]install

+
+
Type:
+

list

+
+
+

Configure custom directories and files to be installed on remote +hosts.

+
+

Note

+

The following directories already get installed by default:

+
+
ana/

Rose ana analysis modules

+
+
app/

Rose applications

+
+
bin/

Cylc bin directory (added to PATH)

+
+
etc/

Miscellaneous resources

+
+
lib/

Cylc lib directory (lib/python added to PYTHONPATH +for workflow config)

+
+
+

These should be located in the top level of your Cylc workflow, +i.e. the directory that contains your flow.cylc file.

+
+

Directories must have a trailing slash. +For example, to add the following items to your file installation:

+
~/cylc-run/workflow_x
+|-- dir1/
+|-- dir2/
+|-- file1
+`-- file2
+
+
+
[scheduler]
+    install = dir/, dir2/, file1, file2
+
+
+
+

Added in version 8.0.0.

+
+
+ +
+
+cycle point format
+
+
Path:
+

flow.cylc[scheduler]cycle point format

+
+
Type:
+

cycle point format

+
+
+

Set the datetime format and precision that Cylc uses for +cycle points in datetime cycling +workflows.

+
+

See also

+ +
+

By default, Cylc uses a CCYYMMDDThhmmZ (Z in the special +case of UTC) or CCYYMMDDThhmm±hhmm format for writing +datetime cycle points, following the ISO 8601 standard.

+

You may use the isodatetime library’s syntax to set +the cycle point format.

+

You can also use a subset of the strptime/strftime POSIX +standard - supported tokens are %F, %H, %M, %S, +%Y, %d, %j, %m, %s, %z.

+

If specifying a format here, we recommend including a time zone - +this will be used for displaying cycle points only. To avoid +confusion, we recommend using the same time zone as +flow.cylc[scheduler]cycle point time zone.

+

The ISO 8601 extended datetime format (CCYY-MM-DDThh:mm) +cannot be used, as cycle points are used in job-log and work +directory paths where the “:” character is invalid.

+
+

Warning

+

The smallest unit included in the format sets the precision +of cycle points in the workflow. +If the precision is lower than the smallest unit +in a graph recurrence, the workflow will fail. +For example, if you set a format of CCYY, and have a +recurrence R/2000/P8M, then both the first and second +cycle points will be 2000, which is invalid.

+
+
+ +
+
+cycle point num expanded year digits
+
+
Path:
+

flow.cylc[scheduler]cycle point num expanded year digits

+
+
Type:
+

integer

+
+
Default:
+

0

+
+
+

Enable negative years or years more than four digits long.

+

For years below 0 or above 9999, the ISO 8601 standard specifies +that an extra number of year digits and a sign should be used. +This extra number needs to be written down somewhere (here).

+

For example, if this extra number is set to 2, 00Z on the 1st of +January in the year 10040 will be represented as ++0100400101T0000Z (2 extra year digits used). With this number +set to 3, 06Z on the 4th of May 1985 would be written as ++00019850504T0600Z.

+

This number defaults to 0 (no sign or extra digits used).

+
+ +
+
+cycle point time zone
+
+
Path:
+

flow.cylc[scheduler]cycle point time zone

+
+
Type:
+

cycle point time zone

+
+
+

Time zone to be used for datetime cycle points if not otherwise +specified.

+

This time zone will be used for +datetime cycle point dumping and inferring the time zone of cycle +points that are input without time zones.

+

Time zones should be expressed as ISO8601 time zone offsets +from UTC, such as +13, +1300, -0500 or +0645, +with Z representing the special case of +0000 (UTC). +Cycle points will be converted to the time zone you give and will +be represented with this string at the end.

+

If not set, it will default to UTC (Z).

+
+

Cylc 7 compatibility mode

+

In Cylc 7 Compatibility Mode, it will default to the +local/system time zone, rather than UTC.

+
+

The time zone will persist over reloads/restarts following any +local time zone changes (e.g. if the +workflow is run during winter time, then stopped, then restarted +after summer time has begun, the cycle points will remain +in winter time). Changing this setting after the workflow has +first started will have no effect.

+

If you use a custom +flow.cylc[scheduler]cycle point format, it is a good +idea to set the same time zone here. If you specify a different +one here, it will only be used for inferring timezone-less cycle +points; cycle points will be displayed in the time zone from the +cycle point format.

+
+

Caution

+

It is not recommended to write the time zone with a “:” +(e.g. +05:30), given that the time zone is used as part of +task output filenames.

+
+ +
+

Changed in version 7.8.9/7.9.4: The value set here now persists over reloads/restarts after a +system time zone change.

+
+
+

Changed in version 8.0.0: The default time zone is now Z instead of the local time of +the first workflow start.

+
+
+ +
+
+[main loop]
+
+
Path:
+

flow.cylc[scheduler][main loop]

+
+
+

Configuration of main loop plugins for the scheduler.

+

The default value is set in the global config: global.cylc[scheduler][main loop].

+

For a list of built in plugins see Main Loop Plugins.

+
+

Added in version 8.0.0.

+
+
+
+[<plugin name>]
+
+
Path:
+

flow.cylc[scheduler][main loop][<plugin name>]

+
+
+

Configure a main loop plugin.

+

The default value is set in the global config: global.cylc[scheduler][main loop][<plugin name>].

+
+

Note

+

Only the configured list of +global.cylc[scheduler][main loop]plugins +is loaded when a scheduler is started.

+
+
+

Added in version 8.0.0.

+
+
+
+interval
+
+
Path:
+

flow.cylc[scheduler][main loop][<plugin name>]interval

+
+
Type:
+

time interval

+
+
+

Interval at which the plugin is invoked.

+

The default value is set in the global config: global.cylc[scheduler][main loop][<plugin name>]interval.

+
+

Added in version 8.0.0.

+
+
+ +
+ +
+ +
+
+[events]
+
+
Path:
+

flow.cylc[scheduler][events]

+
+
+

Configure the workflow event handling system.

+

The default value is set in the global config: global.cylc[scheduler][events].

+
+
+handlers
+
+
Path:
+

flow.cylc[scheduler][events]handlers

+
+
Type:
+

list

+
+
+

Configure event handlers that run when certain workflow +events occur.

+

The default value is set in the global config: global.cylc[scheduler][events]handlers.

+

This section configures workflow event handlers; see +flow.cylc[runtime][<namespace>][events] for task event +handlers.

+

Event handlers can be held in the workflow bin/ directory, +otherwise it is up to you to ensure their location is in $PATH +(in the shell in which the scheduler runs). They should require +little resource to run and return quickly.

+

Template variables can be used to configure handlers. For a full list +of supported variables see Workflow Event Template Variables.

+
+

See also

+

Workflow Events

+
+
+ +
+
+handler events
+
+
Path:
+

flow.cylc[scheduler][events]handler events

+
+
Type:
+

list

+
+
+

Specify the events for which workflow event handlers should be invoked.

+

The default value is set in the global config: global.cylc[scheduler][events]handler events.

+
+

See also

+

Workflow Events

+
+
+ +
+
+mail events
+
+
Path:
+

flow.cylc[scheduler][events]mail events

+
+
Type:
+

list

+
+
+

Specify the workflow events for which notification emails should +be sent.

+

The default value is set in the global config: global.cylc[scheduler][events]mail events.

+
+ +
+
+startup handlers
+
+
Path:
+

flow.cylc[scheduler][events]startup handlers

+
+
Type:
+

list

+
+
+

Handlers to run at scheduler startup.

+

The default value is set in the global config: global.cylc[scheduler][events]startup handlers.

+
+

See also

+

Workflow Events

+
+
+

Changed in version 8.0.0: This item was previously called startup handler.

+
+

Examples:

+
# configure a single event handler
+startup handlers = echo foo
+
+# provide context to the handler
+startup handlers = echo %(workflow)s
+
+# configure multiple event handlers
+# (which will run in parallel)
+startup handlers = \
+    'echo %(workflow)s %(event)s', \
+    'my_exe %(event)s %(message)s', \
+    'curl -X PUT -d event=%(event)s host:port'
+
+
+
+ +
+
+shutdown handlers
+
+
Path:
+

flow.cylc[scheduler][events]shutdown handlers

+
+
Type:
+

list

+
+
+

Handlers to run at scheduler shutdown.

+

The default value is set in the global config: global.cylc[scheduler][events]shutdown handlers.

+
+

See also

+

Workflow Events

+
+
+

Changed in version 8.0.0: This item was previously called shutdown handler.

+
+

Examples:

+
# configure a single event handler
+shutdown handlers = echo foo
+
+# provide context to the handler
+shutdown handlers = echo %(workflow)s
+
+# configure multiple event handlers
+# (which will run in parallel)
+shutdown handlers = \
+    'echo %(workflow)s %(event)s', \
+    'my_exe %(event)s %(message)s', \
+    'curl -X PUT -d event=%(event)s host:port'
+
+
+
+ +
+
+abort handlers
+
+
Path:
+

flow.cylc[scheduler][events]abort handlers

+
+
Type:
+

list

+
+
+

Handlers to run if the scheduler shuts down with error status due to +a configured timeout or a fatal error condition.

+

The default value is set in the global config: global.cylc[scheduler][events]abort handlers.

+
+

See also

+

Workflow Events

+
+
+

Changed in version 8.0.0: This item was previously called aborted handler.

+
+

Examples:

+
# configure a single event handler
+abort handlers = echo foo
+
+# provide context to the handler
+abort handlers = echo %(workflow)s
+
+# configure multiple event handlers
+# (which will run in parallel)
+abort handlers = \
+    'echo %(workflow)s %(event)s', \
+    'my_exe %(event)s %(message)s', \
+    'curl -X PUT -d event=%(event)s host:port'
+
+
+
+ +
+
+workflow timeout
+
+
Path:
+

flow.cylc[scheduler][events]workflow timeout

+
+
Type:
+

time interval

+
+
+

Workflow timeout interval. The timer starts counting down at scheduler +startup. It resets on workflow restart.

+

The default value is set in the global config: global.cylc[scheduler][events]workflow timeout.

+
+

See also

+

Workflow Events

+
+
+

Added in version 8.0.0.

+
+
+ +
+
+workflow timeout handlers
+
+
Path:
+

flow.cylc[scheduler][events]workflow timeout handlers

+
+
Type:
+

list

+
+
+

Handlers to run if the workflow timer times out.

+

The default value is set in the global config: global.cylc[scheduler][events]workflow timeout handlers.

+
+

See also

+

Workflow Events

+
+
+

Added in version 8.0.0.

+
+

Examples:

+
# configure a single event handler
+workflow timeout handlers = echo foo
+
+# provide context to the handler
+workflow timeout handlers = echo %(workflow)s
+
+# configure multiple event handlers
+# (which will run in parallel)
+workflow timeout handlers = \
+    'echo %(workflow)s %(event)s', \
+    'my_exe %(event)s %(message)s', \
+    'curl -X PUT -d event=%(event)s host:port'
+
+
+
+ +
+
+abort on workflow timeout
+
+
Path:
+

flow.cylc[scheduler][events]abort on workflow timeout

+
+
Type:
+

boolean

+
+
+

Whether the scheduler should shut down immediately with error status if +the workflow timer times out.

+

The default value is set in the global config: global.cylc[scheduler][events]abort on workflow timeout.

+
+

See also

+

Workflow Events

+
+
+

Added in version 8.0.0.

+
+
+ +
+
+stall handlers
+
+
Path:
+

flow.cylc[scheduler][events]stall handlers

+
+
Type:
+

list

+
+
+

Handlers to run if the scheduler stalls.

+

The default value is set in the global config: global.cylc[scheduler][events]stall handlers.

+
+

See also

+

Workflow Events

+
+
+

Changed in version 8.0.0: This item was previously called stalled handler.

+
+

Examples:

+
# configure a single event handler
+stall handlers = echo foo
+
+# provide context to the handler
+stall handlers = echo %(workflow)s
+
+# configure multiple event handlers
+# (which will run in parallel)
+stall handlers = \
+    'echo %(workflow)s %(event)s', \
+    'my_exe %(event)s %(message)s', \
+    'curl -X PUT -d event=%(event)s host:port'
+
+
+
+ +
+
+stall timeout
+
+
Path:
+

flow.cylc[scheduler][events]stall timeout

+
+
Type:
+

time interval

+
+
+

The length of a timer which starts if the scheduler stalls.

+

The default value is set in the global config: global.cylc[scheduler][events]stall timeout.

+
+

See also

+

Workflow Events

+
+
+

Changed in version 8.0.0: This item was previously called timeout.

+
+
+ +
+
+stall timeout handlers
+
+
Path:
+

flow.cylc[scheduler][events]stall timeout handlers

+
+
Type:
+

list

+
+
+

Handlers to run if the stall timer times out.

+

The default value is set in the global config: global.cylc[scheduler][events]stall timeout handlers.

+
+

See also

+

Workflow Events

+
+
+

Changed in version 8.0.0: This item was previously called timeout handler.

+
+

Examples:

+
# configure a single event handler
+stall timeout handlers = echo foo
+
+# provide context to the handler
+stall timeout handlers = echo %(workflow)s
+
+# configure multiple event handlers
+# (which will run in parallel)
+stall timeout handlers = \
+    'echo %(workflow)s %(event)s', \
+    'my_exe %(event)s %(message)s', \
+    'curl -X PUT -d event=%(event)s host:port'
+
+
+
+ +
+
+abort on stall timeout
+
+
Path:
+

flow.cylc[scheduler][events]abort on stall timeout

+
+
Type:
+

boolean

+
+
+

Whether the scheduler should shut down immediately with error status if +the stall timer times out.

+

The default value is set in the global config: global.cylc[scheduler][events]abort on stall timeout.

+
+

See also

+

Workflow Events

+
+
+

Changed in version 8.0.0: This item was previously called abort on timeout.

+
+
+ +
+
+inactivity timeout
+
+
Path:
+

flow.cylc[scheduler][events]inactivity timeout

+
+
Type:
+

time interval

+
+
+

Scheduler inactivity timeout interval. The timer resets when any +workflow activity occurs.

+

The default value is set in the global config: global.cylc[scheduler][events]inactivity timeout.

+
+

See also

+

Workflow Events

+
+
+

Changed in version 8.0.0: This item was previously called inactivity.

+
+
+ +
+
+inactivity timeout handlers
+
+
Path:
+

flow.cylc[scheduler][events]inactivity timeout handlers

+
+
Type:
+

list

+
+
+

Handlers to run if the inactivity timer times out.

+

The default value is set in the global config: global.cylc[scheduler][events]inactivity timeout handlers.

+
+

See also

+

Workflow Events

+
+
+

Changed in version 8.0.0: This item was previously called inactivity handler.

+
+

Examples:

+
# configure a single event handler
+inactivity timeout handlers = echo foo
+
+# provide context to the handler
+inactivity timeout handlers = echo %(workflow)s
+
+# configure multiple event handlers
+# (which will run in parallel)
+inactivity timeout handlers = \
+    'echo %(workflow)s %(event)s', \
+    'my_exe %(event)s %(message)s', \
+    'curl -X PUT -d event=%(event)s host:port'
+
+
+
+ +
+
+abort on inactivity timeout
+
+
Path:
+

flow.cylc[scheduler][events]abort on inactivity timeout

+
+
Type:
+

boolean

+
+
+

Whether the scheduler should shut down immediately with error status if +the inactivity timer times out.

+

The default value is set in the global config: global.cylc[scheduler][events]abort on inactivity timeout.

+
+

See also

+

Workflow Events

+
+
+

Changed in version 8.0.0: This item was previously called abort on inactivity.

+
+
+ +
+
+restart timeout
+
+
Path:
+

flow.cylc[scheduler][events]restart timeout

+
+
Type:
+

time interval

+
+
+

How long to wait for intervention on restarting a completed workflow. +The timer stops if any task is triggered.

+

The default value is set in the global config: global.cylc[scheduler][events]restart timeout.

+
+

See also

+

Workflow Events

+
+
+

Added in version 8.2.0.

+
+
+ +
+
+expected task failures
+
+
Path:
+

flow.cylc[scheduler][events]expected task failures

+
+
Type:
+

list

+
+
+

(For Cylc developers writing a functional tests only) +List of tasks that are expected to fail in the test.

+
+ +
+ +
+
+[mail]
+
+
Path:
+

flow.cylc[scheduler][mail]

+
+
+

Settings for the scheduler to send event emails.

+

The default value is set in the global config: global.cylc[scheduler][mail].

+

These settings are used for both workflow and task events.

+
+

Added in version 8.0.0.

+
+
+
+footer
+
+
Path:
+

flow.cylc[scheduler][mail]footer

+
+
Type:
+

string

+
+
+

Specify a string or string template for footers of emails sent for both +workflow and task events.

+

The default value is set in the global config: global.cylc[scheduler][mail]footer.

+

Template variables may be used in the mail footer. For a list of supported +variables see Workflow Event Template Variables.

+

Example:

+
footer = see http://ahost/%(owner)s/notes/%(workflow)s``
+
+
+
+

Changed in version 8.0.0: This item was previously called [cylc][events]mail footer.

+
+
+ +
+
+to
+
+
Path:
+

flow.cylc[scheduler][mail]to

+
+
Type:
+

string

+
+
+

A list of email addresses that event notifications should be sent to.

+

The default value is set in the global config: global.cylc[scheduler][mail]to.

+
+

Changed in version 8.0.0: This item was previously called [cylc][events]mail to.

+
+
+ +
+
+from
+
+
Path:
+

flow.cylc[scheduler][mail]from

+
+
Type:
+

string

+
+
+

Specify an alternative from email address for workflow event notifications.

+

The default value is set in the global config: global.cylc[scheduler][mail]from.

+
+

Changed in version 8.0.0: This item was previously called [cylc][events]mail from.

+
+
+ +
+
+task event batch interval
+
+
Path:
+

flow.cylc[scheduler][mail]task event batch interval

+
+
Type:
+

time interval

+
+
+

Gather all task event notifications in the given interval into a single email.

+

The default value is set in the global config: global.cylc[scheduler][mail]task event batch interval.

+

Useful to prevent being overwhelmed by emails.

+
+

Changed in version 8.0.0: This item was previously called [cylc]task event mail interval.

+
+
+ +
+ +
+ +
+
+[task parameters]
+
+
Path:
+

flow.cylc[task parameters]

+
+
+

Set task parameters and parameter templates.

+

Define parameter values here for use in expanding +parameterized tasks.

+
+

Changed in version 8.0.0: This item was previously called [cylc][parameters].

+
+
+
+<parameter>
+
+
Path:
+

flow.cylc[task parameters]<parameter>

+
+
Type:
+

parameter list

+
+
+

A custom parameter to use in a workflow.

+

Examples:

+
    +
  • run = control, test1, test2

  • +
  • mem = 1..5 (equivalent to 1, 2, 3, 4, 5).

  • +
  • mem = -11..-7..2 (equivalent to -11, -9, -7).

  • +
+
+ +
+
+[templates]
+
+
Path:
+

flow.cylc[task parameters][templates]

+
+
+

Cylc will expand each parameterized task name using a string +template.

+

You can set templates for any parameter name here to override the +default template.

+
+

Changed in version 8.0.0: This item was previously called [cylc][parameter templates].

+
+
+
+<parameter>
+
+
Path:
+

flow.cylc[task parameters][templates]<parameter>

+
+
Type:
+

string

+
+
+

A template for a parameter.

+

For example:

+

If you set:

+
[task parameters]
+    myparameter = 1..3
+    [[templates]]
+        myparameter = _run_%(myparameter)s
+
+
+

task name foo<myparameter> becomes foo_run_3 for +run == 3.

+
+

Note

+

The default parameter templates are:

+
+
For integer parameters:

_p%(p)0Nd +where N is the number of digits of the maximum +integer value, i.e. If the largest parameter value is +3142 then N = 4.

+
+
Default for non-integer parameters:

_%(p)s e.g. foo<run> becomes foo_top for +run value top.

+
+
+
+
+ +
+ +
+ +
+
+[scheduling]
+
+
Path:
+

flow.cylc[scheduling]

+
+
+

This section allows Cylc to determine when tasks are ready to run.

+

Any cycle points defined here without a time zone will use the +time zone from +flow.cylc[scheduler]cycle point time zone.

+
+
+initial cycle point
+
+
Path:
+

flow.cylc[scheduling]initial cycle point

+
+
Type:
+

cycle point

+
+
+

The earliest cycle point at which any task can run.

+

In a cold start each cycling task (unless specifically excluded +under [special tasks]) will be loaded into the +workflow with this cycle point, or with the closest subsequent +valid cycle point for the task.

+

In integer cycling, the default is 1.

+

The string now converts to the current datetime on the workflow +host when first starting the workflow (with precision determined +by flow.cylc[scheduler]cycle point format).

+

For more information on setting the initial cycle point relative +to the current time see Setting The Initial Cycle Point Relative To The Current Time.

+

This item can be overridden on the command line using +cylc play --initial-cycle-point or --icp.

+
+ +
+
+final cycle point
+
+
Path:
+

flow.cylc[scheduling]final cycle point

+
+
Type:
+

cycle point with support for offsets

+
+
+

The (optional) last cycle point at which tasks are run.

+

Once all tasks have reached this cycle point, the +workflow will shut down.

+

This item can be overridden on the command line using +cylc play --final-cycle-point or --fcp.

+

Examples:

+
    +
  • 2000 - Shorthand for 2000-01-01T00:00.

  • +
  • +P1D - The initial cycle point plus one day.

  • +
  • 2000 +P1D +P1Y - The year 2000 plus one day and one year.

  • +
+
+ +
+
+initial cycle point constraints
+
+
Path:
+

flow.cylc[scheduling]initial cycle point constraints

+
+
Type:
+

list

+
+
+

Rules to allow only some initial datetime cycle points.

+
+

Use Case

+

Writing a workflow where users may change the initial +cycle point, but where only some initial cycle points are +reasonable.

+
+

Set by defining a list of truncated time points, which +the initial cycle point must match.

+

Examples:

+
    +
  • T00, T06, T12, T18 - only at 6 hourly intervals.

  • +
  • T-30 - only at half-past an hour.

  • +
  • 01T00 - only at midnight on the first day of a month.

  • +
+
+

See also

+

Recurrence tutorial.

+
+
+

Note

+

This setting does not coerce initial cycle point=now.

+
+
+ +
+
+final cycle point constraints
+
+
Path:
+

flow.cylc[scheduling]final cycle point constraints

+
+
Type:
+

list

+
+
+

Rules restricting permitted final cycle points.

+

In a cycling workflow it is possible to restrict the final cycle +point by defining a list of truncated time points under the final +cycle point constraints.

+
+

See also

+

Recurrence tutorial.

+
+
+ +
+
+hold after cycle point
+
+
Path:
+

flow.cylc[scheduling]hold after cycle point

+
+
Type:
+

cycle point

+
+
+

Hold all tasks that pass this cycle point.

+

Unlike the final +cycle point, the workflow does not shut down once all tasks have +passed this point. If this item is set you can override it on the +command line using --hold-after.

+
+

Changed in version 8.0.0: This item was previously called [scheduling]hold after point.

+
+
+ +
+
+stop after cycle point
+
+
Path:
+

flow.cylc[scheduling]stop after cycle point

+
+
Type:
+

cycle point with support for offsets

+
+
+

Shut down the workflow after all tasks pass this cycle point.

+

The stop cycle point can be overridden on the command line using +cylc play --stop-cycle-point=POINT

+
+

Note

+

Not to be confused with final cycle point: +There can be more graph beyond this point, but you are +choosing not to run that part of the graph. You can play +the workflow and continue.

+
+

Examples:

+
    +
  • 2000 - Shorthand for 2000-01-01T00:00.

  • +
  • +P1D - The initial cycle point plus one day.

  • +
  • 2000 +P1D +P1Y - The year 2000 plus one day and one year.

  • +
+
+

Added in version 8.0.0.

+
+
+

Changed in version 8.3.0: This now supports offsets (e.g. +P1D) in the same way the +final cycle point does.

+
+
+ +
+
+cycling mode
+
+
Path:
+

flow.cylc[scheduling]cycling mode

+
+
Type:
+

string

+
+
Default:
+

gregorian

+
+
Options:
+

360day, 360_day, 365day, 365_day, 366day, 366_day, gregorian, integer

+
+
+

Choice of integer cycling or one of several +datetime cycling calendars.

+

Cylc runs workflows using the proleptic Gregorian calendar +by default. This setting allows you to instead choose +integer cycling, or one of the other supported non-Gregorian +datetime calendars: 360 day (12 months of 30 days in a year), +365 day (never a leap year) and 366 day (always a leap year).

+
+ +
+
+runahead limit
+
+
Path:
+

flow.cylc[scheduling]runahead limit

+
+
Type:
+

string

+
+
Default:
+

P4

+
+
+

The runahead limit prevents a workflow from getting too far ahead +of the oldest cycle with active tasks.

+

A cycle is considered to be active if it contains any +active tasks.

+

An integer interval value of Pn allows up to n+1 cycles +to be active at once.

+

The default runahead limit is P4, which means there may be up +to 5 active cycles.

+

Datetime cycling workflows can optionally use a datetime interval +value instead, in which case the number of cycles +within the interval depends on the cycling intervals present.

+

Examples:

+
+
P0

Only one cycle can be active at a time.

+
+
P2

The scheduler will run up to two cycles ahead of the oldest +active cycle.

+
+
P3D

The scheduler will run cycles up to three days of cycles ahead +of the oldest active cycle.

+
+
+
+

See also

+

Runahead Limiting

+
+
+

Changed in version 8.0.0: The integer format Pn was introduced to replace the +deprecated [scheduling]max active cycle points = m +(with n = m-1) and unify it with the existing datetime +interval runahead limit setting.

+
+
+ +
+
+[queues]
+
+
Path:
+

flow.cylc[scheduling][queues]

+
+
+

Configuration of internal queues of tasks.

+

This section will allow you to limit the number of simultaneously +active tasks (submitted or running) by +assigning tasks to queues.

+

By default, a single queue called default is defined, +with all tasks assigned to it and no limit to the number of those +tasks which may be active.

+

To use a single queue for the whole workflow, but limit the number +of active tasks, set [default]limit.

+

To add additional queues define additional sections:

+
[[queues]]
+    [[[user_defined_queue]]]
+        limit = 2
+        members = TASK_FAMILY_NAME
+
+
+
+

See also

+

Internal Queues.

+
+
+
+[<queue name>]
+
+
Path:
+

flow.cylc[scheduling][queues][<queue name>]

+
+
+

Section heading for configuration of a single queue.

+
+
+limit
+
+
Path:
+

flow.cylc[scheduling][queues][<queue name>]limit

+
+
Type:
+

integer

+
+
Default:
+

0

+
+
+

The maximum number of active tasks +allowed at any one time, for this queue.

+

If set to 0 this queue is not limited.

+
+ +
+
+members
+
+
Path:
+

flow.cylc[scheduling][queues][<queue name>]members

+
+
Type:
+

spaceless list

+
+
+

A list of member tasks, or task family names to assign to +this queue.

+

Assigned tasks will automatically be removed +from the default queue.

+
+ +
+ +
+
+[default]
+
+
Path:
+

flow.cylc[scheduling][queues][default]

+
+
Inherits:
+

flow.cylc[scheduling][queues][<queue name>]

+
+
+

The default queue for all tasks not assigned to other queues.

+
+
+limit
+
+
Path:
+

flow.cylc[scheduling][queues][default]limit

+
+
Type:
+

integer

+
+
Default:
+

100

+
+
+

Controls the total number of +active tasks in the default queue.

+ +
+ +
+ +
+ +
+
+[special tasks]
+
+
Path:
+

flow.cylc[scheduling][special tasks]

+
+
+

This section is used to identify tasks with special behaviour.

+

Family names can be used in special task lists as shorthand for +listing all member tasks.

+
+
+clock-trigger
+
+
Path:
+

flow.cylc[scheduling][special tasks]clock-trigger

+
+
Type:
+

list

+
+
+

Legacy clock trigger definitions.

+
+

Deprecated since version 8.0.0: These are now auto-upgraded to the newer wall_clock xtriggers +(see External Triggers). The old way defining +clock-triggers will be removed in an upcoming Cylc version.

+
+

Clock-triggered tasks (see Clock Triggers) wait on a wall +clock time specified as an offset from their own cycle point.

+

Example:

+

foo(PT1H30M), bar(PT1.5H), baz

+
+ +
+
+external-trigger
+
+
Path:
+

flow.cylc[scheduling][special tasks]external-trigger

+
+
Type:
+

list

+
+
+

Legacy external trigger definition section.

+
+

Deprecated since version 8.0.0: Please read External Triggers before +using the older mechanism described in this section.

+
+

Externally triggered tasks (see Push External Triggers) wait on external events reported via the +cylc ext-trigger command. To constrain triggers to a +specific cycle point, include $CYLC_TASK_CYCLE_POINT +in the trigger message string and pass the cycle point to the +cylc ext-trigger command.

+
+ +
+
+clock-expire
+
+
Path:
+

flow.cylc[scheduling][special tasks]clock-expire

+
+
Type:
+

list

+
+
+

Don’t submit jobs if they are too late in wall clock time.

+

Clock-expire tasks enter the expired state and skip job +submission if too far behind the wall clock when they become +ready to run.

+

The expiry time is specified as an offset from the task’s +cycle point. The offset:

+
+
    +
  • May be positive or negative

  • +
  • May be omitted if it is zero

  • +
+
+
+

See also

+

Clock-Expire Triggers.

+
+

Examples:

+

foo(PT1H) - expire task foo if the current wall clock +time has reached 1 hour after the task’s cycle point.

+

bar(-PT5M) - expire task bar if the current wall clock +time has reached 5 minutes before the task’s cycle point.

+
+ +
+
+sequential
+
+
Path:
+

flow.cylc[scheduling][special tasks]sequential

+
+
Type:
+

list

+
+
+

A list of tasks which automatically depend on their own +previous-cycle instance.

+
+

Tip

+

Recommend best practice is now to use explicit inter-cycle +triggers rather than sequential tasks.

+
+ +
+ +
+ +
+
+sequential xtriggers
+
+
Path:
+

flow.cylc[scheduling]sequential xtriggers

+
+
Type:
+

boolean

+
+
Default:
+

False

+
+
+

If True, tasks that only depend on xtriggers will not spawn +until the xtrigger of previous (cycle point) instance is satisfied. +Otherwise, they will all spawn at once out to the runahead limit.

+

This setting can be overridden by the reserved keyword argument +sequential in individual xtrigger declarations.

+

One sequential xtrigger on a parentless task with multiple +xtriggers will cause sequential spawning.

+
+

Added in version 8.3.0.

+
+
+ +
+
+[xtriggers]
+
+
Path:
+

flow.cylc[scheduling][xtriggers]

+
+
+

This section is for External Trigger function declarations - +see External Triggers.

+
+
+<xtrigger name>
+
+
Path:
+

flow.cylc[scheduling][xtriggers]<xtrigger name>

+
+
Type:
+

xtrigger function signature

+
+
+

Any user-defined event trigger function declarations and +corresponding labels for use in the graph.

+

See External Triggers for details.

+

Example:

+
``my_trigger(arg1, arg2, kwarg1, kwarg2):PT10S``
+
+
+
+ +
+ +
+
+[graph]
+
+
Path:
+

flow.cylc[scheduling][graph]

+
+
+

The workflow graph is defined under this section.

+

You can plot the dependency graph as you work on it, with +cylc graph.

+ +
+

Changed in version 8.0.0: This item was previously called [runtime][dependencies][graph].

+
+
+
+<recurrence>
+
+
Path:
+

flow.cylc[scheduling][graph]<recurrence>

+
+
Type:
+

string

+
+
+

The recurrence defines the sequence of cycle points +for which the dependency graph is valid.

+ +

Cycle points should be specified in our ISO 8601 derived +sequence syntax, or as integers, in integer cycling mode:

+

Example Recurrences:

+
+
datetime cycling:
    +
  • R1 - once at the initial cycle point

  • +
  • T00,T06,T12,T18 - daily at 00:00, 06:00, 12:00 +& 18:00

  • +
  • PT6H - every six hours starting at the initial +cycle point

  • +
+
+
integer cycling:
    +
  • R1 - once at the initial cycle point

  • +
  • P2 - every other cycle

  • +
  • P3,P5 - every third or fifth cycle

  • +
+
+
+
+

Note

+

Unlike other Cylc configurations duplicate recurrences +are additive and do not override.

+

For example this:

+
[scheduling]
+    [[graph]]
+        R1 = a => b
+        R1 = c => d
+
+
+

Is equivalent to this:

+
[scheduling]
+    [[graph]]
+        R1 = """
+            a => b
+            c => d
+        """
+
+
+

See Graph Types for more on recurrence expressions, +and how multiple graphs combine.

+
+

The value should be a dependency graph the given recurrence. +Syntax examples follow; see also Scheduling Configuration +and Task Triggering.

+

Example Graph Strings:

+
+
# baz and waz both trigger off bar
+foo => bar => baz & waz
+
+# bar triggers off foo[-P1D-PT6H]
+foo[-P1D-PT6H] => bar
+
+# faz triggers off a message output of baz
+baz:out1 => faz
+
+# Y triggers if X starts executing
+X:start => Y
+
+# Y triggers if X fails
+X:fail => Y
+
+# bar triggers if foo[-PT6H] fails
+foo[-PT6H]:fail => bar
+
+# Y suicides if X succeeds
+X => !Y
+
+# Z triggers if X succeeds or fails
+X | X:fail => Z
+
+# Z triggers if X succeeds or fails
+X:finish => Z
+
+# general conditional triggers
+(A | B & C ) | D => foo
+
+# bar triggers if foo is successfully submitted
+foo:submit => bar
+
+# bar triggers if submission of foo fails
+foo:submit-fail => bar
+
+
+
+
+

Changed in version 8.0.0: This item was previously called +[runtime][dependencies][graph][<recurrence>]graph.

+
+
+ +
+ +
+ +
+
+[runtime]
+
+
Path:
+

flow.cylc[runtime]

+
+
+

This section is used to specify settings for tasks to be run.

+

You can specify:

+
    +
  • What scripts or commands you want to execute.

  • +
  • Which compute resource (platform) you wish to use.

  • +
  • How to run your task.

  • +
+

If multiple tasks need the same settings, they can share settings by +inheriting them from one or more other tasks.

+

Precedence is determined by the same C3 +linearization algorithm used to find the method resolution order +in Python language class hierarchies.

+
+

See also

+

For details and examples see Task Configuration.

+
+
+
+[<namespace>]
+
+
Path:
+

flow.cylc[runtime][<namespace>]

+
+
+

The name(s) of one or more tasks or task families.

+

A namespace (i.e. task or family name) or a comma-separated list +of namespace names, and repeat as needed to define all tasks in +the workflow. Names may contain letters, digits, underscores, and +hyphens. A namespace represents a group or family of tasks if +other namespaces inherit from it, or a task if no others inherit +from it.

+
+

Important

+

Names may not contain : or ..

+

See task namespace rules.

+
+

Examples of legal values:

+
    +
  • [foo]

  • +
  • [foo, bar, baz]

  • +
+

If multiple names are listed the subsequent settings apply to +all.

+

All tasks or task families inherit initially from root, which +can be explicitly configured to provide or override default +settings for all tasks in the workflow.

+
+
+completion
+
+
Path:
+

flow.cylc[runtime][<namespace>]completion

+
+
Type:
+

string

+
+
+

Define the condition for task output completion.

+

The completion condition is evaluated when a task reaches +a final state - i.e. once it finished executing (succeeded +or failed) or it submit-failed, or expired. +It is a validation check which confirms that the +task has generated the outputs it was expected to.

+

If the task fails this check its outputs are considered +incomplete and a warning will be +raised alerting you that something has gone wrong which +requires investigation.

+
+

Note

+

An event hook for this warning will follow in a future +release of Cylc.

+
+

By default, the completion condition ensures that all required +outputs, i.e. outputs which appear in the graph but are not +marked as optional with the ? character, are completed.

+

E.g., in this example, the task foo must generate the +required outputs succeeded and x and it may or may not +generate the optional output y:

+
foo => bar
+foo:x => x
+foo:y? => y
+
+
+

The default completion condition would be this:

+
# the task must succeed and generate the custom output "x"
+succeeded and x
+
+
+

You can override this default to suit your needs. E.g., in this +example, the task foo has three optional outputs, x, +y and z:

+
foo:x? => x
+foo:y? => y
+foo:z? => z
+x | y | z => bar
+
+
+

Because all three of these outputs are optional, if none of +them are generated, the task’s outputs will still be +considered complete.

+

If you wanted to require that at least one of these outputs is +generated you can configure the completion condition like so:

+
# the task must succeed and generate at least one of the
+# outputs "x" or "y" or "z":
+succeeded and (x or y or z)
+
+
+
+

Note

+

For the completion expression, hyphens in task outputs +must be replaced with underscores to allow evaluation by +Python, e.g.:

+
[runtime]
+    [[foo]]
+        completion = succeeded and my_output # underscore
+        [[[outputs]]]
+            my-output = 'my custom task output' # hyphen
+
+
+
+
+

Note

+

In some cases the succeeded output might not explicitly +appear in the graph, e.g:

+
foo:x? => x
+
+
+

In these cases success is presumed to be required unless +explicitly stated otherwise, either in the graph e.g:

+
foo?
+foo:x? => x
+
+
+

Or in the completion expression e.g:

+
completion = x  # no reference to succeeded
+# or
+completion = succeeded or failed  # success is optional
+
+
+
+
+

Hint

+

If task outputs are optional in the graph they must also +be optional in the completion condition and vice versa.

+

For example this graph conflicts with the completion +statement:

+
# "a" must succeed
+a => b
+
+
+
# "a" may either succeed or fail
+completion = succeeded or failed
+
+
+

Which could be fixed by amending the graph like so:

+
# "a" may either succeed or fail
+a? => b
+
+
+
+

Examples

+
+
succeeded

The task must succeed.

+
+
succeeded or (failed and my_error)

The task can fail, but only if it also yields the custom +output my_error.

+
+
succeeded and (x or y or z)

The task must succeed and yield at least one of the +custom outputs, x, y or z.

+
+
(a and b) or (c and d)

One pair of these outputs must be yielded for the task +to be complete.

+
+
+
+

Added in version 8.3.0.

+
+
+ +
+
+platform
+
+
Path:
+

flow.cylc[runtime][<namespace>]platform

+
+
Type:
+

string

+
+
+

The name of a compute resource defined in +global.cylc[platforms] or +global.cylc[platform groups].

+

The platform specifies the host(s) that the tasks’ jobs +will run on and where (if necessary) files need to be +installed, and what job runner will be used.

+
+

Added in version 8.0.0.

+
+
+ +
+
+inherit
+
+
Path:
+

flow.cylc[runtime][<namespace>]inherit

+
+
Type:
+

list

+
+
+

A list of the immediate parent(s) of this task or task family.

+

If no parents are listed default is root.

+
+ +
+
+script
+
+
Path:
+

flow.cylc[runtime][<namespace>]script

+
+
Type:
+

string

+
+
+

The main custom script run from the job script.

+

It can be an external command or script, or inlined scripting.

+

See Job Script Variables for the list of variables +available in the task execution environment.

+

See also Job Scripts.

+

Other user-defined script items:

+ +

Example:

+
my_script.sh
+
+
+
+ +
+
+init-script
+
+
Path:
+

flow.cylc[runtime][<namespace>]init-script

+
+
Type:
+

string

+
+
+

Custom script run by the job script before the task +execution environment is configured.

+

By running before the task execution environment is configured, +this script does not have +access to any workflow or task environment variables. It can be +an external command or script, or inlined scripting. The +original intention for this item was to allow remote tasks to +source login scripts to configure their access to cylc, but +this should no longer be necessary.

+

See also Job Scripts.

+

Other user-defined script items:

+ +

Example:

+
echo "Hello World"
+
+
+
+ +
+
+env-script
+
+
Path:
+

flow.cylc[runtime][<namespace>]env-script

+
+
Type:
+

string

+
+
+

Custom script run by the job script between the +cylc-defined environment (workflow and task identity, etc.) and +the user-defined task runtime environment.

+

The env-script has access to the Cylc environment (and the task +environment has access to variables defined by this scripting). +It can be an external command or script, or inlined scripting.

+

See also Job Scripts.

+

Other user-defined script items:

+ +

Example:

+
echo "Hello World"
+
+
+
+ +
+
+err-script
+
+
Path:
+

flow.cylc[runtime][<namespace>]err-script

+
+
Type:
+

string

+
+
+

Script run when a job error is detected.

+
+

Custom script to be run at the end of the error trap, +which is triggered due to failure of a command in the job +script or trappable job kill.

+

The output of this script will always +be sent to STDERR and $1 is set to the name of the signal +caught by the error trap. The script should be fast and use +very little system resource to ensure that the error trap can +return quickly. Companion of exit-script, +which is executed on job success. It can be an external +command or script, or inlined scripting.

+
+

See also Job Scripts.

+

Other user-defined script items:

+ +

Example:

+
echo "Uh oh, received ${1}"
+
+
+
+ +
+
+exit-script
+
+
Path:
+

flow.cylc[runtime][<namespace>]exit-script

+
+
Type:
+

string

+
+
+

Custom script run at the very end of successful job +execution, just before the job script exits.

+

The exit-script should execute very quickly. +Companion of err-script, +which is executed on job failure. It can be an external +command or script, or inlined scripting.

+

See also Job Scripts.

+

Other user-defined script items:

+ +

Example:

+
rm -f "$TMP_FILES"
+
+
+
+ +
+
+pre-script
+
+
Path:
+

flow.cylc[runtime][<namespace>]pre-script

+
+
Type:
+

string

+
+
+

Custom script run by the job script immediately +before script.

+

The pre-script can be an external command or script, or +inlined scripting.

+

See also Job Scripts.

+

Other user-defined script items:

+ +

Example:

+
echo "Hello from workflow ${CYLC_WORKFLOW_ID}!"
+
+
+
+ +
+
+post-script
+
+
Path:
+

flow.cylc[runtime][<namespace>]post-script

+
+
Type:
+

string

+
+
+

Custom script run by the job script immediately +after script.

+

The post-script can be an external +command or script, or inlined scripting.

+

See also Job Scripts.

+

Other user-defined script items:

+ +

Example:

+
echo "Hello World"
+
+
+
+ +
+
+work sub-directory
+
+
Path:
+

flow.cylc[runtime][<namespace>]work sub-directory

+
+
Type:
+

string

+
+
+

The directory from which tasks are executed.

+

Job scripts are executed from within work directories +created automatically under the workflow run directory. A task +can get its own work directory from $CYLC_TASK_WORK_DIR +(or $PWD if it does not cd elsewhere at +runtime). The default directory path contains task name and +cycle point, to provide a unique workspace for every instance +of every task. If several tasks need to exchange files and +simply read and write from their from current working +directory, setting work sub-directory can be used to +override the default to make them all use the same workspace.

+

The top level share and work directory location can be changed +(e.g. to a large data area) by a global config setting (see +global.cylc[install][symlink dirs]).

+
+

Caution

+

If you omit cycle point from the work sub-directory path +successive instances of the task will share the same +workspace. Consider the effect on cycle point offset +housekeeping of work directories before doing this.

+
+

Example:

+
+

$CYLC_TASK_CYCLE_POINT/shared/

+
+
+ +
+
+execution polling intervals
+
+
Path:
+

flow.cylc[runtime][<namespace>]execution polling intervals

+
+
Type:
+

time interval list

+
+
+

List of intervals at which to poll status of job execution.

+

The default value is set in the global config: global.cylc[platforms][<platform name>]execution polling intervals.

+

Cylc can poll running jobs to catch problems that prevent task messages from +being sent back to the workflow, such as hard job kills, network outages, or +unplanned job host shutdown.

+

The last interval in the list is used repeatedly until the job completes.

+

Multipliers can be used as shorthand as in the example below.

+

Example:

+
5*PT2M, PT5M
+
+
+

Note that if the polling +global.cylc[platforms][<platform name>]communication method is +used then Cylc relies on polling to detect all task state changes, so you may +want to configure more frequent polling.

+
+

Changed in version 8.0.0: This item was previously called [runtime][<namespace>][job]execution polling intervals.

+
+
+ +
+
+execution retry delays
+
+
Path:
+

flow.cylc[runtime][<namespace>]execution retry delays

+
+
Type:
+

time interval list

+
+
+

Cylc can automate resubmission of failed jobs.

+

Execution retry delays is a list of ISO 8601 durations which +tell Cylc how long to wait before the next try.

+

The job environment variable $CYLC_TASK_TRY_NUMBER +increments with each automatic retry, allowing you to vary task +behaviour between retries.

+

Tasks only go to the failed state if job execution fails +with no retries left.

+
+

Changed in version 8.0.0: This item was previously called [runtime][<namespace>][job]execution +retry delays.

+
+
+ +
+
+execution time limit
+
+
Path:
+

flow.cylc[runtime][<namespace>]execution time limit

+
+
Type:
+

time interval

+
+
+

Set the execution (wallclock) time +limit of a job.

+

For background and at job runners Cylc runs the +job’s script using the timeout command. For other job runners +Cylc will convert execution time limit to a directive.

+

If a job exceeds its execution time limit Cylc can +poll the job multiple times. You can set polling +intervals using global.cylc[platforms][<platform name>]execution time limit polling intervals

+
+

Changed in version 8.0.0: This item was previously called [runtime][<namespace>][job]execution +time limit.

+
+
+ +
+
+submission polling intervals
+
+
Path:
+

flow.cylc[runtime][<namespace>]submission polling intervals

+
+
Type:
+

time interval list

+
+
+

List of intervals at which to poll status of job submission.

+

The default value is set in the global config: global.cylc[platforms][<platform name>]submission polling intervals.

+

Cylc can poll submitted jobs to catch problems that prevent the submitted job +from executing at all, such as deletion from an external job runner queue.

+

The last value is used repeatedly until the task starts running.

+

Multipliers can be used as shorthand as in the example below.

+

Example:

+
5*PT2M, PT5M
+
+
+

Note that if the polling +global.cylc[platforms][<platform name>]communication method +is used then Cylc relies on polling to detect all task state changes, +so you may want to configure more frequent polling.

+
+

Changed in version 8.0.0: This item was previously called [runtime][<namespace>][job]submission polling intervals.

+
+
+ +
+
+submission retry delays
+
+
Path:
+

flow.cylc[runtime][<namespace>]submission retry delays

+
+
Type:
+

time interval list

+
+
+

Cylc can automatically resubmit jobs after submission failures.

+

The default value is set in the global config: global.cylc[platforms][<platform name>]submission retry delays.

+

Submission retry delays is a list of ISO 8601 durations which tell Cylc +how long to wait before the next try.

+

The job environment variable $CYLC_TASK_SUBMIT_NUMBER increments with each +job submission attempt.

+

Tasks only go to the submit-failed state if job submission fails with no +retries left.

+
+

Changed in version 8.0.0: This item was previously called [runtime][<namespace>][job]submission retry delays.

+
+
+ +
+
+[meta]
+
+
Path:
+

flow.cylc[runtime][<namespace>][meta]

+
+
+

Metadata for the task or task family.

+

The meta section contains metadata items for this task or +family namespace. The items title, description and +URL are pre-defined and are used by Cylc. Others can be +user-defined and passed to task event handlers to be +interpreted according to your needs. For example, the value of +an “importance” item could determine how an event handler +responds to task failure events.

+

Any workflow meta item can now be passed to task event handlers +by prefixing the string template item name with workflow_, +for example:

+
[runtime]
+    [[root]]
+        [[[events]]]
+            failed handlers = """
+                send-help.sh \
+                    %(workflow_title)s \
+                    %(workflow_importance)s \
+                    %(title)s
+             """
+
+
+
+
+title
+
+
Path:
+

flow.cylc[runtime][<namespace>][meta]title

+
+
Type:
+

string

+
+
+

A single line description of this task or task family.

+

It is displayed by the cylc list command and can be +retrieved from running tasks with the cylc show +command.

+
+ +
+
+description
+
+
Path:
+

flow.cylc[runtime][<namespace>][meta]description

+
+
Type:
+

string

+
+
+

A multi-line description of this task or task family.

+

It is retrievable from running tasks with the +cylc show command.

+
+ +
+
+URL
+
+
Path:
+

flow.cylc[runtime][<namespace>][meta]URL

+
+
Type:
+

string

+
+
+

A URL link to task documentation for this task or task +family.

+

The templates %(workflow)s and +%(task)s will be replaced with the actual +workflow ID and task name.

+
+

Deprecated since version 8.0.0: The %(suite_name)s template variable is +deprecated, please use %(workflow)s.

+

The %(task_name)s template variable is +deprecated, please use %(task)s.

+
+

See also [meta]URL.

+

Example:

+

http://my-site.com/workflows/%(workflow)s/%(task)s.html

+
+ +
+
+<custom metadata>
+
+
Path:
+

flow.cylc[runtime][<namespace>][meta]<custom metadata>

+
+
Type:
+

string

+
+
+

Any user-defined metadata item.

+

These, like title, description and URL. can be passed to +task event handlers to be interpreted according to your +needs. For example, the value of an “importance” item could +determine how an event handler responds to task failure +events.

+
+ +
+ +
+
+[simulation]
+
+
Path:
+

flow.cylc[runtime][<namespace>][simulation]

+
+
+

Task configuration for workflow simulation and dummy run +modes.

+

For a full description of simulation and dummy run modes see +Simulation Modes.

+
+
+default run length
+
+
Path:
+

flow.cylc[runtime][<namespace>][simulation]default run length

+
+
Type:
+

time interval

+
+
Default:
+

PT10S

+
+
+

The default simulated job run length.

+

Used if flow.cylc[runtime][<namespace>]execution time limit and +flow.cylc[runtime][<namespace>][simulation]speedup factor are not set.

+
+ +
+
+speedup factor
+
+
Path:
+

flow.cylc[runtime][<namespace>][simulation]speedup factor

+
+
Type:
+

float

+
+
+

Simulated run length = speedup factor * execution time +limit.

+

If flow.cylc[runtime][<namespace>]execution time limit is set, the task +simulated run length is computed by dividing it by this +factor.

+
+ +
+
+time limit buffer
+
+
Path:
+

flow.cylc[runtime][<namespace>][simulation]time limit buffer

+
+
Type:
+

time interval

+
+
Default:
+

PT30S

+
+
+

For dummy jobs flow.cylc[runtime][<namespace>]execution time limit is extended +by time limit buffer.

+

The time limit buffer is added to prevent dummy jobs +being killed after exceeding the execution time limit.

+
+ +
+
+fail cycle points
+
+
Path:
+

flow.cylc[runtime][<namespace>][simulation]fail cycle points

+
+
Type:
+

list

+
+
+

Configure simulated or dummy jobs to fail at certain cycle +points.

+

Example:

+
    +
  • all - all instance of the task will fail

  • +
  • 2017-08-12T06, 2017-08-12T18 - these instances of +the task will fail

  • +
+

If you set execution retry delays +the second attempt will succeed unless you set +fail try 1 only=False.

+
+ +
+
+fail try 1 only
+
+
Path:
+

flow.cylc[runtime][<namespace>][simulation]fail try 1 only

+
+
Type:
+

boolean

+
+
Default:
+

True

+
+
+

If True only the first run of the task +instance will fail, otherwise retries will fail too.

+

Task instances must be set to fail by +fail cycle points.

+
+

Note

+

This setting is designed for use with automatic +retries. Subsequent manual submissions will not +change the outcome of the task.

+
+
+ +
+
+disable task event handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][simulation]disable task event handlers

+
+
Type:
+

boolean

+
+
Default:
+

True

+
+
+

If True configured task event handlers +will not be called in simulation or dummy modes.

+
+ +
+ +
+
+[environment filter]
+
+
Path:
+

flow.cylc[runtime][<namespace>][environment filter]

+
+
+

This section contains environment variable inclusion and +exclusion lists that can be used to filter the inherited +environment.

+

This is not intended as an alternative to a +well-designed inheritance hierarchy that provides each task +with just the variables it needs.

+

Filters can improve workflows with tasks which inherit a lot +of environment variables: Filters can make it clear which +variables each task uses.

+

You can use filters as explicit “task environment interfaces”. +They make sure that variables filtered out of the inherited +environment are not used. However, using filters in this way +will make your workflow definition longer.

+
+

Note

+

Environment filtering is done after inheritance is +completely worked out, not at each level on the way, so +filter lists in higher-level namespaces only have an effect +if they are not overridden by descendants.

+
+
+
+include
+
+
Path:
+

flow.cylc[runtime][<namespace>][environment filter]include

+
+
Type:
+

list

+
+
+

If given, only variables named in this list will be +included from the inherited environment.

+

Other variables will be filtered out. Variables may also +be explicitly excluded by an exclude list.

+
+ +
+
+exclude
+
+
Path:
+

flow.cylc[runtime][<namespace>][environment filter]exclude

+
+
Type:
+

list

+
+
+

Variables named in this list will be filtered out of the +inherited environment.

+

Variables may also be implicitly +excluded by omission from an include list.

+
+ +
+ +
+
+[job]
+
+
Path:
+

flow.cylc[runtime][<namespace>][job]

+
+
+
+

Deprecated since version 8.0.0: This is used to select a matching platform. +It will be removed in a future version of Cylc 8. +Please set a suitable platform in +flow.cylc[runtime][<namespace>]platform instead. +See the migration guide.

+
+

This section configures the means by which cylc submits task +job scripts to run.

+
+
+batch system
+
+
Path:
+

flow.cylc[runtime][<namespace>][job]batch system

+
+
Type:
+

string

+
+
+
+

Deprecated since version 8.0.0: Kept for back compatibility but replaced by +global.cylc[platforms][<platform name>]job runner.

+
+

Batch/queuing system (aka job runner) to submit task +jobs to.

+
+ +
+
+batch submit command template
+
+
Path:
+

flow.cylc[runtime][<namespace>][job]batch submit command template

+
+
Type:
+

string

+
+
+
+

Deprecated since version 8.0.0: Kept for back compatibility but replaced by +global.cylc[platforms][<platform name>]job runner command template.

+
+

Override the default job submission command for the chosen +batch system.

+
+ +
+ +
+
+[remote]
+
+
Path:
+

flow.cylc[runtime][<namespace>][remote]

+
+
+

Job host settings.

+
+

Deprecated since version 8.0.0: This is used to select a matching platform. +It will be removed in a future version of Cylc 8. +Please set a suitable platform in +flow.cylc[runtime][<namespace>]platform instead. +See the migration guide.

+
+
+
+host
+
+
Path:
+

flow.cylc[runtime][<namespace>][remote]host

+
+
Type:
+

string

+
+
+

Hostname or IP address of the job host.

+
+

Deprecated since version 8.0.0: This is used to select a matching platform. +It will be removed in a future version of Cylc 8. +Please set a suitable platform in +flow.cylc[runtime][<namespace>]platform instead. +See the migration guide.

+
+
+ +
+
+owner
+
+
Path:
+

flow.cylc[runtime][<namespace>][remote]owner

+
+
Type:
+

string

+
+
+

Your username on the job host, if different from that on +the scheduler host.

+
+

Warning

+

This setting is obsolete at Cylc 8.

+

See documentation on changes to remote owner

+
+
+ +
+
+retrieve job logs
+
+
Path:
+

flow.cylc[runtime][<namespace>][remote]retrieve job logs

+
+
Type:
+

boolean

+
+
+

Whether to retrieve job logs from the job platform.

+
+

Deprecated since version 8.0.0: This is used to select a matching platform. +It will be removed in a future version of Cylc 8. +Please set a suitable platform in +flow.cylc[runtime][<namespace>]platform instead. +See the migration guide.

+
+
+ +
+
+retrieve job logs max size
+
+
Path:
+

flow.cylc[runtime][<namespace>][remote]retrieve job logs max size

+
+
Type:
+

string

+
+
+

The maximum size of job logs to retrieve.

+

Can be anything +accepted by the --max-size=SIZE option of rsync.

+
+

Deprecated since version 8.0.0: This is used to select a matching platform. +It will be removed in a future version of Cylc 8. +Please set a suitable platform in +flow.cylc[runtime][<namespace>]platform instead. +See the migration guide.

+
+
+ +
+
+retrieve job logs retry delays
+
+
Path:
+

flow.cylc[runtime][<namespace>][remote]retrieve job logs retry delays

+
+
Type:
+

time interval list

+
+
+

Configure retries for unsuccessful job log retrieval.

+

If there is a significant delay between job completion and +logs appearing in their final location (due to the job runner) +you can configure time intervals here to delay the first and +subsequent retrieval attempts.

+
+

Deprecated since version 8.0.0: This is used to select a matching platform. +It will be removed in a future version of Cylc 8. +Please set a suitable platform in +flow.cylc[runtime][<namespace>]platform instead. +See the migration guide.

+
+
+ +
+ +
+
+[events]
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]

+
+
+

Configure the task event handling system.

+

The default value is set in the global config: global.cylc[task events].

+

See also flow.cylc[scheduler][events] for workflow events.

+

Task event handlers are scripts to run when task events occur.

+

Event handlers can be stored in the workflow bin/ directory, or +anywhere the scheduler environment $PATH. They should return quickly.

+

Multiple event handlers can be specified as a list of command line templates. +For supported template variables see Task Event Template Variables. +Python template substitution syntax is used: +String Formatting Operations in the Python documentation.

+
+
+execution timeout
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]execution timeout

+
+
Type:
+

time interval

+
+
+

If a task has not finished after the specified interval, the execution +timeout event handler(s) will be called.

+

The default value is set in the global config: global.cylc[task events]execution timeout.

+
+ +
+
+handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]handlers

+
+
Type:
+

list

+
+
+

Commands to run on task handler events.

+

The default value is set in the global config: global.cylc[task events]handlers.

+

A command or list of commands to run for each task event handler +set in +flow.cylc[runtime][<namespace>][events]handler events.

+

Information about the event can be provided to the command +using Task Event Template Variables. +For more information, see +Task Event Handling.

+

For workflow events, see +Workflow Events.

+

Example:

+
echo %(event)s occurred in %(workflow)s >> my-log-file
+
+
+
+ +
+
+handler events
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]handler events

+
+
Type:
+

list

+
+
+

A list of events for which handlers are run.

+

The default value is set in the global config: global.cylc[task events]handler events.

+

Specify the events for which the general task event handlers +flow.cylc[runtime][<namespace>][events]handlers +should be invoked.

+

See Task Event Handling for more information.

+

Example:

+
submission failed, failed
+
+
+
+ +
+
+handler retry delays
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]handler retry delays

+
+
Type:
+

time interval list

+
+
+

Specify an initial delay before running an event handler command and +any retry delays in case the command returns a non-zero code.

+

The default value is set in the global config: global.cylc[task events]handler retry delays.

+

The default behaviour is to run an event handler command once without +any delay.

+

Example:

+
PT10S, PT1M, PT5M
+
+
+
+ +
+
+mail events
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]mail events

+
+
Type:
+

list

+
+
+

Specify the events for which notification emails should be sent.

+

The default value is set in the global config: global.cylc[task events]mail events.

+

Example:

+
submission failed, failed
+
+
+
+ +
+
+submission timeout
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]submission timeout

+
+
Type:
+

time interval

+
+
+

If a task has not started after the specified interval, the submission +timeout event handler(s) will be called.

+

The default value is set in the global config: global.cylc[task events]submission timeout.

+
+ +
+
+expired handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]expired handlers

+
+
Type:
+

list

+
+
+

Handlers to run if this task has expired.

+
+

See also

+

Tasks in the GUI/Tui

+
+
+

Caution

+

Changes to the scheduling algorithm in Cylc 8 mean +this event will not be triggered until the expired task +is ready to run. Earlier expired-task detection will be +implemented in a future Cylc release.

+
+
+ +
+
+late offset
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]late offset

+
+
Type:
+

time interval

+
+
+

Offset from cycle point, in real time, at which this task +is considered to be “running late” (i.e. the time by which +it would normally have started running).

+
+

Caution

+

Changes to the scheduling algorithm in Cylc 8 mean +this event will not be triggered until the late task +is ready to run. Earlier late-task detection will be +implemented in a future Cylc release.

+
+ +
+ +
+
+late handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]late handlers

+
+
Type:
+

list

+
+
+

Handlers to run if this task is late.

+
+

Caution

+

Due to changes to the Cylc 8 scheduling algorithm +this event is unlikely to occur until the task is about +to submit anyway.

+
+
+ +
+
+submitted handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]submitted handlers

+
+
Type:
+

list

+
+
+

Handlers to run when this task is submitted.

+
+ +
+
+started handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]started handlers

+
+
Type:
+

list

+
+
+

Handlers to run when this task starts executing.

+
+ +
+
+succeeded handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]succeeded handlers

+
+
Type:
+

list

+
+
+

Handlers to run if this task succeeds.

+
+ +
+
+failed handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]failed handlers

+
+
Type:
+

list

+
+
+

Handlers to run if this task fails.

+
+ +
+
+submission failed handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]submission failed handlers

+
+
Type:
+

list

+
+
+

Handlers to run if submission of this task fails.

+
+ +
+
+warning handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]warning handlers

+
+
Type:
+

list

+
+
+

Handlers to run if this task runs cylc message +with severity level “WARNING”.

+
+ +
+
+critical handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]critical handlers

+
+
Type:
+

list

+
+
+

Handlers to run if this task runs cylc message +with severity level “CRITICAL”.

+
+ +
+
+retry handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]retry handlers

+
+
Type:
+

list

+
+
+

Handlers to run if this task failed but is retrying.

+
+ +
+
+submission retry handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]submission retry handlers

+
+
Type:
+

list

+
+
+

Handlers to run if a job failed to submit but is +retrying.

+
+

See also

+

Tasks in the GUI/Tui

+
+
+ +
+
+execution timeout handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]execution timeout handlers

+
+
Type:
+

list

+
+
+

Handlers to run if this task execution exceeds +flow.cylc[runtime][<namespace>]execution time limit.

+
+ +
+
+submission timeout handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]submission timeout handlers

+
+
Type:
+

list

+
+
+

Handlers to run if this task exceeds +flow.cylc[runtime][<namespace>][events]submission timeout in the submitted state.

+
+ +
+
+custom handlers
+
+
Path:
+

flow.cylc[runtime][<namespace>][events]custom handlers

+
+
Type:
+

list

+
+
+

Handlers to run if this task runs cylc message +with severity level “CUSTOM”.

+
+ +
+ +
+
+[mail]
+
+
Path:
+

flow.cylc[runtime][<namespace>][mail]

+
+
+

Email notification settings for task events.

+
+

Added in version 8.0.0.

+
+
+
+from
+
+
Path:
+

flow.cylc[runtime][<namespace>][mail]from

+
+
Type:
+

string

+
+
+

Specify an alternate from: email address for event +notifications.

+
+

Changed in version 8.0.0: This item was previously called [runtime][task][events]mail from

+
+
+ +
+
+to
+
+
Path:
+

flow.cylc[runtime][<namespace>][mail]to

+
+
Type:
+

string

+
+
+

A list of email addresses to send task event +notifications.

+

The list can be any address accepted by the +mail command.

+
+

Changed in version 8.0.0: This item was previously called [runtime][task][events]mail to

+
+
+ +
+ +
+
+[workflow state polling]
+
+
Path:
+

flow.cylc[runtime][<namespace>][workflow state polling]

+
+
+

Deprecated support for automatic workflow state polling tasks +as described in Triggering Off Of Tasks In Other Workflows. Note the Cylc 7 +“user” and “host” config items are not supported.

+
+

Changed in version 8.0.0: This item was previously called [runtime][<namespace>]suite state polling.

+
+
+

Deprecated since version 8.3.0.

+
+

Please use the workflow_state xtrigger instead.

+
+
+interval
+
+
Path:
+

flow.cylc[runtime][<namespace>][workflow state polling]interval

+
+
Type:
+

time interval

+
+
+

Polling interval.

+
+ +
+
+max-polls
+
+
Path:
+

flow.cylc[runtime][<namespace>][workflow state polling]max-polls

+
+
Type:
+

integer

+
+
+

Maximum number of polls to attempt before the task fails.

+
+ +
+
+message
+
+
Path:
+

flow.cylc[runtime][<namespace>][workflow state polling]message

+
+
Type:
+

string

+
+
+

Target task output (task message, not trigger name).

+
+ +
+
+alt-cylc-run-dir
+
+
Path:
+

flow.cylc[runtime][<namespace>][workflow state polling]alt-cylc-run-dir

+
+
Type:
+

string

+
+
+

The cylc-run directory location of the target workflow. +Use to poll workflows owned by other users.

+
+ +
+
+verbose mode
+
+
Path:
+

flow.cylc[runtime][<namespace>][workflow state polling]verbose mode

+
+
Type:
+

boolean

+
+
+

Run the cylc workflow-state command in verbose mode.

+
+ +
+ +
+
+[environment]
+
+
Path:
+

flow.cylc[runtime][<namespace>][environment]

+
+
+

The user defined task execution environment.

+

Variables defined here can refer to cylc workflow and task +identity variables, which are exported earlier in the job +script. Variable assignment expressions can use cylc +utility commands because access to cylc is also configured +earlier in the script.

+
+

See also

+

Job Environment.

+
+

You can also specify job environment templates here for +parameterized tasks.

+
+
+<variable>
+
+
Path:
+

flow.cylc[runtime][<namespace>][environment]<variable>

+
+
Type:
+

string

+
+
+

A custom user defined variable for a task execution +environment.

+

The order of definition is preserved that each variable can +refer to previously defined +variables. Values are passed through to the job +script without evaluation or manipulation by Cylc +(with the exception of valid Python string templates +that match parameterized task names - see below), so any +variable assignment expression that is legal in the job +submission shell can be used. White space around the += is allowed (as far as cylc’s flow.cylc parser is +concerned these are just normal configuration items).

+

Examples:

+
FOO = $HOME/bar/baz
+BAR = ${FOO}$GLOBALVAR
+BAZ = $( echo "hello world" )
+WAZ = ${FOO%.jpg}.png
+NEXT_CYCLE = $( cylc cycle-point --offset=PT6H )
+ZAZ = "${FOO#bar}"
+# ^ quoted to escape the flow.cylc comment character
+DICE = [$((($RANDOM % 6) + 1)) $((($RANDOM % 6) + 1))]
+
+
+

For parameter environment templates, use Python string +templates for parameter substitution. This is only +relevant for +parameterized tasks. +The job script will export the named variables specified +here (in addition to the standard CYLC_TASK_PARAM_<key> +variables), with the template strings substituted with +the parameter values.

+

Examples:

+
MYNUM = %(i)d
+MYITEM = %(item)s
+MYFILE = /path/to/%(i)03d/%(item)s
+
+
+
+

Note

+

As with other Cylc configurations, leading or trailing +whitespace will be stripped, so the following two +examples are equivalent:

+ + + + + + +
[environment]
+    FOO = " a "
+    BAR = """
+      $(foo bar baz)
+  """
+
+
+
[environment]
+    FOO = "a"
+    BAR = "$(foo bar baz)"
+
+
+
+

If leading or trailing whitespace is required, consider +using the \0 escape character, or set the variable +in env-script.

+
+
+

Changed in version 7.8.7/7.9.2: Parameter environment templates (previously in +[runtime][X][parameter environment templates]) have +moved here.

+
+
+ +
+ +
+
+[directives]
+
+
Path:
+

flow.cylc[runtime][<namespace>][directives]

+
+
+

Job runner (batch scheduler) directives.

+

The default value is set in the global config: global.cylc[platforms][<platform name>][directives].

+

Supported for use with job runners:

+
    +
  • pbs

  • +
  • slurm

  • +
  • loadleveler

  • +
  • lsf

  • +
  • sge

  • +
  • slurm_packjob

  • +
  • moab

  • +
+

Directives are written to the top of the job script in the correct format +for the job runner.

+

Specifying directives individually like this allows use of default directives +for task families which can be individually overridden at lower levels of the +runtime namespace hierarchy.

+
+
+<directive>
+
+
Path:
+

flow.cylc[runtime][<namespace>][directives]<directive>

+
+
Type:
+

string

+
+
+

Example directives for the built-in job runner handlers are shown in +Supported Job Submission Methods.

+
+ +
+ +
+
+[outputs]
+
+
Path:
+

flow.cylc[runtime][<namespace>][outputs]

+
+
+

Register custom task outputs for use in message triggering in +this section (Message Triggers)

+
+
+<output>
+
+
Path:
+

flow.cylc[runtime][<namespace>][outputs]<output>

+
+
Type:
+

string

+
+
+

Define custom task outputs (aka Message Triggers).

+

Custom outputs allow you to extend +the built-in task outputs e.g. succeeded and failed +in order to provide more detailed information about task +state. Custom outputs can be used to express dependencies +in the graph as with built-in outputs.

+

Custom outputs are defined in the form:

+
output = message
+
+
+

Where output is the name of the output as it is used in +the graph, and message is the task message sent by +the cylc message command which tells Cylc that this +output has been completed. See Message Triggers for +more details.

+

Examples:

+
out1 = "sea state products ready"
+out2 = "NWP restart files completed"
+
+
+

Custom outputs must satisfy these rules:

+
+
+class cylc.flow.unicode_rules.TaskOutputValidator[source]
+

The rules for valid task outputs/message triggers:

+
    +
  • can only contain: alphanumeric, numbers, -

  • +
  • cannot start with: _cylc

  • +
  • cannot be: required, optional, all, and or or

  • +
  • cannot be: expire, expired, fail, fail-all, fail-any, failed, finish, finish-all, finish-any, finished, preparing, running, start, start-all, start-any, started, submit, submit-all, submit-any, submit-fail, submit-fail-all, submit-fail-any, submit-failed, submitted, succeed, succeed-all, succeed-any, succeeded or waiting

  • +
+
+ +

Task messages must satisfy these rules:

+
+
+class cylc.flow.unicode_rules.TaskMessageValidator[source]
+

The rules for valid task messages:

+
    +
  • cannot contain : unless it occurs at the end of the first word

  • +
  • cannot be: expired, submitted, submit-failed, started, succeeded, failed, finished, expire, submit, submit-fail, start, succeed, fail, finish, succeed-all, succeed-any, fail-all, fail-any, finish-all, finish-any, start-all, start-any, submit-all, submit-any, submit-fail-all or submit-fail-any

  • +
  • cannot start with: _cylc

  • +
+
+ +
+ +
+ +
+
+[parameter environment templates]
+
+
Path:
+

flow.cylc[runtime][<namespace>][parameter environment templates]

+
+
+
+

Deprecated since version 7.8.7/7.9.2: Parameter environment templates have moved to +flow.cylc[runtime][<namespace>][environment].

+
+

This was done to allow users to control the order of +definition of the variables. This section will be removed +in a future version of Cylc 8.

+

For the time being, the contents of this section will be +prepended to the [environment] section when running +a workflow.

+
+
+<parameter>
+
+
Path:
+

flow.cylc[runtime][<namespace>][parameter environment templates]<parameter>

+
+
Type:
+

string

+
+
+
+

Deprecated since version 7.8.7/7.9.2: Parameter environment templates have moved to +flow.cylc[runtime][<namespace>][environment].

+
+
+ +
+ +
+ +
+ +
+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/config/writing-platform-configs.html b/nightly_8.4/html/reference/config/writing-platform-configs.html new file mode 100644 index 00000000000..763a08d7666 --- /dev/null +++ b/nightly_8.4/html/reference/config/writing-platform-configs.html @@ -0,0 +1,604 @@ + + + + + + + Platform Configuration — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Platform Configuration

+
+

Writing Platform Configurations

+
+

Added in version 8.0.0.

+
+ +
+

Listing available platforms

+

If you are working on an institutional network, platforms may already +have been configured for you.

+

To see a list of available platforms:

+
cylc config --platform-names
+
+
+

To see the full configuration of available platforms:

+
cylc config --platforms
+
+
+

This is equivalent to cylc config -i 'platforms' -i 'platform groups'

+
+
+

What Are Platforms?

+

Platforms define settings, most importantly:

+
+
    +
  • A set of hosts.

  • +
  • A job runner (formerly a batch system) where Cylc can submit a job.

  • +
  • An install target for Cylc to install job files on.

  • +
+
+
+
+

Why Were Platforms Introduced?

+
    +
  • Allow a compute cluster with multiple login nodes to be treated as a single +unit.

  • +
  • Allow Cylc to elegantly handle failure to communicate with login nodes.

  • +
  • Reduce the number of ssh connections required for job submission and polling.

  • +
+
+
+

What Are Install Targets?

+

Install targets represent file systems. More than one platform can use the +same file system. Cylc relies on the site configuration file global.cylc to determine +which platforms share install targets.

+

Cylc will setup each remote install target once. During setup it will:

+
+
    +
  • Install workflow files

  • +
  • Symlink directories

  • +
  • Copy authentication keys (to allow secure communication)

  • +
+
+

Note, if missing from configuration, the install target will default to the +platform name. If incorrectly configured, this will cause errors in +Remote Initialization.

+

If you log into one system and see the same files as on another, then these two +platforms will require the same install target in global.cylc config file.

+
+
+
+

Example Platform Configurations

+

Detailed below are some examples of common platform configurations.

+
+

Submit PBS Jobs from Localhost

+
    +
  • The scheduler runs on the localhost platform.

  • +
  • Platforms can share hosts without sharing job runners.

  • +
+
+

Scenario

+

You have a cluster where you can submit jobs from the Cylc scheduler host +using PBS.

+
+

The localhost platform is the Cylc Scheduler host, as configured in +global.cylc[scheduler][run hosts]available. This is the host that +the workflow will start on. For more information, see +Platform Configuration.

+

Our platform pbs_cluster shares this localhost host and setting the +install target to localhost ensures that Cylc knows this platform does not +require remote initialization.

+
+
part of a global.cylc config file
+
[platforms]
+    # The localhost platform is available by default
+    # [[localhost]]
+    #     hosts = localhost
+    #     install target = localhost
+    [[pbs_cluster]]
+        hosts = localhost
+        job runner = pbs
+        install target = localhost
+
+
+
+

Our Cylc scheduler does not have a job runner defined. Any job submitted to +this localhost platform will run as a background job. Users can now set +flow.cylc[runtime][<namespace>]platform = pbs_cluster to run +pbs jobs.

+
+

Note

+

Both hosts and install target default to the platform name.

+
+
+
+

Multiple Platforms Sharing File System with Cylc Scheduler

+
    +
  • Platform names can be defined as regular expressions.

  • +
+
+

Scenario

+

Everyone in your organization has a computer called desktopNNN, +all with a file system shared with the scheduler host. Many users +will want their desktop set up as a platform to run small jobs.

+
+

In this scenario, Cylc does not need to install files on the desktop, since +required files which are on the scheduler host will be accessible on the +desktop. From Cylc’s point of view, the desktop and scheduler hosts are +considered different platforms but must share an install target. +Cylc needs to be told that these platforms share an install target and so we +configure this using the designated configuration item: +global.cylc[platforms][<platform name>]install target.

+

global.cylc[platforms][<platform name>] has optional configuration +[[[meta]]] which users can view with cylc config --platforms. We will add +a description designed to help users in this example.

+

The following platform definition is simplified, taking advantage of defaults +for hosts and install targets.

+
+
the global.cylc config file for this scenario could look like:
+
[platforms]
+    [[desktop\d\d\d]]
+        install target = localhost
+        [[[meta]]]
+            description = "Background job on a desktop system"
+
+
+
+

As before, a localhost platform is available by default. +desktop\d\d\d is a pattern which defines multiple platforms. +When using a pattern the “hosts” setting must be left unset so that it defaults +to the platform name. This ensures each of the matching platforms is unique.

+
+

Note

+

Cylc carries out a “fullmatch” regular expression comparison with the +the platform name so desktop\d\d\d is effectively the same as +^desktop\d\d\d$.

+
+

If a user wants to run a job on their local desktop, e.g. “desktop123”, they should +set:

+
+
[runtime]
+    [[mytask]]
+        platform = desktop123
+
+
+
+

in their workflow configuration. +If [runtime][mytask]platform is unset, the job will run on the Cylc +Scheduler host using this default localhost platform.

+

Neither platforms will require remote initialization as the install target +is set to localhost.

+
+
+

Cluster with Multiple Login Nodes

+
    +
  • Platforms with multiple hosts require job runner to be set

  • +
  • Platforms can group multiple hosts together.

  • +
+
+

Scenario

+

You have a cluster where users submit jobs to Slurm from +either of a pair of identical login nodes which share a file system.

+
+
+
part of a global.cylc config file
+
[platforms]
+    [[slurm_cluster]]
+        hosts = login_node_1, login_node_2
+        job runner = slurm
+        retrieve job logs = True
+
+
+
+

The slurm_cluster hosts do not share a file system with the scheduler, +therefore slurm_cluster is a remote platform. +As the install target setting for this platform has been omitted, this will +default to the platform name. +Cylc will initiate a remote installation, to transfer required files to +slurm_cluster which will commence before job submission for the first job +on that platform.

+

Cylc will attempt to communicate with jobs via the other login node if either +of the login_nodes becomes unavailable.

+

With multiple hosts defined under slurm_cluster, a job runner is required.

+
+

Note

+

The “background” and “at” job runners require single-host platforms, +because the job ID is only valid on the submission host.

+
+

We have set retrieve job logs = True. This will ensure our job logs are +fetched from the slurm_cluster platform. This setting is recommended for +all remote platforms (i.e. where install target is not localhost).

+
+
+

Grouping Platforms

+
    +
  • Platform groups allow users to ask for jobs to be run on any +suitable computer.

  • +
+
+

Scenario

+

Extending the example from above, we now wish to set the slurm_cluster +up such that slurm_cluster nodes can accept background jobs. +We would like to group these background platforms together so users can set +flow.cylc[runtime][<namespace>]platform = slurm_cluster_bg.

+
+
+
part of a global.cylc config file
+
[platforms]
+    [[slurm_cluster, slurm_cluster_bg1, slurm_cluster_bg2]]  # settings that apply to all:
+        install target = slurm_cluster
+        retrieve job logs = True
+    [[slurm_cluster]]
+        batch system = slurm
+        hosts = login_node_1, login_node_2
+    [[slurm_cluster_bg1]]
+        hosts = login_node_1
+    [[slurm_cluster_bg2]]
+        hosts = login_node_2
+[platform groups]
+    [[slurm_cluster_bg]]
+        platforms = slurm_cluster_bg1, slurm_cluster_bg2
+
+
+
+

Group platforms together using the configuration item +global.cylc[platform groups]. In the above example, the +slurm_cluster_bg platforms all share a file system +(install target = slurm_cluster). We advise caution when grouping platforms +with different install targets as users could encounter a scenario whereby +files (created by a previous task using the same platform group) are +not available to them.

+

With the above configuration, users can now run background jobs on either of +the login nodes, without the concern of selecting a specific platform.

+
+

Warning

+

Platforms and platform groups are both configured by +flow.cylc[runtime][<namespace>]platform. +Therefore a platform group cannot be given the same name as a platform. +The global.cylc file will fail validation if the same name is +used for both.

+
+
+
+
+

Symlinking Directories

+

To minimize the disk space used by ~/cylc-run, set +global.cylc[install][symlink dirs] to offload files onto other +locations. The entire run directory can be symlinked, as well as +certain sub-directories.

+ +

These should be configured per install target.

+

For example, to configure workflow log directories (on the +scheduler host) so that they symlink to a different location, +you could write the following in global.cylc:

+
[install]
+    [[symlink dirs]]
+        [[[localhost]]]
+            log = /somewhere/else
+
+
+

This would result in the following file structure on the Cylc scheduler host:

+
~/cylc-run
+└── myflow
+    ├── flow.cylc
+    ├── log -> /somewhere/else/cylc-run/myflow/log
+    ...
+
+/somewhere
+└── else
+    └── cylc-run
+        └── myflow
+            └── log
+                ├── flow-config
+                ├── install
+                ...
+
+
+

These localhost symlinks are created during the cylc install process. +Symlinks for remote install targets are created during Remote Initialization following +cylc play.

+
+
+

Advanced Platform Examples

+
+

Platform with no $HOME directory

+
+

Scenario

+

You are trying to run jobs on a platform where the compute nodes don’t +have a configured HOME directory.

+
+

So long as the login and compute nodes share a filesystem the workflow can be +installed on the shared filesystem using +global.cylc[install][symlink dirs].

+

The $CYLC_RUN_DIR variable can then be set on the compute node to point +at the cylc-run directory on the shared filesystem using +global.cylc[platforms][<platform name>]global init-script.

+
+
+
part of a global.cylc config file
+
[platforms]
+    [[homeless-hpc]]
+        job runner = my-job-runner
+        install target = homeless-hpc
+        global init-script = """
+            export CYLC_RUN_DIR=/shared/filesystem/cylc-run
+        """
+
+[install]
+    [[symlink dirs]]
+        [[[homeless-hpc]]]
+            run = /shared/filesystem/
+
+
+
+
+

In this example Cylc will install workflows into +/shared/filesystem/cylc-run.

+
+

Note

+

If you are running schedulers directly on the login node +and submitting jobs locally then the platform name and install target should +be localhost.

+
+
+
+

Sharing environment variables with the Cylc server

+
+

Scenario

+

An environment variable on the computer where you’re running cylc play +needs to be shared with the Cylc server (e.g. to set up storage paths)

+
+

Normally if a Cylc server is running on a remote host it will not keep +environment variables that are present when you run cylc play. You can +whitelist variables to be sent to remote servers using +global.cylc[platforms][<platform name>]ssh forward environment variables.

+

These variables are forwarded to the Cylc server and may be used in the +global.cylc file templating.

+
+
+
part of a global.cylc config file
+
[install]
+    [[symlink dirs]]
+        [[[hpc]]]
+            # Here the environment variable on the server is used
+            run = {{ environ['LUSTRE_DISK'] }}
+
+[platforms]
+    # 'localhost' platform is used when communicating with the server
+    [[localhost]]
+        ssh forward environment variables = LUSTRE_DISK, PROJECT
+
+    [[hpc]]
+        submit method = pbs
+        [[[directives]]]
+            -P = {{ environ['PROJECT'] }}
+
+
+
+
+

In this example Cylc will install workflows into the directory specified by +$LUSTRE_DISK and use the project specified by $PROJECT in the +environment where you run cylc play, e.g.

+
+
export LUSTRE_DISK=/g/data/foo
+export PROJECT=bar
+cylc play
+
+
+
+

will store the workflow under /g/data/foo and submit jobs under project +bar.

+

You can also forward variables from the server to other platforms. You should +first ensure the variable is available on the server, e.g. by also forwarding +the variable to [[localhost]].

+

This setting only affects the task submission (e.g. qsub) which may use +environment variables to set default directives. To set a variable once the +task has started see +global.cylc[platforms][<platform name>]copyable environment variables.

+
+
+
part of a global.cylc config file
+
[platforms]
+    [[localhost]]
+        ssh forward environment variables = PROJECT
+
+    [[hpc]]
+        # Here qsub has been configured to read from $PROJECT
+        ssh forward environment variables = PROJECT
+        submit method = pbs
+
+
+
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/dev-history-major-changes.html b/nightly_8.4/html/reference/dev-history-major-changes.html new file mode 100644 index 00000000000..82d996abbcb --- /dev/null +++ b/nightly_8.4/html/reference/dev-history-major-changes.html @@ -0,0 +1,231 @@ + + + + + + + Cylc Development History - Major Changes — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Cylc Development History - Major Changes

+
    +
  • pre-cylc-3

    +
      +
    • early versions focused on the new +scheduling algorithm. A suite was a collection of “task definition files” +that encoded the prerequisites and outputs of each task, +exposing Cylc’s self-organising nature. Tasks could be transferred +from one suite to another by simply copying their taskdef files over +and checking prerequisite and output consistency. Global suite +structure was not easy to discern until run time (although cylc-2 +could generate resolved run time dependency graphs).

    • +
    +
  • +
  • cylc-3

    +
      +
    • a new suite design interface: dependency graph and task runtime properties +defined in a single structured, validated, configuration file

    • +
    • graphical user interface

    • +
    • suite graphing

    • +
    +
  • +
  • cylc-4

    +
      +
    • refined and organized the suite config file structure

    • +
    • task runtime properties defined by an efficient inheritance hierarchy

    • +
    • support for the Jinja2 template processor in suite configurations

    • +
    +
  • +
  • cylc-5

    +
      +
    • multi-threading for continuous network request handling and job submission

    • +
    • more task states to distinguish job submission from execution

    • +
    • dependence between suites via new run databases

    • +
    • polling and killing of real jobs

    • +
    • polling as task communications option

    • +
    +
  • +
  • cylc-6

    +
      +
    • specification of all datetimes and cycling suites via ISO8601 +datetimes, durations, and recurrence expressions

    • +
    • integer cycling

    • +
    • a multi-process pool to execute job submissions, event handlers, and poll +and kill commands

    • +
    +
  • +
  • cylc-7

    +
      +
    • Replaced the Pyro communications layer with RESTful HTTPS

    • +
    • Removed deprecated pre cylc-6 syntax and features

    • +
    +
  • +
  • cylc-8

    +
      +
    • Migrated to Python 3

    • +
    • New architecture, network layers, security

    • +
    • New web UI

    • +
    • New efficient scheduling algorithm

    • +
    • Removed deprecated pre cylc-6 syntax and features

    • +
    +
  • +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/environments/conda.html b/nightly_8.4/html/reference/environments/conda.html new file mode 100644 index 00000000000..96868933784 --- /dev/null +++ b/nightly_8.4/html/reference/environments/conda.html @@ -0,0 +1,313 @@ + + + + + + + Conda Environments — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Conda Environments

+

Cylc consists of multiple components.

+

This Conda environment will provide you with the “recommended” installation of +all components:

+
name: cylc-8.4
+channels:
+  - conda-forge
+dependencies:
+  - cylc-flow =8.4
+  - cylc-uiserver
+  - cylc-rose
+  - metomi-rose
+
+
+

The following sections outline alternatives for finer control over installation.

+
+

Cylc Flow

+

The simplest Cylc installation consists only of Cylc Flow:

+
name: cylc-flow
+channels:
+  - conda-forge
+dependencies:
+  - cylc-flow =8.4
+
+
+
+

Tip

+

We suggest installing Cylc Flow at a “minor” version (e.g. 8.1 rather +than 8.1.2) to pick up the latest “maintenance” release.

+
+

If you do not specify your Python version you will be provided with the most +recent compatible one.

+

If you are installing Cylc on multiple machines across a network it is +advisable to keep the Python versions consistent.

+

You can do this by adding Python into the environment at a particular version:

+
name: cylc-flow-with-python-3.7
+channels:
+  - conda-forge
+dependencies:
+  - python =3.7
+  - cylc-flow =8.4
+
+
+

Cylc Flow provides a cut-down package containing only the bare essentials +called cylc-flow-base.

+

This may be useful for installing onto job hosts where client-facing extra +features are not of interest:

+
name: cylc-flow-base
+channels:
+  - conda-forge
+dependencies:
+  - cylc-flow-base =8.4
+
+
+
+
+

Cylc UIServer

+

The default Cylc UIServer package comes with Jupyter Hub and the +Configurable HTTP Proxy (required by Jupyter Hub) bundled:

+
name: cylc-uiserver
+channels:
+  - conda-forge
+dependencies:
+  - cylc-flow =8.4
+  - cylc-uiserver
+
+
+
+

Tip

+

We suggest not specifying the version of other Cylc components to +(i.e. Cylc UIServer and Cylc Rose). This will pick up the most recent +version compatible with the specified Cylc Flow version.

+
+

Jupyter Hub is only required for multi-user setups, the Cylc UIServer +can be run as a standalone application.

+

To exclude Jupyter Hub from the installation use cylc-uiserver-base:

+
name: cylc-uiserver-without-jupyterhub
+channels:
+  - conda-forge
+dependencies:
+  - cylc-flow =8.4
+  - cylc-uiserver-base
+
+
+

If you want to use Jupyter Hub with an alternative proxy use +cylc-uiserver-hub-base (this depends on jupyterhub-base, see the +Jupyter Hub documentation for details):

+
name: cylc-uiserver-with-traefik-proxy
+channels:
+  - conda-forge
+dependencies:
+  - cylc-flow =8.4
+  - cylc-uiserver-hub-base
+  - pip
+  - pip:
+      - jupyterhub-traefik-proxy
+
+
+
+
+

Cylc Rose

+

For working with Rose add metomi-rose and cylc-rose (the bridge +between Cylc & Rose):

+
name: cylc-rose
+channels:
+  - conda-forge
+dependencies:
+  - cylc-flow =8.4
+  - cylc-rose
+  - metomi-rose
+
+
+

We will look at providing more installation options for Rose in the near +future.

+
+
+

Adding Cylc To Your Conda Package

+

If you want to publish a package (e.g. to Conda Forge) that depends on Cylc, +consider using the minimal package (e.g. cylc-flow-base) as a dependency +to allow the installer to maintain flexibility over the installation.

+
+
+

Working With Other Conda Channels

+

Cylc projects are published to Conda Forge and the above environments install +all dependencies from Conda Forge.

+

If you want to install other dependencies (e.g. Python), from other channels +(e.g. Anaconda), list the dependency explicitly and place the channel above +the Conda Forge channel.

+
name: cylc-flow
+channels:
+  - defaults
+  - conda-forge
+dependencies:
+  - python
+  - cylc-flow =8.4
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/index.html b/nightly_8.4/html/reference/index.html new file mode 100644 index 00000000000..f1dfa91ceda --- /dev/null +++ b/nightly_8.4/html/reference/index.html @@ -0,0 +1,214 @@ + + + + + + + Reference — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/reference/job-script-vars/index.html b/nightly_8.4/html/reference/job-script-vars/index.html new file mode 100644 index 00000000000..9f42264a19e --- /dev/null +++ b/nightly_8.4/html/reference/job-script-vars/index.html @@ -0,0 +1,240 @@ + + + + + + + Job Script Environment Variables — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Job Script Environment Variables

+

These environment variables provided by the scheduler are available +to Cylc job scripts at run time:

+
CYLC_VERSION                       # Version of cylc installation used
+CYLC_VERBOSE                       # Verbose mode, true or false
+CYLC_DEBUG                         # Debug mode (even more verbose), true or false
+
+CYLC_CYCLING_MODE                  # Cycling mode, e.g. gregorian
+ISODATETIMECALENDAR                # Calendar mode for the `isodatetime` command,
+                                   #   defined with the value of CYLC_CYCLING_MODE
+                                   #   when in any datetime cycling mode
+
+CYLC_WORKFLOW_FINAL_CYCLE_POINT    # Final cycle point
+CYLC_WORKFLOW_INITIAL_CYCLE_POINT  # Initial cycle point
+CYLC_WORKFLOW_ID                   # Workflow ID
+                                   # e.g. "a/b/c/run1"
+CYLC_WORKFLOW_NAME                 # Workflow ID with the run name removed
+                                   # (use CYLC_WORKFLOW_ID for most purposes)
+                                   # e.g. "a/b/c"
+CYLC_WORKFLOW_NAME_BASE            # The basename of the workflow name
+                                   # (use CYLC_WORKFLOW_ID for most purposes)
+                                   # e.g. "c"
+CYLC_UTC                           # UTC mode, True or False
+TZ                                 # Set to "UTC" in UTC mode or not defined
+
+CYLC_WORKFLOW_RUN_DIR              # Location of the run directory in
+                                   # job host, e.g. ~/cylc-run/foo
+CYLC_WORKFLOW_HOST                 # Host running the workflow process
+CYLC_WORKFLOW_OWNER                # User ID running the workflow process
+
+CYLC_WORKFLOW_SHARE_DIR            # Workflow (or task!) shared directory (see below)
+CYLC_WORKFLOW_UUID                 # Workflow UUID string
+CYLC_WORKFLOW_WORK_DIR             # Workflow work directory (see below)
+
+CYLC_TASK_JOB                      # Job identifier expressed as
+                                   # CYCLE-POINT/TASK-NAME/SUBMIT-NUMBER
+                                   #   e.g. 20110511T1800Z/t1/01
+
+CYLC_TASK_CYCLE_POINT              # Cycle point, e.g. 20110511T1800Z
+ISODATETIMEREF                     # Reference time for the `isodatetime` command,
+                                   #   defined with the value of CYLC_TASK_CYCLE_POINT
+                                   #   when in any datetime cycling mode
+
+CYLC_TASK_NAME                     # Job's task name, e.g. t1
+CYLC_TASK_ID                       # Task instance identifier CYCLE-POINT/TASK-NAME
+                                   #   e.g. 20110511T1800Z/t1
+
+CYLC_TASK_SUBMIT_NUMBER            # Job's submit number, e.g. 1,
+                                   #   increments with every submit
+CYLC_TASK_TRY_NUMBER               # Number of execution tries, e.g. 1
+                                   #   increments with automatic execution retry delays.
+CYLC_TASK_FLOW_NUMBERS             # Flows this task belongs to, e.g. 1,2
+
+CYLC_TASK_LOG_DIR                  # Location of the job log directory
+                                   #   e.g. ~/cylc-run/foo/log/job/20110511T1800Z/t1/01/
+CYLC_TASK_LOG_ROOT                 # The job script path
+                                   #   e.g. ~/cylc-run/foo/log/job/20110511T1800Z/t1/01/job
+CYLC_TASK_WORK_DIR                 # Location of task work directory (see below)
+                                   #   e.g. ~/cylc-run/foo/work/20110511T1800Z/t1
+
+CYLC_TASK_NAMESPACE_HIERARCHY      # Linearised family namespace of the task,
+                                   #   e.g. root postproc t1
+
+CYLC_TASK_COMMS_METHOD             # Set to "ssh" if communication method is "ssh"
+CYLC_TASK_SSH_LOGIN_SHELL          # With "ssh" communication, if set to "True",
+                                   #   use login shell on workflow host
+
+
+
+

See also

+

Job Script Variables

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/search.html b/nightly_8.4/html/search.html new file mode 100644 index 00000000000..12843ec20b0 --- /dev/null +++ b/nightly_8.4/html/search.html @@ -0,0 +1,170 @@ + + + + + + Search — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + + + +
+ +
+ +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/searchindex.js b/nightly_8.4/html/searchindex.js new file mode 100644 index 00000000000..484b8e69648 --- /dev/null +++ b/nightly_8.4/html/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"alltitles": {"1. File Installation": [[93, "file-installation"]], "1. Gathering Observations": [[76, "gathering-observations"]], "2. Running Computer Models to Generate Forecast Data": [[76, "running-computer-models-to-generate-forecast-data"]], "2. Symlinking of Directories": [[93, "symlinking-of-directories"]], "3. Processing the data output to produce user-friendly forecasts": [[76, "processing-the-data-output-to-produce-user-friendly-forecasts"]], "7 to 8 upgrades": [[124, "to-8-upgrades"]], "A note on symlink directories": [[96, "a-note-on-symlink-directories"]], "A variety of other examples": [[11, "a-variety-of-other-examples"]], "API Reference": [[27, "api-reference"]], "Aborting Job Scripts on Error": [[120, "aborting-job-scripts-on-error"]], "Aborting a Retry Sequence": [[102, "aborting-a-retry-sequence"]], "Access to Workflow Files": [[128, "access-to-workflow-files"]], "Adding Cylc To Your Conda Package": [[55, "adding-cylc-to-your-conda-package"]], "Adding More Clock-Triggered Tasks": [[59, "adding-more-clock-triggered-tasks"]], "Additional CLI options": [[24, "additional-cli-options"]], "Advanced Examples": [[132, "advanced-examples"]], "Advanced Installation": [[23, "advanced-installation"]], "Advanced Integer Cycling Syntax": [[132, "advanced-integer-cycling-syntax"]], "Advanced Platform Examples": [[53, "advanced-platform-examples"]], "Advanced Starting Up": [[132, "advanced-starting-up"]], "Aims": [[76, null], [77, null], [78, null], [80, null]], "Altering Behaviour": [[65, "altering-behaviour"]], "Alternative Calendars": [[77, "alternative-calendars"]], "An Example": [[137, "an-example"]], "An Integer Cycling Example": [[132, "an-integer-cycling-example"]], "Analysis View": [[44, "analysis-view"], [44, "id1"]], "Any valid Python literals": [[18, "any-valid-python-literals"]], "Architecture": [[20, "architecture"], [42, "architecture"]], "Assert": [[128, "assert"]], "Associative Arrays In Jinja2": [[128, "associative-arrays-in-jinja2"]], "At Start-Up": [[135, "at-start-up"]], "Authentication Files": [[97, "authentication-files"], [104, "authentication-files"]], "Authentication Overview": [[43, null], [43, null]], "Authorizing Others to Access Your Workflows": [[48, "authorizing-others-to-access-your-workflows"]], "Auto Generated 7 to 8 upgrades": [[124, "auto-generated-7-to-8-upgrades"]], "Automatically Generated Directories and Files": [[93, "automatically-generated-directories-and-files"]], "Automating Failure Recovery": [[135, "automating-failure-recovery"]], "Avoid Detaching Processes": [[120, "avoid-detaching-processes"]], "Avoiding External Files": [[135, "avoiding-external-files"]], "Bash Completion": [[44, "bash-completion"]], "Bash Profile": [[23, "bash-profile"]], "Basic Cycling": [[80, "basic-cycling"]], "Basic Example": [[132, "basic-example"]], "Basic Functionality": [[135, "basic-functionality"]], "Basic Principles": [[135, "basic-principles"]], "Broadcast Tutorial": [[58, "broadcast-tutorial"]], "Browser Based UI": [[0, "browser-based-ui"]], "Built In Plugins": [[27, "built-in-plugins"], [35, "built-in-plugins"]], "Built-in Clock Triggers": [[126, "built-in-clock-triggers"]], "Built-in Email Event Handler": [[130, "built-in-email-event-handler"]], "Built-in Workflow State Triggers": [[126, "built-in-workflow-state-triggers"]], "Cannot determine whether workflow is running on ": [[123, "cannot-determine-whether-workflow-is-running-on-host"]], "Changes": [[18, "changes"], [44, "changes"]], "Cheat Sheet": [[1, "cheat-sheet"], [81, "cheat-sheet"]], "Cleaning on remote install targets": [[96, "cleaning-on-remote-install-targets"]], "Cleaning specific subdirectories or files": [[96, "cleaning-specific-subdirectories-or-files"]], "Client": [[40, "client"]], "Client -> Scheduler": [[41, "client-scheduler"]], "Client-Server Interaction": [[97, "client-server-interaction"]], "Clock Triggered Tasks": [[59, "clock-triggered-tasks"]], "Clock Triggering": [[59, "clock-triggering"]], "Clock Triggers": [[77, "clock-triggers"], [132, "clock-triggers"]], "Clock-Expire Triggers": [[132, "clock-expire-triggers"]], "Clock-Triggered Tasks": [[135, "clock-triggered-tasks"]], "Clock-Triggering Tasks": [[59, "clock-triggering-tasks"]], "Cluster with Multiple Login Nodes": [[53, "cluster-with-multiple-login-nodes"]], "Coding Standards": [[135, "coding-standards"]], "Collaborative Development Model": [[137, "collaborative-development-model"]], "Combined Commands": [[44, "combined-commands"]], "Command Changes": [[20, "command-changes"]], "Command Line Interface": [[3, "command-line-interface"]], "Comments": [[138, "comments"]], "Completion Expressions": [[44, "completion-expressions"], [132, "completion-expressions"]], "Complex Jinja2 Code": [[135, "complex-jinja2-code"]], "Component Interactions": [[41, "component-interactions"]], "Compound Commands": [[93, "compound-commands"]], "Concurrent Flows": [[101, "concurrent-flows"]], "Conda / Mamba environment activation fails": [[123, "conda-mamba-environment-activation-fails"]], "Conda Environments": [[55, "conda-environments"]], "Conditional Triggers": [[132, "conditional-triggers"]], "Configurable Source Directories": [[93, "configurable-source-directories"]], "Configuration": [[23, "configuration"], [47, "configuration"]], "Configuration Changes at Cylc 8": [[5, "configuration-changes-at-cylc-8"]], "Configuration File": [[24, "configuration-file"]], "Configuration Logs": [[104, "configuration-logs"]], "Configure cylc lint at project level": [[124, "configure-cylc-lint-at-project-level"]], "Configuring": [[35, "configuring"]], "Configuring Retries": [[65, "configuring-retries"]], "Confining Output To The Run Directory": [[135, "confining-output-to-the-run-directory"]], "Consolidating Configuration": [[69, "consolidating-configuration"]], "Contents": [[93, "contents"], [94, "contents"]], "Continuing a Cylc 7 Workflow with Cylc 8": [[6, "continuing-a-cylc-7-workflow-with-cylc-8"]], "Continuous Event Watchers?": [[126, "continuous-event-watchers"]], "Converging Workflow": [[85, "converging-workflow"]], "Coroutines": [[35, "coroutines"]], "Current Limitations": [[126, "current-limitations"]], "Custom Event Handlers": [[131, "custom-event-handlers"]], "Custom Failure Messages": [[120, "custom-failure-messages"]], "Custom Jinja2 Filters, Tests and Globals": [[128, "custom-jinja2-filters-tests-and-globals"]], "Custom Job Submission Methods": [[28, "custom-job-submission-methods"]], "Custom Output Generation Timing": [[132, "custom-output-generation-timing"]], "Custom Outputs": [[132, "custom-outputs"]], "Custom Trigger Functions": [[126, "custom-trigger-functions"]], "Cycle Point Time Zone": [[76, "cycle-point-time-zone"]], "Cycle point time zone": [[135, "cycle-point-time-zone"]], "Cycling Graphs": [[132, "cycling-graphs"]], "Cycling Syntax Rules": [[132, "cycling-syntax-rules"]], "Cylc 7": [[21, null], [21, null], [21, null], [21, null], [21, null]], "Cylc 7 Compatibility Mode": [[4, "cylc-7-compatibility-mode"], [20, "cylc-7-compatibility-mode"]], "Cylc 7 compatibility mode": [[52, null], [52, null]], "Cylc 8 Migration Guide": [[2, "cylc-8-migration-guide"]], "Cylc 8 Standardised IDs": [[3, "cylc-8-standardised-ids"]], "Cylc 8 UIs": [[19, "cylc-8-uis"]], "Cylc 8.0": [[44, "cylc-8-0"]], "Cylc 8.1": [[44, "cylc-8-1"]], "Cylc 8.2": [[44, "cylc-8-2"]], "Cylc 8.3": [[44, "cylc-8-3"]], "Cylc 8.4 Caveats": [[0, "cylc-version-caveats"]], "Cylc API": [[38, "cylc-api"]], "Cylc Broadcast": [[98, "cylc-broadcast"]], "Cylc Components": [[44, null], [44, null], [44, null], [44, null]], "Cylc Configuration Data Types": [[50, "cylc-configuration-data-types"]], "Cylc Debugging Utilities": [[123, "cylc-debugging-utilities"]], "Cylc Development History - Major Changes": [[54, "cylc-development-history-major-changes"]], "Cylc Documentation": [[22, "cylc-documentation"]], "Cylc Flow": [[0, "cylc-flow"], [23, "cylc-flow"], [55, "cylc-flow"]], "Cylc Graphs": [[78, "cylc-graphs"]], "Cylc Hub": [[19, "cylc-hub"], [42, "cylc-hub"]], "Cylc Install": [[7, "cylc-install"], [20, "cylc-install"]], "Cylc Install Optional Config": [[24, "cylc-install-optional-config"]], "Cylc Message": [[103, "cylc-message"]], "Cylc Parameters": [[71, "cylc-parameters"]], "Cylc Rose": [[24, "cylc-rose"], [55, "cylc-rose"]], "Cylc Scheduler": [[42, "cylc-scheduler"]], "Cylc Site Configuration": [[48, "cylc-site-configuration"]], "Cylc Tui": [[19, "cylc-tui"]], "Cylc UI": [[42, "cylc-ui"]], "Cylc UI Server": [[23, "cylc-ui-server"], [42, "cylc-ui-server"], [43, "cylc-ui-server"]], "Cylc UIServer": [[55, "cylc-uiserver"]], "Cylc User Authorisation": [[48, "cylc-user-authorisation"]], "Cylc Web GUI": [[19, "cylc-web-gui"]], "Cylc and Cycling Workflows": [[95, "cylc-and-cycling-workflows"]], "Cylc commands in task scripts": [[4, "cylc-commands-in-task-scripts"], [4, "compat-eg-cylc-commands"]], "Cylc ignores $PYTHONPATH": [[44, "cylc-ignores-pythonpath"]], "Data Flow": [[41, "data-flow"]], "Datetime Cycling": [[76, "datetime-cycling"], [84, "datetime-cycling"]], "Datetime Format": [[132, "datetime-format"]], "Datetime Operations": [[1, "datetime-operations"]], "Datetime Recurrences": [[76, "datetime-recurrences"]], "Debugging": [[128, "debugging"]], "Debugging Workflow Configurations": [[123, "debugging-workflow-configurations"]], "Default Directives Provided": [[121, "default-directives-provided"]], "Default Values and Template Variables": [[128, "default-values-and-template-variables"]], "Defining Multiple Tasks or Families at Once": [[130, "defining-multiple-tasks-or-families-at-once"]], "Deleting": [[1, "deleting"]], "Detailed Description of Major Changes": [[9, "detailed-description-of-major-changes"]], "Developing Main Loop Plugins": [[35, "developing-main-loop-plugins"]], "Developing pre_configure and post_install plugins": [[27, "developing-pre-configure-and-post-install-plugins"]], "Developing xtrigger plugins": [[36, "developing-xtrigger-plugins"]], "Different Triggers": [[60, "different-triggers"]], "Directives Section Quirks (PBS, SGE, \u2026)": [[121, "directives-section-quirks-pbs-sge"]], "Does This Change Affect Me?": [[3, null], [4, null], [6, null], [7, null], [8, null], [11, null], [12, null], [13, null], [16, null], [18, null]], "Does this affect me?": [[96, null]], "Duplicate Items": [[78, "duplicate-items"]], "Durations and the Initial Cycle Point": [[76, "durations-and-the-initial-cycle-point"]], "Edit Runtime": [[44, "edit-runtime"]], "Edit The Workflow Configuration": [[94, "edit-the-workflow-configuration"]], "Edit a Task\u2019s Configuration and Re-Run It": [[94, "edit-a-task-s-configuration-and-re-run-it"]], "Efficiency And Maintainability": [[134, "efficiency-and-maintainability"]], "Efficient Inter-Family Triggering": [[132, "efficient-inter-family-triggering"]], "EmPy": [[125, "empy"]], "Engine Type": [[62, "engine-type"]], "Environment Variables": [[71, "environment-variables"], [74, "environment-variables"], [128, "environment-variables"]], "Error Messages": [[123, "error-messages"]], "Event Driven Cycling": [[87, "event-driven-cycling"]], "Event Types": [[35, "event-types"]], "Event-Specific Handlers": [[130, "event-specific-handlers"]], "Example": [[10, "example"], [11, "example"], [16, "example"], [18, "example"], [36, "example"], [59, "example"], [60, "example"], [64, "example"], [65, "example"], [70, "example"], [78, "example"], [88, "example"]], "Example - CI/CD": [[86, null], [87, null]], "Example - Decoupled workflows": [[91, null]], "Example - Genetic algorithms": [[85, null]], "Example - Polar satellite data processing": [[86, null], [87, null]], "Example Installation": [[93, "example-installation"]], "Example Platform Configurations": [[53, "example-platform-configurations"]], "Example Site Authorization Configuration": [[48, "example-site-authorization-configuration"]], "Example: Rerun a Sub-Graph": [[101, "example-rerun-a-sub-graph"]], "Examples": [[4, "examples"], [11, "examples"], [48, "examples"], [89, "examples"], [130, "examples"]], "Exceptions": [[37, "module-cylc.flow.exceptions"]], "Excluding Dates": [[132, "id2"]], "Excluding Items From Installation": [[93, "excluding-items-from-installation"]], "Excluding Recurrences": [[132, "excluding-recurrences"]], "Excluding Tasks at Start-up is Not Supported": [[8, "excluding-tasks-at-start-up-is-not-supported"]], "Execution Time Limit": [[121, "execution-time-limit"]], "Execution Time Limit and Execution Timeout": [[121, "execution-time-limit-and-execution-timeout"]], "Expected Errors": [[93, "expected-errors"]], "Explanation": [[60, "explanation"], [63, "explanation"]], "Extending Workflow": [[88, "extending-workflow"]], "External Command Execution": [[131, "external-command-execution"]], "External Platform Selection Scripts": [[130, "external-platform-selection-scripts"]], "External Triggers": [[126, "external-triggers"], [132, "external-triggers"]], "Failure Recovery Workflows": [[135, "failure-recovery-workflows"]], "Failure Triggers": [[132, "failure-triggers"]], "Families": [[68, "families"]], "Families of Families": [[130, "families-of-families"]], "Family Finish Triggers": [[132, "family-finish-triggers"]], "Family Triggering": [[134, "family-triggering"]], "Family Triggering: Failure": [[60, "family-triggering-failure"]], "Family Triggering: Success": [[60, "family-triggering-success"]], "Family Triggers": [[60, "family-triggers"], [132, "family-triggers"], [132, "optional-outputs-family-triggers"]], "Family-to-Family Triggering": [[134, "family-to-family-triggering"]], "File Installation": [[20, "file-installation"]], "FileNotFoundError: No such file or directory": [[123, "filenotfounderror-no-such-file-or-directory"]], "Files Generated at Runtime": [[73, "files-generated-at-runtime"]], "Files created at workflow start": [[104, "files-created-at-workflow-start"]], "Filesystem Events?": [[126, "filesystem-events"]], "Fine Or Coarse-Grained Workflows": [[135, "fine-or-coarse-grained-workflows"]], "Finish Triggers": [[132, "finish-triggers"], [132, "id8"]], "Finished Workflow": [[62, "finished-workflow"]], "First-parent Family Hierarchy for Visualization": [[130, "first-parent-family-hierarchy-for-visualization"]], "Fixing deprecation warnings": [[5, "fixing-deprecation-warnings"]], "Flow Merging in n=0": [[101, "flow-merging-in-n-0"]], "Flow Numbers": [[101, "flow-numbers"]], "Format 1: R[limit?]/[datetime]/[datetime]": [[132, "format-1-r-limit-datetime-datetime"]], "Format 3: R[limit?]/[datetime]/[interval]": [[132, "format-3-r-limit-datetime-interval"]], "Format 4: R[limit?]/[interval]/[datetime]": [[132, "format-4-r-limit-interval-datetime"]], "Formats": [[41, "formats"]], "Full List Of Command Changes": [[3, "full-list-of-command-changes"]], "Further Reading": [[42, "further-reading"], [64, "further-reading"], [65, "further-reading"]], "Further Scheduling": [[77, "further-scheduling"]], "Further Topics": [[61, "further-topics"]], "Future Triggers": [[132, "future-triggers"]], "Gantt View": [[44, "gantt-view"]], "General Event Handlers": [[130, "general-event-handlers"]], "Generated Workflow Files": [[73, "generated-workflow-files"]], "Generating Tasks Automatically": [[134, "generating-tasks-automatically"]], "Get a copy of this example": [[82, null], [83, null], [84, null], [85, null], [87, null], [88, null], [91, null]], "Getting Help": [[123, "getting-help"]], "Global Configuration": [[46, "global-configuration"]], "Glossary": [[21, "glossary"]], "Graph": [[5, "graph"]], "Graph Branching": [[132, "graph-branching"]], "Graph String Lines": [[138, "graph-string-lines"]], "Graph Strings": [[78, "graph-strings"]], "Graph Types": [[132, "graph-types"]], "Graph View": [[44, "graph-view"]], "Graph branching, optional outputs and suicide triggers": [[16, "graph-branching-optional-outputs-and-suicide-triggers"]], "GraphQL": [[41, "graphql"]], "Graphing": [[68, "graphing"]], "Gross File Structure": [[124, "gross-file-structure"]], "Group Support": [[48, "group-support"]], "Group by cycle point in the graph view": [[44, "group-by-cycle-point-in-the-graph-view"]], "Grouping Platforms": [[53, "grouping-platforms"]], "HTTPS (Hypertext Transfer Protocol Secure)": [[41, "https-hypertext-transfer-protocol-secure"]], "Handling Job Preemption": [[99, "handling-job-preemption"]], "Hello World": [[27, "hello-world"], [35, "hello-world"], [82, "hello-world"]], "Hint": [[62, null], [62, null], [74, null], [74, null], [74, null], [74, null], [76, null]], "Hold & Release": [[12, "hold-release"]], "Hold The Workflow And Trigger Tasks One By One": [[94, "hold-the-workflow-and-trigger-tasks-one-by-one"]], "Host Pool": [[131, "host-pool"]], "Hovercraft": [[62, "hovercraft"]], "How Cylc 8 handles host-to-platform upgrades": [[11, "how-cylc-8-handles-host-to-platform-upgrades"]], "How Multiple Graph Strings Combine": [[132, "how-multiple-graph-strings-combine"]], "How to Run User Guide Examples": [[95, "how-to-run-user-guide-examples"]], "How to create a message trigger": [[63, "how-to-create-a-message-trigger"]], "ISO8601": [[76, "iso8601"]], "ISO8601 Datetimes": [[76, "iso8601-datetimes"]], "ISO8601 Durations": [[76, "iso8601-durations"]], "Impacted Scripts": [[13, "impacted-scripts"]], "Implicit Tasks": [[130, "implicit-tasks"]], "Importing Python modules": [[128, "importing-python-modules"]], "In-Situ Example": [[58, "in-situ-example"]], "Include Files": [[135, "include-files"]], "Indentation": [[78, "indentation"], [138, "indentation"]], "Inferred Recurrence": [[76, "inferred-recurrence"]], "Inheritance": [[62, "inheritance"], [135, "inheritance"]], "Inheritance Hierarchy": [[62, "inheritance-hierarchy"]], "Inheriting from Multiple Parents": [[130, "inheriting-from-multiple-parents"]], "Inlined Site-Switching": [[137, "inlined-site-switching"]], "Inlined Tasks": [[120, "inlined-tasks"]], "Inspecting Workflows": [[81, "inspecting-workflows"]], "Installation": [[7, null], [23, "installation"]], "Installation Types": [[23, "installation-types"]], "Installing & Running": [[1, "installing-running"]], "Installing A Workflow": [[73, "installing-a-workflow"]], "Installing Custom Files At Start-up": [[104, "installing-custom-files-at-start-up"]], "Installing On Mac OS": [[23, "installing-on-mac-os"]], "Installing Workflows": [[93, "installing-workflows"]], "Integer Cycling": [[83, "integer-cycling"], [132, "integer-cycling"]], "Integer Format": [[132, "integer-format"]], "Inter-Workflow Triggering": [[91, "inter-workflow-triggering"]], "Interacting with Others\u2019 Workflows": [[48, "interacting-with-others-workflows"]], "Intercycle Dependencies": [[76, "intercycle-dependencies"], [80, "intercycle-dependencies"]], "Intercycle Triggers": [[132, "intercycle-triggers"]], "Internal Platform and Host Selection": [[130, "internal-platform-and-host-selection"]], "Internal Queues": [[132, "internal-queues"], [135, "internal-queues"]], "Interpreter": [[120, "interpreter"]], "Interventions": [[1, "interventions"], [81, "interventions"], [94, "interventions"]], "Introduction": [[67, "introduction"], [73, "introduction"], [95, "introduction"]], "Jinja2": [[70, "jinja2"], [128, "jinja2"]], "Jinja2 - integers with leading zeros": [[13, "jinja2-integers-with-leading-zeros"]], "Jinja2 Code": [[138, "jinja2-code"]], "Jinja2 Loops": [[134, "jinja2-loops"]], "Jinja2 Variable Scope": [[128, "jinja2-variable-scope"]], "Jinja2 Variables": [[135, "jinja2-variables"]], "Job -> Scheduler": [[41, "job-scheduler"]], "Job Environment": [[130, "job-environment"]], "Job Execution Retries": [[135, "job-execution-retries"]], "Job Killing": [[121, "job-killing"]], "Job Polling": [[121, "job-polling"]], "Job Script Environment Variables": [[57, "job-script-environment-variables"]], "Job Script Variables": [[130, "job-script-variables"]], "Job Scripts": [[120, "job-scripts"]], "Job Status Isn\u2019t Updating": [[123, "job-status-isn-t-updating"]], "Job Submission": [[74, "job-submission"]], "Job Submission Retries": [[135, "job-submission-retries"]], "Job Submission Triggers": [[132, "job-submission-triggers"]], "Job Submission and Management": [[121, "job-submission-and-management"]], "Jupyter Hub": [[43, "jupyter-hub"]], "Jupyter Hub Authorisation": [[48, "jupyter-hub-authorisation"]], "Jupyter Server": [[43, "jupyter-server"]], "Jupyter Server Authorisation": [[48, "jupyter-server-authorisation"]], "Late Events": [[130, "late-events"]], "Limitations": [[105, "limitations"]], "Line Breaks": [[10, "line-breaks"]], "Line Length And Continuation": [[138, "line-length-and-continuation"]], "Linting": [[124, "linting"]], "List Workflows": [[81, "list-workflows"]], "Listing available platforms": [[53, "listing-available-platforms"]], "Load Balancing": [[131, "load-balancing"]], "Log Files": [[123, "log-files"]], "Log View": [[44, "log-view"]], "Logging": [[128, "logging"]], "Mail Events": [[131, "mail-events"]], "Main Loop Plugins": [[35, "module-cylc.flow.main_loop"]], "Making Changes To Running Workflows": [[81, "making-changes-to-running-workflows"]], "Managing Environments": [[23, "managing-environments"]], "Managing Multiple Workflows": [[81, "managing-multiple-workflows"]], "Manually setting task outputs and prerequisites": [[44, "manually-setting-task-outputs-and-prerequisites"]], "Mapping To Old Commands": [[12, "mapping-to-old-commands"]], "Message Triggers": [[63, "message-triggers"], [132, "message-triggers"]], "Migrating From rose suite-run": [[7, "migrating-from-rose-suite-run"]], "Migration": [[10, "migration"]], "Misconfiguration": [[104, "misconfiguration"]], "Monolithic Or Interdependent Workflows": [[135, "monolithic-or-interdependent-workflows"]], "More Inheritance": [[62, "more-inheritance"]], "More advanced example": [[27, "more-advanced-example"]], "Multi-User Mode": [[43, "multi-user-mode"]], "Multiple Inheritance": [[62, "multiple-inheritance"]], "Multiple Platforms Sharing File System with Cylc Scheduler": [[53, "multiple-platforms-sharing-file-system-with-cylc-scheduler"]], "Mutually Exclusive Outputs": [[132, "mutually-exclusive-outputs"]], "My Job Failed": [[123, "my-job-failed"]], "My Job Submit-Failed": [[123, "my-job-submit-failed"]], "My workflow shut down unexpectedly": [[123, "my-workflow-shut-down-unexpectedly"]], "N-Window selector in the GUI": [[44, "n-window-selector-in-the-gui"]], "Named Runs": [[93, "named-runs"]], "Network layers": [[42, "network-layers"]], "New Features": [[18, "new-features"]], "New Web and Terminal UIs": [[20, "new-web-and-terminal-uis"]], "Non-Cycling": [[132, "non-cycling"]], "Non-Python Requirements": [[23, "non-python-requirements"]], "Notable differences to rose suite-run": [[7, "notable-differences-to-rose-suite-run"]], "Note": [[78, null], [78, null]], "Numbered Runs": [[93, "numbered-runs"]], "Numbered run directories": [[73, "numbered-run-directories"]], "Offsets at Sequence Start": [[129, "offsets-at-sequence-start"]], "Offsets in the Graph": [[129, "offsets-in-the-graph"]], "Omitting Tasks": [[132, "omitting-tasks"]], "Opening User Interfaces": [[1, "opening-user-interfaces"]], "Opening the GUI/Tui": [[81, "opening-the-gui-tui"]], "OperationalError: disk I/O error": [[123, "operationalerror-disk-i-o-error"]], "Optional App Config Files": [[134, "optional-app-config-files"]], "Optional Outputs": [[132, "user-guide-optional-outputs"]], "Optional and Required Task Outputs": [[20, "optional-and-required-task-outputs"]], "Options": [[93, "options"]], "Orphan a \u201cStuck\u201d Job Submission": [[94, "orphan-a-stuck-job-submission"]], "Other Cases Where Cylc Uses SSH Directly": [[122, "other-cases-where-cylc-uses-ssh-directly"]], "Other Changes": [[20, "other-changes"]], "Other caveats": [[4, "other-caveats"]], "Override default symlink locations": [[93, "override-default-symlink-locations"]], "Overriding Inherited Environment Variables": [[130, "overriding-inherited-environment-variables"]], "Overriding The Job Submission Command": [[121, "overriding-the-job-submission-command"]], "Overview": [[3, "overview"], [4, "overview"], [7, "overview"], [8, "overview"], [10, "overview"], [11, "overview"], [12, "overview"], [13, "overview"], [14, "overview"], [18, "overview"]], "PATH and PYTHONPATH": [[73, "path-and-pythonpath"]], "Package Name Changes": [[13, "package-name-changes"]], "Parameter Expansion": [[129, "parameter-expansion"]], "Parameter Types": [[71, "parameter-types"]], "Parameterized Cycling": [[129, "parameterized-cycling"]], "Parameterized Sub-Cycles": [[129, "parameterized-sub-cycles"]], "Parameterized Tasks": [[71, "parameterized-tasks"], [134, "parameterized-tasks"]], "Parameters": [[10, "parameters"]], "Parameters as Full Task Names": [[129, "parameters-as-full-task-names"]], "Passing Values To Tasks": [[129, "passing-values-to-tasks"]], "Pausing & Unpausing": [[1, "pausing-unpausing"]], "Penny Farthing": [[62, "penny-farthing"]], "Permissions": [[48, "permissions"]], "Platform Awareness": [[20, "platform-awareness"]], "Platform Configuration": [[53, "platform-configuration"], [131, "platform-configuration"]], "Platform with no $HOME directory": [[53, "platform-with-no-home-directory"]], "Platforms": [[5, "platforms"], [11, "platforms"]], "Play Pause Stop": [[12, "play-pause-stop"]], "Plugins": [[25, "plugins"]], "Polling to Track Job Status": [[107, "polling-to-track-job-status"]], "Portable Workflows": [[137, "portable-workflows"]], "Practical": [[63, "message-triggers-practical"], [68, "cylc-tutorial-families-practical"], [70, "cylc-tutorial-jinja2-practical"], [71, "cylc-tutorial-parameters-practical"], [73, null], [74, "tutorial-cylc-runtime-forecasting-workflow"], [76, "datetime-cycling-practical"], [78, null], [80, "basic-cycling-practical"]], "Pre-Configure And Post-Install Plugins": [[27, "pre-configure-and-post-install-plugins"]], "Problems": [[123, "problems"]], "Protobuf": [[41, "protobuf"]], "Protocols, Transport & Security": [[41, "protocols-transport-security"]], "Purpose": [[58, "purpose"], [65, "purpose"]], "Push External Triggers": [[126, "push-external-triggers"]], "Putting It All Together": [[76, "putting-it-all-together"]], "Python 2 => 3": [[13, "python-2-3"]], "Python 2 to 3": [[4, "python-2-to-3"]], "Python API": [[29, "python-api"], [30, "python-api"], [31, "python-api"], [32, "python-api"], [33, "python-api"], [34, "python-api"]], "Qualifiers": [[77, "qualifiers"]], "Queues": [[64, "queues"]], "Quick Installation": [[23, "quick-installation"]], "Raise": [[128, "raise"]], "Raising Exceptions": [[128, "raising-exceptions"]], "Re-Run All Failed Tasks": [[94, "re-run-all-failed-tasks"]], "Re-Run Multiple Tasks": [[94, "re-run-multiple-tasks"]], "Re-Run a Task": [[94, "re-run-a-task"]], "Re-Running Workflows": [[12, "re-running-workflows"]], "Recommended Installation": [[23, "recommended-installation"]], "Recurrence Formats": [[76, "recurrence-formats"]], "Recurrence Sections": [[80, "recurrence-sections"]], "Reference": [[56, "reference"]], "Referencing The Initial And Final Cycle Points": [[132, "referencing-the-initial-and-final-cycle-points"]], "Reinstalling a Workflow": [[93, "reinstalling-a-workflow"]], "Related Tutorial": [[95, null], [95, null], [128, null], [130, null], [132, null], [132, null], [132, null], [132, null], [132, null]], "Relative initial cycle point examples for now = 2018-03-14T15:12Z": [[132, "id14"]], "Relative initial cycle point examples for now = 2018-03-14T15:12Z\n using ISO8601 truncated dates.": [[132, "id15"]], "Reload": [[44, "reload"]], "Reloading": [[1, "reloading"]], "Reloading the Workflow Configuration at Runtime": [[104, "reloading-the-workflow-configuration-at-runtime"]], "Remaining Use Case": [[133, "remaining-use-case"]], "Reminder": [[62, null], [76, null]], "Remote Initialization": [[104, "remote-initialization"]], "Remote Installation": [[7, "remote-installation"]], "Remote Job Log Directories": [[130, "remote-job-log-directories"]], "Remote Job Management": [[122, "remote-job-management"]], "Remote Task Hosting": [[130, "remote-task-hosting"]], "Remote Usernames": [[14, "remote-usernames"]], "Removing Workflows": [[20, "removing-workflows"], [96, "removing-workflows"]], "Renaming to flow.cylc": [[4, "renaming-to-flow-cylc"]], "Repeating Workflows": [[80, "repeating-workflows"]], "Required Changes": [[4, "required-changes"], [16, "required-changes"]], "Required Outputs": [[132, "required-outputs"]], "Required files are not being installed on remote platforms": [[123, "required-files-are-not-being-installed-on-remote-platforms"]], "Research-To-Operations Transition": [[137, "research-to-operations-transition"]], "Restarting": [[1, "restarting"]], "Restarting or Reloading after Graph Changes": [[104, "restarting-or-reloading-after-graph-changes"]], "Restarts and the Initial, Final, Start and Stop Cycle Points": [[104, "restarts-and-the-initial-final-start-and-stop-cycle-points"]], "Restricting Workflow Activity": [[135, "restricting-workflow-activity"]], "Retries": [[65, "retries"], [74, "retries"]], "Retrying Tasks": [[102, "retrying-tasks"]], "Rose": [[13, "rose"]], "Rose App File Polling": [[135, "rose-app-file-polling"]], "Rose Apps": [[135, "rose-apps"]], "Rose Config Files": [[138, "rose-config-files"]], "Rose Metadata Compliance": [[135, "rose-metadata-compliance"]], "Rose Stem": [[1, "rose-stem"], [24, "rose-stem"]], "Rose Suite Configurations": [[24, "rose-suite-configurations"]], "Runahead Limit Notes": [[132, "runahead-limit-notes"]], "Runahead Limiting": [[132, "runahead-limiting"], [135, "runahead-limiting"]], "Running Rose Stem Workflows": [[81, "running-rose-stem-workflows"]], "Running Tasks At The stop after cycle point": [[88, "running-tasks-at-the-stop-after-cycle-point"]], "Running With Retries": [[65, "running-with-retries"]], "Running Without Retries": [[65, "running-without-retries"]], "Running Workflows": [[100, "running-workflows"]], "Running Workflows in Debug Mode": [[81, "running-workflows-in-debug-mode"]], "Running a workflow": [[73, "running-a-workflow"]], "Runtime": [[68, "runtime"], [72, "runtime"]], "Runtime Configuration": [[74, "runtime-configuration"]], "S001": [[124, "id2"]], "S002": [[124, "id3"]], "S003": [[124, "id4"]], "S004": [[124, "id5"]], "S005": [[124, "id6"]], "S006": [[124, "id7"]], "S007": [[124, "id8"]], "S008": [[124, "s008"]], "S009": [[124, "id9"]], "S010": [[124, "id10"]], "S011": [[124, "s011"]], "S012": [[124, "id11"]], "S013": [[124, "s013"]], "S014": [[124, "s014"]], "SSH": [[41, "ssh"]], "SSH Task Communication": [[107, "ssh-task-communication"]], "SSH-based Job Management": [[122, "ssh-based-job-management"]], "SSH-free Job Management?": [[122, "ssh-free-job-management"]], "Scan API": [[39, "module-cylc.flow.network.scan"]], "Scanning": [[1, "scanning"]], "Scenario": [[53, null], [53, null], [53, null], [53, null], [53, null], [53, null]], "Scheduler -> UI Server": [[41, "scheduler-ui-server"]], "Scheduler Configuration": [[131, "scheduler-configuration"]], "Scheduler Logs": [[103, "scheduler-logs"]], "Scheduler Stall": [[108, "scheduler-stall"]], "Scheduling": [[79, "scheduling"]], "Scheduling Algorithm": [[15, "scheduling-algorithm"], [20, "scheduling-algorithm"]], "Scheduling Configuration": [[132, "scheduling-configuration"]], "Script String Lines": [[138, "script-string-lines"]], "See what the Jinja2 is doing": [[123, "see-what-the-jinja2-is-doing"]], "Selecting Partial Ranges": [[129, "selecting-partial-ranges"]], "Selecting Specific Values": [[129, "selecting-specific-values"]], "Self-Contained Workflows": [[135, "self-contained-workflows"]], "Sequential Xtriggers": [[126, "sequential-xtriggers"]], "Server": [[40, "server"]], "Set Task Outputs": [[94, "set-task-outputs"]], "Set Task Prerequisites": [[94, "set-task-prerequisites"]], "Set a Switch Task": [[94, "set-a-switch-task"]], "Setting The Initial Cycle Point Relative To The Current Time": [[132, "setting-the-initial-cycle-point-relative-to-the-current-time"]], "Settings (Config Items)": [[138, "settings-config-items"]], "Shared Configuration": [[135, "shared-configuration"]], "Shared Task IO Paths": [[135, "shared-task-io-paths"]], "Sharing By Inheritance": [[134, "sharing-by-inheritance"]], "Sharing environment variables with the Cylc server": [[53, "sharing-environment-variables-with-the-cylc-server"]], "Shell Auto-Completion": [[23, "shell-auto-completion"]], "Shell Login/Profile Files": [[123, "shell-login-profile-files"]], "Shorthand": [[45, "shorthand"], [78, "shorthand"]], "Shorthand for list of strings": [[18, "shorthand-for-list-of-strings"]], "Simple example": [[11, "simple-example"]], "Simulated Failure": [[105, "simulated-failure"]], "Simulated Run Length": [[105, "simulated-run-length"]], "Simulation Modes": [[105, "simulation-modes"]], "Single-User Mode": [[43, "single-user-mode"]], "Site Include-Files": [[137, "site-include-files"]], "Site-Agnostic File Paths in App Configs": [[137, "site-agnostic-file-paths-in-app-configs"]], "Site-Specific Graphs": [[137, "site-specific-graphs"]], "Site-Specific Optional App Configs": [[137, "site-specific-optional-app-configs"]], "Site-Specific Optional Workflow Configs": [[137, "site-specific-optional-workflow-configs"]], "Site-Specific Workflow Variables": [[137, "site-specific-workflow-variables"]], "Solution": [[62, null], [62, null], [62, null], [62, null], [63, null], [63, null], [71, null], [71, null], [74, null], [76, null], [76, null], [78, null], [80, null]], "Some Use Cases": [[101, "some-use-cases"]], "Special Sequential Tasks": [[132, "special-sequential-tasks"]], "Special Variables": [[24, "special-variables"]], "Splitting Up Long Graph Lines": [[132, "splitting-up-long-graph-lines"]], "Standalone Example": [[58, "standalone-example"]], "Start Triggers": [[132, "start-triggers"]], "Start and Stop vs Initial and Final Cycle Points": [[104, "start-and-stop-vs-initial-and-final-cycle-points"]], "Start, Restart, Reload": [[104, "start-restart-reload"]], "Start, Stop, Restart": [[74, "start-stop-restart"]], "Starting and Stopping Workflows": [[81, "starting-and-stopping-workflows"]], "Static Graph Visualisation": [[1, "static-graph-visualisation"]], "Stopping": [[1, "stopping"]], "Stopping Flows": [[101, "stopping-flows"]], "Style": [[124, "style"]], "Style Guidelines": [[138, "style-guidelines"]], "Submit PBS Jobs from Localhost": [[53, "submit-pbs-jobs-from-localhost"]], "Submitting Workflows To a Pool Of Hosts": [[131, "submitting-workflows-to-a-pool-of-hosts"]], "Success Triggers": [[132, "success-triggers"]], "Suicide Triggers": [[133, "suicide-triggers"]], "Summary": [[59, "summary"], [60, "summary"]], "Summary Of Major Changes": [[20, "summary-of-major-changes"]], "Supported Job Submission Methods": [[121, "supported-job-submission-methods"]], "Symlink Directories": [[93, "symlink-directories"]], "Symlink Dirs": [[20, "symlink-dirs"]], "Symlinking Directories": [[53, "symlinking-directories"]], "Syntax": [[45, "syntax"]], "Syntax Highlighting For Workflow Configuration": [[124, "syntax-highlighting-for-workflow-configuration"]], "TCP Task Messaging": [[107, "tcp-task-messaging"]], "Tab Characters": [[138, "tab-characters"]], "Task & Job States": [[73, "task-job-states"], [106, "id1"]], "Task Configuration": [[130, "task-configuration"]], "Task Definitions": [[73, "task-definitions"]], "Task Event Handling": [[130, "task-event-handling"]], "Task Event Template Variables": [[130, "task-event-template-variables"]], "Task Execution Time Limits": [[135, "task-execution-time-limits"]], "Task Families And Visualization": [[134, "task-families-and-visualization"]], "Task Families and Parameters": [[129, "task-families-and-parameters"]], "Task Host Selection": [[135, "task-host-selection"]], "Task Implementation": [[110, "task-implementation"], [120, "task-implementation"]], "Task Independence": [[135, "task-independence"]], "Task Messages": [[120, "task-messages"]], "Task Modifiers": [[106, "task-modifiers"]], "Task Naming Conventions": [[138, "task-naming-conventions"]], "Task Parameters": [[129, "task-parameters"]], "Task Retry On Failure": [[130, "task-retry-on-failure"]], "Task Scripting": [[135, "task-scripting"]], "Task Triggering": [[132, "task-triggering"]], "Task Work Directories": [[130, "task-work-directories"]], "Task and Family Names": [[130, "task-and-family-names"]], "Task stdout and stderr Logs": [[121, "task-stdout-and-stderr-logs"]], "Task/Job States": [[17, "task-job-states"], [20, "task-job-states"]], "Tasks And Jobs": [[73, "tasks-and-jobs"]], "Tasks in the GUI/Tui": [[106, "tasks-in-the-gui-tui"]], "Template Variables": [[18, "template-variables"]], "Terminate a Chain of Automatic Retries": [[94, "terminate-a-chain-of-automatic-retries"]], "Terminology": [[20, "terminology"]], "Text Editors": [[23, "text-editors"]], "The -s, -z and --set-file Options": [[128, "the-s-z-and-set-file-options"]], "The .cylc File Format": [[45, "the-cylc-file-format"]], "The Cylc CLI": [[73, "the-cylc-cli"]], "The Cylc Components": [[23, "the-cylc-components"]], "The Cylc GUI": [[73, "the-cylc-gui"]], "The Cylc Install Command": [[93, "the-cylc-install-command"]], "The Cylc Install Process": [[93, "the-cylc-install-process"]], "The Cylc TUI": [[73, "the-cylc-tui"]], "The Cylc User Interfaces": [[73, "the-cylc-user-interfaces"]], "The Dependency Graph": [[78, "the-dependency-graph"]], "The Environment Variable CYLC_WORKFLOW_INITIAL_CYCLE_POINT": [[132, "the-environment-variable-cylc-workflow-initial-cycle-point"]], "The Graph": [[132, "the-graph"]], "The Initial Cycle Point": [[132, "the-initial-cycle-point"]], "The Initial and Final Cycle Points": [[76, "the-initial-and-final-cycle-points"]], "The Jinja2 Language": [[70, "the-jinja2-language"]], "The Jinja2 SITE Variable": [[137, "the-jinja2-site-variable"]], "The Root Family": [[130, "the-root-family"]], "The Task Family Hierarchy": [[134, "the-task-family-hierarchy"]], "The Three Approaches": [[69, "the-three-approaches"]], "The Workflow Contact File": [[104, "the-workflow-contact-file"]], "The cylc config Command": [[69, "the-cylc-config-command"]], "The flow.cylc File": [[124, "the-flow-cylc-file"]], "The flow.cylc File Format": [[78, "the-flow-cylc-file-format"]], "The global.cylc file": [[24, "the-global-cylc-file"]], "The root Family": [[68, "the-root-family"]], "The script Setting": [[73, "the-script-setting"]], "The \u201cn\u201d Window": [[106, "the-n-window"]], "Time Limits": [[74, "time-limits"]], "Timeout": [[104, "timeout"]], "Titles, Descriptions, And URLs": [[138, "titles-descriptions-and-urls"]], "To skip making localhost symlinks": [[93, "to-skip-making-localhost-symlinks"]], "Toy Examples": [[126, "toy-examples"]], "Tracking Job Status": [[107, "tracking-job-status"]], "Trailing Whitespace": [[138, "trailing-whitespace"]], "Triggering & Flows": [[101, "triggering-flows"]], "Triggering Off Of Tasks In Other Workflows": [[126, "triggering-off-of-tasks-in-other-workflows"]], "Troubleshooting": [[104, "troubleshooting"], [123, "troubleshooting"]], "Troubleshooting Authorization": [[48, "troubleshooting-authorization"]], "Tui": [[44, "tui"]], "Tutorial": [[66, "tutorial"]], "Tutorial Summary": [[75, "tutorial-summary"]], "U001": [[124, "u001"]], "U002": [[124, "u002"]], "U003": [[124, "u003"]], "U004": [[124, "u004"]], "U005": [[124, "u005"]], "U006": [[124, "id12"]], "U007": [[124, "id13"]], "U008": [[124, "id14"]], "U009": [[124, "u009"]], "U010": [[124, "u010"]], "U011": [[124, "id15"]], "U012": [[124, "id16"]], "U013": [[124, "id17"]], "U014": [[124, "id18"]], "U015": [[124, "id19"]], "U016": [[124, "id20"]], "UI Server": [[0, "ui-server"]], "UI Server -> UI": [[41, "ui-server-ui"]], "UI Server Configuration": [[51, "ui-server-configuration"]], "UI now remembers workspace tab layout": [[44, "ui-now-remembers-workspace-tab-layout"]], "UM System Task Names": [[138, "um-system-task-names"]], "Understanding Code in Workflow Configurations": [[124, "understanding-code-in-workflow-configurations"]], "Upgrade To The Latest Jupyter Releases": [[44, "upgrade-to-the-latest-jupyter-releases"]], "Upgrading To Cylc 8": [[20, "upgrading-to-cylc-8"]], "Usage": [[63, "usage"]], "Use Case": [[52, null]], "Use of Pipes in Job Scripts": [[120, "use-of-pipes-in-job-scripts"]], "User Guide": [[92, "user-guide"]], "Users": [[48, "users"]], "Using Cylc Install": [[93, "using-cylc-install"]], "Using a plugin": [[128, "using-a-plugin"]], "Valid Task Cycle Points": [[132, "valid-task-cycle-points"]], "Validating": [[1, "validating"]], "Validating A Workflow": [[73, "validating-a-workflow"]], "Validating with Cylc 7": [[4, "validating-with-cylc-7"]], "Validation": [[124, "validation"]], "Varying Behaviour By Cycle Point": [[135, "varying-behaviour-by-cycle-point"]], "Via Conda (recommended)": [[23, "via-conda-recommended"]], "Via Pip (+npm)": [[23, "via-pip-npm"]], "View A Workflow\u2019s Configuration": [[1, "view-a-workflow-s-configuration"]], "WSS (WebSocket Secure)": [[41, "wss-websocket-secure"]], "What Are Install Targets?": [[53, "what-are-install-targets"]], "What Are Platforms?": [[53, "what-are-platforms"]], "What Is A Workflow?": [[67, "what-is-a-workflow"]], "What Is Cylc?": [[67, "what-is-cylc"]], "What is Cylc?": [[95, "what-is-cylc"]], "What is a Platform?": [[11, "what-is-a-platform"]], "What is a Workflow?": [[95, "what-is-a-workflow"]], "Which Approach To Use": [[69, "which-approach-to-use"]], "Why Were Platforms Introduced?": [[53, "why-were-platforms-introduced"]], "Why isn\u2019t my task running?": [[123, "why-isn-t-my-task-running"]], "Workflow Completion": [[108, "workflow-completion"]], "Workflow Configuration": [[52, "workflow-configuration"], [124, "workflow-configuration"]], "Workflow Configuration Directories": [[124, "workflow-configuration-directories"]], "Workflow Context variables": [[128, "workflow-context-variables"]], "Workflow Design Guide": [[136, "workflow-design-guide"]], "Workflow Event Template Variables": [[131, "workflow-event-template-variables"]], "Workflow Events": [[131, "workflow-events"]], "Workflow Housekeeping": [[135, "workflow-housekeeping"]], "Workflow Installation": [[20, "workflow-installation"]], "Workflow Migration": [[131, "workflow-migration"]], "Workflow Run Databases": [[109, "workflow-run-databases"]], "Workflow Runtime Interface": [[40, "workflow-runtime-interface"]], "Workflow Share Directories": [[130, "workflow-share-directories"]], "Workflow State Triggers & Commands": [[44, "workflow-state-triggers-commands"]], "Workflow files and Context Variables": [[125, "workflow-files-and-context-variables"]], "Working With Cylc IDs": [[81, "working-with-cylc-ids"]], "Working With Other Conda Channels": [[55, "working-with-other-conda-channels"]], "Working with Workflows": [[81, "working-with-workflows"]], "Writing Platform Configurations": [[53, "writing-platform-configurations"]], "Writing Workflows": [[127, "writing-workflows"]], "Xtrigger Plugins": [[36, "xtrigger-plugins"]], "Xtrigger Validation Functions": [[126, "xtrigger-validation-functions"]], "ZMQ (Over TCP)": [[41, "zmq-over-tcp"]], "Zero-Padded Integer Values": [[129, "zero-padded-integer-values"]], "at": [[111, "module-cylc.flow.job_runner_handlers.at"]], "background": [[112, "module-cylc.flow.job_runner_handlers.background"]], "cylc lint": [[124, "module-cylc.flow.scripts.lint"]], "cylc vip (Validate, Install and Play)": [[93, "cylc-vip-validate-install-and-play"]], "cylc vr (Validate, Reinstall and Reload or Play)": [[93, "cylc-vr-validate-reinstall-and-reload-or-play"]], "cylc.flow.install_plugins.log_vc_info": [[26, "module-cylc.flow.install_plugins.log_vc_info"]], "cylc.flow.main_loop.auto_restart": [[29, "module-cylc.flow.main_loop.auto_restart"]], "cylc.flow.main_loop.health_check": [[30, "module-cylc.flow.main_loop.health_check"]], "cylc.flow.main_loop.log_data_store": [[31, "module-cylc.flow.main_loop.log_data_store"]], "cylc.flow.main_loop.log_main_loop": [[32, "module-cylc.flow.main_loop.log_main_loop"]], "cylc.flow.main_loop.log_memory": [[33, "module-cylc.flow.main_loop.log_memory"]], "cylc.flow.main_loop.reset_bad_hosts": [[34, "module-cylc.flow.main_loop.reset_bad_hosts"]], "does this change affect me?": [[10, null], [14, null]], "echo": [[126, "echo"]], "failed/XCPU": [[123, "failed-xcpu"]], "loadleveler": [[113, "module-cylc.flow.job_runner_handlers.loadleveler"]], "lsf": [[114, "module-cylc.flow.job_runner_handlers.lsf"]], "moab": [[115, "module-cylc.flow.job_runner_handlers.moab"]], "pbs": [[116, "module-cylc.flow.job_runner_handlers.pbs"]], "platform: - initialisation did not complete": [[123, "platform-name-initialisation-did-not-complete"]], "rose bunch": [[135, "rose-bunch"]], "sge": [[117, "module-cylc.flow.job_runner_handlers.sge"]], "slurm": [[118, "module-cylc.flow.job_runner_handlers.slurm"]], "slurm_packjob": [[119, "module-cylc.flow.job_runner_handlers.slurm_packjob"]], "socket.gaierror": [[123, "socket-gaierror"]], "xrandom": [[126, "xrandom"]]}, "docnames": ["7-to-8/caveats", "7-to-8/cheat-sheet", "7-to-8/index", "7-to-8/major-changes/cli", "7-to-8/major-changes/compatibility-mode", "7-to-8/major-changes/config-changes", "7-to-8/major-changes/continuing-c7-c8", "7-to-8/major-changes/cylc-install", "7-to-8/major-changes/excluding-tasks", "7-to-8/major-changes/index", "7-to-8/major-changes/parameters", "7-to-8/major-changes/platforms", "7-to-8/major-changes/play-pause-stop", "7-to-8/major-changes/python-2-3", "7-to-8/major-changes/remote-owner", "7-to-8/major-changes/scheduling", "7-to-8/major-changes/suicide-triggers", "7-to-8/major-changes/task-job-states", "7-to-8/major-changes/template-vars", "7-to-8/major-changes/ui", "7-to-8/summary", "glossary", "index", "installation", "plugins/cylc-rose", "plugins/index", "plugins/install/built-in/cylc.flow.install_plugins.log_vc_info", "plugins/install/index", "plugins/job-runners/index", "plugins/main-loop/built-in/cylc.flow.main_loop.auto_restart", "plugins/main-loop/built-in/cylc.flow.main_loop.health_check", "plugins/main-loop/built-in/cylc.flow.main_loop.log_data_store", "plugins/main-loop/built-in/cylc.flow.main_loop.log_main_loop", "plugins/main-loop/built-in/cylc.flow.main_loop.log_memory", "plugins/main-loop/built-in/cylc.flow.main_loop.reset_bad_hosts", "plugins/main-loop/index", "plugins/xtriggers/index", "reference/api/exceptions", "reference/api/index", "reference/api/scan", "reference/api/zmq", "reference/architecture/data-flow", "reference/architecture/index", "reference/architecture/ui-server", "reference/changes", "reference/config/file-format", "reference/config/global", "reference/config/index", "reference/config/sharing-access-to-workflows", "reference/config/shorthand", "reference/config/types", "reference/config/ui-server", "reference/config/workflow", "reference/config/writing-platform-configs", "reference/dev-history-major-changes", "reference/environments/conda", "reference/index", "reference/job-script-vars/index", "tutorial/furthertopics/broadcast", "tutorial/furthertopics/clock-triggered-tasks", "tutorial/furthertopics/family-triggers", "tutorial/furthertopics/index", "tutorial/furthertopics/inheritance", "tutorial/furthertopics/message-triggers", "tutorial/furthertopics/queues", "tutorial/furthertopics/retries", "tutorial/index", "tutorial/introduction", "tutorial/runtime/configuration-consolidation/families", "tutorial/runtime/configuration-consolidation/index", "tutorial/runtime/configuration-consolidation/jinja2", "tutorial/runtime/configuration-consolidation/parameters", "tutorial/runtime/index", "tutorial/runtime/introduction", "tutorial/runtime/runtime-configuration", "tutorial/runtime/summary", "tutorial/scheduling/datetime-cycling", "tutorial/scheduling/further-scheduling", "tutorial/scheduling/graphing", "tutorial/scheduling/index", "tutorial/scheduling/integer-cycling", "user-guide/cheat-sheet", "user-guide/examples/1-hello-world/index", "user-guide/examples/2-integer-cycling/index", "user-guide/examples/3-datetime-cycling/index", "user-guide/examples/converging-workflow/index", "user-guide/examples/event-driven-cycling/README", "user-guide/examples/event-driven-cycling/index", "user-guide/examples/extending-workflow/index", "user-guide/examples/index", "user-guide/examples/inter-workflow-triggers/README", "user-guide/examples/inter-workflow-triggers/index", "user-guide/index", "user-guide/installing-workflows", "user-guide/interventions/index", "user-guide/introduction", "user-guide/removing-workflows", "user-guide/running-workflows/authentication-files", "user-guide/running-workflows/dynamic-behaviour", "user-guide/running-workflows/handling-job-preemption", "user-guide/running-workflows/index", "user-guide/running-workflows/reflow", "user-guide/running-workflows/retrying-tasks", "user-guide/running-workflows/scheduler-log-files", "user-guide/running-workflows/scheduler-start-up", "user-guide/running-workflows/simulation-modes", "user-guide/running-workflows/tasks-jobs-ui", "user-guide/running-workflows/tracking-task-state", "user-guide/running-workflows/workflow-completion", "user-guide/running-workflows/workflow-databases", "user-guide/task-implementation/index", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.at", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.background", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.loadleveler", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.lsf", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.moab", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.pbs", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.sge", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm_packjob", "user-guide/task-implementation/job-scripts", "user-guide/task-implementation/job-submission", "user-guide/task-implementation/ssh-job-management", "user-guide/troubleshooting", "user-guide/writing-workflows/configuration", "user-guide/writing-workflows/empy", "user-guide/writing-workflows/external-triggers", "user-guide/writing-workflows/index", "user-guide/writing-workflows/jinja2", "user-guide/writing-workflows/parameterized-tasks", "user-guide/writing-workflows/runtime", "user-guide/writing-workflows/scheduler", "user-guide/writing-workflows/scheduling", "user-guide/writing-workflows/suicide-triggers", "workflow-design-guide/efficiency", "workflow-design-guide/general-principles", "workflow-design-guide/index", "workflow-design-guide/portable-workflows", "workflow-design-guide/style-guide"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.intersphinx": 1, "sphinx.ext.viewcode": 1}, "filenames": ["7-to-8/caveats.rst", "7-to-8/cheat-sheet.rst", "7-to-8/index.rst", "7-to-8/major-changes/cli.rst", "7-to-8/major-changes/compatibility-mode.rst", "7-to-8/major-changes/config-changes.rst", "7-to-8/major-changes/continuing-c7-c8.rst", "7-to-8/major-changes/cylc-install.rst", "7-to-8/major-changes/excluding-tasks.rst", "7-to-8/major-changes/index.rst", "7-to-8/major-changes/parameters.rst", "7-to-8/major-changes/platforms.rst", "7-to-8/major-changes/play-pause-stop.rst", "7-to-8/major-changes/python-2-3.rst", "7-to-8/major-changes/remote-owner.rst", "7-to-8/major-changes/scheduling.rst", "7-to-8/major-changes/suicide-triggers.rst", "7-to-8/major-changes/task-job-states.rst", "7-to-8/major-changes/template-vars.rst", "7-to-8/major-changes/ui.rst", "7-to-8/summary.rst", "glossary.rst", "index.rst", "installation.rst", "plugins/cylc-rose.rst", "plugins/index.rst", "plugins/install/built-in/cylc.flow.install_plugins.log_vc_info.rst", "plugins/install/index.rst", "plugins/job-runners/index.rst", "plugins/main-loop/built-in/cylc.flow.main_loop.auto_restart.rst", "plugins/main-loop/built-in/cylc.flow.main_loop.health_check.rst", "plugins/main-loop/built-in/cylc.flow.main_loop.log_data_store.rst", "plugins/main-loop/built-in/cylc.flow.main_loop.log_main_loop.rst", "plugins/main-loop/built-in/cylc.flow.main_loop.log_memory.rst", "plugins/main-loop/built-in/cylc.flow.main_loop.reset_bad_hosts.rst", "plugins/main-loop/index.rst", "plugins/xtriggers/index.rst", "reference/api/exceptions.rst", "reference/api/index.rst", "reference/api/scan.rst", "reference/api/zmq.rst", "reference/architecture/data-flow.rst", "reference/architecture/index.rst", "reference/architecture/ui-server.rst", "reference/changes.rst", "reference/config/file-format.rst", "reference/config/global.rst", "reference/config/index.rst", "reference/config/sharing-access-to-workflows.rst", "reference/config/shorthand.rst", "reference/config/types.rst", "reference/config/ui-server.rst", "reference/config/workflow.rst", "reference/config/writing-platform-configs.rst", "reference/dev-history-major-changes.rst", "reference/environments/conda.rst", "reference/index.rst", "reference/job-script-vars/index.rst", "tutorial/furthertopics/broadcast.rst", "tutorial/furthertopics/clock-triggered-tasks.rst", "tutorial/furthertopics/family-triggers.rst", "tutorial/furthertopics/index.rst", "tutorial/furthertopics/inheritance.rst", "tutorial/furthertopics/message-triggers.rst", "tutorial/furthertopics/queues.rst", "tutorial/furthertopics/retries.rst", "tutorial/index.rst", "tutorial/introduction.rst", "tutorial/runtime/configuration-consolidation/families.rst", "tutorial/runtime/configuration-consolidation/index.rst", "tutorial/runtime/configuration-consolidation/jinja2.rst", "tutorial/runtime/configuration-consolidation/parameters.rst", "tutorial/runtime/index.rst", "tutorial/runtime/introduction.rst", "tutorial/runtime/runtime-configuration.rst", "tutorial/runtime/summary.rst", "tutorial/scheduling/datetime-cycling.rst", "tutorial/scheduling/further-scheduling.rst", "tutorial/scheduling/graphing.rst", "tutorial/scheduling/index.rst", "tutorial/scheduling/integer-cycling.rst", "user-guide/cheat-sheet.rst", "user-guide/examples/1-hello-world/index.rst", "user-guide/examples/2-integer-cycling/index.rst", "user-guide/examples/3-datetime-cycling/index.rst", "user-guide/examples/converging-workflow/index.rst", "user-guide/examples/event-driven-cycling/README.rst", "user-guide/examples/event-driven-cycling/index.rst", "user-guide/examples/extending-workflow/index.rst", "user-guide/examples/index.rst", "user-guide/examples/inter-workflow-triggers/README.rst", "user-guide/examples/inter-workflow-triggers/index.rst", "user-guide/index.rst", "user-guide/installing-workflows.rst", "user-guide/interventions/index.rst", "user-guide/introduction.rst", "user-guide/removing-workflows.rst", "user-guide/running-workflows/authentication-files.rst", "user-guide/running-workflows/dynamic-behaviour.rst", "user-guide/running-workflows/handling-job-preemption.rst", "user-guide/running-workflows/index.rst", "user-guide/running-workflows/reflow.rst", "user-guide/running-workflows/retrying-tasks.rst", "user-guide/running-workflows/scheduler-log-files.rst", "user-guide/running-workflows/scheduler-start-up.rst", "user-guide/running-workflows/simulation-modes.rst", "user-guide/running-workflows/tasks-jobs-ui.rst", "user-guide/running-workflows/tracking-task-state.rst", "user-guide/running-workflows/workflow-completion.rst", "user-guide/running-workflows/workflow-databases.rst", "user-guide/task-implementation/index.rst", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.at.rst", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.background.rst", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.loadleveler.rst", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.lsf.rst", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.moab.rst", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.pbs.rst", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.sge.rst", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm.rst", "user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm_packjob.rst", "user-guide/task-implementation/job-scripts.rst", "user-guide/task-implementation/job-submission.rst", "user-guide/task-implementation/ssh-job-management.rst", "user-guide/troubleshooting.rst", "user-guide/writing-workflows/configuration.rst", "user-guide/writing-workflows/empy.rst", "user-guide/writing-workflows/external-triggers.rst", "user-guide/writing-workflows/index.rst", "user-guide/writing-workflows/jinja2.rst", "user-guide/writing-workflows/parameterized-tasks.rst", "user-guide/writing-workflows/runtime.rst", "user-guide/writing-workflows/scheduler.rst", "user-guide/writing-workflows/scheduling.rst", "user-guide/writing-workflows/suicide-triggers.rst", "workflow-design-guide/efficiency.rst", "workflow-design-guide/general-principles.rst", "workflow-design-guide/index.rst", "workflow-design-guide/portable-workflows.rst", "workflow-design-guide/style-guide.rst"], "indexentries": {"active": [[21, "term-active", true]], "active cycle": [[21, "term-active-cycle", true]], "active task": [[21, "term-active-task", true]], "active window": [[21, "term-active-window", true]], "api() (cylc.flow.network.server.workflowruntimeserver method)": [[40, "cylc.flow.network.server.WorkflowRuntimeServer.api", false]], "api_version() (in module cylc.flow.network.scan)": [[39, "cylc.flow.network.scan.api_version", false]], "artificial dependency": [[21, "term-artificial-dependency", true]], "async_request() (cylc.flow.network.client.workflowruntimeclient method)": [[40, "cylc.flow.network.client.WorkflowRuntimeClient.async_request", false]], "auto_restart() (in module cylc.flow.main_loop.auto_restart)": [[29, "cylc.flow.main_loop.auto_restart.auto_restart", false]], "branching": [[21, "term-branching", true]], "clienterror": [[37, "cylc.flow.exceptions.ClientError", false]], "clienttimeout": [[37, "cylc.flow.exceptions.ClientTimeout", false]], "clock expire": [[21, "term-clock-expire", true]], "clock trigger": [[21, "term-clock-trigger", true]], "cold start": [[21, "term-cold-start", true]], "commandfailederror": [[37, "cylc.flow.exceptions.CommandFailedError", false]], "conditional dependence": [[21, "term-conditional-dependence", true]], "conditional dependency": [[21, "term-conditional-dependency", true]], "conditional trigger": [[21, "term-conditional-trigger", true]], "contact file": [[21, "term-contact-file", true]], "contact_info() (in module cylc.flow.network.scan)": [[39, "cylc.flow.network.scan.contact_info", false]], "contactfileexists": [[37, "cylc.flow.exceptions.ContactFileExists", false]], "custom output": [[21, "term-custom-output", true]], "cycle": [[21, "term-cycle", true]], "cycle point": [[21, "term-cycle-point", true]], "cycle point time zone": [[21, "term-cycle-point-time-zone", true]], "cyclertypeerror": [[37, "cylc.flow.exceptions.CyclerTypeError", false]], "cycling": [[21, "term-cycling", true]], "cycling workflow": [[21, "term-cycling-workflow", true]], "cyclingerror": [[37, "cylc.flow.exceptions.CyclingError", false]], "cylc workflow": [[21, "term-cylc-workflow", true]], "cylc-run directory": [[21, "term-cylc-run-directory", true]], "cylc.flow.exceptions": [[37, "module-cylc.flow.exceptions", false]], "cylc.flow.install_plugins.log_vc_info": [[26, "module-cylc.flow.install_plugins.log_vc_info", false]], "cylc.flow.job_runner_handlers": [[121, "module-cylc.flow.job_runner_handlers", false]], "cylc.flow.job_runner_handlers.at": [[111, "module-cylc.flow.job_runner_handlers.at", false]], "cylc.flow.job_runner_handlers.background": [[112, "module-cylc.flow.job_runner_handlers.background", false]], "cylc.flow.job_runner_handlers.loadleveler": [[113, "module-cylc.flow.job_runner_handlers.loadleveler", false]], "cylc.flow.job_runner_handlers.lsf": [[114, "module-cylc.flow.job_runner_handlers.lsf", false]], "cylc.flow.job_runner_handlers.moab": [[115, "module-cylc.flow.job_runner_handlers.moab", false]], "cylc.flow.job_runner_handlers.pbs": [[116, "module-cylc.flow.job_runner_handlers.pbs", false]], "cylc.flow.job_runner_handlers.sge": [[117, "module-cylc.flow.job_runner_handlers.sge", false]], "cylc.flow.job_runner_handlers.slurm": [[118, "module-cylc.flow.job_runner_handlers.slurm", false]], "cylc.flow.job_runner_handlers.slurm_packjob": [[119, "module-cylc.flow.job_runner_handlers.slurm_packjob", false]], "cylc.flow.main_loop": [[35, "module-cylc.flow.main_loop", false]], "cylc.flow.main_loop.auto_restart": [[29, "module-cylc.flow.main_loop.auto_restart", false]], "cylc.flow.main_loop.health_check": [[30, "module-cylc.flow.main_loop.health_check", false]], "cylc.flow.main_loop.log_data_store": [[31, "module-cylc.flow.main_loop.log_data_store", false]], "cylc.flow.main_loop.log_main_loop": [[32, "module-cylc.flow.main_loop.log_main_loop", false]], "cylc.flow.main_loop.log_memory": [[33, "module-cylc.flow.main_loop.log_memory", false]], "cylc.flow.main_loop.reset_bad_hosts": [[34, "module-cylc.flow.main_loop.reset_bad_hosts", false]], "cylc.flow.network.scan": [[39, "module-cylc.flow.network.scan", false]], "cylc.flow.parsec.exceptions": [[37, "module-cylc.flow.parsec.exceptions", false]], "cylc.flow.scripts.lint": [[124, "module-cylc.flow.scripts.lint", false]], "cylc.flow.xtriggers.xrandom": [[126, "module-cylc.flow.xtriggers.xrandom", false]], "cylc.rose": [[24, "module-cylc.rose", false]], "cylc.uiserver.app": [[51, "module-cylc.uiserver.app", false]], "cylc_conf_path": [[46, "envvar-CYLC_CONF_PATH", false]], "cylc_site_conf_path": [[46, "envvar-CYLC_SITE_CONF_PATH", false], [46, "index-0", false]], "cylc_version() (in module cylc.flow.network.scan)": [[39, "cylc.flow.network.scan.cylc_version", false]], "cylcauthorizer (class in cylc.uiserver.authorise)": [[48, "cylc.uiserver.authorise.CylcAuthorizer", false]], "cylcconfigerror": [[37, "cylc.flow.exceptions.CylcConfigError", false]], "cylcerror": [[37, "cylc.flow.exceptions.CylcError", false]], "cylcmissingcontextpointerror": [[37, "cylc.flow.exceptions.CylcMissingContextPointError", false]], "cylcmissingfinalcyclepointerror": [[37, "cylc.flow.exceptions.CylcMissingFinalCyclePointError", false]], "cylctimesyntaxerror": [[37, "cylc.flow.exceptions.CylcTimeSyntaxError", false]], "cylcuiserver (class in cylc.uiserver.app)": [[51, "cylc.uiserver.app.CylcUIServer", false]], "cylcversionerror": [[37, "cylc.flow.exceptions.CylcVersionError", false]], "datetime cycling": [[21, "term-datetime-cycling", true]], "dependence": [[21, "term-dependence", true]], "dependency": [[21, "term-dependency", true]], "directive": [[21, "term-directive", true]], "duration_as() (in module cylc.flow.jinja.filters.duration_as)": [[128, "cylc.flow.jinja.filters.duration_as.duration_as", false]], "echo() (in module cylc.flow.xtriggers.echo)": [[126, "cylc.flow.xtriggers.echo.echo", false]], "empyerror": [[37, "cylc.flow.parsec.exceptions.EmPyError", false]], "environment variable": [[46, "envvar-CYLC_CONF_PATH", false], [46, "envvar-CYLC_SITE_CONF_PATH", false], [46, "index-0", false], [72, "index-0", false], [73, "index-0", false], [73, "index-1", false]], "event": [[21, "term-event", true]], "event handler": [[21, "term-event-handler", true]], "event handlers": [[21, "term-event-handlers", true]], "exact datetime unit": [[21, "term-exact-datetime-unit", true]], "examplehandler (class in cylc.flow.job_runner_handlers.documentation)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler", false]], "expected output": [[21, "term-expected-output", true]], "expired task": [[21, "term-expired-task", true]], "external trigger": [[21, "term-external-trigger", true]], "fail_signals (cylc.flow.job_runner_handlers.documentation.examplehandler attribute)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.FAIL_SIGNALS", false]], "family": [[21, "term-family", true]], "family inheritance": [[21, "term-family-inheritance", true]], "family trigger": [[21, "term-family-trigger", true]], "fileparseerror": [[37, "cylc.flow.parsec.exceptions.FileParseError", false]], "fileremovalerror": [[37, "cylc.flow.exceptions.FileRemovalError", false]], "filter_name() (in module cylc.flow.network.scan)": [[39, "cylc.flow.network.scan.filter_name", false]], "filter_poll_many_output() (cylc.flow.job_runner_handlers.documentation.examplehandler method)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.filter_poll_many_output", false]], "filter_submit_output() (cylc.flow.job_runner_handlers.documentation.examplehandler method)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.filter_submit_output", false]], "final cycle point": [[21, "term-final-cycle-point", true]], "final status": [[21, "term-final-status", true]], "flow": [[21, "term-flow", true]], "flow front": [[21, "term-flow-front", true]], "flow merge": [[21, "term-flow-merge", true]], "flow number": [[21, "term-flow-number", true]], "format_directives() (cylc.flow.job_runner_handlers.documentation.examplehandler method)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.format_directives", false]], "future trigger": [[21, "term-future-trigger", true]], "get_groups() (in module cylc.uiserver.authorise)": [[48, "cylc.uiserver.authorise.get_groups", false]], "get_hint() (cylc.flow.exceptions.hostselectexception method)": [[37, "cylc.flow.exceptions.HostSelectException.get_hint", false]], "get_poll_many_cmd() (cylc.flow.job_runner_handlers.documentation.examplehandler method)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.get_poll_many_cmd", false]], "get_submit_stdin() (cylc.flow.job_runner_handlers.documentation.examplehandler method)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.get_submit_stdin", false]], "get_vacation_signal() (cylc.flow.job_runner_handlers.documentation.examplehandler method)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.get_vacation_signal", false]], "globalconfigerror": [[37, "cylc.flow.exceptions.GlobalConfigError", false]], "graph": [[21, "term-graph", true]], "graph branching": [[21, "term-graph-branching", true]], "graph string": [[21, "term-graph-string", true]], "graphparseerror": [[37, "cylc.flow.exceptions.GraphParseError", false]], "graphql() (cylc.flow.network.server.workflowruntimeserver method)": [[40, "cylc.flow.network.server.WorkflowRuntimeServer.graphql", false]], "graphql_query() (in module cylc.flow.network.scan)": [[39, "cylc.flow.network.scan.graphql_query", false]], "handler": [[21, "term-handler", true]], "header (cylc.flow.network.client.workflowruntimeclient attribute)": [[40, "cylc.flow.network.client.WorkflowRuntimeClient.header", false]], "health_check() (in module cylc.flow.main_loop.health_check)": [[30, "cylc.flow.main_loop.health_check.health_check", false]], "held task": [[21, "term-held-task", true]], "hold": [[21, "term-hold", true]], "hold after cycle point": [[21, "term-hold-after-cycle-point", true]], "host (cylc.flow.network.client.workflowruntimeclient attribute)": [[40, "cylc.flow.network.client.WorkflowRuntimeClient.host", false]], "hostselectexception": [[37, "cylc.flow.exceptions.HostSelectException", false]], "illegalitemerror": [[37, "cylc.flow.parsec.exceptions.IllegalItemError", false]], "illegalvalueerror": [[37, "cylc.flow.parsec.exceptions.IllegalValueError", false]], "implicit task": [[21, "term-implicit-task", true]], "includefilenotfounderror": [[37, "cylc.flow.parsec.exceptions.IncludeFileNotFoundError", false]], "inexact datetime unit": [[21, "term-inexact-datetime-unit", true]], "init() (in module cylc.flow.main_loop.log_data_store)": [[31, "cylc.flow.main_loop.log_data_store.init", false]], "init() (in module cylc.flow.main_loop.log_main_loop)": [[32, "cylc.flow.main_loop.log_main_loop.init", false]], "init() (in module cylc.flow.main_loop.log_memory)": [[33, "cylc.flow.main_loop.log_memory.init", false]], "initial cycle point": [[21, "term-initial-cycle-point", true]], "inputerror": [[37, "cylc.flow.exceptions.InputError", false]], "install": [[21, "term-install", true]], "install target": [[21, "term-install-target", true]], "installation": [[21, "term-installation", true]], "integer cycling": [[21, "term-integer-cycling", true]], "intercycle dependence": [[21, "term-intercycle-dependence", true]], "intercycle dependency": [[21, "term-intercycle-dependency", true]], "intercycle trigger": [[21, "term-intercycle-trigger", true]], "internal queue": [[21, "term-internal-queue", true]], "intervalparsingerror": [[37, "cylc.flow.exceptions.IntervalParsingError", false]], "invalidcompletionexpression": [[37, "cylc.flow.exceptions.InvalidCompletionExpression", false]], "invalidconfigerror": [[37, "cylc.flow.parsec.exceptions.InvalidConfigError", false]], "is_active() (in module cylc.flow.network.scan)": [[39, "cylc.flow.network.scan.is_active", false]], "iso 8601": [[21, "term-ISO-8601", true]], "iso 8601 datetime": [[21, "term-ISO-8601-datetime", true]], "iso 8601 duration": [[21, "term-ISO-8601-duration", true]], "iso8601": [[21, "term-ISO8601", true]], "iso8601 datetime": [[21, "term-ISO8601-datetime", true]], "iso8601 duration": [[21, "term-ISO8601-duration", true]], "itemnotfounderror": [[37, "cylc.flow.parsec.exceptions.ItemNotFoundError", false]], "jinja2error": [[37, "cylc.flow.parsec.exceptions.Jinja2Error", false]], "job": [[21, "term-job", true]], "job host": [[21, "term-job-host", true]], "job log": [[21, "term-job-log", true]], "job log directory": [[21, "term-job-log-directory", true]], "job platform": [[21, "term-job-platform", true]], "job runner": [[21, "term-job-runner", true]], "job script": [[21, "term-job-script", true]], "job submission number": [[21, "term-job-submission-number", true]], "kill_cmd_tmpl (cylc.flow.job_runner_handlers.documentation.examplehandler attribute)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.KILL_CMD_TMPL", false]], "listvalueerror": [[37, "cylc.flow.parsec.exceptions.ListValueError", false]], "log_data_store() (in module cylc.flow.main_loop.log_data_store)": [[31, "cylc.flow.main_loop.log_data_store.log_data_store", false]], "manip_job_id() (cylc.flow.job_runner_handlers.documentation.examplehandler method)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.manip_job_id", false]], "max_threads (cylc.uiserver.app.cylcuiserver attribute)": [[51, "cylc.uiserver.app.CylcUIServer.max_threads", false]], "max_workers (cylc.uiserver.app.cylcuiserver attribute)": [[51, "cylc.uiserver.app.CylcUIServer.max_workers", false]], "message (cylc.flow.exceptions.clienterror attribute)": [[37, "cylc.flow.exceptions.ClientError.message", false]], "message trigger": [[21, "term-message-trigger", true]], "module": [[24, "module-cylc.rose", false], [26, "module-cylc.flow.install_plugins.log_vc_info", false], [29, "module-cylc.flow.main_loop.auto_restart", false], [30, "module-cylc.flow.main_loop.health_check", false], [31, "module-cylc.flow.main_loop.log_data_store", false], [32, "module-cylc.flow.main_loop.log_main_loop", false], [33, "module-cylc.flow.main_loop.log_memory", false], [34, "module-cylc.flow.main_loop.reset_bad_hosts", false], [35, "module-cylc.flow.main_loop", false], [37, "module-cylc.flow.exceptions", false], [37, "module-cylc.flow.parsec.exceptions", false], [39, "module-cylc.flow.network.scan", false], [51, "module-cylc.uiserver.app", false], [111, "module-cylc.flow.job_runner_handlers.at", false], [112, "module-cylc.flow.job_runner_handlers.background", false], [113, "module-cylc.flow.job_runner_handlers.loadleveler", false], [114, "module-cylc.flow.job_runner_handlers.lsf", false], [115, "module-cylc.flow.job_runner_handlers.moab", false], [116, "module-cylc.flow.job_runner_handlers.pbs", false], [117, "module-cylc.flow.job_runner_handlers.sge", false], [118, "module-cylc.flow.job_runner_handlers.slurm", false], [119, "module-cylc.flow.job_runner_handlers.slurm_packjob", false], [121, "module-cylc.flow.job_runner_handlers", false], [124, "module-cylc.flow.scripts.lint", false], [126, "module-cylc.flow.xtriggers.xrandom", false]], "n-window": [[21, "term-n-window", true]], "nohostserror": [[37, "cylc.flow.exceptions.NoHostsError", false]], "nominal duration": [[21, "term-nominal-duration", true]], "noplatformserror": [[37, "cylc.flow.exceptions.NoPlatformsError", false]], "notsingleitemerror": [[37, "cylc.flow.parsec.exceptions.NotSingleItemError", false]], "operate() (cylc.flow.network.server.workflowruntimeserver method)": [[40, "cylc.flow.network.server.WorkflowRuntimeServer.operate", false]], "optional output": [[21, "term-optional-output", true]], "output": [[21, "term-output", true]], "output completion": [[21, "term-output-completion", true]], "output completion condition": [[21, "term-output-completion-condition", true]], "pad() (in module cylc.flow.jinja.filters.pad)": [[128, "cylc.flow.jinja.filters.pad.pad", false]], "parameterization": [[21, "term-parameterization", true]], "paramexpanderror": [[37, "cylc.flow.exceptions.ParamExpandError", false]], "parsecerror": [[37, "cylc.flow.parsec.exceptions.ParsecError", false]], "pause": [[21, "term-pause", true]], "pb_data_elements() (cylc.flow.network.server.workflowruntimeserver method)": [[40, "cylc.flow.network.server.WorkflowRuntimeServer.pb_data_elements", false]], "pb_entire_workflow() (cylc.flow.network.server.workflowruntimeserver method)": [[40, "cylc.flow.network.server.WorkflowRuntimeServer.pb_entire_workflow", false]], "periodic() (in module cylc.flow.main_loop)": [[35, "cylc.flow.main_loop.periodic", false]], "platform": [[21, "term-platform", true]], "platform group": [[21, "term-platform-group", true]], "platformerror": [[37, "cylc.flow.exceptions.PlatformError", false]], "platformlookuperror": [[37, "cylc.flow.exceptions.PlatformLookupError", false]], "play": [[21, "term-play", true]], "pluginerror": [[37, "cylc.flow.exceptions.PluginError", false]], "pointparsingerror": [[37, "cylc.flow.exceptions.PointParsingError", false]], "poll_cant_connect_err (cylc.flow.job_runner_handlers.documentation.examplehandler attribute)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.POLL_CANT_CONNECT_ERR", false]], "poll_cmd (cylc.flow.job_runner_handlers.documentation.examplehandler attribute)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.POLL_CMD", false]], "port (cylc.flow.network.client.workflowruntimeclient attribute)": [[40, "cylc.flow.network.client.WorkflowRuntimeClient.port", false]], "prerequisite": [[21, "term-prerequisite", true]], "profile (cylc.uiserver.app.cylcuiserver attribute)": [[51, "cylc.uiserver.app.CylcUIServer.profile", false]], "publish_queued_items() (cylc.flow.network.server.workflowruntimeserver method)": [[40, "cylc.flow.network.server.WorkflowRuntimeServer.publish_queued_items", false]], "pythonpath": [[72, "index-0", false], [73, "index-0", false], [73, "index-1", false]], "qualifier": [[21, "term-qualifier", true]], "queue": [[21, "term-queue", true]], "rec_id_from_submit_err (cylc.flow.job_runner_handlers.documentation.examplehandler attribute)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.REC_ID_FROM_SUBMIT_ERR", false]], "rec_id_from_submit_out (cylc.flow.job_runner_handlers.documentation.examplehandler attribute)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.REC_ID_FROM_SUBMIT_OUT", false]], "receiver() (cylc.flow.network.server.workflowruntimeserver method)": [[40, "cylc.flow.network.server.WorkflowRuntimeServer.receiver", false]], "recurrence": [[21, "term-recurrence", true]], "register_endpoints() (cylc.flow.network.server.workflowruntimeserver method)": [[40, "cylc.flow.network.server.WorkflowRuntimeServer.register_endpoints", false]], "reinstall": [[21, "term-reinstall", true]], "reinstallation": [[21, "term-reinstallation", true]], "release": [[21, "term-release", true]], "reload": [[21, "term-reload", true]], "report() (in module cylc.flow.main_loop.log_data_store)": [[31, "cylc.flow.main_loop.log_data_store.report", false]], "report() (in module cylc.flow.main_loop.log_main_loop)": [[32, "cylc.flow.main_loop.log_main_loop.report", false]], "report() (in module cylc.flow.main_loop.log_memory)": [[33, "cylc.flow.main_loop.log_memory.report", false]], "required output": [[21, "term-required-output", true]], "reset_bad_hosts() (in module cylc.flow.main_loop.reset_bad_hosts)": [[34, "cylc.flow.main_loop.reset_bad_hosts.reset_bad_hosts", false]], "restart": [[21, "term-restart", true]], "retry": [[21, "term-retry", true]], "run directory": [[21, "term-run-directory", true]], "runahead": [[21, "term-runahead", true]], "runahead limit": [[21, "term-runahead-limit", true]], "runtime inheritance": [[21, "term-runtime-inheritance", true]], "scan() (in module cylc.flow.network.scan)": [[39, "cylc.flow.network.scan.scan", false]], "scan_interval (cylc.uiserver.app.cylcuiserver attribute)": [[51, "cylc.uiserver.app.CylcUIServer.scan_interval", false]], "schd_expected (cylc.flow.parsec.exceptions.parsecerror attribute)": [[37, "cylc.flow.parsec.exceptions.ParsecError.schd_expected", false]], "scheduler": [[21, "term-scheduler", true]], "scheduler log": [[21, "term-scheduler-log", true]], "sequencedegenerateerror": [[37, "cylc.flow.exceptions.SequenceDegenerateError", false]], "sequenceparsingerror": [[37, "cylc.flow.exceptions.SequenceParsingError", false]], "serial_request() (cylc.flow.network.client.workflowruntimeclient method)": [[40, "cylc.flow.network.client.WorkflowRuntimeClient.serial_request", false]], "service directory": [[21, "term-service-directory", true]], "servicefileerror": [[37, "cylc.flow.exceptions.ServiceFileError", false]], "share directory": [[21, "term-share-directory", true]], "should_kill_proc_group (cylc.flow.job_runner_handlers.documentation.examplehandler attribute)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.SHOULD_KILL_PROC_GROUP", false]], "should_poll_proc_group (cylc.flow.job_runner_handlers.documentation.examplehandler attribute)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.SHOULD_POLL_PROC_GROUP", false]], "shutdown": [[21, "term-shutdown", true]], "shutdown() (in module cylc.flow.main_loop)": [[35, "cylc.flow.main_loop.shutdown", false]], "site_authorization (cylc.uiserver.app.cylcuiserver attribute)": [[51, "cylc.uiserver.app.CylcUIServer.site_authorization", false]], "source directory": [[21, "term-source-directory", true]], "source workflow": [[21, "term-source-workflow", true]], "stall": [[21, "term-stall", true]], "stalled workflow": [[21, "term-stalled-workflow", true]], "standard output": [[21, "term-standard-output", true]], "start": [[21, "term-start", true]], "start cycle point": [[21, "term-start-cycle-point", true]], "start task": [[21, "term-start-task", true]], "start() (cylc.flow.network.server.workflowruntimeserver method)": [[40, "cylc.flow.network.server.WorkflowRuntimeServer.start", false]], "startup": [[21, "term-startup", true]], "startup() (in module cylc.flow.main_loop)": [[35, "cylc.flow.main_loop.startup", false]], "stop": [[21, "term-stop", true]], "stop cycle point": [[21, "term-stop-cycle-point", true]], "stop() (cylc.flow.network.server.workflowruntimeserver method)": [[40, "cylc.flow.network.server.WorkflowRuntimeServer.stop", false]], "strftime() (in module cylc.flow.jinja.filters.strftime)": [[128, "cylc.flow.jinja.filters.strftime.strftime", false]], "submit number": [[21, "term-submit-number", true]], "submit() (cylc.flow.job_runner_handlers.documentation.examplehandler method)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.submit", false]], "submit_cmd_env (cylc.flow.job_runner_handlers.documentation.examplehandler attribute)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.SUBMIT_CMD_ENV", false]], "submit_cmd_tmpl (cylc.flow.job_runner_handlers.documentation.examplehandler attribute)": [[28, "cylc.flow.job_runner_handlers.documentation.ExampleHandler.SUBMIT_CMD_TMPL", false]], "suicide trigger": [[21, "term-suicide-trigger", true]], "take_snapshot() (in module cylc.flow.main_loop.log_memory)": [[33, "cylc.flow.main_loop.log_memory.take_snapshot", false]], "task": [[21, "term-task", true]], "task output": [[21, "term-task-output", true]], "task parameters": [[21, "term-task-parameters", true]], "task retry": [[21, "term-task-retry", true]], "task state": [[21, "term-task-state", true]], "task submit number": [[21, "term-task-submit-number", true]], "task trigger": [[21, "term-task-trigger", true]], "taskdeferror": [[37, "cylc.flow.exceptions.TaskDefError", false]], "tasknamevalidator (class in cylc.flow.unicode_rules)": [[130, "cylc.flow.unicode_rules.TaskNameValidator", false]], "taskproxysequenceboundserror": [[37, "cylc.flow.exceptions.TaskProxySequenceBoundsError", false]], "templatevarlanguageclash": [[37, "cylc.flow.parsec.exceptions.TemplateVarLanguageClash", false]], "timeout_handler (cylc.flow.network.client.workflowruntimeclient attribute)": [[40, "cylc.flow.network.client.WorkflowRuntimeClient.timeout_handler", false]], "title() (in module cylc.flow.network.scan)": [[39, "cylc.flow.network.scan.title", false]], "traceback (cylc.flow.exceptions.clienterror attribute)": [[37, "cylc.flow.exceptions.ClientError.traceback", false]], "trigger": [[21, "term-trigger", true]], "triggerexpressionerror": [[37, "cylc.flow.exceptions.TriggerExpressionError", false]], "try number": [[21, "term-try-number", true]], "ui_build_dir (cylc.uiserver.app.cylcuiserver attribute)": [[51, "cylc.uiserver.app.CylcUIServer.ui_build_dir", false]], "ui_version (cylc.uiserver.app.cylcuiserver attribute)": [[51, "cylc.uiserver.app.CylcUIServer.ui_version", false]], "upgradeerror": [[37, "cylc.flow.parsec.exceptions.UpgradeError", false]], "user_authorization (cylc.uiserver.app.cylcuiserver attribute)": [[51, "cylc.uiserver.app.CylcUIServer.user_authorization", false]], "validate() (in module cylc.flow.xtriggers.xrandom)": [[126, "cylc.flow.xtriggers.xrandom.validate", false]], "validation": [[21, "term-validation", true]], "validationerror": [[37, "cylc.flow.parsec.exceptions.ValidationError", false]], "wall_clock() (in module cylc.flow.xtriggers.wall_clock)": [[126, "cylc.flow.xtriggers.wall_clock.wall_clock", false]], "wallclock time": [[21, "term-wallclock-time", true]], "warm start": [[21, "term-warm-start", true]], "window": [[21, "term-window", true]], "work directory": [[21, "term-work-directory", true]], "workflow": [[21, "term-workflow", true]], "workflow (cylc.flow.exceptions.clienterror attribute)": [[37, "cylc.flow.exceptions.ClientError.workflow", false]], "workflow completion": [[21, "term-workflow-completion", true]], "workflow id": [[21, "term-workflow-id", true]], "workflow installation": [[21, "term-workflow-installation", true]], "workflow log": [[21, "term-workflow-log", true]], "workflow log directory": [[21, "term-workflow-log-directory", true]], "workflow name": [[21, "term-workflow-name", true]], "workflow run directory": [[21, "term-workflow-run-directory", true]], "workflow validation": [[21, "term-workflow-validation", true]], "workflow_params() (in module cylc.flow.network.scan)": [[39, "cylc.flow.network.scan.workflow_params", false]], "workflow_state() (in module cylc.flow.xtriggers.workflow_state)": [[126, "cylc.flow.xtriggers.workflow_state.workflow_state", false]], "workflowconfigerror": [[37, "cylc.flow.exceptions.WorkflowConfigError", false]], "workfloweventerror": [[37, "cylc.flow.exceptions.WorkflowEventError", false]], "workflowfileserror": [[37, "cylc.flow.exceptions.WorkflowFilesError", false]], "workflownamevalidator (class in cylc.flow.unicode_rules)": [[93, "cylc.flow.unicode_rules.WorkflowNameValidator", false]], "workflowruntimeclient (class in cylc.flow.network.client)": [[40, "cylc.flow.network.client.WorkflowRuntimeClient", false]], "workflowruntimeserver (class in cylc.flow.network.server)": [[40, "cylc.flow.network.server.WorkflowRuntimeServer", false]], "workflowstopped": [[37, "cylc.flow.exceptions.WorkflowStopped", false]], "xrandom() (in module cylc.flow.xtriggers.xrandom)": [[126, "cylc.flow.xtriggers.xrandom.xrandom", false]], "xtrigger": [[21, "term-xtrigger", true]], "xtriggerconfigerror": [[37, "cylc.flow.exceptions.XtriggerConfigError", false]], "xtriggernamevalidator (class in cylc.flow.unicode_rules)": [[126, "cylc.flow.unicode_rules.XtriggerNameValidator", false]]}, "objects": {"": [[50, 3, 1, "", "absolute host list"], [50, 3, 1, "", "boolean"], [50, 3, 1, "", "cycle point"], [50, 3, 1, "", "cycle point format"], [50, 3, 1, "", "cycle point time zone"], [50, 3, 1, "", "cycle point with support for offsets"], [50, 3, 1, "", "float"], [50, 3, 1, "", "float list"], [50, 3, 1, "", "integer"], [50, 3, 1, "", "integer list"], [50, 3, 1, "", "integer range"], [50, 3, 1, "", "list"], [50, 3, 1, "", "parameter list"], [50, 3, 1, "", "spaceless list"], [50, 3, 1, "", "string"], [50, 3, 1, "", "time interval"], [50, 3, 1, "", "time interval list"], [50, 3, 1, "", "xtrigger function signature"], [46, 10, 1, "-", "CYLC_CONF_PATH"], [46, 10, 1, "-", "CYLC_SITE_CONF_PATH"]], "cylc": [[24, 4, 0, "-", "rose"]], "cylc.flow": [[37, 4, 0, "-", "exceptions"], [121, 4, 0, "-", "job_runner_handlers"], [35, 4, 0, "-", "main_loop"]], "cylc.flow.exceptions": [[37, 5, 1, "", "ClientError"], [37, 5, 1, "", "ClientTimeout"], [37, 5, 1, "", "CommandFailedError"], [37, 5, 1, "", "ContactFileExists"], [37, 5, 1, "", "CyclerTypeError"], [37, 5, 1, "", "CyclingError"], [37, 5, 1, "", "CylcConfigError"], [37, 5, 1, "", "CylcError"], [37, 5, 1, "", "CylcMissingContextPointError"], [37, 5, 1, "", "CylcMissingFinalCyclePointError"], [37, 5, 1, "", "CylcTimeSyntaxError"], [37, 5, 1, "", "CylcVersionError"], [37, 5, 1, "", "FileRemovalError"], [37, 5, 1, "", "GlobalConfigError"], [37, 5, 1, "", "GraphParseError"], [37, 5, 1, "", "HostSelectException"], [37, 5, 1, "", "InputError"], [37, 5, 1, "", "IntervalParsingError"], [37, 5, 1, "", "InvalidCompletionExpression"], [37, 5, 1, "", "NoHostsError"], [37, 5, 1, "", "NoPlatformsError"], [37, 5, 1, "", "ParamExpandError"], [37, 5, 1, "", "PlatformError"], [37, 5, 1, "", "PlatformLookupError"], [37, 5, 1, "", "PluginError"], [37, 5, 1, "", "PointParsingError"], [37, 5, 1, "", "SequenceDegenerateError"], [37, 5, 1, "", "SequenceParsingError"], [37, 5, 1, "", "ServiceFileError"], [37, 5, 1, "", "TaskDefError"], [37, 5, 1, "", "TaskProxySequenceBoundsError"], [37, 5, 1, "", "TriggerExpressionError"], [37, 5, 1, "", "WorkflowConfigError"], [37, 5, 1, "", "WorkflowEventError"], [37, 5, 1, "", "WorkflowFilesError"], [37, 5, 1, "", "WorkflowStopped"], [37, 5, 1, "", "XtriggerConfigError"]], "cylc.flow.exceptions.ClientError": [[37, 6, 1, "", "message"], [37, 6, 1, "", "traceback"], [37, 6, 1, "", "workflow"]], "cylc.flow.exceptions.HostSelectException": [[37, 7, 1, "", "get_hint"]], "cylc.flow.install_plugins": [[26, 4, 0, "-", "log_vc_info"]], "cylc.flow.jinja.filters.duration_as": [[128, 8, 1, "", "duration_as"]], "cylc.flow.jinja.filters.pad": [[128, 8, 1, "", "pad"]], "cylc.flow.jinja.filters.strftime": [[128, 8, 1, "", "strftime"]], "cylc.flow.job_runner_handlers": [[111, 4, 0, "-", "at"], [112, 4, 0, "-", "background"], [113, 4, 0, "-", "loadleveler"], [114, 4, 0, "-", "lsf"], [115, 4, 0, "-", "moab"], [116, 4, 0, "-", "pbs"], [117, 4, 0, "-", "sge"], [118, 4, 0, "-", "slurm"], [119, 4, 0, "-", "slurm_packjob"]], "cylc.flow.job_runner_handlers.documentation": [[28, 9, 1, "", "ExampleHandler"]], "cylc.flow.job_runner_handlers.documentation.ExampleHandler": [[28, 6, 1, "", "FAIL_SIGNALS"], [28, 6, 1, "", "KILL_CMD_TMPL"], [28, 6, 1, "", "POLL_CANT_CONNECT_ERR"], [28, 6, 1, "", "POLL_CMD"], [28, 6, 1, "", "REC_ID_FROM_SUBMIT_ERR"], [28, 6, 1, "", "REC_ID_FROM_SUBMIT_OUT"], [28, 6, 1, "", "SHOULD_KILL_PROC_GROUP"], [28, 6, 1, "", "SHOULD_POLL_PROC_GROUP"], [28, 6, 1, "", "SUBMIT_CMD_ENV"], [28, 6, 1, "", "SUBMIT_CMD_TMPL"], [28, 7, 1, "", "filter_poll_many_output"], [28, 7, 1, "", "filter_submit_output"], [28, 7, 1, "", "format_directives"], [28, 7, 1, "", "get_poll_many_cmd"], [28, 7, 1, "", "get_submit_stdin"], [28, 7, 1, "", "get_vacation_signal"], [28, 7, 1, "", "manip_job_id"], [28, 7, 1, "", "submit"]], "cylc.flow.main_loop": [[29, 4, 0, "-", "auto_restart"], [30, 4, 0, "-", "health_check"], [31, 4, 0, "-", "log_data_store"], [32, 4, 0, "-", "log_main_loop"], [33, 4, 0, "-", "log_memory"], [35, 8, 1, "", "periodic"], [34, 4, 0, "-", "reset_bad_hosts"], [35, 8, 1, "", "shutdown"], [35, 8, 1, "", "startup"]], "cylc.flow.main_loop.auto_restart": [[29, 8, 1, "", "auto_restart"]], "cylc.flow.main_loop.health_check": [[30, 8, 1, "", "health_check"]], "cylc.flow.main_loop.log_data_store": [[31, 8, 1, "", "init"], [31, 8, 1, "", "log_data_store"], [31, 8, 1, "", "report"]], "cylc.flow.main_loop.log_main_loop": [[32, 8, 1, "", "init"], [32, 8, 1, "", "report"]], "cylc.flow.main_loop.log_memory": [[33, 8, 1, "", "init"], [33, 8, 1, "", "report"], [33, 8, 1, "", "take_snapshot"]], "cylc.flow.main_loop.reset_bad_hosts": [[34, 8, 1, "", "reset_bad_hosts"]], "cylc.flow.network": [[39, 4, 0, "-", "scan"]], "cylc.flow.network.client": [[40, 9, 1, "", "WorkflowRuntimeClient"]], "cylc.flow.network.client.WorkflowRuntimeClient": [[40, 7, 1, "", "async_request"], [40, 6, 1, "", "header"], [40, 6, 1, "", "host"], [40, 6, 1, "", "port"], [40, 7, 1, "", "serial_request"], [40, 6, 1, "", "timeout_handler"]], "cylc.flow.network.scan": [[39, 8, 1, "", "api_version"], [39, 8, 1, "", "contact_info"], [39, 8, 1, "", "cylc_version"], [39, 8, 1, "", "filter_name"], [39, 8, 1, "", "graphql_query"], [39, 8, 1, "", "is_active"], [39, 8, 1, "", "scan"], [39, 8, 1, "", "title"], [39, 8, 1, "", "workflow_params"]], "cylc.flow.network.server": [[40, 9, 1, "", "WorkflowRuntimeServer"]], "cylc.flow.network.server.WorkflowRuntimeServer": [[40, 7, 1, "", "api"], [40, 7, 1, "", "graphql"], [40, 7, 1, "", "operate"], [40, 7, 1, "", "pb_data_elements"], [40, 7, 1, "", "pb_entire_workflow"], [40, 7, 1, "", "publish_queued_items"], [40, 7, 1, "", "receiver"], [40, 7, 1, "", "register_endpoints"], [40, 7, 1, "", "start"], [40, 7, 1, "", "stop"]], "cylc.flow.parsec": [[37, 4, 0, "-", "exceptions"]], "cylc.flow.parsec.exceptions": [[37, 5, 1, "", "EmPyError"], [37, 5, 1, "", "FileParseError"], [37, 5, 1, "", "IllegalItemError"], [37, 5, 1, "", "IllegalValueError"], [37, 5, 1, "", "IncludeFileNotFoundError"], [37, 5, 1, "", "InvalidConfigError"], [37, 5, 1, "", "ItemNotFoundError"], [37, 5, 1, "", "Jinja2Error"], [37, 5, 1, "", "ListValueError"], [37, 5, 1, "", "NotSingleItemError"], [37, 5, 1, "", "ParsecError"], [37, 5, 1, "", "TemplateVarLanguageClash"], [37, 5, 1, "", "UpgradeError"], [37, 5, 1, "", "ValidationError"]], "cylc.flow.parsec.exceptions.ParsecError": [[37, 6, 1, "", "schd_expected"]], "cylc.flow.scripts": [[124, 4, 0, "-", "lint"]], "cylc.flow.unicode_rules": [[130, 9, 1, "", "TaskNameValidator"], [93, 9, 1, "", "WorkflowNameValidator"], [126, 9, 1, "", "XtriggerNameValidator"]], "cylc.flow.xtriggers": [[126, 4, 0, "-", "xrandom"]], "cylc.flow.xtriggers.echo": [[126, 8, 1, "", "echo"]], "cylc.flow.xtriggers.wall_clock": [[126, 8, 1, "", "wall_clock"]], "cylc.flow.xtriggers.workflow_state": [[126, 8, 1, "", "workflow_state"]], "cylc.flow.xtriggers.xrandom": [[126, 8, 1, "", "validate"], [126, 8, 1, "", "xrandom"]], "cylc.uiserver": [[51, 4, 0, "-", "app"]], "cylc.uiserver.app": [[51, 9, 1, "", "CylcUIServer"]], "cylc.uiserver.app.CylcUIServer": [[51, 6, 1, "", "max_threads"], [51, 6, 1, "", "max_workers"], [51, 6, 1, "", "profile"], [51, 6, 1, "", "scan_interval"], [51, 6, 1, "", "site_authorization"], [51, 6, 1, "", "ui_build_dir"], [51, 6, 1, "", "ui_version"], [51, 6, 1, "", "user_authorization"]], "cylc.uiserver.authorise": [[48, 9, 1, "", "CylcAuthorizer"], [48, 8, 1, "", "get_groups"]], "flow": [[52, 0, 1, "", "cylc"], [52, 1, 1, "", "cylc[meta]"], [52, 2, 1, "flow.cylc[meta]", "cylc[meta]<custom metadata>"], [52, 2, 1, "", "cylc[meta]URL"], [52, 2, 1, "", "cylc[meta]description"], [52, 2, 1, "", "cylc[meta]title"], [52, 1, 1, "", "cylc[runtime]"], [52, 1, 1, "flow.cylc[runtime][]", "cylc[runtime][<namespace>]"], [52, 1, 1, "flow.cylc[runtime][][directives]", "cylc[runtime][<namespace>][directives]"], [52, 2, 1, "flow.cylc[runtime][][directives]", "cylc[runtime][<namespace>][directives]<directive>"], [52, 1, 1, "flow.cylc[runtime][][environment filter]", "cylc[runtime][<namespace>][environment filter]"], [52, 2, 1, "flow.cylc[runtime][][environment filter]exclude", "cylc[runtime][<namespace>][environment filter]exclude"], [52, 2, 1, "flow.cylc[runtime][][environment filter]include", "cylc[runtime][<namespace>][environment filter]include"], [52, 1, 1, "flow.cylc[runtime][][environment]", "cylc[runtime][<namespace>][environment]"], [52, 2, 1, "flow.cylc[runtime][][environment]", "cylc[runtime][<namespace>][environment]<variable>"], [52, 1, 1, "flow.cylc[runtime][][events]", "cylc[runtime][<namespace>][events]"], [52, 2, 1, "flow.cylc[runtime][][events]critical handlers", "cylc[runtime][<namespace>][events]critical handlers"], [52, 2, 1, "flow.cylc[runtime][][events]custom handlers", "cylc[runtime][<namespace>][events]custom handlers"], [52, 2, 1, "flow.cylc[runtime][][events]execution timeout", "cylc[runtime][<namespace>][events]execution timeout"], [52, 2, 1, "flow.cylc[runtime][][events]execution timeout handlers", "cylc[runtime][<namespace>][events]execution timeout handlers"], [52, 2, 1, "flow.cylc[runtime][][events]expired handlers", "cylc[runtime][<namespace>][events]expired handlers"], [52, 2, 1, "flow.cylc[runtime][][events]failed handlers", "cylc[runtime][<namespace>][events]failed handlers"], [52, 2, 1, "flow.cylc[runtime][][events]handler events", "cylc[runtime][<namespace>][events]handler events"], [52, 2, 1, "flow.cylc[runtime][][events]handler retry delays", "cylc[runtime][<namespace>][events]handler retry delays"], [52, 2, 1, "flow.cylc[runtime][][events]handlers", "cylc[runtime][<namespace>][events]handlers"], [52, 2, 1, "flow.cylc[runtime][][events]late handlers", "cylc[runtime][<namespace>][events]late handlers"], [52, 2, 1, "flow.cylc[runtime][][events]late offset", "cylc[runtime][<namespace>][events]late offset"], [52, 2, 1, "flow.cylc[runtime][][events]mail events", "cylc[runtime][<namespace>][events]mail events"], [52, 2, 1, "flow.cylc[runtime][][events]retry handlers", "cylc[runtime][<namespace>][events]retry handlers"], [52, 2, 1, "flow.cylc[runtime][][events]started handlers", "cylc[runtime][<namespace>][events]started handlers"], [52, 2, 1, "flow.cylc[runtime][][events]submission failed handlers", "cylc[runtime][<namespace>][events]submission failed handlers"], [52, 2, 1, "flow.cylc[runtime][][events]submission retry handlers", "cylc[runtime][<namespace>][events]submission retry handlers"], [52, 2, 1, "flow.cylc[runtime][][events]submission timeout", "cylc[runtime][<namespace>][events]submission timeout"], [52, 2, 1, "flow.cylc[runtime][][events]submission timeout handlers", "cylc[runtime][<namespace>][events]submission timeout handlers"], [52, 2, 1, "flow.cylc[runtime][][events]submitted handlers", "cylc[runtime][<namespace>][events]submitted handlers"], [52, 2, 1, "flow.cylc[runtime][][events]succeeded handlers", "cylc[runtime][<namespace>][events]succeeded handlers"], [52, 2, 1, "flow.cylc[runtime][][events]warning handlers", "cylc[runtime][<namespace>][events]warning handlers"], [52, 1, 1, "flow.cylc[runtime][][job]", "cylc[runtime][<namespace>][job]"], [52, 2, 1, "flow.cylc[runtime][][job]batch submit command template", "cylc[runtime][<namespace>][job]batch submit command template"], [52, 2, 1, "flow.cylc[runtime][][job]batch system", "cylc[runtime][<namespace>][job]batch system"], [52, 1, 1, "flow.cylc[runtime][][mail]", "cylc[runtime][<namespace>][mail]"], [52, 2, 1, "flow.cylc[runtime][][mail]from", "cylc[runtime][<namespace>][mail]from"], [52, 2, 1, "flow.cylc[runtime][][mail]to", "cylc[runtime][<namespace>][mail]to"], [52, 1, 1, "flow.cylc[runtime][][meta]", "cylc[runtime][<namespace>][meta]"], [52, 2, 1, "flow.cylc[runtime][][meta]", "cylc[runtime][<namespace>][meta]<custom metadata>"], [52, 2, 1, "flow.cylc[runtime][][meta]URL", "cylc[runtime][<namespace>][meta]URL"], [52, 2, 1, "flow.cylc[runtime][][meta]description", "cylc[runtime][<namespace>][meta]description"], [52, 2, 1, "flow.cylc[runtime][][meta]title", "cylc[runtime][<namespace>][meta]title"], [52, 1, 1, "flow.cylc[runtime][][outputs]", "cylc[runtime][<namespace>][outputs]"], [52, 2, 1, "flow.cylc[runtime][][outputs]", "cylc[runtime][<namespace>][outputs]<output>"], [52, 1, 1, "flow.cylc[runtime][][parameter environment templates]", "cylc[runtime][<namespace>][parameter environment templates]"], [52, 2, 1, "flow.cylc[runtime][][parameter environment templates]", "cylc[runtime][<namespace>][parameter environment templates]<parameter>"], [52, 1, 1, "flow.cylc[runtime][][remote]", "cylc[runtime][<namespace>][remote]"], [52, 2, 1, "flow.cylc[runtime][][remote]host", "cylc[runtime][<namespace>][remote]host"], [52, 2, 1, "flow.cylc[runtime][][remote]owner", "cylc[runtime][<namespace>][remote]owner"], [52, 2, 1, "flow.cylc[runtime][][remote]retrieve job logs", "cylc[runtime][<namespace>][remote]retrieve job logs"], [52, 2, 1, "flow.cylc[runtime][][remote]retrieve job logs max size", "cylc[runtime][<namespace>][remote]retrieve job logs max size"], [52, 2, 1, "flow.cylc[runtime][][remote]retrieve job logs retry delays", "cylc[runtime][<namespace>][remote]retrieve job logs retry delays"], [52, 1, 1, "flow.cylc[runtime][][simulation]", "cylc[runtime][<namespace>][simulation]"], [52, 2, 1, "flow.cylc[runtime][][simulation]default run length", "cylc[runtime][<namespace>][simulation]default run length"], [52, 2, 1, "flow.cylc[runtime][][simulation]disable task event handlers", "cylc[runtime][<namespace>][simulation]disable task event handlers"], [52, 2, 1, "flow.cylc[runtime][][simulation]fail cycle points", "cylc[runtime][<namespace>][simulation]fail cycle points"], [52, 2, 1, "flow.cylc[runtime][][simulation]fail try 1 only", "cylc[runtime][<namespace>][simulation]fail try 1 only"], [52, 2, 1, "flow.cylc[runtime][][simulation]speedup factor", "cylc[runtime][<namespace>][simulation]speedup factor"], [52, 2, 1, "flow.cylc[runtime][][simulation]time limit buffer", "cylc[runtime][<namespace>][simulation]time limit buffer"], [52, 1, 1, "flow.cylc[runtime][][workflow state polling]", "cylc[runtime][<namespace>][workflow state polling]"], [52, 2, 1, "flow.cylc[runtime][][workflow state polling]alt-cylc-run-dir", "cylc[runtime][<namespace>][workflow state polling]alt-cylc-run-dir"], [52, 2, 1, "flow.cylc[runtime][][workflow state polling]interval", "cylc[runtime][<namespace>][workflow state polling]interval"], [52, 2, 1, "flow.cylc[runtime][][workflow state polling]max-polls", "cylc[runtime][<namespace>][workflow state polling]max-polls"], [52, 2, 1, "flow.cylc[runtime][][workflow state polling]message", "cylc[runtime][<namespace>][workflow state polling]message"], [52, 2, 1, "flow.cylc[runtime][][workflow state polling]verbose mode", "cylc[runtime][<namespace>][workflow state polling]verbose mode"], [52, 2, 1, "flow.cylc[runtime][]completion", "cylc[runtime][<namespace>]completion"], [52, 2, 1, "flow.cylc[runtime][]env-script", "cylc[runtime][<namespace>]env-script"], [52, 2, 1, "flow.cylc[runtime][]err-script", "cylc[runtime][<namespace>]err-script"], [52, 2, 1, "flow.cylc[runtime][]execution polling intervals", "cylc[runtime][<namespace>]execution polling intervals"], [52, 2, 1, "flow.cylc[runtime][]execution retry delays", "cylc[runtime][<namespace>]execution retry delays"], [52, 2, 1, "flow.cylc[runtime][]execution time limit", "cylc[runtime][<namespace>]execution time limit"], [52, 2, 1, "flow.cylc[runtime][]exit-script", "cylc[runtime][<namespace>]exit-script"], [52, 2, 1, "flow.cylc[runtime][]inherit", "cylc[runtime][<namespace>]inherit"], [52, 2, 1, "flow.cylc[runtime][]init-script", "cylc[runtime][<namespace>]init-script"], [52, 2, 1, "flow.cylc[runtime][]platform", "cylc[runtime][<namespace>]platform"], [52, 2, 1, "flow.cylc[runtime][]post-script", "cylc[runtime][<namespace>]post-script"], [52, 2, 1, "flow.cylc[runtime][]pre-script", "cylc[runtime][<namespace>]pre-script"], [52, 2, 1, "flow.cylc[runtime][]script", "cylc[runtime][<namespace>]script"], [52, 2, 1, "flow.cylc[runtime][]submission polling intervals", "cylc[runtime][<namespace>]submission polling intervals"], [52, 2, 1, "flow.cylc[runtime][]submission retry delays", "cylc[runtime][<namespace>]submission retry delays"], [52, 2, 1, "flow.cylc[runtime][]work sub-directory", "cylc[runtime][<namespace>]work sub-directory"], [52, 1, 1, "", "cylc[scheduler]"], [52, 2, 1, "", "cylc[scheduler]UTC mode"], [52, 1, 1, "", "cylc[scheduler][events]"], [52, 2, 1, "", "cylc[scheduler][events]abort handlers"], [52, 2, 1, "", "cylc[scheduler][events]abort on inactivity timeout"], [52, 2, 1, "", "cylc[scheduler][events]abort on stall timeout"], [52, 2, 1, "", "cylc[scheduler][events]abort on workflow timeout"], [52, 2, 1, "", "cylc[scheduler][events]expected task failures"], [52, 2, 1, "", "cylc[scheduler][events]handler events"], [52, 2, 1, "", "cylc[scheduler][events]handlers"], [52, 2, 1, "", "cylc[scheduler][events]inactivity timeout"], [52, 2, 1, "", "cylc[scheduler][events]inactivity timeout handlers"], [52, 2, 1, "", "cylc[scheduler][events]mail events"], [52, 2, 1, "", "cylc[scheduler][events]restart timeout"], [52, 2, 1, "", "cylc[scheduler][events]shutdown handlers"], [52, 2, 1, "", "cylc[scheduler][events]stall handlers"], [52, 2, 1, "", "cylc[scheduler][events]stall timeout"], [52, 2, 1, "", "cylc[scheduler][events]stall timeout handlers"], [52, 2, 1, "", "cylc[scheduler][events]startup handlers"], [52, 2, 1, "", "cylc[scheduler][events]workflow timeout"], [52, 2, 1, "", "cylc[scheduler][events]workflow timeout handlers"], [52, 1, 1, "", "cylc[scheduler][mail]"], [52, 2, 1, "", "cylc[scheduler][mail]footer"], [52, 2, 1, "", "cylc[scheduler][mail]from"], [52, 2, 1, "", "cylc[scheduler][mail]task event batch interval"], [52, 2, 1, "", "cylc[scheduler][mail]to"], [52, 1, 1, "", "cylc[scheduler][main loop]"], [52, 1, 1, "flow.cylc[scheduler][main loop][]", "cylc[scheduler][main loop][<plugin name>]"], [52, 2, 1, "flow.cylc[scheduler][main loop][]interval", "cylc[scheduler][main loop][<plugin name>]interval"], [52, 2, 1, "", "cylc[scheduler]allow implicit tasks"], [52, 2, 1, "", "cylc[scheduler]cycle point format"], [52, 2, 1, "", "cylc[scheduler]cycle point num expanded year digits"], [52, 2, 1, "", "cylc[scheduler]cycle point time zone"], [52, 2, 1, "", "cylc[scheduler]install"], [52, 1, 1, "", "cylc[scheduling]"], [52, 1, 1, "", "cylc[scheduling][graph]"], [52, 2, 1, "flow.cylc[scheduling][graph]", "cylc[scheduling][graph]<recurrence>"], [52, 1, 1, "", "cylc[scheduling][queues]"], [52, 1, 1, "flow.cylc[scheduling][queues][]", "cylc[scheduling][queues][<queue name>]"], [52, 2, 1, "flow.cylc[scheduling][queues][]limit", "cylc[scheduling][queues][<queue name>]limit"], [52, 2, 1, "flow.cylc[scheduling][queues][]members", "cylc[scheduling][queues][<queue name>]members"], [52, 1, 1, "", "cylc[scheduling][queues][default]"], [52, 2, 1, "", "cylc[scheduling][queues][default]limit"], [52, 1, 1, "", "cylc[scheduling][special tasks]"], [52, 2, 1, "", "cylc[scheduling][special tasks]clock-expire"], [52, 2, 1, "", "cylc[scheduling][special tasks]clock-trigger"], [52, 2, 1, "", "cylc[scheduling][special tasks]external-trigger"], [52, 2, 1, "", "cylc[scheduling][special tasks]sequential"], [52, 1, 1, "", "cylc[scheduling][xtriggers]"], [52, 2, 1, "flow.cylc[scheduling][xtriggers]", "cylc[scheduling][xtriggers]<xtrigger name>"], [52, 2, 1, "", "cylc[scheduling]cycling mode"], [52, 2, 1, "", "cylc[scheduling]final cycle point"], [52, 2, 1, "", "cylc[scheduling]final cycle point constraints"], [52, 2, 1, "", "cylc[scheduling]hold after cycle point"], [52, 2, 1, "", "cylc[scheduling]initial cycle point"], [52, 2, 1, "", "cylc[scheduling]initial cycle point constraints"], [52, 2, 1, "", "cylc[scheduling]runahead limit"], [52, 2, 1, "", "cylc[scheduling]sequential xtriggers"], [52, 2, 1, "", "cylc[scheduling]stop after cycle point"], [52, 1, 1, "", "cylc[task parameters]"], [52, 2, 1, "flow.cylc[task parameters]", "cylc[task parameters]<parameter>"], [52, 1, 1, "", "cylc[task parameters][templates]"], [52, 2, 1, "flow.cylc[task parameters][templates]", "cylc[task parameters][templates]<parameter>"]], "global": [[46, 0, 1, "", "cylc"], [46, 1, 1, "", "cylc[hub]"], [46, 2, 1, "", "cylc[hub]url"], [46, 1, 1, "", "cylc[install]"], [46, 1, 1, "", "cylc[install][symlink dirs]"], [46, 1, 1, "global.cylc[install][symlink dirs][]", "cylc[install][symlink dirs][<install target>]"], [46, 2, 1, "global.cylc[install][symlink dirs][]log", "cylc[install][symlink dirs][<install target>]log"], [46, 2, 1, "global.cylc[install][symlink dirs][]log/job", "cylc[install][symlink dirs][<install target>]log/job"], [46, 2, 1, "global.cylc[install][symlink dirs][]run", "cylc[install][symlink dirs][<install target>]run"], [46, 2, 1, "global.cylc[install][symlink dirs][]share", "cylc[install][symlink dirs][<install target>]share"], [46, 2, 1, "global.cylc[install][symlink dirs][]share/cycle", "cylc[install][symlink dirs][<install target>]share/cycle"], [46, 2, 1, "global.cylc[install][symlink dirs][]work", "cylc[install][symlink dirs][<install target>]work"], [46, 2, 1, "", "cylc[install]max depth"], [46, 2, 1, "", "cylc[install]source dirs"], [46, 1, 1, "", "cylc[platform groups]"], [46, 1, 1, "global.cylc[platform groups][]", "cylc[platform groups][<group>]"], [46, 1, 1, "global.cylc[platform groups][][meta]", "cylc[platform groups][<group>][meta]"], [46, 2, 1, "global.cylc[platform groups][][meta]", "cylc[platform groups][<group>][meta]<custom metadata>"], [46, 1, 1, "global.cylc[platform groups][][selection]", "cylc[platform groups][<group>][selection]"], [46, 2, 1, "global.cylc[platform groups][][selection]method", "cylc[platform groups][<group>][selection]method"], [46, 2, 1, "global.cylc[platform groups][]platforms", "cylc[platform groups][<group>]platforms"], [46, 1, 1, "", "cylc[platforms]"], [46, 1, 1, "global.cylc[platforms][]", "cylc[platforms][<platform name>]"], [46, 1, 1, "global.cylc[platforms][][directives]", "cylc[platforms][<platform name>][directives]"], [46, 2, 1, "global.cylc[platforms][][directives]", "cylc[platforms][<platform name>][directives]<directive>"], [46, 1, 1, "global.cylc[platforms][][meta]", "cylc[platforms][<platform name>][meta]"], [46, 2, 1, "global.cylc[platforms][][meta]", "cylc[platforms][<platform name>][meta]<custom metadata>"], [46, 1, 1, "global.cylc[platforms][][selection]", "cylc[platforms][<platform name>][selection]"], [46, 2, 1, "global.cylc[platforms][][selection]method", "cylc[platforms][<platform name>][selection]method"], [46, 2, 1, "global.cylc[platforms][]clean job submission environment", "cylc[platforms][<platform name>]clean job submission environment"], [46, 2, 1, "global.cylc[platforms][]communication method", "cylc[platforms][<platform name>]communication method"], [46, 2, 1, "global.cylc[platforms][]copyable environment variables", "cylc[platforms][<platform name>]copyable environment variables"], [46, 2, 1, "global.cylc[platforms][]cylc path", "cylc[platforms][<platform name>]cylc path"], [46, 2, 1, "global.cylc[platforms][]err tailer", "cylc[platforms][<platform name>]err tailer"], [46, 2, 1, "global.cylc[platforms][]err viewer", "cylc[platforms][<platform name>]err viewer"], [46, 2, 1, "global.cylc[platforms][]execution polling intervals", "cylc[platforms][<platform name>]execution polling intervals"], [46, 2, 1, "global.cylc[platforms][]execution time limit polling intervals", "cylc[platforms][<platform name>]execution time limit polling intervals"], [46, 2, 1, "global.cylc[platforms][]global init-script", "cylc[platforms][<platform name>]global init-script"], [46, 2, 1, "global.cylc[platforms][]hosts", "cylc[platforms][<platform name>]hosts"], [46, 2, 1, "global.cylc[platforms][]install target", "cylc[platforms][<platform name>]install target"], [46, 2, 1, "global.cylc[platforms][]job name length maximum", "cylc[platforms][<platform name>]job name length maximum"], [46, 2, 1, "global.cylc[platforms][]job runner", "cylc[platforms][<platform name>]job runner"], [46, 2, 1, "global.cylc[platforms][]job runner command template", "cylc[platforms][<platform name>]job runner command template"], [46, 2, 1, "global.cylc[platforms][]job submission environment pass-through", "cylc[platforms][<platform name>]job submission environment pass-through"], [46, 2, 1, "global.cylc[platforms][]job submission executable paths", "cylc[platforms][<platform name>]job submission executable paths"], [46, 2, 1, "global.cylc[platforms][]max batch submit size", "cylc[platforms][<platform name>]max batch submit size"], [46, 2, 1, "global.cylc[platforms][]out tailer", "cylc[platforms][<platform name>]out tailer"], [46, 2, 1, "global.cylc[platforms][]out viewer", "cylc[platforms][<platform name>]out viewer"], [46, 2, 1, "global.cylc[platforms][]retrieve job logs", "cylc[platforms][<platform name>]retrieve job logs"], [46, 2, 1, "global.cylc[platforms][]retrieve job logs command", "cylc[platforms][<platform name>]retrieve job logs command"], [46, 2, 1, "global.cylc[platforms][]retrieve job logs max size", "cylc[platforms][<platform name>]retrieve job logs max size"], [46, 2, 1, "global.cylc[platforms][]retrieve job logs retry delays", "cylc[platforms][<platform name>]retrieve job logs retry delays"], [46, 2, 1, "global.cylc[platforms][]rsync command", "cylc[platforms][<platform name>]rsync command"], [46, 2, 1, "global.cylc[platforms][]shell", "cylc[platforms][<platform name>]shell"], [46, 2, 1, "global.cylc[platforms][]ssh command", "cylc[platforms][<platform name>]ssh command"], [46, 2, 1, "global.cylc[platforms][]ssh forward environment variables", "cylc[platforms][<platform name>]ssh forward environment variables"], [46, 2, 1, "global.cylc[platforms][]submission polling intervals", "cylc[platforms][<platform name>]submission polling intervals"], [46, 2, 1, "global.cylc[platforms][]submission retry delays", "cylc[platforms][<platform name>]submission retry delays"], [46, 2, 1, "global.cylc[platforms][]tail command template", "cylc[platforms][<platform name>]tail command template"], [46, 2, 1, "global.cylc[platforms][]use login shell", "cylc[platforms][<platform name>]use login shell"], [46, 1, 1, "", "cylc[platforms][localhost]"], [46, 1, 1, "", "cylc[platforms][localhost][selection]"], [46, 2, 1, "", "cylc[platforms][localhost][selection]method"], [46, 2, 1, "", "cylc[platforms][localhost]hosts"], [46, 1, 1, "", "cylc[scheduler]"], [46, 2, 1, "", "cylc[scheduler]UTC mode"], [46, 1, 1, "", "cylc[scheduler][events]"], [46, 2, 1, "", "cylc[scheduler][events]abort handlers"], [46, 2, 1, "", "cylc[scheduler][events]abort on inactivity timeout"], [46, 2, 1, "", "cylc[scheduler][events]abort on stall timeout"], [46, 2, 1, "", "cylc[scheduler][events]abort on workflow timeout"], [46, 2, 1, "", "cylc[scheduler][events]handler events"], [46, 2, 1, "", "cylc[scheduler][events]handlers"], [46, 2, 1, "", "cylc[scheduler][events]inactivity timeout"], [46, 2, 1, "", "cylc[scheduler][events]inactivity timeout handlers"], [46, 2, 1, "", "cylc[scheduler][events]mail events"], [46, 2, 1, "", "cylc[scheduler][events]restart timeout"], [46, 2, 1, "", "cylc[scheduler][events]shutdown handlers"], [46, 2, 1, "", "cylc[scheduler][events]stall handlers"], [46, 2, 1, "", "cylc[scheduler][events]stall timeout"], [46, 2, 1, "", "cylc[scheduler][events]stall timeout handlers"], [46, 2, 1, "", "cylc[scheduler][events]startup handlers"], [46, 2, 1, "", "cylc[scheduler][events]workflow timeout"], [46, 2, 1, "", "cylc[scheduler][events]workflow timeout handlers"], [46, 1, 1, "", "cylc[scheduler][host self-identification]"], [46, 2, 1, "", "cylc[scheduler][host self-identification]host"], [46, 2, 1, "", "cylc[scheduler][host self-identification]method"], [46, 2, 1, "", "cylc[scheduler][host self-identification]target"], [46, 1, 1, "", "cylc[scheduler][logging]"], [46, 2, 1, "", "cylc[scheduler][logging]maximum size in bytes"], [46, 2, 1, "", "cylc[scheduler][logging]rolling archive length"], [46, 1, 1, "", "cylc[scheduler][mail]"], [46, 2, 1, "", "cylc[scheduler][mail]footer"], [46, 2, 1, "", "cylc[scheduler][mail]from"], [46, 2, 1, "", "cylc[scheduler][mail]smtp"], [46, 2, 1, "", "cylc[scheduler][mail]task event batch interval"], [46, 2, 1, "", "cylc[scheduler][mail]to"], [46, 1, 1, "", "cylc[scheduler][main loop]"], [46, 1, 1, "global.cylc[scheduler][main loop][]", "cylc[scheduler][main loop][<plugin name>]"], [46, 2, 1, "global.cylc[scheduler][main loop][]interval", "cylc[scheduler][main loop][<plugin name>]interval"], [46, 1, 1, "", "cylc[scheduler][main loop][auto restart]"], [46, 2, 1, "", "cylc[scheduler][main loop][auto restart]interval"], [46, 1, 1, "", "cylc[scheduler][main loop][health check]"], [46, 2, 1, "", "cylc[scheduler][main loop][health check]interval"], [46, 1, 1, "", "cylc[scheduler][main loop][reset bad hosts]"], [46, 2, 1, "", "cylc[scheduler][main loop][reset bad hosts]interval"], [46, 2, 1, "", "cylc[scheduler][main loop]plugins"], [46, 1, 1, "", "cylc[scheduler][run hosts]"], [46, 2, 1, "", "cylc[scheduler][run hosts]available"], [46, 2, 1, "", "cylc[scheduler][run hosts]condemned"], [46, 2, 1, "", "cylc[scheduler][run hosts]ports"], [46, 2, 1, "", "cylc[scheduler][run hosts]ranking"], [46, 2, 1, "", "cylc[scheduler]auto restart delay"], [46, 2, 1, "", "cylc[scheduler]process pool size"], [46, 2, 1, "", "cylc[scheduler]process pool timeout"], [46, 1, 1, "", "cylc[task events]"], [46, 2, 1, "", "cylc[task events]execution timeout"], [46, 2, 1, "", "cylc[task events]handler events"], [46, 2, 1, "", "cylc[task events]handler retry delays"], [46, 2, 1, "", "cylc[task events]handlers"], [46, 2, 1, "", "cylc[task events]mail events"], [46, 2, 1, "", "cylc[task events]submission timeout"]]}, "objnames": {"0": ["cylc", "conf", "Cylc conf"], "1": ["cylc", "section", "Cylc section"], "2": ["cylc", "setting", "Cylc setting"], "3": ["parsec", "type", "Parsec type"], "4": ["py", "module", "Python module"], "5": ["py", "exception", "Python exception"], "6": ["py", "attribute", "Python attribute"], "7": ["py", "method", "Python method"], "8": ["py", "function", "Python function"], "9": ["py", "class", "Python class"], "10": ["std", "envvar", "environment variable"]}, "objtypes": {"0": "cylc:conf", "1": "cylc:section", "2": "cylc:setting", "3": "parsec:type", "4": "py:module", "5": "py:exception", "6": "py:attribute", "7": "py:method", "8": "py:function", "9": "py:class", "10": "std:envvar"}, "terms": {"": [3, 5, 6, 11, 16, 18, 21, 23, 24, 28, 35, 36, 37, 40, 43, 44, 45, 46, 48, 50, 52, 53, 54, 57, 58, 63, 65, 68, 69, 71, 73, 74, 75, 76, 78, 80, 81, 88, 91, 92, 93, 101, 102, 103, 104, 107, 120, 121, 123, 124, 126, 129, 130, 131, 132, 133, 134, 135, 137, 138], "0": [4, 5, 7, 10, 13, 20, 21, 23, 24, 26, 27, 29, 35, 46, 50, 51, 52, 53, 56, 59, 68, 70, 73, 100, 102, 106, 108, 118, 123, 124, 126, 128, 129, 130, 131, 132], "00": [50, 52, 59, 73, 74, 76, 77, 84, 91, 103, 117, 118, 123, 125, 128, 132], "0000": 52, "00019850504t0600z": 52, "001": 132, "007": 124, "00t00": 84, "00z": [21, 50, 52, 73, 76, 105, 132], "01": [5, 21, 24, 40, 50, 52, 57, 59, 73, 74, 76, 77, 81, 103, 105, 121, 123, 126, 128, 129, 130, 132, 135, 137], "0100": 128, "0100400101t0000z": 52, "013": 128, "01t00": [21, 50, 52, 73, 76, 105, 123, 132, 135], "01t00z": [59, 77, 128, 132], "01t01": [105, 123], "01t03": 105, "01t12": 76, "01t12z": 77, "02": [46, 50, 123, 132], "02d": [59, 129], "03": [109, 123], "03d": [52, 129], "03t00z": 132, "04": [50, 103, 132], "05": [52, 132], "0500": 52, "05t00z": 132, "06": [13, 52, 63, 109, 132], "0645": 52, "06z": 52, "07": 132, "08": [52, 125, 128, 132], "0830": 50, "08t12": [125, 128], "08z": 73, "09": 129, "091": 132, "09z": 109, "0nd": 52, "1": [4, 5, 7, 10, 18, 21, 27, 28, 29, 32, 35, 39, 40, 46, 48, 50, 51, 52, 55, 56, 57, 59, 63, 65, 70, 71, 73, 78, 80, 83, 84, 85, 87, 101, 103, 104, 105, 106, 109, 115, 116, 120, 121, 122, 123, 126, 128, 129, 130, 131, 134, 135, 137, 138], "10": [23, 46, 50, 51, 63, 65, 74, 95, 104, 105, 107, 114, 118, 120, 121, 123, 126, 128, 129, 130, 132, 134], "100": [46, 51, 52, 126, 128, 137], "1000000": 46, "1000000000": 46, "10040": 52, "1012": 58, "10120101t0000z": 58, "10120101t0100z": 58, "10120101t0200z": 58, "10120101t0300z": 58, "1024m": 117, "1066": 128, "10661004t08": 128, "10661014t08": 128, "1068": 128, "108179": 123, "10th": 132, "11": [52, 77, 129, 134], "11000101t00": 4, "12": [13, 18, 46, 52, 68, 74, 76, 77, 121, 126, 128, 129, 132], "1225": 132, "123": [18, 128], "12345": 123, "127": [29, 50], "12t06": 52, "12t11": 109, "12t18": 52, "13": [17, 20, 46, 50, 52, 121, 128, 129], "130": 124, "1300": 52, "13t06": 132, "14": [26, 73, 128, 129, 132], "14t00": 132, "14t11": 103, "14t12": 132, "14t16": 132, "14t18": 132, "15": [23, 46, 65, 74, 121, 123, 126, 132], "155": 0, "15min": 46, "15t00": 132, "15t06": 132, "15th": 132, "15z": 132, "18": [52, 121, 126, 132], "1800": 128, "181": 132, "1970": 73, "1983": 123, "1985": 52, "19t03": 73, "19z": 109, "1e11": 50, "1g": 118, "1gb": 46, "1st": [21, 52, 76, 77, 132], "1t00": 132, "2": [1, 7, 9, 10, 12, 18, 21, 26, 28, 39, 46, 48, 50, 51, 52, 54, 55, 56, 57, 60, 63, 64, 65, 68, 70, 71, 74, 80, 101, 103, 104, 106, 121, 122, 123, 124, 125, 126, 128, 129, 130, 131, 132, 135, 137], "20": [125, 126, 128, 132], "2000": [3, 5, 21, 50, 52, 59, 76, 77, 88, 94, 123, 128, 132], "20000101": 132, "20000101t00": [76, 132], "20000101t0000": 76, "20000101t000000": 76, "20000101t0000z": [40, 73], "20000101t00z": [76, 81, 132], "20000101t06z": 132, "20000101t07": 132, "20000102": 132, "20000105t00z": 132, "2002": [88, 132], "2004": [88, 132], "2005": [126, 132], "2006": 132, "2008": 132, "2010": [126, 132], "20100101t03": 132, "20100101t06": 132, "20100101t12": 132, "20100808t00": 128, "20100808t06z": 132, "20100816t00": 128, "2011": [125, 126, 128], "20110511t1800z": [57, 130], "20120808t06z": 132, "20130808t00": 132, "20130808t18": 132, "20130812t00": 132, "2014": 132, "20140201t06": 132, "20140801t00": 132, "20141201t00": 132, "2015": 126, "20150125t00": 126, "20150126t00": 126, "2017": [52, 109, 132, 137], "20170103": 135, "20170104": 135, "20170105": 135, "20171009t0950": 74, "2018": [126, 135], "2019": [1, 2, 7, 12, 24, 52, 63], "2020": [24, 88, 96, 129, 132, 135], "20200101": 132, "20200202": 132, "2022": 105, "2023": 103, "20240101": 44, "2025": [132, 137], "2030": 88, "2038": 73, "2050": 132, "2052": 132, "2054": 132, "20t06": 132, "21": 126, "2100": 132, "21491012t0410z": 103, "219f5687": 26, "21t18": 132, "22": 62, "236": [46, 121], "23t00": 132, "23t02": 132, "24": [21, 117, 128], "25": [126, 130, 132, 137], "254": 93, "25t06": 132, "271": 132, "27t00z": 63, "28": [21, 121], "287": 128, "29t00": 50, "2g": 118, "3": [9, 10, 18, 20, 21, 23, 28, 36, 42, 46, 48, 50, 52, 54, 55, 56, 58, 64, 65, 68, 70, 74, 80, 101, 102, 104, 118, 121, 122, 123, 124, 126, 128, 129, 130, 131, 137], "30": [50, 52, 74, 76, 77, 118, 123, 128, 130, 132], "3000": 88, "3005": [68, 69, 70, 71, 74], "30t06": 132, "30th": 132, "30z": [105, 132], "31": 21, "3142": 52, "31t12": 132, "331": 0, "34": [18, 74, 128], "35": 103, "3528": 0, "356": 132, "36": [103, 121], "360": [52, 77, 132], "3600": 128, "360_dai": 52, "360dai": [52, 77], "365": [21, 52, 77, 132], "365_dai": 52, "365dai": 52, "365t12z": 132, "366": [21, 52, 77, 132], "366_dai": 52, "366dai": 52, "3772": [68, 69, 70, 71, 74], "3808": [68, 69, 70, 71, 74], "3917": [68, 69, 70, 71, 74], "4": [2, 4, 22, 44, 46, 52, 54, 55, 74, 85, 104, 124, 128, 129, 138], "40": 63, "42": [50, 128], "43001": 46, "43101": 46, "434": 0, "440": 39, "44b1": 26, "45": 132, "46": 123, "48": 68, "4th": 52, "5": [35, 44, 46, 50, 51, 52, 54, 60, 63, 65, 68, 71, 74, 80, 101, 104, 107, 118, 126, 128, 129, 130, 131, 132, 134, 135], "50": [107, 123], "500": 74, "500mb": 74, "5h": 52, "6": [4, 13, 50, 51, 52, 54, 65, 68, 74, 76, 88, 118, 126, 128, 129, 130, 132, 134], "60": [21, 68, 71, 115, 116, 118, 128], "600": 113, "61": 68, "660": 113, "6702": 20, "7": [0, 1, 2, 3, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 23, 24, 42, 44, 46, 50, 53, 54, 55, 60, 74, 78, 81, 88, 104, 121, 123, 129, 131, 132, 133, 134], "70": 46, "728": [5, 124], "79": 138, "8": [1, 4, 7, 8, 9, 10, 12, 13, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 36, 39, 42, 46, 50, 52, 53, 54, 55, 56, 78, 81, 88, 101, 102, 106, 107, 120, 123, 126, 129, 130, 131, 132, 133], "8601": [21, 52, 126, 128, 132], "86400": 128, "8eb8": 26, "9": [23, 39, 46, 52, 121, 123, 126, 128, 129, 132], "91": 132, "99": [124, 126, 128], "9999": 52, "A": [2, 3, 7, 12, 17, 18, 19, 20, 21, 24, 27, 28, 40, 42, 45, 46, 48, 49, 50, 52, 53, 54, 62, 65, 66, 68, 69, 72, 74, 76, 78, 81, 82, 83, 84, 85, 92, 93, 94, 95, 101, 102, 104, 106, 107, 108, 121, 122, 123, 124, 126, 128, 129, 130, 132, 133, 134, 135, 136, 137, 138], "AND": 132, "And": [10, 11, 22, 25, 26, 28, 42, 48, 62, 64, 65, 71, 72, 74, 80, 92, 95, 129, 135, 136, 137], "As": [0, 7, 13, 19, 44, 48, 52, 53, 60, 62, 69, 76, 93, 101, 120, 123, 125, 126, 129, 131, 132, 135, 138], "At": [0, 3, 5, 11, 20, 21, 24, 27, 44, 59, 67, 70, 71, 89, 101, 108, 130, 132, 133], "Be": [107, 126, 131], "But": [75, 77, 86, 87, 95, 101, 118, 132, 137], "By": [7, 20, 21, 44, 46, 48, 51, 52, 59, 62, 68, 73, 74, 76, 77, 80, 92, 93, 101, 106, 107, 121, 124, 126, 129, 130, 131, 132], "FOR": 137, "For": [3, 5, 7, 11, 13, 19, 20, 21, 23, 24, 27, 28, 29, 33, 34, 35, 37, 39, 40, 41, 42, 43, 44, 46, 48, 51, 52, 53, 55, 58, 59, 62, 64, 65, 68, 70, 71, 74, 76, 77, 78, 80, 81, 93, 94, 95, 96, 102, 103, 104, 105, 109, 118, 120, 121, 123, 125, 126, 127, 128, 129, 130, 131, 132, 134, 135, 136, 137, 138], "IFS": 58, "If": [2, 4, 7, 10, 11, 12, 13, 14, 20, 21, 24, 26, 28, 29, 31, 32, 33, 34, 37, 40, 41, 43, 44, 45, 46, 48, 51, 52, 53, 55, 60, 63, 65, 73, 74, 75, 77, 78, 80, 81, 84, 88, 93, 94, 96, 101, 102, 103, 104, 105, 107, 108, 109, 111, 112, 113, 114, 115, 116, 117, 118, 120, 121, 123, 124, 125, 126, 128, 129, 130, 131, 132, 133, 134, 135, 137, 138], "In": [3, 4, 7, 11, 16, 18, 19, 21, 29, 33, 40, 42, 43, 44, 45, 46, 48, 49, 52, 53, 59, 60, 62, 63, 64, 67, 68, 69, 70, 73, 74, 76, 77, 78, 80, 82, 90, 91, 93, 95, 96, 101, 104, 105, 106, 110, 120, 123, 127, 129, 130, 132, 133, 135, 137, 138], "Into": 68, "It": [3, 4, 5, 7, 12, 16, 19, 20, 21, 23, 36, 41, 43, 44, 45, 46, 48, 52, 58, 63, 67, 68, 70, 74, 75, 77, 78, 79, 82, 88, 92, 93, 96, 101, 104, 105, 107, 122, 123, 124, 125, 126, 128, 129, 130, 131, 132, 135, 137, 138], "NO": 134, "Near": 76, "No": [3, 37, 45, 48, 51, 101, 125, 128, 134, 138], "Not": [0, 9, 46, 52, 135], "OR": [37, 81, 102, 126, 132, 133], "Of": [2, 22, 46, 52, 62, 127], "On": [22, 44, 74, 94, 97, 113, 127, 128, 131, 134], "One": [39, 52, 92, 110, 123, 135], "Or": [1, 12, 21, 42, 51, 52, 88, 104, 121, 123, 132, 136, 138], "Such": [11, 60], "THE": 137, "That": [6, 21, 108], "The": [0, 1, 3, 4, 5, 7, 8, 11, 12, 13, 15, 16, 17, 19, 20, 21, 25, 27, 28, 29, 34, 35, 37, 39, 40, 41, 42, 43, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 60, 62, 63, 64, 65, 66, 67, 71, 72, 74, 75, 79, 80, 81, 84, 85, 86, 87, 89, 91, 92, 98, 99, 100, 101, 103, 105, 109, 110, 111, 113, 118, 120, 122, 123, 125, 126, 127, 129, 131, 133, 136, 138], "Their": 101, "Then": [11, 12, 23, 28, 60, 65, 70, 73, 86, 87, 123, 126, 129, 132, 135], "There": [0, 3, 5, 10, 11, 12, 13, 19, 20, 21, 23, 39, 44, 46, 48, 52, 63, 68, 70, 73, 74, 75, 76, 77, 78, 81, 93, 104, 121, 123, 126, 131, 132, 135], "These": [0, 5, 12, 13, 20, 21, 23, 36, 41, 46, 50, 52, 53, 57, 60, 62, 63, 73, 78, 89, 104, 106, 107, 113, 114, 115, 116, 117, 118, 120, 121, 123, 124, 126, 128, 129, 130, 131, 132, 135], "To": [1, 3, 6, 8, 21, 23, 24, 28, 29, 37, 46, 48, 51, 52, 53, 56, 59, 60, 62, 65, 68, 70, 71, 72, 73, 76, 80, 84, 86, 87, 92, 94, 96, 101, 102, 104, 120, 121, 122, 123, 124, 125, 126, 127, 128, 130, 133, 134, 136, 138], "Will": [48, 51], "With": [7, 24, 48, 52, 53, 56, 57, 76, 86, 87, 88, 92, 94, 101, 104, 130, 137], "_": [29, 30, 32, 34, 52, 93, 125, 126, 128, 138], "_0": 129, "_1": 129, "__call__": 40, "__file__": 27, "__init__": 37, "__many__": 124, "__name__": 126, "__python__": 128, "__set_file__": 128, "_all_": 126, "_buoi": 129, "_context__self": 128, "_cylc": [0, 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, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138], "_e": 129, "_end_": 109, "_eof_": 138, "_four": [125, 128], "_i": 129, "_i01": 129, "_i02": 129, "_i03": 129, "_i05": 129, "_i09": 129, "_i10": 129, "_i11": 129, "_i12": 129, "_i13": 129, "_idx": 129, "_idx1": 129, "_idx3": 129, "_idx5": 129, "_idx7": 129, "_idx9": 129, "_kwarg": 40, "_member": 138, "_one": [125, 128], "_p": [52, 129], "_pi": 129, "_plane": 129, "_r": 129, "_r01": 129, "_r02": 129, "_r03": 129, "_r10": 129, "_run1": 129, "_run2": 129, "_run3": 129, "_run4": 129, "_run5": 129, "_run_": 52, "_ship": 129, "_three": [125, 128], "_two": [125, 128], "a23": 135, "a380": 62, "a_": 128, "a_00": 128, "a_01": 128, "a_99": 128, "a_x1": 10, "a_x2": 10, "a_x3": 10, "abc": 18, "abil": [0, 23, 44, 58, 131, 135], "abl": [4, 5, 20, 28, 29, 44, 48, 76, 78, 80, 81, 85, 94, 105, 123, 135], "abnorm": 107, "abort": [29, 35, 46, 52, 100, 108, 110, 124, 128, 131, 135], "about": [10, 20, 21, 23, 26, 27, 39, 40, 44, 46, 48, 52, 65, 73, 75, 77, 81, 93, 94, 123, 124, 126, 130, 131, 132, 136], "abov": [7, 8, 28, 46, 48, 51, 52, 53, 55, 60, 62, 68, 71, 73, 76, 78, 80, 93, 95, 101, 120, 121, 126, 128, 129, 130, 132, 134, 135, 138], "absenc": [4, 132], "absolut": [46, 50, 93, 132], "abstract": [17, 20, 106, 110], "accept": [28, 40, 46, 52, 53, 93], "access": [14, 19, 43, 44, 46, 47, 51, 52, 53, 56, 68, 74, 103, 122, 123, 124, 125, 126, 127, 130, 135], "accident": 21, "accommod": [132, 137], "accomplish": 128, "accord": [21, 51, 52, 67, 76, 95, 104, 106, 121, 123, 129, 132, 135], "accordingli": 129, "account": [14, 19, 43, 46, 48, 118, 126, 131, 135], "account_no": 137, "accumul": [32, 121, 132, 137], "achiev": [21, 44, 67, 80, 126, 129, 130, 132], "ack": 41, "acknowledg": 41, "acquir": 39, "across": [15, 21, 44, 55, 67, 95, 98, 126, 128, 132, 136], "act": [64, 122, 129], "action": [0, 19, 20, 27, 41, 90, 91, 101, 122, 135], "activ": [15, 19, 21, 23, 24, 27, 35, 41, 44, 46, 51, 52, 64, 67, 81, 95, 101, 102, 104, 106, 107, 108, 110, 121, 124, 130, 131, 132, 133, 136], "actual": [20, 21, 52, 59, 73, 95, 96, 104, 121, 130, 132, 137], "ad": [3, 18, 29, 35, 36, 41, 44, 46, 50, 52, 53, 56, 63, 68, 73, 76, 78, 80, 94, 101, 104, 113, 121, 124, 126, 129, 130, 132, 137], "adapt": [6, 23, 63, 137], "add": [7, 27, 44, 46, 52, 53, 55, 58, 60, 62, 63, 64, 65, 68, 70, 71, 73, 74, 76, 78, 80, 94, 95, 103, 104, 121, 123, 126, 128, 129, 130, 131, 132, 137], "addit": [7, 25, 27, 37, 41, 44, 45, 46, 48, 49, 51, 52, 78, 93, 96, 104, 122, 123, 128, 130, 131, 132, 135, 137], "addition": [3, 4, 46, 48, 123, 132, 137], "address": [5, 46, 52, 60, 104, 123, 126, 130, 131, 135], "adher": 126, "adjac": 37, "adjust": [46, 86, 87], "admin": 5, "administr": [19, 42, 43, 46, 48, 122, 123, 131], "adopt": 21, "advanc": [21, 22, 28, 47, 77, 80, 95, 101, 106, 135, 136], "advantag": [20, 53, 135], "advers": [46, 132], "advic": [135, 136], "advis": [45, 48, 53, 55, 128], "affect": [20, 21, 46, 53, 101, 124, 130, 132, 134, 137, 138], "after": [5, 7, 10, 18, 20, 21, 24, 27, 28, 40, 41, 45, 46, 50, 52, 58, 59, 62, 63, 65, 70, 71, 73, 74, 76, 78, 80, 81, 84, 89, 93, 94, 99, 100, 106, 107, 120, 121, 123, 124, 126, 128, 130, 131, 132, 133, 134, 135, 137, 138], "afterward": 123, "again": [12, 21, 28, 34, 59, 65, 84, 85, 94, 99, 101, 104, 113, 126, 128, 130, 132, 137], "against": [1, 44, 81, 93, 123, 124, 126, 132, 135], "agent": 122, "agnost": 136, "ago": [74, 132], "agre": [135, 137], "agreement": 137, "ahead": [21, 52, 74, 80, 84, 94, 101, 132], "ahost": 52, "ai": 84, "aid": 126, "aim": 75, "air": [62, 128], "air_vehicl": 62, "airbu": 62, "aircraft": 62, "airplan": 62, "airport": 74, "aka": [28, 52, 138], "alarm": 130, "aldergrov": [70, 71, 74, 76], "alert": [52, 63], "algorithm": [2, 4, 9, 16, 52, 54, 130], "alia": [123, 128], "alias": 123, "alic": 128, "align": [132, 138], "aliv": [21, 108], "all": [1, 3, 4, 7, 8, 10, 11, 16, 20, 21, 23, 29, 34, 39, 40, 41, 44, 46, 48, 51, 52, 53, 54, 55, 60, 62, 63, 64, 68, 70, 73, 74, 75, 78, 79, 80, 81, 83, 84, 87, 92, 93, 96, 101, 104, 105, 106, 108, 120, 121, 123, 124, 126, 128, 129, 130, 131, 132, 134, 135, 137, 138], "allow": [3, 4, 8, 11, 13, 16, 18, 20, 21, 23, 24, 27, 32, 36, 43, 44, 46, 48, 51, 52, 53, 55, 60, 63, 65, 69, 70, 73, 74, 76, 78, 80, 81, 88, 94, 95, 99, 101, 103, 105, 107, 120, 121, 122, 123, 124, 125, 126, 128, 129, 130, 131, 132, 134, 135, 138], "almost": [7, 58, 126], "alon": [122, 126, 135], "along": [23, 73, 74, 126], "alongsid": [74, 126], "alphabet": [76, 129], "alphanumer": [52, 93, 130], "alreadi": [11, 21, 46, 52, 53, 59, 63, 69, 74, 78, 81, 93, 101, 102, 104, 126, 132, 135], "also": [3, 5, 8, 13, 14, 16, 19, 21, 23, 26, 28, 40, 41, 43, 44, 46, 50, 51, 52, 53, 60, 63, 70, 71, 73, 74, 75, 76, 77, 78, 80, 81, 88, 94, 96, 101, 103, 104, 107, 120, 121, 122, 123, 124, 125, 126, 128, 129, 130, 131, 132, 134, 135, 137, 138], "alt": [52, 124], "alt_cylc_run_dir": 126, "alter": [7, 35, 48, 52, 60, 93], "altern": [1, 4, 20, 37, 46, 51, 52, 55, 79, 93, 94, 104, 105, 120, 126, 128, 129, 130, 132, 135], "although": [21, 24, 54, 126], "altogeth": 96, "alwai": [12, 21, 28, 52, 58, 77, 78, 81, 104, 105, 123, 130, 132, 135, 137], "ambigu": [10, 29, 129, 132], "amend": 52, "among": [126, 128, 136], "amount": [33, 125, 126], "an": [0, 3, 4, 6, 8, 11, 13, 16, 20, 21, 26, 27, 28, 29, 33, 34, 37, 39, 40, 41, 42, 43, 44, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 58, 62, 63, 67, 70, 71, 74, 75, 76, 78, 80, 81, 83, 84, 85, 86, 87, 91, 93, 94, 95, 96, 101, 103, 104, 106, 107, 108, 109, 111, 112, 113, 118, 120, 121, 123, 124, 125, 126, 128, 129, 130, 131, 133, 134, 135, 136], "ana": [7, 13, 52, 104], "anaconda": 55, "analys": 132, "analysi": [52, 104], "anchor": [76, 132], "ancillari": 101, "and_m": 88, "anew": 46, "angl": [71, 129], "ani": [1, 4, 5, 7, 11, 12, 13, 15, 16, 19, 20, 21, 24, 26, 27, 29, 37, 39, 40, 41, 44, 46, 48, 50, 51, 52, 53, 57, 58, 59, 60, 62, 63, 64, 68, 70, 73, 74, 76, 80, 81, 86, 87, 88, 93, 94, 95, 96, 97, 101, 104, 105, 106, 109, 120, 121, 123, 124, 126, 128, 129, 130, 131, 132, 133, 134, 135, 137, 138], "anim": [45, 106], "announc": [58, 75], "annual": 76, "anoth": [7, 33, 45, 46, 48, 49, 53, 54, 60, 63, 76, 78, 80, 90, 91, 93, 94, 98, 101, 105, 107, 118, 120, 122, 123, 126, 129, 130, 131, 132, 133, 135, 138], "another_weather_task": 63, "answer": 128, "anticip": 37, "anyon": 44, "anyth": [7, 21, 23, 46, 52, 74, 120, 126, 132, 135], "anywai": [52, 135], "anywher": [28, 52, 101, 126, 128, 129, 130, 131, 138], "apart": [37, 48, 137], "api": [22, 40, 48, 56, 68, 74], "api_kei": [68, 69, 70, 71, 74], "api_vers": [38, 39], "apollo": 41, "app": [7, 19, 48, 51, 52, 94, 104, 136, 138], "app1": 135, "app2": 135, "appear": [7, 15, 21, 44, 46, 48, 52, 60, 63, 70, 99, 103, 106, 120, 123, 126, 128, 129, 130, 131, 132, 133, 137], "append": [28, 46, 123], "appl": 23, "appli": [7, 44, 48, 51, 52, 53, 59, 62, 65, 69, 81, 93, 94, 107, 123, 128, 129, 130, 131, 132], "applic": [19, 20, 23, 42, 52, 55, 67, 72, 73, 75, 78, 94, 95, 104, 126, 130, 135], "approach": [14, 23, 46, 72, 86, 87, 88, 94, 120, 132, 135], "appropri": [6, 11, 20, 37, 41, 46, 48, 50, 67, 95, 121, 123, 126, 128, 135, 137], "april": 132, "ar": [0, 1, 3, 4, 5, 7, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 27, 28, 29, 33, 35, 37, 39, 40, 41, 42, 43, 44, 45, 46, 48, 51, 52, 55, 57, 58, 59, 60, 63, 64, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 80, 81, 86, 87, 88, 90, 91, 93, 94, 95, 96, 97, 99, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 113, 114, 115, 116, 117, 118, 120, 121, 122, 124, 126, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138], "arbitrari": [3, 48, 76, 80, 93, 95, 126, 128, 132, 138], "arbitrarili": 126, "arch": 135, "architectur": [2, 22, 43, 46, 54, 56, 137], "archiv": [46, 68, 70, 129, 135, 137], "area": [52, 68, 121, 130], "aren": [123, 137, 138], "arg": [37, 40, 50, 126], "arg1": 52, "arg2": 52, "arguabl": 132, "argument": [18, 27, 28, 35, 37, 40, 44, 52, 69, 71, 78, 93, 121, 126, 128, 130], "aris": 37, "arithmet": 129, "around": [24, 52, 80, 81, 128], "arrai": 127, "arrang": [48, 126], "arriv": [40, 62, 86, 87, 126, 135], "arrow": [67, 78, 80, 132, 134, 138], "articl": 109, "artifici": [21, 95, 102, 105, 132], "ascend": 46, "asid": 126, "ask": [46, 53], "aspect": [63, 123, 131, 135], "assign": [11, 48, 52, 62, 124, 128, 130, 132, 135], "associ": [21, 33, 62, 63, 72, 73, 74, 95, 102, 121, 123, 126, 127, 130, 131, 132, 137], "assort": 20, "assum": [11, 28, 46, 60, 85, 104, 113, 132, 136, 137], "assumpt": 137, "async": [29, 30, 31, 32, 33, 34, 35, 39, 40], "async_request": 40, "asyncgener": 39, "asynchron": [35, 39, 40, 126], "asyncio": 40, "atd": 111, "atmo": 130, "atmospher": [67, 130], "atom": 124, "atq": 111, "atrun": 23, "attach": [21, 29, 40, 63, 132], "attempt": [11, 24, 29, 31, 37, 39, 46, 52, 53, 120, 123, 126, 130, 132, 135], "attent": 124, "attribut": [46, 126], "audit": 122, "auth": [40, 48], "authent": [7, 19, 40, 41, 42, 48, 51, 53, 74, 92, 100, 107, 124], "author": [19, 43, 44, 47, 51, 56], "authoris": 47, "authorizer_class": 48, "auto": [29, 35, 46, 52, 131], "auto_restart": 46, "autom": [3, 23, 52, 136], "automat": [1, 3, 4, 5, 7, 11, 14, 17, 20, 21, 23, 29, 44, 46, 48, 52, 57, 62, 63, 65, 67, 71, 73, 74, 81, 92, 95, 96, 99, 101, 103, 104, 106, 107, 108, 113, 120, 121, 122, 124, 126, 128, 129, 130, 131, 132, 135, 136, 137, 138], "avail": [11, 12, 19, 20, 23, 24, 27, 29, 35, 37, 40, 44, 46, 48, 52, 57, 60, 63, 86, 87, 93, 94, 106, 120, 122, 123, 124, 125, 126, 128, 130, 131, 132, 135, 137], "averag": [46, 106], "avoid": [5, 6, 21, 23, 44, 46, 48, 52, 64, 69, 70, 71, 86, 87, 88, 93, 95, 104, 105, 107, 110, 121, 123, 126, 129, 130, 131, 132, 137, 138], "awai": [44, 48, 51, 80, 88, 94, 106, 126, 137], "await": [0, 40], "awar": [23, 77, 107, 124, 137], "awkward": 88, "b": [10, 18, 21, 24, 27, 45, 50, 52, 57, 78, 80, 83, 84, 91, 118, 128, 130, 132, 133, 134, 135], "b_x1": 10, "b_x2": 10, "b_x3": 10, "back": [41, 44, 46, 48, 52, 60, 69, 73, 80, 94, 96, 104, 106, 107, 113, 120, 121, 123, 132, 135, 137], "background": [11, 20, 21, 23, 28, 29, 46, 52, 53, 74, 105, 120, 121, 122, 123, 130, 135], "backslash": [45, 138], "backtick": 124, "backup": 46, "backward": [4, 11, 20, 21, 52, 126, 133], "bad": [29, 34, 37, 46, 69, 101, 130, 132, 134, 135, 138], "bad_host": 34, "bail": [39, 40], "bake": 80, "bake_bread": [60, 78, 80], "bakeri": 80, "balanc": [46, 130], "bang": [125, 128], "bar": [5, 8, 16, 18, 21, 28, 29, 36, 39, 40, 45, 50, 52, 53, 63, 64, 68, 71, 73, 76, 77, 78, 80, 93, 104, 113, 123, 126, 128, 129, 130, 132, 133, 135, 138], "bare": 55, "barrier": [40, 95, 125, 137], "base": [3, 12, 15, 20, 21, 23, 37, 41, 42, 45, 46, 55, 60, 65, 73, 76, 105, 110, 121, 123, 132, 134, 135], "baseexcept": 40, "basenam": [57, 130], "bash": [4, 21, 46, 60, 63, 73, 81, 87, 113, 114, 115, 116, 117, 118, 120, 123, 124, 128, 131, 135], "bash_login": 46, "bash_profil": [46, 123], "bashrc": [46, 120, 123], "basi": [20, 21, 23, 41, 48], "basic": [0, 1, 21, 22, 63, 66, 76, 79, 83, 84, 88, 121, 125, 128, 130, 136], "batch": [5, 11, 20, 21, 28, 46, 52, 53, 80, 120, 121, 122, 123, 124, 130, 137], "batch_sys_job_id": [124, 130], "batch_sys_nam": [124, 130], "baz": [5, 8, 21, 28, 36, 45, 50, 52, 63, 64, 71, 73, 76, 78, 80, 93, 113, 126, 128, 132, 133, 135, 138], "bcd": 18, "bear": 59, "beb6": 26, "becam": 74, "becaus": [5, 10, 11, 15, 21, 24, 28, 34, 46, 52, 53, 58, 62, 65, 86, 87, 88, 94, 99, 101, 104, 105, 107, 120, 122, 123, 124, 126, 129, 130, 131, 132, 134, 135, 137, 138], "becom": [20, 52, 53, 63, 129, 131, 135, 137], "been": [0, 3, 4, 5, 7, 10, 13, 18, 20, 28, 34, 43, 44, 48, 51, 52, 53, 59, 62, 63, 69, 73, 74, 85, 93, 94, 101, 104, 106, 107, 113, 123, 124, 126], "beer": 21, "befor": [4, 7, 15, 16, 18, 21, 23, 24, 27, 29, 33, 39, 40, 44, 46, 52, 53, 59, 60, 63, 65, 73, 74, 76, 77, 80, 81, 88, 91, 95, 96, 99, 101, 102, 104, 106, 107, 120, 121, 123, 124, 126, 129, 130, 132, 135, 137], "begin": [3, 12, 21, 46, 93, 94, 96, 107, 118, 129, 132], "begun": 52, "behalf": [21, 43, 48], "behav": [4, 132, 135], "behaviour": [4, 10, 21, 24, 46, 52, 120, 121, 123, 129, 131, 132, 137], "behind": [21, 52, 84, 101, 106, 123, 130, 132, 137], "being": [0, 3, 7, 21, 36, 37, 52, 60, 63, 68, 94, 102, 104, 106, 120, 121, 126, 132, 134, 135, 138], "belfast": 76, "believ": 135, "bell": 59, "belong": [20, 21, 57, 59, 69, 80, 101, 130], "below": [4, 5, 6, 11, 21, 27, 46, 48, 52, 53, 57, 67, 78, 80, 93, 96, 101, 109, 120, 121, 126, 130, 132, 135, 137], "benefit": 137, "bespok": 63, "best": [52, 69, 75, 132, 136], "better": [58, 62, 106, 126, 128, 135], "between": [1, 13, 14, 15, 21, 29, 40, 41, 46, 51, 52, 54, 55, 58, 60, 62, 65, 67, 71, 73, 76, 78, 80, 81, 93, 94, 95, 97, 104, 106, 122, 123, 124, 125, 126, 129, 130, 131, 132, 134, 135, 137], "bewar": [76, 124], "beyond": [28, 46, 52, 60, 123, 132, 135], "bht130": 62, "bicycl": 62, "big": [74, 129, 130], "big_fam_1": 134, "big_fam_1_don": 134, "big_fam_2": 134, "big_job": 135, "big_jobs_queu": 135, "big_task": 74, "bigger": 137, "bigmachin": 46, "bigmachine01": 46, "bigmachine02": 46, "bigmachine1": 46, "bigmachine2": 46, "bin": [7, 26, 28, 33, 46, 52, 63, 73, 74, 86, 87, 93, 104, 113, 114, 115, 116, 117, 118, 120, 123, 124, 130, 131, 135], "bit": 91, "blam": 126, "blank": [37, 78, 123, 132, 134], "blob": 48, "block": [13, 48, 107, 120, 123, 124, 128, 130, 131, 137, 138], "blow": 74, "blue": [101, 106, 130], "bo": 58, "board": 62, "bob": 128, "boil": 21, "bol": 71, "bold": 123, "bong": 59, "bool": [21, 28, 37, 39, 51, 126], "boolean": [18, 28, 45, 46, 50, 52, 126, 128, 138], "bootstrap": 129, "both": [3, 4, 13, 16, 17, 20, 21, 23, 27, 40, 41, 46, 48, 52, 53, 60, 62, 63, 70, 76, 90, 91, 93, 101, 105, 109, 123, 129, 132, 133, 135, 137], "bottom": [46, 51, 62, 67, 74, 129], "bound": [37, 40, 129, 132], "boundari": [76, 91], "box": [20, 21, 23, 80, 135, 137], "brace": 128, "bracket": [45, 49, 71, 78, 129, 132], "branch": [4, 5, 9, 15, 20, 21, 94, 101, 105, 127, 133, 135, 137], "bread": 80, "break": [23, 45, 126, 132, 135, 137], "breakfast": 126, "breakpoint": 128, "breed": 85, "breviti": [21, 76], "brew": [21, 23, 102], "bridg": 55, "broad": 69, "broadcast": [4, 44, 48, 61, 66, 87, 92, 94, 100, 126], "broken": [132, 138], "broker": 126, "brown": [45, 126, 137, 138], "brows": 44, "browser": [19, 23, 41, 42, 43, 44, 46, 48, 74, 81, 94], "bsd": 46, "bsub": 114, "buffer": 52, "bug": [74, 132, 138], "build": [28, 51, 76, 80, 137], "built": [21, 28, 36, 46, 52, 59, 63, 73, 120, 121, 124, 127, 128, 129, 134, 135, 137], "bulk": [134, 136], "bundl": [51, 55, 63], "buoi": [129, 134], "busi": [21, 67, 95], "button": [44, 60, 73, 74, 81], "buy_ingredi": [78, 80], "bypass": [46, 48], "byte": [40, 46], "c": [1, 10, 18, 21, 23, 24, 42, 45, 48, 50, 51, 52, 57, 73, 78, 80, 83, 84, 124, 128, 130, 132, 134], "c3": [52, 130], "c_x1": 10, "c_x2": 10, "c_x3": 10, "cach": 121, "caffein": 95, "calcul": [33, 132], "calendar": [21, 52, 57, 79, 130, 132], "call": [0, 4, 16, 20, 21, 23, 24, 27, 28, 35, 36, 40, 41, 43, 46, 48, 52, 53, 55, 58, 59, 60, 62, 63, 64, 68, 69, 71, 73, 74, 76, 78, 80, 93, 101, 104, 120, 121, 123, 126, 128, 130, 132, 137], "callabl": [37, 40], "camborn": [70, 71, 74, 76], "can": [0, 3, 4, 7, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 23, 24, 27, 28, 33, 35, 36, 39, 40, 41, 42, 43, 44, 45, 46, 48, 50, 51, 52, 53, 55, 58, 59, 60, 62, 63, 64, 65, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 80, 81, 86, 87, 88, 90, 91, 93, 94, 95, 96, 97, 98, 99, 101, 102, 103, 104, 105, 106, 107, 109, 113, 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, 128, 129, 130, 131, 132, 133, 134, 135, 137, 138], "can_take_off_vert": 62, "can_task_off_vert": 62, "cancel": [41, 94], "cannot": [4, 6, 21, 29, 34, 44, 46, 48, 50, 52, 53, 93, 94, 99, 104, 108, 120, 121, 126, 130, 131, 132], "capabl": [1, 21, 41, 75, 101, 135, 136, 137], "capit": 45, "captur": [21, 82, 123], "care": [6, 48, 96, 107, 130, 138], "carefulli": 137, "caret": [76, 132], "carri": [21, 53, 74, 86, 87, 93, 101, 104, 132], "case": [3, 4, 11, 13, 16, 21, 37, 40, 44, 46, 48, 59, 62, 63, 68, 71, 73, 93, 95, 100, 104, 105, 107, 110, 120, 121, 123, 125, 126, 127, 128, 129, 130, 132, 134, 135, 137], "cash": 80, "cat": [21, 45, 46, 73, 91, 93, 120, 121, 123, 126, 128, 129, 138], "catalina": 23, "catch": [37, 52, 84, 95, 101, 124, 131, 132], "categori": [2, 134], "caught": [35, 37, 52, 59], "caus": [7, 13, 15, 21, 44, 46, 52, 53, 59, 74, 76, 80, 81, 87, 106, 108, 120, 123, 126, 132, 135, 138], "caution": [53, 135], "caveat": [2, 20, 21, 22, 46, 135], "ccyi": [52, 88], "ccyymm": 50, "ccyymmddthhmm": 52, "ccyymmddthhmmz": 52, "cd": [7, 23, 52, 58, 59, 60, 62, 63, 64, 65, 68, 73, 74, 76, 78, 80], "cell": 68, "central": [19, 23, 48, 94], "centralis": 70, "centuri": 132, "certain": [4, 21, 23, 33, 37, 44, 46, 52, 53, 58, 77, 93, 96, 104, 105, 124, 126, 130, 131], "certainli": 7, "certif": 41, "cfg": [35, 36, 37], "chain": [78, 92, 126, 128, 129, 132, 134], "chanc": [65, 126], "chang": [1, 2, 21, 22, 23, 24, 25, 26, 28, 46, 48, 51, 52, 56, 58, 59, 60, 62, 63, 65, 68, 70, 71, 73, 76, 80, 84, 86, 87, 88, 92, 93, 94, 100, 102, 105, 106, 120, 121, 123, 124, 126, 128, 130, 132, 134, 135, 137, 138], "change_word": 58, "changelog": 44, "channel": [41, 56], "chapter": 93, "char": 124, "charact": [45, 46, 48, 52, 70, 76, 78, 81, 93, 121, 123, 124, 128, 129, 136], "chat": [75, 123], "cheat": [2, 3, 22, 65, 92, 123], "check": [1, 4, 5, 7, 21, 28, 29, 30, 35, 44, 46, 48, 52, 54, 60, 63, 70, 73, 74, 81, 85, 93, 107, 121, 123, 124, 126, 130, 132, 134, 135, 137, 138], "check_converg": 85, "check_first_run": 129, "check_someth": 128, "checker": 120, "checkpoint": [3, 15, 104], "checkx": 129, "cheddar": 21, "chees": [21, 130], "cheesecak": 64, "cheesecake1": 64, "cheesecake2": 64, "chef": 64, "chicago": [125, 128], "child": [21, 101], "children": [101, 104, 120], "chill": 21, "chime": 59, "chmod": [23, 46, 63], "choic": [35, 52], "choos": [20, 23, 46, 48, 52, 101, 120, 138], "chosen": [44, 46, 51, 52, 63, 121, 130], "chunk": [129, 134], "cicada_": 123, "cicada_2": 123, "cicada_3": 123, "cicada_5": 123, "circl": [17, 130, 132], "citi": [125, 128], "cityjob": [125, 128], "clariti": [45, 128, 134, 135], "class": [28, 37, 40, 48, 51, 52, 93, 120, 126, 128, 130, 137], "classic": [23, 132], "classif": 37, "clean": [1, 3, 5, 7, 12, 20, 21, 35, 40, 46, 48, 80, 81, 92, 123, 125, 126, 128, 132, 134, 137], "clean_oven": [78, 80], "cleaner": 129, "cleanli": [20, 31, 32, 33, 104, 137], "cleanup": [125, 128, 138], "clear": [34, 46, 52, 98, 123, 132, 134, 135, 136, 138], "clearli": 138, "cli": [0, 27, 37, 42, 48, 51, 94, 124, 128], "click": [0, 73], "client": [21, 37, 38, 46, 55, 92, 100, 103, 104, 107, 126], "client_localhost": 97, "client_public_kei": 97, "clienterror": [37, 38, 40], "clienttimeout": [37, 38, 40], "clobber": 123, "clock": [21, 36, 52, 61, 66, 76, 79, 84, 95, 102, 106, 127, 130, 136, 137], "clock_0": 126, "clock_1": 126, "close": [60, 107, 134, 137], "close_shaft": 60, "closest": [52, 130], "cluster": [23, 122, 126], "clutter": [126, 134, 135], "cmd": [37, 40, 123], "cmp": 120, "coars": 136, "code": [13, 21, 28, 29, 35, 37, 46, 48, 52, 59, 62, 63, 65, 69, 71, 73, 74, 75, 76, 77, 80, 81, 103, 106, 120, 122, 123, 125, 126, 127, 128, 130, 132, 136], "coerc": 52, "cold": [6, 21, 52, 104], "collabor": [48, 136, 138], "collaps": [81, 130, 132, 134], "collat": 126, "collect": [11, 21, 54, 60, 69, 78], "collid": 101, "colon": [21, 76, 96], "color": [21, 126, 130], "colour": [17, 73, 106, 126], "column": [109, 132], "com": [0, 46, 48, 52], "combin": [4, 21, 39, 46, 48, 52, 78, 81, 121, 123, 126, 133], "combust": 62, "come": [19, 23, 55, 101, 106, 123, 126, 136], "comm": 37, "comma": [21, 37, 45, 46, 50, 52, 62, 65, 130], "command": [0, 1, 6, 7, 9, 14, 18, 19, 21, 23, 24, 27, 28, 37, 40, 41, 42, 43, 46, 48, 51, 52, 54, 57, 58, 60, 62, 63, 64, 65, 67, 68, 71, 72, 73, 74, 76, 78, 80, 81, 88, 92, 94, 95, 96, 97, 98, 103, 104, 106, 107, 109, 110, 111, 112, 113, 114, 116, 118, 120, 122, 123, 124, 126, 127, 128, 130, 132, 134, 135, 137], "commandfailederror": [37, 38], "commenc": [21, 53, 126], "comment": [8, 23, 45, 52, 68, 70, 78, 124, 125, 128, 132, 136], "commit": 26, "common": [3, 11, 19, 21, 28, 40, 44, 46, 53, 68, 81, 93, 94, 107, 123, 124, 126, 130, 131, 132, 134, 135, 137, 138], "commonli": [21, 68, 132], "commun": [28, 40, 41, 46, 52, 53, 54, 57, 58, 73, 75, 97, 98, 100, 104, 105, 120, 123, 126, 130], "compact": [45, 49, 78], "companion": 52, "compar": [11, 46, 125, 132], "comparison": [3, 53], "compat": [3, 9, 11, 16, 21, 24, 44, 55, 78, 126, 132, 133], "compel": 123, "compil": 28, "complet": [4, 6, 15, 16, 20, 21, 29, 37, 46, 52, 63, 68, 73, 77, 80, 83, 84, 88, 92, 95, 100, 101, 102, 104, 105, 109, 120, 121, 122, 129, 130, 131, 134, 135, 137], "complex": [4, 23, 33, 44, 75, 78, 80, 121, 122, 125, 128, 129, 130, 134, 136, 137, 138], "complianc": 136, "compliant": 46, "complic": [125, 132, 135, 137], "compon": [42, 46, 48, 55, 76, 110, 118, 135, 138], "compos": 132, "compound": [3, 92], "comprehens": [5, 73, 75, 125], "compress": 130, "compris": 21, "comput": [11, 21, 46, 52, 53, 67, 74, 105, 128, 129, 130, 132], "con": 135, "concaten": 120, "concept": [20, 75, 95], "concern": [52, 53, 60, 135], "concis": 132, "concret": [110, 129], "concurr": [15, 21, 46, 92, 95, 100, 132, 135], "conda": [20, 22, 56], "condemn": [29, 46, 131], "condens": 132, "condit": [3, 21, 27, 46, 52, 73, 85, 91, 106, 120, 125, 126, 131, 135], "conf": [4, 7, 24, 46, 52, 107, 128, 137, 138], "config": [1, 3, 5, 7, 8, 11, 14, 20, 27, 37, 39, 45, 46, 48, 49, 51, 52, 53, 54, 62, 68, 70, 71, 72, 73, 78, 81, 104, 121, 123, 124, 125, 126, 128, 129, 130, 131, 135, 136], "configur": [3, 4, 6, 7, 8, 9, 11, 14, 19, 20, 21, 22, 25, 28, 29, 33, 37, 41, 43, 44, 45, 54, 55, 56, 58, 60, 62, 63, 66, 68, 70, 71, 72, 73, 75, 78, 80, 81, 83, 84, 86, 87, 88, 92, 95, 96, 98, 100, 102, 105, 106, 107, 108, 120, 121, 125, 126, 127, 128, 129, 134, 136, 137, 138], "confirm": [52, 59, 62, 121, 132], "conflict": [7, 23, 52], "confus": [21, 52, 71, 76, 93, 138], "connect": [14, 21, 28, 37, 40, 41, 43, 46, 48, 53, 80, 107, 122, 123, 126, 129, 131, 132, 135, 137], "consequ": [3, 8, 80, 106, 130, 132], "consid": [4, 11, 36, 46, 52, 53, 55, 76, 101, 104, 107, 122, 124, 126, 129, 132, 134, 135, 137], "consider": 135, "consist": [4, 24, 30, 46, 48, 54, 55, 67, 68, 95, 101, 123, 124, 130, 132, 135, 138], "consol": 128, "consolid": [21, 66, 68, 70, 71, 72, 73, 76, 128], "consolidate_observ": [68, 69, 70, 71, 76], "consortium": [67, 136], "constitu": [101, 135], "constrain": [21, 52, 76, 84, 95, 132], "constraint": [21, 52, 76, 108, 124, 126, 132], "construct": [31, 39, 121, 128, 129, 132, 134, 135], "consult": [108, 136], "consum": [104, 135], "contact": [11, 21, 30, 34, 37, 39, 40, 107, 121, 123, 124], "contact_info": [38, 39], "contactfileexist": [37, 38], "contain": [11, 16, 18, 21, 24, 27, 28, 35, 37, 39, 40, 41, 44, 45, 46, 50, 51, 52, 55, 60, 63, 68, 71, 73, 74, 75, 78, 86, 87, 93, 97, 103, 104, 106, 108, 109, 120, 121, 123, 124, 126, 128, 129, 130, 132, 136, 137], "containeris": 123, "content": [28, 40, 52, 69, 120, 121, 123, 135, 136], "context": [37, 40, 52, 127, 132, 136, 138], "context_lin": 37, "contextu": 131, "contigu": [46, 101], "continu": [4, 9, 20, 21, 22, 24, 44, 45, 52, 54, 65, 70, 71, 81, 88, 94, 101, 102, 108, 120, 123, 127, 131, 132, 136], "contrast": 96, "control": [1, 7, 12, 19, 20, 24, 26, 41, 43, 44, 48, 51, 52, 55, 67, 73, 81, 93, 94, 106, 120, 121, 123, 125, 135, 137], "conv": 126, "conveni": [6, 40, 46, 48, 51, 81, 104, 126, 128, 129, 130, 132, 137], "convent": [21, 62, 68, 76, 135, 136], "converg": [89, 92], "convers": 128, "convert": [13, 52, 126, 132, 135, 138], "coordin": 40, "copi": [3, 6, 7, 23, 24, 26, 46, 53, 54, 58, 68, 70, 73, 74, 80, 81, 93, 104, 109, 121, 124, 135, 137], "copyabl": [46, 53], "core": [19, 20, 23, 25, 42, 46, 137], "coreutil": 23, "corner": 73, "cornwal": 76, "coroutin": [29, 30, 31, 32, 33, 34], "correct": [11, 14, 15, 23, 37, 48, 52, 74, 78, 104, 120, 124, 132, 135], "correctli": [20, 23, 59, 63, 68, 99, 104, 105, 109, 121, 123, 132, 134], "correspond": [52, 70, 74, 76, 132, 137], "corrupt": [101, 104], "cost": 135, "costli": 15, "could": [4, 6, 7, 18, 21, 24, 27, 37, 46, 48, 52, 53, 54, 58, 62, 63, 68, 69, 70, 71, 73, 74, 76, 80, 86, 87, 101, 102, 107, 110, 120, 122, 123, 126, 128, 130, 131, 132, 135], "count": [21, 31, 37, 46, 52, 80, 83, 126, 131, 132], "countdown": 74, "counter": 63, "coupl": 62, "cours": [67, 126, 137], "cover": [37, 46, 60, 69, 72, 73, 75, 78, 81, 89, 91, 94, 110, 129, 131, 135], "coveral": 40, "cprofil": 51, "cpu": [46, 74, 132, 137], "cpu_count": 46, "cpu_perc": 46, "crash": [41, 123], "cream": 45, "creat": [7, 20, 21, 23, 46, 52, 53, 58, 59, 60, 62, 64, 65, 68, 71, 73, 74, 75, 76, 77, 78, 79, 80, 93, 95, 96, 97, 100, 123, 124, 128, 130, 134, 135], "creation": [126, 132, 135], "credenti": [48, 107], "criterion": 131, "critic": [21, 52, 103, 120, 123, 124, 130], "cross": [62, 126, 132], "cshrc": 46, "csv": [68, 74], "ctx": 37, "cujo": 45, "curl": 52, "curli": 128, "current": [4, 8, 11, 21, 28, 39, 44, 46, 48, 50, 52, 59, 63, 73, 74, 76, 81, 91, 93, 101, 104, 106, 124, 127, 128, 129, 130, 135], "curvezmq": [41, 97], "custom": [4, 7, 13, 21, 22, 25, 44, 46, 52, 59, 63, 64, 77, 96, 103, 105, 121, 124, 127, 129, 130, 134, 135, 137], "customis": 131, "cut": [44, 55, 123], "cwd": [117, 121], "cycl": [0, 3, 4, 5, 6, 8, 15, 20, 21, 22, 23, 24, 37, 40, 46, 50, 52, 53, 54, 57, 58, 59, 63, 66, 68, 71, 73, 74, 77, 78, 79, 81, 85, 86, 89, 91, 92, 94, 96, 98, 100, 101, 103, 105, 106, 109, 121, 123, 124, 125, 126, 127, 128, 130, 136, 137], "cycle1": 81, "cycle2": 81, "cycle_interv": 128, "cycle_point": [50, 126], "cycle_subinterv": 128, "cyclepoint": [59, 129, 130, 132, 135], "cyclertypeerror": [37, 38], "cyclingerror": [37, 38], "cylc": [1, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 25, 27, 28, 35, 36, 37, 39, 40, 41, 46, 47, 49, 51, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 70, 72, 74, 75, 76, 77, 79, 80, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 94, 96, 97, 99, 100, 101, 102, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138], "cylc_": 120, "cylc__job__inst__user_env": 126, "cylc__job_abort": 120, "cylc_conf_path": 46, "cylc_cycling_mod": [57, 130], "cylc_debug": [57, 130], "cylc_ext_trigger_id": [87, 126], "cylc_fail_sign": 130, "cylc_home_root": 23, "cylc_home_root_alt": 23, "cylc_job_exit": 123, "cylc_job_exit_tim": 123, "cylc_job_id": 123, "cylc_job_init_tim": 123, "cylc_job_pid": 123, "cylc_job_runner_nam": 123, "cylc_job_runner_submit_tim": 123, "cylc_pythonpath": [36, 44, 126, 131], "cylc_run_dir": [24, 53, 126], "cylc_site_conf_path": [46, 51], "cylc_suite_def_path": 124, "cylc_suite_def_path_on_suite_host": 124, "cylc_suite_final_cycle_point": 124, "cylc_suite_final_cycle_tim": 124, "cylc_suite_host": 124, "cylc_suite_initial_cycle_point": 124, "cylc_suite_initial_cycle_tim": 124, "cylc_suite_log_dir": 124, "cylc_suite_nam": [4, 124], "cylc_suite_own": 124, "cylc_suite_run_dir": 124, "cylc_suite_share_dir": 124, "cylc_suite_share_path": 124, "cylc_suite_uuid": 124, "cylc_suite_work_dir": 124, "cylc_symlink": 24, "cylc_task_comms_method": [57, 130], "cylc_task_cycle_point": [1, 52, 57, 58, 68, 74, 83, 84, 85, 87, 91, 120, 126, 129, 130, 135], "cylc_task_flow_numb": [21, 57, 130], "cylc_task_id": [57, 120, 130], "cylc_task_job": [57, 63, 120, 130, 132], "cylc_task_log_dir": [57, 130], "cylc_task_log_root": [57, 68, 130], "cylc_task_message_started_pid": 130, "cylc_task_nam": [57, 83, 84, 120, 130], "cylc_task_namespace_hierarchi": [57, 130], "cylc_task_param_": [52, 71], "cylc_task_param_chunk": 129, "cylc_task_param_ob": 129, "cylc_task_param_p": 134, "cylc_task_param_run": 129, "cylc_task_param_sit": 71, "cylc_task_param_world": 71, "cylc_task_ssh_login_shel": [57, 130], "cylc_task_submit_numb": [21, 52, 57, 130], "cylc_task_try_numb": [21, 52, 57, 65, 130, 135], "cylc_task_work_dir": [21, 52, 57, 74, 130], "cylc_task_work_dir_bas": 130, "cylc_template_var": 128, "cylc_utc": [57, 130], "cylc_vacation_sign": 130, "cylc_verbos": [57, 130], "cylc_vers": [4, 7, 24, 38, 39, 57, 124, 128, 130], "cylc_workflow_final_cycle_point": [57, 124, 130], "cylc_workflow_final_cycle_tim": 124, "cylc_workflow_host": [39, 46, 57, 124, 130], "cylc_workflow_id": [4, 21, 52, 57, 58, 63, 87, 120, 124, 126, 128, 130, 132], "cylc_workflow_initial_cycle_point": [57, 124, 130], "cylc_workflow_initial_cycle_tim": 124, "cylc_workflow_log_dir": [124, 128], "cylc_workflow_nam": [21, 57, 128, 130], "cylc_workflow_name_bas": [57, 130], "cylc_workflow_own": [57, 124, 130], "cylc_workflow_run_dir": [21, 57, 68, 74, 87, 124, 128, 130], "cylc_workflow_share_dir": [21, 57, 58, 91, 124, 126, 128, 130, 135], "cylc_workflow_share_path": 124, "cylc_workflow_uuid": [57, 124, 130], "cylc_workflow_work_dir": [57, 68, 124, 126, 128, 130], "cylcauthor": 48, "cylcconfigerror": [37, 38], "cylcerror": [35, 37, 38], "cylcignor": [7, 93], "cylcmissingcontextpointerror": [37, 38], "cylcmissingfinalcyclepointerror": [37, 38], "cylctimesyntaxerror": [37, 38], "cylcuiserv": [47, 48, 51], "cylcversionerror": [37, 38], "d": [11, 21, 50, 52, 53, 76, 78, 80, 83, 84, 122, 128, 129, 132], "daemon": [20, 21, 111, 126], "dai": [21, 50, 52, 59, 76, 77, 86, 87, 88, 128, 132], "daili": [21, 52, 77, 126, 132], "daisi": 130, "danger": 130, "dark": 130, "dashboard": 42, "data": [12, 13, 17, 21, 27, 31, 37, 39, 40, 42, 43, 47, 52, 53, 56, 63, 68, 70, 73, 74, 77, 85, 91, 93, 95, 97, 101, 120, 124, 126, 128, 130, 132, 135], "data_dir": 135, "data_fil": 126, "data_id": 126, "data_in_dir": 126, "databas": [3, 12, 21, 39, 41, 43, 44, 54, 73, 92, 96, 100, 103, 104, 105, 123, 126, 130, 131, 132, 137], "datadir": 135, "datapoint": [68, 70, 74], "dataset": [95, 101, 126, 129, 132], "date": [1, 21, 50, 58, 74, 76, 88, 96, 124, 126, 128, 129, 130, 135], "datetim": [21, 52, 54, 57, 59, 66, 77, 79, 80, 89, 92, 104, 124, 126, 128, 129, 130], "daylight": [21, 76], "db": [12, 73, 109, 126], "ddthh": 52, "deal": 16, "debug": [13, 21, 31, 32, 33, 46, 57, 92, 103, 126, 127, 130], "debugg": 128, "dec": 132, "decid": [102, 126, 135, 137], "decim": 50, "declar": [52, 126, 130, 132], "decor": [35, 40], "decreas": 33, "decrypt": 97, "dedent": 138, "dedic": [46, 97, 107, 130], "deep": [5, 46, 128], "def": [27, 35, 36, 73, 126], "default": [4, 7, 18, 20, 21, 23, 24, 28, 32, 35, 39, 40, 41, 44, 46, 48, 51, 52, 53, 55, 71, 73, 74, 76, 77, 80, 81, 94, 101, 104, 105, 106, 107, 120, 123, 124, 126, 127, 129, 130, 131, 132, 134, 135, 137], "default_timeout": 40, "defend": 123, "defin": [4, 5, 7, 11, 20, 21, 24, 28, 29, 37, 40, 41, 45, 46, 48, 51, 52, 53, 54, 57, 59, 62, 63, 65, 68, 69, 70, 71, 73, 74, 78, 80, 81, 104, 120, 121, 124, 126, 127, 128, 129, 131, 132, 134, 135, 137], "definit": [4, 5, 8, 11, 18, 21, 24, 46, 52, 53, 54, 65, 70, 72, 75, 94, 95, 124, 126, 128, 129, 130, 132, 134, 135, 137, 138], "degre": [68, 74], "delai": [21, 29, 46, 52, 57, 65, 74, 84, 95, 101, 102, 105, 107, 120, 121, 124, 129, 130, 135], "deleg": 48, "delet": [3, 7, 20, 21, 37, 52, 58, 81, 93, 96, 104, 109, 124, 135, 137], "delimit": 96, "deliv": [21, 133], "deliveri": 126, "delta": [40, 41], "deltas_map": 40, "demand": [3, 4, 8, 121], "demo": [20, 63, 126], "demonstr": [63, 93, 132], "demot": 134, "denot": [21, 37, 48, 129, 132], "depart": 62, "depend": [3, 4, 5, 8, 10, 15, 20, 21, 23, 28, 45, 52, 54, 55, 59, 60, 63, 64, 65, 67, 73, 77, 79, 83, 84, 95, 104, 106, 107, 120, 121, 124, 125, 126, 128, 129, 130, 132, 134, 135, 137, 138], "deploi": [19, 48, 123, 137], "deploy": [19, 94], "deprec": [3, 4, 11, 20, 21, 24, 46, 52, 54, 78, 93, 107, 121, 123, 124, 126, 130, 131, 132, 135], "depth": [42, 46, 130], "deriv": [37, 43, 52, 135], "descend": [39, 52, 106], "describ": [8, 21, 52, 60, 69, 120, 124, 126, 129, 132, 134, 137, 138], "descript": [2, 21, 22, 24, 37, 52, 53, 62, 73, 76, 82, 83, 84, 85, 88, 91, 106, 124, 125, 126, 128, 130, 132, 136], "descriptor": 77, "design": [6, 7, 20, 21, 22, 42, 52, 53, 54, 63, 70, 75, 123, 124, 128, 134, 135, 137, 138], "desir": [12, 13, 29, 43, 60, 88, 94, 125, 129, 130, 134], "desktop": [42, 46, 53, 130], "desktop0000": 46, "desktop123": 53, "desktop9999": 46, "desktopnnn": 53, "despit": [21, 102], "dessert": 64, "dessert_chef_queu": 64, "destin": [24, 27, 124, 128, 130], "destroi": 134, "detach": [29, 110, 126], "detail": [1, 2, 4, 7, 11, 19, 21, 22, 23, 37, 41, 43, 44, 46, 48, 52, 53, 55, 63, 69, 73, 75, 76, 93, 98, 106, 109, 110, 123, 125, 126, 128, 130, 132, 134, 135, 136, 137], "detect": [4, 21, 28, 46, 51, 52, 96, 120, 124, 126, 132, 135], "detect_old_contact_fil": 122, "determin": [19, 21, 37, 40, 41, 44, 46, 48, 51, 52, 53, 93, 96, 101, 120, 121, 124, 126, 129, 130, 132, 135, 137], "determinist": 138, "develop": [7, 21, 22, 23, 31, 32, 33, 42, 51, 52, 56, 67, 73, 76, 81, 94, 123, 126, 128, 135, 136, 138], "di": 21, "diagnos": [20, 81, 132, 135], "diagnosi": [15, 135], "diagnost": [123, 135], "diagram": [78, 80, 101, 109], "diamond": 60, "dice": [52, 65], "dict": [27, 28, 37, 39, 40, 51, 126], "dictat": 8, "dictionari": [18, 27, 28, 37, 39, 40, 51, 70, 125, 126, 128], "did": [3, 16, 21, 37, 44, 132, 135], "didn": 75, "die_1": 65, "die_2": 65, "diff": [3, 26, 138], "differ": [2, 4, 6, 14, 16, 20, 21, 23, 28, 29, 33, 40, 41, 43, 44, 46, 48, 51, 52, 53, 59, 62, 63, 65, 68, 69, 70, 73, 76, 77, 80, 81, 93, 94, 101, 123, 125, 126, 129, 130, 131, 132, 134, 135, 137], "different_weather_task": 63, "difficult": [105, 123, 126, 135, 137, 138], "digit": [52, 74], "dimens": 68, "dimension": [86, 87], "dir": [7, 21, 24, 26, 28, 36, 39, 46, 51, 52, 53, 93, 96, 104, 124, 126, 130], "dir1": [52, 93, 104], "dir2": [52, 93, 104], "dir3": 93, "direct": [0, 21, 28, 45, 46, 48, 52, 53, 74, 94, 105, 107, 113, 114, 115, 116, 117, 118, 119, 122, 124, 125, 128, 129, 130, 135, 137], "directive_prefix": 28, "directli": [1, 3, 21, 44, 53, 93, 96, 104, 108, 110, 126, 135], "directori": [1, 3, 4, 6, 7, 12, 13, 20, 21, 23, 24, 26, 27, 30, 31, 32, 33, 37, 39, 46, 47, 51, 52, 57, 58, 59, 62, 63, 68, 69, 74, 76, 78, 80, 81, 92, 94, 97, 103, 104, 120, 125, 126, 127, 128, 131, 132, 137, 138], "dirti": 26, "disabl": [23, 52, 73, 107, 124, 130], "disadvantag": 129, "disambigu": 128, "discern": 54, "discourag": 12, "discours": [3, 75, 123], "discret": 126, "discuss": [60, 136, 137], "dish": 64, "disk": [20, 46, 53, 93, 104], "disk_usag": 46, "dispatch": 40, "displai": [19, 21, 23, 42, 44, 52, 78, 80, 81, 106, 121, 123, 132, 138], "distinct": [11, 21, 76, 135], "distinguish": [15, 21, 54, 93, 99, 118, 126, 128, 132, 138], "distribut": [19, 22, 23, 123, 126, 137], "ditto": 132, "divid": [52, 105, 138], "divorc": 130, "dn": [123, 126], "do": [0, 1, 4, 12, 13, 21, 23, 24, 29, 37, 41, 46, 48, 52, 53, 55, 59, 60, 62, 63, 65, 67, 68, 73, 74, 76, 80, 85, 93, 94, 95, 101, 104, 107, 113, 114, 115, 116, 117, 118, 120, 121, 124, 126, 128, 129, 130, 131, 132, 135, 137, 138], "do_someth": 105, "doc": [28, 60], "document": [0, 3, 7, 24, 28, 40, 41, 42, 48, 51, 52, 55, 70, 94, 95, 124, 125, 126, 128, 130, 131, 132, 133, 135, 136, 137, 138], "doe": [20, 21, 23, 26, 27, 28, 41, 46, 48, 50, 52, 53, 58, 60, 63, 69, 71, 73, 78, 93, 95, 101, 104, 105, 111, 118, 120, 122, 123, 124, 126, 129, 130, 132, 133, 135], "doesn": [11, 41, 46, 75, 76, 78, 80, 95, 120, 123, 129, 132, 133, 134], "dog": [45, 93, 126, 128, 129, 138], "dollar": 132, "dolphin": 128, "domain": [68, 123, 137, 138], "don": [6, 21, 28, 52, 53, 73, 78, 86, 87, 93, 94, 101, 104, 120, 123, 124, 126, 131, 132, 134, 135, 138], "done": [15, 21, 41, 48, 52, 63, 76, 81, 88, 94, 95, 104, 105, 120, 122, 126, 129, 130, 131, 132, 134, 135], "dopei": 60, "dot": 21, "doubl": [65, 129, 134], "down": [21, 30, 31, 32, 33, 45, 46, 52, 55, 60, 62, 74, 81, 88, 94, 101, 104, 108, 121, 122, 130, 131, 132], "downstream": [15, 21, 44, 90, 91, 94, 101, 102, 108, 126, 130, 132, 133], "downtim": 95, "draw": [62, 80, 135, 138], "drawn": [78, 136], "drink_coffe": 95, "drive": [93, 135], "driven": [16, 21, 86, 89, 92, 126, 132], "drop": 23, "dst": [59, 60, 65], "dt": 128, "due": [11, 21, 33, 37, 44, 46, 48, 52, 65, 74, 94, 120, 123, 131, 132], "dumb": 39, "dummi": [7, 21, 52, 76, 95, 105, 123, 130, 132], "dump": [31, 33, 52, 138], "duplic": [41, 45, 52, 60, 69, 70, 79, 104, 130, 132, 134, 135, 137], "durat": [13, 21, 50, 52, 54, 59, 74, 104, 107, 126, 128, 129, 130, 132], "duration_a": 128, "dure": [4, 16, 21, 37, 52, 53, 63, 96, 97, 104, 122, 123, 124, 128, 129, 135, 137], "dusti": 45, "dynam": [70, 130], "e": [0, 3, 4, 7, 10, 11, 13, 14, 16, 18, 20, 21, 23, 24, 28, 29, 33, 35, 37, 39, 40, 43, 44, 46, 48, 50, 51, 52, 53, 55, 57, 58, 59, 60, 64, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 80, 81, 84, 86, 87, 88, 91, 93, 94, 96, 101, 103, 104, 106, 118, 120, 121, 122, 123, 124, 126, 128, 129, 130, 131, 132, 133, 134, 135, 137, 138], "e5dc6573dd70cabd8f973d1535c17c29c026d553": 26, "e8220fa964d3": 26, "each": [7, 8, 11, 20, 21, 23, 24, 28, 31, 36, 40, 43, 44, 45, 46, 48, 49, 51, 52, 53, 54, 62, 63, 65, 67, 68, 69, 71, 73, 74, 76, 77, 78, 80, 83, 84, 93, 95, 101, 103, 104, 107, 109, 123, 124, 126, 129, 130, 131, 132, 134, 135, 137, 138], "earli": [54, 131], "earlier": [21, 24, 52, 80, 84, 101, 104, 120, 129, 132, 133, 135, 136, 137], "earliest": [52, 77], "earth": [71, 86, 87, 91, 124], "eas": [24, 135], "easi": [54, 95, 105, 126, 128, 134, 135], "easier": [18, 68, 81, 93, 106, 122, 123, 125, 128, 129, 135, 138], "easili": [73, 88, 125, 130, 135, 137, 138], "echo": [4, 28, 52, 58, 59, 60, 62, 63, 65, 68, 71, 73, 74, 82, 83, 84, 87, 91, 123, 130, 131, 134, 135, 138], "echo_1": 126, "economi": 134, "ecosystem": 125, "edg": [21, 44, 106, 133, 134], "edinburgh": 71, "edit": [0, 3, 21, 51, 59, 75, 78, 81, 88, 92, 120, 135, 138], "editor": [3, 68, 73, 124, 138], "eeyor": 11, "effect": [8, 35, 48, 51, 52, 53, 58, 59, 80, 101, 104, 105, 126, 132, 135, 137], "effici": [7, 15, 20, 22, 46, 54, 80, 95, 107, 126, 129, 135, 136], "effort": 130, "egg": 126, "eight": 138, "either": [3, 4, 12, 21, 35, 37, 43, 44, 52, 53, 60, 64, 68, 69, 71, 74, 77, 93, 94, 104, 105, 108, 121, 123, 126, 129, 130, 132, 135, 137], "ekk": 58, "el": 124, "elaps": 106, "elegantli": 53, "element": [28, 40], "element_typ": 40, "eleven": 138, "elif": [24, 65, 132, 137], "elimin": 137, "els": [4, 13, 24, 27, 53, 60, 65, 85, 120, 123, 126, 128, 132, 135, 137], "elsewher": [7, 52, 73, 96, 105, 132], "emac": [124, 138], "email": [21, 23, 46, 52, 63, 131], "embed": [52, 124, 125, 126, 128, 138], "emit": [126, 132], "empi": [4, 5, 18, 21, 23, 24, 27, 37, 92, 123, 124, 127, 129, 130], "empti": [34, 51, 73, 126, 130, 135], "empyerror": [37, 38], "en": 128, "enabl": [23, 41, 46, 48, 52, 58, 59, 67, 70, 73, 93, 95, 107, 125, 131], "encapsul": [120, 128], "encod": [54, 135], "encount": [53, 75, 123], "encrypt": 97, "end": [6, 13, 28, 29, 41, 52, 65, 67, 71, 73, 74, 75, 76, 85, 88, 94, 107, 120, 123, 125, 129, 130, 132, 136, 137, 138], "endeavour": 135, "endfor": [70, 123, 128, 134, 138], "endif": [4, 7, 13, 24, 128, 134, 137], "endpoint": 40, "enforc": [121, 124, 132], "engin": [22, 37, 42, 67, 95, 117, 120], "england": 76, "enhanc": 135, "enorm": 135, "enough": [123, 135], "ensembl": [128, 129, 130, 132, 134, 138], "ensemble_s": 137, "ensur": [7, 23, 30, 44, 46, 52, 53, 63, 68, 74, 76, 80, 86, 87, 97, 104, 107, 109, 123, 132, 134, 135, 137, 138], "enter": [52, 65, 74, 102, 130, 132], "enterprise1701": 96, "entir": [3, 4, 7, 8, 10, 12, 40, 45, 49, 53, 69, 78, 80, 84, 120, 122, 129, 132, 134, 137], "entiti": [85, 109, 128], "entri": [27, 35, 36, 37, 39, 58, 124, 126, 132], "entry_point": [27, 35, 36, 37], "env": [23, 24, 27, 28, 52, 63, 120, 135], "environ": [0, 4, 20, 21, 22, 24, 27, 28, 44, 45, 46, 51, 52, 56, 58, 62, 65, 68, 69, 70, 72, 73, 86, 87, 91, 98, 101, 105, 120, 124, 126, 127, 129, 131, 134, 135, 137], "eof": [21, 123], "eq": 130, "equal": [11, 21, 37, 59, 95, 121, 122, 132, 135, 137], "equalto": 128, "equival": [1, 3, 10, 11, 44, 45, 52, 53, 64, 68, 71, 78, 96, 124, 128, 129, 132, 133, 134], "equivel": 124, "er": 135, "eriod": 84, "err": [21, 28, 37, 46, 52, 73, 120, 121, 123], "err_typ": 37, "errno": 123, "erron": 37, "error": [1, 8, 13, 16, 21, 28, 30, 37, 40, 41, 46, 52, 53, 63, 73, 74, 81, 92, 103, 104, 107, 110, 124, 126, 128, 129, 130, 131, 132, 135, 137], "error_lin": 37, "escap": 52, "especi": [86, 87, 138], "essenti": [55, 63, 93, 123, 135, 137, 138], "establish": [41, 86, 87], "etc": [7, 21, 23, 40, 46, 48, 51, 52, 60, 73, 76, 103, 104, 118, 120, 121, 123, 124, 125, 129, 135, 137, 138], "eu": [63, 123], "euo": [123, 135], "eval": 135, "evalu": [10, 29, 50, 51, 52, 70, 124, 128, 130, 132, 135], "even": [19, 21, 34, 45, 48, 57, 64, 73, 75, 80, 95, 101, 105, 106, 118, 121, 123, 124, 130, 132, 134, 135, 137], "event": [16, 21, 23, 30, 37, 40, 44, 46, 52, 54, 59, 63, 77, 86, 89, 92, 101, 103, 108, 109, 120, 121, 123, 124, 127, 128, 132, 133, 135], "eventu": [16, 109, 125], "ever": [130, 135], "everi": [8, 21, 35, 41, 50, 51, 52, 57, 58, 65, 71, 73, 74, 76, 80, 86, 87, 101, 104, 107, 120, 121, 123, 129, 130, 132, 134, 137], "everyon": [53, 137], "everyth": [10, 40, 81, 94, 128, 135], "everywher": 132, "evid": [12, 123], "evolv": [8, 15, 85, 95, 101, 136], "ex": [120, 124, 135], "exact": [21, 120, 132], "exactli": [21, 40, 63, 104, 121, 124, 130, 134, 135], "examin": 73, "exampl": [3, 5, 6, 7, 13, 20, 21, 22, 23, 24, 26, 28, 29, 35, 37, 44, 46, 47, 50, 51, 52, 63, 68, 71, 73, 74, 76, 77, 79, 80, 81, 90, 92, 94, 96, 100, 103, 104, 105, 110, 121, 123, 124, 125, 128, 129, 131, 133, 134, 135, 136, 138], "examplehandl": 28, "exc": 37, "exce": [21, 46, 52, 104, 121, 132], "exceed": [52, 123], "except": [21, 35, 38, 40, 45, 48, 51, 52, 56, 62, 78, 86, 87, 101, 126, 127, 132, 137], "excess": 135, "exchang": [52, 91], "exclam": [21, 29, 132], "exclud": [4, 9, 52, 55, 124, 128, 131], "exclus": [52, 60, 105, 128], "execut": [3, 4, 17, 21, 28, 35, 40, 46, 48, 51, 52, 54, 57, 63, 65, 67, 72, 73, 74, 93, 95, 102, 104, 105, 107, 110, 111, 112, 113, 114, 115, 116, 117, 118, 120, 122, 123, 124, 126, 127, 130, 132, 136], "execution_time_limit": 28, "executiontim": 113, "exercis": 74, "exet": [68, 71, 74, 76], "exist": [4, 21, 24, 27, 37, 46, 52, 63, 78, 93, 101, 104, 120, 123, 126, 132, 135, 137, 138], "exit": [21, 28, 37, 52, 65, 73, 107, 120, 122, 126, 130, 135, 138], "expand": [52, 69, 71, 81, 104, 123, 125, 128, 129, 132, 134, 137], "expandtab": 138, "expans": [37, 127, 134], "expect": [13, 16, 21, 37, 41, 44, 46, 48, 52, 59, 65, 92, 97, 104, 105, 107, 120, 121, 123, 126, 130, 132, 135], "expens": 6, "experi": [128, 136], "expert": 135, "expir": [21, 52, 98, 106, 120, 124, 130], "expiri": [21, 52, 132], "explain": [5, 37, 78, 121, 123], "explan": [11, 42, 96, 126, 130, 131], "explicit": [46, 48, 52, 130, 132, 134, 135, 137], "explicitli": [18, 48, 52, 55, 113, 114, 115, 116, 117, 118, 122, 123, 129, 132, 135], "explor": 73, "exponenti": 50, "export": [24, 27, 28, 52, 53, 123, 126, 129, 130], "expos": [40, 48, 54, 101, 126, 137], "expr": 37, "express": [10, 13, 21, 28, 37, 46, 52, 53, 54, 57, 70, 76, 125, 126, 128, 129, 130, 134], "ext": [48, 52, 86, 87, 126], "extend": [3, 4, 13, 52, 53, 89, 92, 128, 129, 137], "extens": [13, 42, 43, 44, 48, 51, 63, 73, 124, 125, 128, 135], "extent": [44, 104, 106, 129], "extern": [6, 21, 46, 50, 52, 59, 73, 86, 87, 92, 94, 103, 108, 109, 120, 123, 124, 127, 128, 133, 137], "extra": [3, 23, 28, 52, 55, 73, 75, 78, 93, 113, 123, 124, 126, 128], "extract": [23, 27, 28, 32, 39], "extrem": [48, 123, 135, 138], "ey": [75, 103], "f": [27, 35, 39, 42, 46, 52, 78, 80, 87, 120, 121, 123, 126, 132], "f1": [126, 132], "f2": [126, 132], "f22011": 126, "f3": 126, "facad": 40, "face": [41, 55, 106], "facil": 99, "facilit": 135, "fact": 77, "factor": [52, 94, 105, 130, 134, 137], "fail": [3, 4, 11, 15, 16, 19, 21, 28, 37, 39, 40, 44, 46, 52, 53, 59, 60, 63, 65, 68, 73, 74, 77, 81, 92, 93, 99, 102, 103, 104, 105, 106, 107, 110, 120, 121, 124, 126, 128, 129, 130, 131, 132, 135], "fail_sign": 28, "failsaf": 46, "failur": [21, 27, 34, 37, 46, 52, 53, 65, 67, 74, 86, 87, 100, 107, 108, 123, 126, 127, 131, 136], "fairli": 130, "fall": [23, 48, 123], "fallback": 11, "fals": [37, 39, 45, 46, 50, 51, 52, 57, 60, 62, 105, 120, 126, 128, 130, 135], "fam": [126, 129, 130, 132], "fam1": [129, 132], "fam1_don": 132, "fam2": [129, 132], "famili": [21, 44, 52, 57, 61, 62, 66, 69, 70, 71, 72, 81, 95, 121, 123, 124, 126, 127, 128, 135, 136, 137, 138], "fanci": 75, "far": [21, 52, 73, 76, 77, 78, 80, 106, 130, 132, 135], "fashion": 62, "fast": [23, 35, 39, 52, 95, 126, 137], "fatal": [46, 52, 131], "fault": 37, "favour": [4, 124, 135], "faz": 52, "fcm": [7, 24], "fcm_make": [7, 123], "fcm_version": 124, "fcn": 35, "fcp": 52, "fcst": 138, "feasibl": 122, "featur": [0, 8, 11, 20, 25, 27, 29, 54, 55, 77, 81, 95, 107, 123, 125, 131, 137], "feed": [101, 126], "feel": 75, "ferment": 21, "ferri": 62, "fetch": [41, 53, 76], "fetch_fil": 123, "few": [0, 59, 65, 76, 88, 95, 120, 123, 126, 134, 135, 137], "fewer": [135, 137], "fi": [4, 60, 65, 85, 120, 123, 132, 135, 138], "fido": [45, 93], "field": [28, 39, 67], "fifo": 132, "fifth": 52, "file": [1, 3, 4, 5, 6, 7, 11, 13, 14, 18, 19, 21, 23, 26, 27, 28, 30, 35, 36, 37, 39, 40, 41, 43, 44, 46, 47, 48, 49, 50, 51, 52, 54, 56, 58, 59, 60, 62, 63, 65, 66, 68, 69, 70, 71, 72, 74, 76, 79, 80, 81, 82, 86, 87, 90, 91, 92, 99, 100, 101, 103, 105, 113, 114, 115, 116, 117, 118, 120, 121, 122, 126, 127, 129, 130, 131, 132, 133, 136], "file1": [52, 93, 104, 120, 132], "file2": [52, 93, 104, 120, 132], "file3": [93, 132], "file_1": 132, "file_1_readi": 132, "file_in": 135, "filenam": [4, 16, 20, 37, 46, 52, 74, 93, 121, 126], "fileparseerror": [37, 38], "fileremovalerror": [37, 38], "filesystem": [29, 37, 39, 41, 42, 43, 46, 48, 51, 53, 73, 96, 122, 123, 124, 127, 135], "fill": [104, 128], "fillchar": 128, "filter": [4, 13, 28, 39, 46, 52, 104, 124, 127, 131, 135], "filter_nam": [38, 39], "filter_poll_many_output": 28, "filter_submit_output": 28, "fin": 132, "final": [4, 20, 21, 24, 33, 37, 44, 46, 52, 57, 59, 63, 65, 71, 73, 74, 80, 88, 100, 101, 103, 106, 108, 120, 121, 125, 126, 128, 129, 130, 137], "find": [0, 7, 11, 21, 46, 48, 52, 60, 68, 73, 74, 80, 97, 101, 104, 121, 123, 126, 130, 135, 138], "fine": 136, "finer": [44, 55], "finish": [21, 46, 52, 60, 63, 68, 73, 74, 77, 88, 95, 104, 107, 108, 120, 121, 124, 126, 130, 135], "finish_tim": 130, "finit": 129, "firefox": 74, "first": [4, 6, 7, 8, 10, 20, 21, 29, 33, 34, 37, 40, 44, 46, 52, 53, 58, 59, 60, 62, 63, 71, 73, 76, 80, 81, 86, 87, 93, 101, 103, 104, 107, 118, 120, 121, 123, 125, 126, 128, 129, 132, 134, 137, 138], "first_task": 128, "firstli": 123, "fit": 85, "five": [20, 126, 132, 135, 138], "fix": [4, 21, 43, 52, 62, 76, 94, 101, 120, 123, 132, 135], "fixabl": 65, "flag": [37, 128, 135], "flaki": [105, 130, 135], "flat": [41, 126], "flexibl": [55, 126, 129, 135], "flist": 37, "float": [18, 40, 50, 51, 52, 126, 128], "flood": [63, 130], "flow": [1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 27, 28, 35, 36, 37, 38, 39, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138], "flow1": 3, "flow2": 3, "flow_num": [28, 126], "fluffi": 45, "fly": [58, 62, 132, 138], "fm1": 130, "fm2": 130, "focus": 54, "folder": [104, 124, 130], "follow": [3, 5, 8, 11, 13, 16, 21, 23, 24, 25, 27, 28, 29, 35, 36, 41, 45, 46, 50, 52, 53, 55, 58, 59, 60, 62, 63, 64, 65, 67, 68, 69, 70, 71, 73, 74, 76, 77, 78, 80, 93, 94, 96, 101, 103, 104, 105, 121, 123, 124, 126, 128, 129, 130, 131, 132, 133, 134, 135, 137, 138], "foo": [4, 5, 8, 10, 16, 18, 21, 28, 29, 36, 39, 40, 45, 50, 52, 53, 57, 63, 64, 68, 70, 71, 73, 76, 77, 78, 80, 93, 102, 104, 107, 109, 113, 114, 115, 116, 117, 121, 123, 125, 126, 128, 129, 130, 132, 133, 134, 135, 137, 138], "foo_color": 130, "foo_p": 129, "foo_p09": 129, "foo_p10": 129, "foo_run_3": 52, "foo_top": 52, "footer": [46, 52, 124, 131], "forc": [24, 29, 77, 80], "forecast": [67, 68, 71, 73, 74, 95, 128, 130, 132, 134, 138], "foreground": 120, "forev": 132, "forg": [20, 23, 55], "forget": 94, "forgotten": 122, "form": [0, 21, 28, 39, 40, 48, 52, 69, 74, 78, 118, 121, 126, 128, 132], "formal": 129, "format": [3, 21, 23, 28, 37, 39, 40, 42, 46, 47, 50, 51, 52, 56, 66, 69, 73, 79, 81, 88, 93, 118, 121, 124, 126, 128, 130, 131, 138], "format_direct": 28, "former": 3, "formerli": 53, "formul": 76, "fortun": 130, "forum": [2, 75, 123], "forward": [21, 46, 53, 101, 107, 132], "found": [4, 21, 23, 37, 48, 73, 74, 93, 103, 104, 123, 124, 126, 128, 135, 137], "four": [46, 52, 62, 65, 71, 74, 76, 125, 128, 129, 132, 138], "fourth": 76, "fox": [45, 126, 137, 138], "fpath": 37, "fqdn": 123, "fragil": [45, 132], "fragment": 45, "framework": 136, "free": [46, 75, 110], "freeform": 62, "frequenc": 132, "frequent": [46, 52, 107, 135], "fresh": [20, 93], "from": [0, 1, 2, 3, 4, 6, 8, 9, 11, 12, 13, 15, 17, 19, 20, 21, 23, 24, 27, 28, 29, 33, 35, 37, 39, 40, 41, 42, 43, 44, 46, 48, 51, 52, 54, 55, 58, 59, 60, 62, 63, 64, 67, 68, 69, 70, 71, 73, 74, 76, 78, 80, 81, 83, 84, 88, 91, 94, 95, 96, 97, 99, 101, 102, 104, 105, 106, 107, 109, 118, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 131, 132, 133, 134, 135, 136, 137, 138], "front": [21, 76, 101], "fuel": 62, "fulfil": [121, 134], "full": [1, 4, 20, 21, 42, 48, 52, 53, 69, 73, 81, 93, 94, 122, 123, 125, 132, 134, 135, 138], "fuller": [24, 46, 73], "fulli": [15, 27, 63, 104, 123], "fullmatch": 53, "func": 37, "function": [3, 4, 7, 13, 20, 21, 23, 25, 29, 32, 35, 36, 37, 39, 40, 41, 44, 50, 52, 81, 96, 120, 121, 122, 123, 125, 127, 128, 130, 132, 138], "fundament": 20, "further": [20, 21, 22, 39, 44, 56, 66, 75, 79, 97, 131, 134, 136], "futur": [0, 1, 7, 20, 21, 24, 25, 44, 52, 55, 59, 68, 71, 81, 94, 101, 104, 106, 126, 134, 135, 136, 138], "g": [0, 3, 4, 7, 10, 11, 13, 14, 16, 18, 21, 23, 24, 28, 29, 33, 35, 37, 39, 40, 43, 44, 46, 48, 51, 52, 53, 55, 57, 58, 59, 60, 68, 69, 70, 71, 73, 74, 75, 76, 77, 80, 81, 84, 86, 87, 88, 91, 93, 94, 96, 101, 103, 104, 106, 118, 120, 121, 122, 123, 124, 126, 128, 129, 130, 131, 132, 133, 134, 135, 137, 138], "gain": [48, 137], "gap": 95, "gather": [46, 52, 125, 128], "gcylc": 3, "gedit": [124, 138], "gener": [0, 1, 3, 21, 28, 33, 37, 39, 40, 44, 51, 52, 54, 62, 63, 67, 68, 71, 72, 74, 78, 81, 92, 95, 97, 101, 105, 113, 114, 115, 116, 117, 118, 120, 121, 123, 125, 126, 128, 129, 135, 136, 137, 138], "gentl": 35, "geograph": 138, "get": [1, 3, 16, 20, 21, 23, 24, 28, 37, 41, 45, 46, 48, 52, 63, 68, 69, 70, 71, 73, 74, 75, 76, 78, 81, 92, 93, 94, 101, 104, 105, 107, 109, 120, 121, 122, 124, 125, 126, 129, 130, 131, 132, 134, 135, 137, 138], "get_buoi": 129, "get_data": [105, 126], "get_group": 48, "get_hint": 37, "get_ic": [125, 128], "get_lbc": [125, 128], "get_observ": [68, 69, 70, 71, 73, 74, 76, 105], "get_observations_": [70, 76], "get_observations_aldergrov": [68, 69, 70, 71, 74, 76], "get_observations_camborn": [68, 69, 70, 71, 74, 76], "get_observations_heathrow": [68, 69, 70, 71, 73, 74, 76], "get_observations_shetland": [68, 69, 70, 71, 74, 76], "get_plan": 129, "get_poll_many_cmd": 28, "get_rainfal": [68, 70, 71, 73, 76], "get_ship": 129, "get_submit_stdin": 28, "get_vacation_sign": 28, "getgrgid": 48, "getgrouplist": 48, "getloadavg": [46, 131], "git": [26, 93], "github": [0, 48, 123], "give": [5, 16, 48, 51, 52, 76, 80, 94, 121, 123, 126, 129, 130, 131, 132, 134, 138], "given": [21, 37, 39, 46, 48, 52, 53, 64, 76, 80, 83, 84, 87, 101, 104, 106, 126, 129, 130, 132, 138], "glanc": 138, "glob": [40, 48, 81, 96, 124], "global": [3, 4, 5, 7, 11, 13, 20, 21, 23, 28, 29, 35, 37, 41, 45, 47, 52, 53, 54, 56, 69, 75, 91, 93, 95, 96, 104, 107, 113, 114, 115, 116, 117, 118, 121, 123, 124, 127, 130, 131, 134, 135, 138], "globalconfigerror": [37, 38], "globalvar": 52, "gloss": 137, "glossari": [22, 106], "glu": 138, "glu_ops_process_scatwind": 138, "glu_snow": 135, "gmt": 50, "gnu": [23, 46], "go": [21, 52, 60, 73, 94, 104, 123, 129, 134, 137], "goal": 67, "goe": [9, 21, 74, 75, 102, 107, 123, 130, 131], "gone": [52, 94, 123, 132], "gonna": 45, "good": [5, 23, 45, 52, 63, 69, 75, 78, 81, 86, 87, 124, 132, 135, 136], "goodby": 138, "googl": [46, 135], "got": [13, 74, 104], "govern": 21, "gpanel": 3, "grace": 131, "grain": 136, "grant": [19, 43, 48, 51], "graph": [0, 3, 4, 6, 7, 8, 9, 12, 15, 17, 20, 21, 23, 24, 27, 28, 37, 45, 52, 54, 58, 59, 60, 62, 63, 64, 65, 67, 69, 70, 71, 74, 76, 77, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 91, 94, 95, 100, 105, 106, 120, 124, 125, 126, 127, 128, 130, 131, 133, 134, 135, 136], "graphen": 40, "graphic": [1, 3, 43, 54, 73, 81], "graphiql": 103, "graphparseerror": [16, 37, 38], "graphql": [39, 40, 48, 103], "graphql_queri": [38, 39], "graphviz": [0, 1, 23], "greater": 137, "greatli": [95, 132], "greet": 71, "gregorian": [21, 52, 57, 77, 130, 132], "grei": [48, 73, 101], "grep": [3, 138], "grid": [68, 117, 120], "griffon": 62, "grind_bean": 95, "gross": 127, "ground": 62, "group": [11, 21, 28, 37, 46, 51, 52, 62, 68, 69, 81, 93, 120, 124, 125, 128, 129, 130, 132, 134, 136, 138], "group2": 51, "group_a": 51, "group_b": 51, "groupa": 48, "groupb": [48, 51], "groupnam": 48, "grow": [125, 132], "grp": 48, "grp_of_svr_own": [48, 51], "grumpi": 60, "gscan": [3, 42], "gt": 130, "gtk": 3, "guess": 73, "gui": [0, 1, 3, 12, 15, 17, 20, 21, 23, 46, 48, 52, 63, 64, 65, 67, 74, 75, 92, 93, 94, 100, 103, 123, 130, 132, 135], "guid": [0, 5, 7, 15, 16, 17, 20, 21, 22, 44, 46, 52, 53, 59, 60, 63, 64, 65, 68, 71, 73, 75, 76, 77, 134, 135], "guidanc": [23, 136], "guidelin": [22, 123, 136], "gvim": 68, "h": [52, 76, 118, 128, 132, 135], "h_data": 117, "h_rt": [117, 124], "ha": [0, 3, 4, 5, 7, 10, 11, 15, 16, 17, 18, 20, 21, 23, 28, 29, 33, 34, 37, 40, 44, 46, 48, 51, 52, 53, 59, 60, 62, 63, 65, 68, 69, 73, 74, 76, 77, 78, 80, 81, 83, 84, 85, 88, 93, 94, 95, 101, 102, 104, 106, 107, 108, 113, 120, 121, 123, 124, 125, 126, 128, 129, 130, 131, 132, 134, 135, 137], "had": [5, 15, 17, 44, 46, 60, 101, 123, 132, 137], "half": [52, 59, 76, 105], "half_past": 59, "half_past_trigg": 59, "halt": [3, 20, 101], "hand": [21, 60, 73, 121, 134], "handi": [81, 132], "handl": [3, 4, 10, 16, 21, 28, 29, 37, 41, 46, 52, 53, 54, 62, 63, 64, 77, 86, 87, 92, 95, 96, 100, 102, 105, 120, 122, 127, 128, 131, 132, 135], "handler": [21, 23, 28, 37, 44, 46, 52, 54, 108, 120, 121, 124], "hang": 123, "happen": [65, 101, 104, 121, 126, 132], "happi": 60, "hard": [52, 113, 123, 134, 135, 138], "hardcod": 51, "harder": [69, 126], "hardwar": 65, "hardwir": [46, 130, 135], "hash": [125, 128], "hasn": [21, 123], "have": [0, 1, 3, 4, 5, 6, 7, 8, 10, 11, 13, 14, 17, 19, 20, 21, 23, 24, 33, 34, 35, 41, 43, 44, 45, 46, 48, 51, 52, 53, 58, 59, 60, 62, 63, 64, 65, 68, 69, 71, 73, 74, 75, 76, 77, 78, 80, 81, 86, 87, 88, 91, 93, 94, 95, 96, 101, 102, 103, 104, 106, 108, 118, 120, 121, 122, 123, 124, 126, 129, 130, 131, 132, 134, 135, 137, 138], "have_idl": 137, "haven": [21, 74, 135], "head": [45, 49, 52, 78, 95, 124, 130, 137], "header": [40, 109], "health": [30, 35, 46, 124], "heat": 80, "heathrow": [70, 71, 74, 76], "heavili": 132, "held": [3, 21, 46, 52, 94, 102, 106, 123, 130, 132, 135], "helicopt": 62, "hello": [4, 13, 28, 50, 52, 71, 73, 74, 83, 84, 87, 89, 92, 120, 121, 123, 126, 128, 135, 138], "hello_": 24, "hello_computehost": 74, "hello_earth": 71, "hello_mar": 24, "hello_mercuri": 71, "hello_venu": 71, "hello_world": [73, 82], "help": [2, 3, 7, 13, 24, 44, 50, 52, 53, 69, 73, 76, 81, 92, 93, 94, 98, 121, 126, 131, 134, 135, 138], "help_lin": 37, "here": [11, 13, 16, 20, 21, 24, 35, 41, 44, 46, 51, 52, 53, 63, 73, 76, 78, 80, 81, 87, 95, 103, 120, 121, 125, 126, 128, 129, 130, 132, 133, 134, 135, 137, 138], "heredoc": 138, "heterogen": [118, 119], "hetjob": [118, 119], "hetjob_0_": 118, "hetjob_1_": 118, "hhmm": 52, "hidden": [21, 126, 137], "hierarch": 41, "hierarchi": [21, 46, 51, 52, 54, 123, 124, 132, 135, 136], "high": [44, 46, 95, 99, 106, 130, 131, 132], "higher": [21, 23, 46, 51, 52, 132, 134, 135], "highest": [51, 130], "highli": [69, 126], "highlight": [5, 23, 44, 127, 135, 138], "hint": 37, "histori": [22, 44, 56, 109, 124, 138], "hit": [74, 86, 87, 88, 123], "hitherto": 137, "hold": [1, 3, 4, 20, 21, 41, 44, 48, 52, 73, 92, 103, 108, 118, 120, 122, 124, 132], "home": [7, 20, 23, 26, 46, 52, 91, 93, 96, 97, 103, 104, 109, 123, 128, 130, 131, 135], "home_dir_on_workflow_host": 128, "homebrew": 23, "homeless": 53, "homepag": [19, 81], "honour": 82, "hook": [21, 52, 103, 124, 131], "hopefulli": 65, "host": [4, 5, 14, 20, 21, 23, 24, 28, 29, 34, 37, 40, 46, 50, 52, 53, 55, 57, 58, 63, 73, 74, 97, 103, 104, 105, 107, 120, 121, 122, 124, 125, 127, 128, 134, 136, 137], "host1": 121, "host2": 121, "host_1": 131, "host_2": 131, "host_3": 131, "hosti": 134, "hostnam": [50, 52, 73, 130], "hosts_consum": 37, "hostselectexcept": [37, 38], "hostx": 134, "hour": [21, 34, 50, 52, 58, 59, 65, 71, 74, 76, 77, 86, 87, 88, 91, 105, 126, 128, 130, 132], "hourli": [52, 126, 132], "housekeep": [52, 136, 138], "houston": [125, 128], "hoverwork": 62, "how": [4, 5, 10, 19, 21, 41, 44, 46, 48, 50, 52, 59, 62, 66, 69, 74, 76, 79, 80, 84, 90, 91, 92, 93, 94, 96, 104, 106, 109, 110, 120, 121, 123, 124, 125, 126, 129, 130], "howev": [0, 3, 4, 7, 12, 16, 20, 21, 23, 45, 46, 48, 49, 52, 69, 73, 74, 76, 78, 93, 94, 95, 101, 104, 105, 106, 107, 120, 121, 123, 125, 126, 129, 132, 133, 135, 136, 137], "hpc": [11, 21, 24, 53, 99, 107, 126, 130, 137], "hpc1": [5, 130], "hpc_init": 7, "html": [28, 51, 52, 68, 74], "http": [0, 23, 28, 43, 48, 52, 54, 55, 131], "hub": [1, 23, 44, 46, 47, 55, 56], "hubapp": 48, "huge": 129, "human": [62, 103, 123], "human_engin": 62, "hungri": 105, "hyphen": [52, 76], "i": [0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 44, 45, 46, 48, 50, 51, 52, 53, 55, 57, 58, 59, 60, 62, 63, 64, 65, 66, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 85, 86, 87, 88, 91, 92, 93, 94, 96, 99, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 120, 121, 122, 124, 125, 126, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138], "i1": 129, "i2": 129, "i3": 129, "i4": 129, "iasi": 128, "ibm": 114, "ic": [45, 62], "ice_cream": 64, "ice_cream1": 64, "ice_cream2": 64, "ice_cream3": 64, "ice_cream4": 64, "ice_cream5": 64, "icon": [17, 73, 94, 106], "icp": [52, 128], "id": [7, 12, 21, 23, 28, 37, 39, 40, 41, 44, 46, 52, 53, 57, 70, 71, 74, 86, 87, 91, 92, 97, 101, 103, 104, 105, 109, 121, 122, 123, 124, 126, 128, 130, 131, 134, 135], "idea": [5, 52, 63, 78, 107], "ideal": 37, "ident": [37, 46, 52, 53, 96, 109, 126], "identif": [46, 123, 130, 131], "identifi": [3, 21, 24, 40, 46, 48, 52, 57, 73, 74, 84, 93, 101, 121, 123, 126, 130], "idl": 137, "idx": 129, "ignor": [24, 28, 45, 59, 60, 65, 74, 78, 80, 94, 104, 105, 120, 121, 124, 126, 129, 132, 134, 137, 138], "ill": 137, "illeg": [13, 21, 132], "illegalitemerror": [4, 37, 38], "illegalvalueerror": [37, 38], "illustr": [93, 95, 125, 128, 130, 132], "imag": [0, 1], "imagin": 133, "imbal": 46, "immedi": [29, 44, 46, 52, 73, 101, 106, 120, 131, 132, 137], "impact": 44, "implement": [0, 4, 20, 21, 22, 27, 28, 36, 43, 46, 52, 76, 89, 92, 121, 122, 125, 126, 130, 132, 135], "impli": [105, 120, 132, 138], "implicit": [4, 15, 21, 52, 70, 73, 74, 76, 78, 80, 95, 125, 127, 128, 132, 134], "implicitli": [11, 21, 52, 71, 130], "import": [4, 13, 21, 27, 28, 35, 40, 46, 48, 52, 73, 126, 127, 130, 132, 135, 137, 138], "importantli": 53, "impos": 21, "imposs": [16, 124], "improv": [52, 69, 130, 137], "inact": [46, 52, 124, 131], "inadvert": 23, "inbox": [63, 130], "inc": [45, 135], "includ": [3, 4, 6, 7, 8, 18, 20, 21, 23, 26, 37, 40, 42, 43, 44, 45, 46, 48, 50, 51, 52, 67, 73, 93, 95, 98, 101, 103, 104, 105, 119, 122, 123, 124, 125, 128, 129, 130, 132, 136], "includefilenotfounderror": [37, 38], "inclus": [45, 50, 52, 128, 129, 137], "incom": [40, 126], "incompat": 37, "incomplet": [20, 21, 44, 52, 101, 108, 130, 132], "inconsist": [24, 30], "incorpor": [17, 120], "incorrect": 37, "incorrectli": [53, 132, 135], "increas": [20, 33, 37, 123], "increment": [20, 21, 42, 52, 57, 65, 73, 85, 93, 101, 121, 129, 130, 135], "incur": 6, "inde": 80, "indefinit": [22, 101], "indent": [45, 79, 124, 136], "independ": [4, 11, 76, 101, 120, 126, 136, 137], "index": [37, 41, 51, 52, 129], "indic": [5, 16, 17, 28, 48, 120, 132, 134], "indirectli": 108, "indiscrimin": 15, "individu": [12, 20, 21, 35, 36, 40, 48, 52, 68, 76, 95, 101, 120, 121, 124, 130, 132, 135, 137], "ineffici": [63, 135], "inexact": [21, 132], "infer": [52, 126, 132, 133], "infinit": [15, 19, 106, 129], "info": [27, 28, 35, 37, 81, 96, 103, 131], "inform": [3, 4, 7, 18, 19, 20, 21, 23, 26, 28, 37, 39, 40, 41, 42, 43, 44, 46, 48, 50, 51, 52, 53, 59, 63, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 78, 81, 93, 94, 95, 98, 103, 104, 107, 109, 113, 120, 121, 123, 124, 126, 130, 131, 132, 134, 135, 136], "infrastructur": [43, 136], "infrequ": [107, 123], "ingredi": 80, "inherit": [21, 28, 46, 48, 52, 54, 60, 61, 64, 66, 68, 81, 83, 84, 123, 124, 125, 126, 127, 128, 129, 132, 137, 138], "ini": [45, 78], "init": [28, 31, 32, 33, 41, 46, 52, 53, 62, 104, 105, 120, 126, 129, 134], "initi": [4, 5, 6, 8, 11, 20, 21, 24, 31, 33, 37, 40, 46, 50, 52, 53, 57, 58, 59, 63, 67, 71, 73, 74, 77, 80, 83, 84, 85, 87, 88, 91, 95, 100, 101, 103, 121, 123, 125, 126, 128, 129, 130, 135, 137], "initial_point": 129, "initialis": 70, "inject": 48, "inlin": [52, 78, 110, 123, 124, 125, 135, 136], "inner": 128, "inotifi": 126, "inpr": 138, "input": [37, 52, 78, 128, 135, 137], "inputerror": [37, 38], "insensit": 128, "insert": [1, 3, 4, 8, 24, 71, 135], "insid": [4, 7, 20, 21, 35, 73, 78, 93, 96, 107, 123, 128], "inspect": [58, 62, 63, 68, 69, 71, 73, 76, 92, 123, 135], "instabl": 135, "instal": [0, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 25, 26, 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, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 94, 95, 97, 98, 99, 100, 101, 102, 103, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138], "install_niwa": 137, "instanc": [6, 8, 15, 21, 28, 37, 42, 43, 48, 52, 57, 58, 73, 74, 78, 80, 81, 83, 84, 94, 101, 104, 105, 122, 126, 128, 129, 130, 132, 135, 137], "instanti": [28, 40], "instead": [6, 11, 21, 28, 40, 44, 45, 46, 52, 74, 76, 88, 96, 105, 106, 118, 119, 122, 124, 125, 126, 129, 130, 133, 134, 135, 137, 138], "institut": [46, 53, 67], "instruct": [7, 23, 44, 122, 124], "insuffici": 37, "insur": 104, "int": [28, 37, 39, 40, 51, 126, 128, 129], "integ": [18, 21, 46, 50, 52, 54, 71, 76, 77, 80, 85, 87, 89, 92, 101, 104, 124, 126, 128, 134], "integr": [7, 28, 30, 42, 46, 124, 125, 131], "intend": [41, 42, 52, 96, 103, 107, 123, 126, 135, 138], "intent": 52, "inter": [52, 83, 84, 89, 90, 92, 95, 126, 129, 135], "interact": [0, 19, 20, 23, 42, 46, 47, 73, 92, 94, 100, 107, 121, 122, 123, 126, 130], "intercycl": [21, 79, 95, 129, 135], "interdepend": [22, 95, 136], "interest": [33, 55, 63, 75], "interfac": [4, 9, 19, 20, 23, 25, 28, 37, 38, 41, 42, 43, 44, 46, 48, 52, 54, 56, 67, 72, 74, 94, 103, 109, 130, 131], "interfer": [120, 123, 135], "interim": 0, "interleav": 135, "intermedi": 132, "intern": [20, 21, 41, 46, 52, 62, 67, 106, 120, 121, 127, 138], "internal_combustion_engin": 62, "internet": 46, "interoper": [4, 7, 137], "interpos": 134, "interpret": [10, 41, 52, 73, 109, 110, 124, 126, 129, 132], "interrog": [109, 121, 122, 126], "interrupt": [12, 40], "interv": [33, 34, 35, 37, 46, 50, 51, 52, 59, 63, 68, 76, 86, 87, 95, 107, 121, 123, 124, 126, 129, 130, 135], "interval_month": 129, "intervalparsingerror": [37, 38], "interven": [81, 107, 130, 132], "intervent": [20, 21, 22, 44, 46, 52, 92, 101, 106, 108, 132], "intra": 95, "intranet": 46, "introduc": [3, 18, 46, 52, 69, 75, 126, 132, 134], "introduct": [22, 66, 72, 78, 92], "intuit": 44, "invalid": [28, 37, 52, 93, 128], "invalidcompletionexpress": [37, 38], "invalidconfigerror": [37, 38], "investig": [52, 120, 122, 123], "invis": [45, 138], "invoc": [46, 98, 126], "invok": [23, 40, 46, 52, 97, 107, 124, 130, 131, 135], "involv": [6, 21, 41, 51, 60, 93, 95, 104, 126, 132, 135], "io": 35, "ip": [46, 52, 123], "irregular": [86, 87], "irrespect": 132, "is_act": [38, 39], "is_messag": 126, "is_trigg": [44, 126], "isl": 62, "isn": [37, 48, 62, 132], "iso": [21, 37, 52, 126, 128, 132], "iso8601": [21, 50, 52, 54, 59, 74, 79, 126, 128, 130], "iso8601_datetim": 128, "iso8601_dur": 128, "iso8601syntaxerror": 128, "isodatetim": [1, 13, 23, 44, 50, 52, 57, 124, 128, 130], "isodatetimecalendar": [57, 130], "isodatetimeref": [57, 130], "isol": [73, 120, 137], "issu": [0, 37, 40, 41, 48, 63, 75, 88, 123, 124, 126, 131, 132], "item": [4, 5, 8, 11, 20, 21, 23, 24, 37, 40, 45, 46, 49, 52, 53, 69, 70, 79, 96, 104, 105, 120, 121, 124, 126, 128, 129, 130, 132, 134, 135, 137], "itemnotfounderror": [37, 38], "iter": [28, 37, 39, 95, 134], "itertool": 128, "its": [8, 11, 20, 21, 23, 28, 41, 43, 44, 46, 52, 62, 67, 69, 73, 81, 83, 84, 91, 93, 94, 95, 101, 102, 103, 104, 107, 111, 112, 120, 121, 123, 124, 125, 126, 129, 130, 132, 135, 137, 138], "itself": [0, 16, 21, 44, 46, 48, 53, 62, 73, 75, 93, 94, 101, 120, 121, 123, 126, 130, 132, 135, 137], "j": [52, 123, 126, 128, 132], "jan": 132, "januari": [21, 52, 59, 76, 77, 132], "jet": 62, "jinja": [128, 135], "jinja2": [4, 5, 7, 18, 21, 24, 27, 37, 45, 46, 52, 54, 69, 71, 72, 73, 81, 88, 92, 104, 124, 125, 126, 127, 129, 130, 132, 136], "jinja2error": [13, 37, 38], "jinja2filt": [13, 128], "jinja2glob": [13, 128], "jinja2test": [13, 128], "jitter": 33, "job": [0, 1, 3, 4, 5, 6, 9, 11, 12, 14, 15, 19, 21, 22, 23, 25, 29, 34, 37, 40, 42, 44, 46, 52, 54, 55, 56, 65, 71, 72, 81, 82, 92, 95, 96, 97, 100, 101, 102, 103, 104, 105, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 124, 125, 126, 127, 128, 129, 131, 134, 137, 138], "job_conf": 28, "job_d": 28, "job_file_path": 28, "job_id": [28, 46, 121, 124, 130], "job_id_list": 28, "job_runn": 28, "job_runner_cmd_tmpl": 28, "job_runner_command_templ": 28, "job_runner_handl": 28, "job_runner_nam": [28, 124, 130], "job_typ": 137, "job_vers": 135, "jobscript": 3, "join": [21, 132], "jpg": 52, "json": [26, 27, 31, 41], "juli": 132, "jumbo": 62, "jump": 138, "june": 132, "jupyt": [19, 41, 42, 46, 47, 51, 55], "jupyter_config": [48, 51], "jupyterhub": [42, 48, 55], "just": [7, 8, 21, 28, 52, 69, 75, 77, 78, 80, 91, 96, 99, 101, 120, 121, 122, 125, 126, 128, 129, 130, 132, 133, 134, 135, 137, 138], "justifi": 58, "k": 132, "kate": 124, "keep": [7, 12, 21, 53, 55, 73, 75, 91, 123, 135, 138], "kei": [11, 18, 27, 37, 39, 40, 41, 45, 48, 52, 53, 68, 70, 74, 78, 97, 104, 107, 126, 128], "kept": [15, 32, 52, 63, 132, 135], "kernel": 23, "kerosen": 62, "key1": 134, "key2": 134, "key_secret": 97, "keyword": [52, 126, 128], "kick": [86, 87], "kill": [0, 21, 28, 46, 48, 51, 52, 54, 74, 81, 94, 99, 102, 104, 110, 122, 123, 126, 131], "kill_cmd_tmpl": 28, "kind": [67, 85, 101, 132, 137], "knight": 58, "know": [53, 86, 87, 94, 105, 123, 126, 135, 137], "knowledg": 136, "known": [21, 40, 62, 65, 113, 114, 115, 116, 117, 118, 121, 130, 132, 135], "kwarg": [37, 48, 50, 51, 126], "kwarg1": 52, "kwarg2": 52, "l": [1, 20, 23, 28, 73, 74, 115, 116, 117, 121, 123, 124, 126, 132], "lab": [43, 48], "label": [21, 37, 52, 76, 77, 80, 126, 132], "lack": 137, "lag": 137, "lambda": [125, 126], "land": [62, 132], "land_vehicl": 62, "lang": 124, "languag": [27, 41, 52, 124, 125], "larg": [19, 21, 29, 46, 52, 104, 106, 129, 130, 132, 134, 135, 137, 138], "larger": 44, "largest": [52, 76, 132], "last": [21, 46, 51, 52, 69, 73, 74, 76, 107, 120, 123, 126, 128, 129, 132, 135], "last_task": 128, "lastli": 63, "lat1": 68, "lat2": 68, "late": [52, 124, 135], "later": [5, 8, 11, 44, 78, 88, 104, 130, 132, 135], "latest": [3, 17, 21, 55, 74, 121, 126], "latin": 126, "latitud": 74, "latter": [3, 21, 135], "launch": [3, 20, 42, 43, 48, 94, 135], "layer": [48, 54, 56], "layout": 135, "lazi": 138, "le": 63, "lead": [52, 101, 124, 128, 138], "leader": 120, "leaf": 132, "leap": [21, 52, 77, 132], "learn": 125, "least": [17, 52, 60, 74, 107, 132, 135], "leav": [1, 37, 59, 73, 74, 123, 138], "left": [1, 12, 21, 29, 52, 53, 60, 62, 65, 67, 73, 74, 81, 88, 101, 102, 104, 106, 121, 123, 128, 130, 132, 138], "legaci": 52, "legal": [11, 52, 124], "length": [32, 46, 52, 100, 121, 124, 126, 128, 136], "lengthi": 69, "less": [4, 37, 40, 46, 52, 107, 121, 123, 126, 132, 135, 137], "let": [44, 65, 74, 80, 101, 105, 123, 132], "letter": [52, 126], "level": [20, 21, 39, 45, 46, 48, 49, 51, 52, 78, 103, 104, 120, 126, 128, 130, 131, 132, 134, 135, 138], "lib": [7, 28, 36, 52, 68, 73, 93, 104, 123, 124, 126, 130], "librari": [23, 28, 52, 104, 109, 124, 130, 131, 135], "licens": 3, "life": 128, "lifecycl": 21, "lifetim": [21, 98, 130, 131], "lightweight": 131, "like": [4, 7, 10, 13, 16, 20, 21, 23, 25, 40, 43, 44, 46, 48, 51, 52, 53, 58, 60, 62, 63, 64, 68, 70, 71, 73, 74, 77, 78, 80, 81, 94, 101, 106, 113, 114, 115, 116, 117, 118, 120, 121, 123, 124, 125, 126, 128, 129, 130, 132, 133, 134, 137, 138], "likelihood": 126, "likewis": [11, 69, 93, 132], "limit": [15, 20, 21, 24, 28, 45, 46, 48, 51, 52, 64, 72, 80, 86, 87, 93, 100, 106, 110, 111, 112, 113, 114, 115, 116, 117, 118, 123, 124, 127, 130, 136, 138], "limit_min": [125, 128], "line": [1, 4, 6, 7, 9, 12, 14, 18, 19, 20, 21, 23, 24, 27, 28, 29, 37, 41, 42, 43, 44, 45, 46, 48, 49, 51, 52, 62, 64, 65, 67, 68, 70, 71, 73, 74, 78, 80, 81, 84, 88, 93, 94, 103, 104, 109, 120, 121, 123, 124, 125, 128, 129, 130, 131, 134, 135, 136, 137], "linear": [52, 130, 132], "linearis": [57, 130], "liner": 138, "link": [23, 42, 46, 52, 137], "lint": [5, 81, 123, 127, 138], "linter": 124, "linux": [23, 118, 126], "linuxbox": 11, "linuxbox42": 11, "linuxboxnn": 11, "list": [1, 4, 5, 7, 8, 11, 19, 21, 24, 28, 29, 34, 35, 37, 39, 40, 45, 46, 48, 50, 52, 55, 63, 68, 73, 74, 75, 92, 93, 94, 105, 120, 121, 123, 124, 125, 128, 129, 130, 131, 132, 134, 138], "listen": [21, 40, 97], "listvalueerror": [37, 38], "liter": [128, 129, 130, 135, 137], "littl": [28, 52, 88, 91, 95, 125, 126, 130, 135], "live": [1, 43, 73, 101, 105], "ll": [123, 132], "llsubmit": [113, 120, 121], "ln": 23, "lng1": 68, "lng2": 68, "load": [27, 29, 37, 40, 46, 51, 52, 123, 128, 130, 134, 137, 138], "load_rol": 48, "loadlevel": [52, 74, 99, 120, 121, 124, 137], "local": [4, 11, 20, 23, 29, 46, 52, 53, 96, 105, 107, 120, 122, 123, 126, 128, 130, 132, 135, 137], "localhost": [11, 28, 29, 46, 50, 104, 130, 131], "locat": [3, 7, 13, 21, 23, 28, 45, 46, 51, 52, 53, 57, 73, 76, 78, 96, 104, 121, 123, 124, 126, 128, 130, 133, 135], "location_a": 24, "location_b": 24, "location_c": 24, "lock": 109, "log": [0, 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, 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, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 122, 124, 125, 126, 127, 129, 131, 132, 133, 134, 135, 136, 137, 138], "logger": 103, "logic": [4, 11, 28, 40, 78, 125, 126, 128, 130, 132, 134, 135, 138], "login": [5, 11, 23, 46, 52, 57, 92, 107, 120, 130], "login_nod": 53, "login_node01": 11, "login_node02": 11, "login_node_1": 53, "login_node_2": 53, "london": 76, "long": [7, 28, 45, 46, 52, 53, 63, 78, 93, 95, 105, 109, 118, 120, 121, 126, 128, 129, 131, 135, 138], "long_fc": 135, "long_forecasting_task": 63, "longer": [3, 12, 14, 23, 24, 40, 44, 46, 52, 73, 97, 120, 124, 130, 134], "longest": [124, 129], "longitud": 74, "look": [7, 27, 39, 41, 44, 46, 51, 53, 55, 58, 60, 61, 62, 63, 64, 65, 73, 74, 78, 80, 93, 96, 104, 123, 124, 126, 135], "lookup": 41, "loop": [21, 22, 25, 32, 40, 46, 52, 70, 71, 95, 125, 128, 135], "loos": 135, "lose": 81, "lost": [21, 96, 124], "lot": [52, 128, 135, 137], "low": 99, "lower": [46, 48, 52, 62], "lowercas": [68, 124, 138], "lowest": [46, 132], "lsf": [52, 74, 124], "lucki": 65, "lustre_disk": 53, "lyric": 45, "m": [21, 26, 50, 52, 76, 83, 84, 94, 128, 129, 132, 134, 138], "m1": [130, 132], "m2": [130, 132], "m3": 130, "m_max": 138, "mac": 22, "machin": [11, 14, 23, 46, 55, 69, 74, 121, 131], "macro": [13, 128, 134, 135], "made": [21, 44, 46, 59, 73, 75, 93, 126, 132, 135, 137], "mai": [4, 5, 6, 7, 9, 11, 14, 16, 20, 21, 22, 23, 24, 27, 28, 39, 40, 41, 44, 45, 46, 48, 52, 53, 55, 59, 60, 65, 67, 68, 73, 76, 78, 80, 81, 88, 93, 94, 95, 99, 101, 104, 105, 107, 113, 114, 115, 116, 117, 118, 121, 122, 123, 124, 126, 128, 129, 130, 132, 133, 134, 135, 136, 137, 138], "mail": [23, 46, 52, 59, 63, 124, 130], "main": [22, 25, 32, 42, 46, 52, 64, 75, 76, 89, 93, 101, 126, 129, 132, 134, 135, 137, 138], "main_loop": [35, 37, 46], "mainlooppluginexcept": 35, "mains_chef_queu": 64, "maintain": [21, 22, 25, 41, 46, 52, 55, 69, 103, 109, 125, 135, 136, 137], "mainten": [5, 29, 55, 130, 131, 134, 135], "major": [2, 22, 44, 56, 81, 132, 135, 137], "make": [4, 5, 7, 20, 21, 27, 29, 44, 52, 59, 60, 62, 63, 68, 69, 70, 74, 75, 78, 80, 83, 84, 86, 87, 92, 94, 95, 96, 99, 102, 104, 120, 121, 123, 124, 125, 126, 128, 129, 131, 132, 134, 135, 136, 137, 138], "make_coffe": 95, "make_dough": [78, 80], "malici": 122, "malt": 21, "mamba": 23, "man": 46, "manag": [0, 14, 15, 20, 21, 37, 43, 46, 63, 64, 67, 92, 95, 96, 99, 104, 110, 115, 118, 120, 124, 126, 130, 135, 136], "mani": [2, 21, 23, 46, 48, 53, 64, 74, 81, 95, 101, 104, 110, 120, 123, 129, 130, 131, 132, 134, 135, 137], "manip_job_id": 28, "manipul": [23, 52, 119], "manner": [12, 16, 60, 62, 125, 132], "manual": [7, 8, 17, 20, 21, 23, 29, 37, 46, 52, 68, 74, 94, 96, 101, 104, 106, 108, 123, 129, 137], "map": [41, 48, 51, 68, 74], "map_fil": 68, "map_templ": 68, "mar": 24, "margin": 138, "mark": [4, 16, 20, 21, 29, 52, 60, 81, 102, 104, 132], "marker": [132, 138], "markup": 125, "mash": 21, "mass": 138, "master": 48, "match": [11, 15, 27, 28, 33, 39, 40, 44, 46, 48, 52, 53, 63, 78, 80, 84, 93, 104, 121, 123, 124, 126, 128, 130, 132, 135, 138], "materi": [67, 95], "math": [74, 125, 128], "mathemat": 125, "matplotlib": [31, 32, 33], "matter": [76, 78, 132, 135], "max": [46, 52, 87, 124, 126, 132], "max_depth": 39, "max_line_len": 124, "max_thread": 51, "max_work": 51, "maximum": [39, 46, 48, 50, 51, 52, 95, 121, 126, 132, 135, 138], "mc": 129, "mcshipfac": 129, "me": [45, 93], "mean": [4, 16, 21, 45, 46, 48, 52, 65, 68, 77, 78, 80, 93, 120, 121, 123, 128, 132, 134, 137], "meaning": 46, "meantim": 126, "meanwhil": 101, "measur": [0, 33, 132], "mechan": [45, 46, 52, 120, 126, 128, 135], "meddl": [27, 35], "medium": 126, "meet": 131, "mem": [52, 74, 118, 128, 129], "mem_": 128, "mem_0": 128, "mem_1": 128, "mem_2": 128, "mem_3": 128, "mem_4": 128, "mem_5": 128, "mem_6": 128, "mem_7": 128, "mem_8": 128, "mem_9": 128, "member": [21, 48, 51, 52, 60, 64, 67, 68, 126, 128, 129, 130, 131, 132, 134, 135, 136, 137, 138], "member_r1": 129, "member_r2": 129, "membership": [48, 101], "memori": [21, 33, 41, 74, 130, 131, 132, 137], "menu": [64, 73], "mercuri": 71, "mere": 137, "merg": [21, 45, 78, 100, 104, 137], "mess": [134, 137, 138], "messag": [4, 21, 27, 28, 37, 40, 41, 44, 46, 48, 52, 58, 60, 61, 66, 73, 85, 92, 100, 104, 109, 110, 121, 122, 126, 128, 130, 131, 135], "messi": 137, "met": [21, 27, 67, 73, 76, 77, 80, 85, 126, 132, 136, 137], "meta": [39, 40, 46, 52, 53, 62, 63, 82, 83, 84, 85, 88, 91, 124, 125, 126, 128, 130, 131, 132, 138], "metadata": [46, 52, 62, 75, 130, 136], "meteorolog": 67, "meteorologi": 91, "method": [22, 25, 39, 40, 41, 46, 48, 52, 53, 57, 69, 70, 107, 110, 120, 126, 128, 130, 135], "metoffic": [74, 137], "metoffice_pbs_platform": 137, "metomi": [13, 23, 44, 55, 128], "mice": 128, "middai": [77, 86, 87], "middl": [73, 129], "midnight": [21, 52, 76, 86, 87, 132], "might": [4, 7, 11, 16, 20, 23, 34, 46, 51, 52, 65, 75, 76, 85, 91, 94, 96, 105, 123, 124, 125, 126, 129, 132, 135], "migrat": [9, 15, 22, 44, 46, 52, 54, 81, 135], "mile": 74, "mileston": 21, "militari": [62, 76], "mimic": 4, "min": [46, 74, 121, 132, 135], "mind": 135, "miner": 60, "mineshaft": 60, "minim": [53, 55, 78, 82, 94, 95, 137, 138], "minimum": [46, 50], "minor": [20, 55, 134, 135], "minu": [21, 50, 128], "minut": [21, 35, 50, 52, 65, 68, 71, 74, 76, 88, 104, 107, 113, 120, 121, 128, 130, 132], "mirror": [7, 11, 126], "miscellan": [52, 104], "miss": [37, 53, 71, 95, 96, 123, 132, 137], "misspel": [21, 130], "mistak": [130, 134], "mistaken": 62, "mix": [37, 50, 69, 129], "mixtur": 138, "mkdir": [58, 59, 60, 62, 63, 64, 65, 76, 78, 80, 126, 135], "mm": [52, 132], "mmz": 132, "moab": [52, 74, 121, 124], "mobil": 42, "mock": 130, "mocked_randint": 126, "mocked_random": 126, "mode": [5, 9, 11, 16, 21, 29, 42, 46, 57, 59, 60, 63, 65, 71, 73, 74, 76, 77, 78, 80, 83, 85, 87, 92, 100, 101, 104, 120, 123, 124, 126, 130, 132, 135, 137], "model": [3, 12, 67, 85, 91, 95, 101, 109, 120, 124, 129, 130, 132, 134, 135, 136, 138], "model1": 134, "model2": 134, "model3": 134, "model4": 134, "model_a": 3, "model_chunk0": 129, "model_p": 134, "model_p7": 134, "model_r1": 129, "model_r2": 129, "model_run1": 129, "model_run1_buoi": 129, "model_run1_plan": 129, "model_run1_ship": 129, "model_run2": 129, "model_run2_buoi": 129, "model_run2_plan": 129, "model_run2_ship": 129, "model_run3": 129, "model_run4": 129, "model_run5": 129, "model_short": 135, "model_system_funct": 138, "modif": [4, 120, 135], "modifi": [3, 23, 28, 58, 59, 62, 63, 100, 120, 121, 128, 134, 135], "modul": [4, 13, 27, 28, 35, 36, 37, 52, 74, 104, 109, 123, 124, 125, 126, 127, 130], "modular": 135, "moment": [71, 76], "mondai": 132, "monitor": [1, 3, 19, 20, 32, 41, 43, 44, 48, 67, 73, 77, 81, 103, 104, 126, 132, 134], "monochrom": 17, "monochromat": 106, "monolith": 136, "month": [21, 52, 76, 77, 86, 87, 88, 129, 132], "monthli": 129, "more": [1, 2, 3, 4, 7, 11, 15, 18, 19, 20, 21, 23, 24, 28, 37, 39, 40, 41, 43, 44, 46, 48, 50, 51, 52, 53, 54, 55, 57, 63, 64, 65, 68, 70, 71, 73, 74, 75, 77, 78, 80, 81, 88, 93, 94, 95, 101, 102, 103, 104, 106, 109, 120, 122, 123, 124, 125, 126, 128, 129, 130, 131, 132, 134, 135, 136, 137, 138], "morn": [59, 84], "mosr": 137, "most": [4, 8, 11, 16, 32, 41, 44, 46, 48, 53, 55, 57, 68, 73, 81, 91, 95, 101, 120, 123, 128, 130, 131, 132, 135, 136, 137, 138], "mostli": [124, 132], "motiv": 3, "mount": 46, "move": [5, 13, 20, 21, 46, 52, 62, 63, 68, 76, 78, 80, 88, 98, 124, 126, 131, 132, 135, 136, 137], "mpiproc": 121, "mr": 138, "mro": 134, "msg": [37, 40], "msub": 115, "much": [4, 15, 21, 44, 75, 95, 123], "muddi": 21, "multi": [6, 19, 23, 42, 44, 46, 48, 52, 54, 55, 78, 120, 130, 134, 135, 138], "multilin": [45, 46], "multipl": [0, 11, 15, 17, 20, 21, 23, 33, 37, 40, 42, 43, 44, 45, 46, 48, 52, 55, 63, 65, 68, 70, 78, 80, 92, 93, 95, 101, 106, 121, 124, 126, 127, 129, 134, 135], "multipli": [46, 50, 52, 74], "must": [4, 7, 11, 13, 16, 18, 20, 21, 23, 27, 28, 29, 35, 39, 40, 41, 43, 44, 45, 46, 48, 52, 53, 67, 71, 76, 80, 87, 93, 101, 104, 111, 118, 121, 122, 125, 126, 128, 129, 130, 131, 132, 133, 135], "mutat": [41, 48, 51], "mutual": [60, 105, 135], "mv": 126, "my": [7, 13, 26, 27, 35, 40, 44, 48, 52, 53, 81, 93, 94, 121, 126, 128, 130, 131, 134, 135], "my_clock_trigg": 59, "my_custom_platform": 121, "my_env": 123, "my_environ": 123, "my_error": 52, "my_ex": 52, "my_funct": 123, "my_handl": 28, "my_hpc": 21, "my_in": 126, "my_lib_path": 123, "my_out": 126, "my_output": 52, "my_packag": 36, "my_platform": [28, 107], "my_plugin": [27, 35], "my_script": 52, "my_startup_coroutin": 35, "my_str": 128, "my_task": [28, 113, 114, 115, 116, 117, 118, 123, 138], "my_trigg": 52, "my_workflow": [21, 24, 73], "my_xtrigg": [44, 126], "my_xtrigger_fcn": 126, "myfil": [52, 129], "myflow": [53, 93, 96], "myhandl": 28, "myhost": [14, 46], "myhosta": 28, "myhostb": 28, "myitem": 52, "mynam": 129, "mynum": 52, "myparamet": 52, "myplatform": [113, 114, 115, 116], "myriad": 137, "mystr": 128, "mytask": [11, 44, 53, 81, 103, 130], "mytask_big_serv": 11, "mytask_cylc_serv": 11, "mytask_login_to_hpc_and_submit": 11, "mytask_submit_local_to_remote_comput": 11, "mytrigg": 50, "myworkflow": [88, 94], "n": [4, 15, 19, 20, 21, 27, 40, 46, 52, 58, 59, 62, 94, 100, 108, 121, 123, 126, 128, 132, 134], "n_dataset": 126, "n_member": 128, "nake": 21, "name": [1, 3, 7, 8, 11, 16, 21, 23, 24, 27, 28, 29, 35, 37, 39, 40, 41, 43, 44, 45, 46, 48, 52, 53, 55, 57, 58, 62, 64, 68, 69, 71, 73, 74, 76, 78, 81, 87, 104, 107, 109, 118, 121, 122, 124, 126, 127, 128, 132, 134, 135, 136, 137], "namespac": [4, 11, 14, 20, 21, 27, 35, 37, 44, 46, 52, 53, 57, 103, 105, 107, 121, 123, 124, 126, 128, 130, 131, 132, 134, 135, 137, 138], "namespace_hierarchi": 28, "nano": 124, "nanorc": 124, "nasti": 123, "nation": 67, "nativ": 135, "nato": 76, "natur": [44, 54, 101, 120, 125, 126, 138], "navig": [44, 48, 73], "ncpu": [121, 128], "nearest": 50, "necessari": [28, 40, 44, 45, 46, 48, 52, 60, 77, 101, 104, 121, 124, 126, 130, 132, 134, 137], "necessarili": [16, 76, 80], "need": [2, 3, 4, 5, 6, 7, 9, 11, 13, 15, 16, 19, 21, 23, 29, 41, 44, 45, 46, 48, 49, 52, 53, 60, 62, 63, 64, 65, 67, 71, 73, 74, 76, 78, 81, 87, 91, 93, 94, 101, 103, 107, 120, 121, 123, 124, 125, 126, 128, 129, 130, 131, 132, 133, 134, 135, 137, 138], "neg": [10, 52, 126, 129], "negat": [48, 51], "neither": [53, 93, 120], "nest": [5, 20, 39, 45, 49, 62, 78, 93, 124, 126, 130, 134, 138], "netcdf": 135, "network": [37, 39, 40, 46, 52, 53, 54, 55, 56, 65, 74, 76, 97, 120, 121, 122, 123, 135], "never": [52, 64, 77, 81, 88, 123, 132, 133], "nevertheless": 120, "new": [0, 1, 3, 4, 6, 7, 8, 11, 12, 15, 16, 21, 24, 25, 28, 29, 42, 44, 46, 54, 58, 59, 60, 62, 63, 64, 65, 67, 68, 71, 73, 74, 75, 76, 78, 80, 81, 86, 87, 88, 93, 94, 95, 98, 101, 102, 104, 105, 107, 109, 121, 123, 124, 126, 128, 129, 130, 131, 132, 134, 135, 137, 138], "new_err": 28, "new_out": 28, "newark": [125, 128], "newer": [23, 52, 126], "newli": 74, "newlin": 28, "newrand": 63, "newyork": [125, 128], "next": [0, 8, 21, 41, 45, 50, 52, 59, 62, 63, 65, 69, 70, 71, 73, 74, 76, 78, 80, 94, 95, 101, 102, 120, 123, 126, 128, 129, 130, 132, 138], "next_cycl": 52, "nf": 46, "ngroups_max": 48, "ni": 58, "nice": 128, "nich": 58, "nine": 138, "niwa": [20, 67, 137], "niwa_arch": 137, "niwa_hpc": 137, "niwa_loadleveler_platform": 137, "nobodi": 45, "node": [11, 17, 20, 21, 28, 46, 67, 107, 115, 116, 118, 123, 126], "node_1": 21, "node_2": 21, "nodej": 23, "nohostserror": [37, 38], "nomin": 21, "non": [21, 22, 24, 28, 29, 37, 46, 52, 68, 77, 78, 95, 107, 120, 121, 122, 123, 124, 126, 128, 130, 135, 136, 137], "none": [18, 27, 28, 35, 37, 39, 40, 48, 52, 101, 126, 128, 130, 132, 134], "noplatformserror": [37, 38], "noqa": 124, "nor": [93, 120], "normal": [21, 29, 32, 46, 52, 53, 73, 74, 86, 87, 94, 95, 99, 104, 107, 120, 121, 123, 126, 130, 132, 133, 135, 137], "northernmost": 76, "not_converg": 85, "notat": [20, 21, 45, 49, 78, 126, 128, 129], "note": [4, 6, 10, 11, 20, 28, 35, 40, 41, 44, 48, 51, 52, 53, 59, 60, 62, 63, 74, 80, 91, 92, 93, 104, 123, 126, 128, 129, 130, 131, 134, 135, 136, 137], "noteworthi": 20, "noth": [40, 60, 73, 85, 101, 131, 132, 134], "notic": [21, 59, 60, 73, 101, 126], "notif": [46, 52, 63, 126, 130], "notifi": [123, 126, 130], "notsingleitemerror": [37, 38], "now": [3, 4, 5, 7, 8, 12, 13, 18, 20, 24, 41, 46, 50, 52, 53, 58, 59, 60, 62, 63, 64, 67, 71, 73, 74, 78, 80, 93, 94, 95, 104, 121, 124, 126, 128, 129, 130, 135], "nowcast": 76, "ntask": 74, "nudg": 3, "null": [121, 132, 134], "num": [21, 52, 73], "number": [12, 18, 20, 21, 23, 24, 28, 29, 31, 37, 39, 44, 45, 46, 50, 51, 52, 53, 57, 59, 63, 64, 65, 74, 76, 78, 80, 81, 83, 86, 87, 91, 100, 103, 104, 106, 118, 121, 123, 124, 126, 128, 129, 130, 132, 134, 135, 137, 138], "numer": [46, 74, 129, 135], "nw": 76, "nwp": [52, 93], "nwp1623": 137, "o": [13, 22, 46, 48, 120, 121, 132, 134, 135, 137], "ob": [128, 129, 134], "obatchmod": 46, "object": [28, 31, 33, 37, 40, 41, 128], "obs1": 134, "obs2": 134, "obs3": 134, "obs4": 134, "obs5": 134, "obs_get": 129, "obs_proc": 129, "obs_radar": 138, "obs_sond": 138, "obs_typ": 128, "observ": [68, 69, 70, 71, 73, 74, 132], "obsolet": [5, 52, 104, 124], "obsproc": 134, "obtain": [39, 91, 124], "obvious": [64, 121, 137], "occas": 93, "occasion": [65, 135], "occur": [3, 7, 16, 21, 46, 52, 120, 123, 130, 131], "occurr": 132, "oconnecttimeout": 46, "odd": 80, "off": [1, 4, 12, 21, 29, 46, 52, 60, 62, 63, 74, 81, 86, 87, 88, 90, 91, 95, 120, 123, 127, 129, 130, 131, 132, 134, 137], "offer": 69, "offic": [67, 136, 137], "offici": [44, 137], "offlin": [43, 123], "offload": [53, 93], "offset": [1, 10, 21, 50, 52, 59, 76, 77, 80, 126, 127, 128, 130, 132, 135], "offset_month": 129, "ofsprei": 62, "often": [44, 45, 46, 49, 52, 70, 74, 75, 78, 80, 88, 106, 107, 108, 126, 128, 132], "oh": [52, 120], "ok": [28, 46, 130, 132], "old": [0, 3, 4, 5, 6, 20, 46, 52, 62, 81, 124, 126, 132, 134], "older": [46, 52, 118, 119, 121, 126], "oldest": [21, 52, 132], "oliv": 20, "oliverh": 20, "omiss": 52, "omit": [39, 52, 53, 76, 93, 126, 127, 129], "ompthread": 121, "on_": [125, 128], "onc": [4, 7, 17, 21, 44, 46, 52, 53, 59, 60, 64, 65, 68, 74, 76, 77, 78, 81, 82, 95, 101, 106, 121, 123, 124, 126, 127, 129, 132, 134, 135, 137], "one": [11, 20, 21, 24, 28, 33, 35, 36, 41, 44, 45, 46, 52, 53, 54, 55, 59, 60, 62, 63, 64, 65, 68, 71, 73, 74, 76, 77, 78, 80, 88, 90, 91, 93, 94, 95, 97, 102, 106, 107, 118, 120, 123, 125, 126, 128, 129, 130, 131, 132, 133, 135, 137, 138], "ones": [68, 78, 96, 101, 104, 130, 132], "ongo": 135, "onli": [3, 4, 7, 8, 11, 12, 15, 17, 18, 21, 23, 28, 32, 36, 41, 43, 44, 45, 46, 48, 51, 52, 53, 55, 59, 60, 64, 65, 68, 71, 73, 74, 76, 93, 94, 95, 96, 101, 102, 103, 104, 105, 106, 109, 120, 121, 122, 123, 124, 126, 128, 129, 130, 132, 133, 135, 137], "onto": [41, 48, 53, 55, 76, 93, 123], "onward": [76, 104, 132], "oop": 130, "oopsi": 130, "op": 138, "open": [19, 41, 44, 46, 48, 59, 60, 63, 68, 73, 74, 92, 107, 123, 128], "open_restaur": 64, "oper": [4, 11, 32, 37, 40, 48, 51, 52, 76, 77, 78, 81, 91, 93, 107, 122, 124, 126, 130, 131, 132, 133, 135, 136, 138], "opportun": [94, 132], "oppos": [23, 35, 80], "opposit": 16, "ops_": 138, "ops_task": 138, "opt": [23, 24, 27, 137], "option": [0, 1, 4, 6, 7, 9, 14, 15, 18, 19, 21, 23, 27, 28, 35, 36, 37, 40, 44, 45, 46, 48, 50, 51, 52, 53, 54, 55, 60, 62, 68, 69, 73, 74, 76, 80, 94, 96, 102, 104, 120, 121, 122, 123, 124, 126, 127, 129, 131, 135, 136, 138], "optpars": 27, "oracl": 117, "orang": 126, "orca": 130, "orchestr": [22, 40, 67, 86, 87, 95], "order": [4, 7, 15, 21, 29, 40, 46, 48, 52, 59, 62, 63, 64, 67, 69, 76, 78, 80, 99, 120, 121, 126, 129, 130, 131, 132, 134, 135, 138], "ordin": 132, "org": 28, "organ": [53, 54, 67, 95], "organis": [21, 54, 107], "orient": 0, "origin": [12, 21, 37, 52, 67, 76, 93, 101, 104, 123, 135, 137], "orphan": [21, 92, 104], "osprei": 62, "other": [12, 19, 21, 23, 27, 35, 37, 40, 41, 43, 44, 46, 47, 51, 52, 53, 56, 60, 65, 67, 68, 73, 74, 80, 93, 94, 99, 101, 104, 106, 109, 110, 120, 121, 123, 124, 127, 128, 129, 130, 131, 132, 133, 134, 135, 137, 138], "other_var": 137, "otherwis": [4, 8, 16, 21, 37, 46, 48, 52, 65, 74, 98, 102, 108, 113, 114, 115, 116, 117, 118, 122, 128, 130, 135, 137], "our": [52, 53, 59, 63, 64, 67, 75, 76, 80, 93, 132, 135], "our_clust": 11, "ourselv": 80, "out": [1, 7, 8, 10, 15, 20, 21, 23, 28, 33, 37, 39, 44, 46, 48, 52, 53, 68, 69, 70, 71, 73, 74, 75, 80, 82, 93, 96, 104, 106, 113, 114, 115, 116, 117, 118, 120, 121, 123, 126, 129, 130, 131, 132, 134, 135, 136, 137, 138], "out1": [21, 52, 63, 132], "out2": [21, 52, 132], "outag": [52, 65, 135], "outcom": [21, 52, 60, 132], "outer": 128, "outlin": [46, 55, 62, 76], "output": [1, 3, 4, 9, 15, 21, 23, 28, 46, 52, 54, 60, 62, 63, 68, 73, 77, 82, 85, 92, 101, 102, 103, 104, 105, 108, 109, 120, 121, 123, 126, 127, 128, 130], "outsid": [3, 7, 128, 137], "oven": 80, "over": [21, 23, 33, 39, 46, 48, 52, 54, 55, 62, 65, 70, 71, 81, 83, 84, 85, 86, 87, 88, 104, 106, 120, 121, 122, 123, 124, 126, 128, 129, 130, 134, 135, 136, 137, 138], "overhead": [86, 87], "overlap": [23, 132, 134], "overload": [46, 74], "overrid": [3, 24, 28, 32, 40, 46, 48, 52, 62, 68, 76, 94, 98, 104, 110, 123, 124, 132, 134, 135, 137], "overridden": [40, 46, 48, 52, 93, 121, 128, 129, 132], "overus": 135, "overview": 52, "overwhelm": [52, 64, 132, 135], "overwrit": [45, 123], "overwritten": [21, 62, 78], "own": [8, 11, 21, 28, 43, 48, 52, 71, 76, 77, 95, 103, 121, 124, 126, 130, 132, 135, 138], "owner": [4, 14, 20, 48, 51, 52, 131, 137], "p": [46, 52, 53, 64, 65, 76, 80, 81, 84, 87, 94, 123, 126, 129, 132, 134, 135], "p0": [52, 132, 135], "p003": 129, "p004": 129, "p013": 129, "p014": 129, "p0d": 132, "p0y": [76, 132], "p1": [21, 76, 80, 83, 85, 87, 101, 104, 126, 132], "p15d": 132, "p1d": [5, 21, 50, 52, 59, 76, 84, 86, 87, 117, 126, 129, 132, 135, 137], "p1dt1h": 76, "p1h": 132, "p1m": [50, 86, 87, 132], "p1w": 132, "p1y": [50, 52, 76, 88, 126, 128, 129, 132, 135, 137], "p1y1m1dt1h1m1": 76, "p2": [52, 76, 80, 104, 132], "p2d": [132, 135], "p2m": [63, 129, 132], "p2w": 132, "p2y": [50, 123, 132], "p3": [21, 52, 80], "p366d": 132, "p3d": [21, 52, 132], "p3m": 129, "p3y": [50, 123], "p4": [52, 132], "p4m": 129, "p4y": [76, 132], "p5": [50, 52, 80, 87, 132], "p5d": 132, "p5y": 123, "p6": 132, "p8m": 52, "pack": 135, "packag": [19, 20, 23, 36, 51, 56, 123, 125, 126], "packjob": [118, 119], "packjob_0_": 118, "pad": 128, "page": [19, 23, 44, 46, 74, 135, 138], "pai": 124, "pair": [11, 40, 45, 52, 53, 70, 78, 97, 128, 132, 138], "panel": 42, "paragraph": 138, "parallel": [35, 52, 86, 87, 126, 132, 134, 137], "param": 134, "param_var": 28, "paramet": [9, 21, 28, 37, 39, 40, 48, 50, 52, 69, 92, 95, 124, 126, 127, 128, 130, 134, 135, 137], "parameter": [21, 52, 69, 72, 126, 127, 128, 135], "paramexpanderror": [37, 38], "parent": [21, 29, 40, 46, 52, 80, 101, 104, 120, 127, 134], "parenthes": [132, 137], "parentless": [52, 126], "pars": [1, 4, 18, 21, 37, 39, 48, 50, 69, 81, 103, 104, 123, 124, 126, 128, 135, 138], "parsec": 37, "parsecerror": [37, 38], "parser": [37, 52], "part": [5, 10, 24, 40, 48, 52, 53, 68, 76, 80, 81, 93, 101, 120, 123, 129, 132, 135, 136, 137, 138], "partial": [4, 6, 10, 21, 63, 108, 127, 132], "particular": [7, 21, 55, 60, 67, 69, 76, 77, 94, 120, 126, 129, 130, 131, 132], "particularli": [44, 63, 64, 74, 104, 123, 132, 134, 135], "partit": 132, "partli": 132, "partnership": 67, "pass": [5, 18, 21, 27, 28, 40, 44, 46, 48, 52, 59, 84, 86, 87, 88, 101, 104, 120, 126, 127, 128, 130, 131, 132, 135], "passphras": 126, "passwordless": 131, "passx12334a": 126, "past": [52, 59, 60, 62, 63, 64, 65, 76, 78, 106, 132], "pasta": 64, "pasta1": 64, "pasta2": 64, "pasta3": 64, "path": [1, 6, 7, 13, 16, 21, 23, 26, 27, 28, 37, 39, 44, 45, 46, 52, 53, 57, 63, 68, 69, 72, 74, 76, 78, 81, 86, 87, 93, 94, 101, 105, 120, 121, 123, 124, 126, 129, 130, 131, 132, 136, 138], "pathlib": 27, "pathtyp": 51, "pathwai": [105, 131], "pattern": [21, 28, 39, 40, 44, 46, 48, 53, 67, 85, 86, 87, 88, 89, 91, 93, 95, 96, 124, 130, 131, 135], "paus": [3, 4, 9, 20, 21, 39, 44, 48, 51, 73, 81, 94, 104, 123], "pb": [11, 21, 28, 46, 52, 74, 115, 120, 124, 137], "pb_data_el": 40, "pb_entire_workflow": 40, "pbs_cluster": 53, "pbs_local": 11, "pbs_multi_clust": 124, "pbshandler": 28, "pdb": 128, "pdf": [31, 32, 33], "pencil": [0, 94], "pend": [20, 21, 44, 108, 126, 132], "penny_farth": 62, "pep": 39, "pep440": 51, "pep8": 135, "per": [20, 21, 36, 41, 44, 46, 48, 53, 73, 74, 93, 97, 104, 107, 126, 131, 132, 137, 138], "percent": [126, 129, 130, 131], "perform": [3, 16, 19, 30, 35, 44, 46, 48, 81, 94, 104, 122, 124, 126, 130, 132, 134, 135, 138], "perhap": [63, 101, 120, 137], "period": [21, 29, 34, 35, 46, 65, 76, 107, 108, 126, 131, 132], "perl": 138, "permiss": [19, 41, 43, 46, 51], "permit": [21, 24, 48, 51, 52, 69, 93, 124], "persist": [52, 98, 104, 106, 122, 126, 132], "person": 48, "perspect": [131, 135, 137], "pertain": 131, "petrol": 62, "philadelphia": [125, 128], "phonet": 76, "phrase": 82, "physic": 28, "pi": [129, 138], "pick": [1, 11, 12, 20, 21, 39, 46, 51, 55, 74, 104, 120, 123, 131], "pictur": 76, "pid": [20, 28, 121, 130], "ping_workflow": 40, "pink": 106, "pip": [55, 73, 125], "pipe": [28, 39, 110, 128, 135], "pipefail": [120, 123, 135], "pipelin": [95, 120, 132], "pizza": [62, 64], "pizza1": 64, "pizza2": 64, "pizza3": 64, "pizza4": 64, "place": [4, 6, 12, 21, 27, 33, 35, 37, 51, 55, 63, 71, 76, 81, 96, 101, 104, 107, 121, 124, 125, 130, 134, 135, 137, 138], "placehold": [21, 87, 130, 132], "plai": [1, 3, 6, 7, 9, 18, 20, 21, 24, 33, 35, 44, 46, 48, 51, 52, 53, 58, 59, 60, 63, 64, 65, 73, 74, 81, 88, 101, 103, 104, 105, 123, 124, 126, 128, 131, 132], "plain": 50, "plan": [0, 44, 94, 106, 129, 134, 137], "plane": [62, 129], "planet": 124, "platform": [6, 7, 9, 21, 23, 28, 37, 41, 46, 47, 52, 56, 74, 94, 96, 104, 105, 106, 107, 113, 114, 115, 116, 117, 118, 120, 121, 124, 126, 128, 132, 135, 137], "platform_a": 46, "platform_nam": [37, 124, 130], "platform_using_pb": 128, "platform_with_at": 121, "platform_with_loadlevel": 121, "platformerror": [37, 38], "platformlookuperror": [37, 38], "player": [12, 81], "pleas": [2, 3, 52, 123, 126, 136], "plot": [31, 32, 33, 44, 52, 134], "plu": [21, 50, 52, 76, 128, 135, 137], "plugin": [7, 22, 23, 24, 31, 32, 33, 34, 37, 43, 46, 52, 93, 123, 124, 126, 131, 138], "plugin_nam": 37, "plugin_set_var": 27, "plugin_st": 35, "pluginerror": [37, 38], "pn": 52, "png": [0, 52, 135], "poach": 126, "point": [1, 3, 4, 5, 6, 15, 20, 21, 23, 24, 27, 35, 36, 37, 40, 46, 50, 51, 52, 53, 57, 58, 59, 63, 68, 71, 73, 74, 77, 78, 79, 80, 81, 83, 84, 85, 87, 89, 91, 93, 94, 95, 96, 98, 99, 100, 101, 103, 105, 106, 121, 124, 125, 126, 127, 128, 129, 130, 136, 137], "pointer": 136, "pointparsingerror": [37, 38], "polici": 48, "poll": [11, 28, 42, 46, 48, 52, 53, 54, 63, 99, 100, 110, 120, 122, 123, 124, 126, 130, 131, 136], "poll_cant_connect_err": 28, "poll_cmd": 28, "poller": 126, "pollut": 138, "pool": [8, 46, 51, 54, 126, 127, 130], "popen": 28, "popul": 37, "port": [21, 24, 40, 46, 52, 97, 103, 104, 107, 123, 130, 131], "portabl": [22, 124, 128, 135, 136], "posit": [21, 52, 126, 129, 132], "posix": [21, 46, 52], "possibl": [0, 3, 4, 6, 12, 19, 21, 24, 28, 37, 41, 43, 44, 46, 48, 52, 59, 60, 68, 73, 77, 88, 93, 96, 99, 101, 104, 107, 120, 122, 123, 128, 129, 130, 132, 135, 137, 138], "possibli": [121, 132], "post": [2, 3, 22, 25, 28, 52, 62, 68, 71, 101, 102, 120, 123, 126, 128, 129, 134, 135, 137], "post_": 128, "post_0": 128, "post_1": 128, "post_2": 128, "post_3": 128, "post_4": 128, "post_proc": 129, "post_proc_r1": 129, "post_process": 71, "post_process_": 76, "post_process_exet": [68, 71, 74, 76], "postproc": [57, 130, 135, 137], "postprocess": [101, 135], "potenti": [21, 107, 120, 123, 132], "power": [3, 86, 87, 123, 125, 132], "powerful_comput": 74, "practic": [2, 3, 46, 52, 69, 75, 124, 136], "pre": [4, 15, 21, 22, 25, 28, 43, 51, 52, 54, 62, 80, 81, 94, 120, 123, 126, 129, 132, 133, 134, 135, 137], "pre_heat_oven": [78, 80], "preced": [23, 48, 51, 52, 76, 88, 126, 130, 134, 138], "precis": [52, 120], "predat": 8, "predefin": 126, "preempt": [99, 113], "preemption": [92, 100], "prefer": [37, 39, 63, 104, 107, 123, 124, 125, 126, 132, 134, 135], "prefix": [28, 52, 71, 76, 118, 119, 123, 128, 130, 133], "preload": 63, "prematur": 28, "prep": [5, 126, 129, 130, 132, 138], "prep1": 132, "prep2": 132, "prepackag": 51, "prepar": [21, 44, 52, 73, 75, 93, 106, 123], "prepend": [23, 51, 52, 63, 73, 123], "preproc": 137, "preprocess": 124, "prereq": 94, "prerequisit": [3, 17, 21, 54, 92, 101, 106, 108, 123, 126, 132], "presenc": 39, "present": [0, 6, 12, 24, 30, 37, 41, 46, 52, 53, 68, 71, 76, 93, 95, 96, 108, 123, 126, 129, 132, 133], "preserv": [52, 104, 130, 131], "preset": 46, "press": [0, 73, 74, 94], "presum": [52, 132], "prevent": [21, 29, 46, 48, 52, 63, 71, 81, 84, 87, 94, 102, 106, 120, 121, 123, 128, 132], "previou": [12, 15, 21, 52, 53, 68, 69, 73, 74, 76, 80, 83, 84, 91, 93, 101, 104, 121, 125, 126, 129, 130, 132], "previous": [7, 20, 21, 45, 46, 52, 104], "primari": [69, 130], "primarili": [21, 73, 103, 135], "principl": [22, 136], "print": [3, 21, 39, 50, 59, 69, 73, 120, 123, 124, 126, 128, 130, 134, 135], "printf": [28, 59, 123], "prior": [4, 21, 23, 46, 78, 104, 129, 132, 135], "prioriti": [46, 51, 52, 99], "privat": [97, 109, 130, 135], "privileg": [42, 43, 48, 51], "pro": 135, "probabl": [37, 94, 120, 123], "problem": [5, 21, 46, 52, 62, 63, 74, 76, 80, 81, 86, 87, 88, 92, 94, 104, 120, 121, 126, 132, 135, 137], "proc": [21, 120, 126, 129, 132], "proc1": [126, 132], "proc2": [126, 132], "proc3": 132, "proc_big": 129, "proc_buoi": 129, "proc_file0": 129, "proc_file1": 129, "proc_hug": 129, "proc_plan": 129, "proc_ship": 129, "proc_smal": 129, "proc_stdin_arg": 28, "proc_stdin_valu": 28, "proce": [41, 135], "procedur": 6, "proceed": 44, "process": [4, 13, 17, 20, 21, 23, 24, 28, 29, 40, 41, 46, 51, 52, 53, 54, 57, 67, 68, 70, 71, 73, 74, 77, 81, 85, 91, 92, 95, 101, 103, 104, 106, 110, 112, 121, 122, 123, 124, 125, 126, 128, 129, 130, 131, 132, 134, 135, 137], "process_file_1": 132, "process_scatwind": 138, "processor": [54, 124, 125, 128, 135, 138], "prod": 126, "prod1": 101, "prod2": 101, "produc": [24, 44, 63, 74, 77, 103, 132, 135], "product": [48, 52, 101, 120, 126, 128, 137], "product_dir": 126, "prof": 51, "profil": [33, 46, 51, 92], "program": [21, 23, 28, 46, 72, 95, 104, 121, 124, 135, 138], "programmat": [27, 124, 125, 128, 129, 130], "progress": [17, 21, 46, 107, 123, 131], "prohibit": 107, "project": [36, 53, 55], "prolept": [52, 132], "pronounc": [67, 95], "proof": 20, "propag": [21, 128], "proper": 135, "properli": [27, 35, 107, 123, 134], "properti": [54, 106, 121, 124, 125, 126, 128], "proport": 106, "protect": [97, 120, 131, 132, 137], "protobuf": 40, "protocol": [40, 42, 107], "prototyp": 52, "prove": 42, "provid": [0, 3, 4, 5, 7, 11, 15, 20, 21, 23, 24, 25, 27, 28, 35, 37, 39, 40, 41, 42, 43, 44, 46, 48, 52, 55, 57, 58, 59, 63, 67, 68, 71, 72, 74, 78, 86, 87, 91, 93, 94, 95, 104, 107, 109, 113, 114, 115, 116, 117, 118, 120, 123, 124, 125, 126, 128, 130, 132, 134, 135, 136], "proxi": [23, 42, 43, 55, 129], "ps1": 123, "pseudo": 132, "psutil": 46, "pt0": [126, 130], "pt0h": [126, 132], "pt0m": 135, "pt1": 52, "pt10": [50, 52, 126, 130], "pt10m": [46, 65, 74, 107, 113, 114, 135], "pt12h": [21, 76, 132, 135], "pt13h": 132, "pt15": 65, "pt15m": [46, 59, 74], "pt1d": [128, 132], "pt1h": [46, 50, 52, 58, 59, 65, 76, 77, 86, 87, 91, 118, 121, 126, 128, 132], "pt1h30m": [21, 52, 76], "pt1h_trigger": 77, "pt1m": [28, 46, 50, 52, 107, 115, 116, 120, 121, 128], "pt2h": [91, 132], "pt2m": [46, 52, 121], "pt30": [52, 105, 130], "pt30m": [46, 59, 74, 128, 135], "pt3h": [58, 65, 69, 70, 71, 76, 126, 132], "pt40m": 130, "pt45m": 59, "pt48h": 135, "pt5": [123, 126], "pt5m": [35, 46, 52, 132, 135], "pt6": 65, "pt6h": [50, 52, 74, 76, 95, 132], "pt7h": 74, "pt7m": [46, 121], "pt8h": 132, "ptang": 58, "pub": [21, 29, 71], "public": [46, 97, 109, 126], "publish": [40, 55, 101], "publish_queued_item": 40, "pull": 123, "purchas": 80, "purpos": [41, 43, 51, 57, 67, 85, 126, 129, 130, 134, 135], "push": [41, 42, 52, 123, 127], "put": [24, 52, 64, 68, 70, 79, 81, 113, 123, 126, 128, 132, 135, 137, 138], "pwd": [1, 20, 21, 52, 93, 126, 130, 135], "pxty": 132, "py": [27, 28, 35, 36, 48, 51, 73, 128, 130], "py_modul": [27, 35], "pycharm": 124, "pympler": 33, "pypi": [20, 23], "pyproject": [36, 124], "pyro": 54, "python": [9, 20, 21, 22, 27, 28, 35, 36, 40, 42, 46, 50, 51, 52, 54, 55, 70, 73, 74, 93, 103, 109, 123, 124, 125, 126, 127, 130, 131, 135], "python3": 28, "pythonpath": [27, 28, 35, 52, 72, 124, 130, 131], "q": [28, 114, 115, 116, 117, 132], "q_foo": 132, "qcat": [46, 121], "qstat": 121, "qsub": [28, 53, 116, 117, 120, 121], "qsubhandl": 28, "qualifi": [21, 60, 63, 68, 79, 123, 126, 132, 134], "quarter": 59, "quarter_past": 59, "quarter_past_trigg": 59, "quarter_to": 59, "quarter_to_trigg": 59, "queri": [21, 39, 41, 73, 122, 137], "question": [2, 21, 75, 128], "queu": [40, 44, 52, 106, 132, 133], "queue": [20, 21, 32, 41, 44, 52, 61, 66, 99, 101, 106, 113, 121, 127], "quick": [1, 2, 3, 22, 45, 48, 73, 81, 126, 131, 137, 138], "quicker": 135, "quickli": [23, 46, 52, 81, 94, 95, 126, 130, 131], "quietli": 63, "quit": [46, 135, 137], "quot": [18, 45, 52, 81, 96, 128, 130, 131, 138], "quota": 123, "qux": [21, 45, 71, 113, 126, 132, 138], "qxz5w2": 118, "r": [5, 21, 52, 58, 123, 129, 138], "r1": [4, 5, 7, 21, 24, 28, 45, 52, 58, 60, 62, 63, 64, 65, 71, 76, 78, 80, 82, 88, 120, 126, 128, 129, 130, 132, 134, 135, 137, 138], "r2": 132, "r3": 132, "r44": 62, "r5": 132, "rack": 21, "radar": 76, "radial": 17, "radiosond": 134, "rainfal": [68, 70, 73, 74, 76], "rainfall_fil": 68, "rais": [35, 37, 40, 52, 126, 127, 130, 131, 132, 137], "ram": [46, 74], "ran": [7, 13, 24, 73, 74, 96, 101, 104, 123], "randint": 126, "random": [29, 46, 52, 58, 60, 63, 65, 91, 126, 132], "randomli": [46, 58, 60, 132], "rang": [10, 21, 46, 50, 70, 80, 127, 128, 134, 138], "rank": [46, 131], "rare": [21, 133], "rate": 101, "rather": [3, 6, 12, 18, 20, 21, 24, 41, 46, 52, 55, 59, 63, 68, 69, 70, 73, 88, 94, 103, 120, 121, 123, 126, 130, 131, 132, 134, 135, 137, 138], "raw": [52, 126], "rc": [0, 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, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138], "re": [0, 1, 3, 7, 17, 20, 21, 28, 35, 37, 39, 51, 53, 58, 62, 65, 73, 81, 86, 87, 88, 92, 93, 101, 103, 107, 110, 120, 121, 123, 124, 130, 132, 138], "reach": [21, 34, 46, 52, 59, 60, 73, 74, 75, 104, 120, 121, 126, 132], "reachabl": 37, "react": 135, "read": [3, 4, 6, 18, 20, 21, 24, 27, 28, 35, 37, 39, 46, 48, 51, 52, 53, 56, 58, 59, 63, 69, 71, 73, 81, 87, 90, 91, 96, 104, 121, 122, 124, 126, 128, 135], "read_data": 135, "read_text": 27, "readabl": [76, 78, 123, 125, 138], "reader": [27, 109], "readi": [4, 20, 21, 46, 52, 63, 73, 86, 87, 93, 94, 106, 120, 121, 124, 126, 130, 135], "readm": 26, "real": [17, 21, 27, 52, 54, 59, 76, 77, 84, 91, 95, 105, 106, 121, 126, 130, 132, 135, 136], "realist": 132, "realiti": [11, 28], "realli": [126, 134, 135], "reason": [23, 34, 37, 40, 46, 52, 65, 74, 107, 108, 122, 124, 125, 128, 129, 130, 131, 135], "reboot": 121, "rec_id_from_submit_err": 28, "rec_id_from_submit_out": 28, "recal": 73, "receiv": [21, 40, 41, 52, 86, 87, 103, 120, 121, 122, 126, 130], "recent": [32, 55, 73, 91, 101, 128], "recogn": [122, 126], "recognis": [78, 104], "recommend": [7, 11, 20, 21, 28, 36, 46, 52, 53, 55, 73, 75, 88, 93, 96, 120, 123, 124, 126, 129, 132, 134, 135, 137, 138], "reconfigur": 134, "record": [21, 24, 26, 27, 63, 73, 93, 96, 99, 103, 104, 105, 109, 121, 123], "recov": [16, 67, 120, 132], "recoveri": [120, 132, 136], "rectifi": [101, 132], "recurr": [21, 52, 54, 58, 79, 88, 124], "recurs": 138, "red": [126, 130], "redefin": [48, 130], "redirect": [121, 126], "redon": [21, 104], "reduc": [51, 53, 60, 81, 132, 134], "redund": 124, "ref": [1, 124], "refactor": [125, 137], "refer": [20, 21, 22, 24, 33, 35, 41, 44, 45, 48, 49, 50, 52, 57, 59, 60, 63, 68, 69, 71, 75, 77, 78, 80, 96, 109, 121, 124, 126, 130, 132, 135, 137, 138], "referenc": [21, 71, 76, 120, 126, 137], "reference_tim": 130, "refin": [0, 54], "reflect": [21, 109, 130, 134, 138], "reformat": 138, "reformul": 132, "refus": 46, "regard": 132, "regardless": [59, 77, 80, 101, 129, 132], "regener": 101, "regex": [11, 39], "region": 91, "region1": 93, "region2": 93, "regist": [3, 27, 35, 36, 40, 41, 44, 52, 87, 126, 132], "register_endpoint": 40, "registr": [3, 39], "regular": [1, 21, 28, 35, 42, 46, 53, 76, 81, 95, 107, 120, 121, 126, 135], "reimplement": [0, 44], "reinstal": [1, 3, 21, 24, 27, 44, 81, 88, 92, 94, 104], "reject": [29, 74, 107], "rel": [21, 39, 40, 45, 52, 76, 77, 93, 126, 130], "relat": [37, 48, 59, 62, 69, 73, 103, 104, 109, 123, 124, 125, 129, 131, 134], "relationship": [109, 124, 137], "relax": 135, "releas": [0, 1, 3, 5, 11, 20, 21, 25, 48, 52, 55, 73, 75, 94, 102, 106, 123, 126, 132, 137], "releaseholdpoint": 48, "relev": [28, 41, 52, 62, 71, 73, 105, 121, 123, 130, 135, 137], "reli": [21, 52, 53, 96, 123, 132, 135], "reload": [3, 20, 21, 24, 48, 52, 81, 88, 92, 94, 100, 123], "remain": [3, 21, 34, 37, 52, 74, 97, 108, 126, 127, 132, 137], "remedi": 135, "rememb": [7, 16, 63, 71, 123], "remind": 132, "remot": [4, 5, 6, 9, 11, 20, 21, 37, 41, 46, 52, 53, 73, 74, 92, 93, 97, 100, 103, 105, 107, 110, 124, 125, 126, 127, 128, 135], "remov": [3, 4, 7, 8, 10, 11, 12, 16, 21, 22, 24, 28, 41, 44, 48, 51, 52, 54, 57, 68, 71, 73, 74, 81, 84, 92, 94, 95, 97, 101, 102, 104, 129, 130, 132, 133, 137, 138], "renam": [3, 5, 13, 20, 52, 126], "render": [74, 81, 135, 138], "renumb": 138, "rep": 40, "repeat": [11, 15, 21, 52, 67, 69, 71, 76, 79, 83, 84, 95, 118, 126, 132, 134, 135, 137], "repeatedli": [21, 46, 52, 107, 120, 126, 132, 135], "repetit": [21, 69, 80, 95, 132], "replac": [0, 3, 4, 5, 7, 11, 19, 20, 23, 24, 44, 46, 52, 54, 70, 71, 74, 86, 87, 105, 109, 121, 123, 124, 126, 130, 132, 138], "replic": 129, "replier": 40, "repo": 26, "report": [21, 28, 31, 32, 33, 46, 52, 60, 63, 104, 107, 109, 111, 120, 121, 123, 126, 135, 137], "repositori": 26, "repres": [11, 17, 20, 21, 37, 48, 52, 53, 59, 62, 67, 76, 78, 106, 110, 124, 126, 132], "represent": [81, 110, 128, 132], "republish": 101, "req": 40, "req_meta": 40, "request": [21, 39, 40, 41, 54, 105, 123, 135, 137], "request_str": 40, "requeu": 99, "requir": [3, 11, 15, 21, 22, 28, 37, 39, 41, 43, 44, 46, 48, 52, 53, 55, 60, 63, 68, 70, 73, 74, 76, 81, 85, 88, 97, 104, 105, 106, 107, 118, 121, 122, 124, 126, 127, 128, 130, 131, 135, 137, 138], "rerun": [65, 100, 104, 135], "research": [48, 67, 136], "resend": 120, "resent": 120, "reserv": [52, 93, 126], "reset": [1, 3, 6, 34, 46, 52, 101, 131], "resid": [51, 122], "resili": 41, "resolut": [52, 68, 130], "resolv": [41, 46, 54, 80, 123, 124], "resort": [46, 107, 123], "resourc": [21, 23, 46, 52, 67, 68, 73, 74, 82, 83, 84, 85, 87, 88, 91, 95, 99, 104, 105, 107, 118, 124, 128, 131, 132, 135, 137], "respect": [48, 62, 128, 130, 132, 134, 135, 137], "respond": [37, 52], "respons": [21, 40, 41, 42, 64, 104, 137], "rest": [48, 54, 132], "restart": [3, 4, 6, 12, 15, 20, 21, 29, 35, 41, 44, 46, 48, 52, 72, 81, 88, 92, 94, 98, 99, 100, 101, 103, 105, 108, 113, 121, 122, 123, 126, 128, 130, 131, 132], "restaur": 64, "restor": [130, 131, 132], "restrict": [20, 48, 52, 122, 132, 136], "resubmiss": 52, "resubmit": [46, 52, 65, 104, 135], "result": [6, 7, 10, 11, 13, 20, 21, 27, 28, 31, 32, 33, 40, 41, 44, 46, 51, 52, 53, 62, 70, 71, 76, 78, 80, 93, 101, 107, 118, 120, 121, 123, 124, 126, 128, 129, 130, 132, 135, 137, 138], "resum": [3, 12, 21, 44, 48, 81, 94, 104, 123], "ret_cod": [28, 37, 123], "retab": 138, "retain": [4, 20, 21, 44, 46, 101, 124, 126, 132], "retri": [17, 20, 21, 46, 52, 57, 61, 66, 72, 92, 100, 105, 106, 120, 124, 126, 127, 132], "retriev": [27, 46, 52, 53, 76, 126, 132], "retrigg": [21, 132, 135], "return": [21, 27, 28, 29, 37, 39, 40, 46, 48, 52, 65, 73, 74, 77, 93, 99, 102, 104, 120, 121, 126, 128, 130, 131, 132, 135], "reveal": 123, "revers": 46, "review": [1, 3, 5, 131, 136, 137], "revis": [26, 138], "rewind": 101, "rf": [1, 126], "rich": 81, "riddl": 137, "right": [6, 8, 21, 46, 62, 73, 74, 76, 94, 101, 120, 126, 132, 134, 135], "ring": 59, "risk": [7, 15, 130, 134, 135], "rm": [1, 12, 52, 58, 96, 126], "rn": 132, "robson": 62, "robust": [44, 130, 135], "role": 23, "roll": [46, 65], "roll_doubl": 65, "root": [14, 20, 21, 26, 28, 52, 57, 59, 62, 83, 84, 95, 121, 123, 124, 126, 127, 128, 134, 135, 137], "rose": [0, 2, 3, 4, 11, 12, 18, 20, 22, 23, 25, 27, 44, 52, 53, 56, 62, 75, 92, 93, 96, 123, 124, 128, 134, 136, 137], "rose2019": 24, "rose_ana": 104, "rose_app_opt_conf_kei": 134, "rose_arch": [135, 138], "rose_data": 135, "rose_datac": 135, "rose_datacp1d": 135, "rose_datacp2d": 135, "rose_orig_host": 24, "rose_prun": [135, 138], "rose_vers": [24, 124], "rosi": 23, "rotor": 62, "rough": 130, "roughli": 121, "round": [50, 137], "rout": [0, 46, 94, 121, 126], "routin": [5, 120], "rsync": [14, 23, 46, 52, 122, 123], "rubric": 46, "rudimentari": 111, "rule": [21, 45, 51, 52, 69, 93, 120, 124, 126, 127, 128, 130, 135, 138], "ruleset": 124, "run": [3, 4, 5, 6, 8, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 35, 37, 39, 40, 42, 43, 44, 46, 48, 50, 52, 53, 54, 55, 57, 58, 59, 60, 62, 63, 64, 66, 67, 68, 69, 72, 74, 77, 78, 80, 82, 83, 84, 85, 86, 87, 89, 90, 91, 92, 96, 97, 98, 99, 101, 102, 103, 104, 106, 107, 108, 110, 111, 112, 113, 118, 120, 121, 122, 124, 125, 126, 128, 129, 130, 131, 132, 133, 134, 137, 138], "run002": 129, "run1": [7, 20, 21, 46, 57, 73, 93, 96, 130], "run2": [7, 21, 73, 93], "run3": [7, 93], "run_dir": [39, 120, 126], "run_len": 135, "run_m": 88, "run_r1": 129, "run_r2": 129, "runahead": [20, 21, 52, 80, 86, 87, 106, 124, 126, 127], "rundir": 27, "runn": [0, 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, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138], "runnabl": 95, "runner": [11, 20, 21, 23, 28, 46, 52, 53, 73, 74, 99, 105, 113, 114, 115, 116, 117, 118, 120, 121, 122, 124, 130, 135], "runtim": [4, 5, 6, 7, 8, 11, 14, 16, 20, 21, 22, 24, 28, 37, 38, 45, 46, 52, 53, 54, 56, 58, 59, 60, 62, 63, 64, 65, 66, 69, 70, 71, 77, 78, 81, 82, 83, 84, 85, 87, 88, 91, 93, 95, 98, 100, 103, 105, 106, 107, 113, 114, 115, 116, 117, 118, 120, 121, 123, 124, 125, 126, 128, 129, 130, 131, 132, 133, 134, 135, 137, 138], "runx": [73, 129], "rwx": 46, "safe": [12, 20, 21, 23, 35, 48, 120, 123], "safeti": [29, 46, 120, 123], "sai": [44, 48, 58, 76, 78, 99, 101, 130, 132, 135], "said": [21, 44, 132], "same": [11, 13, 15, 20, 21, 23, 28, 40, 41, 43, 44, 46, 48, 50, 52, 53, 64, 73, 74, 76, 78, 80, 83, 84, 91, 93, 94, 99, 101, 103, 104, 120, 121, 125, 126, 128, 129, 130, 132, 133, 134, 135, 137, 138], "sane": 23, "santaf": [125, 128], "sat": 126, "satellit": 126, "satisfact": 126, "satisfi": [17, 21, 44, 52, 59, 64, 85, 94, 101, 106, 108, 123, 126, 133, 137], "satsim": 126, "satur": 131, "save": [21, 23, 26, 34, 44, 51, 59, 60, 63, 74, 76, 137, 138], "sbatch": 118, "sbin": 46, "scan": [3, 38, 46, 51, 56, 67, 73, 81, 93, 97], "scan_dir": 39, "scan_interv": 51, "scenario": [48, 94, 104, 132], "schd": [35, 40], "schd_expect": 37, "schedudul": 88, "schedul": [0, 2, 4, 5, 7, 8, 9, 12, 14, 16, 19, 21, 22, 23, 24, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 40, 46, 52, 54, 56, 57, 58, 59, 60, 62, 63, 64, 65, 66, 67, 69, 70, 71, 73, 74, 76, 78, 80, 82, 83, 84, 85, 86, 87, 88, 91, 92, 95, 97, 98, 100, 101, 102, 104, 105, 106, 107, 109, 111, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 133, 134, 135, 137, 138], "schema": [40, 41, 48], "scheme": 41, "scienc": [137, 138], "scientif": [67, 137], "scope": [48, 127], "scratch": [6, 21, 104, 105, 135], "screenshot": 73, "script": [1, 5, 7, 11, 17, 20, 21, 22, 23, 24, 27, 28, 37, 44, 46, 52, 53, 56, 58, 59, 60, 62, 63, 65, 67, 68, 69, 70, 71, 72, 74, 78, 81, 82, 83, 84, 85, 87, 91, 93, 94, 95, 104, 105, 106, 107, 110, 111, 112, 113, 114, 115, 116, 117, 118, 121, 122, 123, 124, 126, 129, 131, 132, 134, 136, 137], "scrutini": 137, "se": 76, "sea": 52, "seamless": 125, "search": [3, 27, 28, 36, 39, 44, 46, 73, 93, 120, 138], "sec": 126, "second": [8, 21, 24, 29, 34, 40, 46, 50, 51, 52, 60, 62, 63, 65, 71, 74, 76, 80, 105, 120, 121, 124, 126, 128, 129, 130, 132, 134], "secondari": 134, "section": [1, 5, 7, 9, 11, 18, 20, 21, 24, 35, 37, 41, 42, 44, 45, 46, 48, 49, 52, 55, 58, 59, 60, 61, 62, 63, 64, 65, 68, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 83, 84, 93, 94, 95, 104, 110, 120, 123, 124, 125, 126, 128, 130, 131, 132, 134, 135, 137, 138], "secur": [2, 23, 42, 43, 46, 53, 54, 104, 107, 122], "sed": [23, 138], "see": [1, 3, 4, 5, 7, 11, 18, 19, 20, 21, 23, 24, 27, 28, 35, 36, 41, 43, 44, 46, 48, 50, 51, 52, 53, 55, 57, 58, 59, 60, 62, 63, 64, 65, 68, 69, 70, 71, 73, 74, 76, 77, 78, 80, 81, 84, 90, 91, 93, 94, 96, 97, 98, 101, 103, 104, 106, 108, 120, 121, 122, 124, 125, 126, 128, 129, 130, 131, 132, 134, 135, 138], "seed": [65, 132], "seen": [46, 62, 63, 74, 78, 80, 125], "select": [0, 11, 19, 20, 21, 29, 37, 44, 46, 52, 53, 58, 74, 98, 109, 121, 123, 124, 127, 134, 136, 137], "selector": [11, 126], "self": [21, 40, 41, 46, 48, 50, 54, 101, 123, 126, 132, 136], "sell": 60, "sell_bread": [60, 78, 80], "sell_diamond": 60, "semant": [129, 134, 137], "semicolon": 132, "send": [21, 28, 40, 41, 46, 52, 63, 99, 120, 123, 126, 130, 131], "sens": [80, 132, 134, 135], "sensibl": [15, 20, 33, 48], "sent": [41, 46, 52, 53, 63, 97, 103, 120, 130, 131, 132], "separ": [7, 10, 11, 19, 20, 21, 37, 44, 45, 46, 50, 52, 62, 65, 73, 76, 103, 104, 120, 121, 125, 126, 128, 130, 132, 135, 137], "seq": [59, 74], "sequenc": [21, 37, 52, 76, 80, 100, 107, 126, 132], "sequencedegenerateerror": [37, 38], "sequenceparsingerror": [37, 38], "sequenti": [52, 127, 129], "seri": [21, 120, 123], "serial": [41, 134, 137], "serial_request": 40, "serialis": 40, "serv": [42, 51], "server": [1, 3, 11, 19, 20, 29, 38, 44, 46, 47, 56, 92, 100, 103, 107, 120, 123, 130, 131], "server_owner2": 48, "server_owner_1": [48, 51], "server_owner_2": 48, "serverapp": 48, "servic": [0, 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, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138], "servicefileerror": [37, 38], "session": [41, 44, 106, 123], "set": [1, 3, 6, 11, 14, 18, 20, 21, 23, 24, 27, 29, 33, 34, 35, 37, 40, 45, 46, 48, 49, 51, 52, 53, 57, 58, 59, 62, 63, 65, 67, 68, 69, 70, 71, 72, 74, 76, 78, 81, 83, 84, 86, 87, 88, 92, 93, 96, 98, 101, 102, 104, 105, 106, 107, 113, 120, 121, 123, 124, 125, 126, 129, 130, 131, 134, 135, 137], "set_trac": 128, "set_typ": 37, "setgraphwindowext": 48, "setholdpoint": 48, "setoutput": 48, "settl": 138, "setup": [7, 19, 23, 27, 35, 36, 37, 42, 48, 53, 55, 75, 105, 123, 125, 128], "setup_foo": 132, "setuptool": [27, 35, 36], "setverbos": 48, "seven": 138, "sever": [20, 52, 73, 74, 93, 103, 104, 120, 124, 125, 126, 129, 130, 132, 133, 134, 135], "sface": 129, "sge": [52, 74, 124], "sge_platform": 117, "sgr": 123, "sh": [26, 52, 63, 120, 126, 130, 135, 137], "shall": 63, "shape": 130, "share": [0, 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, 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, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 131, 132, 133, 136, 137, 138], "shebang": [27, 37, 70, 124], "sheet": [2, 3, 22, 92, 123], "shell": [28, 46, 52, 57, 81, 92, 120, 124, 128, 130, 135], "shetland": [70, 71, 74, 76], "ship": [129, 134], "shipi": 129, "short": [16, 21, 37, 44, 118, 123, 126, 128, 130, 132, 135, 138], "short_fc": 135, "short_timestep": 135, "shorten": 128, "shorthand": [20, 46, 47, 52, 77, 79, 132], "should": [5, 6, 7, 10, 11, 16, 17, 20, 21, 23, 24, 27, 28, 29, 35, 44, 45, 46, 48, 51, 52, 53, 58, 59, 60, 62, 63, 64, 65, 68, 70, 71, 73, 74, 76, 77, 78, 91, 93, 94, 97, 101, 103, 105, 107, 120, 121, 123, 124, 126, 128, 129, 130, 131, 132, 134, 135, 136, 137, 138], "should_kill_proc_group": 28, "should_poll_proc_group": 28, "shouldn": [35, 137], "show": [4, 11, 17, 19, 21, 46, 52, 66, 73, 79, 80, 90, 91, 106, 123, 124, 126, 128, 138], "showdown": 132, "shown": [46, 52, 67, 109, 120, 121, 123, 126, 129, 132, 138], "shut": [21, 30, 31, 32, 33, 46, 52, 74, 81, 88, 101, 104, 108, 131, 132], "shutdown": [12, 21, 29, 35, 46, 52, 73, 104, 122, 124, 130, 131, 132], "si": 21, "side": [3, 21, 41, 42, 44, 60, 121, 132, 135, 138], "sidebar": 74, "sigkil": [99, 121], "sign": [45, 52, 71, 121, 129], "signal": [28, 52, 86, 87, 99, 120, 121, 123, 130], "signatur": [35, 50, 52, 126], "signifi": 134, "signific": [44, 46, 52, 137], "significantli": [33, 132, 137], "sigterm": [99, 120], "sigusr1": [99, 113], "silk": [22, 67, 95], "sim": 134, "similar": [3, 7, 21, 46, 50, 60, 69, 70, 78, 95, 96, 103, 115, 128, 129, 132, 135, 138], "similarli": [73, 80, 81, 129, 132, 135], "simpl": [27, 40, 59, 74, 78, 80, 82, 88, 96, 105, 118, 123, 126, 129, 132, 135], "simpler": [21, 48, 128, 129], "simplest": [55, 67, 135], "simpli": [21, 41, 52, 54, 63, 65, 73, 96, 126, 128, 130, 132, 135, 137], "simplic": [11, 135], "simplifi": [3, 6, 12, 20, 53, 69, 71, 128, 129, 134, 135], "simul": [52, 59, 65, 84, 88, 92, 100, 124, 126], "simultan": [29, 43, 46, 52, 90, 91, 132], "sinc": [14, 24, 48, 51, 52, 53, 120, 126, 128, 130, 131], "singl": [11, 20, 21, 40, 42, 45, 46, 48, 49, 51, 52, 53, 54, 59, 69, 78, 82, 95, 101, 106, 121, 126, 128, 129, 130, 132, 135, 137, 138], "singleton": 28, "sit": 62, "site": [3, 11, 19, 20, 21, 23, 29, 45, 46, 47, 51, 52, 53, 68, 71, 75, 76, 94, 104, 107, 121, 122, 123, 125, 128, 131, 135, 136], "site_author": [48, 51], "site_id": [68, 69, 70, 71, 74], "situat": [20, 58, 132], "six": [13, 50, 52, 74, 76, 138], "size": [31, 46, 52, 107, 126, 129, 131, 137], "skip": [48, 52, 132], "slash": [52, 104], "sleep": [60, 63, 65, 95, 105, 118, 123, 126, 130, 132], "sleepi": 60, "slightli": [78, 135], "slow": [23, 33, 45, 46, 104, 130], "slowdown": 46, "slowli": 106, "slurm": [5, 11, 20, 21, 28, 46, 52, 53, 74, 119, 122, 124], "slurm_clust": 53, "slurm_cluster_bg": 53, "slurm_cluster_bg1": 53, "slurm_cluster_bg2": 53, "slurm_packjob": [52, 118, 124], "slurm_platform": [74, 118], "slurm_supercomput": 11, "small": [53, 62, 95, 126, 129, 132, 135, 137], "smaller": [95, 125, 129, 132, 135], "smallest": [52, 76], "smtp": [46, 124, 130], "snapshot": [33, 123], "sneezi": 60, "snippet": [21, 95, 130], "so": [3, 4, 6, 7, 8, 10, 11, 20, 21, 23, 28, 29, 41, 44, 45, 46, 48, 51, 52, 53, 58, 60, 62, 63, 64, 67, 68, 70, 71, 73, 75, 76, 77, 78, 80, 88, 94, 95, 96, 99, 101, 102, 104, 105, 106, 107, 120, 122, 123, 124, 126, 128, 129, 130, 131, 132, 133, 134, 135, 137, 138], "socket": 40, "soft": 113, "softwar": 23, "sole": 121, "solo": 134, "solut": [10, 13, 16, 85, 86, 87, 88, 94, 107, 122, 135], "solv": 80, "solver": [21, 23], "some": [0, 3, 4, 5, 6, 9, 10, 11, 13, 19, 20, 21, 23, 24, 27, 33, 41, 44, 46, 48, 52, 53, 58, 60, 62, 63, 64, 67, 70, 73, 74, 75, 77, 78, 85, 86, 87, 89, 93, 94, 99, 100, 104, 105, 106, 120, 121, 122, 123, 124, 126, 128, 130, 131, 132, 134, 135, 136, 137], "some_funct": 103, "some_task": 74, "someon": 135, "someoth": 124, "someth": [4, 52, 73, 74, 78, 120, 123, 126, 132], "sometim": [21, 35, 76, 86, 87, 88, 94, 95, 123, 126, 130, 132, 135, 137], "somewhat": [130, 137], "somewher": [52, 53, 132], "sonde_ob": 138, "song": 45, "soon": [41, 59, 67, 68, 76, 80, 95, 97, 106, 121, 132], "sort": [51, 75, 132, 135], "sourc": [0, 1, 3, 6, 7, 20, 21, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 40, 46, 48, 51, 52, 69, 73, 76, 78, 80, 81, 94, 96, 104, 120, 124, 126, 128, 130, 132, 137], "source_nam": 93, "space": [20, 24, 45, 46, 50, 52, 53, 78, 93, 104, 123, 124, 128, 130, 132, 135, 138], "spaceless": [46, 50, 52], "spam": [63, 107], "sparg": 21, "sparingli": 46, "spars": 1, "spawn": [3, 4, 8, 15, 21, 42, 43, 48, 52, 101, 104, 120, 124, 126, 132, 133], "spawner_class": 48, "special": [8, 11, 21, 46, 52, 59, 60, 62, 68, 76, 87, 88, 101, 118, 120, 124, 126, 128, 129, 134, 135, 137], "specif": [8, 11, 21, 40, 46, 48, 51, 52, 53, 54, 69, 71, 73, 81, 92, 98, 101, 120, 121, 123, 124, 126, 127, 132, 135, 136], "specifi": [3, 4, 7, 11, 14, 21, 28, 39, 40, 46, 48, 50, 52, 53, 55, 60, 62, 63, 74, 80, 86, 87, 88, 94, 96, 101, 104, 111, 112, 113, 114, 115, 116, 117, 118, 121, 123, 124, 126, 128, 130, 132], "specnam": 37, "speed": [45, 74, 95, 135, 137], "speedup": [52, 105], "spell": 48, "spin": 6, "split": [23, 45, 64, 95, 129, 135], "spot": 81, "spuriou": 138, "sqlite": [103, 109], "sqlite3": [41, 109], "squar": [17, 45, 73, 78], "src": [7, 20, 21, 26, 46, 58, 59, 60, 62, 63, 64, 65, 68, 73, 74, 76, 78, 80, 93, 94], "srcdir": 27, "srun": 118, "srv_public_key_loc": 40, "ssh": [14, 20, 23, 46, 53, 57, 100, 110, 121, 123, 130, 131], "stabl": 123, "staff": [64, 137], "stage": [17, 21, 107, 123], "stagger": 132, "stai": [21, 108, 130], "stakehold": 137, "stall": [4, 15, 20, 21, 46, 52, 87, 92, 100, 103, 124, 130, 131, 132, 133], "stamp": [93, 103, 104], "standalon": [3, 11, 42, 46, 55], "standard": [3, 21, 28, 46, 48, 52, 58, 73, 74, 76, 82, 109, 120, 123, 125, 126, 128, 129, 130, 132, 137, 138], "standardis": 21, "start": [1, 3, 4, 6, 7, 9, 12, 15, 19, 20, 21, 29, 37, 40, 41, 43, 44, 46, 48, 51, 52, 53, 60, 62, 63, 65, 71, 72, 73, 76, 77, 78, 80, 83, 84, 86, 87, 88, 91, 92, 93, 94, 95, 97, 99, 100, 101, 103, 105, 107, 109, 113, 120, 123, 124, 126, 128, 130, 131, 136, 137], "start_cycl": 128, "start_hour": 13, "start_numb": 74, "start_tim": 130, "startup": [21, 35, 46, 52, 59, 74, 124, 130, 131], "state": [3, 9, 21, 31, 33, 35, 36, 39, 42, 48, 52, 54, 60, 63, 65, 74, 77, 81, 93, 94, 99, 100, 102, 104, 107, 108, 109, 113, 121, 123, 124, 127, 130, 131, 132, 134], "statement": [13, 39, 52, 70, 120, 125, 128, 130], "static": [0, 135], "station": [70, 71, 74, 76, 86, 87], "statist": 44, "statu": [4, 20, 21, 26, 41, 44, 46, 52, 73, 92, 99, 100, 101, 108, 120, 121, 122, 126, 130, 131, 132, 133, 135], "status": 126, "stderr": [21, 28, 37, 46, 52, 110, 123, 126, 130], "stdin": 28, "stdout": [21, 23, 28, 37, 46, 73, 110, 123, 126, 130], "stdtype": 28, "steak": 64, "steak1": 64, "steak2": 64, "stem": [7, 92], "step": [67, 76, 88, 95, 121, 124, 129, 132, 135], "sticky_toffe": 64, "sticky_toffee1": 64, "sticky_toffee2": 64, "still": [0, 3, 4, 5, 7, 11, 12, 13, 16, 18, 21, 28, 29, 30, 45, 52, 59, 63, 65, 74, 78, 80, 91, 99, 118, 120, 123, 126, 129, 130, 132, 135], "stop": [3, 6, 9, 20, 21, 28, 29, 37, 39, 40, 41, 44, 45, 46, 48, 51, 52, 58, 59, 60, 65, 72, 73, 80, 89, 92, 93, 94, 100, 102, 121, 123, 128, 131, 132, 134], "stop_cycl": 88, "storag": [23, 41, 53], "store": [21, 24, 31, 34, 40, 41, 52, 53, 73, 93, 104, 126, 130, 131, 132], "str": [27, 28, 37, 39, 40, 48, 126, 128], "straight": 80, "straightforward": [125, 129, 137], "stream": [40, 46, 121, 126, 130], "strftime": [52, 128], "strftime_str": 128, "strftimesyntaxerror": 128, "stricter": 123, "strictli": 138, "string": [21, 27, 28, 37, 39, 40, 45, 46, 50, 52, 57, 71, 80, 105, 120, 121, 124, 126, 128, 129, 130, 131, 134, 135, 137], "strip": [52, 88, 128], "strptime": [52, 128], "strptime_str": 128, "structur": [6, 21, 36, 41, 53, 54, 62, 69, 93, 97, 125, 127, 130, 132, 135, 137], "struggl": 123, "stuck": [75, 92, 133], "studio": 124, "stuff": [120, 135], "style": [22, 28, 75, 81, 123, 126, 130, 131, 132, 135, 136], "sub": [20, 21, 40, 45, 46, 49, 52, 53, 63, 73, 78, 86, 87, 93, 100, 104, 120, 122, 126, 128, 130, 135, 137], "subclass": [28, 35], "subcommand": 41, "subdir": 39, "subdirectori": [92, 93, 128, 135], "subfunccontext": 37, "subject": [126, 138], "sublim": 124, "submiss": [3, 11, 17, 20, 21, 22, 25, 46, 52, 53, 54, 63, 65, 72, 73, 81, 92, 102, 105, 106, 107, 110, 119, 120, 123, 124, 130, 131, 134], "submit": [0, 1, 3, 6, 11, 12, 15, 17, 20, 21, 28, 34, 44, 46, 52, 57, 65, 67, 73, 74, 81, 94, 99, 101, 102, 104, 105, 106, 107, 109, 110, 111, 113, 114, 115, 116, 117, 118, 120, 121, 122, 124, 126, 127, 130, 132, 135, 137], "submit_cmd_env": 28, "submit_cmd_tmpl": 28, "submit_num": [28, 109, 130], "submit_opt": 28, "submit_tim": 130, "subprocess": [28, 46, 131], "subroutin": 125, "subscrib": 41, "subscript": 41, "subsect": [45, 130, 138], "subsequ": [20, 46, 52, 63, 88, 101, 104, 120, 128, 132], "subset": 52, "subshel": [11, 20, 120, 124, 130], "substanti": 132, "substitut": [46, 52, 68, 121, 126, 129, 130, 131], "subtl": 10, "subtli": [23, 69], "subtract": [48, 74], "succe": [4, 16, 20, 21, 34, 44, 52, 60, 63, 65, 68, 74, 77, 94, 102, 105, 120, 126, 128, 129, 130, 132, 133, 134, 135, 138], "succeed": [1, 4, 15, 16, 21, 44, 52, 60, 68, 73, 74, 77, 78, 81, 94, 102, 103, 105, 106, 109, 120, 123, 124, 126, 130, 132, 134], "success": [16, 20, 21, 52, 80, 107, 120, 123, 126, 128, 135], "successfulli": [4, 52, 73, 77, 84, 132, 135], "successor": 132, "succinctli": 129, "suffici": [122, 130, 132, 135, 137], "suffix": [29, 59, 80, 118, 129, 138], "suggest": [14, 34, 55, 128, 132], "suicid": [4, 9, 15, 20, 21, 52, 92, 124, 127, 132], "suit": [0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 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, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138], "suitabl": [11, 23, 28, 41, 46, 52, 53, 130], "suite_nam": [20, 52, 126], "suite_run_dir": 126, "suite_share_dir": 126, "suite_url": 131, "suite_uuid": [124, 130, 131], "summari": [1, 2, 21, 22, 42, 44, 66, 72, 74, 81, 132, 134], "summer": 52, "sun": [117, 120], "supercomput": [23, 46, 125, 128], "supercomputer_a": 11, "supercomputer_b": 11, "supercomputer_login_node_selector_script": 11, "superior": 63, "suppli": [21, 93, 126, 128, 134], "support": [3, 4, 5, 7, 9, 13, 14, 15, 16, 19, 20, 21, 23, 25, 26, 28, 37, 39, 41, 43, 44, 46, 50, 52, 54, 74, 75, 76, 77, 93, 104, 107, 110, 118, 119, 124, 125, 126, 128, 129, 130, 131, 132, 133, 135, 137], "suppos": [63, 71, 80, 123, 132], "suppress": 128, "sure": [20, 52, 74, 81, 96, 104, 123, 134, 135], "surplu": 128, "surpris": 128, "surround": [120, 128], "suspend": 99, "sustain": 95, "svn": [26, 93], "sw": 76, "swamp": [21, 64], "swapper": 33, "swiftli": 64, "switch": [5, 20, 73, 81, 92, 128, 132, 134, 135, 136], "sy": [13, 126, 129], "symbol": [0, 23, 28, 45, 46, 132], "symlink": [7, 21, 24, 46, 47, 52, 73, 92, 104, 130, 135, 137], "sync": [113, 114, 115, 116, 117, 118, 120, 138], "synchron": 126, "synchronis": 41, "syntax": [4, 5, 11, 16, 20, 21, 23, 37, 44, 47, 52, 54, 60, 115, 123, 125, 126, 127, 128, 129, 130, 131, 138], "system": [5, 11, 19, 20, 21, 22, 23, 24, 26, 28, 42, 46, 48, 51, 52, 63, 64, 67, 69, 73, 74, 76, 77, 95, 97, 103, 104, 120, 121, 123, 124, 125, 126, 129, 130, 131, 132, 135, 137], "systemat": [67, 95], "t": [6, 11, 21, 28, 35, 37, 41, 46, 48, 50, 52, 53, 62, 73, 74, 75, 76, 78, 80, 86, 87, 91, 93, 94, 95, 101, 104, 106, 120, 124, 126, 128, 129, 131, 132, 133, 134, 135, 137, 138], "t00": [52, 69, 70, 71, 76, 84, 86, 87, 125, 126, 128, 132, 135], "t03": [126, 132], "t06": [52, 126, 132], "t0830": 132, "t09": [126, 132], "t1": [57, 130], "t11": 132, "t12": [52, 77, 86, 87, 125, 126, 128, 132, 135], "t15": [126, 132], "t18": [52, 126, 132], "t21": 126, "t23": [125, 128], "tab": [42, 73, 124, 136], "tabl": [42, 73, 93, 109, 126], "tail": [46, 121], "tailer": [46, 121], "tailor": 63, "take": [5, 11, 20, 21, 23, 27, 33, 40, 44, 46, 48, 51, 53, 62, 73, 78, 80, 81, 88, 94, 95, 96, 105, 121, 126, 130, 132, 135, 138], "take_snapshot": 33, "taken": [29, 93, 104, 131, 132, 133, 137], "talk": 77, "tape": [12, 81], "target": [7, 11, 20, 21, 37, 46, 52, 73, 92, 93, 98, 104, 123, 124, 126, 130, 132, 135], "task": [0, 1, 3, 6, 7, 9, 10, 11, 12, 13, 15, 16, 19, 21, 22, 23, 28, 34, 40, 42, 45, 46, 48, 50, 52, 53, 54, 57, 58, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 72, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 85, 86, 87, 89, 90, 91, 92, 95, 98, 100, 101, 103, 104, 105, 108, 111, 112, 122, 124, 125, 127, 128, 131, 133, 136, 137], "task1": [11, 128], "task2": 11, "task_bar1": 71, "task_bar3": 71, "task_bar5": 71, "task_bol": 71, "task_ev": 109, "task_family_nam": 52, "task_id": 28, "task_nam": [52, 126], "task_output_messag": 126, "task_output_trigg": 126, "task_pub": 71, "task_qux": 71, "task_statu": 126, "task_url": [124, 130], "taskdef": [37, 54], "taskdeferror": [37, 38], "taskjob": 131, "taskmessagevalid": [52, 120], "tasknamevalid": 130, "taskoutputvalid": 52, "taskproxi": 37, "taskproxysequenceboundserror": [37, 38], "tcp": [21, 40, 46, 97, 100, 123, 130], "team": 25, "technic": [43, 48, 75, 76, 110, 129, 130, 134, 135, 136, 137], "techniqu": 134, "tell": [1, 41, 44, 52, 58, 59, 65, 73, 80, 81, 83, 88, 94, 104, 123, 131, 132, 135], "templat": [7, 9, 21, 24, 27, 28, 37, 45, 46, 52, 53, 54, 68, 70, 104, 121, 123, 124, 125, 126, 127, 129, 134, 135], "template_fil": 27, "template_vari": 27, "templatesyntaxerror": 13, "templatevarlanguageclash": [37, 38], "templating_detect": 27, "temporari": 65, "temporarili": [132, 137], "tempt": 137, "ten": 138, "tend": 138, "term": [11, 20, 28, 52, 78, 122, 126, 130, 132, 137, 138], "termin": [1, 3, 19, 21, 28, 40, 42, 44, 67, 69, 73, 74, 81, 92, 123, 126], "test": [1, 4, 13, 46, 52, 59, 63, 74, 81, 85, 93, 94, 101, 104, 105, 120, 124, 126, 127, 130, 132, 135, 137], "test1": 52, "test2": 52, "tether": 59, "text": [3, 50, 63, 68, 73, 78, 124, 125, 128, 135, 138], "textfile1": 93, "textfile2": 93, "textmat": 124, "textur": 130, "textwrap": 138, "than": [3, 6, 12, 18, 20, 21, 24, 28, 37, 40, 46, 48, 52, 53, 55, 59, 63, 64, 68, 69, 70, 73, 88, 94, 103, 104, 107, 120, 121, 122, 123, 125, 126, 128, 130, 131, 132, 134, 135, 137, 138], "thei": [3, 4, 15, 16, 18, 19, 20, 21, 23, 29, 43, 44, 46, 48, 52, 53, 59, 60, 62, 65, 68, 71, 74, 76, 80, 94, 97, 98, 99, 101, 102, 104, 105, 106, 107, 110, 120, 121, 123, 126, 128, 129, 130, 131, 132, 133, 134, 135, 137, 138], "them": [1, 7, 8, 21, 23, 27, 35, 36, 39, 40, 43, 46, 48, 52, 53, 60, 65, 67, 68, 69, 73, 74, 76, 78, 80, 81, 88, 93, 94, 96, 101, 104, 106, 120, 121, 123, 124, 125, 126, 128, 129, 130, 131, 132, 134, 135, 137, 138], "themselv": [48, 58, 96, 132, 137], "theori": 48, "thereaft": [74, 132], "therebi": 137, "therefor": [29, 53, 120, 126, 131, 134, 135, 137], "thereof": 129, "thh": 132, "thi": [0, 1, 5, 9, 20, 21, 23, 24, 26, 27, 28, 29, 31, 32, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 44, 45, 46, 48, 50, 51, 52, 53, 55, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 86, 90, 93, 94, 95, 99, 101, 103, 104, 105, 106, 107, 110, 113, 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138], "thicker": 129, "thing": [23, 26, 63, 75, 80, 86, 87, 94, 123, 124, 129], "think": 98, "third": [21, 52, 58, 65, 73, 80, 124], "thirteen": 138, "thirti": 21, "thompson": 138, "those": [4, 21, 41, 44, 46, 48, 52, 59, 60, 78, 80, 101, 103, 123, 126, 128, 132, 135, 137], "though": [4, 34, 67, 74, 101, 129, 132], "thought": [62, 128], "thread": [40, 51, 54], "three": [7, 12, 13, 20, 46, 48, 52, 62, 63, 65, 71, 72, 73, 74, 76, 80, 81, 93, 107, 123, 125, 128, 129, 130, 132, 134, 135, 138], "threshold": 46, "through": [21, 39, 41, 46, 48, 52, 58, 60, 69, 73, 80, 95, 101, 120, 131, 135], "throughout": [69, 129, 137], "throughput": 95, "throw_awai": 60, "thu": [11, 59, 128, 137], "thumb": 69, "ti": 132, "ticket": 137, "tidi": 135, "tidier": [135, 137], "tie": 131, "tigger": 11, "time": [4, 5, 7, 8, 12, 20, 21, 24, 28, 29, 32, 33, 44, 45, 46, 50, 52, 54, 57, 59, 60, 63, 64, 65, 70, 72, 73, 75, 77, 79, 80, 81, 82, 84, 86, 87, 88, 91, 93, 94, 95, 96, 101, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 123, 124, 126, 128, 130, 131, 134, 136, 137], "timeout": [21, 37, 40, 46, 52, 108, 111, 112, 120, 124, 130, 131, 135], "timeout_handl": 40, "timer": [46, 52, 131], "timestamp": [21, 46, 52, 103], "timestep": 135, "timezon": [52, 128, 135], "tisd": 136, "titl": [38, 39, 52, 62, 63, 82, 83, 84, 85, 88, 91, 124, 125, 126, 128, 130, 132, 136], "tmbundl": 124, "tmp": [123, 130], "tmp_file": 52, "todo": [59, 74], "togeth": [21, 46, 53, 68, 70, 78, 79, 93, 126, 130, 132], "toi": 36, "token": [13, 43, 52], "told": [53, 123], "toml": [36, 124], "too": [21, 23, 45, 52, 64, 73, 74, 80, 94, 95, 106, 109, 121, 123, 124, 126, 129, 130, 132, 135, 137, 138], "tool": [3, 7, 13, 67, 75, 81, 109, 123, 124, 134, 138], "toolbar": 44, "top": [21, 39, 44, 46, 48, 52, 62, 70, 73, 101, 104, 106, 113, 114, 115, 116, 117, 118, 120, 124, 126, 128, 129, 130, 134], "topic": [22, 66, 75, 132, 135, 136], "torqu": 116, "total": [52, 128], "touch": [63, 126, 137], "toward": [21, 74, 85, 132], "tput": 123, "trac": 137, "traceback": [37, 123, 128], "track": [21, 46, 51, 92, 100, 121, 123], "tradit": 82, "tradition": [95, 134], "traefik": 55, "trail": [45, 52, 104, 124, 128, 136], "transfer": [4, 7, 53, 54, 104, 122], "transform": [39, 67, 95], "transit": 136, "transitori": 34, "translat": [74, 124, 137], "transmiss": 97, "transpar": [126, 135], "transport": 42, "transpos": 81, "trap": [28, 46, 52, 73, 113, 120, 130], "trappabl": 52, "travel": 62, "treat": [21, 53, 68, 122], "tree": [19, 41, 51, 62, 73, 93, 130, 132, 134, 135], "tri": [21, 34, 57, 65, 120, 126, 130], "tricki": [86, 87], "trigger": [1, 3, 4, 9, 13, 15, 17, 19, 20, 21, 27, 36, 37, 46, 48, 50, 51, 52, 61, 66, 68, 73, 76, 79, 81, 84, 86, 87, 89, 90, 92, 100, 102, 104, 106, 120, 121, 124, 127, 129, 130, 131, 136, 137, 138], "trigger_fil": 87, "triggerexpressionerror": [37, 38], "trim": [128, 138], "trip": 60, "tripl": [45, 138], "trivial": [126, 135], "troubleshoot": [22, 47, 73, 81, 92], "true": [5, 7, 18, 24, 37, 39, 40, 44, 45, 46, 50, 52, 53, 57, 58, 59, 60, 62, 63, 65, 70, 71, 74, 76, 78, 80, 94, 95, 120, 121, 125, 126, 128, 130, 132, 134, 135, 137], "truncat": [52, 121], "trunk": [26, 101, 137], "trust": [28, 107], "try": [3, 21, 33, 37, 48, 52, 53, 58, 65, 73, 74, 75, 78, 80, 81, 84, 93, 94, 102, 105, 123, 126, 130], "try_num": [28, 130], "tui": [1, 3, 17, 20, 21, 42, 43, 52, 63, 64, 65, 67, 74, 92, 94, 100, 123, 132], "tune": 95, "tupl": [18, 28, 48, 126, 128], "turbin": 62, "turbine_engin": 62, "turn": [4, 46, 51, 52, 62, 71, 80, 95, 120, 123, 130, 134], "tutori": [21, 22, 23, 52, 60, 61, 62, 64, 65, 68, 69, 72, 73, 74, 77, 78, 98], "twelv": 138, "twice": [71, 120, 126, 132], "two": [3, 10, 11, 19, 20, 21, 24, 29, 43, 44, 46, 48, 52, 53, 62, 63, 64, 65, 68, 73, 74, 76, 78, 80, 81, 86, 87, 88, 90, 91, 93, 101, 106, 109, 118, 120, 123, 124, 125, 128, 129, 130, 131, 132, 133, 135, 137, 138], "txt": [26, 63, 74, 93, 138], "ty": [130, 131], "type": [18, 28, 31, 37, 39, 40, 44, 46, 47, 48, 52, 56, 59, 60, 73, 86, 87, 126, 127, 128, 129, 131, 134], "typic": [6, 16, 21, 53, 73, 74, 93, 120, 129, 130, 132, 135, 137], "typo": [52, 74, 120], "tz": [57, 130], "u": [4, 48, 58, 59, 60, 63, 65, 69, 74, 85, 120, 123, 132, 135], "u998": 124, "u999": 124, "ugli": 132, "ugo": 46, "uh": [52, 120], "ui": [1, 2, 3, 9, 17, 46, 47, 48, 54, 56, 60, 73, 74, 101, 106, 126, 134], "ui_build_dir": 51, "ui_vers": 51, "uiserv": [23, 44, 48, 51, 56], "uk": [67, 76], "um": [134, 136], "unabl": [34, 37, 48, 51, 93, 121, 123], "unaffect": 101, "unattend": 46, "unavail": [20, 28, 53, 74], "unbound": 21, "unchang": [3, 4, 5], "uncommit": 26, "uncontrol": 21, "undefin": [120, 128, 130, 135], "under": [13, 14, 19, 21, 28, 29, 43, 46, 48, 52, 53, 76, 78, 80, 93, 104, 124, 126, 129, 130, 131, 132, 134, 135, 137], "underli": [37, 104, 132], "underneath": 93, "underscor": [52, 71, 129], "understaf": 64, "understand": [2, 9, 15, 95, 115, 123, 126, 127, 128, 134, 135], "understood": [20, 135], "undocu": 132, "unexpect": [21, 58, 108, 123, 131], "unfortun": [123, 134, 135], "unhold": 1, "unicod": 51, "unicode_rul": [52, 93, 120, 126, 130], "unifi": [52, 67, 135, 136], "uniform": 132, "unilater": 48, "unintent": 132, "uniqu": [3, 21, 52, 53, 63, 80, 101, 120, 121, 123, 126, 129, 130, 131, 135], "unit": [21, 52, 53, 76, 128, 132], "univers": [44, 128], "unix": [23, 28, 48, 111, 112], "unless": [4, 8, 11, 16, 20, 40, 46, 52, 65, 98, 104, 120, 122, 126, 128, 130, 132, 137], "unlik": [21, 46, 52, 121, 126, 129, 132], "unlimit": 132, "unlock": 3, "unnecessari": [16, 126, 132, 134], "unnecessarili": [5, 15, 21, 120, 135], "unpaus": 21, "unplan": 52, "unproduct": 60, "unreach": [34, 46], "unregist": 39, "unrol": 95, "unsaf": 120, "unset": [28, 53, 123], "unsuccess": [46, 52], "unsupport": 137, "untidi": [137, 138], "until": [7, 21, 28, 46, 52, 54, 59, 77, 83, 84, 85, 88, 93, 94, 101, 107, 113, 121, 126, 131, 132, 135], "untouch": 1, "untrack": 26, "untrapp": 121, "unus": [4, 132], "unusu": [121, 132], "up": [1, 4, 5, 6, 9, 11, 12, 20, 21, 29, 39, 40, 41, 44, 46, 48, 50, 51, 52, 53, 55, 59, 63, 74, 78, 81, 85, 93, 95, 96, 97, 101, 107, 120, 123, 124, 126, 130, 131, 138], "upcom": [6, 52, 98, 101, 132], "updat": [1, 13, 21, 28, 41, 42, 44, 51, 58, 63, 87, 93, 107, 121, 130, 137, 138], "update1": 63, "update2": 63, "upgrad": [2, 4, 5, 13, 16, 37, 41, 52, 53, 134, 135, 137], "upgradeerror": [37, 38], "upload": 137, "upload_niwa": 137, "upload_product": 129, "upon": [5, 37], "upper": [21, 46, 62, 68], "uppercas": 138, "upstream": [21, 44, 63, 80, 90, 91, 94, 104, 126, 132], "upstream_cylc_run_dir": 126, "upstream_messag": 126, "upstream_offset": 126, "upstream_point": 126, "upstream_statu": 126, "upstream_task": 126, "upstream_workflow": 126, "url": [26, 43, 46, 48, 52, 124, 130, 131, 136], "us": [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 16, 18, 19, 20, 21, 23, 24, 27, 28, 29, 34, 35, 36, 37, 39, 40, 41, 42, 43, 44, 45, 46, 48, 49, 51, 53, 55, 57, 58, 59, 60, 62, 63, 64, 65, 68, 70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 81, 86, 87, 88, 91, 92, 94, 95, 96, 97, 100, 102, 103, 104, 105, 106, 107, 109, 110, 113, 114, 115, 116, 117, 118, 119, 121, 123, 124, 125, 126, 127, 129, 130, 131, 134, 135, 136, 137, 138], "usag": [3, 28, 33, 40, 46, 125, 128, 130, 135], "user": [2, 3, 7, 14, 15, 16, 17, 19, 20, 21, 22, 23, 24, 37, 39, 40, 41, 42, 44, 46, 47, 51, 52, 53, 54, 55, 57, 59, 60, 63, 64, 65, 67, 68, 71, 72, 74, 75, 77, 78, 96, 97, 104, 106, 107, 120, 121, 123, 124, 125, 126, 128, 130, 131, 132, 134, 135, 136, 137], "user1": [48, 51], "user2": 48, "user_author": [48, 51], "user_defined_queu": 52, "user_nam": 126, "usera": [48, 51], "userb": 48, "usernam": [4, 9, 20, 48, 52, 73], "usr": [28, 33, 46, 63], "usual": [7, 21, 43, 123, 130, 132, 135], "utc": [4, 5, 20, 21, 46, 50, 52, 57, 59, 60, 63, 65, 71, 74, 76, 130, 132, 135, 137], "util": [27, 41, 43, 52, 78, 81, 118, 128, 135], "utilis": [44, 46], "uuid": [26, 57, 124, 130, 131], "uuid_str": 28, "v": [28, 33, 46, 62, 100, 115, 116, 121, 123, 132, 134, 135, 137], "v22": 62, "vacat": [28, 99, 113, 130], "valid": [3, 5, 10, 13, 16, 20, 21, 24, 27, 28, 36, 41, 44, 46, 52, 53, 54, 58, 59, 60, 63, 64, 65, 72, 74, 75, 76, 78, 81, 95, 120, 122, 123, 125, 127, 128, 130, 134, 135, 137], "validationerror": [37, 38], "valu": [4, 5, 10, 18, 21, 24, 27, 37, 39, 40, 44, 45, 46, 49, 50, 51, 52, 57, 58, 59, 62, 69, 70, 71, 73, 74, 76, 78, 88, 104, 106, 107, 118, 121, 124, 126, 127, 130, 132, 134, 135, 137, 138], "value1": 138, "value2": 138, "valueerror": 128, "var": [128, 137], "vari": [52, 78, 129], "variabl": [4, 7, 9, 21, 22, 23, 27, 28, 40, 46, 51, 52, 56, 58, 62, 65, 68, 69, 70, 72, 73, 86, 87, 98, 104, 120, 123, 124, 126, 127, 129, 134, 136, 138], "variant": [126, 130], "variat": [134, 137], "varieti": [43, 48, 67], "variou": [21, 23, 94, 120, 130, 135], "vast": 135, "vc": 26, "ve": [75, 80, 94, 96, 123, 137], "vehicl": 62, "venu": 71, "verbatim": [45, 124, 138], "verbos": [52, 57, 81, 123, 126, 130, 137, 138], "veri": [19, 46, 52, 69, 106, 115, 126, 128, 130, 134, 135, 137, 138], "verif": 107, "vers": 45, "versa": [52, 105], "version": [3, 7, 13, 18, 19, 23, 24, 26, 27, 35, 36, 37, 39, 44, 46, 51, 52, 53, 54, 55, 57, 94, 101, 102, 104, 106, 118, 119, 121, 124, 126, 128, 129, 130, 131, 132, 135, 137], "vertic": 62, "vi": 1, "via": [0, 20, 21, 24, 28, 29, 39, 40, 44, 46, 48, 51, 52, 53, 54, 58, 74, 93, 94, 98, 103, 105, 107, 118, 122, 126, 128, 130, 131, 132, 134, 135, 137], "vice": [52, 105], "view": [0, 11, 19, 20, 21, 42, 46, 48, 53, 63, 69, 73, 74, 81, 121, 123, 124, 128, 134, 135, 138], "viewer": [46, 121], "vim": [94, 124, 138], "vip": [1, 3, 44, 81, 82, 83, 84, 85, 86, 87, 88, 90, 91, 131], "virtual": [20, 23, 48], "virtual_memori": [46, 131], "visibl": [0, 44, 46, 106, 120, 126], "visit": 43, "visit_min": 60, "visual": [0, 124, 129], "visualis": [44, 67, 76, 78, 80], "vm": 107, "vr": [1, 3, 44, 81, 88, 94, 123, 131], "vscode": 124, "vtype": 37, "vuex": 41, "vulner": 135, "vv": 126, "w": [41, 76, 114, 120, 124, 128, 132], "w101": 132, "wa": [4, 7, 10, 20, 21, 23, 37, 44, 46, 51, 52, 54, 59, 67, 74, 76, 78, 88, 93, 96, 99, 101, 104, 121, 123, 126, 129, 130, 131, 132, 134, 135], "wai": [0, 2, 3, 7, 10, 14, 20, 21, 43, 46, 48, 52, 64, 68, 69, 71, 73, 76, 78, 93, 94, 99, 104, 107, 123, 126, 128, 129, 130, 132, 133, 134, 135, 137], "wait": [4, 15, 21, 29, 40, 44, 46, 52, 59, 60, 63, 64, 65, 73, 74, 77, 80, 83, 84, 86, 87, 91, 94, 95, 101, 102, 106, 108, 120, 123, 126, 129, 130, 132, 133, 135], "walk": [58, 60], "wall": [52, 126, 132], "wall_clock": [52, 59, 77, 84, 91, 126, 135], "wall_clock_limit": [113, 124, 125, 128], "wallclock": [21, 52, 59, 84, 121, 126, 132, 135], "walltim": [115, 116, 124], "want": [0, 4, 6, 7, 12, 13, 21, 23, 28, 39, 44, 51, 52, 53, 55, 58, 59, 62, 63, 68, 71, 74, 75, 76, 80, 81, 83, 84, 86, 87, 88, 91, 93, 94, 96, 101, 102, 105, 122, 123, 124, 126, 130, 132], "wari": 137, "warm": [21, 104], "warn": [4, 20, 21, 45, 52, 103, 120, 124, 126, 130, 132], "warrant": 120, "warranti": 3, "wast": 126, "watch": [33, 60, 126, 133], "watcher": 127, "water": [62, 67], "water_vehicl": 62, "waz": 52, "we": [3, 4, 5, 7, 11, 14, 20, 21, 23, 24, 28, 33, 37, 44, 45, 46, 49, 52, 53, 55, 58, 59, 60, 62, 63, 64, 65, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 80, 81, 83, 84, 86, 87, 88, 91, 93, 94, 96, 101, 120, 122, 123, 126, 129, 132, 135, 136, 137, 138], "weather": [67, 68, 70, 73, 74, 76, 128, 132], "web": [1, 3, 12, 41, 42, 43, 44, 46, 48, 52, 54, 67, 70, 74, 81, 94, 131], "webstorm": 124, "week": [21, 76, 128, 132], "well": [12, 15, 21, 28, 41, 44, 52, 53, 62, 63, 73, 74, 76, 94, 95, 106, 120, 128, 130, 131, 132, 134], "went": [74, 123], "were": [3, 4, 5, 7, 16, 21, 27, 37, 41, 44, 46, 77, 95, 96, 104, 126, 129, 132, 133, 138], "what": [3, 5, 19, 20, 21, 35, 48, 52, 63, 65, 66, 69, 73, 78, 92, 96, 104, 113, 114, 115, 116, 117, 118, 121, 124, 126, 130, 132, 134, 135, 137], "whatev": [126, 128, 130, 132, 137], "wheel": 62, "when": [1, 3, 4, 6, 7, 10, 11, 12, 14, 16, 19, 20, 21, 24, 27, 28, 29, 31, 32, 33, 35, 37, 44, 46, 48, 52, 53, 57, 58, 59, 60, 63, 65, 68, 71, 73, 76, 77, 81, 86, 87, 88, 93, 94, 101, 104, 107, 110, 120, 121, 122, 123, 124, 126, 128, 129, 130, 131, 132, 133, 135, 137, 138], "whenev": 128, "where": [1, 3, 5, 11, 12, 19, 20, 21, 23, 33, 37, 40, 41, 43, 46, 48, 51, 52, 53, 55, 58, 62, 63, 70, 71, 73, 74, 76, 78, 80, 81, 85, 86, 87, 88, 91, 93, 94, 101, 104, 107, 109, 110, 121, 123, 124, 126, 128, 130, 131, 132, 135, 137, 138], "wherea": [4, 10, 29, 46, 88, 126], "wherebi": 53, "wherein": 136, "wherev": 134, "whether": [21, 28, 37, 46, 52, 60, 85, 102, 105, 124, 126, 132], "which": [0, 3, 4, 5, 7, 10, 11, 13, 14, 15, 16, 19, 20, 21, 23, 24, 27, 28, 33, 34, 35, 37, 39, 40, 41, 43, 44, 45, 46, 48, 50, 51, 52, 53, 58, 59, 60, 62, 63, 65, 68, 72, 73, 74, 75, 76, 78, 80, 81, 82, 83, 84, 85, 87, 88, 91, 93, 94, 96, 97, 101, 103, 104, 105, 106, 107, 113, 120, 121, 122, 123, 124, 125, 126, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138], "whight": 62, "while": [4, 21, 46, 59, 63, 80, 121, 122, 123, 126, 128, 129, 130, 132], "whilst": [48, 58, 63, 81, 88, 94, 121], "white": [52, 128, 132, 138], "whitelist": [37, 53, 122], "whitespac": [45, 52, 124, 136], "whizz": 130, "who": [48, 58, 135], "whole": [11, 12, 50, 52, 78, 91, 120, 126, 132, 138], "whose": 135, "why": 137, "wide": [20, 68, 124, 126, 128, 137], "width": 138, "wight": 62, "wikipedia": [21, 67, 95, 109], "win": 65, "wind": [68, 73, 74, 76], "wind_": 68, "wind_cycl": 68, "wind_file_templ": 68, "window": [4, 15, 19, 20, 21, 73, 100, 101, 102, 108, 123, 130, 132, 133], "wing": 62, "winner": 135, "winter": 52, "wipe_log": 58, "wish": [23, 48, 52, 53, 88, 93, 104, 124, 126, 130, 131], "withdraw": 95, "within": [0, 6, 13, 15, 21, 35, 37, 39, 44, 45, 46, 49, 52, 58, 59, 62, 63, 68, 72, 73, 77, 78, 81, 95, 101, 110, 121, 123, 124, 125, 128, 129, 130, 132, 135, 136, 137, 138], "without": [0, 1, 4, 5, 7, 8, 11, 12, 15, 16, 20, 21, 23, 27, 36, 46, 48, 51, 52, 53, 55, 64, 71, 73, 74, 80, 81, 93, 94, 101, 104, 105, 108, 120, 130, 132, 134, 135, 137, 138], "wol": 11, "won": [21, 124], "word": [52, 58, 120, 130], "worflow": 12, "work": [0, 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, 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, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 131, 132, 133, 134, 135, 136, 137, 138], "work_d": 28, "workaround": [7, 119], "workdir": 126, "worker": 51, "workflow": [0, 3, 4, 5, 7, 8, 9, 10, 11, 13, 15, 16, 17, 18, 19, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 41, 42, 43, 45, 46, 47, 51, 53, 56, 57, 58, 59, 60, 63, 64, 65, 66, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 82, 83, 84, 86, 87, 89, 90, 92, 97, 98, 101, 102, 103, 105, 106, 107, 110, 113, 114, 115, 116, 117, 118, 120, 121, 122, 129, 132, 133, 134, 138], "workflow_": [52, 130], "workflow_fil": 122, "workflow_id": [20, 73, 101, 126], "workflow_import": 52, "workflow_nam": [24, 28, 126], "workflow_param": [38, 39], "workflow_r": 130, "workflow_run_dir": 126, "workflow_share_dir": 126, "workflow_st": [44, 52, 91, 126], "workflow_task_id": [91, 126], "workflow_titl": [52, 130], "workflow_url": [124, 130, 131], "workflow_x": [52, 97], "workflowconfigerror": [37, 38, 126], "workfloweventerror": [37, 38], "workflowfileserror": [37, 38], "workflownamevalid": 93, "workflowruntimecli": 40, "workflowruntimeserv": 40, "workflowstop": [37, 38, 40], "workload": 115, "workspac": [52, 130, 132, 135], "workstat": 48, "world": [4, 13, 21, 28, 46, 50, 52, 59, 71, 73, 76, 84, 86, 87, 89, 91, 92, 123, 126, 128, 135, 138], "wors": [134, 138], "worth": 135, "would": [6, 8, 10, 21, 24, 37, 44, 46, 48, 50, 51, 52, 53, 59, 60, 62, 63, 65, 70, 71, 73, 77, 78, 81, 88, 93, 101, 104, 122, 123, 126, 129, 130, 132, 133, 135, 137, 138], "wrap": [7, 40, 70, 95, 111, 112, 121, 123, 128, 129, 130], "wrapper": [23, 24, 37, 40, 46, 122, 135], "write": [5, 21, 22, 23, 24, 27, 28, 35, 36, 44, 47, 52, 58, 59, 60, 62, 66, 68, 70, 71, 73, 75, 76, 78, 80, 82, 90, 91, 92, 93, 104, 105, 120, 121, 122, 123, 125, 126, 131, 132, 135], "write_data": 135, "write_text": 27, "writer": 46, "written": [3, 21, 45, 50, 52, 60, 68, 70, 71, 73, 74, 76, 77, 78, 81, 91, 96, 113, 114, 115, 116, 117, 118, 120, 122, 124, 126, 130, 132, 137, 138], "wrong": [52, 74, 123], "wrongli": 37, "wrote": [69, 87], "x": [5, 10, 13, 18, 21, 23, 24, 44, 52, 63, 70, 81, 120, 121, 126, 132], "x1": 126, "x2": 126, "x3": 126, "xcpu": 28, "xml": 124, "xtrace": [21, 46, 81, 123], "xtrigger": [0, 4, 13, 21, 22, 25, 37, 44, 50, 52, 59, 77, 91, 108, 123, 127, 133, 135], "xtrigger1": 133, "xtrigger2": 133, "xtriggerconfigerror": [37, 38], "xtriggernamevalid": 126, "xxx": 74, "xxxx": [68, 69, 70, 71, 74, 132], "xxxxxxxx": [68, 69, 70, 71, 74], "xxxxxxxxxxxx": [68, 69, 70, 71, 74], "xy": 68, "y": [44, 50, 52, 76, 123, 126, 128, 132], "ye": [12, 46, 113, 120], "year": [21, 50, 52, 76, 77, 88, 128, 129, 132], "yellow": 21, "yet": [0, 21, 78, 94, 101, 104, 120, 122], "yield": [39, 52], "york": 128, "you": [0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 23, 24, 27, 28, 36, 37, 39, 44, 45, 46, 48, 51, 52, 53, 55, 58, 59, 60, 62, 63, 64, 65, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 80, 81, 85, 86, 87, 88, 91, 93, 94, 95, 96, 97, 98, 101, 102, 103, 104, 105, 106, 107, 108, 109, 118, 120, 121, 123, 124, 126, 128, 129, 130, 131, 132, 134, 135, 137, 138], "your": [4, 7, 8, 10, 11, 13, 14, 19, 20, 23, 24, 28, 43, 44, 46, 47, 51, 52, 53, 56, 59, 60, 62, 63, 65, 73, 74, 76, 77, 78, 80, 81, 93, 94, 96, 97, 103, 104, 105, 107, 120, 121, 122, 123, 124, 126, 128, 130, 132, 134, 135, 138], "yourorg": 46, "yourself": [4, 43, 48, 73, 94, 121], "z": [18, 50, 52, 76, 88, 132], "zaz": 52, "zealand": 67, "zero": [28, 29, 46, 52, 76, 77, 120, 124, 126, 130, 132, 135], "zeromq": 40, "zmq": [40, 46, 107, 123], "zmqclient": 40, "zone": [4, 20, 21, 46, 50, 52, 79, 107, 132, 136], "zoo": 58, "zsh": 23, "zulu": 76}, "titles": ["Cylc 8.4 Caveats", "Cheat Sheet", "Cylc 8 Migration Guide", "Command Line Interface", "Cylc 7 Compatibility Mode", "Configuration Changes at Cylc 8", "Continuing a Cylc 7 Workflow with Cylc 8", "Cylc Install", "Excluding Tasks at Start-up is Not Supported", "Detailed Description of Major Changes", "Parameters", "Platforms", "Play Pause Stop", "Python 2 => 3", "Remote Usernames", "Scheduling Algorithm", "Graph branching, optional outputs and suicide triggers", "Task/Job States", "Template Variables", "Cylc 8 UIs", "Summary Of Major Changes", "Glossary", "Cylc Documentation", "Installation", "Cylc Rose", "Plugins", "cylc.flow.install_plugins.log_vc_info", "Pre-Configure And Post-Install Plugins", "Custom Job Submission Methods", "cylc.flow.main_loop.auto_restart", "cylc.flow.main_loop.health_check", "cylc.flow.main_loop.log_data_store", "cylc.flow.main_loop.log_main_loop", "cylc.flow.main_loop.log_memory", "cylc.flow.main_loop.reset_bad_hosts", "Main Loop Plugins", "Xtrigger Plugins", "Exceptions", "Cylc API", "Scan API", "Workflow Runtime Interface", "Data Flow", "Architecture", "Cylc UI Server", "Changes", "The .cylc File Format", "Global Configuration", "Configuration", "Authorizing Others to Access Your Workflows", "<no title>", "Cylc Configuration Data Types", "UI Server Configuration", "Workflow Configuration", "Platform Configuration", "Cylc Development History - Major Changes", "Conda Environments", "Reference", "Job Script Environment Variables", "Broadcast Tutorial", "Clock Triggered Tasks", "Family Triggers", "Further Topics", "Inheritance", "Message Triggers", "Queues", "Retries", "Tutorial", "Introduction", "Families", "Consolidating Configuration", "Jinja2", "Parameterized Tasks", "Runtime", "Introduction", "Runtime Configuration", "Tutorial Summary", "Datetime Cycling", "Further Scheduling", "The flow.cylc File Format", "Scheduling", "Basic Cycling", "Cheat Sheet", "Hello World", "Integer Cycling", "Datetime Cycling", "Converging Workflow", "<no title>", "Event Driven Cycling", "Extending Workflow", "Examples", "<no title>", "Inter-Workflow Triggering", "User Guide", "Installing Workflows", "Interventions", "Introduction", "Removing Workflows", "Client-Server Interaction", "Cylc Broadcast", "Handling Job Preemption", "Running Workflows", "Concurrent Flows", "Retrying Tasks", "Scheduler Logs", "Start, Restart, Reload", "Simulation Modes", "Tasks in the GUI/Tui", "Tracking Job Status", "Workflow Completion", "Workflow Run Databases", "Task Implementation", "at", "background", "loadleveler", "lsf", "moab", "pbs", "sge", "slurm", "slurm_packjob", "Task Implementation", "Job Submission and Management", "Remote Job Management", "Troubleshooting", "Workflow Configuration", "EmPy", "External Triggers", "Writing Workflows", "Jinja2", "Task Parameters", "Task Configuration", "Scheduler Configuration", "Scheduling Configuration", "Suicide Triggers", "Efficiency And Maintainability", "Basic Principles", "Workflow Design Guide", "Portable Workflows", "Style Guidelines"], "titleterms": {"": [1, 94, 128], "0": [44, 101], "03": 132, "1": [44, 76, 93, 132], "12z": 132, "14t15": 132, "2": [4, 13, 44, 76, 93], "2018": 132, "3": [4, 13, 44, 76, 132], "4": [0, 132], "7": [4, 6, 20, 21, 52, 124], "8": [0, 2, 3, 5, 6, 11, 19, 20, 44, 124], "A": [1, 11, 67, 73, 96], "And": [27, 73, 94, 132, 134, 138], "At": [88, 104, 135], "By": [94, 134, 135], "For": 124, "In": [27, 35, 58, 126, 128], "It": [76, 94], "No": 123, "Not": 8, "Of": [3, 20, 126, 131], "On": [23, 130], "One": 94, "Or": 135, "The": [23, 24, 44, 45, 68, 69, 70, 73, 76, 78, 88, 93, 94, 104, 106, 121, 124, 128, 130, 132, 134, 135, 137], "To": [12, 20, 44, 55, 69, 81, 93, 129, 131, 132, 135, 137], "With": [55, 65, 81], "abort": [102, 120], "access": [48, 128], "activ": [123, 135], "ad": [55, 59], "addit": 24, "advanc": [23, 27, 53, 132], "affect": [3, 4, 6, 7, 8, 10, 11, 12, 13, 14, 16, 18, 96], "after": [88, 104], "agnost": 137, "aim": [76, 77, 78, 80], "algorithm": [15, 20, 85], "all": [76, 94], "alter": 65, "altern": 77, "an": [132, 137], "analysi": 44, "ani": 18, "api": [27, 29, 30, 31, 32, 33, 34, 38, 39], "app": [134, 135, 137], "approach": 69, "ar": [53, 123], "architectur": [20, 42], "arrai": 128, "assert": 128, "associ": 128, "authent": [43, 97, 104], "author": 48, "authoris": 48, "auto": [23, 124], "auto_restart": 29, "autom": 135, "automat": [93, 94, 134], "avail": 53, "avoid": [120, 135], "awar": 20, "background": 112, "balanc": 131, "base": [0, 122], "bash": [23, 44], "basic": [80, 132, 135], "behaviour": [65, 135], "being": 123, "branch": [16, 132], "break": 10, "broadcast": [58, 98], "browser": 0, "built": [27, 35, 126, 130], "bunch": 135, "calendar": 77, "cannot": 123, "case": [52, 101, 122, 133], "caveat": [0, 4], "cd": [86, 87], "chain": 94, "chang": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 44, 54, 81, 104], "channel": 55, "charact": 138, "cheat": [1, 81], "ci": [86, 87], "clean": 96, "cli": [24, 73], "client": [40, 41, 97], "clock": [59, 77, 126, 132, 135], "cluster": 53, "coars": 135, "code": [124, 135, 138], "collabor": 137, "combin": [44, 132], "command": [3, 4, 12, 20, 44, 69, 93, 121, 131], "comment": 138, "commun": 107, "compat": [4, 20, 52], "complet": [23, 44, 108, 123, 132], "complex": 135, "complianc": 135, "compon": [23, 41, 44], "compound": 93, "comput": 76, "concurr": 101, "conda": [23, 55, 123], "condit": 132, "config": [24, 69, 134, 137, 138], "configur": [1, 5, 23, 24, 27, 35, 46, 47, 48, 50, 51, 52, 53, 65, 69, 74, 93, 94, 104, 123, 124, 130, 131, 132, 135], "confin": 135, "consolid": 69, "contact": 104, "contain": 135, "content": [93, 94], "context": [125, 128], "continu": [6, 126, 138], "convent": 138, "converg": 85, "copi": [82, 83, 84, 85, 87, 88, 91], "coroutin": 35, "creat": [63, 104], "current": [126, 132], "custom": [28, 104, 120, 126, 128, 131, 132], "cycl": [44, 76, 80, 83, 84, 87, 88, 95, 104, 129, 132, 135], "cylc": [0, 2, 3, 4, 5, 6, 7, 11, 19, 20, 21, 22, 23, 24, 26, 29, 30, 31, 32, 33, 34, 38, 42, 43, 44, 45, 48, 50, 52, 53, 54, 55, 67, 69, 71, 73, 78, 81, 93, 95, 98, 103, 122, 123, 124], "cylc_workflow_initial_cycle_point": 132, "data": [41, 50, 76, 86, 87], "databas": 109, "date": 132, "datetim": [1, 76, 84, 132], "debug": [81, 123, 128], "decoupl": 91, "default": [93, 121, 128], "defin": 130, "definit": 73, "delet": 1, "depend": [76, 78, 80], "deprec": 5, "descript": [9, 138], "design": 136, "detach": 120, "detail": 9, "determin": 123, "develop": [27, 35, 36, 54, 137], "did": 123, "differ": [7, 60], "dir": 20, "direct": 121, "directli": 122, "directori": [53, 73, 93, 96, 123, 124, 130, 135], "disk": 123, "do": 123, "document": 22, "doe": [3, 4, 6, 7, 8, 10, 11, 12, 13, 14, 16, 18, 96], "down": 123, "driven": 87, "duplic": 78, "durat": 76, "echo": 126, "edit": [44, 94], "editor": 23, "effici": [132, 134], "email": 130, "empi": 125, "engin": 62, "environ": [23, 53, 55, 57, 71, 74, 123, 128, 130, 132], "error": [93, 120, 123], "event": [35, 87, 126, 130, 131], "exampl": [4, 10, 11, 16, 18, 27, 36, 48, 53, 58, 59, 60, 64, 65, 70, 78, 82, 83, 84, 85, 86, 87, 88, 89, 91, 93, 95, 101, 126, 130, 132, 137], "except": [37, 128], "exclud": [8, 93, 132], "exclus": 132, "execut": [121, 131, 135], "expans": 129, "expect": 93, "expir": 132, "explan": [60, 63], "express": [44, 132], "extend": 88, "extern": [126, 130, 131, 132, 135], "fail": [94, 123], "failur": [60, 105, 120, 130, 132, 135], "famili": [60, 68, 129, 130, 132, 134], "farth": 62, "featur": 18, "file": [20, 24, 45, 53, 73, 78, 93, 96, 97, 104, 123, 124, 125, 128, 134, 135, 137, 138], "filenotfounderror": 123, "filesystem": 126, "filter": 128, "final": [76, 104, 132], "fine": 135, "finish": [62, 132], "first": 130, "fix": 5, "flow": [0, 4, 23, 26, 29, 30, 31, 32, 33, 34, 41, 55, 78, 101, 124], "forecast": 76, "format": [41, 45, 76, 78, 132], "free": 122, "friendli": 76, "from": [7, 53, 93, 130], "full": [3, 129], "function": [126, 135], "further": [42, 61, 64, 65, 77], "futur": 132, "gaierror": 123, "gantt": 44, "gather": 76, "gener": [73, 76, 93, 124, 130, 132, 134], "genet": 85, "get": [82, 83, 84, 85, 87, 88, 91, 123], "global": [24, 46, 128], "glossari": 21, "grain": 135, "graph": [1, 5, 16, 44, 68, 78, 101, 104, 129, 132, 137, 138], "graphql": 41, "gross": 124, "group": [44, 48, 53], "gui": [19, 44, 73, 81, 106], "guid": [2, 92, 95, 136], "guidelin": 138, "handl": [11, 99, 130], "handler": [130, 131], "health_check": 30, "hello": [27, 35, 82], "help": 123, "hierarchi": [62, 130, 134], "highlight": 124, "hint": [62, 74, 76], "histori": 54, "hold": [12, 94], "home": 53, "host": [11, 123, 130, 131, 135], "housekeep": 135, "hovercraft": 62, "how": [11, 63, 95, 132], "http": 41, "hub": [19, 42, 43, 48], "hypertext": 41, "i": [8, 11, 67, 95, 123], "id": [3, 81], "ignor": 44, "impact": 13, "implement": [110, 120], "implicit": 130, "import": 128, "includ": [135, 137], "indent": [78, 138], "independ": 135, "infer": 76, "inherit": [62, 130, 134, 135], "initi": [76, 104, 132], "initialis": 123, "inlin": [120, 137], "inspect": 81, "instal": [1, 7, 20, 23, 24, 27, 53, 73, 93, 96, 104, 123], "install_plugin": 26, "integ": [13, 83, 129, 132], "inter": [91, 132], "interact": [41, 48, 97], "intercycl": [76, 80, 132], "interdepend": 135, "interfac": [1, 3, 40, 73], "intern": [130, 132, 135], "interpret": 120, "interv": 132, "intervent": [1, 81, 94], "introduc": 53, "introduct": [67, 73, 95], "io": 135, "isn": 123, "iso8601": [76, 132], "item": [78, 93, 138], "jinja2": [13, 70, 123, 128, 134, 135, 137, 138], "job": [17, 20, 28, 41, 53, 57, 73, 74, 94, 99, 106, 107, 120, 121, 122, 123, 130, 132, 135], "jupyt": [43, 44, 48], "kill": 121, "languag": 70, "late": 130, "latest": 44, "layer": 42, "layout": 44, "lead": 13, "length": [105, 138], "level": 124, "limit": [74, 105, 121, 126, 132, 135], "line": [3, 10, 132, 138], "lint": 124, "list": [3, 18, 53, 81], "liter": 18, "load": 131, "loadlevel": 113, "localhost": [53, 93], "locat": 93, "log": [44, 103, 104, 121, 123, 128, 130], "log_data_stor": 31, "log_main_loop": 32, "log_memori": 33, "log_vc_info": 26, "login": [53, 123], "long": 132, "loop": [35, 134], "lsf": 114, "mac": 23, "mail": 131, "main": 35, "main_loop": [29, 30, 31, 32, 33, 34], "maintain": 134, "major": [9, 20, 54], "make": [81, 93], "mamba": 123, "manag": [23, 81, 121, 122], "manual": 44, "map": 12, "me": [3, 4, 6, 7, 8, 10, 11, 12, 13, 14, 16, 18, 96], "merg": 101, "messag": [63, 103, 107, 120, 123, 132], "metadata": 135, "method": [28, 121], "migrat": [2, 7, 10, 131], "misconfigur": 104, "moab": 115, "mode": [4, 20, 43, 52, 81, 105], "model": [76, 137], "modifi": 106, "modul": 128, "monolith": 135, "more": [27, 59, 62], "multi": 43, "multipl": [53, 62, 81, 94, 130, 132], "mutual": 132, "my": 123, "n": [44, 101, 106], "name": [13, 93, 123, 129, 130, 138], "network": 42, "new": [18, 20], "node": 53, "non": [23, 132], "notabl": 7, "note": [78, 96, 132], "now": [44, 132], "npm": 23, "number": [73, 93, 101], "o": [23, 123], "observ": 76, "off": 126, "offset": 129, "old": 12, "omit": 132, "onc": 130, "open": [1, 81], "oper": [1, 137], "operationalerror": 123, "option": [16, 20, 24, 93, 128, 132, 134, 137], "orphan": 94, "other": [4, 11, 20, 48, 55, 122, 126], "output": [16, 20, 44, 76, 94, 132, 135], "over": 41, "overrid": [93, 121, 130], "overview": [3, 4, 7, 8, 10, 11, 12, 13, 14, 18, 43], "packag": [13, 55], "pad": 129, "paramet": [10, 71, 129], "parameter": [71, 129, 134], "parent": 130, "partial": 129, "pass": 129, "path": [73, 135, 137], "paus": [1, 12], "pb": [53, 116, 121], "penni": 62, "permiss": 48, "pip": 23, "pipe": 120, "plai": [12, 93], "platform": [5, 11, 20, 53, 123, 130, 131], "plugin": [25, 27, 35, 36, 128], "point": [44, 76, 88, 104, 132, 135], "polar": [86, 87], "poll": [107, 121, 135], "pool": 131, "portabl": 137, "post": 27, "post_instal": 27, "practic": [63, 68, 70, 71, 73, 74, 76, 78, 80], "pre": 27, "pre_configur": 27, "preemption": 99, "prerequisit": [44, 94], "principl": 135, "problem": 123, "process": [76, 86, 87, 93, 120], "produc": 76, "profil": [23, 123], "project": 124, "protobuf": 41, "protocol": 41, "provid": 121, "purpos": [58, 65], "push": 126, "put": 76, "python": [4, 13, 18, 23, 29, 30, 31, 32, 33, 34, 128], "pythonpath": [44, 73], "qualifi": 77, "queue": [64, 132, 135], "quick": 23, "quirk": 121, "r": 132, "rais": 128, "rang": 129, "re": [12, 94], "read": [42, 64, 65], "recommend": 23, "recoveri": 135, "recurr": [76, 80, 132], "refer": [27, 56], "referenc": 132, "reinstal": 93, "rel": 132, "relat": [95, 128, 130, 132], "releas": [12, 44], "reload": [1, 44, 93, 104], "remain": 133, "rememb": 44, "remind": [62, 76], "remot": [7, 14, 96, 104, 122, 123, 130], "remov": [20, 96], "renam": 4, "repeat": 80, "requir": [4, 16, 20, 23, 123, 132], "rerun": 101, "research": 137, "reset_bad_host": 34, "restart": [1, 74, 104], "restrict": 135, "retri": [65, 74, 94, 102, 130, 135], "root": [68, 130], "rose": [1, 7, 13, 24, 55, 81, 135, 138], "rule": 132, "run": [1, 7, 12, 65, 73, 76, 81, 88, 93, 94, 95, 100, 105, 109, 123, 135], "runahead": [132, 135], "runtim": [40, 44, 68, 72, 73, 74, 104], "s001": 124, "s002": 124, "s003": 124, "s004": 124, "s005": 124, "s006": 124, "s007": 124, "s008": 124, "s009": 124, "s010": 124, "s011": 124, "s012": 124, "s013": 124, "s014": 124, "satellit": [86, 87], "scan": [1, 39], "scenario": 53, "schedul": [15, 20, 41, 42, 53, 77, 79, 103, 108, 131, 132], "scope": 128, "script": [4, 13, 57, 73, 120, 130, 135, 138], "section": [80, 121], "secur": 41, "see": 123, "select": [129, 130, 135], "selector": 44, "self": 135, "sequenc": [102, 129], "sequenti": [126, 132], "server": [0, 23, 40, 41, 42, 43, 48, 51, 53, 97], "set": [44, 73, 94, 128, 132, 138], "sge": [117, 121], "share": [53, 130, 134, 135], "sheet": [1, 81], "shell": [23, 123], "shorthand": [18, 45, 78], "shut": 123, "simpl": 11, "simul": 105, "singl": 43, "site": [48, 137], "situ": 58, "skip": 93, "slurm": 118, "slurm_packjob": 119, "socket": 123, "solut": [62, 63, 71, 74, 76, 78, 80], "some": 101, "sourc": 93, "special": [24, 132], "specif": [96, 129, 130, 137], "split": 132, "ssh": [41, 107, 122], "stall": 108, "standalon": 58, "standard": 135, "standardis": 3, "start": [8, 74, 81, 104, 129, 132, 135], "state": [17, 20, 44, 73, 106, 126], "static": 1, "statu": [107, 123], "stderr": 121, "stdout": 121, "stem": [1, 24, 81], "stop": [1, 12, 74, 81, 88, 101, 104], "string": [18, 78, 132, 138], "structur": 124, "stuck": 94, "style": [124, 138], "sub": [101, 129], "subdirectori": 96, "submiss": [28, 74, 94, 121, 132, 135], "submit": [53, 123, 131], "success": [60, 132], "suicid": [16, 133], "suit": [7, 24], "summari": [20, 59, 60, 75], "support": [8, 48, 121], "switch": [94, 137], "symlink": [20, 53, 93, 96], "syntax": [45, 124, 132], "system": [53, 138], "t": 123, "tab": [44, 138], "target": [53, 96], "task": [4, 8, 17, 20, 44, 59, 71, 73, 88, 94, 102, 106, 107, 110, 120, 121, 123, 126, 129, 130, 132, 134, 135, 138], "tcp": [41, 107], "templat": [18, 128, 130, 131], "termin": [20, 94], "terminologi": 20, "test": 128, "text": 23, "thi": [3, 4, 6, 7, 8, 10, 11, 12, 13, 14, 16, 18, 82, 83, 84, 85, 87, 88, 91, 96], "three": 69, "time": [74, 76, 121, 132, 135], "timeout": [104, 121], "titl": 138, "togeth": 76, "toi": 126, "topic": 61, "track": 107, "trail": 138, "transfer": 41, "transit": 137, "transport": 41, "trigger": [16, 44, 59, 60, 63, 77, 91, 94, 101, 126, 132, 133, 134, 135], "troubleshoot": [48, 104, 123], "truncat": 132, "tui": [19, 44, 73, 81, 106], "tutori": [58, 66, 75, 95, 128, 130, 132], "type": [23, 35, 50, 62, 71, 132], "u001": 124, "u002": 124, "u003": 124, "u004": 124, "u005": 124, "u006": 124, "u007": 124, "u008": 124, "u009": 124, "u010": 124, "u011": 124, "u012": 124, "u013": 124, "u014": 124, "u015": 124, "u016": 124, "ui": [0, 19, 20, 23, 41, 42, 43, 44, 51], "uiserv": 55, "um": 138, "understand": 124, "unexpectedli": 123, "unpaus": 1, "up": [8, 104, 132, 135], "updat": 123, "upgrad": [11, 20, 44, 124], "url": 138, "us": [52, 69, 93, 101, 120, 122, 128, 132, 133], "usag": 63, "user": [1, 43, 48, 73, 76, 92, 95], "usernam": 14, "util": 123, "v": 104, "valid": [1, 4, 18, 73, 93, 124, 126, 132], "valu": [128, 129], "vari": 135, "variabl": [18, 24, 53, 57, 71, 74, 125, 128, 130, 131, 132, 135, 137], "varieti": 11, "via": 23, "view": [1, 44], "vip": 93, "visual": [130, 134], "visualis": 1, "vr": 93, "warn": 5, "watcher": 126, "web": [19, 20], "websocket": 41, "were": 53, "what": [11, 53, 67, 95, 123], "where": 122, "whether": 123, "which": 69, "whitespac": 138, "why": [53, 123], "window": [44, 106], "without": 65, "work": [55, 81, 130], "workflow": [1, 6, 12, 20, 40, 44, 48, 52, 62, 67, 73, 80, 81, 85, 88, 91, 93, 94, 95, 96, 100, 104, 108, 109, 123, 124, 125, 126, 127, 128, 130, 131, 135, 136, 137], "workspac": 44, "world": [27, 35, 82], "write": [53, 127], "wss": 41, "xcpu": 123, "xrandom": 126, "xtrigger": [36, 126], "your": [48, 55], "z": 128, "zero": [13, 129], "zmq": 41, "zone": [76, 135]}}) \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/furthertopics/broadcast.html b/nightly_8.4/html/tutorial/furthertopics/broadcast.html new file mode 100644 index 00000000000..165fbbecdcd --- /dev/null +++ b/nightly_8.4/html/tutorial/furthertopics/broadcast.html @@ -0,0 +1,297 @@ + + + + + + + Broadcast Tutorial — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Broadcast Tutorial

+

This tutorial walks you through using cylc broadcast which can be used +to change task runtime configuration in a +running workflow, on-the-fly.

+
+

Purpose

+

cylc broadcast can be used to change any [runtime] setting whilst the +workflow is running.

+

The standard use of cylc broadcast is to update the workflow to an +unexpected change in configuration, for example modifying the host a task +runs on.

+
+
+

Standalone Example

+

Create a new workflow in the cylc-src directory called +tutorial-broadcast:

+
mkdir ~/cylc-src/tutorial-broadcast
+cd ~/cylc-src/tutorial-broadcast
+
+
+

Copy the following configuration into a flow.cylc file:

+
[scheduling]
+    initial cycle point = 1012
+    [[graph]]
+        R1 = wipe_log => announce
+        PT1H = announce[-PT1H] => announce
+
+[runtime]
+    [[wipe_log]]
+        # Delete any files in the workflow's "share" directory.
+        script = rm "${CYLC_WORKFLOW_SHARE_DIR}/knights" || true
+
+    [[announce]]
+        script = echo "${CYLC_TASK_CYCLE_POINT} - ${MESSAGE}" >> "${FILE}"
+        [[[environment]]]
+            WORD = ni
+            MESSAGE = We are the knights who say \"${WORD}\"!
+            FILE = "${CYLC_WORKFLOW_SHARE_DIR}/knights"
+
+
+

We now have a workflow with an announce task which runs every hour, writing a +message to a log file (share/knights) when it does so. For the first cycle +the log entry will look like this:

+
10120101T0000Z - We are the knights who say "ni"!
+
+
+

The cylc broadcast command enables us to change runtime configuration +whilst the workflow is running. For instance we could change the value of the +WORD environment variable using the command:

+
cylc broadcast tutorial-broadcast -n announce -s "[environment]WORD=it"
+
+
+
    +
  • tutorial-broadcast is the name of the workflow.

  • +
  • -n announce tells Cylc we want to change the runtime configuration of the +announce task.

  • +
  • -s "[environment]WORD=it" changes the value of the WORD environment +variable to it.

  • +
+

Run the workflow then try using the cylc broadcast command to change the +message:

+
cylc validate .
+cylc install
+cylc play tutorial-broadcast
+cylc broadcast tutorial-broadcast -n announce -s "[environment]WORD=it"
+
+
+

Inspect the share/knights file, you should see the message change at +certain points.

+

Stop the workflow:

+
cylc stop tutorial-broadcast
+
+
+
+
+

In-Situ Example

+

We can call cylc broadcast from within a task’s script. This effectively +provides the ability for tasks to communicate between themselves.

+

It is almost always better for tasks to communicate using files but there are +some niche situations where communicating via cylc broadcast is justified. +This tutorial walks you through using cylc broadcast to communicate between +tasks.

+

Add the following recurrence to the graph section:

+
PT3H = announce[-PT1H] => change_word => announce
+
+
+

The change_word task runs the cylc broadcast command to randomly +change the WORD environment variable used by the announce task.

+

Add the following runtime configuration to the runtime section:

+
[[change_word]]
+    script = """
+        # Select random word.
+        IFS=',' read -r -a WORDS <<< $WORDS
+        WORD=${WORDS[$(date +%s) % ${#WORDS[@]}]}
+
+        # Broadcast random word to the announce task.
+        cylc broadcast $CYLC_WORKFLOW_ID -n announce -s "[environment]WORD=${WORD}"
+    """
+    [[[environment]]]
+        WORDS = ni, it, ekke ekke ptang zoo boing
+
+
+

Re-install and run the workflow, and inspect the log. +You should see the message change randomly +after every third entry (because the change_word task runs every 3 hours) +e.g:

+
10120101T0000Z - We are the knights who say "ni"!
+10120101T0100Z - We are the knights who say "ni"!
+10120101T0200Z - We are the knights who say "ni"!
+10120101T0300Z - We are the knights who say "ekke ekke ptang zoo boing!"
+
+
+

Stop the workflow:

+
cylc stop tutorial-broadcast
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/furthertopics/clock-triggered-tasks.html b/nightly_8.4/html/tutorial/furthertopics/clock-triggered-tasks.html new file mode 100644 index 00000000000..f1aba254495 --- /dev/null +++ b/nightly_8.4/html/tutorial/furthertopics/clock-triggered-tasks.html @@ -0,0 +1,326 @@ + + + + + + + Clock Triggered Tasks — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Clock Triggered Tasks

+

In a datetime cycling workflow the time represented by the +cycle points bear no relation to the real-world time. +Using clock-triggers we can make tasks wait until their cycle point time before +running.

+

Clock-triggering effectively enables us to tether the “cycle time” to the +“real world time” which we refer to as the wallclock time.

+
+

Note

+

Clock triggers are External Triggers. They differ from +custom external triggers only in that they are provided with Cylc, and +that the :interval suffix has no effect.

+
+
+

Clock Triggering

+

When clock-triggering tasks we can use different +offsets to the cycle time as follows:

+
my_clock_trigger = wall_clock(offset=<iso8601 duration>)
+
+
+
+

Note

+

Regardless of the offset used, the task still belongs to the cycle from +which the offset has been applied.

+
+
+
+

Example

+

Our example workflow will simulate a clock chiming on the hour.

+

Within your ~/cylc-src directory create a new directory called +clock-trigger:

+
mkdir ~/cylc-src/clock-trigger
+cd ~/cylc-src/clock-trigger
+
+
+

Paste the following code into a flow.cylc file:

+
[scheduler]
+    UTC mode = True # Ignore DST
+
+[scheduling]
+    initial cycle point = TODO
+    final cycle point = +P1D # Run for one day
+    [[graph]]
+        PT1H = bell
+
+[runtime]
+    [[root]]
+        [[[events]]]
+            mail events = failed
+    [[bell]]
+        script = printf 'bong%.02d\n' $(seq 1 $(cylc cyclepoint --print-hour))
+
+
+

Change the initial cycle point to 00:00 this morning (e.g. if it was +the first of January 2000 we would write 2000-01-01T00Z).

+

We now have a simple workflow with a single task that prints “bong” a number +of times equal to the (cycle point) hour.

+

Run your workflow using:

+
cylc validate .
+cylc install
+cylc play clock-trigger
+
+
+

Stop the workflow after a few cycles using cylc stop --now --now clock-trigger. +Notice how the tasks run as soon as possible rather than +waiting for the actual time to be equal to the cycle point.

+
+
+

Clock-Triggering Tasks

+

We want our clock to only ring in real-time rather than the simulated +cycle time.

+

To do this, modify the [scheduling][graph] section of +your flow.cylc:

+
PT1H = @wall_clock  => bell
+
+
+

This tells the workflow to clock trigger the bell task with a cycle +offset of 0 hours.

+

Save your changes, install and run your workflow.

+

Your workflow should now be running the bell task in real-time. Any cycle times +that have already passed (such as the one defined by initial cycle time) +will be run as soon as possible, while those in the future will wait for that +time to pass.

+

At this point you may want to leave your workflow running until the next hour +has passed in order to confirm the clock triggering is working correctly. +Once you are satisfied, stop your workflow.

+

By making the bell task a clock triggered task we have made it run in +real-time. Thus, when the wallclock time caught up with the cycle time, the +bell task triggered.

+
+
+

Adding More Clock-Triggered Tasks

+

Running clock triggered tests at the cycle time is a special case: +We will now modify our workflow to run tasks at quarter-past, half-past and +quarter-to the hour.

+

Open your flow.cylc and modify the [runtime] section by adding the +following:

+
[[quarter_past, half_past, quarter_to]]
+    script = echo 'chimes'
+
+
+

Edit the [[scheduling]] section to read:

+
initial cycle point = now
+final cycle point = +P1D # Run for one day
+[[xtriggers]]
+    quarter_past_trigger = wall_clock(offset=PT15M)
+    half_past_trigger = wall_clock(offset=PT30M)
+    quarter_to_trigger = wall_clock(offset=PT45M)
+[[graph]]
+    PT1H = """
+        @wall_clock => bell
+        @quarter_past_trigger => quarter_past
+        @half_past_trigger => half_past
+        @quarter_to_trigger => quarter_to
+    """
+
+
+

Note the different values used for the cycle offsets of the clock-trigger tasks.

+

Save your changes, install and run your workflow using:

+
cylc validate .
+cylc install
+cylc play clock-trigger
+
+
+
+

Note

+

Setting initial cycle point = now will run your workflow using the +current time at startup as the initial cycle point.

+
+

Again, notice how the tasks trigger until the current time is reached.

+

Leave your workflow running for a while to confirm it is working as expected +before stopping it.

+
+
+

Summary

+ +

For more information see the Cylc User Guide.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/furthertopics/family-triggers.html b/nightly_8.4/html/tutorial/furthertopics/family-triggers.html new file mode 100644 index 00000000000..7c6457eae6f --- /dev/null +++ b/nightly_8.4/html/tutorial/furthertopics/family-triggers.html @@ -0,0 +1,362 @@ + + + + + + + Family Triggers — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Family Triggers

+

To reduce duplication in the graph is is possible to write +dependencies using collections of tasks called +families).

+

This tutorial walks you through writing such dependencies using family +triggers.

+
+

Explanation

+

Dependencies between tasks can be written using a qualifier to describe +the task state that the dependency refers to (e.g. succeed +fail, etc). If a dependency does not use a qualifier then it is assumed +that the dependency refers to the succeed state e.g:

+
bake_bread => sell_bread           # sell_bread is dependent on bake_bread succeeding.
+bake_bread:succeed => sell_bread?  # sell_bread is dependent on bake_bread succeeding.
+sell_bread:fail? => throw_away     # throw_away is dependent on sell_bread failing.
+
+
+

The left-hand side of a dependency (e.g. sell_bread:fail) is +referred to as the trigger.

+
+

Note

+

sell_bread(:succeed) and sell_bread:fail are mutually exclusive +outcomes. As both appear in the graph above, it is +necessary to use the ? syntax to mark them as +Optional Outputs.

+
+

When we write a trigger involving a family, special qualifiers are required +to specify whether the dependency is concerned with all or any of the tasks +in that family reaching the desired state e.g:

+
    +
  • succeed-all

  • +
  • succeed-any

  • +
  • fail-all

  • +
+

Such triggers are referred to as +family triggers

+
+
+

Example

+

Create a new workflow called tutorial-family-triggers:

+
mkdir ~/cylc-src/tutorial-family-triggers
+cd ~/cylc-src/tutorial-family-triggers
+
+
+

Paste the following configuration into the flow.cylc file:

+
[scheduler]
+    UTC mode = True # Ignore DST
+[scheduling]
+    [[graph]]
+        R1 = visit_mine => MINERS
+[runtime]
+    [[visit_mine]]
+        script = sleep 5; echo 'off to work we go'
+
+    [[MINERS]]
+        script = """
+            sleep 5;
+            if (($RANDOM % 2)); then
+                echo 'Diamonds!'; true;
+            else
+                echo 'Nothing...'; false;
+            fi
+        """
+    [[doc, grumpy, sleepy, happy, bashful, sneezy, dopey]]
+        inherit = MINERS
+
+
+

You have now created a workflow that:

+
    +
  • Has a visit_mine task that sleeps for 5 seconds then outputs a +message.

  • +
  • Contains a MINERS family with a command in it that randomly succeeds +or fails.

  • +
  • Has 7 tasks that inherit from the MINERS family.

  • +
+

Validate, install and run the workflow:

+
cylc validate .
+cylc install
+cylc play tutorial-family-triggers
+
+
+

You should see the visit_mine task run, then trigger the members of the +MINERS family. Note that some of the MINERS tasks may fail so you +will need to stop your workflow using the “stop” button in the UI, or:

+
cylc stop tutorial-family-triggers
+
+
+
+
+

Family Triggering: Success

+

As you will have noticed by watching the workflow run, some of the tasks in the +MINERS family succeed and some fail.

+

We would like to add a task to sell any diamonds we find, but wait for all +the miners to report back first so we only make the one trip.

+

We can address this by using family triggers. In particular, we are going +to use the finish-all trigger to check for all members of the MINERS +family finishing, and the succeed-any trigger to check for any of the +tasks in the MINERS family succeeding.

+

Open your flow.cylc file and change the [[graph]] to look like +this:

+
[[graph]]
+    R1 = """
+        visit_mine => MINERS?
+        MINERS:finish-all & MINERS:succeed-any? => sell_diamonds
+    """
+
+
+

Then, add the following task to the [runtime] section:

+
[[sell_diamonds]]
+   script = sleep 5
+
+
+

These changes add a sell_diamonds task to the workflow which is run once +all the MINERS tasks have finished and if any of them have succeeded.

+

Save your changes and run your workflow. You should see the new +sell_diamonds task being run once all the miners have finished and at +least one of them has succeeded. Stop your workflow as described above.

+
+

See also

+

User guide on +family triggers and optional outputs.

+
+
+
+

Family Triggering: Failure

+

Cylc also allows us to trigger off failure of tasks in a particular family.

+

We would like to add another task to close down unproductive mineshafts once +all the miners have reported back and had time to discuss their findings.

+

To do this we will make use of family triggers in a similar manner to before.

+

Open your flow.cylc file and change the [[graph]] to look like +this:

+
[[graph]]
+    R1 = """
+        visit_mine => MINERS?
+        MINERS:finish-all & MINERS:succeed-any? => sell_diamonds
+        MINERS:finish-all & MINERS:fail-any? => close_shafts
+    """
+
+
+

Alter the [[sell_diamonds]] section to look like this:

+
[[close_shafts, sell_diamonds]]
+    script = sleep 5
+
+
+

These changes add a close_shafts task which is run once all the +MINERS tasks have finished and any of them have failed.

+

Save your changes and run your workflow. You should see the new +close_shafts run should any of the MINERS tasks be in the failed +state once they have all finished.

+
+
+

Different Triggers

+

Other family qualifiers beyond those covered in the +example are also available.

+

The following types of “all” qualifier are available:

+
    +
  • :start-all - all the tasks in the family have started

  • +
  • :succeed-all - all the tasks in the family have succeeded

  • +
  • :fail-all - all the tasks in the family have failed

  • +
  • :finish-all - all the tasks in the family have finished

  • +
+

The following types of “any” qualifier are available:

+
    +
  • :start-any - at least one task in the family has started

  • +
  • :succeed-any - at least one task in the family has succeeded

  • +
  • :fail-any - at least one task in the family has failed

  • +
  • :finish-any - at least one task in the family has finished

  • +
+
+
+

Summary

+
    +
  • Family triggers allow you to write dependencies for collections of tasks.

  • +
  • Like task triggers, family triggers can be based on +success, failure, starting and finishing of tasks in a family.

  • +
  • Family triggers can trigger off either all or any of the tasks in a +family.

  • +
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/furthertopics/index.html b/nightly_8.4/html/tutorial/furthertopics/index.html new file mode 100644 index 00000000000..d3ca046eb91 --- /dev/null +++ b/nightly_8.4/html/tutorial/furthertopics/index.html @@ -0,0 +1,187 @@ + + + + + + + Further Topics — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Further Topics

+

This section looks at further topics in cylc.

+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/furthertopics/inheritance.html b/nightly_8.4/html/tutorial/furthertopics/inheritance.html new file mode 100644 index 00000000000..fb437bcbd56 --- /dev/null +++ b/nightly_8.4/html/tutorial/furthertopics/inheritance.html @@ -0,0 +1,728 @@ + + + + + + + Inheritance — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Inheritance

+

We have seen in the runtime tutorial how +tasks can be grouped into families.

+

In this tutorial we will look at nested families, inheritance order and +multiple inheritance.

+
+

Inheritance Hierarchy

+

Within your ~/cylc-src directory create a new directory called +inheritance-tutorial:

+
mkdir ~/cylc-src/inheritance-tutorial
+cd ~/cylc-src/inheritance-tutorial
+
+
+

And paste the following code into a flow.cylc file. This +defines two tasks each representing different aircraft, the Airbus A380 jumbo +jet and the Robson R44 helicopter:

+A380 +R44 +
[scheduling]
+    [[graph]]
+        R1 = a380 & r44
+
+[runtime]
+    [[VEHICLE]]
+        init-script = echo 'Boarding'
+        pre-script = echo 'Departing'
+        post-script = echo 'Arriving'
+
+    [[AIR_VEHICLE]]
+        inherit = VEHICLE
+        [[[meta]]]
+            description = A vehicle which can fly.
+    [[AIRPLANE]]
+        inherit = AIR_VEHICLE
+        [[[meta]]]
+            description = An air vehicle with fixed wings.
+        [[[environment]]]
+            CAN_TAKE_OFF_VERTICALLY = false
+    [[HELICOPTER]]
+        inherit = AIR_VEHICLE
+        [[[meta]]]
+            description = An air vehicle with rotors.
+        [[[environment]]]
+            CAN_TAKE_OFF_VERTICALLY = true
+
+    [[a380]]
+        inherit = AIRPLANE
+        [[[meta]]]
+            title = Airbus A380 Jumbo-Jet.
+    [[r44]]
+        inherit = HELICOPTER
+        [[[meta]]]
+            title = Robson R44 Helicopter.
+
+
+
+

Note

+

The [meta] section is a freeform section where we can define metadata +to be associated with a task, family or the workflow itself.

+

This metadata should not be mistaken for Rose Configuration Metadata.

+
+
+

Reminder

+

By convention we write family names in upper case (with the exception of the +special root family) and task names in lower case.

+
+

These two tasks sit at the bottom of an inheritance tree. The cylc graph +command has an option (-n) for drawing such inheritance hierarchies:

+
cylc graph -n . &
+
+
+

Running this command will generate the following output:

+
+

digraph Example { +AIRPLANE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +a380 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +AIRPLANE -> a380 [color=royalblue]; +HELICOPTER [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +r44 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +HELICOPTER -> r44 [color=royalblue]; +root [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +root -> VEHICLE [color=royalblue]; +AIR_VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +VEHICLE -> AIR_VEHICLE [color=royalblue]; +AIR_VEHICLE -> AIRPLANE [color=royalblue]; +AIR_VEHICLE -> HELICOPTER [color=royalblue]; +}

+
+
+

Note

+

The root family sits at the top of the inheritance tree as all +tasks/families automatically inherit it:

+
+

Cylc handles inheritance by starting with the root family and working down the +inheritance tree applying each section in turn.

+

To see the resulting configuration for the a380 task use the +cylc config command:

+
cylc config . -i "[runtime][a380]"
+
+
+

You should see some settings which have been inherited from the VEHICLE and +AIRPLANE families as well as a couple defined in the a380 task.

+
init-script = echo 'Boarding'                       # Inherited from VEHICLE
+pre-script = echo 'Departing'                       # Inherited from VEHICLE
+post-script = echo 'Arriving'                       # Inherited from VEHICLE
+inherit = AIRPLANE                                  # Defined in a380
+[[[meta]]]
+    description = An air vehicle with fixed wings.  # Inherited from AIR_VEHICLE - overwritten by AIRPLANE
+    title = Airbus A380 Jumbo-Jet.                  # Defined in a380
+[[[environment]]]
+    CAN_TAKE_OFF_VERTICALLY = false                 # Inherited from AIRPLANE
+
+
+

Note that the description setting is defined in the AIR_VEHICLE +family but is overwritten by the value specified in the AIRPLANE family.

+
+
+

Multiple Inheritance

+

Next we want to add a vehicle called the V-22 Osprey to the workflow. The V-22 +is a cross between a plane and a helicopter - it has wings but can take-off and +land vertically.

+https://upload.wikimedia.org/wikipedia/commons/e/e3/MV-22_mcas_Miramar_2014.JPG +

As the V-22 can be thought of as both a plane and a helicopter we want it to +inherit from both the AIRPLANE and HELICOPTER families. In Cylc we can +inherit from multiple families by separating their names with commas:

+

Add the following task to your flow.cylc file.

+
[[v22]]
+    inherit = AIRPLANE, HELICOPTER
+    [[[meta]]]
+        title = V-22 Osprey Military Aircraft.
+
+
+

Re-run the cylc graph command.

+

The inheritance hierarchy should now look like this:

+
+

digraph Example { +AIRPLANE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +v22 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +AIRPLANE -> v22 [color=royalblue]; +a380 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +AIRPLANE -> a380 [color=royalblue]; +HELICOPTER [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +HELICOPTER -> v22 [color=royalblue]; +r44 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +HELICOPTER -> r44 [color=royalblue]; +root [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +root -> VEHICLE [color=royalblue]; +AIR_VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +VEHICLE -> AIR_VEHICLE [color=royalblue]; +AIR_VEHICLE -> AIRPLANE [color=royalblue]; +AIR_VEHICLE -> HELICOPTER [color=royalblue]; +}

+
+

Inspect the configuration of the v22 task using the cylc config +command.

+
+

Hint

+
cylc config . -i "[runtime][v22]"
+
+
+
+

You should see that the CAN_TASK_OFF_VERTICALLY environment variable has +been set to false which isn’t right. This is because of the order in which +inheritance is applied.

+

Cylc handles multiple-inheritance by applying each family from right to left. +For the v22 task we specified inherit = AIRPLANE, HELICOPTER so the +HELICOPTER family will be applied first and the AIRPLANE family after.

+

The inheritance order would be as follows:

+
root
+VEHICLE
+AIR_VEHICLE
+HELICOPTER   # sets "CAN_TAKE_OFF_VERTICALLY to "true"
+AIRPLANE     # sets "CAN_TAKE_OFF_VERTICALLY to "false"
+v22
+
+
+

We could fix this problem by changing the order of inheritance:

+
inherit = HELICOPTER, AIRPLANE
+
+
+

Now the HELICOPTER family is applied second so its values will override any +in the AIRPLANE family.

+
root
+VEHICLE
+AIR_VEHICLE
+AIRPLANE     # sets "CAN_TAKE_OFF_VERTICALLY to "false"
+HELICOPTER   # sets "CAN_TAKE_OFF_VERTICALLY to "true"
+v22
+
+
+

Inspect the configuration of the v22 task using cylc config to +confirm this.

+
+
+

More Inheritance

+

We will now add some more families and tasks to the workflow.

+
+

Engine Type

+

Next we will define four families to represent three different types of engine.

+
+

digraph Example { +size = "5,5" + +ENGINE [color=royalblue, fillcolor=powderblue, shape=box, style=filled, + margin="0.3,0.055"] +TURBINE_ENGINE [color=royalblue, fillcolor=powderblue, shape=box, + style=filled, margin="0.3,0.055"] +INTERNAL_COMBUSTION_ENGINE [color=royalblue, fillcolor=powderblue, + shape=box, style=filled, margin="0.3,0.055"] +HUMAN_ENGINE [color=royalblue, fillcolor=powderblue, shape=box, + style=filled, margin="0.3,0.055"] + +"ENGINE" -> "TURBINE_ENGINE" +"ENGINE" -> "INTERNAL_COMBUSTION_ENGINE" +"ENGINE" -> "HUMAN_ENGINE" +}

+
+

Each engine type should set an environment variable called FUEL which we +will assign to the following values:

+
    +
  • Turbine - kerosene

  • +
  • Internal Combustion - petrol

  • +
  • Human - pizza

  • +
+

Add lines to the runtime section to represent these four families.

+
+

Solution

+
[[ENGINE]]
+[[TURBINE_ENGINE]]
+    inherit = ENGINE
+    [[[environment]]]
+        FUEL = kerosene
+[[INTERNAL_COMBUSTION_ENGINE]]
+    inherit = ENGINE
+    [[[environment]]]
+        FUEL = petrol
+[[HUMAN_ENGINE]]
+    inherit = ENGINE
+    [[[environment]]]
+        FUEL = pizza
+
+
+
+

We now need to make the three aircraft inherit from one of the three engines. +The aircraft use the following types of engine:

+
    +
  • A380 - turbine

  • +
  • R44 - internal combustion

  • +
  • V22 - turbine

  • +
+

Modify the three tasks so that they inherit from the relevant engine families.

+
+

Solution

+
[[a380]]
+    inherit = AIRPLANE, TURBINE_ENGINE
+    [[[meta]]]
+        title = Airbus A380 Jumbo-Jet.
+[[r44]]
+    inherit = HELICOPTER, INTERNAL_COMBUSTION_ENGINE
+    [[[meta]]]
+        title = Robson R44 Helicopter.
+[[v22]]
+    inherit = AIRPLANE, HELICOPTER, TURBINE_ENGINE
+    [[[meta]]]
+        title = V-22 Ofsprey Military Aircraft.
+
+
+
+
+
+

Penny Farthing

+

Next we want to add a new type of vehicle, an old-fashioned bicycle called a +penny farthing.

+Penny Farthing Bicycle +

To do this we will need to add two new families, LAND_VEHICLE and +BICYCLE as well as a new task, penny_farthing related in the +following manner:

+
+

digraph Example { +VEHICLE [color=royalblue, fillcolor=powderblue, shape=box, style=filled] +LAND_VEHICLE [color=royalblue, fillcolor=powderblue, shape=box, + style=filled] +BICYCLE [color=royalblue, fillcolor=powderblue, shape=box, style=filled] +HUMAN_ENGINE [color=royalblue, fillcolor=powderblue, shape=box, + style=filled, margin="0.3,0.055"] +penny_farthing [color=royalblue, fillcolor=powderblue, shape=box, + style=filled, margin="0.3,0.055"] +VEHICLE -> LAND_VEHICLE -> BICYCLE -> penny_farthing +HUMAN_ENGINE -> penny_farthing +}

+
+

Add lines to the runtime section to represent the two new families and one +task outlined above.

+

Add a description ([meta]description) to the LAND_VEHICLE and +BICYCLE families and a title ([meta]title) to the penny_farthing +task.

+
+

Solution

+
[[LAND_VEHICLE]]
+    inherit = VEHICLE
+    [[[meta]]]
+        description = A vehicle which can travel over the ground.
+
+[[BICYCLE]]
+    inherit = LAND_VEHICLE
+    [[[meta]]]
+        description = A small two-wheeled vehicle.
+
+[[penny_farthing]]
+    inherit = BICYCLE, HUMAN_ENGINE
+    [[[meta]]]
+        title = An old-fashioned bicycle.
+
+
+
+

Using cylc config to inspect the configuration of the penny_farthing +task we can see that it inherits settings from the VEHICLE, +BICYCLE and HUMAN_ENGINE families.

+
inherit = BICYCLE, HUMAN_ENGINE
+init-script = echo 'Boarding'  # Inherited from VEHICLE
+pre-script = echo 'Departing'  # Inherited from VEHICLE
+post-script = echo 'Arriving'  # Inherited from VEHICLE
+[[[environment]]]
+    FUEL = pizza               # Inherited from HUMAN_ENGINE
+[[[meta]]]
+    description = A small two-wheeled vehicle.  # Inherited from LAND_VEHICLE - overwritten by BICYCLE
+    title = An old-fashioned bicycle.           # Defined in penny_farthing
+
+
+
+

Hint

+
cylc config . -i "[runtime]penny_farthing"
+
+
+
+
+
+

Hovercraft

+

We will now add a hovercraft called the Hoverwork BHT130, better known to some +as the Isle Of Wight Ferry.

+Hoverwork BHT130 Hovercraft +

Hovercraft can move over both land and water and in some respects can be thought +of as flying vehicles.

+
+

digraph Example { +size = "7,5" + +VEHICLE [color=royalblue, fillcolor=powderblue, shape=box, style=filled] +AIR_VEHICLE [color=royalblue, fillcolor=powderblue, shape=box, style=filled] +LAND_VEHICLE [color=royalblue, fillcolor=powderblue, shape=box, + style=filled] +WATER_VEHICLE [color=royalblue, fillcolor=powderblue, shape=box, + style=filled] +HOVERCRAFT [color=royalblue, fillcolor=powderblue, shape=box, style=filled] +bht130 [color=royalblue, fillcolor=powderblue, shape=box, style=filled] +ENGINE [color=royalblue, fillcolor=powderblue, shape=box, style=filled] +INTERNAL_COMBUSTION_ENGINE [color=royalblue, fillcolor=powderblue, + shape=box, style=filled, margin="0.3,0.055"] +VEHICLE -> AIR_VEHICLE -> HOVERCRAFT +VEHICLE -> LAND_VEHICLE -> HOVERCRAFT +VEHICLE -> WATER_VEHICLE -> HOVERCRAFT +HOVERCRAFT -> bht130 +ENGINE -> INTERNAL_COMBUSTION_ENGINE -> bht130 +}

+
+

Write new families and one new task to represent the above structure.

+

Add a description ([meta]description) to the WATER_VEHICLE and +HOVERCRAFT families and a title ([meta]title) to the bht130 task.

+
+

Solution

+
[[WATER_VEHICLE]]
+    inherit = VEHICLE
+    [[[meta]]]
+        description = A vehicle which can travel over water.
+
+[[HOVERCRAFT]]
+    inherit = LAND_VEHICLE, AIR_VEHICLE, WATER_VEHICLE
+    [[[meta]]]
+        description = A vehicle which can travel over ground, water and ice.
+
+[[bht130]]
+    inherit = HOVERCRAFT, INTERNAL_COMBUSTION_ENGINE
+    [[[meta]]]
+        title = Griffon Hoverwork BHT130 (Isle Of Whight Ferry).
+
+
+
+
+
+
+

Finished Workflow

+

You should now have a workflow with an inheritance hierarchy which looks like +this:

+
+

digraph Example { +size = "7, 5" + +root [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +ENGINE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +root -> ENGINE [color=royalblue]; +VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +root -> VEHICLE [color=royalblue]; +INTERNAL_COMBUSTION_ENGINE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled, + margin="0.3,0.055"]; +ENGINE -> INTERNAL_COMBUSTION_ENGINE [color=royalblue]; +TURBINE_ENGINE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled, + margin="0.3,0.055"]; +ENGINE -> TURBINE_ENGINE [color=royalblue]; +HUMAN_ENGINE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled, + margin="0.3,0.055"]; +ENGINE -> HUMAN_ENGINE [color=royalblue]; +LAND_VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +VEHICLE -> LAND_VEHICLE [color=royalblue]; +WATER_VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +VEHICLE -> WATER_VEHICLE [color=royalblue]; +AIR_VEHICLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +VEHICLE -> AIR_VEHICLE [color=royalblue]; +r44 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +INTERNAL_COMBUSTION_ENGINE -> r44 [color=royalblue]; +bht130 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +INTERNAL_COMBUSTION_ENGINE -> bht130 [color=royalblue]; +v22 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +TURBINE_ENGINE -> v22 [color=royalblue]; +a380 [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +TURBINE_ENGINE -> a380 [color=royalblue]; +penny_farthing [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled, + margin="0.3,0.055"]; +HUMAN_ENGINE -> penny_farthing [color=royalblue]; +AIRPLANE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +AIRPLANE -> v22 [color=royalblue]; +AIRPLANE -> a380 [color=royalblue]; +HELICOPTER [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +HELICOPTER -> v22 [color=royalblue]; +HELICOPTER -> r44 [color=royalblue]; +HOVERCRAFT [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +HOVERCRAFT -> bht130 [color=royalblue]; +LAND_VEHICLE -> HOVERCRAFT [color=royalblue]; +BICYCLE [color=royalblue, + fillcolor=powderblue, + shape=box, + style=filled]; +LAND_VEHICLE -> BICYCLE [color=royalblue]; +WATER_VEHICLE -> HOVERCRAFT [color=royalblue]; +AIR_VEHICLE -> AIRPLANE [color=royalblue]; +AIR_VEHICLE -> HELICOPTER [color=royalblue]; +AIR_VEHICLE -> HOVERCRAFT [color=royalblue]; +BICYCLE -> penny_farthing [color=royalblue]; +}

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/furthertopics/message-triggers.html b/nightly_8.4/html/tutorial/furthertopics/message-triggers.html new file mode 100644 index 00000000000..59a49aa52dd --- /dev/null +++ b/nightly_8.4/html/tutorial/furthertopics/message-triggers.html @@ -0,0 +1,558 @@ + + + + + + + Message Triggers — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Message Triggers

+

Message triggers allow us to trigger dependent tasks +before the upstream task has completed.

+
+

Explanation

+

We have seen before that tasks can have +qualifiers for different +task states. +Message triggers are essentially custom qualifiers. +We can produce a bespoke output while our task is still running. +This output could be, for example, a report or perhaps another task.

+
+
+

Usage

+

Message triggers are particularly useful if we have +a long running task and we want to produce multiple tailored outputs whilst +this task is running, rather than having to wait for the task to +complete.

+

We could also set up message triggers to, for example, +send an email to inform us that a submission has failed, making use of Cylc’s +task event handling system. More information is available on these in the +Cylc User Guide.

+

Message triggers provide a superior solution to +the problem of file system polling. We could, for example, design our workflow +such that we check if our task is finished by polling at intervals. +It is inefficient to ‘spam’ task hosts with polling commands, it is preferable +to set up a message trigger.

+
+
+

How to create a message trigger

+

In order to get our workflow to trigger messages, we need to:

+
    +
  • +
    specify our custom message in a section called [[outputs]] within the

    [runtime] section of our workflow,

    +
    +
    +
  • +
  • +
    add cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" "YOUR CHOSEN TRIGGER MESSAGE"

    to the script section of [runtime], your chosen trigger message +should be unique and should exactly match the message defined in +[[outputs]].

    +
    +
    +
  • +
  • Refer to these messages in the [dependencies] section of our workflow.

  • +
+
+

Note

+

The message will be recorded in the workflow’s scheduler log. +See Cylc Message for details of how messages appear.

+
+

These outputs are then triggered during the running of the task. +We can use these to manage tasks dependent on partially completed tasks.

+

So, a basic example, where we have a task foo, that when partially completed +triggers another task bar and when fully completed triggers another task, baz.

+
+
[scheduling]
+    [[graph]]
+        R1 = """
+            foo:out1 => bar
+            foo => baz
+        """
+[runtime]
+    [[foo]]
+        script = """
+            sleep 5
+            cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" "file 1 done"
+            sleep 10
+        """
+        [[[outputs]]]
+            out1 = "file 1 done"
+
+    [[bar, baz]]
+        script = sleep 10
+
+
+
+
+

Practical

+

In this practical example, we will create a workflow to demonstrate +message triggers. We will use message triggers +to both produce a report and trigger a new task from a partially completed +task.

+
    +
  1. Create a new directory.

    +

    Within your ~/cylc-src directory create a new directory called

    +

    message-triggers and move into it:

    +
    mkdir ~/cylc-src/message-triggers
    +cd ~/cylc-src/message-triggers
    +
    +
    +
  2. +
  3. Install the script needed for our workflow

    +

    The workflow we will be designing requires a bash script, random.sh, +to produce our report. It will simply create a text file report.txt +with some random numbers in it. This will be executed when the associated +task is run.

    +

    Scripts should be kept in the bin sub-directory within the +run directory. If a /bin +exists in the run directory, it will be prepended $PATH at run +time.

    +

    Create a /bin directory.

    +
    mkdir ~/cylc-src/message-triggers/bin
    +
    +
    +

    Create a bash script in the bin directory:

    +
    touch bin/random.sh
    +
    +
    +

    We will need to make this script executable.

    +
    chmod +x bin/random.sh
    +
    +
    +

    Open the file and paste the following basic bash script into it:

    +
    #!/usr/bin/env bash
    +set -eu  # Prevent bash script failing quietly.
    +
    +counter=1
    +
    +while [ $counter -le 10 ]; do
    +    newrand=$(( (( RANDOM % 40) + 1 ) ));
    +    echo $newrand >> report.txt;
    +    counter=$((counter + 1));
    +done
    +
    +
    +
  4. +
  5. Create a new workflow.

    +

    Create a flow.cylc file and paste the following basic workflow into it:

    +
    [meta]
    +    title = "test workflow to demo message triggers"
    +
    +[scheduler]
    +    UTC mode = True
    +
    +[scheduling]
    +    initial cycle point = 2019-06-27T00Z
    +    final cycle point = 2019-10-27T00Z
    +    [[graph]]
    +        P2M = """
    +            long_forecasting_task =>  another_weather_task
    +            long_forecasting_task => different_weather_task
    +            long_forecasting_task[-P2M] => long_forecasting_task
    +        """
    +
    +
    +

    This is a basic workflow, currently it does not have any message triggers +attached to any task.

    +
  6. +
  7. Define our tasks in the runtime section.

    +

    Next we want to create our runtime section of our workflow. +First we define what the tasks do. In this example +long_forecasting_task will sleep, create a file containing some +random numbers and produce a message. +(Note that the random number generator bash script has already been +preloaded into your bin directory.) +another_weather_task and different_weather_task simply sleep.

    +

    Add the following code to the flow.cylc file.

    +
    [runtime]
    +
    +    [[long_forecasting_task]]
    +        script = """
    +            sleep 2
    +            random.sh
    +
    +            sleep 2
    +            random.sh
    +
    +            sleep 2
    +            random.sh
    +        """
    +
    +    [[another_weather_task, different_weather_task]]
    +        script = sleep 1
    +
    +
    +
  8. +
  9. Create message triggers.

    +

    We now have a workflow with a task, long_forecasting_task which, after +it has fully completed, triggers two more tasks, another_weather_task +and different_weather_task.

    +

    Suppose we want another_weather_task and different_weather_task +to start before long_forecasting_task has fully completed, perhaps +after some data has become available.

    +

    In this case, we shall trigger another_weather_task after one set of +random numbers has been created +and different_weather_task after a second set of random numbers has +been created.

    +

    There are three aspects of creating message triggers. +The first is to create the messages. Within runtime, TASK in our +workflow, we need to create a sub-section called outputs. Here we create +our custom outputs.

    +
    +        [[[outputs]]]
    ++            update1 = "Task partially complete, report ready to view"
    ++            update2 = "Task partially complete, report updated"
    +
    +
    +

    The second thing we need to do is to create a cylc message in our script. +This should be placed where you want the message to be called. In our +case, this is after each of the first two set of random numbers are +generated.

    +
    +

    Tip

    +

    Remember that the cylc message should exactly match the outputs +stated in our [[[outputs]]] section.

    +
    +

    Modify the [[long_forecasting_task]] script in the flow.cylc file +as follows:

    +
    [runtime]
    +
    +    [[long_forecasting_task]]
    +        script = """
    +            sleep 2
    +            random.sh
    ++           cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \
    ++                "Task partially complete, report ready to view"
    +            sleep 2
    +            random.sh
    ++           cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \
    ++               "Task partially complete, report updated"
    +            sleep 2
    +            random.sh
    +        """
    +
    +
    +

    Lastly, we need to make reference to the messages in the +graph section. +This will ensure your tasks trigger off of the messages correctly.

    +

    Adapt the [[dependencies]] section in the flow.cylc file to read as +follows:

    +
             [[[P2M]]]
    +             graph = """
    +-               long_forecasting_task =>  another_weather_task
    +-               long_forecasting_task => different_weather_task
    ++               long_forecasting_task:update1 =>  another_weather_task
    ++               long_forecasting_task:update2 => different_weather_task
    +                long_forecasting_task[-P2M] => long_forecasting_task
    +            """
    +
    +
    +

    This completes our flow.cylc file.

    +

    Our final workflow should look like this:

    +
    +

    Solution

    +
    [meta]
    +    title = "test workflow to demo message triggers"
    +
    +[scheduler]
    +    UTC mode = True
    +
    +[scheduling]
    +    initial cycle point = 2019-06-27T00Z
    +    final cycle point = 2019-10-27T00Z
    +
    +    [[graph]]
    +        P2M = """
    +            long_forecasting_task:update1 =>  another_weather_task
    +            long_forecasting_task:update2 => different_weather_task
    +            long_forecasting_task[-P2M] => long_forecasting_task
    +        """
    +
    +[runtime]
    +    [[long_forecasting_task]]
    +        script = """
    +            sleep 2
    +            random.sh
    +            cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \
    +                "Task partially complete, report ready to view"
    +            sleep 2
    +            random.sh
    +            cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \
    +                "Task partially complete, report updated"
    +            sleep 2
    +            random.sh
    +        """
    +        [[[outputs]]]
    +            update1 = "Task partially complete, report ready to view"
    +            update2 = "Task partially complete, report updated"
    +
    +    [[another_weather_task, different_weather_task]]
    +        script = sleep 1
    +
    +
    +
    +
  10. +
  11. Validate the workflow.

    +

    It is a good idea to check that our flow.cylc file does not have any +configuration issues.

    +

    Run cylc validate to check for any errors:

    +
    cylc validate .
    +
    +
    +
  12. +
  13. Install and Play the workflow.

    +

    Now we are ready to run our workflow. Validate, install, then open +the GUI or TUI and play +the workflow.

    +
    cylc validate .
    +cylc install
    +cylc play message-triggers
    +
    +
    +

    Your workflow should now run, the tasks should succeed.

    +
  14. +
  15. Inspect the work directory.

    +

    You can now check for your report outputs. These should appear in the +work directory of the workflow. All being well, our first cycle +point should produce a test file with some random numbers, and each +subsequent cycle point file should have more random numbers added.

    +
  16. +
  17. Extension.

    +

    Suppose now we would like to send an email alerting us to the reports +being ready to view.

    +

    We will need to add to our flow.cylc file.

    +

    In the runtime section, add a sub-section called [[[events]]]. +Within this section we will make use of the built-in setting +mail events. +Here, we specify a list of events for which notifications should be sent.

    +

    The events we are interested in are, in this case, our outputs.

    +

    Add the following code to your [[[events]]] section.

    +
    +
    [[[events]]]
    +    mail events = update1, update2
    +
    +
    +

    Our updated workflow should look like this:

    +
    +
    +

    Solution

    +
    [scheduler]
    +    UTC mode = True
    +[meta]
    +    title = "test workflow to demo message triggers"
    +[scheduling]
    +    initial cycle point = 2019-06-27T00Z
    +    final cycle point = 2019-10-27T00Z
    +    [[graph]]
    +        P2M = """
    +            long_forecasting_task:update1 =>  another_weather_task
    +            long_forecasting_task:update2 => different_weather_task
    +            long_forecasting_task[-P2M] => long_forecasting_task
    +        """
    +[runtime]
    +    [[long_forecasting_task]]
    +        script = """
    +            sleep 2
    +            random.sh
    +            cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \
    +                "Task partially complete, report ready to view"
    +            sleep 2
    +            random.sh
    +            cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \
    +                "Task partially complete, report updated"
    +            sleep 2
    +            random.sh
    +        """
    +
    +        [[[outputs]]]
    +            update1 = "Task partially complete, report ready to view"
    +            update2 = "Task partially complete, report updated"
    +
    +        [[[events]]]
    +            mail events = update1, update2
    +
    +    [[another_weather_task, different_weather_task]]
    +        script = sleep 1
    +
    +
    +
    +

    Save your changes and run your workflow. +Check your emails and you should have, one email for the first update and, +a second email alerting you to the subsequent updated reports being ready.

    +

    Note that the second email automatically bundles the messages to prevent +your inbox from being flooded.

    +
  18. +
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/furthertopics/queues.html b/nightly_8.4/html/tutorial/furthertopics/queues.html new file mode 100644 index 00000000000..fe7850f2b75 --- /dev/null +++ b/nightly_8.4/html/tutorial/furthertopics/queues.html @@ -0,0 +1,276 @@ + + + + + + + Queues — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Queues

+

Queues are used to put a limit on the number of tasks that will be active at +any one time, even if their dependencies are satisfied. This avoids swamping +systems with too many tasks at once.

+
+

Example

+

In this example, our workflow manages a particularly understaffed restaurant.

+

Create a new workflow called queues-tutorial:

+
mkdir -p ~/cylc-src/queues-tutorial
+cd ~/cylc-src/queues-tutorial
+
+
+

And paste the following into flow.cylc:

+
[scheduling]
+    [[graph]]
+        R1 = """
+            open_restaurant => steak1 & steak2 & pasta1 & pasta2 & pasta3 & \
+                               pizza1 & pizza2 & pizza3 & pizza4
+            steak1 => ice_cream1
+            steak2 => cheesecake1
+            pasta1 => ice_cream2
+            pasta2 => sticky_toffee1
+            pasta3 => cheesecake2
+            pizza1 => ice_cream3
+            pizza2 => ice_cream4
+            pizza3 => sticky_toffee2
+            pizza4 => ice_cream5
+        """
+
+[runtime]
+    [[open_restaurant]]
+    [[MAINS]]
+    [[DESSERT]]
+    [[steak1,steak2,pasta1,pasta2,pasta3,pizza1,pizza2,pizza3,pizza4]]
+        inherit = MAINS
+    [[ice_cream1,ice_cream2,ice_cream3,ice_cream4,ice_cream5]]
+        inherit = DESSERT
+    [[cheesecake1,cheesecake2,sticky_toffee1,sticky_toffee2]]
+        inherit = DESSERT
+
+
+
+

Note

+

In graph sections, lines can be split on &, i.e. the +following two examples are equivalent:

+
foo => bar &
+       baz
+
+
+
foo => bar & baz
+
+
+

| (or), and => act in the same way.

+
+

Validate, install and play the workflow:

+
cylc validate .
+cylc install --run-name without-queues
+
+
+

Look at the workflow with The Cylc GUI or The Cylc TUI

+

Play the workflow, either from the GUI or the command line:

+
cylc play queues-tutorial/without-queues
+
+
+

You will see that all the steak, pasta, and pizza tasks are run +at once, swiftly followed by all the ice_cream, cheesecake, +sticky_toffee tasks as the customers order from the dessert menu.

+

This will overwhelm our restaurant staff! The chef responsible for MAINS +can only handle 3 tasks at any given time, and the DESSERT chef can only +handle 2.

+

We need to add some queues. Add a [queues] section to the [scheduling] +section like so:

+
[scheduling]
+    [[queues]]
+        [[[mains_chef_queue]]]
+            limit = 3  # Only 3 mains dishes at one time.
+            members = MAINS
+        [[[dessert_chef_queue]]]
+            limit = 2  # Only 2 dessert dishes at one time.
+            members = DESSERT
+
+
+

Install and play the workflow:

+
cylc validate .
+cylc install --run-name tutorial-with-queues
+
+
+

Play the workflow using the GUI +or TUI.

+

You should see that there are now never more than 3 active MAINS tasks +running and never more than 2 active DESSERT tasks running.

+

The customers will obviously have to wait!

+
+
+

Further Reading

+

For more information, see the Cylc User Guide.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/furthertopics/retries.html b/nightly_8.4/html/tutorial/furthertopics/retries.html new file mode 100644 index 00000000000..f95abceff1c --- /dev/null +++ b/nightly_8.4/html/tutorial/furthertopics/retries.html @@ -0,0 +1,316 @@ + + + + + + + Retries — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Retries

+

Retries allow us to automatically re-submit tasks which have failed due to +failure in submission or execution.

+
+

Purpose

+

Retries can be useful for tasks that occasionally fail for known, fixable +reasons. Cylc can rerun a failing job multiple times, with user-defined delays +between tries.

+

Tasks that fail because of temporary hardware or network outages may succeed if +simply resubmitted after a delay. Others might succeed if configured differently +on the retry.

+

A job environment variable $CYLC_TASK_TRY_NUMBER increments with each try, +to allow try-dependent behaviour in the task script.

+
+

Note

+

Tasks only enter the submit-failed state if job submission fails with no +retries left. Otherwise they return to the waiting state, to wait on the +next try.

+

Tasks only enter the failed state if job execution fails with no retries +left. Otherwise they return to the waiting state, to wait on the next try.

+
+
+
+

Example

+Two dice both showing the number six +

Create a new workflow by running the following commands:

+
mkdir -p ~/cylc-src/retries-tutorial
+cd ~/cylc-src/retries-tutorial
+
+
+

And paste the following code into a flow.cylc file. This workflow has a +roll_doubles task that simulates trying to roll doubles using two dice:

+
[scheduler]
+    UTC mode = True # Ignore DST
+
+[scheduling]
+    [[graph]]
+        R1 = start => roll_doubles => win
+
+[runtime]
+    [[start]]
+    [[win]]
+    [[roll_doubles]]
+        script = """
+            sleep 10
+            RANDOM=$$  # Seed $RANDOM
+            DIE_1=$((RANDOM%6 + 1))
+            DIE_2=$((RANDOM%6 + 1))
+            echo "Rolled $DIE_1 and $DIE_2..."
+            if (($DIE_1 == $DIE_2)); then
+                echo "doubles!"
+            else
+                exit 1
+            fi
+        """
+
+
+
+
+

Running Without Retries

+

Let’s see what happens when we run the workflow as it is. +Look at the workflow with The Cylc GUI or The Cylc TUI

+

Then validate install and run the workflow:

+
cylc validate .
+cylc install
+cylc play retries-tutorial
+
+
+

Unless you’re lucky, the workflow should fail at the roll_doubles task.

+

Stop the workflow:

+
cylc stop retries-tutorial
+
+
+
+
+

Configuring Retries

+

We need to tell Cylc to retry it a few times. To do this, add the following +to the end of the [[roll_doubles]] task section in the flow.cylc file:

+
execution retry delays = 5*PT6S
+
+
+

This means that if the roll_doubles task fails, Cylc expects to +retry running it 5 times before finally failing. Each retry will have +a delay of 6 seconds.

+

We can apply multiple retry periods with the execution retry delays setting +by separating them with commas, for example the following line would tell Cylc +to retry a task four times, once after 15 seconds, then once after 10 minutes, +then once after one hour then once after three hours.

+
execution retry delays = PT15S, PT10M, PT1H, PT3H
+
+
+
+
+

Running With Retries

+

Look at the workflow with The Cylc GUI or The Cylc TUI

+

Re-install and run the workflow:

+
cylc validate .
+cylc install
+cylc play retries-tutorial
+
+
+

What you should see is Cylc retrying the roll_doubles task. Hopefully, +it will succeed (there is only about a 1 in 3 chance of every task +failing) and the workflow will continue.

+
+
+

Altering Behaviour

+

We can alter the behaviour of the task based on the number of retries, using +$CYLC_TASK_TRY_NUMBER.

+

Change the script setting for the roll_doubles task to this:

+
sleep 10
+RANDOM=$$  # Seed $RANDOM
+DIE_1=$((RANDOM%6 + 1))
+DIE_2=$((RANDOM%6 + 1))
+echo "Rolled $DIE_1 and $DIE_2..."
+if (($DIE_1 == $DIE_2)); then
+    echo "doubles!"
+elif (($CYLC_TASK_TRY_NUMBER >= 2)); then
+    echo "look over there! ..."
+    echo "doubles!"  # Cheat!
+else
+    exit 1
+fi
+
+
+

If your workflow is still running, stop it, then run it again.

+

This time, the task should definitely succeed before the third retry.

+
+
+

Further Reading

+

For more information see the Cylc User Guide.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/index.html b/nightly_8.4/html/tutorial/index.html new file mode 100644 index 00000000000..7918e432ca4 --- /dev/null +++ b/nightly_8.4/html/tutorial/index.html @@ -0,0 +1,199 @@ + + + + + + + Tutorial — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+ +
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/introduction.html b/nightly_8.4/html/tutorial/introduction.html new file mode 100644 index 00000000000..6c3f2e4b4f4 --- /dev/null +++ b/nightly_8.4/html/tutorial/introduction.html @@ -0,0 +1,226 @@ + + + + + + + Introduction — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Introduction

+
+

What Is A Workflow?

+
+

A workflow consists of an orchestrated and repeatable pattern of business +activity enabled by the systematic organization of resources into processes +that transform materials, provide services, or process information.

+

—Wikipedia

+
+

In research, business and other fields we may need to repeat processes in +the course of our work. At its simplest a workflow is a set of steps that +must be followed in a particular order to achieve some end goal.

+

We can represent each “step” in a workflow as a node in a graph, and the +order with arrows between them.

+
+

digraph bakery { +"purchase ingredients" -> "make dough" -> "bake bread" -> "sell bread" +"bake bread" -> "clean oven" +"pre-heat oven" -> "bake bread" +}

+
+
+
+

What Is Cylc?

+

Cylc (pronounced silk) is a workflow engine, a system that automatically +executes tasks according to schedules and dependencies.

+

In a Cylc workflow each step is a computational task that runs a script or +application of some kind. Cylc runs each task as soon as it is appropriate +to do so.

+
+

digraph Mini_Cylc { +b -> c +f +b -> d +c +d -> f +a -> b +e -> f +}

+
+

Cylc can automatically:

+
    +
  • Submit tasks across computer systems and resource managers.

  • +
  • Recover from failures.

  • +
  • Repeat workflows.

  • +
+

Cylc was originally developed at NIWA (The National Institute of Water and +Atmospheric Research, New Zealand) for running their weather forecasting +workflows. It is now developed by an international partnership including +NIWA, the Met Office (UK), and members of the Unified Model Consortium. +Though initially developed for meteorological purposes Cylc is a general +purpose tool as applicable in business as it is in scientific research.

+

Cylc provides a variety of command line and GUI tools for visualising, +monitoring, and controlling workflows. The Cylc TUI (Terminal +User Interface), web GUI, and cylc scan (bottom left) are shown below.

+A screenshot of several Cylc tools. +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/runtime/configuration-consolidation/families.html b/nightly_8.4/html/tutorial/runtime/configuration-consolidation/families.html new file mode 100644 index 00000000000..1427ef74e94 --- /dev/null +++ b/nightly_8.4/html/tutorial/runtime/configuration-consolidation/families.html @@ -0,0 +1,399 @@ + + + + + + + Families — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ +
+
+ +
+

Families

+

Families provide a way of grouping tasks together so they can +be treated as one.

+
+

Runtime

+

Families are groups of tasks which share a common +configuration. In the present example the common configuration is:

+
script = get-observations
+[[[environment]]]
+    API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+
+
+

We define a family as a new task consisting of the common configuration. By +convention families are named in upper case:

+
[[GET_OBSERVATIONS]]
+    script = get-observations
+    [[[environment]]]
+        API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+
+
+

We “add” tasks to a family using the inherit setting:

+
[[get_observations_heathrow]]
+    inherit = GET_OBSERVATIONS
+    [[[environment]]]
+        SITE_ID = 3772
+
+
+

When we add a task to a family in this way it inherits the configuration from the family, i.e. the above example is +equivalent to:

+
[[get_observations_heathrow]]
+    script = get-observations
+    [[[environment]]]
+        API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+        SITE_ID = 3772
+
+
+

It is possible to override inherited configuration within the task. For +example if we wanted the get_observations_heathrow task to use a +different API key we could write:

+
[[get_observations_heathrow]]
+    inherit = GET_OBSERVATIONS
+    [[[environment]]]
+        API_KEY = special-api-key
+        SITE_ID = 3772
+
+
+

Using families the get_observations tasks could be written like so:

+
[runtime]
+    [[GET_OBSERVATIONS]]
+        script = get-observations
+        [[[environment]]]
+            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+
+    [[get_observations_heathrow]]
+        inherit = GET_OBSERVATIONS
+        [[[environment]]]
+            SITE_ID = 3772
+    [[get_observations_camborne]]
+        inherit = GET_OBSERVATIONS
+        [[[environment]]]
+            SITE_ID = 3808
+    [[get_observations_shetland]]
+        inherit = GET_OBSERVATIONS
+        [[[environment]]]
+            SITE_ID = 3005
+    [[get_observations_aldergrove]]
+        inherit = GET_OBSERVATIONS
+        [[[environment]]]
+            SITE_ID = 3917
+
+
+
+
+

Graphing

+

Families can be used in the workflow’s graph, e.g:

+
GET_OBSERVATIONS:succeed-all => consolidate_observations
+
+
+

The :succeed-all is a special qualifier which in this example +means that the consolidate_observations task will run once all of the +members of the GET_OBSERVATIONS family have succeeded. This is +equivalent to:

+
get_observations_heathrow => consolidate_observations
+get_observations_camborne => consolidate_observations
+get_observations_shetland => consolidate_observations
+get_observations_aldergrove => consolidate_observations
+
+
+

The GET_OBSERVATIONS:succeed-all part is referred to as a +family trigger. Family triggers use special qualifiers which are +non-optional. The most commonly used ones are:

+
+
succeed-all

Run if all of the members of the family have succeeded.

+
+
succeed-any

Run as soon as any one family member has succeeded.

+
+
finish-all

Run as soon as all of the family members have completed (i.e. have each +either succeeded or failed).

+
+
+

For more information on family triggers see the Cylc User Guide.

+
+
+

The root Family

+

There is a special family called root (in lowercase) which is used only +in the runtime to provide configuration which will be inherited by all +tasks.

+

In the following example the task bar will inherit the environment +variable FOO from the [root] section:

+
[runtime]
+    [[root]]
+        [[[environment]]]
+            FOO = foo
+    [[bar]]
+        script = echo $FOO
+
+
+
+

Practical

+

In this practical we will consolidate the configuration of the +weather-forecasting workflow +from the previous section.

+
    +
  1. Create A New Workflow.

    +

    To make a new copy of the forecasting workflow run the following commands:

    +
    cylc get-resources tutorial/consolidation-tutorial
    +cd ~/cylc-src/consolidation-tutorial
    +
    +
    +
  2. +
  3. Move Site-Wide Settings Into The root Family.

    +

    The following two environment variables are used by multiple tasks:

    +
    RESOLUTION = 0.2
    +DOMAIN = -12,48,5,61  # Do not change!
    +
    +
    +

    Rather than manually adding them to each task individually we could put +them in the root family, making them accessible to all tasks.

    +

    Add a root section containing these two environment variables. +Remove the variables from any other task’s environment sections:

    +
     [runtime]
    ++    [[root]]
    ++        [[[environment]]]
    ++            # The dimensions of each grid cell in degrees.
    ++            RESOLUTION = 0.2
    ++            # The area to generate forecasts for (lng1, lat1, lng2, lat2).
    ++            DOMAIN = -12,48,5,61  # Do not change!
    +
    +
    +
     [[consolidate_observations]]
    +     script = consolidate-observations
    +-    [[[environment]]]
    +-        # The dimensions of each grid cell in degrees.
    +-        RESOLUTION = 0.2
    +-        # The area to generate forecasts for (lng1, lat1, lng2, lat2).
    +-        DOMAIN = -12,48,5,61  # Do not change!
    +
    + [[get_rainfall]]
    +     script = get-rainfall
    +     [[[environment]]]
    +         # The key required to get weather data from the DataPoint service.
    +         # To use archived data comment this line out.
    +         API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    +-        # The dimensions of each grid cell in degrees.
    +-        RESOLUTION = 0.2
    +-        # The area to generate forecasts for (lng1, lat1, lng2, lat2).
    +-        DOMAIN = -12,48,5,61  # Do not change!
    +
    + [[forecast]]
    +     script = forecast 60 5  # Generate 5 forecasts at 60 minute intervals.
    +     [[[environment]]]
    +-        # The dimensions of each grid cell in degrees.
    +-        RESOLUTION = 0.2
    +-        # The area to generate forecasts for (lng1, lat1, lng2, lat2)
    +-        DOMAIN = -12,48,5,61  # Do not change!
    +         # The path to the files containing wind data (the {variables} will
    +         # get substituted in the forecast script).
    +         WIND_FILE_TEMPLATE = $CYLC_WORKFLOW_WORK_DIR/{cycle}/consolidate_observations/wind_{xy}.csv
    +         # List of cycle points to process wind data from.
    +         WIND_CYCLES = 0, -3, -6
    +
    +         # The path to the rainfall file.
    +         RAINFALL_FILE = $CYLC_WORKFLOW_WORK_DIR/$CYLC_TASK_CYCLE_POINT/get_rainfall/rainfall.csv
    +         # Create the html map file in the task's log directory.
    +         MAP_FILE = "${CYLC_TASK_LOG_ROOT}-map.html"
    +         # The path to the template file used to generate the html map.
    +         MAP_TEMPLATE = "$CYLC_WORKFLOW_RUN_DIR/lib/template/map.html"
    +
    + [[post_process_exeter]]
    +     # Generate a forecast for Exeter 60 minutes into the future.
    +     script = post-process exeter 60
    +-    [[[environment]]]
    +-        # The dimensions of each grid cell in degrees.
    +-        RESOLUTION = 0.2
    +-        # The area to generate forecasts for (lng1, lat1, lng2, lat2).
    +-        DOMAIN = -12,48,5,61  # Do not change!
    +
    +
    +

    To ensure that the environment variables are being inherited correctly +by the tasks, inspect the [runtime] section using cylc config +by running the following command:

    +
    cylc config . -i "[runtime]"
    +
    +
    +

    You should see the environment variables from the [root] section +in the [environment] section for all tasks.

    +
    +

    Tip

    +

    You may find it easier to open the output of this command in a text +editor, e.g:

    +
    cylc config . -i "[runtime]" | gvim -
    +
    +
    +
    +
  4. +
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/runtime/configuration-consolidation/index.html b/nightly_8.4/html/tutorial/runtime/configuration-consolidation/index.html new file mode 100644 index 00000000000..90775d3c277 --- /dev/null +++ b/nightly_8.4/html/tutorial/runtime/configuration-consolidation/index.html @@ -0,0 +1,289 @@ + + + + + + + Consolidating Configuration — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Consolidating Configuration

+

In the last section we wrote out the following code in the +flow.cylc file:

+
[runtime]
+    [[get_observations_heathrow]]
+        script = get-observations
+        [[[environment]]]
+            SITE_ID = 3772
+            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+    [[get_observations_camborne]]
+        script = get-observations
+        [[[environment]]]
+            SITE_ID = 3808
+            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+    [[get_observations_shetland]]
+        script = get-observations
+        [[[environment]]]
+            SITE_ID = 3005
+            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+    [[get_observations_aldergrove]]
+        script = get-observations
+        [[[environment]]]
+            SITE_ID = 3917
+            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+
+
+

In this code the script item and the API_KEY environment variable have +been repeated for each task. This is bad practice as it makes the +configuration lengthy and harder to maintain.

+

Likewise the graph relating to the get_observations tasks is highly +repetitive:

+
[scheduling]
+    [[graph]]
+        T00/PT3H = """
+            get_observations_aldergrove => consolidate_observations
+            get_observations_camborne => consolidate_observations
+            get_observations_heathrow => consolidate_observations
+            get_observations_shetland => consolidate_observations
+        """
+
+
+

Cylc offers three ways of consolidating configurations to help improve the +structure of a workflow and avoid duplication.

+ +
+

The cylc config Command

+

The cylc config command reads in either the +global.cylc file, or a specific workflow’s flow.cylc +file, and it prints the parsed configuration out to the terminal.

+

Throughout this section as we introduce methods for consolidating +the flow.cylc file, the cylc config command can be used to +“expand” the file back to its full form.

+
+

Note

+

A primary use of cylc config is inspecting the +[runtime] section of a workflow. However, the command does not +expand parameterizations and +families in the workflow graph. To see the +expanded graph use the cylc graph command.

+
+

Call cylc config with the path of the workflow (or . if you are +already in the source directory or the run directory).

+
cylc config <path>
+
+
+

To view the configuration of a particular section or setting refer to it by +name using the -i option (see The flow.cylc File Format for details), e.g:

+
# Print the contents of the [scheduling] section.
+cylc config <path> -i '[scheduling]'
+# Print the contents of the get_observations_heathrow task.
+cylc config <path> -i '[runtime][get_observations_heathrow]'
+# Print the value of the script setting in the get_observations_heathrow task
+cylc config <path> -i '[runtime][get_observations_heathrow]script'
+
+
+
+
+

The Three Approaches

+

The next three sections cover the three consolidation approaches and how we +could use them to simplify the workflow from the previous tutorial. Work +through them in order!

+ +
+
+

Which Approach To Use

+

Each approach has its uses. Cylc permits mixing approaches, allowing us to +use what works best for us. As a rule of thumb:

+
    +
  • Families work best consolidating runtime configuration by +collecting tasks into broad groups, e.g. groups of tasks which run on a +particular machine or groups of tasks belonging to a particular system.

  • +
  • Jinja2 is good at configuring settings which apply to the entire workflow +rather than just a single task, as we can define variables then use them +throughout the workflow.

  • +
  • Parameterization works best for describing tasks +which are very similar but which have subtly different configurations +(e.g. different arguments or environment variables).

  • +
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/runtime/configuration-consolidation/jinja2.html b/nightly_8.4/html/tutorial/runtime/configuration-consolidation/jinja2.html new file mode 100644 index 00000000000..b93adf65b28 --- /dev/null +++ b/nightly_8.4/html/tutorial/runtime/configuration-consolidation/jinja2.html @@ -0,0 +1,350 @@ + + + + + + + Jinja2 — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ +
+
+ +
+

Jinja2

+

Jinja2 is a templating language often used in web design, with some +similarities to Python. It can be used to make a workflow definition more +dynamic.

+
+

The Jinja2 Language

+

In Jinja2 statements are wrapped with {% characters, i.e:

+
{% ... %}
+
+
+

Variables are initialised with the set statement, e.g:

+
{% set foo = 3 %}
+
+
+

Expressions wrapped with {{ characters will be replaced with +the evaluated expression, e.g:

+
There are {{ foo }} methods for consolidating the flow.cylc file
+
+
+

Would result in:

+
There are 3 methods for consolidating the flow.cylc file
+
+
+

Loops are written with for statements, e.g:

+
{% for x in range(foo) %}
+   {{ x }}
+{% endfor %}
+
+
+

Would result in:

+
0
+1
+2
+
+
+

To enable Jinja2 in the flow.cylc file, add the following shebang to the +top of the file:

+
#!Jinja2
+
+
+

For more information see the Jinja2 documentation.

+
+
+

Example

+

To consolidate the configuration for the get_observations tasks we could +define a dictionary of station and ID pairs:

+
{% set stations = {'aldergrove': 3917,
+                   'camborne': 3808,
+                   'heathrow': 3772,
+                   'shetland': 3005} %}
+
+
+

We could then loop over the stations like so:

+
{% for station in stations %}
+    {{ station }}
+{% endfor %}
+
+
+

After processing, this would result in:

+
aldergrove
+camborne
+heathrow
+shetland
+
+
+

We could also loop over both the stations and corresponding IDs like so:

+
{% for station, id in stations.items() %}
+    {{ station }} - {{ id }}
+{% endfor %}
+
+
+

This would result in:

+
aldergrove - 3917
+camborne - 3808
+heathrow - 3772
+shetland - 3005
+
+
+

Putting this all together, the get_observations configuration could be +written as follows:

+
#!Jinja2
+
+{% set stations = {'aldergrove': 3917,
+                   'camborne': 3808,
+                   'heathrow': 3772,
+                   'shetland': 3005} %}
+
+[scheduler]
+    allow implicit tasks = True
+
+[scheduling]
+    [[graph]]
+        T00/PT3H = """
+{% for station in stations %}
+            get_observations_{{station}} => consolidate_observations
+{% endfor %}
+        """
+
+
+
[runtime]
+{% for station, id in stations.items() %}
+    [[get_observations_{{station}}]]
+        script = get-observations
+        [[[environment]]]
+            SITE_ID = {{ id }}
+            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+
+{% endfor %}
+
+
+
+

Practical

+

This practical continues on from the +families practical.

+
    +
  1. Use Jinja2 To Avoid Duplication.

    +

    The API_KEY environment variable is used by both the +get_observations and get_rainfall tasks. Rather than writing it +out multiple times we will use Jinja2 to centralise this configuration.

    +

    At the top of the flow.cylc file add the Jinja2 shebang line. Then +copy the value of the API_KEY environment variable and use it to +define an API_KEY Jinja2 variable:

    +
    #!Jinja2
    +
    +{% set API_KEY = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' %}
    +
    +
    +

    Next replace the key, where it appears in the workflow, with +{{ API_KEY }}:

    +
     [runtime]
    +     [[get_observations_heathrow]]
    +         script = get-observations
    +         [[[environment]]]
    +             SITE_ID = 3772
    +-            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    ++            API_KEY = {{ API_KEY }}
    +     [[get_observations_camborne]]
    +         script = get-observations
    +         [[[environment]]]
    +             SITE_ID = 3808
    +-            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    ++            API_KEY = {{ API_KEY }}
    +     [[get_observations_shetland]]
    +         script = get-observations
    +         [[[environment]]]
    +            SITE_ID = 3005
    +-            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    ++            API_KEY = {{ API_KEY }}
    +     [[get_observations_aldergrove]]
    +         script = get-observations
    +         [[[environment]]]
    +             SITE_ID = 3917
    +-            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    ++            API_KEY = {{ API_KEY }}
    +    [[get_rainfall]]
    +        script = get-rainfall
    +        [[[environment]]]
    +            # The key required to get weather data from the DataPoint service.
    +            # To use archived data comment this line out.
    +-            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    ++            API_KEY = {{ API_KEY }}
    +
    +
    +

    Check the result with cylc config. The Jinja2 will be processed +so you should not see any difference after making these changes.

    +
  2. +
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/runtime/configuration-consolidation/parameters.html b/nightly_8.4/html/tutorial/runtime/configuration-consolidation/parameters.html new file mode 100644 index 00000000000..5861c0a3d79 --- /dev/null +++ b/nightly_8.4/html/tutorial/runtime/configuration-consolidation/parameters.html @@ -0,0 +1,434 @@ + + + + + + + Parameterized Tasks — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Parameterized Tasks

+

Parameterized tasks (see parameterization) provide a way of implicitly +looping over tasks without the need for Jinja2.

+
+

Cylc Parameters

+

Parameters are defined in their own section, e.g:

+
[task parameters]
+    world = Mercury, Venus, Earth
+
+
+

They can then be referenced by writing the name of the parameter in angle +brackets, e.g:

+
[scheduling]
+    [[graph]]
+        R1 = start => hello<world> => end
+[runtime]
+    [[hello<world>]]
+        script = echo 'Hello World!'
+
+
+

When the flow.cylc file is read by Cylc, the parameters will be expanded. +For example the code above is equivalent to:

+
[scheduling]
+    [[graph]]
+        R1 = """
+            start => hello_Mercury => end
+            start => hello_Venus => end
+            start => hello_Earth => end
+        """
+[runtime]
+    [[hello_Mercury]]
+        script = echo 'Hello World!'
+    [[hello_Venus]]
+        script = echo 'Hello World!'
+    [[hello_Earth]]
+        script = echo 'Hello World!'
+
+
+

We can refer to a specific parameter by writing it after an = sign:

+
[runtime]
+    [[hello<world=Earth>]]
+        script = echo 'Greetings Earth!'
+
+
+
+
+

Environment Variables

+

The name of the parameter is provided to the job as an environment variable +called CYLC_TASK_PARAM_<parameter> where <parameter> is the name of +the parameter (in the present case world):

+
[runtime]
+    [[hello<world>]]
+        script = echo "Hello ${CYLC_TASK_PARAM_world}!"
+
+
+
+
+

Parameter Types

+

Parameters can be either strings or integers:

+
[task parameters]
+    foo = 1..5
+    bar = 1..5..2
+    baz = pub, qux, bol
+
+
+
+

Hint

+

Remember that by default Cylc automatically inserts an underscore between the task and +the parameter, e.g. the following lines are equivalent:

+
task<baz=pub>
+task_pub
+
+
+
+
+

Hint

+

When using integer parameters, to prevent confusion, Cylc prefixes the +parameter value with the parameter name. For example:

+
[scheduling]
+    [[graph]]
+        R1 = """
+            # task<bar> would result in:
+            task_bar1
+            task_bar3
+            task_bar5
+
+            # task<baz> would result in:
+            task_pub
+            task_qux
+            task_bol
+        """
+
+
+
+

Using parameters the get_observations configuration could be written like +so:

+
[scheduling]
+   [[graph]]
+       T00/PT3H = """
+           get_observations<station> => consolidate_observations
+       """
+[runtime]
+    [[get_observations<station>]]
+        script = get-observations
+        [[[environment]]]
+            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+
+    [[get_observations<station=aldergrove>]]
+        [[[environment]]]
+            SITE_ID = 3917
+    [[get_observations<station=camborne>]]
+        [[[environment]]]
+            SITE_ID = 3808
+    [[get_observations<station=heathrow>]]
+        [[[environment]]]
+            SITE_ID = 3772
+    [[get_observations<station=shetland>]]
+        [[[environment]]]
+            SITE_ID = 3005
+
+
+

For more information see the Cylc User Guide.

+
+

Practical

+

This practical continues on from the +Jinja2 practical.

+
    +
  1. Use Parameterization To Consolidate The get_observations +Tasks.

    +

    Next we will parameterize the get_observations tasks.

    +

    Add a parameter called station:

    +
    +[task parameters]
    ++    station = aldergrove, camborne, heathrow, shetland
    +
    + [scheduler]
    +     UTC mode = True
    +
    +
    +

    Remove the four get_observations tasks and insert the following code +in their place:

    +
    [[get_observations<station>]]
    +    script = get-observations
    +    [[[environment]]]
    +        API_KEY = {{ API_KEY }}
    +
    +
    +

    Using cylc config you should see that Cylc replaces the +<station> with each of the stations in turn, creating a new task for +each:

    +
    cylc config . -i "[runtime]"
    +
    +
    +

    The get_observations tasks are now missing the SITE_ID +environment variable. Add a new section for each station with a +SITE_ID:

    +
    [[get_observations<station=heathrow>]]
    +    [[[environment]]]
    +        SITE_ID = 3772
    +
    +
    +
    +

    Hint

    +

    The relevant IDs are:

    +
      +
    • Aldergrove - 3917

    • +
    • Camborne - 3808

    • +
    • Heathrow - 3772

    • +
    • Shetland - 3005

    • +
    +
    +
    +

    Solution

    +
    [[get_observations<station=aldergrove>]]
    +    [[[environment]]]
    +        SITE_ID = 3917
    +[[get_observations<station=camborne>]]
    +    [[[environment]]]
    +        SITE_ID = 3808
    +[[get_observations<station=heathrow>]]
    +    [[[environment]]]
    +        SITE_ID = 3772
    +[[get_observations<station=shetland>]]
    +    [[[environment]]]
    +        SITE_ID = 3005
    +
    +
    +
    +

    Using cylc config you should now see four get_observations +tasks, each with a script, an API_KEY and a SITE_ID:

    +
    cylc config . -i "[runtime]"
    +
    +
    +

    Finally we can use this parameterization to simplify the workflow’s +graphing. Replace the get_observations lines in the graph with +get_observations<station>:

    +
     # Repeat every three hours starting at the initial cycle point.
    + PT3H = """
    +-    get_observations_aldergrove => consolidate_observations
    +-    get_observations_camborne => consolidate_observations
    +-    get_observations_heathrow => consolidate_observations
    +-    get_observations_shetland => consolidate_observations
    ++    get_observations<station> => consolidate_observations
    + """
    +
    +
    +
    +

    Hint

    +

    The cylc config command does not expand parameters or families +in the graph so you must use cylc graph to inspect changes to the +graphing.

    +
    +
  2. +
  3. Use Parameterization To Consolidate The post_process Tasks.

    +

    At the moment we only have one post_process task +(post_process_exeter), but suppose we wanted to add a second task for +Edinburgh.

    +

    Create a new parameter called site and set it to contain exeter +and edinburgh. Parameterize the post_process task using this +parameter.

    +
    +

    Hint

    +

    The first argument to the post-process task is the name of the +site. We can use the CYLC_TASK_PARAM_site environment variable to +avoid having to write out this section twice.

    +
    +
    +

    Solution

    +

    First we must create the site parameter:

    +
     [scheduler]
    +     UTC mode = True
    + [task parameters]
    +     station = aldergrove, camborne, heathrow, shetland
    ++        site = exeter, edinburgh
    +
    +
    +

    Next we parameterize the task in the graph:

    +
    -get_rainfall => forecast => post_process_exeter
    ++get_rainfall => forecast => post_process<site>
    +
    +
    +

    And also the runtime:

    +
    -[[post_process_exeter]]
    ++[[post_process<site>]]
    +     # Generate a forecast for Exeter 60 minutes in the future.
    +-    script = post-process exeter 60
    ++    script = post-process $CYLC_TASK_PARAM_site 60
    +
    +
    +
    +
  4. +
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/runtime/index.html b/nightly_8.4/html/tutorial/runtime/index.html new file mode 100644 index 00000000000..66f568684a1 --- /dev/null +++ b/nightly_8.4/html/tutorial/runtime/index.html @@ -0,0 +1,213 @@ + + + + + + + Runtime — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Runtime

+

This section covers:

+
    +
  • Associating workflow tasks with executable applications (scripts and +programs).

  • +
  • Providing executables with runtime configurations, within the workflow.

  • +
  • Running Cylc workflows.

  • +
+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/runtime/introduction.html b/nightly_8.4/html/tutorial/runtime/introduction.html new file mode 100644 index 00000000000..0a22225cfd5 --- /dev/null +++ b/nightly_8.4/html/tutorial/runtime/introduction.html @@ -0,0 +1,628 @@ + + + + + + + Introduction — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Introduction

+

So far we have worked with the [scheduling] section of the flow.cylc +file, where workflow tasks and dependencies are defined.

+

Now, in the [runtime] section, we need to associate each task with a +script or application to run when its dependencies are met.

+
+

Task Definitions

+

The runtime settings for each task are stored in a sub-section of the +[runtime] section. E.g. for a task called hello_world we would write +settings inside the following section:

+
[runtime]
+    [[hello_world]]
+
+
+
+

Note

+

A runtime sub-section for each task is normally required, even if it is +empty. However, in the previous tutorials we disabled this requirement +with flow.cylc[scheduler]allow implicit tasks. +See Implicit Tasks for more details.

+
+
+
+

The script Setting

+

The task script setting tells Cylc what to execute when a task is +ready to run.

+

This value of this setting is interpreted as a bash script. The following +example defines a task called hello_world which simply writes Hello +World! to standard output.

+
[runtime]
+    [[hello_world]]
+        script = echo 'Hello World!'
+
+
+
+

Note

+

A task with no script defined will run a job that does nothing but +communicate its status back to the scheduler before exiting immediately.

+
+

We can also call other scripts or executables in this way, e.g:

+
[runtime]
+    [[hello_world]]
+        script = ~/foo/bar/baz/hello_world
+
+
+
+
+

PATH and PYTHONPATH

+

Keeping task scripts with the workflow, rather than leaving them elsewhere on +the system, helps isolate the workflow from external changes.

+

To help with this, Cylc automatically adds a bin/ sub-directory of the +workflow source directory to the executable search path ($PATH) +in task environments.

+
+
bin/hello_world
+
#!/bin/bash
+echo 'Hello World!'
+
+
+
+
+
flow.cylc
+
[runtime]
+    [[hello_world]]
+        script = hello_world
+
+
+
+

Similarly the lib/python/ directory gets prepended to the +PYTHONPATH variable.

+
+
lib/python/hello.py
+
def world():
+   print('Hello World!')
+
+
+
+
+
flow.cylc
+
[runtime]
+   [[hello_world]]
+      script = python -c 'import hello; hello.world()'
+
+
+
+
+
+

Tasks And Jobs

+

When a task is ready to run Cylc creates a job script for +it: a bash file containing the scripting defined for the task along with +other configuration and error trapping code. This is what actually executes +as the job.

+

Tasks typically go through the following states as a workflow +runs:

+
+
Waiting

Waiting for dependencies to be met.

+
+
Preparing

Dependencies met; preparing the task job script for submission.

+
+
Submitted

Job script submitted to the job runner; waiting on execution.

+
+
Running

Job script executing.

+
+
Succeeded

Job completed successfully (i.e. exited with 0 return status).

+
+
+

There are several other task states as well, such as failed.

+

See the next section for more about running jobs.

+
+
+

The Cylc User Interfaces

+

To help you to keep monitor and control running workflows Cylc has

+
    +
  • A graphical user interface (Cylc GUI).

  • +
  • A terminal-based user interface (Cylc TUI).

  • +
  • A comprehensive command line interface (Cylc CLI).

  • +
+
+

The Cylc CLI

+

You can start, stop, query, and control workflow, in every possible way, +from the command line.

+

All Cylc commands have built-in help information:

+
cylc help
+cylc play --help  # etc.
+
+
+
+
+

The Cylc TUI

+

The Cylc TUI (Terminal User Interface) enables you to view and interact +with your workflows.

+

To start the Cylc TUI:

+
cylc tui <workflow_id>
+
+
+
+
+

The Cylc GUI

+

The Cylc GUI has different views you can use to examine your workflows, +including a Cylc scan menu allowing you to switch between workflows.

+
+

Note

+

You only need to have one instance of the Cylc GUI open - you can +easily switch between workflows.

+
+

To start the Cylc UI, open a new terminal window or tab, then type:

+
cylc gui
+
+
+
+
+

Task & Job States

+
    +
  • Task states have grey icons.

  • +
  • Job states have colour coded squares.

  • +
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Task Icon

Job Icon

Description

task-waiting

Task waiting

task-submitted

job-submitted

Job submitted

task-running

job-running

Job running

task-succeeded

job-succeeded

Job ran successfully

task-failed

job-failed

Job failed

+
+

See also

+

Full list of Tasks in the GUI/Tui.

+
+

This is the “tree” view:

+
+../../_images/cylc-gui-tree-view.png +
+

Screenshot of the Cylc GUI in “Tree” view mode.

+
+
+

This is the “table” view:

+
+../../_images/cylc-gui-table-view.png +
+

Screenshot of the Cylc GUI in “Table” view mode.

+
+
+

You can navigate between workflows using the list on the left (the +screenshot shows only one, however).

+
+../../_images/cylc-gui-scan-view.png +
+

Screenshot of the Cylc GUI “Scan” bar.

+
+
+
+
+
+

Validating A Workflow

+

We recommend using cylc validate to check a workflow definition for +errors before running it.

+
$ cylc validate ~/cylc-src/my_workflow
+
+
+
+
+

Installing A Workflow

+ +

To separate the development and running of workflows, use the +cylc install command.

+
cylc install my_workflow
+
+
+

This will install ~/cylc-src/my_workflow to ~/cylc-run/my_workflow/runN.

+
+
+

Running a workflow

+

Now we have installed the workflow we can run it +using the cylc play command:

+
$ cylc play my_workflow
+
+
+
+
+

Generated Workflow Files

+
+

Numbered run directories

+
+

See also

+

Installing Workflows for a fuller description of Cylc install, +including the option of naming rather than numbering runs.

+
+

By default cylc install will create a new numbered run directory each +time you run it:

+
$ cylc install my_workflow
+INSTALLED my_workflow/run1 from ...
+$ cylc install my_workflow
+INSTALLED my_workflow/run2 from ...
+
+# The most recent ``runX`` directory is symlinked to ``runN``
+$ ls -l ~/cylc-run/my_workflow/runN
+~/cylc-run/baz/runN -> run2
+
+
+

You can run cylc commands using a specific run number, but if you don’t, +runN will be used:

+
$ cylc play my_workflow
+# is the same as
+$ cylc play my_workflow/runN
+# and the same as (in this case)
+$ cylc play my_workflow/run2
+
+
+
+
+

Files Generated at Runtime

+

Cylc generates files and directories when it runs a workflow, namely:

+
+
log
+
db

The database which Cylc uses to record the state of the workflow;

+
+
job

The directory where all job log files live, +primarily the job script itself (job) and the job output logs +(job.out and job.err);

+
+
scheduler

The directory where scheduler log files live. +These are written as the workflow runs and are useful when troubleshooting.

+
+
config/flow.cylc.processed

A copy of the flow.cylc file made after any Jinja2 has been +processed - we will cover this in the +Consolidating Configuration section.

+
+
remote-install

Information related to Remote Initialization file installation can be found +here. A separate file is created per install target.

+
+
+
+
share/

The share directory is where tasks can +read or write files shared with other tasks.

+
+
work/
+

Contains task work directories, i.e. the +current working directories of running tasks. These are +removed automatically if empty when a task finishes.

+
+

The job log directory path ends in <cycle-point>/<task-name>/<job-submission-num>/, +where the job submission number starts at 1 and increments each time a +task re-runs.

+

You can use the command line to view scheduler or job logs without +having to find them yourself on the filesystem:

+
cylc cat-log <workflow-name>
+cylc cat-log <workflow-name>//<cycle-point>/<task-name>
+
+
+
+
+
+

Note

+

If you used pip to install Cylc, you will need to run

+
pip install 'cylc-flow[tutorial]'
+
+
+

to install extra dependencies needed for running the following +tutorial workflows.

+
+
+

Practical

+

In this practical we will add some scripts to, and run, the +weather forecasting workflow +from the scheduling tutorial.

+
    +
  1. Create A New Workflow.

    +

    The following command will copy some workflow files into +a new source directory called runtime-introduction:

    +
    cylc get-resources tutorial/runtime-introduction
    +cd ~/cylc-src/runtime-introduction
    +
    +
    +

    This includes the flow.cylc file from the +weather forecasting workflow +with some runtime configuration added to it.

    +

    There is also a script called get-observations located in the bin +directory.

    +

    Take a look at the [runtime] section in the flow.cylc file.

    +
  2. +
  3. Run The Workflow.

    +

    First validate the workflow by running:

    +
    cylc validate .
    +
    +
    +

    Then install the workflow:

    +
    cylc install
    +
    +
    +

    Open a user interface (The Cylc TUI or The Cylc GUI) to view +your workflow.

    +

    Finally run the workflow by executing:

    +
    cylc play runtime-introduction
    +
    +
    +

    The tasks will start to run - you should see them going through the +waiting, running and succeeded states. The preparing and +submitted states may be too quick to notice.

    +

    When the workflow reaches the final cycle point and all tasks have succeeded +the scheduler will shutdown automatically.

    +
    +

    Tip

    +

    You can run a workflow from the Cylc GUI by pressing the “play” +button at the top.

    +
    +
  4. +
  5. Inspect A Job Log.

    +

    Try opening the job.out log for one of the +get_observations tasks in a text editor. The file will be +in the job log directory:

    +
    cd ~/cylc-run/runtime-introduction/runN
    +cat log/job/<cycle-point>/get_observations_heathrow/01/job.out
    +
    +
    +

    You should see something like this:

    +
    Workflow    : runtime-introduction
    +Job : 20000101T0000Z/get_observations_heathrow/01 (try 1)
    +User@Host: username@hostname
    +
    +Guessing Weather Conditions
    +Writing Out Wind Data
    +
    +1970-01-01T00:00:00Z NORMAL - started
    +2038-01-19T03:14:08Z NORMAL - succeeded
    +
    +
    +
      +
    • The first three lines are identifying information written by Cylc.

    • +
    • The lines in the middle are the job stdout.

    • +
    • The last two lines are written by Cylc, to record job start and finish +times. The started message would be above the job stdout for a +longer-running job.

    • +
    +
  6. +
  7. Inspect A Work Directory.

    +

    The get_rainfall task should create a file called rainfall in its +work directory. Try opening this file, recalling that the +format of the relevant path from within the work directory will be:

    +
    work/<cycle-point>/get_rainfall/rainfall
    +
    +
    +
    +

    Hint

    +

    The get_rainfall task only runs every third cycle.

    +
    +
  8. +
  9. Extension: Explore The Cylc GUI

    +
      +
    • Try re-installing the workflow and running it from the GUI.

    • +
    • Try adding a new view(s).

      +
      +

      Tip

      +

      You can do this from the “Add View” button (top-right):

      +../../_images/cylc-gui-views-button.png +
      +
    • +
    • Try pressing the “Pause” button which is found in the top left-hand +corner of the GUI.

    • +
    • Try clicking on a task state icon. From the menu you could try:

      +
        +
      • “Trigger”

      • +
      • “Hold”

      • +
      • “Release”

      • +
      +
    • +
    +
  10. +
+
+

See also

+

See guide to Tasks in the GUI/Tui for a guide to the icons.

+
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/runtime/runtime-configuration.html b/nightly_8.4/html/tutorial/runtime/runtime-configuration.html new file mode 100644 index 00000000000..9815b1bfc60 --- /dev/null +++ b/nightly_8.4/html/tutorial/runtime/runtime-configuration.html @@ -0,0 +1,571 @@ + + + + + + + Runtime Configuration — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Runtime Configuration

+

In the last section we associated tasks with scripts and ran a simple workflow. In +this section we will look at how to configure these tasks.

+
+

Environment Variables

+

We can define environment variables in task [environment] sections, +to be provided to task jobs at runtime.

+
[runtime]
+    [[countdown]]
+        script = seq $START_NUMBER
+        [[[environment]]]
+            START_NUMBER = 5
+
+
+

Each job is also provided with some standard environment variables e.g:

+
+
CYLC_WORKFLOW_RUN_DIR

The path to the run directory +(e.g. ~/cylc-run/workflow).

+
+
CYLC_TASK_WORK_DIR

The path to the associated task’s work directory +(e.g. run-directory/work/cycle/task).

+
+
CYLC_TASK_CYCLE_POINT

The cycle point for the associated task +(e.g. 20171009T0950).

+
+
+
+

See also

+

There are many more environment variables - see +Job Script Variables for more information.

+
+
+
+

Job Submission

+

By default Cylc runs jobs on the same machine as +the scheduler. It can run them on other machines too if we set the +platform like this:

+
[runtime]
+    [[hello_computehost]]
+        script = echo "Hello Compute Host"
+        platform = powerful_computer
+
+
+

By default Cylc also executes jobs as background processes. +We often want to submit jobs to a job runner instead, +particularly on shared compute resources. Cylc supports the following +job runners:

+
    +
  • at

  • +
  • loadleveler

  • +
  • lsf

  • +
  • pbs

  • +
  • sge

  • +
  • slurm

  • +
  • moab

  • +
+

Job runners typically require +directives in some form, to specify +job requirements such as memory use and number of CPUs to run on. For +example:

+
[runtime]
+    [[big_task]]
+        script = big-executable
+
+        # Submit to the host "big-computer".
+        platform = slurm_platform
+
+        # job requires 500MB of RAM & 4 CPUs
+        [[[directives]]]
+            --mem = 500
+            --ntasks = 4
+
+
+
+
+

Time Limits

+

We can specify an execution time limit, as an ISO8601 duration, after +which a job will be terminated. Cylc automatically translates this to +the correct job runner directives.

+
[runtime]
+    [[some_task]]
+        script = some-executable
+        execution time limit = PT15M  # 15 minutes.
+
+
+
+
+

Retries

+

Jobs can fail for several reasons:

+
    +
  • Something went wrong with job submission, e.g:

    +
      +
    • A network problem;

    • +
    • The job host became unavailable or overloaded;

    • +
    • The job runner rejected your job directives.

    • +
    +
  • +
+
    +
  • Something went wrong with job execution, e.g:

    +
      +
    • A bug;

    • +
    • A system error;

    • +
    • The job hitting the execution time limit.

    • +
    +
  • +
+

We can configure Cylc to automatically retry tasks that fail, +by setting submission retry delays and/or execution retry delays +to a list of ISO8601 durations. +For example, setting execution retry delays = PT10M +will cause the job to retry every 10 minutes on execution failure.

+

Use a multiplier to limit the number of retries:

+
[runtime]
+   [[some-task]]
+      script = some-script
+
+      # On execution failure
+      #   retry up to 3 times every 15 minutes.
+      execution retry delays = 3*PT15M
+      # On submission failure
+      #   retry up to 2 times every 10 min,
+      #   then every 30 mins thereafter.
+      submission retry delays = 2*PT10M, PT30M
+
+
+
+

Note

+

Tasks only enter the submit-failed state if job submission fails with no +retries left. Otherwise they return to the waiting state, to wait on the +next try.

+

Tasks only enter the failed state if job execution fails with no retries +left. Otherwise they return to the waiting state, to wait on the next try.

+
+
+
+

Start, Stop, Restart

+

We have seen how to start and stop Cylc workflows with cylc play and +cylc stop. By default cylc stop causes the scheduler to wait +for running jobs to finish before it shuts down. There are several +other stop options, however. For example:

+
+
cylc stop --kill

Kill all running jobs before stopping. (Cylc can kill jobs on remote +hosts, via the configured job runner).

+
+
cylc stop --now --now

stop right now, leaving any jobs running.

+
+
+

Once a workflow has stopped you can restart it with cylc play. +The scheduler will pick up where it left off, and carry on as normal.

+
# Run the workflow "name".
+cylc play <id>
+# Stop the workflow "name", killing any running tasks.
+cylc stop <id> --kill
+# Restart the workflow "name", picking up where it left off.
+cylc play <id>
+
+
+
+

Practical

+

In this practical we will add runtime configuration to the +weather-forecasting workflow +from the scheduling tutorial.

+
    +
  1. Create A New Workflow.

    +

    Create a new workflow by running the command:

    +
    cylc get-resources tutorial/runtime-tutorial
    +cd ~/cylc-src/runtime-tutorial
    +
    +
    +

    You will now have a copy of the weather-forecasting workflow along with some +executables and python modules.

    +
  2. +
  3. Set The Initial And Final Cycle Points.

    +

    We want the workflow to run for 6 hours, starting at least 7 hours ago, on +the hour.

    +

    We could work out the dates and times manually, or we could let Cylc do +the maths for us.

    +

    Set the initial cycle point:

    +
    initial cycle point = previous(T-00) - PT7H
    +
    +
    +
      +
    • previous(T-00) returns the current time ignoring minutes and +seconds.

      +

      e.g. if the current time is 12:34 this will return 12:00

      +
    • +
    • -PT7H subtracts 7 hours from this value.

    • +
    +

    Set the final cycle point:

    +
    final cycle point = +PT6H
    +
    +
    +

    This sets the final cycle point six hours after the +initial cycle point.

    +

    Run cylc validate to check for any errors:

    +
    cylc validate .
    +
    +
    +
  4. +
  5. Add Runtime Configuration For The get_observations Tasks.

    +

    In the bin directory is a script called get-observations. This +script gets weather data from the MetOffice DataPoint service. +It requires two environment variables:

    +
    +
    SITE_ID:

    A four digit numerical code which is used to identify a +weather station, e.g. 3772 is Heathrow Airport.

    +
    +
    API_KEY:

    An authentication key required for access to the service.

    +
    +
    +

    Generate a Datapoint API key:

    +
    cylc get-resources api-key
    +
    +
    +

    Add the following lines to the bottom of the flow.cylc file replacing +xxx... with your API key:

    +
    [runtime]
    +    [[get_observations_heathrow]]
    +        script = get-observations
    +        [[[environment]]]
    +            SITE_ID = 3772
    +            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    +
    +
    +

    Add three more get_observations tasks for each of the remaining +weather stations.

    +

    You will need the codes for the other three weather stations, which are:

    +
      +
    • Camborne - 3808

    • +
    • Shetland - 3005

    • +
    • Aldergrove - 3917

    • +
    +
    +

    Solution

    +
    [runtime]
    +    [[get_observations_heathrow]]
    +        script = get-observations
    +        [[[environment]]]
    +            SITE_ID = 3772
    +            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    +    [[get_observations_camborne]]
    +        script = get-observations
    +        [[[environment]]]
    +            SITE_ID = 3808
    +            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    +    [[get_observations_shetland]]
    +        script = get-observations
    +        [[[environment]]]
    +            SITE_ID = 3005
    +            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    +    [[get_observations_aldergrove]]
    +        script = get-observations
    +        [[[environment]]]
    +            SITE_ID = 3917
    +            API_KEY = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    +
    +
    +
    +

    Check the flow.cylc file is valid by running the command:

    +
    cylc validate .
    +
    +
    +
  6. +
  7. Test the get_observations tasks.

    +

    Next we will test the get_observations tasks.

    +

    Install the workflow:

    +
    cylc install
    +
    +
    +

    Open a user interface (The Cylc TUI or The Cylc GUI) to view +your workflow. Run the workflow either from the UI or command line.

    +
    +

    Hint

    +
    cylc tui runtime-tutorial
    +# or
    +cylc gui  # If you haven't already got an instance running.
    +
    +
    +

    Run the workflow either by:

    +
      +
    • GUI: selecting the runtime-tutorial workflow in the sidebar and +pressing the play button.

    • +
    • Tui: pressing enter on the workflow and selecting “play”.

    • +
    • Command line: running cylc play runtime-tutorial.

    • +
    +
    +

    If all goes well the workflow will startup and the tasks will run and +succeed. Note that the tasks which do not have a [runtime] section +will still run though they will not do anything as they do not call any +scripts.

    +

    Once the workflow has reached the final cycle point and all tasks have +succeeded the scheduler will shut down automatically.

    +

    The get-observations script produces a file called wind.csv which +specifies the wind speed and direction. This file is written in the task’s +work directory.

    +

    Try and open one of the wind.csv files. Note that the path to the +work directory is:

    +
    work/<cycle-point>/<task-name>
    +
    +
    +

    You should find a file containing four numbers:

    +
      +
    • The longitude of the weather station;

    • +
    • The latitude of the weather station;

    • +
    • The wind direction (the direction the wind is blowing towards) +in degrees;

    • +
    • The wind speed in miles per hour.

    • +
    +
    +

    Hint

    +

    If you run ls work you should see a +list of cycles. Pick one of them and open the file:

    +
    work/<cycle-point>/get_observations_heathrow/wind.csv
    +
    +
    +
    +
  8. +
  9. Add runtime configuration for the other tasks.

    +

    The runtime configuration for the remaining tasks has been written out +for you in the runtime file which you will find in the +run directory. Copy the code in the runtime file to the +bottom of the flow.cylc file.

    +

    Now that all the tasks have runtime sections, remove +[scheduler]allow implicit tasks:

    +
     [scheduler]
    +     UTC mode = True
    +-    allow implicit tasks = True  # TODO: remove at end of exercise
    +
    +
    +

    Removing this ensures that any tasks in the graph without a corresponding +runtime section will cause validation to fail (e.g. due to a typo).

    +

    Check the flow.cylc file is valid by running the command:

    +
    cylc validate .
    +
    +
    +

    Now install a new run of the workflow:

    +
    cylc install
    +
    +
    +
  10. +
  11. Run The Workflow.

    +

    Open a user interface (The Cylc TUI or The Cylc GUI) and +run the workflow.

    +
    +

    Tip

    +

    Make sure you play the latest run that was newly installed.

    +
    +
  12. +
  13. View The Forecast Summary.

    +

    The post_process_exeter task will produce a one-line summary of the +weather in Exeter, as forecast two hours ahead of time. This summary can +be found in the summary.txt file in the work directory.

    +

    Try opening the summary file - it will be in the last cycle. The path to +the work directory is:

    +
    work/<cycle-point>/<task-name>
    +
    +
    +
    +

    Hint

    +
      +
    • cycle-point - this will be the last cycle of the workflow, +i.e. the final cycle point.

    • +
    • task-name - set this to “post_process_exeter”.

    • +
    +
    +
  14. +
  15. View The Rainfall Data.

    +

    The forecast task will produce a html page where the rainfall +data is rendered on a map. This html file is called job-map.html and +is saved alongside the job log.

    +

    Try opening this file in a web browser, e.g via:

    +
    firefox <filename> &
    +
    +
    +

    The path to the job log directory is:

    +
    log/job/<cycle-point>/<task-name>/<submission-number>
    +
    +
    +
    +

    Hint

    +
      +
    • cycle-point - this will be the last cycle of the workflow, +i.e. the final cycle point.

    • +
    • task-name - set this to “forecast”.

    • +
    • submission-number - set this to “01”.

    • +
    +
    +
  16. +
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/runtime/summary.html b/nightly_8.4/html/tutorial/runtime/summary.html new file mode 100644 index 00000000000..8d88c896087 --- /dev/null +++ b/nightly_8.4/html/tutorial/runtime/summary.html @@ -0,0 +1,204 @@ + + + + + + + Tutorial Summary — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Tutorial Summary

+

You’ve made it to the end of the Cylc tutorial!

+

The Cylc tutorial aims to introduce you to the main concepts in Cylc to +prepare you for working with and writing Cylc workflows. +But there is so much more we didn’t have time for.

+
+
Rose Tutorial

Rose is a tool for creating configurable applications. It’s often used +with Cylc to configure more complex tasks, or even the workflow itself.

+

Rose configurations can have metadata, support validation and can be edited +using a GUI.

+

You might want to try the Rose Tutorial if these things are of interest.

+
+
Further Topics

There some extra tutorials which cover some of the things the main tutorial +doesn’t in the further topics section.

+
+
Discourse

If you get stuck, encounter an issue, have a question, or just fancy a chat +about Cylc, feel free to reach out to the Cylc community on our Discourse +forum.

+

We also make announcements (e.g. new Cylc releases) on the forum, so it’s a +good to keep an eye on it.

+
+
User Guide

There is a comprehensive User Guide which goes into Cylc’s +capabilities in detail.

+
+
Workflow Design Guide

This covers recommended code style and best practice.

+
+
Reference

The reference section contains all sorts of technical details.

+

It also lists all of the configurations Cylc supports for workflow +definition flow.cylc, and for site/user setup +global.cylc.

+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/scheduling/datetime-cycling.html b/nightly_8.4/html/tutorial/scheduling/datetime-cycling.html new file mode 100644 index 00000000000..e0587221483 --- /dev/null +++ b/nightly_8.4/html/tutorial/scheduling/datetime-cycling.html @@ -0,0 +1,669 @@ + + + + + + + Datetime Cycling — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Datetime Cycling

+
+

Aims

+
+
You should be able to:
+
✅ Write workflows with datetime cycle points.
+
+
+

In the last section we created an integer cycling workflow +with numbered cycle points.

+

Workflows may need to be repeated at a regular time intervals, say every day +or every few hours. To support this Cylc can generate datetime sequences +as cycle points instead of integers.

+
+

Reminder

+

In Cylc, cycle points are task labels that anchor the +dependencies between individual tasks: this task depends on that task in +that cycle. Tasks can run as soon as their individual dependencies are met, +so cycles do not necessarily run in order, or at the real world time +corresponding to the cycle point value (to do that, see +Clock Triggers).

+
+
+

ISO8601

+

Cylc uses the ISO8601 datetime standard to represent datetimes and durations.

+
+

ISO8601 Datetimes

+

ISO8601 datetimes are written from the largest unit to the smallest +(year, month, day, hour, minute, second) with a T separating the date +and time components. For example, midnight on the 1st of January 2000 is +written 20000101T000000.

+

For brevity we can omit seconds (or minutes) from the time: +20000101T0000 (or 20000101T00).

+
+

Note

+

The smallest interval for a datetime cycling sequence in Cylc is 1 minute.

+
+

For readability we can add hyphens (-) between the date components +and colons (:) between the time components. +This is optional, but if you do it you must use both hyphens and colons.

+

Time-zone information can be added onto the end. UTC is written Z, +UTC+1 is written +01, etc. E.G: 2000-01-01T00:00Z.

+../../_images/iso8601-dates.svg +
+
+

ISO8601 Durations

+

ISO8601 durations are prefixed with a P (for “period”) and +special characters following each unit:

+
    +
  • Y for year.

  • +
  • M for month.

  • +
  • D for day.

  • +
  • W for week.

  • +
  • H for hour.

  • +
  • M for minute.

  • +
  • S for second.

  • +
+

As for datetimes, duration components are written in order from largest to +smallest, and the date and time components are separated by a T:

+
    +
  • P1D: one day.

  • +
  • PT1H: one hour.

  • +
  • P1DT1H: one day and one hour.

  • +
  • PT1H30M: one and a half hours.

  • +
  • P1Y1M1DT1H1M1S: a year and a month and a day and an hour and a +minute and a second.

  • +
+
+
+
+

Datetime Recurrences

+

In integer cycling, workflows, recurrences are written P1, P2, +etc.

+

In datetime cycling workflows, there are two ways to +write recurrences:

+
    +
  1. Using ISO8601 durations (e.g. P1D, PT1H).

  2. +
  3. Using ISO8601 datetimes with inferred recurrence.

  4. +
+
+

Inferred Recurrence

+

Recurrence can be inferred from a datetime by omitting components from the +front. For example, if the year is omitted then the recurrence can be +inferred to be annual. E.g.:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +

Recurrence

Description

2000-01-01T00

Midnight on the 1st of January 2000

01-01T00

Every year on the 1st of January

01T00

Every month on the first of the month

T00

Every day at midnight

T-00

Every hour at zero minutes past (i.e. every hour on the hour)

+
+

Note

+

To omit hours from a date time, place a - after the T character.

+
+
+
+

Recurrence Formats

+

As with integer cycling, recurrences start at the initial cycle +point by default. We can override this in two ways:

+

By giving an arbitrary start cycle point (datetime/recurrence):

+
+
2000/P4Y

Every fourth year, starting with the year 2000.

+
+
2000-01-01T00/P1D

Every day at midnight, starting on the 1st of January 2000.

+
+
+

By offset, relative to the initial cycle point (offset/recurrence).

+

The offset must be an ISO8601 duration preceded by a plus character:

+
+
+PT1H/PT1H

Every hour starting one hour after the initial cycle point.

+
+
+P1Y/P1Y

Every year starting one year after the initial cycle point.

+
+
+
+
+

Durations and the Initial Cycle Point

+

When using durations, beware that a change in the initial cycle point +might produce different results for the recurrences.

+ + + + + + + + + +
[scheduling]
+    initial cycle point = \
+        2000-01-01T00
+    [[graph]]
+        P1D = foo[-P1D] => foo
+
+
+
[scheduling]
+    initial cycle point = \
+        2000-01-01T12
+    [[graph]]
+        P1D = foo[-P1D] => foo
+
+
+
+

digraph Example { +size = "3,3" + +"1/foo" [label="foo\n2000-01-01T00"] +"2/foo" [label="foo\n2000-01-02T00"] +"3/foo" [label="foo\n2000-01-03T00"] + +"1/foo" -> "2/foo" -> "3/foo" +}

+
+
+

digraph Example { +size = "3,3" + +"1/foo" [label="foo\n2000-01-01T12"] +"2/foo" [label="foo\n2000-01-02T12"] +"3/foo" [label="foo\n2000-01-03T12"] + +"1/foo" -> "2/foo" -> "3/foo" +}

+
+
+

We could write the recurrence “every midnight” independent of the initial +cycle point by:

+
    +
  • Using an inferred recurrence instead (i.e. T00).

  • +
  • Overriding the recurrence start point (i.e. T00/P1D)

  • +
  • Using [scheduling]initial cycle point constraints to +constrain the initial cycle point (e.g. to a particular time of day). See +the Cylc User Guide for details.

  • +
+
+
+

The Initial and Final Cycle Points

+

There are two special recurrences for the initial and final cycle points:

+
    +
  • R1: run once at the initial cycle point.

  • +
  • R1/P0Y: run once at the final cycle point.

  • +
+
+
+

Intercycle Dependencies

+

Intercycle dependencies are written as ISO8601 durations, e.g:

+
    +
  • foo[-P1D]: the task foo from the cycle one day before.

  • +
  • bar[-PT1H30M]: the task bar from the cycle 1 hour 30 minutes before.

  • +
+

The initial cycle point can be referenced using a caret character ^, e.g:

+
    +
  • baz[^]: the task baz from the initial cycle point.

  • +
+
+
+
+

Cycle Point Time Zone

+

Cylc can generate datetime cycle points in any time zone, but “daylight saving” +boundaries can cause confusion, so the default is UTC, i.e. the +00 time +zone. You can override this by setting [scheduler]cycle point time zone.

+
+

Note

+

UTC is sometimes also labelled Z (“Zulu” from the NATO phonetic alphabet) +according to the +military time zone convention.

+
+
+
+

Putting It All Together

+

Cylc was originally developed for running operational weather forecasting. In +this section we will outline how to implement a basic weather-forecasting workflow.

+
+

Note

+

Technically this example is a nowcasting workflow, +but the distinction doesn’t matter here.

+
+

A basic weather forecasting workflow has three main steps:

+
+

1. Gathering Observations

+

We gather observations from different weather stations to build a picture of +the current weather. Our dummy weather forecast will get wind observations +from four weather stations:

+
    +
  • Aldergrove (Near Belfast in NW of the UK)

  • +
  • Camborne (In Cornwall, the far SW of England)

  • +
  • Heathrow (Near London in the SE)

  • +
  • Shetland (The northernmost part of the UK)

  • +
+

The tasks that retrieve observation data will be called +get_observations_<site> where site is the name of the weather +station.

+

Next we need to consolidate the observations so that our forecasting +system can work with them. To do this we have a +consolidate_observations task.

+

We will fetch wind observations every three hours, starting from the +initial cycle point.

+

The consolidate_observations task must run after the +get_observations<site> tasks.

+
+

digraph example { +size = "7,4" + +get_observations_aldergrove -> consolidate_observations +get_observations_camborne -> consolidate_observations +get_observations_heathrow -> consolidate_observations +get_observations_shetland -> consolidate_observations + +hidden [style="invis"] +get_observations_aldergrove -> hidden [style="invis"] +get_observations_camborne -> hidden [style="invis"] +hidden -> consolidate_observations [style="invis"] +}

+
+

We will also use the UK radar network to get rainfall data with a task +called get_rainfall.

+

We will fetch rainfall data every six hours, from six hours after the +initial cycle point.

+
+
+

2. Running Computer Models to Generate Forecast Data

+

We will do this with a task called forecast that runs +every six hours, from six hours after the initial cycle point. +The forecast task will depend on:

+
    +
  • The consolidate_observations task from the previous two cycles and +the present cycle.

  • +
  • The get_rainfall task from the present cycle.

  • +
+
+

digraph example { +size = "7,4" + +subgraph cluster_T00 { + label="+PT0H" + style="dashed" + "observations.t00" [label="consolidate observations\n+PT0H"] +} + +subgraph cluster_T03 { + label="+PT3H" + style="dashed" + "observations.t03" [label="consolidate observations\n+PT3H"] +} + +subgraph cluster_T06 { + label="+PT6H" + style="dashed" + "forecast.t06" [label="forecast\n+PT6H"] + "get_rainfall.t06" [label="get_rainfall\n+PT6H"] + "observations.t06" [label="consolidate observations\n+PT6H"] +} + +"observations.t00" -> "forecast.t06" +"observations.t03" -> "forecast.t06" +"observations.t06" -> "forecast.t06" +"get_rainfall.t06" -> "forecast.t06" +}

+
+
+
+

3. Processing the data output to produce user-friendly forecasts

+

This will be done with a task called post_process_<location> where +location is the place we want to generate the forecast for. For +the moment we will use Exeter.

+

The post_process_exeter task will run every six hours starting six +hours after the initial cycle point and will be dependent on the +forecast task.

+
+

digraph example { +size = "2.5,2" + +"forecast" -> "post_process_exeter" +}

+
+
+

Practical

+

In this practical we will create a dummy forecasting workflow +using datetime cycling.

+
    +
  1. Create A New Workflow.

    +

    Create a new source directory datetime-cycling under ~/cylc-src, +and move into it:

    +
    mkdir ~/cylc-src/datetime-cycling
    +cd ~/cylc-src/datetime-cycling
    +
    +
    +

    Create a flow.cylc file and paste the following code into it:

    +
    [scheduler]
    +    UTC mode = True
    +    allow implicit tasks = True
    +[scheduling]
    +    initial cycle point = 20000101T00Z
    +    [[graph]]
    +
    +
    +
  2. +
  3. Add The Recurrences.

    +

    The weather-forecasting workflow will require two +recurrences. Add these under the graph section +based on the information given above.

    +
    +

    Hint

    +

    See Datetime Recurrences.

    +
    +
    +

    Solution

    +

    The two recurrences you need are

    +
      +
    • PT3H: repeat every three hours starting from the initial cycle +point.

    • +
    • +PT6H/PT6H: repeat every six hours starting six hours after the +initial cycle point.

    • +
    +
     [scheduler]
    +     UTC mode = True
    +     allow implicit tasks = True
    + [scheduling]
    +     initial cycle point = 20000101T00Z
    +     [[graph]]
    ++        PT3H =
    ++        +PT6H/PT6H =
    +
    +
    +
    +
  4. +
  5. Write The Graph.

    +

    With the help of the the information above add the tasks and dependencies to +to implement the weather-forecasting workflow.

    +

    You will need to consider the intercycle dependencies between tasks as well.

    +

    Use cylc graph to inspect your work.

    +
    +

    Hint

    +

    The dependencies you will need to formulate are as follows:

    +
      +
    • The consolidate_observations task depends on get_observations_<site>.

    • +
    • The forecast task depends on:

      +
        +
      • the get_rainfall task;

      • +
      • the consolidate_observations tasks from:

        +
          +
        • the same cycle;

        • +
        • the cycle 3 hours before (-PT3H);

        • +
        • the cycle 6 hours before (-PT6H).

        • +
        +
      • +
      +
    • +
    • The post_process_exeter task depends on the forecast +task.

    • +
    +

    To visualise your workflow run the command:

    +
    cylc graph <path/to/flow.cylc>
    +
    +
    +
    +
    +

    Solution

    +
    [scheduler]
    +    UTC mode = True
    +    allow implicit tasks = True
    +[scheduling]
    +    initial cycle point = 20000101T00Z
    +    [[graph]]
    +        PT3H = """
    +            get_observations_aldergrove => consolidate_observations
    +            get_observations_camborne => consolidate_observations
    +            get_observations_heathrow => consolidate_observations
    +            get_observations_shetland => consolidate_observations
    +        """
    +        +PT6H/PT6H = """
    +            consolidate_observations => forecast
    +            consolidate_observations[-PT3H] => forecast
    +            consolidate_observations[-PT6H] => forecast
    +            get_rainfall => forecast => post_process_exeter
    +        """
    +
    +
    +
    +
  6. +
  7. Intercycle Offsets.

    +

    To ensure the forecast tasks run in the right order (one cycle +after another) they each need to depend on their own previous run:

    +
    +

    digraph example { +size = "4,1.5" +rankdir=LR + +subgraph cluster_T06 { + label="T06" + style="dashed" + "forecast.t06" [label="forecast\nT06"] +} + +subgraph cluster_T12 { + label="T12" + style="dashed" + "forecast.t12" [label="forecast\nT12"] +} + +subgraph cluster_T18 { + label="T18" + style="dashed" + "forecast.t18" [label="forecast\nT18"] +} + +"forecast.t06" -> "forecast.t12" -> "forecast.t18" +}

    +
    +

    We can express this dependency as forecast[-PT6H] => forecast.

    +

    However, the forecast task runs every six hours +starting 6 hours after the initial cycle point, so the +dependency is only valid from 12:00 onwards. To fix the problem we +must add a new dependency section which repeats every six hours +starting 12 hours after the initial cycle point:

    +
               +PT6H/PT6H = """
    +               ...
    +-              forecast[-PT6H] => forecast
    +           """
    ++          +PT12H/PT6H = """
    ++              forecast[-PT6H] => forecast
    ++          """
    +
    +
    +
  8. +
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/scheduling/further-scheduling.html b/nightly_8.4/html/tutorial/scheduling/further-scheduling.html new file mode 100644 index 00000000000..b81b724fb39 --- /dev/null +++ b/nightly_8.4/html/tutorial/scheduling/further-scheduling.html @@ -0,0 +1,251 @@ + + + + + + + Further Scheduling — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Further Scheduling

+
+

Aims

+
+
You should be aware of some more advanced scheduling features:
+
✅ Task state qualifiers.
+
✅ Clock triggers.
+
✅ Alternative calendars.
+
+
+
+

Qualifiers

+

So far we have written dependencies like foo => bar. This is, in fact, +shorthand for foo:succeed => bar. It means that the task bar will run +once foo has finished successfully. If foo were to fail then bar +would not run. We will talk more about these task states +in the Runtime Section.

+

We refer to the :succeed descriptor as a qualifier. +There are qualifiers for different task states e.g:

+
+
:start

When the task has started running.

+
+
:fail

When the task finishes if it fails (produces non-zero return code).

+
+
:finish

When the task has completed (either succeeded or failed).

+
+
+

It is also possible to create your own qualifiers +to handle events within your code (custom outputs).

+

For more information see the Cylc User Guide.

+
+
+

Clock Triggers

+

In Cylc, cycle points are just task labels. Tasks are +triggered when their dependencies are met, regardless of cycle point. +But clock triggers can be used to force tasks to wait for a particular +real time, relative to their cycle point, before running. +This is necessary for certain operational and monitoring systems, e.g. for +tasks that process real-time data.

+

For example in the following workflow the cycle 2000-01-01T12Z will wait +until 11:00 on the 1st of January 2000 before running:

+
[scheduling]
+    initial cycle point = 2000-01-01T00Z
+    [[xtriggers]]
+        PT1H_trigger = wall_clock(offset=-PT1H)
+    [[graph]]
+        # "daily" will run, at the earliest, one hour before midday.
+        T12 = @PT1H_trigger => daily
+
+
+
+

Tip

+

See the Clock Triggered Tasks tutorial for more information.

+
+
+
+

Alternative Calendars

+

By default Cylc uses the Gregorian calendar for datetime cycling, +but it also supports:

+
    +
  • Integer cycling.

  • +
  • 360-day calendar (12 months of 30 days each in a year).

  • +
  • 365-day calendar (never a leap year).

  • +
  • 366-day calendar (always a leap year).

  • +
+
[scheduling]
+    cycling mode = 360day
+
+
+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/scheduling/graphing.html b/nightly_8.4/html/tutorial/scheduling/graphing.html new file mode 100644 index 00000000000..cca297328a9 --- /dev/null +++ b/nightly_8.4/html/tutorial/scheduling/graphing.html @@ -0,0 +1,544 @@ + + + + + + + The flow.cylc File Format — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

The flow.cylc File Format

+
+

Aims

+
+
You will be able to:
+
✅ Recognise the flow.cylc file format.
+
✅ Write simple chains of dependencies.
+
+
+

A Cylc workflow is defined by a flow.cylc configuration +file, which uses a nested INI format:

+
    +
  • Comments start with a # character.

  • +
  • Settings are written as key = value pairs.

  • +
  • Settings can be contained within sections.

  • +
  • Sections are written inside square brackets i.e. [section-name].

  • +
  • Sections can be nested, by adding an extra square bracket with each level, +so a sub-section would be written [[sub-section]], a sub-sub-section +[[[sub-sub-section]]], and so on.

  • +
+
+

Note

+

Prior to Cylc 8, flow.cylc was named suite.rc, +but that name is now deprecated.

+

See Cylc 7 Compatibility Mode for information on compatibility with +existing Cylc 7 suite.rc files.

+
+
+

Example

+
# Comment
+[section]
+    key = value
+    [[sub-section]]
+        another-key = another-value  # Inline comment
+        yet-another-key = """
+            A
+            Multi-line
+            String
+        """
+
+
+
+
+

Shorthand

+

We often use a compact single-line notation to refer to nested config items:

+
+
[section]

An entire section.

+
+
[section]setting

A setting within a section.

+
+
[section]setting=value

The value of a setting within a section.

+
+
[section][sub-section]another-setting

A setting within a sub-section.

+
+
+

In the file, however, section headings need additional brackets at each level.

+
+
+

Duplicate Items

+

Duplicate sections get merged:

+ + + + + + +
+
input
+
[a]
+   c = C
+[b]
+   d = D
+[a]  # duplicate
+   e = E
+
+
+
+
+
result
+
[a]
+   c = C
+   e = E
+[b]
+   d = D
+
+
+
+
+

Duplicate settings get overwritten:

+ + + + + + +
+
input
+
a = foo
+a = bar  # duplicate
+
+
+
+
+
result
+
a = bar
+
+
+
+
+

Except for duplicate graph string items, which get merged:

+ + + + + + +
+
input
+
R1 = "foo => bar"
+R1 = "foo => baz"
+
+
+
+
+
result
+
R1 = "foo => bar & baz"
+
+
+
+
+
+
+

Indentation

+

It is a good idea to indent flow.cylc files for readability.

+

However, Cylc ignores indentation, so the following examples are equivalent:

+ + + + + + +
+
input
+
[section]
+    a = A
+    [[sub-section]]
+        b = B
+    b = C
+    # this setting is still
+    # in [[sub-section]]
+
+
+
+
+
result
+
[section]
+    a = A
+    [[sub-section]]
+        b = C
+
+
+
+
+
+
+

The Dependency Graph

+
+

Graph Strings

+

Cylc workflows are defined in terms of tasks and +dependencies.

+

Task have names, and dependencies are represented by arrows +(=>) between them. For example, here’s a task make_dough that should +run after another task buy_ingredients has succeeded:

+
buy_ingredients => make_dough
+
+
+
+

digraph Mini_Cylc { +buy_ingredients -> make_dough +make_dough +}

+
+

These dependencies can be chained together in +graph strings:

+
buy_ingredients => make_dough => bake_bread => sell_bread
+
+
+
+

digraph Mini_Cylc { +bake_bread -> sell_bread +buy_ingredients -> make_dough +sell_bread +make_dough -> bake_bread +}

+
+

Graph strings can be combined to form more complex graphs:

+
buy_ingredients => make_dough => bake_bread => sell_bread
+pre_heat_oven => bake_bread
+bake_bread => clean_oven
+
+
+
+

digraph Mini_Cylc { +buy_ingredients -> make_dough +pre_heat_oven -> bake_bread +make_dough -> bake_bread +bake_bread -> clean_oven +clean_oven +bake_bread +bake_bread -> sell_bread +sell_bread +}

+
+

Graphs can also contain logical operators & (and) and | (or). +For example, the following lines are equivalent to those just above:

+
buy_ingredients => make_dough
+pre_heat_oven & make_dough => bake_bread => sell_bread & clean_oven
+
+
+

Collectively, all the graph strings make up the workflow dependency graph.

+
+

Note

+

The order of lines in the graph doesn’t matter, so +the following examples are equivalent:

+ + + + + + +
foo => bar
+bar => baz
+
+
+
bar => baz
+foo => bar
+
+
+
+
+
+
+

Cylc Graphs

+

A non-cycling graph can be defined with [scheduling][graph]R1, +where R1 means run once:

+
[scheduling]
+    [[graph]]
+        R1 = """
+            buy_ingredients => make_dough
+            pre_heat_oven & make_dough => bake_bread
+            bake_bread => sell_bread & clean_oven
+        """
+
+
+

This is a minimal Cylc workflow that defines a graph of +tasks to run, but does not yet say what scripts or applications to run +for each task. We will cover that later in the runtime tutorial.

+

Cylc provides a command line utility +for visualising graphs, cylc graph <path>, where +path is the location of the flow.cylc file. +It generates diagrams similar to the ones you have seen so far. The number +1 below each task is the cycle point. We will explain what this +means in the next section.

+../../_images/cylc-graph.png +
+

Hint

+

A graph can be drawn in multiple ways, for instance the following two +examples are equivalent:

+../../_images/cylc-graph-reversible.svg

Graphs drawn by cylc graph may vary slightly from one run to +another, but the tasks and dependencies will always be the same.

+
+
+

Practical

+

In this practical we will create a new Cylc workflow and write a +graph of tasks for it to run.

+
    +
  1. Create a Cylc workflow.

    +

    A Cylc workflow is defined by a flow.cylc file.

    +

    If you don’t have one already, create a cylc-src directory in your +user space:

    +
    mkdir ~/cylc-src
    +
    +
    +

    Now create a new workflow source directory called +graph-introduction under cylc-src and move into it:

    +
    mkdir ~/cylc-src/graph-introduction
    +cd ~/cylc-src/graph-introduction
    +
    +
    +

    In your new source directory create a flow.cylc +file and paste the following text into it:

    +
    [scheduler]
    +    allow implicit tasks = True
    +[scheduling]
    +    [[graph]]
    +        R1 = """
    +            # Write graph strings here!
    +        """
    +
    +
    +
  2. +
  3. Write a graph.

    +

    We now have a blank Cylc workflow. Next we need to define a graph.

    +

    Edit your flow.cylc file to add graph strings representing the +following graph:

    +
    +

    digraph graph_tutorial { +a -> b -> d -> e +c -> b -> f +}

    +
    +
  4. +
  5. Visualise the workflow.

    +

    Once you have written some graph strings try using cylc graph to +display the workflow. Run the following command:

    +
    cylc graph .
    +
    +
    +
    +

    Note

    +

    cylc graph takes the path to the workflow as an argument. Inside +the source directory we can just run cylc graph ..

    +
    +

    If the results don’t match the diagram above try to correct the graph +in your flow.cylc file.

    +
    +

    Solution

    +

    There are multiple correct ways to write this graph. So long as what +you see from cylc graph matches the above diagram then you have a +correct solution.

    +

    Two valid examples:

    +
    +
    + + + + + +
    a & c => b => d & f
    +d => e
    +
    +
    +
    a => b => d => e
    +c => b => f
    +
    +
    +
    +
    +

    The whole workflow should look something like this:

    +
    [scheduler]
    +    allow implicit tasks = True
    +[scheduling]
    +    [[graph]]
    +        R1 = """
    +            a & c => b => d & f
    +            d => e
    +        """
    +
    +
    +
    +
  6. +
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/scheduling/index.html b/nightly_8.4/html/tutorial/scheduling/index.html new file mode 100644 index 00000000000..579bc47bb25 --- /dev/null +++ b/nightly_8.4/html/tutorial/scheduling/index.html @@ -0,0 +1,204 @@ + + + + + + + Scheduling — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+ +
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/tutorial/scheduling/integer-cycling.html b/nightly_8.4/html/tutorial/scheduling/integer-cycling.html new file mode 100644 index 00000000000..91f104f5d89 --- /dev/null +++ b/nightly_8.4/html/tutorial/scheduling/integer-cycling.html @@ -0,0 +1,657 @@ + + + + + + + Basic Cycling — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Basic Cycling

+
+

Aims

+
+
You will be able to:
+
✅ Write simple cycling (repeating) workflows.
+
+
+
+

Repeating Workflows

+

You may want to repeat the same workflow multiple times. In Cylc this +is called cycling, and each repetition is called a cycle.

+

Each cycle is given a unique label, called a +cycle point. For now these will be integers, but they can also be +datetimes as we will see in the next section.

+

To make a workflow repeat we must tell Cylc three things:

+
+
The recurrence.

How often to repeat the workflow (or part of it).

+
+
The initial cycle point.

The cycle point to start from.

+
+
The final cycle point (optional).

We can also tell Cylc where to stop the workflow.

+
+
+

Let’s take the bakery example from the previous section. Bread is +baked in batches so the bakery will repeat this workflow for each +batch. We can make the workflow repeat by adding three lines:

+
 [scheduler]
+     allow implicit tasks = True
+ [scheduling]
++    cycling mode = integer
++    initial cycle point = 1
+     [[graph]]
+-        R1 = """
++        P1 = """
+             buy_ingredients => make_dough
+             pre_heat_oven & make_dough => bake_bread
+             bake_bread => sell_bread & clean_oven
+         """
+
+
+
    +
  • cycling mode = integer tells Cylc to give our cycle points integer labels.

  • +
  • initial cycle point = 1 tells Cylc to start counting cycle points +from 1.

  • +
  • P1 is the recurrence; a P1 graph string +repeats at every integer cycle point.

  • +
+

The first three cycles look like this, with the entire +workflow repeated at each cycle point:

+
+

digraph example { +size = "7,15" + +subgraph cluster_1 { + label = 1 + style = dashed + "1/pur" [label="buy_ingredients\n1"] + "1/mak" [label="make_dough\n1"] + "1/bak" [label="bake_bread\n1"] + "1/sel" [label="sell_bread\n1"] + "1/cle" [label="clean_oven\n1"] + "1/pre" [label="pre_heat_oven\n1"] +} + +subgraph cluster_2 { + label = 2 + style = dashed + "2/pur" [label="buy_ingredients\n2"] + "2/mak" [label="make_dough\n2"] + "2/bak" [label="bake_bread\n2"] + "2/sel" [label="sell_bread\n2"] + "2/cle" [label="clean_oven\n2"] + "2/pre" [label="pre_heat_oven\n2"] +} + +subgraph cluster_3 { + label = 3 + style = dashed + "3/pur" [label="buy_ingredients\n3"] + "3/mak" [label="make_dough\n3"] + "3/bak" [label="bake_bread\n3"] + "3/sel" [label="sell_bread\n3"] + "3/cle" [label="clean_oven\n3"] + "3/pre" [label="pre_heat_oven\n3"] +} + +"1/pur" -> "1/mak" -> "1/bak" -> "1/sel" +"1/pre" -> "1/bak" -> "1/cle" +"2/pur" -> "2/mak" -> "2/bak" -> "2/sel" +"2/pre" -> "2/bak" -> "2/cle" +"3/pur" -> "3/mak" -> "3/bak" -> "3/sel" +"3/pre" -> "3/bak" -> "3/cle" +}

+
+

The number under each task shows which cycle point it belongs to.

+
+
+

Intercycle Dependencies

+

We’ve just seen how to write a workflow that repeats every cycle.

+

Cylc runs tasks as soon as their dependencies are met, regardless of cycle +point, so cycles will not necessarily run in order. This can be efficient, +but it could also cause problems. For instance we could find ourselves +pre-heating the oven in one cycle while still cleaning it in another.

+

To resolve this we can add dependencies between +cycles, to the graph. To ensure that clean_oven completes before +pre_heat_oven starts in the next cycle, we can write this:

+
clean_oven[-P1] => pre_heat_oven
+
+
+

In a P1 recurrence, the suffix [-P1] means the previous cycle point, +Similarly, [-P2] refers back two cycles. The new dependency can be added +to the workflow graph like this:

+
 [scheduling]
+     cycling mode = integer
+     initial cycle point = 1
+     [[graph]]
+         P1 = """
+             buy_ingredients => make_dough
+             pre_heat_oven & make_dough => bake_bread
+             bake_bread => sell_bread & clean_oven
++            clean_oven[-P1] => pre_heat_oven
+         """
+
+
+

And the resulting workflow looks like this:

+
+

digraph example { +size = "7,15" + +subgraph cluster_1 { + label = 1 + style = dashed + "1/pur" [label="buy_ingredients\n1"] + "1/mak" [label="make_dough\n1"] + "1/bak" [label="bake_bread\n1"] + "1/sel" [label="sell_bread\n1"] + "1/cle" [label="clean_oven\n1"] + "1/pre" [label="pre_heat_oven\n1"] +} + +subgraph cluster_2 { + label = 2 + style = dashed + "2/pur" [label="buy_ingredients\n2"] + "2/mak" [label="make_dough\n2"] + "2/bak" [label="bake_bread\n2"] + "2/sel" [label="sell_bread\n2"] + "2/cle" [label="clean_oven\n2"] + "2/pre" [label="pre_heat_oven\n2"] +} + +subgraph cluster_3 { + label = 3 + style = dashed + "3/pur" [label="buy_ingredients\n3"] + "3/mak" [label="make_dough\n3"] + "3/bak" [label="bake_bread\n3"] + "3/sel" [label="sell_bread\n3"] + "3/cle" [label="clean_oven\n3"] + "3/pre" [label="pre_heat_oven\n3"] +} + +"1/pur" -> "1/mak" -> "1/bak" -> "1/sel" +"1/pre" -> "1/bak" -> "1/cle" +"1/cle" -> "2/pre" +"2/pur" -> "2/mak" -> "2/bak" -> "2/sel" +"2/pre" -> "2/bak" -> "2/cle" +"2/cle" -> "3/pre" +"3/pur" -> "3/mak" -> "3/bak" -> "3/sel" +"3/pre" -> "3/bak" -> "3/cle" +}

+
+

The intercycle dependency forces the connected tasks, in +different cycle points, to run in order.

+

Note that the buy_ingredients task has no arrows pointing at it. +This means it has no parent tasks to wait on, upstream in the graph. +Consequently all buy_ingredients tasks (out to a configurable +runahead limit) want to run straight away. +This could cause our bakery to run into cash-flow problems by purchasing +ingredients too far in advance of using them.

+

To solve this problem without running out of ingredients, the bakery wants +to purchase ingredients two batches ahead. This can be achieved by adding +the following dependency:

+
 [scheduling]
+     cycling mode = integer
+     initial cycle point = 1
+     [[graph]]
+         P1 = """
+             buy_ingredients => make_dough
+             pre_heat_oven & make_dough => bake_bread
+             bake_bread => sell_bread & clean_oven
+             clean_oven[-P1] => pre_heat_oven
++            sell_bread[-P2] => buy_ingredients
+         """
+
+
+

This means that buy_ingredients will run after the sell_bread task +two cycles earlier.

+
+

Note

+

The [-P2] suffix references a task two cycles back. For the first two +cycles this doesn’t make sense, so those dependencies (and indeed any before +the initial cycle point) will be ignored.

+
+
+

digraph example { +size = "4.5,15" + +subgraph cluster_1 { + label = 1 + style = dashed + "1/pur" [label="buy_ingredients\n1"] + "1/mak" [label="make_dough\n1"] + "1/bak" [label="bake_bread\n1"] + "1/sel" [label="sell_bread\n1"] + "1/cle" [label="clean_oven\n1"] + "1/pre" [label="pre_heat_oven\n1"] +} + +subgraph cluster_2 { + label = 2 + style = dashed + "2/pur" [label="buy_ingredients\n2"] + "2/mak" [label="make_dough\n2"] + "2/bak" [label="bake_bread\n2"] + "2/sel" [label="sell_bread\n2"] + "2/cle" [label="clean_oven\n2"] + "2/pre" [label="pre_heat_oven\n2"] +} + +subgraph cluster_3 { + label = 3 + style = dashed + "3/pur" [label="buy_ingredients\n3"] + "3/mak" [label="make_dough\n3"] + "3/bak" [label="bake_bread\n3"] + "3/sel" [label="sell_bread\n3"] + "3/cle" [label="clean_oven\n3"] + "3/pre" [label="pre_heat_oven\n3"] +} + +subgraph cluster_4 { + label = 4 + style = dashed + "4/pur" [label="buy_ingredients\n4"] + "4/mak" [label="make_dough\n4"] + "4/bak" [label="bake_bread\n4"] + "4/sel" [label="sell_bread\n4"] + "4/cle" [label="clean_oven\n4"] + "4/pre" [label="pre_heat_oven\n4"] +} + +"1/pur" -> "1/mak" -> "1/bak" -> "1/sel" +"1/pre" -> "1/bak" -> "1/cle" +"1/cle" -> "2/pre" +"1/sel" -> "3/pur" +"2/pur" -> "2/mak" -> "2/bak" -> "2/sel" +"2/pre" -> "2/bak" -> "2/cle" +"2/cle" -> "3/pre" +"2/sel" -> "4/pur" +"3/pur" -> "3/mak" -> "3/bak" -> "3/sel" +"3/pre" -> "3/bak" -> "3/cle" +"3/cle" -> "4/pre" +"4/pur" -> "4/mak" -> "4/bak" -> "4/sel" +"4/pre" -> "4/bak" -> "4/cle" +}

+
+
+
+

Recurrence Sections

+

In the previous examples we used a +P1recurrence to make the workflow repeat at successive integer +cycle points. Similarly P2 means repeat every other cycle, and so +on. We can use multiple recurrences to build more complex workflows:

+
[scheduling]
+   cycling mode = integer
+   initial cycle point = 1
+   [[graph]]
+      # Repeat every cycle.
+      P1 = foo
+      # Repeat every second cycle.
+      P2 = bar
+      # Repeat every third cycle.
+      P3 = baz
+
+
+../../_images/recurrence-sections.svg

We can also tell Cylc where to start a recurrence sequence.

+
+
From the initial cycle point:

By default, recurrences start at the: initial cycle point.

+
+
From an arbitrary cycle point:

We can give a different start point like this: +5/P3 means repeat every third cycle, starting from cycle number 5. +To run a graph at every other cycle point, use 2/P2.

+
+
Offset from the initial cycle point:

The start point of a recurrence can also be defined as an offset from the +initial cycle point For example, +P5/P3 means repeat every +third cycle from 5 cycles after the initial cycle point.

+
+
+
+

Practical

+

In this practical we will turn the workflow +of the previous section into a cycling workflow.

+

If you have not completed the previous practical use the following code for +your flow.cylc file.

+
[scheduler]
+    allow implicit tasks = True
+[scheduling]
+    [[graph]]
+        R1 = """
+            a & c => b => d & f
+            d => e
+        """
+
+
+
    +
  1. Create a new workflow.

    +

    Create a new source directory integer-cycling under ~/cylc-src/, +and move into it:

    +
    mkdir -p ~/cylc-src/integer-cycling
    +cd ~/cylc-src/integer-cycling
    +
    +
    +

    Copy the above code into a flow.cylc file in that directory.

    +
  2. +
  3. Make the workflow cycle.

    +

    Add the following lines to your flow.cylc file:

    +
     [scheduling]
    ++    cycling mode = integer
    ++    initial cycle point = 1
    +     [[graph]]
    +-        R1 = """
    ++        P1 = """
    +             a & c => b => d & f
    +             d => e
    +         """
    +
    +
    +
  4. +
  5. Visualise the workflow.

    +

    Try visualising your workflow using cylc graph.

    +
    cylc graph .
    +
    +
    +
    +

    Tip

    +

    You can use the -c (--cycles) option +to draw a box around each cycle:

    +
    cylc graph -c .
    +
    +
    +
    +
    +

    Tip

    +

    By default cylc graph displays the first three cycles of the graph, +but you can specify the range of cycles on the command line. +Here’s how to display cycles 1 through 5:

    +
    cylc graph . 1 5
    +
    +
    +
    +
  6. +
  7. Add another recurrence.

    +

    Suppose we wanted the e task to run every other cycle +as opposed to every cycle. We can do this by adding another +recurrence.

    +

    Make the following changes to your flow.cylc file.

    +
     [scheduling]
    +     cycling mode = integer
    +     initial cycle point = 1
    +     [[graph]]
    +         P1 = """
    +             a & c => b => d & f
    +-            d => e
    +         """
    ++        P2 = """
    ++            d => e
    ++        """
    +
    +
    +

    Use cylc graph to see the effect this has on the workflow.

    +
  8. +
  9. intercycle dependencies.

    +

    Now we will add +three intercycle dependencies:

    +
      +
    1. Between f from the previous cycle and c.

    2. +
    3. Between d from the previous cycle and a +every odd cycle (e.g. 2/d => 3/a).

    4. +
    5. Between e from the previous cycle and a +every even cycle (e.g. 1/e => 2/a).

    6. +
    +

    Try adding these to your flow.cylc file to +make your workflow match the diagram below.

    +
    +

    Hint

    +
      +
    • P2 means every other cycle, from the initial cycle point.

    • +
    • 2/P2 means every other cycle, from cycle point 2.

    • +
    +
    +
    +

    digraph example { + size = "4.5,7" + + subgraph cluster_1 { + label = 1 + style = dashed + "1/a" [label="a\n1"] + "1/b" [label="b\n1"] + "1/d" [label="d\n1"] + "1/f" [label="f\n1"] + "1/c" [label="c\n1"] + "1/e" [label="e\n1"] + } + + subgraph cluster_2 { + label = 2 + style = dashed + "2/a" [label="a\n2"] + "2/b" [label="b\n2"] + "2/d" [label="d\n2"] + "2/f" [label="f\n2"] + "2/c" [label="c\n2"] + } + + subgraph cluster_3 { + label = 3 + style = dashed + "3/a" [label="a\n3"] + "3/b" [label="b\n3"] + "3/d" [label="d\n3"] + "3/f" [label="f\n3"] + "3/c" [label="c\n3"] + "3/e" [label="e\n3"] + } + + "1/a" -> "1/b" -> "1/f" + "1/b" -> "1/d" + "1/c" -> "1/b" + "2/a" -> "2/b" -> "2/f" + "2/b" -> "2/d" + "2/c" -> "2/b" + "3/a" -> "3/b" -> "3/f" + "3/b" -> "3/d" + "3/c" -> "3/b" + "1/d" -> "1/e" -> "2/a" + "3/d" -> "3/e" + "2/d" -> "3/a" + "1/f" -> "2/c" + "2/f" -> "3/c" +}

    +
    +
    +

    Solution

    +
    [scheduler]
    +    allow implicit tasks = True
    +[scheduling]
    +    cycling mode = integer
    +    initial cycle point = 1
    +    [[graph]]
    +        P1 = """
    +            a & c => b => d & f
    +            f[-P1] => c  # (1)
    +        """
    +        P2 = """
    +            d => e
    +            d[-P1] => a  # (2)
    +        """
    +        2/P2 = """
    +            e[-P1] => a  # (3)
    +        """
    +
    +
    +
    +
  10. +
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/cheat-sheet.html b/nightly_8.4/html/user-guide/cheat-sheet.html new file mode 100644 index 00000000000..74b89d2a493 --- /dev/null +++ b/nightly_8.4/html/user-guide/cheat-sheet.html @@ -0,0 +1,459 @@ + + + + + + + Cheat Sheet — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Cheat Sheet

+

A cheat sheet covering most of the major Cylc commands. For a full list see +cylc help all.

+

See also the Cylc 7 to 8 migration cheat sheet.

+ +
+

Working with Workflows

+
+
cylc validate

Validates the workflow configuration (will tell you if there are any problems).

+
+
cylc install

Install a workflow (i.e. copy its files into the ~/cylc-run directory).

+
+
cylc play

Start a workflow running.

+
+
+

Install and start a workflow:

+
# validate a workflow
+cylc validate <name|path>
+
+# install a workflow
+cylc install <name|path>
+
+# start a workflow
+cylc play <id>
+
+
+

For convenience, these three operations can be combined with the cylc vip command +(vip = validate + install + play):

+
# validate, install and play a workflow
+cylc vip <name|path>
+
+
+

When you’re done with a workflow run, remove it with cylc clean:

+
# delete a workflow installation
+cylc clean <id>
+
+
+
+
+

Starting and Stopping Workflows

+

Start workflows with cylc play, stop them with cylc stop.

+

Workflows can be started or stopped multiple times, Cylc will always continue +where it left off:

+
# start a workflow
+cylc play <id>
+
+# stop a workflow
+cylc stop <id>
+
+# restart a workflow
+cylc play <id>
+
+
+

You can also “pause” a workflow. A paused workflow will not submit any new +jobs. Pausing workflows can be handy if you need to perform +interventions on them. Use cylc play to +resume a workflow:

+
# pause a workflow
+cylc pause <id>
+
+# resume a workflow
+cylc play <id>
+
+
+

The Cylc play, pause and stop commands work similarly to the play, pause and +stop buttons on an old tape player. You can play, pause or stop a workflow as +many times as you like; Cylc will never lose its place in the workflow.

+
+
+

List Workflows

+

The cylc scan command can list your installed workflows:

+
# list all running workflows
+cylc scan
+
+# get information about running workflows
+cylc scan --format=rich
+
+# list all installed workflows
+cylc scan --states=all
+
+
+

You can also view your workflows in the GUI or Tui.

+
+
+

Opening the GUI/Tui

+

Cylc has an in-terminal utility for monitoring and controlling workflows:

+
# view all workflows
+cylc tui
+
+# open a specific workflow
+cylc tui <id>
+
+
+

There is also a GUI which opens in a web browser:

+
# open the GUI to the homepage
+cylc gui
+
+# open the GUI to a specific workflow
+cylc gui <id>
+
+
+
+
+

Making Changes To Running Workflows

+

You can make changes to a workflow without having to shut it down and restart it.

+

First, make your required changes to the files in the workflow’s +source directory, then run the cylc vr command +(more information):

+
# validate, reinstall and reload the workflow
+cylc vr <id>
+
+
+

If you want to quickly edit a task’s configuration, e.g. whilst developing a +workflow or testing changes, the +“Edit Runtime” feature +in the GUI can be convenient.

+
+
+

Inspecting Workflows

+

Validate the workflow configuration (good for spotting errors):

+
cylc validate <path|id>
+
+
+

Check the workflow for common problems and code style:

+
cylc lint <path|id>
+
+
+

View the workflow configuration before Cylc has parsed it +(but after pre-processing - good for debugging Jinja2 errors):

+
cylc view -p <path|id>
+
+
+

View the workflow configuration after Cylc has parsed it +(good for debugging family inheritance):

+
cylc config <path|id>
+
+# view a specific task's configuration
+cylc config <path|id> -i '[runtime][<task>]'
+
+# view the workflow configuration with defaults applied
+cylc config <path|id> --defaults
+
+
+

Generate a graphical representation of the workflow’s graph +(a useful tool for developing workflow graphs):

+
cylc graph <path|id>
+
+# render the graph between two cycle points
+cylc graph <path|id> <cycle1> <cycle2>
+
+# render the graph transposed (can make it easier to read)
+cylc graph <path|id> --transpose
+
+# group tasks by cycle point
+cylc graph <path|id> --cycles
+
+# collapse tasks within a family (can reduce the number of tasks displayed)
+cylc graph <path|id> --group=<family>
+
+
+

List all tasks and families defined in a workflow:

+
cylc list <path|id>
+
+
+
+
+

Running Rose Stem Workflows

+

Currently, Rose stem workflows are installed using a different command to +regular workflows:

+
# install a rose-stem workflow
+rose stem
+
+# start a rose-stem workflow
+cylc play <id>
+
+
+

Once a workflow is installed you can run regular Cylc commands against it, e.g +cylc stop.

+

We may be able to automatically activate rose stem functionality as part +of cylc install in the future which would allow you to install and start +a Rose Stem workflow with cylc vip.

+
+
+

Interventions

+

You can intervene in the running a workflow, e.g. to re-run a task.

+

Interventions are written up in Interventions. Here is a +quick summary:

+

Run or re-run a task (more info):

+
cylc trigger <id>//<cycle>/<task>
+
+
+

Mark a task as “succeeded” +(more info):

+
cylc set <id>//<cycle>/<task>
+
+
+

Kill a running job:

+
cylc kill <id>//<cycle>/<task>
+
+
+
+
+

Running Workflows in Debug Mode

+

When a workflow is in debug mode, more information gets written to the +workflow’s log file. +Jobs also get run in Bash “xtrace” mode (set -x) which can help to diagnose +the line in a task’s script that caused the error.

+

Start a workflow in debug mode:

+
$ cylc vip --debug <name|path>
+
+# OR
+$ cylc play --debug <id>
+
+
+

Switch an already running workflow into debug mode:

+
cylc verbosity DEBUG <workflow-id>
+
+
+

For more information, see Troubleshooting.

+
+
+

Managing Multiple Workflows

+

Many Cylc commands can operate over multiple workflows:

+
# stop all workflows
+cylc stop '*'
+
+# pause all workflows
+cylc pause '*'
+
+# re-run all failed tasks in all workflows
+cylc trigger "*//*/*:failed"
+
+
+

The * characters in these examples are “globs”. Make sure you put quotes +around them to prevent the shell from trying to expand them.

+

For more information on globs or the Cylc ID format, run cylc help id.

+
+
+

Working With Cylc IDs

+

Everything in a Cylc workflow has an ID. We use these IDs on the command line +and in the GUI.

+

Cylc Ids take the format:

+
<workflow-id>//<cycle>/<task>/<job>
+
+
+

E.G:

+
# a workflow
+my-workflow
+
+# a cycle within a workflow
+my-workflow//20000101T00Z
+
+# a task instance
+my-workflow//20000101T00Z/mytask
+
+# a job submission
+my-workflow//20000101T00Z/mytask/01
+
+
+

For more information on the Cylc ID format, run cylc help id.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/examples/1-hello-world/index.html b/nightly_8.4/html/user-guide/examples/1-hello-world/index.html new file mode 100644 index 00000000000..0d0f1f3dc4c --- /dev/null +++ b/nightly_8.4/html/user-guide/examples/1-hello-world/index.html @@ -0,0 +1,210 @@ + + + + + + + Hello World — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Hello World

+
+

Get a copy of this example

+
$ cylc get-resources examples/hello-world
+
+
+
+

In the time honoured tradition, this is the minimal Cylc workflow:

+
[meta]
+    title = Hello World
+    description = """
+        A simple workflow which runs a single task (hello_world) once.
+    """
+
+[scheduling]
+    [[graph]]
+        R1 = hello_world
+
+[runtime]
+    [[hello_world]]
+        script = echo "Hello World!"
+
+
+

It writes the phrase “Hello World!” to standard output (captured to the +job.out log file).

+

Run it with:

+
$ cylc vip hello-world
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/examples/2-integer-cycling/index.html b/nightly_8.4/html/user-guide/examples/2-integer-cycling/index.html new file mode 100644 index 00000000000..35499c466be --- /dev/null +++ b/nightly_8.4/html/user-guide/examples/2-integer-cycling/index.html @@ -0,0 +1,222 @@ + + + + + + + Integer Cycling — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Integer Cycling

+
+

Get a copy of this example

+
$ cylc get-resources examples/integer-cycling
+
+
+
+
[meta]
+    title = Integer Cycling
+    description = """
+        A basic cycling workflow which runs the same set of tasks over
+        and over. Each cycle will be given an integer number.
+    """
+
+[scheduling]
+    # tell Cylc to count cycles as numbers starting from the number 1
+    cycling mode = integer
+    initial cycle point = 1
+    [[graph]]
+        P1 = """
+            # this is the workflow we want to repeat:
+            a => b => c & d
+            # this is an "inter-cycle dependency", it makes the task "b"
+            # wait until its previous instance has completed:
+            b[-P1] => b
+        """
+
+[runtime]
+    [[root]]
+        # all tasks will "inherit" the configuration in the "root" section
+        script = echo "Hello, I'm task $CYLC_TASK_NAME in cycle $CYLC_TASK_CYCLE_POINT!"
+    [[a]]
+    [[b]]
+    [[c]]
+    [[d]]
+
+
+

Run it with:

+
$ cylc vip integer-cycling
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/examples/3-datetime-cycling/index.html b/nightly_8.4/html/user-guide/examples/3-datetime-cycling/index.html new file mode 100644 index 00000000000..a64a4ef15c1 --- /dev/null +++ b/nightly_8.4/html/user-guide/examples/3-datetime-cycling/index.html @@ -0,0 +1,238 @@ + + + + + + + Datetime Cycling — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Datetime Cycling

+
+

Get a copy of this example

+
$ cylc get-resources examples/datetime-cycling
+
+
+
+
[meta]
+    title = Datetime Cycling
+    description = """
+        A basic cycling workflow which runs the same set of tasks over
+        and over. Each cycle will be given a datetime identifier.
+
+        The task "a" will wait until the real-world (or wallclock) time passes
+        the cycle time.
+
+        Try changing the "initial cycle point" to "previous(00T00) - P1D" to
+        see how this works.
+    """
+
+[scheduling]
+    # set the start of the graph to 00:00 this morning
+    initial cycle point = previous(T00)
+
+    [[graph]]
+        # repeat this with a "P"eriod of "1" "D"ay -> P1D
+        P1D = """
+            # this is the workflow we want to repeat:
+            a => b => c & d
+
+            # this is an "inter-cycle dependency", it makes the task "b"
+            # wait until its previous instance has successfully completed:
+            b[-P1D] => b
+
+            # this makes the task "a" wait until its cycle point matches
+            # the real world time - i.e. it prevents the workflow from getting
+            # ahead of the clock. If the workflow is running behind (e.g. after
+            # a delay, or from an earlier initial cycle point) it will catch
+            # until the clock-trigger constrains it again. To run entirely in
+            # "simulated time" remove this line:
+            @wall_clock => a
+        """
+
+[runtime]
+    [[root]]
+        # all tasks will "inherit" the configuration in the "root" section
+        script = echo "Hello, I'm task $CYLC_TASK_NAME in cycle $CYLC_TASK_CYCLE_POINT!"
+    [[a]]
+    [[b]]
+    [[c]]
+    [[d]]
+
+
+

Run it with:

+
$ cylc vip datetime-cycling
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/examples/converging-workflow/index.html b/nightly_8.4/html/user-guide/examples/converging-workflow/index.html new file mode 100644 index 00000000000..3db53972f1d --- /dev/null +++ b/nightly_8.4/html/user-guide/examples/converging-workflow/index.html @@ -0,0 +1,249 @@ + + + + + + + Converging Workflow — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Converging Workflow

+
+

Get a copy of this example

+
$ cylc get-resources examples/converging-workflow
+
+
+
+

A workflow which runs a pattern of tasks over and over until a convergence +condition has been met.

+
    +
  • The increment task runs some kind of model or process which increments +us toward the solution.

  • +
  • The check_convergence task, checks if the convergence condition has been +met.

  • +
+
[meta]
+    title = Converging Workflow
+    description = """
+        A workflow which runs a pattern of tasks over and over until a
+        convergence condition has been met.
+    """
+
+[scheduling]
+    cycling mode = integer
+    initial cycle point = 1
+    [[graph]]
+        P1 = """
+            # run "increment" then check the convergence condition
+            check_convergence[-P1]:not_converged? => increment => check_convergence
+
+            # if the workflow has converged, then do nothing
+            check_convergence:converged?
+        """
+
+[runtime]
+    [[increment]]
+        # a task which evolves the data
+    [[check_convergence]]
+        # a task which checks whether the convergence condition has been met
+        script = """
+            if (( CYLC_TASK_CYCLE_POINT == 4 )); then
+                # for the purpose of example, assume convergence at cycle point 4
+                cylc message -- 'convergence condition met'
+            else
+                cylc message -- 'convergence condition not met'
+            fi
+        """
+        [[[outputs]]]
+            converged = 'convergence condition met'
+            not_converged = 'convergence condition not met'
+
+
+

Run it with:

+
$ cylc vip converging-workflow
+
+
+
+

Example - Genetic algorithms

+

An example of a converging workflow might be a genetic algorithm, where you +“breed” entities, then test their “fitness”, and breed again, over and over +until you end up with an entity which is able to satisfy the requirement.

+
+

digraph Example { +random_seed -> breed -> test_fitness +test_fitness -> breed +test_fitness -> stop +}

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/examples/event-driven-cycling/README.html b/nightly_8.4/html/user-guide/examples/event-driven-cycling/README.html new file mode 100644 index 00000000000..03623375f86 --- /dev/null +++ b/nightly_8.4/html/user-guide/examples/event-driven-cycling/README.html @@ -0,0 +1,197 @@ + + + + + + + <no title> — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Cylc is good at orchestrating tasks to a schedule, e.g:

+
    +
  • PT1H - every hour

  • +
  • P1D - every day

  • +
  • P1M - every month

  • +
  • PT1H ! (T00, T12) - every hour, except midnight and midday.

  • +
+

But sometimes the things you want to run don’t have a schedule.

+

This example uses cylc ext-trigger to establish a pattern where Cylc waits +for an external signal and starts a new cycle every time a signal is received.

+

The signal can carry data using the ext-trigger ID, this example sets the ID +as a file path containing some data that we want to make available to the tasks +that run in the cycle it triggers.

+

To use this example, first start the workflow as normal:

+
cylc vip event-driven-cycling
+
+
+

Then, when you’re ready, kick off a new cycle, specifying any +environment variables you want to configure this cycle with:

+
./bin/trigger <workflow-id> WORLD=earth
+
+
+

Replacing <workflow-id> with the ID you installed this workflow as.

+
+

Example - CI/CD

+

This pattern is good for CI/CD type workflows where you’re waiting on +external events. This pattern is especially powerful when used with +sub-workflows where it provides a solution to two-dimensional cycling +problems.

+
+
+

Example - Polar satellite data processing

+

Polar satellites pass overhead at irregular intervals. This makes it tricky +to schedule data processing because you don’t know when the satellite will +pass over the receiver station. With the event driven cycling approach you +could start a new cycle every time data arrives.

+
+
+

Note

+
    +
  • The number of parallel cycles can be adjusted by changing the +[scheduling]runahead limit.

  • +
  • To avoid hitting the runahead limit, ensure that failures are handled in +the graph.

  • +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/examples/event-driven-cycling/index.html b/nightly_8.4/html/user-guide/examples/event-driven-cycling/index.html new file mode 100644 index 00000000000..c1fa3cafc38 --- /dev/null +++ b/nightly_8.4/html/user-guide/examples/event-driven-cycling/index.html @@ -0,0 +1,268 @@ + + + + + + + Event Driven Cycling — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Event Driven Cycling

+
+

Get a copy of this example

+
$ cylc get-resources examples/event-driven-cycling
+
+
+
+

Cylc is good at orchestrating tasks to a schedule, e.g:

+
    +
  • PT1H - every hour

  • +
  • P1D - every day

  • +
  • P1M - every month

  • +
  • PT1H ! (T00, T12) - every hour, except midnight and midday.

  • +
+

But sometimes the things you want to run don’t have a schedule.

+

This example uses cylc ext-trigger to establish a pattern where Cylc waits +for an external signal and starts a new cycle every time a signal is received.

+

The signal can carry data using the ext-trigger ID, this example sets the ID +as a file path containing some data that we want to make available to the tasks +that run in the cycle it triggers.

+

To use this example, first start the workflow as normal:

+
cylc vip event-driven-cycling
+
+
+

Then, when you’re ready, kick off a new cycle, specifying any +environment variables you want to configure this cycle with:

+
./bin/trigger <workflow-id> WORLD=earth
+
+
+

Replacing <workflow-id> with the ID you installed this workflow as.

+
+

Example - CI/CD

+

This pattern is good for CI/CD type workflows where you’re waiting on +external events. This pattern is especially powerful when used with +sub-workflows where it provides a solution to two-dimensional cycling +problems.

+
+
+

Example - Polar satellite data processing

+

Polar satellites pass overhead at irregular intervals. This makes it tricky +to schedule data processing because you don’t know when the satellite will +pass over the receiver station. With the event driven cycling approach you +could start a new cycle every time data arrives.

+
+
+

Note

+
    +
  • The number of parallel cycles can be adjusted by changing the +[scheduling]runahead limit.

  • +
  • To avoid hitting the runahead limit, ensure that failures are handled in +the graph.

  • +
+
+
[scheduling]
+    cycling mode = integer
+    initial cycle point = 1
+    runahead limit = P5  # max number of cycles which can run in parallel
+    [[special tasks]]
+        # register the external trigger, it must be given a name,
+        # here, 'trigger' is used as a placeholder, the bash script will
+        # need to be updated if this is changed
+        external-trigger = configure("trigger")
+    [[graph]]
+        P1 = """
+            # use a "?" to prevent failures causing runahead stalls
+            configure? => run
+        """
+
+[runtime]
+    [[configure]]
+        # this task reads in the broadcast file the trigger wrote
+        # and broadcasts any variables set to all tasks in this cycle
+        script = """
+            echo "received new ext-trigger ID=$CYLC_EXT_TRIGGER_ID"
+            TRIGGER_FILE="${CYLC_WORKFLOW_RUN_DIR}/triggers/${CYLC_EXT_TRIGGER_ID}.cylc"
+            cylc broadcast "${CYLC_WORKFLOW_ID}" \
+                -p "${CYLC_TASK_CYCLE_POINT}" \
+                -F "${TRIGGER_FILE}"
+        """
+
+    [[run]]
+        # this task could be a sub-workflow
+        script = """
+            echo "Hello $WORLD!"
+        """
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/examples/extending-workflow/index.html b/nightly_8.4/html/user-guide/examples/extending-workflow/index.html new file mode 100644 index 00000000000..8c29c6cab33 --- /dev/null +++ b/nightly_8.4/html/user-guide/examples/extending-workflow/index.html @@ -0,0 +1,288 @@ + + + + + + + Extending Workflow — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Extending Workflow

+

Sometimes we may run a workflow to completion, +but subsequently wish to run it for a few more cycles.

+

With Cylc 7 this was often done by changing the final cycle point and +restarting the workflow. This approach worked, but was a little awkward. +It’s possible with Cylc 8, but we would recommend moving away from this +pattern instead.

+

The recommended approach to this problem (Cylc 6+) is to use the +stop after cycle point rather than the final cycle point.

+

The stop after cycle point tells Cylc to stop after the workflow passes +the specified point, whereas the final cycle point tells Cylc that the +workflow finishes at the specified point.

+

When a workflow finishes, it is a little awkward to restart as you have to +tell Cylc which tasks to continue on from. The stop after cycle point +solution avoids this issue.

+
+

Example

+
+

Get a copy of this example

+
$ cylc get-resources examples/extending-workflow/simple
+
+
+
+

This workflow will stop at the end of the 2002 cycle:

+
[meta]
+    title = "Basic extendable workflow"
+    description = """
+        Use the "stop after cycle point" rather than the "final cycle point"
+        to allow this workflow to be easily extended at a later date.
+    """
+
+[scheduler]
+    # use the year for the cycle point
+    # (strip off the month, day, hour and minute)
+    cycle point format = CCYY
+
+[scheduling]
+    initial cycle point = 2000
+    stop after cycle point = 2002  # stop after two years of simulated time
+    [[graph]]
+        P1Y = """
+            z[-P1Y] => a
+            a => z
+        """
+
+[runtime]
+    [[a]]
+    [[z]]
+
+
+

After it has run and shut down, change the stop after cycle point to +the desired value and restart it. E.g:

+
# install and run the workflow:
+cylc vip
+
+# then later edit "stop after cycle point" to "2004"
+
+# then reinstall and restart the workflow:
+cylc vr
+
+
+

The workflow will continue from where it left off and run until the end of the +2004 cycle. Because the workflow never hit the final cycle point it +never “finished” so no special steps are required to restart the workflow.

+

You can also set the stop after cycle point when you start the workflow:

+
cylc play --stop-cycle-point=2020 myworkflow
+
+
+

Or change it at any point whilst the workflow is running:

+
cylc stop myworkflow//2030  # change the stop after cycle point to 2030
+
+
+
+

Note

+

If you set the stop after cycle point on the command line, this value will +take precedence over the one in the workflow configuration. Use +cylc play --stop-cycle-point=reload to restart the workflow using the +stop after cycle point configured in the workflow configuration.

+
+
+
+

Running Tasks At The stop after cycle point

+

If you have tasks that you want to run before the workflow shuts down at the +stop after cycle point, use the recurrence R1/<cycle-point> to schedudule +them, e.g:

+
#!Jinja2
+
+{% set stop_cycle = '3000' %}
+
+[scheduling]
+   initial cycle point = 2000
+   stop after cycle point = {{ stop_cycle }}
+   [[graph]]
+      R1/{{ stop_cycle }} = """
+         # these tasks will run *before* the workflow shuts down
+         z => run_me => and_me
+      """
+
+
+

When the workflow is subsequently restarted with a later +stop after cycle point, these tasks will be re-scheduled at the new +stop point.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/examples/index.html b/nightly_8.4/html/user-guide/examples/index.html new file mode 100644 index 00000000000..4eb26f6693f --- /dev/null +++ b/nightly_8.4/html/user-guide/examples/index.html @@ -0,0 +1,197 @@ + + + + + + + Examples — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Examples

+

These examples cover some of the main patterns for implementing Cylc workflows.

+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/examples/inter-workflow-triggers/README.html b/nightly_8.4/html/user-guide/examples/inter-workflow-triggers/README.html new file mode 100644 index 00000000000..2b5ec9f3ddf --- /dev/null +++ b/nightly_8.4/html/user-guide/examples/inter-workflow-triggers/README.html @@ -0,0 +1,163 @@ + + + + + + + <no title> — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

This example shows how one workflow can “trigger off” of tasks in another +workflow.

+

In this example, there are two workflows:

+
    +
  • “upstream” writes a file.

  • +
  • “downstream” reads this file.

  • +
+

Run both workflows simultaneously to see this in action:

+
$ cylc vip inter-workflow-triggers/upstream
+$ cylc vip inter-workflow-triggers/downstream
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/examples/inter-workflow-triggers/index.html b/nightly_8.4/html/user-guide/examples/inter-workflow-triggers/index.html new file mode 100644 index 00000000000..442b20a9253 --- /dev/null +++ b/nightly_8.4/html/user-guide/examples/inter-workflow-triggers/index.html @@ -0,0 +1,270 @@ + + + + + + + Inter-Workflow Triggering — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Inter-Workflow Triggering

+
+

Get a copy of this example

+
$ cylc get-resources examples/inter-workflow-triggers
+
+
+
+

This example shows how one workflow can “trigger off” of tasks in another +workflow.

+

In this example, there are two workflows:

+
    +
  • “upstream” writes a file.

  • +
  • “downstream” reads this file.

  • +
+

Run both workflows simultaneously to see this in action:

+
$ cylc vip inter-workflow-triggers/upstream
+$ cylc vip inter-workflow-triggers/downstream
+
+
+
+
Upstream Workflow
+
[meta]
+    title = Upstream Workflow
+    description = """
+        This is the workflow which is providing the data that the downstream
+        workflow wants to use.
+    """
+
+[scheduling]
+    # start two hours before the current time on the whole hour
+    initial cycle point = previous(T-00) - PT2H
+    [[graph]]
+        PT1H = """
+            # wait for the "real world" time before running "a":
+            @wall_clock => a
+
+            # then run task "b"
+            a => b
+        """
+
+[runtime]
+    [[a]]
+    [[b]]
+        # write a random number to ~/cylc-run/<workflow-id>/share/<cycle>
+        # for the downstream workflow to use
+        script = echo "$RANDOM" > "$file"
+        [[[environment]]]
+            file = ${CYLC_WORKFLOW_SHARE_DIR}/${CYLC_TASK_CYCLE_POINT}
+
+
+
+
+
Downstream Workflow
+
[meta]
+    title = Downstream Workflow
+    description = """
+        This workflow uses the data provided by the upstream workflow.
+    """
+
+[scheduling]
+    # start two hours before the current hour
+    initial cycle point = previous(T-00) - PT2H
+    [[xtriggers]]
+        # this is an "xtrigger" - it will wait for the task "b" in the same
+        # cycle from the workflow "upstream"
+        upstream = workflow_state(workflow_task_id="inter-workflow-triggers/upstream//%(point)s/b")
+    [[graph]]
+        PT1H = """
+            @upstream => process
+        """
+
+[runtime]
+    [[process]]
+        script = echo "The random number is: $(cat "$file")"
+        [[[environment]]]
+            # this is where the data should be written to in the upstream workflow
+            # Note: "runN" will point to the most recent run of a workflow
+            file = $HOME/cylc-run/upstream/runN/share/$CYLC_TASK_CYCLE_POINT
+
+
+
+
+

Example - Decoupled workflows

+

This pattern is useful where you have workflows that you want to keep decoupled +from one another, but still need to exchange data. E.G. in operational +meteorology we might have a global model (covering the whole Earth) and a +regional model (just covering a little bit of it) where the regional model +obtains its boundary condition from the global model.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/index.html b/nightly_8.4/html/user-guide/index.html new file mode 100644 index 00000000000..70e3b801be6 --- /dev/null +++ b/nightly_8.4/html/user-guide/index.html @@ -0,0 +1,280 @@ + + + + + + + User Guide — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

User Guide

+
+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/installing-workflows.html b/nightly_8.4/html/user-guide/installing-workflows.html new file mode 100644 index 00000000000..cde9ba9f320 --- /dev/null +++ b/nightly_8.4/html/user-guide/installing-workflows.html @@ -0,0 +1,648 @@ + + + + + + + Installing Workflows — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Installing Workflows

+

Cylc commands identify workflows via their names, which are relative path names +under the cylc-run directory, ~/cylc-run/ by default.

+

Workflows can be grouped together under sub-directories. E.g. there are three +workflows in the example below: nwp/oper/region1, nwp/oper/region2 and +nwp/test/region1.

+
$ cylc scan --state=all --name nwp --format=tree
+nwp
+├─oper
+│ ├─ region1
+│ └─ region2
+└─test
+   └─ region1
+
+
+

This chapter will demonstrate how to install a workflow from an arbitrary +location, called a source directory. +cylc install will create a new run directory in the cylc-run directory +for each installation of a workflow.

+ +
+

The Cylc Install Command

+

Workflows can be installed with the cylc install command, which creates +the run directory structure and some service files underneath it.

+
+

Note

+

It is possible to run a workflow without installation by writing it +directly in the run directory. +However, we recommend that you write your workflow in a source +directory and use cylc install to create a fresh run directory.

+
+
+
+

Using Cylc Install

+

cylc install accepts as its only argument either:

+
    +
  • a workflow source name (see Configurable Source Directories below) e.g. +foo/bar

  • +
  • a path to the source directory e.g. ./foo/bar or /path/to/foo/bar +(note that relative paths must begin with ./ to distinguish them from +workflow source names)

  • +
+

If no argument is supplied, the current working directory is used as the +source directory.

+
+

Note

+

To avoid confusion, cylc install does not permit any of the following +reserved directory names: .service, runN, flow.cylc, share, _cylc-install, suite.rc, work, log

+
+
+

Options

+

The table below illustrates several command line options that control naming +of run directories for installed workflows (the current working directory in +these examples is ~/cylc-src/my-flow):

+ + + + + + + + + + + + + + + + + + + + +

Command

Results in Installation in Directory

cylc install

~/cylc-run/my-flow/run1

cylc install --no-run-name

~/cylc-run/my-flow

cylc install --run-name=new-run

~/cylc-run/my-flow/new-run

cylc install --workflow-name=new-name

~/cylc-run/new-name/run1

+
+
+

Configurable Source Directories

+

You can configure a list of directories that cylc install SOURCE_NAME +and the GUI will search for source directories inside, using +global.cylc[install]source dirs. For example, if you have

+
# global.cylc
+[install]
+    source dirs = ~/cylc-src, ~/roses
+
+
+

then cylc install dogs/fido will search for a workflow source directory +~/cylc-src/dogs/fido, or, failing that, ~/roses/dogs/fido, and install +the first match (into ~/cylc-run/dogs/fido/run1).

+
+
+

Numbered Runs

+

By default, cylc install creates numbered run directories, i.e. +~/cylc-run/<workflow-name>/run<number>, provided the options +--run-name or --no-run-name are not used. The run number automatically +increments each time cylc install is run, and a symlink runN is +created/updated to point to the run.

+

Example: A typical run directory structure, after three executions of +cylc install will look as follows.

+
├── _cylc-install
+│   └── source -> /home/cylc-src/test-flow
+├── run1
+│   ├── flow.cylc
+│   └── log
+│       └── install
+│           └── <time-stamp>-install.log
+├── run2
+│   ├── flow.cylc
+│   └── log
+│       └── install
+│           └── <time-stamp>-install.log
+├── run3
+│   ├── flow.cylc
+│   └── log
+│       └── install
+│           └── <time-stamp>-install.log
+└── runN -> /home/cylc-run/test-flow/run3
+
+
+

The numbered runs option may be overridden, using either the --no-run-name +or the --run-name options.

+
+
+

Named Runs

+

As an alternative to numbered runs, it is possible to name the runs, using the +--run-name option. +In this case, the runN symlink will not be created. +This option cannot be used if numbered runs are already present. Likewise, +numbered runs cannot be used if named runs are already present.

+
+ +
+
+

The Cylc Install Process

+

There are two main parts of the cylc install process.

+
    +
  1. File Installation

  2. +
  3. Symlinking of Directories

  4. +
+
+

1. File Installation

+

Installation will involve copying the files found in the source directory into +a new run directory. If you wish to install files into an existing run +directory, use cylc reinstall, see Reinstalling a Workflow.

+
+

Excluding Items From Installation

+

By default, cylc install will exclude .git, .svn directories. +To configure excluded files and directories from the file installation, +create a .cylcignore file in your source directory, this supports +pattern matching.

+

The following example will detail how to install a workflow, including +configuring files to be excluded from the installation.

+
+
+

Example Installation

+

For example: +We will look at running the cylc install command inside the directory +~/cylc-src/test-flow with the following directory structure:

+
$ pwd
+/home/cylc-src/test-flow
+
+
+
$ tree -all
+├── .cylcignore
+├── dir1
+│   ├── another-file
+│   └── file
+├── dir2
+│   ├── another-file
+│   └── file
+├── file1
+├── file2
+├── file3
+├── flow.cylc
+├── textfile1.txt
+└── textfile2.txt
+
+
+

We wish to omit any files matching the pattern *.txt, the file +file1, the contents of dir1 and the contents of dir2 including the +directory itself.

+
$ cat .cylcignore
+*.txt
+file1
+dir1/*
+dir2
+
+
+

Now we are ready to install our workflow.

+
$ cylc install
+INSTALLED test-flow from home/cylc-src/test-flow -> home/cylc-run/test-flow/run1
+
+
+

Looking at the directory structure that has been created

+
$ tree -all home/cylc-run/test-flow/run1
+├── dir1
+├── file2
+├── file3
+├── flow.cylc
+├── log
+│   └── install
+│       └── <time-stamp>-install.log
+└── .service
+
+
+
+
+
+

2. Symlinking of Directories

+

If symlink directories are configured in the [[[localhost]]] section in +global.cylc[install][symlink dirs], +cylc install will create these symlinks and their target locations +(symlinks for remote install targets do not get created until +starting the workflow).

+ + +
+
+
+

Automatically Generated Directories and Files

+

Running cylc install will generate some extra files in your workflow run +directory.

+
    +
  • The service directory will be created in preparation for running the +workflow. This is needed to store essential files used by Cylc.

  • +
  • A _cylc-install directory containing a source symlink to the +source directory. +This is needed to enable Cylc to determine the original workflow source +for cylc reinstall.

  • +
  • A new install directory in the workflow’s log directory, with a +time-stamped install log file containing information about the installation.

  • +
+

Cylc plugins (such as Cylc Rose) may generate additional files.

+
+
+

Reinstalling a Workflow

+

To apply changes from your source directory to the installed run directory, +use cylc reinstall. Changes made will be recorded in the workflow log +directory.

+

For example:

+
$ cylc reinstall myflow/run1
+
+
+

Cylc will determine the source directory and update your workflow.

+

Returning to the example from above (see Example Installation).

+

The source directory, ~/cylc-src/test-flow has been altered as follows:

+
$ tree -all ~/cylc-src/test-flow
+├── .cylcignore
+├── dir1
+│   ├── another-file
+│   └── file
+├── dir2
+│   ├── another-file
+│   └── file
+├── dir3
+│   ├── another-file
+│   └── file
+├── file1
+├── file2
+├── file3
+├── flow.cylc
+├── textfile1.txt
+└── textfile2.txt
+
+
+
$ cat .cylcignore
+*.txt
+file1
+dir2
+
+
+

We wish to update our ~/cylc-run/test-flow/run1 with the directories dir1 +and dir3:

+
$ cylc reinstall test-flow/run1
+
+
+

The run directory now looks as follows:

+
$ tree -all home/cylc-run/test-flow/run1
+├── dir1
+│   ├── another-file
+│   └── file
+├── dir3
+│   ├── another-file
+│   └── file
+├── file2
+├── file3
+├── flow.cylc
+├── log
+│   └── install
+│       └── <time-stamp>-install.log
+│       └── <time-stamp>-reinstall.log
+└── .service
+
+
+
+

Note

+

If your workflow needs to create or install scripts or executables at runtime +and you don’t want Cylc to delete them on re-installation, you can use +bin and lib/python directories in the +workflow share directory.

+
+
+
+

Expected Errors

+

There are some occasions when installation is expected to fail:

+
    +
  • log, share, work or _cylc-install directories exist in the +source directory

  • +
  • Neither flow.cylc nor the deprecated suite.rc are found in +the source directory

  • +
  • Both flow.cylc and the deprecated suite.rc are found in +the source directory. Only one should be present.

  • +
  • The workflow name is an absolute path or invalid

    +

    Workflow names are validated by +cylc.flow.unicode_rules.WorkflowNameValidator.

    +
    +
    +class cylc.flow.unicode_rules.WorkflowNameValidator[source]
    +

    The rules for valid workflow names:

    +
      +
    • must be between 1 and 254 characters long

    • +
    • cannot start with: ., -, numbers

    • +
    • can only contain: alphanumeric, /, _, +, -, ., @

    • +
    +
    + +
  • +
  • The workflow name contains a directory name that is any of these reserved +filenames: .service, runN, flow.cylc, share, _cylc-install, suite.rc, work, log

  • +
  • The install would create nested install directories. Neither a new +installation in a subdirectory of an existing one, nor a directory containing +an existing installation are permitted. For example, having installed a +workflow in bar you would be unable to install one in foo +or foo/bar/baz.

    +
    foo
    +└── bar
    +    ├── _cylc-install
    +    ├── baz
    +    ├── run1
    +    └── runN
    +
    +
    +

    This means you cannot install using --no-run-name for a workflow that +has installed numbered/named runs, nor can you install numbered/named runs +for a workflow where --no-run-name was used.

    +
  • +
  • Trying to install a workflow into an already existing run directory. +cylc reinstall should be used for this, see +Reinstalling a Workflow.

  • +
  • The source directory path does not match the source directory path of a +previous installation. i.e. running cylc install in +~/cylc-src/my-flow, followed by running cylc install from +~/different/my-flow.

  • +
+
+
+

Compound Commands

+

Cylc provides compound commands which carry out multiple operations.

+

For example Cylc provides a command to validate, install and play a workflow.

+

Compound commands make common ways of working easier.

+
+

Tip

+

Use cylc command --help to get help for each compound command, +including a full list of available options.

+
+
+

cylc vip (Validate, Install and Play)

+

cylc vip /home/me/cylc-src/my-workflow is the same as running:

+
$ cylc validate /home/me/cylc-src/my-workflow
+$ cylc install /home/me/cylc-src/my-workflow
+INSTALLED my-workflow/run1 from /home/me/cylc-src/my-workflow
+$ cylc play my-workflow
+
+
+
+
+

cylc vr (Validate, Reinstall and Reload or Play)

+

cylc vr my-workflow is the same as running:

+
# Check that the changes you want to
+# make will be valid after installation:
+$ cylc validate my-workflow --against-source
+$ cylc reinstall my-workflow
+
+# If workflow is running:
+$ cylc reload my-workflow
+
+# If workflow is stopped:
+$ cylc play my-workflow
+
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/interventions/index.html b/nightly_8.4/html/user-guide/interventions/index.html new file mode 100644 index 00000000000..1c12a6f984d --- /dev/null +++ b/nightly_8.4/html/user-guide/interventions/index.html @@ -0,0 +1,597 @@ + + + + + + + Interventions — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Interventions

+

Sometimes things don’t go to plan!

+

So Cylc allows you to take manual control of your workflow whilst it’s running +allowing you to do things like edit a task’s configuration, re-run a section +of your graph or override task outputs.

+

This section of the documentation covers some of the common interventions you +might want to perform in various scenarios.

+

You can perform these interventions in multiple ways:

+
+ +
+

The Cylc web app (GUI) can be launched with the cylc gui command.

+

Some sites provide a central deployment for you where you log in via the +web browser rather than launching it yourself.

+
+ +
+

Cylc Tui is an interactive in-terminal application, like a minimal +version of the GUI. Start it with the cylc tui command.

+

Launch it with the cylc tui command.

+
+ +
+

The Cylc command line interface (CLI) can do everything the GUI can.

+

To see the full list of available commands run cylc help all.

+
+
+ +
+

Re-Run a Task

+
+
Example:
+

A task failed and I want to give it another try.

+
+
Solution:
+

Trigger the failed task.

+
+
+
+ +
+../../_images/re-run-a-task.gui.gif +
+ +
+../../_images/re-run-a-task.tui.gif +
+ +
+
$ cylc trigger <workflow>//<task>
+
+
+
+
+
+
+

Re-Run Multiple Tasks

+
+
Example:
+

I need to make changes to a task, then re-run it and everything downstream +of it.

+
+
Solution:
+

Edit the tasks configuration, +then trigger it in a new flow.

+
+
+
+ +
+../../_images/re-run-multiple-tasks.gui.gif +
+ +
+
$ cylc trigger --flow=new <workflow>//<cycle>/<task>
+
+
+
+
+
+
+

Re-Run All Failed Tasks

+
+
Example:
+

Multiple tasks failed due to factors external to the workflow. +I’ve fixed the problem, now I want them to run again.

+
+
Solution:
+

Trigger all failed tasks.

+
+
+
+

Note

+

You can use this intervention with other states too, e.g. “submit-failed”.

+
+
+ +
+../../_images/re-run-all-failed-tasks.gui.gif +
+ +
+
$ cylc trigger <workflow>:failed
+
+
+
+
+
+
+

Set Task Outputs

+
+
Example:
+

My task failed, I’ve gone and fixed the problem, now I want to tell Cylc +that the task succeeded.

+
+
Solution:
+

Set the “succeeded” output on the failed task.

+
+
+
+ +
+../../_images/set-task-outputs.gui.gif +

By default this sets the “succeeded” output, press the pencil icon next +to the trigger command to specify a different output.

+
+ +
+../../_images/set-task-outputs.tui.gif +

By default, this sets the “succeeded” output. Use cylc set --output +to specify a different output.

+
+ +
+
$ cylc set <workflow>//<task>
+
+
+

By default, this sets the “succeeded” output. Use the --output option +to specify a different output.

+
+
+

You can also set task prerequisites. +Should I set task outputs or prerequisites?

+
    +
  • If you set a task’s outputs, then tasks downstream of it may start to run.

  • +
  • If you set a task’s prerequisites, the task itself may start to run.

  • +
+
+
+

Set Task Prerequisites

+
+
Example:
+

A task is not running yet, because one or more of its +prerequisites are not satisfied (e.g. upstream tasks +have not run yet or have failed). I want it to ignore one or more of these +prerequisites.

+
+
Solution:
+

Set the task’s prerequisites as satisfied.

+
+
+
+

Note

+

If you want the task to run right away, then trigger it using the same +intervention as Re-Run a Task.

+
+
+ +
+../../_images/set-task-prerequisites.gui.gif +
+ +
+
$ cylc set \
+>   --pre <prereq-cycle>/<prereq-task>:<prereq-output> \
+>   <workflow>//<cycle><task>
+
+
+
+
+

You can also set task outputs. +Should I set task outputs or prerequisites?

+
    +
  • If you set a task’s outputs, then tasks downstream of it may start to run.

  • +
  • If you set a task’s prerequisites, the task itself may start to run.

  • +
+
+
+

Set a Switch Task

+
+
Example:
+

I have a branched workflow, I want to direct it to +take a particular path ahead of time:

+
start => switch
+
+# by default, the workflow follows the "normal" path
+switch:normal? => normal
+
+# but it can follow an alternate route if desired
+switch:alternate? => alternate
+
+normal | alternate => end
+
+
+
+
Solution:
+

Set “succeeded” as well as the desired output(s) on the task and use the +-wait option. Cylc will follow the desired path when it gets there.

+
+

Note

+

We set the “succeeded” output to prevent the task from being re-run when the +flow approaches it.

+
+
+
+
+ +
+../../_images/set-a-switch-task.gui.gif +
+ +
+
$ cylc set --wait --output=succeeded,alternate <workflow>
+
+
+
+
+
+
+

Edit a Task’s Configuration and Re-Run It

+
+
Example:
+

I’m developing a task and need to be able to quickly make changes and re-run +the task.

+
+
Solution:
+

Edit the task’s definition and trigger it.

+
+
+
+ +
+../../_images/edit-a-tasks-configuration.gui.gif +
+

Note

+

Any changes you make apply only to this one instance of the task, not +to any future instances.

+

To change future instances, either use “broadcast” or see +Edit The Workflow Configuration.

+
+
+ +
+
$ cylc broadcast <workflow> -p <cycle> -n <task> -s 'script=true'
+$ cylc trigger <workflow>//<cycle>/<task>
+
+
+
+
+
+

+
+
+
+

Edit The Workflow Configuration

+
+
Example:
+

I want to change the configuration of multiple tasks or add/remove tasks +without stopping the workflow or starting it from the beginning again.

+
+
Solution:
+

Edit the workflow configuration in the source directory, then +reinstall and reload the workflow.

+
+
+
+ +
+../../_images/edit-the-workflow-configuration.tui.gif +
+ +
+
$ vim ~/cylc-src/myworkflow  # edit the workflow configuration
+$ cylc vr myworkflow         # reinstall and reload the workflow
+
+
+
+
+
+

Note

+

For information on how graph changes (e.g. the adding or removing of tasks) +are applied, see +Restarting or Reloading after Graph Changes.

+
+
+
+

Orphan a “Stuck” Job Submission

+
+
Example:
+

I have a job which cannot be killed (e.g. the platform has gone down), I +want Cylc to forget about it.

+
+
Solution:
+

Set the “failed” output on the task.

+
+
+

Use the same intervention as Set Task Outputs, +but you will probably want to specify the “failed” output rather than +“succeeded”.

+
+
+

Terminate a Chain of Automatic Retries

+
+
Example:
+

I have a failed task which has been configured to automatically +retry, I want to cancel these retries because I know it can’t +succeed.

+
+
Solution:
+

Set the “failed” output on the task.

+
+
+

Use the same intervention as Set Task Outputs, +but specify the “failed” output rather than +“succeeded”.

+
+
+

Hold The Workflow And Trigger Tasks One By One

+
+
Example:
+

I want to hold back the workflow whilst I manually run one or more tasks +to fix a problem or test a task.

+
+
Solution:
+
    +
  • Hold all tasks after a specified cycle.

  • +
  • Trigger the task(s) you want to run.

  • +
  • When you’re done triggering, release the held tasks to allow the workflow +to continue.

  • +
+
+
+
+ +
+../../_images/set-and-release-hold-point.gif +
+ +
+
$ # hold all tasks after the cycle "2000"
+$ cylc hold --after=2000 <workflow>
+
+$ # trigger the task(s) you want to run
+$ cylc trigger <workflow>//<cycle>/<task>
+
+$ # release the "hold point" to allow the workflow to continue
+$ cylc release --all <workflow>
+
+
+
+
+
+

Note

+

The difference between the workflow “paused” state and the task “held” state:

+
+
Workflow Pause

When a workflow is paused, no new jobs will be submitted. +This gives you an opportunity to make changes to the workflow, however, if +you trigger tasks, they will not run until the workflow is resumed.

+
+
Task Hold

When a task is held, then it will not submit (if ready to +submit) until released.

+
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/introduction.html b/nightly_8.4/html/user-guide/introduction.html new file mode 100644 index 00000000000..fb8f2d260b5 --- /dev/null +++ b/nightly_8.4/html/user-guide/introduction.html @@ -0,0 +1,264 @@ + + + + + + + Introduction — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Introduction

+
+

What is a Workflow?

+
+

A workflow consists of an orchestrated and repeatable pattern of business +activity enabled by the systematic organization of resources into processes +that transform materials, provide services, or process information.

+

—Wikipedia

+
+
+

Related Tutorial

+

What is a Workflow?

+
+
+
+

What is Cylc?

+

Cylc (pronounced silk) is a workflow engine, a system that automatically +executes tasks according to schedules and dependencies.

+

In a Cylc workflow each step is an application: an executable command, script, +or program. Cylc runs each task as soon as it is appropriate to do so.

+
+

Related Tutorial

+

What is Cylc?

+
+
+
+

Cylc and Cycling Workflows

+

A cycling workflow is a repetitive process involving many interdependent +tasks. Cylc tasks wrap arbitrary applications: executable commands, +scripts, or programs. Example use cases include:

+
    +
  • Processing many similar datasets, through a pipeline or graph of tasks

  • +
  • Forecasting systems that generate new forecasts at regular intervals

  • +
  • Splitting a long model run and associated processing tasks into many smaller runs

  • +
  • Iterative tuning of model parameters by model, processing, and validation tasks

  • +
+

Cycling systems were traditionally managed by repeat-running the single-cycle +workflow, finishing each new cycle before starting the next. Sometimes, however, +it can be much more efficient to run multiple cycles at once. Even in real time +forecasting systems that normally have a gap between cycles waiting on new +data, this can greatly speed catch up from delays or downtime. But it can’t +be done if the workflow manager has a global loop that handles only one cycle +at a time and does not understand any intercycle dependence that may be present.

+
+

Important

+

Cylc handles inter- and intra-cycle dependence equally, and it unrolls the +cycle loop to create a single non-cycling workflow of repeating tasks, each +with its own individual cycle point.

+
+../_images/cycling.png +

This removes the artificial barrier between cycles. Cylc tasks can advance +constrained only by their individual dependencies, for maximum concurrency +across as well as within cycles. This allows fast catch-up from delays in +real time systems, and sustained high throughput off the clock.

+
+
+

How to Run User Guide Examples

+

Many Cylc concepts and features in this document are illustrated with minimal +snippets of workflow configuration. Most of these can be turned into a complete +workflow that you can actually run, with a few easy steps:

+
    +
  • Add scheduling section headings, if missing, above the graph

  • +
  • Use [scheduler]allow implicit tasks = True to automatically create dummy definitions +for each task

  • +
  • Configure the root task family to make the dummy jobs take a little time +to run, so the workflow doesn’t evolve too quickly

  • +
  • For cycling graphs, configure an initial cycle point to start at

  • +
+

For example, here is a small cycling workflow graph:

+
# Avoid caffeine withdrawal
+PT6H = "grind_beans => make_coffee => drink_coffee"
+
+
+

And here it is as a complete runnable workflow:

+
[scheduler]
+    allow implicit tasks = True
+[scheduling]
+    initial cycle point = now
+    [[graph]]
+        # Avoid caffeine withdrawal
+        PT6H = "grind_beans => make_coffee => drink_coffee"
+[runtime]
+    [[root]]
+        script = "sleep 10"
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/removing-workflows.html b/nightly_8.4/html/user-guide/removing-workflows.html new file mode 100644 index 00000000000..043c66f679f --- /dev/null +++ b/nightly_8.4/html/user-guide/removing-workflows.html @@ -0,0 +1,270 @@ + + + + + + + Removing Workflows — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Removing Workflows

+

To delete an installed workflow run directory, we recommend using +the cylc clean command. cylc clean takes care of deleting workflows +on the local filesystem and any remote install targets. +It follows any symlink directories specified in +global.cylc[install][symlink dirs] +(see A note on symlink directories below). You can also use cylc clean to +just delete certain files or subdirectories (see Cleaning specific subdirectories or files below).

+

If you’ve used rose suite-clean before, the functionality is similar, but +not identical.

+
+

Note

+

cylc clean only affects workflow run directories +(located in the cylc-run directory). It will not affect +workflow source directories.

+
+
+

Warning

+

cylc clean is intended for use on workflows installed with +cylc install. If you clean a workflow that was instead written +directly in the cylc-run directory and not backed up elsewhere, +it will be lost.

+
+

Simple example of using cylc clean:

+
$ cylc clean myflow/run1
+INFO - Removing directory: ~/cylc-run/myflow/run1
+
+
+
+

Cleaning on remote install targets

+

If any jobs in your workflow ran on a remote platform, Cylc will +automatically remove the workflow files on there in addition to the local +filesystem.

+
$ cylc clean remote-example
+INFO - Cleaning on install target: enterprise1701
+INFO - [enterprise1701]
+        INFO - Removing directory: /home/user/cylc-run/remote-example/run1
+INFO - Removing directory: ~/cylc-run/remote-example/run1
+
+
+
+

Note

+

This relies on determining which platforms were used from the workflow +database. If the platforms recorded in the database are out of date with +the global configuration, or if the database is missing altogether, you will +have to manually remove the files on remote install targets.

+
+

You can also clean on just the local filesystem using the --local option, +or just the remote install target using the --remote option.

+
+
+

Cleaning specific subdirectories or files

+

You can clean specific subdirectories or files inside a run directory using +the --rm option (we refer to this as a targeted clean). +For example, to remove the log and work directories:

+
$ cylc clean myflow --rm log --rm work
+
+
+

Colons can be used to delimit the items to clean, so the following is +equivalent:

+
$ cylc clean myflow --rm log:work
+
+
+

You can also use globs. E.g., to remove all job logs for cycle points +beginning with 2020:

+
$ cylc clean myflow --rm 'log/job/2020*'
+
+
+
+

Note

+

Make sure to place glob patterns in quotes.

+
+
+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/running-workflows/authentication-files.html b/nightly_8.4/html/user-guide/running-workflows/authentication-files.html new file mode 100644 index 00000000000..fe784e90377 --- /dev/null +++ b/nightly_8.4/html/user-guide/running-workflows/authentication-files.html @@ -0,0 +1,225 @@ + + + + + + + Client-Server Interaction — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Client-Server Interaction

+

Schedulers listen on dedicated network ports for +TCP communications from Cylc clients (jobs and user-invoked commands).

+

Use cylc scan to see which workflows are listening on which ports on +scanned hosts.

+

Cylc generates public-private key pairs on the workflow server and job hosts +which are used for authentication.

+
+
+

Authentication Files

+

Cylc uses CurveZMQ to ensure that +any data, sent between the scheduler and the client, +remains protected during transmission. Public keys are used to encrypt the +data, private keys for decryption.

+

Authentication files will be created in your +$HOME/cylc-run/<workflow-id>/.service/ directory at start-up. You can +expect to find one client public key per file system for remote jobs.

+

On the workflow host, the directory structure should contain:

+
~/cylc-run/workflow_x
+`-- .service
+    |-- client_public_keys
+    |   |-- client_localhost.key
+    |   `-- <any further client keys>
+    |-- client.key_secret
+    |-- server.key
+    `-- server.key_secret
+
+
+

On the remote job host, the directory structure should contain:

+
~/cylc-run/workflow_x
+`-- .service
+    |-- client.key
+    |-- client.key_secret
+    `-- server.key
+
+
+

Keys are removed as soon as they are no longer required.

+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/running-workflows/dynamic-behaviour.html b/nightly_8.4/html/user-guide/running-workflows/dynamic-behaviour.html new file mode 100644 index 00000000000..92b50afb1a4 --- /dev/null +++ b/nightly_8.4/html/user-guide/running-workflows/dynamic-behaviour.html @@ -0,0 +1,201 @@ + + + + + + + Cylc Broadcast — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Cylc Broadcast

+

The cylc broadcast command overrides task [runtime] +settings in a running scheduler. You can think of it as communicating +new configuration settings (including information via environment variables) to +selected upcoming tasks via the scheduler.

+

See cylc broadcast --help for detailed information.

+

Broadcast settings targeting a specific cycle point expire as the workflow +moves on. Otherwise they persist for lifetime of the run, and across restarts, +unless cleared with another invocation of the command.

+
+

See also

+

Broadcast Tutorial

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/running-workflows/handling-job-preemption.html b/nightly_8.4/html/user-guide/running-workflows/handling-job-preemption.html new file mode 100644 index 00000000000..195d27da882 --- /dev/null +++ b/nightly_8.4/html/user-guide/running-workflows/handling-job-preemption.html @@ -0,0 +1,203 @@ + + + + + + + Handling Job Preemption — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Handling Job Preemption

+

Some HPC facilities allow job preemption: the resource manager can kill +or suspend running low priority jobs in order to make way for high +priority jobs. The preempted jobs may then be automatically restarted +by the resource manager, from the same point (if suspended) or requeued +to run again from the start (if killed).

+

Suspended jobs will poll as still running (their job status file says they +started running, and they still appear in the resource manager queue). +Loadleveler jobs that are preempted by kill-and-requeue (“job vacation”) are +automatically returned to the submitted state by Cylc. This is possible +because Loadleveler sends the SIGUSR1 signal before SIGKILL for preemption. +Other job runners just send SIGTERM before SIGKILL as normal, so Cylc +cannot distinguish a preemption job kill from a normal job kill. After this the +job will poll as failed (correctly, because it was killed, and the job status +file records that).

+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/running-workflows/index.html b/nightly_8.4/html/user-guide/running-workflows/index.html new file mode 100644 index 00000000000..2fd00529c9b --- /dev/null +++ b/nightly_8.4/html/user-guide/running-workflows/index.html @@ -0,0 +1,243 @@ + + + + + + + Running Workflows — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/running-workflows/reflow.html b/nightly_8.4/html/user-guide/running-workflows/reflow.html new file mode 100644 index 00000000000..ff61f6ce51d --- /dev/null +++ b/nightly_8.4/html/user-guide/running-workflows/reflow.html @@ -0,0 +1,369 @@ + + + + + + + Concurrent Flows — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Concurrent Flows

+
+

Added in version 8.0.0.

+
+

In Cylc, a flow is a single self-consistent run through the workflow +graph from some initial task(s).

+

As a flow advances, upcoming tasks run only if they have not already run in +the same flow.

+

At start-up the scheduler automatically triggers the first flow from +the start of the graph.

+

By default, manually triggered tasks “belong to” the existing flow(s), but you +can also choose to start new flows by triggering tasks anywhere in the graph.

+
+

Note

+

A flow does not have to be contiguous in the graph because different graph +branches can evolve at different rates, and tasks can be manually triggered +anywhere in the graph.

+
+

See below for uses, and an +example, of concurrent flows.

+
+

Note

+

Flows merge where (and if) tasks collide in the n=0 +active window. Downstream of a merge, tasks are considered to belong +to all of their constituent flows.

+
+
+

Flow Numbers

+

Flows are identified by numbers passed down from parent task to child task in +the graph.

+

Flow number 1 is triggered automatically by cylc play at scheduler +start-up. The next flow started by manual triggering +gets the number 2, then 3, and so on.

+

Tasks can carry multiple flow numbers as a result of flow +merging.

+
+

Note

+

Flow numbers are not yet exposed in the UI, but they are logged with task +events in the scheduler log.

+
+
+
+

Triggering & Flows

+

By default, manual triggering (with cylc trigger or the UI) starts a new +front of activity in current flows. +But it can also start new flows and trigger flow-independent single tasks.

+

In the diagrams below, the grey tasks run in the original flow (1), and the +blue ones run as a result of a manual triggering event. They may be triggered +as part of flow 1, or as a new flow 2, or with no flow number.

+
+
Triggering in Current Flows

cylc trigger [--wait] ID

+

This is the default action. The triggered task gets all current active flow +numbers. Subsequently, each of those flows will consider the task to have +run already.

+

Ahead of active flows this starts a new front of activity for the +existing flows, which by default can continue on without waiting for them to +catch up:

+../../_images/same-flow-n.png +

With --wait, action downstream of the triggered task is delayed until +the first flow catches up:

+../../_images/same-flow-wait-n.png +

Behind active flows the triggered task will run, but nothing more will +happen if any of the original flows already passed by there:

+../../_images/same-flow-behind.png +
+
Triggering in Specific Flows

cylc trigger --flow=1,2 ID

+

This triggers the task with flow numbers 1 and 2.

+

The result is like the default above, except that tasks in the new front +belong only to the specified flow(s), regardless of which flows are +active at triggering time.

+
+
Triggering a New Flow

cylc trigger --flow=new ID

+

This triggers the task with a new, incremented flow number.

+

The new flow will re-run tasks that already ran in previous flows:

+../../_images/new-flow-n.png +
+
Triggering a Flow-Independent Single Task

cylc trigger --flow=none ID

+

This triggers a task with no flow numbers.

+

It will not spawn children, and other flows that come by will re-run it.

+../../_images/no-flow-n.png +
+
Triggering with No Active Flows

cylc trigger [--wait] ID

+

By default, triggered tasks will be given the flow numbers of the most +recent active task. This can happen, for instance, if you restart a +completed workflow and then trigger a task in it. The result will be the +same as if you had triggered the task just before the workflow completed.

+
+
Special Case: Triggering n=0 Tasks

Tasks in the n=0 window are active tasks. +Their flow membership is already determined - that of +the parent tasks that spawned them.

+
    +
  • Triggering a task with a submitted or running job has no effect +(it is already triggered).

  • +
  • Triggering other n=0 tasks, including tasks with +incomplete outputs queues them to run in +the flow that they already belong to.

  • +
+
+
+
+
+

Flow Merging in n=0

+

If a task spawning into the n=0 window finds another instance +of itself (same task ID) already there, the two will merge and carry both +(sets of) flow numbers forward. Downstream tasks will belong to both flows.

+

Flow merging is necessary because active task IDs +must be unique.

+

If the original task instance has a final status (and has been retained +in the n=0 window with +incomplete outputs) the merged task will be reset to +run again without manual intervention.

+
+
+

Stopping Flows

+

By default, cylc stop halts the workflow and shuts the scheduler down.

+

It can also stop specific flows: cylc stop --flow=N removes the flow number +N from active tasks. Tasks that have no flow +numbers left as a result do not spawn children at all. If there are no active +flows left, the scheduler shuts down.

+
+
+

Some Use Cases

+
+
Running Tasks Ahead of Time

To run a task within the existing flow(s) even though its prerequisites are +not yet satisfied, just trigger it. Use --wait if you don’t want the new +flow front to continue immediately. Triggered task(s) will not re-run when +the main front catches up.

+
+
Regenerating Outputs Behind a Flow

To re-run a sub-graph (e.g. because the original run was affected by a +corrupt file), just trigger the task(s) at the top of the sub-graph with +--flow=new.

+

You may need to manually stop the new flow if it leads into the main trunk +of the graph, and you do not want it to carry on indefinitely.

+
+
Rewinding a Workflow

To rewind the workflow to an earlier point, perhaps to regenerate data and/or +allow the workflow to evolve a new path into the future, trigger a new +flow at the right place and then stop the original flow.

+
+
Test-running Tasks in a Live Workflow

You can trigger individual tasks as many times as you like with +--flow=none, without affecting the workflow. The task submit +number will increment each time.

+
+
Processing Flow-Specific Data?

Flow numbers are passed to job environments, so it is +possible for tasks to process flow-specific data. Every task would have to +be capable of processing multiple datasets at once, however, in case of +flow merging. Generally, you should use cycling +for this kind of use case.

+
+
+
+
+

Example: Rerun a Sub-Graph

+

The following cycling workflow runs a task called model in +every cycle, followed by a postprocessing task, two product-generating tasks, +and finally a task that publishes results for the cycle point:

+
[scheduling]
+    cycling mode = integer
+    initial cycle point = 1
+    [[graph]]
+        P1 = model[-P1] => model => post => prod1 & prod2 => publish
+
+
+

Let’s say the workflow has run to cycle 8, but we have just noticed that +a corrupted ancillary file resulted in bad products at cycle 5.

+

To rectify this we could fix the corrupted file and trigger a new flow at +5/post:

+
cylc trigger --flow=new <workflow_id>//5/post
+
+
+

The new flow will regenerate and republish cycle 5 products before naturally +coming to a halt, because the triggered tasks do not feed into the next cycle.

+

Meanwhile, the original flow will carry on unaffected, from cycle point 8.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/running-workflows/retrying-tasks.html b/nightly_8.4/html/user-guide/running-workflows/retrying-tasks.html new file mode 100644 index 00000000000..725dc452575 --- /dev/null +++ b/nightly_8.4/html/user-guide/running-workflows/retrying-tasks.html @@ -0,0 +1,230 @@ + + + + + + + Retrying Tasks — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Retrying Tasks

+
+

Changed in version 8.0.0.

+
+

Tasks that fail but are configured to retry return to the waiting +state, with a new clock trigger to handle the configured retry delay.

+
+

Note

+

A task that is waiting on a retry will already have one or more failed jobs +associated with it.

+
+
+

Note

+

Tasks only enter the submit-failed state if job submission fails with no +retries left. Otherwise they return to the waiting state, to wait on the +next try.

+

Tasks only enter the failed state if job execution fails with no retries +left. Otherwise they return to the waiting state, to wait on the next try.

+
+
+

Aborting a Retry Sequence

+

To prevent a waiting task from retrying, remove it from the scheduler’s +active window. For a task 3/foo in workflow brew:

+
$ cylc remove brew//3/foo
+
+
+

If you kill a running task that has more retries configured, it goes to the +held state so you can decide whether to release it and continue the retry +sequence, or remove it.

+
$ cylc kill brew//3/foo     # 3/foo goes to held state post kill
+$ cylc release brew//3/foo  # release to continue retrying...
+$ cylc remove brew//3/foo   # ... OR remove the task to stop retries
+
+
+

If you want trigger downstream tasks despite 3/foo being removed before it +could succeed, use cylc set to artificially mark its succeeded +output as complete (and with the --flow option, to make the flow +continue on from there).

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/running-workflows/scheduler-log-files.html b/nightly_8.4/html/user-guide/running-workflows/scheduler-log-files.html new file mode 100644 index 00000000000..6b599652358 --- /dev/null +++ b/nightly_8.4/html/user-guide/running-workflows/scheduler-log-files.html @@ -0,0 +1,245 @@ + + + + + + + Scheduler Logs — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Scheduler Logs

+

Each workflow maintains its own log of time-stamped events in the +workflow log directory ($HOME/cylc-run/<workflow-id>/log/scheduler/).

+

The information logged here includes:

+
    +
  • Event timestamps, at the start of each line

  • +
  • Workflow server host, port and process ID

  • +
  • Workflow initial and final cycle points

  • +
  • Workflow (re)start number (1 for the first play, 2 or more for restarts)

  • +
  • Task events (task started, succeeded, failed, etc.)

  • +
  • Workflow stalled warnings.

  • +
  • Client commands (e.g. cylc hold)

  • +
  • Job IDs.

  • +
  • Information relating to the remote file installation is contained in a +separate log file, which can be found in +$HOME/cylc-run/<workflow-id>/log/remote-install/.

  • +
+
+

Note

+

Workflow log files are primarily intended for human eyes. If you need +to have an external system to monitor workflow events automatically, use:

+ +

Rather than parse the log files.

+
+
+

Cylc Message

+

The Scheduler Log also records messages sent by cylc message allowing you +to add custom messages to this log.

+

For example, if your task contained the following code:

+
cylc message -- "ERROR:some_function failed."
+
+
+

Your log should produce output similar to:

+
ERROR - [21491012T0410Z/mytask running job:01 flows:1] (received)some_function failed ERROR at 2023-04-14T11:36:35+01:00
+
+
+

Severity levels are the same as those used by +Python’s logger:

+
    +
  • CRITICAL

  • +
  • ERROR

  • +
  • WARNING

  • +
  • INFO

  • +
  • DEBUG

  • +
+

Messages logged at “DEBUG” will only appear in the scheduler log if the +workflow is played with cylc play --debug.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/running-workflows/scheduler-start-up.html b/nightly_8.4/html/user-guide/running-workflows/scheduler-start-up.html new file mode 100644 index 00000000000..b8155ee0d73 --- /dev/null +++ b/nightly_8.4/html/user-guide/running-workflows/scheduler-start-up.html @@ -0,0 +1,441 @@ + + + + + + + Start, Restart, Reload — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Start, Restart, Reload

+

The cylc play command starts a new instance of the Cylc scheduler program +to manage a workflow, for the duration of the run. It also resumes paused +workflows.

+

There are several ways to start a workflow that is not running:

+
    +
  • cylc play from the initial cycle point

    +
      +
    • This is the default for a workflow that has not run yet

    • +
    • The initial cycle point is taken from flow.cylc or the command line

    • +
    • Dependence on earlier tasks is ignored, for convenience

    • +
    • (In Cylc 7, this was called a cold start)

    • +
    +
  • +
  • cylc play --start-cycle-point=POINT from a later start cycle point

    +
      +
    • This is an option for a workflow that has not run yet

    • +
    • The start point must be given on the command line

    • +
    • Dependence on earlier tasks is ignored, for convenience

    • +
    • The initial cycle point value defined in flow.cylc is preserved

    • +
    • (In Cylc 7, this was called a warm start)

    • +
    +
  • +
  • cylc play --start-task=TASK-ID from any task(s) in the graph

    +
      +
    • This is an option for a workflow that has not run yet

    • +
    • The start task(s) must be given on the command line

    • +
    • The flow will follow the graph onward from the start task(s)

    • +
    • (In Cylc 7, this was not possible)

    • +
    • (This makes Cylc 7 restart-from-checkpoint obsolete)

    • +
    +
  • +
  • cylc play to restart from previous state

    +
      +
    • This is automatic for a workflow that previously ran

    • +
    • The scheduler will carry on from exactly where it got to before

    • +
    • At start-up, it will automatically find out what happened to any active +tasks that were orphaned during shutdown

    • +
    • Failed tasks are not automatically resubmitted at restart, in case the +underlying problem has not been addressed

    • +
    • (In Cylc 7, this used the now-obsolete restart command)

    • +
    +
  • +
+
+

Note

+

If a workflow gets stopped or killed it can be restarted, but to avoid +corrupting an existing run directory it cannot be started again from scratch +(unless you delete certain files from the run directory). To start from +scratch again, install a new copy of the workflow to a new run directory.

+
+
+

See also

+ +
+
+

Start and Stop vs Initial and Final Cycle Points

+

All workflows have an initial cycle point and some may have a +final cycle point. These define extent of the graph of tasks that Cylc +can schedule to run.

+

Start and stop cycle points, if used, define a sub-section of the graph that +the scheduler actually does run. For example:

+
[scheduling]
+    cycling mode = integer
+    initial cycle point = 1
+    final cycle point = 5
+    [[graph]]
+        # every cycle: 1, 2, 3, 4, 5
+        P1 = foo
+        # every other cycle: 1, 3, 5
+        P2 = bar
+
+
+

With a start cycle point of 2 and a stop cycle point of +4, the task foo would run at cycles 2, 3 & 4 and the task bar +would only run at cycle 3.

+../../_images/initial-start-stop-final-cp.svg
+
+

Restarts and the Initial, Final, Start and Stop Cycle Points

+

When a workflow is restarted or reloaded, any changes to +[scheduling]final cycle point or +[scheduling]stop after cycle point are normally picked up by Cylc.

+

However, this is not the case if you used the --final-cycle-point or +--stop-cycle-point options in a prior run. If you use either of these +options, the values you specify are stored in the workflow database, so the +original values will be used if you restart the workflow later on. +You can override these original values using the options again, and the new +value will persist over restarts. Or, you can pick up the workflow config +values by passing reload to the options +(e.g. --final-cycle-point=reload); this will remove the stored value from +the database so future restarts will go back to picking up any changes +to the config.

+
+

Note

+

If the workflow reached the final cycle point and shut down, it is finished +and cannot be restarted; the --final-cycle-point option will have +no effect.

+
+

The --initial-cycle-point and --start-cycle-point options cannot be used +in a restart; workflows always start from the cycle point where they +previously stopped.

+
+
+

Reloading the Workflow Configuration at Runtime

+

The cylc reload command tells the target scheduler to reload its +workflow configuration at run time. This is an alternative to shutting a +workflow down and restarting it after making changes.

+
+

Note

+

If writing your workflows in a source directory, then be sure to +reinstall your changes to the +run directory before doing a reload.

+
+

If you make an error in the flow.cylc file before a reload, the workflow +log will report an error and the reload will have no effect.

+

Note, Remote Initialization will be redone for each job platform, when the first +job is submitted there after a reload.

+
+
+

Restarting or Reloading after Graph Changes

+

If dependencies have changed, tasks that were already active will spawn +children according to their original outputs. Subsequent instances will have +the new settings.

+

If tasks were removed from the graph, any active instances will be left to +finish, but they will not spawn children. They can be removed manually if +necessary, with cylc remove.

+

If new tasks were added to the graph, instances will be spawned automatically +as upstream tasks complete the outputs that they depend on. If they have no +parents to do that, you can trigger the first ones manually with cylc trigger.

+
+
+

Remote Initialization

+

For workflows that run on remote platforms, i.e. using a host other than +localhost, Cylc performs an initialization process. This involves transferring +files and directories required to run jobs, including authentication keys +(see Authentication Files for more information).

+

The default directories included in the remote install are:

+
+
ana/

For workflow-level rose_ana analysis modules.

+
+
app/

For Application Configuration.

+
+
bin/

For scripts and executables to be run by tasks.

+
+
etc/

For miscellaneous resources.

+
+
lib/

For shared libraries e.g. Custom Jinja2 Filters, Tests and Globals.

+
+
+

These will be transferred from the workflow run directory on the +scheduler host to the remote host. +In addition, custom file and directories configured in +flow.cylc[scheduler]install will be included in the transfer.

+

This remote initialization process also creates symlinks on the remote +platform, if these are configured using +global.cylc[install][symlink dirs]. This provides a +way to manage disk space.

+

A log file is created on the scheduler to report information relating to the +remote file installation process. There will be a separate log created per install +target. These can be found in $HOME/cylc-run/<workflow-id>/log/remote-install/.

+
+

Installing Custom Files At Start-up

+

Cylc supports adding custom directories and files to the file installation.

+

If, for example, you wished to install directories dir1, dir2, and +files file1, file2, add the following configuration to your +flow.cylc, under the section +[scheduler]install. +To mark an item as a directory, add a trailing slash.

+
[scheduler]
+    install = dir1/, dir2/, file1, file2
+
+
+
+

Note

+

Ensure files and directories to be installed are located in the top +level of your workflow.

+
+

Install tasks are preferred for time-consuming installations because +they don’t slow the workflow start-up process, they can be monitored, +they can run directly on target platforms, and you can rerun them later without +restarting the workflow.

+
+

Note

+

Files configured for installation to remote job platforms can be reinstalled by doing a reload. The reinstallation is done when the first job submits to a platform after the reload.

+
+
+
+

Troubleshooting

+

There are certain scenarios where remote initialization may fail. Cylc will return +a REMOTE INIT FAILED message.

+
+

Timeout

+

Remote initialization has a timeout set at 10 minutes, after which remote +initialization will fail. If you have particularly large files files to +transfer, which you expect to exceed the 10 minute timeout, consider using an +install task in your workflow.

+
+
+

Misconfiguration

+

Platforms must be correctly configured to ensure authentication keys, which are +responsible for secure communication between the scheduler and the +platform, are correctly in place. +Sites can configure these platforms, insuring they match up with the correct +install target. Cylc uses install targets as a way of recognising which platforms +share the same file system. For more information, see What Are Install Targets?.

+
+
+
+
+

Files created at workflow start

+
+

Configuration Logs

+

A folder log/config is created where the workflow configuration is +recorded, with all templating expanded:

+
    +
  • flow-processed.cylc - A record of the current workflow configuration +with templating expanded, but without being fully parsed: Duplicate sections +will not be merged.

  • +
  • <datetime-stamp>-<start/restart/reload> - A record of the config at +the time a workflow was started, restarted or reloaded, parsed by Cylc: +Duplicate sections will be merged.

  • +
+
+

Note

+

These are particularly useful files to look at if the workflow +configuration contains many template variables, to see how they are +filled in.

+
+
+
+

The Workflow Contact File

+

The scheduler writes a contact file at +$HOME/cylc-run/<workflow-name>/.service/contact that records workflow host, +user, port number, process ID, Cylc version, and other information. Client +commands read this file to find the scheduler.

+

The contact file gets removed automatically at shutdown (assuming the +scheduler shuts down cleanly).

+
+
+

Authentication Files

+

See Authentication Files.

+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/running-workflows/simulation-modes.html b/nightly_8.4/html/user-guide/running-workflows/simulation-modes.html new file mode 100644 index 00000000000..7804a7abba9 --- /dev/null +++ b/nightly_8.4/html/user-guide/running-workflows/simulation-modes.html @@ -0,0 +1,272 @@ + + + + + + + Simulation Modes — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Simulation Modes

+

Cylc can run a workflow without running the real jobs, which may be +long-running and resource-hungry.

+

Dummy mode replaces real jobs with background sleep jobs on the +scheduler host. This avoids job runner directives that request compute +resources for real workflow tasks, and it allows any workflow configuration to +be run locally in dummy mode.

+
$ cylc play --mode=dummy <workflow-id>  # real dummy jobs
+
+
+
+

Note

+

All configured task script items including init-script are ignored +in dummy mode. If your init-script is required to run even local dummy +jobs, the relevant environment setup should be done elsewhere.

+
+

Simulation mode does not run real jobs at all, and does not generate job +log files.

+
$ cylc play --mode=simulation <workflow-id>  # no real jobs
+
+
+
+

Simulated Run Length

+

The default dummy or simulated job run length is 10 seconds. It can be +changed with [runtime][<namespace>][simulation]default run length.

+

If [runtime][<namespace>]execution time limit and +[runtime][<namespace>][simulation]speedup factor are both set, +run length is computed by dividing the time limit by the speedup factor.

+
+
+

Simulated Failure

+

Tasks always complete custom outputs, by default they succeed.

+
+

Warning

+

In simulation mode a succeeded output may not imply that +submitted and/or started outputs are generated - so you will not +be able to test graph pathways such as task:started => do_something.

+
+

You can set some or all instances of a task to fail using +[runtime][<namespace>][simulation]fail cycle points. +fail cycle points takes either a list of cycle point strings or “all”.

+

Tasks set to fail will succeed on their second or following simulated +submission. If you want all submissions to fail, set +[runtime][<namespace>][simulation]fail try 1 only=False.

+

For example, to simulate a task you know to be flaky on the half +hour but not on the hour:

+
[[get_observations]]
+   execution retry delays = PT30S
+   [[[simulation]]]
+      fail cycle points = 2022-01-01T00:30Z,  2022-01-01T01:30Z
+
+
+

In another case you might not expect the retry to work, and want to test +whether your failure handling works correctly:

+
[[get_data]]
+    execution retry delays = PT30S
+    [[[simulation]]]
+       fail try 1 only = false
+       fail cycle points = 2022-01-01T03:00Z
+
+
+
+
+

Limitations

+

Dummy tasks run locally, so dummy mode does not test communication with remote +job platforms. However, it is easy to write a live-mode test workflow with +simple sleep 10 tasks that submit to a remote platform.

+

Alternate path branching is difficult to simulate effectively. You can +configure certain tasks to fail via +[runtime][<namespace>][simulation], but all branches based +on mutually exclusive custom outputs will run because all custom outputs get +artificially completed in dummy mode and in simulation mode.

+
+

Note

+

Run mode is recorded in the workflow run database. Cylc will not let you +restart a dummy mode workflow in live mode, or vice versa. Instead, +install a new instance of the workflow and run it from scratch in the new mode.

+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/running-workflows/tasks-jobs-ui.html b/nightly_8.4/html/user-guide/running-workflows/tasks-jobs-ui.html new file mode 100644 index 00000000000..57e63e3bd29 --- /dev/null +++ b/nightly_8.4/html/user-guide/running-workflows/tasks-jobs-ui.html @@ -0,0 +1,344 @@ + + + + + + + Tasks in the GUI/Tui — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Tasks in the GUI/Tui

+
+

Task & Job States

+

Tasks are a workflow abstraction; they represent future and past jobs as +well as current active jobs. In the Cylc UI, task states have monochromatic +icons like this: task-running.

+

Jobs represent real job scripts submitted to run +on a job platform. In the Cylc UI, job states have coloured icons like +this: job-running.

+

A single task can have multiple jobs, by automatic retry or manual triggering.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

State

Task Icon

Job Icon

Description

waiting

task-waiting

waiting on prerequisites

preparing

task-preparing

job being prepared for submission

submitted

task-submitted

job-submitted

job submitted

running

task-running

job-running

job running

succeeded

task-succeeded

job-succeeded

job succeeded

failed

task-failed

job-failed

job failed

submit-failed

task-submit-failed

job-submit-failed

job submission failed

expired

task-expired

will not submit job (too far behind)

+

The running task icon contains a clock face which shows the time elapsed +as a proportion of the average runtime.

+../../_images/task-running-0.png +../../_images/task-running-25.png +../../_images/task-running-50.png +../../_images/task-running-75.png +../../_images/task-running-100.png +
+

+
+
+

+
+
+
+

Task Modifiers

+

Tasks are run as soon as their dependencies are satisfied, however, there are +some other conditions which can prevent tasks from being run. These are +given “modifier” icons which appear to the top-left of the task icon:

+ ++++ + + + + + + + + + + + +
../../_images/task-isHeld.png +

Held: Task has been manually held back from +running.

../../_images/task-isRunahead.png +

Runahead: Task is held back by the runahead limit.

../../_images/task-isQueued.png +

Queued: Task has been held back by an internal queue.

+
+
+

The “n” Window

+
+

Changed in version 8.0.0.

+
+

Cylc workflow graphs can be very large, even infinite for +cycling workflows with no final cycle point.

+

Consequently the GUI often can’t display “all of the tasks” at once. Instead +it displays all active tasks (e.g. running tasks) +as well as any tasks which are a configurable number of tasks away from +them in the task dependency graph.

+../../_images/n-window.png +
+
n=0:

The n=0 window contains active tasks. An active +task is a task which is near ready to run, in the process of running, or +which requires user intervention (see the glossary +for a more detailed description).

+
+
n=1:

The n=1 window contains all “active tasks” as well as any tasks one +“edge” out from them, i.e. their dependencies (the tasks that come immediately +before them in the graph) and their descendants (the tasks that come +immediately after them in the graph).

+
+
n=2:

The n=2 window contains all “active tasks” as well as any tasks two +edges out from them, and so on.

+
+
+

This animation shows how the n-window advances as a workflow runs, tasks are +colour coded according to their n-window value with the colours changing from +n=0 (blue) to n=8 (pink):

+../../_images/n-window.gif +
+

+
+

By default the GUI/Tui displays the n=1 window. You can change this using +the “Set Graph Window Extent” command which is currently only available in the +GUI.

+
+

Note

+

The “graph window extent” is a property of the workflow not a property of +the GUI so persists between sessions. Better visibility and easier control +over the n-window are planned in future releases of Cylc.

+
+
+

Warning

+

High “graph window extent” values can cause a Cylc scheduler and the GUI +to run slowly.

+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/running-workflows/tracking-task-state.html b/nightly_8.4/html/user-guide/running-workflows/tracking-task-state.html new file mode 100644 index 00000000000..162043b9c9d --- /dev/null +++ b/nightly_8.4/html/user-guide/running-workflows/tracking-task-state.html @@ -0,0 +1,291 @@ + + + + + + + Tracking Job Status — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Tracking Job Status

+

Cylc supports three ways of tracking task state on job hosts:

+
    +
  • task-to-scheduler messaging via TCP (using ZMQ protocol)

  • +
  • task-to-scheduler messaging via non-interactive SSH to the workflow host, then +local TCP.

  • +
  • regular polling by the scheduler

  • +
+

These can be configured per platform using +global.cylc[platforms][<platform name>]communication method.

+

If your site prohibits TCP and SSH back from job hosts to workflow hosts, +before resorting to the polling method you should consider installing dedicated +Cylc servers or VMs inside the HPC trust zone (where TCP and SSH should be +allowed).

+

It is possible to run Cylc schedulers on HPC login nodes, +but be aware of scheduler resource requirements (which depend on workflow size +and run duration).

+

Port forwarding could potentially provide another solution, but the idea has +been rejected at this stage. Organisations often disable port forwarding for +security reasons.

+
+

Note

+

Use Cylc 8 platform configuration via +flow.cylc[runtime][<namespace>]platform, not the +deprecated host setting, to ensure the intended task communication +method is applied.

+
+
+

TCP Task Messaging

+

Cylc job scripts automatically invoke cylc message to +report progress back to the scheduler when they begin executing, at +normal exit (success) and abnormal exit (failure).

+

By default job status messaging goes by an authenticated TCP connection to the +scheduler, using the ZMQ protocol. This is the preferred task +communications method because it is efficient and direct.

+

Schedulers automatically install workflow contact information and credentials on job hosts.

+
+
+

SSH Task Communication

+

Cylc can be configured to re-invoke task messaging commands on the workflow +host via non-interactive SSH (from job platform to workflow host).

+

User-invoked client commands also support this communication method, when +global.cylc[platforms][<platform name>]communication method is +configured to ssh.

+

This is less efficient than direct ZMQ protocol messaging, but it may be useful at +sites where the ZMQ ports are blocked but non-interactive SSH is allowed.

+
+

Warning

+

Ensure SSH keys are in place for the remote task platform(s) before enabling +this feature. Failure to do so, will result in Host key verification +failed errors.

+
+
+
+

Polling to Track Job Status

+

Schedulers can actively poll jobs at configured intervals, via +non-interactive SSH to the job platform.

+

This is the least efficient communication method because task status updates +are delayed by up to the polling interval. However, it may be needed at sites +that do not allow TCP or non-interactive SSH from job host to workflow host.

+

Be careful to avoid spamming task hosts with polling operations. Each poll +opens (and then closes) a new SSH connection.

+

Polling intervals are configured by +:cylc:conf: +global.cylc[platforms][<platform name>]submission polling intervals +and +:cylc:conf: +global.cylc[platforms][<platform name>]execution polling intervals.

+

A common use case is to poll:

+
    +
  • frequently at first, to check that a job has started running properly;

  • +
  • frequently near the expected end of its run time, to get a timely task finished update;

  • +
  • infrequently in the intervening period.

  • +
+

Configured intervals are used in sequence until +the last value, which is used repeatedly until the job is finished:

+
+
global.cylc
+
[platforms]
+    [[my_platform]]
+        # poll every minute in the 'submitted' state:
+        submission polling intervals = PT1M
+
+        # poll one minute after foo starts running, then every 10
+        # minutes for 50 minutes, then every minute until finished:
+        execution polling intervals = PT1M, 5*PT10M, PT1M
+
+
+
+
+
flow.cylc
+
[runtime]
+   [[task]]
+      platform = my_platform
+
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/running-workflows/workflow-completion.html b/nightly_8.4/html/user-guide/running-workflows/workflow-completion.html new file mode 100644 index 00000000000..f127c98ec79 --- /dev/null +++ b/nightly_8.4/html/user-guide/running-workflows/workflow-completion.html @@ -0,0 +1,225 @@ + + + + + + + Workflow Completion — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Workflow Completion

+

A workflow is complete, and the scheduler will automatically +shut down, if no tasks remain in the +n=0.

+

That is, all active tasks have finished, and no tasks remain waiting on +prerequisites or “external” constraints (such as +xtriggers or task hold).

+

If no active tasks remain and all external constraints are satisfied, +but the n=0 window contains tasks waiting with partially satisfied +prerequisites, or tasks with final status and +incomplete outputs, then the workflow is +not complete and the scheduler will stall pending manual intervention.

+
+
+

Scheduler Stall

+

A stalled workflow has not run to completion +but cannot continue without manual intervention.

+

A stalled scheduler stays alive for a configurable timeout period +pending manual intervention. If it shuts down (on the stall timeout +or otherwise) it will remain in the stalled state on restart.

+

Stalls are often caused by unexpected task failures, either directly (tasks +with final status and incomplete outputs) +or indirectly (tasks with partially satisfied prerequisites, +downstream of an unexpected failure).

+
+

Warning

+

At present you have to consult the scheduler log to see the reason +for a stall.

+
+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/running-workflows/workflow-databases.html b/nightly_8.4/html/user-guide/running-workflows/workflow-databases.html new file mode 100644 index 00000000000..5bd0b2d0351 --- /dev/null +++ b/nightly_8.4/html/user-guide/running-workflows/workflow-databases.html @@ -0,0 +1,266 @@ + + + + + + + Workflow Run Databases — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Workflow Run Databases

+

Schedulers maintain two sqlite databases to record +information on run history:

+
$HOME/cylc-run/<workflow-id>/log/db  # public workflow DB
+$HOME/cylc-run/<workflow-id>/.service/db  # private workflow DB
+
+
+

The private DB is for use only by the scheduler. The identical +public DB is provided for use by external commands such as +cylc workflow-state, and cylc report-timings. +If the public DB gets locked for too long by +an external reader, the scheduler will eventually delete it and +replace it with a new copy of the private DB, to ensure that both correctly +reflect the workflow state.

+

You can interrogate the public DB with the sqlite3 command line tool, +the sqlite3 module in the Python standard library, or any other +sqlite interface.

+
$ sqlite3 ~/cylc-run/foo/log/db << _END_
+> .headers on
+> select * from task_events where name is "foo";
+> _END_
+name|cycle|time|submit_num|event|message
+foo|1|2017-03-12T11:06:09Z|1|submitted|
+foo|1|2017-03-12T11:06:09Z|1|output completed|started
+foo|1|2017-03-12T11:06:09Z|1|started|
+foo|1|2017-03-12T11:06:19Z|1|output completed|succeeded
+foo|1|2017-03-12T11:06:19Z|1|succeeded|
+
+
+

The diagram shown below contains the database tables, their columns, +and how the tables are related to each other. For more details on how +to interpret the diagram, refer to the +Entity–relationship model Wikipedia article.

+
+

graph { +node [label = "\N", shape = plaintext]; +edge [color = gray50, minlen = 2, style = dashed]; +rankdir = "LR"; +"absolute_outputs" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">absolute_outputs</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><FONT>cycle</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>name</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>output</FONT></TD></TR></TABLE></FONT>>]; +"broadcast_events" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">broadcast_events</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><FONT>time</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>change</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>point</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>namespace</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>key</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>value</FONT></TD></TR></TABLE></FONT>>]; +"broadcast_states" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">broadcast_states</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>point</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>namespace</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>key</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>value</FONT></TD></TR></TABLE></FONT>>]; +"inheritance" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">inheritance</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>namespace</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>inheritance</FONT></TD></TR></TABLE></FONT>>]; +"task_action_timers" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">task_action_timers</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>cycle</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>name</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>ctx_key</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>ctx</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>delays</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>num</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>delay</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>timeout</FONT></TD></TR></TABLE></FONT>>]; +"task_events" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">task_events</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><FONT>name</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>cycle</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>time</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>submit_num</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>event</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>message</FONT></TD></TR></TABLE></FONT>>]; +"task_jobs" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">task_jobs</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>cycle</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>name</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>submit_num</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>flow_nums</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>is_manual_submit</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>try_num</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>time_submit</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>time_submit_exit</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>submit_status</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>time_run</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>time_run_exit</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>run_signal</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>run_status</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>platform_name</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>job_runner_name</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>job_id</FONT></TD></TR></TABLE></FONT>>]; +"task_late_flags" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">task_late_flags</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>cycle</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>name</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>value</FONT></TD></TR></TABLE></FONT>>]; +"task_outputs" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">task_outputs</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>cycle</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>name</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>flow_nums</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>outputs</FONT></TD></TR></TABLE></FONT>>]; +"task_pool" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">task_pool</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>cycle</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>name</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>flow_nums</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>status</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>is_held</FONT></TD></TR></TABLE></FONT>>]; +"task_prerequisites" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">task_prerequisites</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>cycle</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>name</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>flow_nums</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>prereq_name</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>prereq_cycle</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>prereq_output</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>satisfied</FONT></TD></TR></TABLE></FONT>>]; +"task_states" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">task_states</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>name</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>cycle</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>flow_nums</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>time_created</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>time_updated</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>submit_num</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>status</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>flow_wait</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>is_manual_submit</FONT></TD></TR></TABLE></FONT>>]; +"task_timeout_timers" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">task_timeout_timers</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>cycle</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>name</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>timeout</FONT></TD></TR></TABLE></FONT>>]; +"tasks_to_hold" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">tasks_to_hold</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><FONT>name</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>cycle</FONT></TD></TR></TABLE></FONT>>]; +"workflow_flows" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">workflow_flows</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>flow_num</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>start_time</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>description</FONT></TD></TR></TABLE></FONT>>]; +"workflow_params" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">workflow_params</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>key</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>value</FONT></TD></TR></TABLE></FONT>>]; +"workflow_template_vars" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">workflow_template_vars</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>key</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>value</FONT></TD></TR></TABLE></FONT>>]; +"xtriggers" [label=<<FONT FACE="Helvetica"><TABLE BORDER="0" CELLBORDER="1" CELLPADDING="4" CELLSPACING="0"><TR><TD><B><FONT POINT-SIZE="16">xtriggers</FONT></B></TD></TR><TR><TD ALIGN="LEFT"><u><FONT>signature</FONT></u></TD></TR><TR><TD ALIGN="LEFT"><FONT>results</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>absolute_outputs</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>broadcast_events</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>broadcast_states</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>inheritance</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>tasks_to_hold</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>workflow_flows</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>workflow_params</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>workflow_template_vars</FONT></TD></TR><TR><TD ALIGN="LEFT"><FONT>xtriggers</FONT></TD></TR></TABLE></FONT>>]; +"task_states" -- "task_events" [taillabel=<<FONT>0..N</FONT>>,headlabel=<<FONT>{0,1}</FONT>>]; +"task_states" -- "task_jobs" [taillabel=<<FONT>0..N</FONT>>,headlabel=<<FONT>{0,1}</FONT>>]; +"task_pool" -- "task_action_timers" [taillabel=<<FONT>0..N</FONT>>,headlabel=<<FONT>{0,1}</FONT>>]; +"task_pool" -- "task_late_flags" [taillabel=<<FONT>{0,1}</FONT>>,headlabel=<<FONT>{0,1}</FONT>>]; +"task_pool" -- "task_outputs" [taillabel=<<FONT>0..N</FONT>>,headlabel=<<FONT>{0,1}</FONT>>]; +"task_pool" -- "task_prerequisites" [taillabel=<<FONT>0..N</FONT>>,headlabel=<<FONT>{0,1}</FONT>>]; +"task_pool" -- "task_timeout_timers" [taillabel=<<FONT>{0,1}</FONT>>,headlabel=<<FONT>{0,1}</FONT>>]; +subgraph { +rank=same +rankdir=LR +"absolute_outputs" +"broadcast_events" +"broadcast_states" +"inheritance" +"tasks_to_hold" +"workflow_flows" +"workflow_params" +"workflow_template_vars" +"xtriggers" +} +}

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/task-implementation/index.html b/nightly_8.4/html/user-guide/task-implementation/index.html new file mode 100644 index 00000000000..6d721ad11ef --- /dev/null +++ b/nightly_8.4/html/user-guide/task-implementation/index.html @@ -0,0 +1,212 @@ + + + + + + + Task Implementation — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Task Implementation

+

This section covers the technical detail of how Cylc runs tasks.

+

In Cylc tasks represent activities within the workflow. +Tasks submit jobs when they are run.

+

Tasks are the “abstract” workflow component. Jobs are the concrete +representation of a task. One task could submit many jobs (for example if the +job fails and the task is re-run).

+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.at.html b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.at.html new file mode 100644 index 00000000000..8a7ec0c5321 --- /dev/null +++ b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.at.html @@ -0,0 +1,198 @@ + + + + + + + at — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ +
+
+ +
+

at

+

Submits job scripts to the rudimentary Unix at scheduler.

+
+

Note

+

The atd daemon must be running.

+
+
+

Note

+

The atq command does not report if the job is running or not.

+
+

If an execution time limit is specified for a task, its job will +be wrapped by the timeout command.

+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.background.html b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.background.html new file mode 100644 index 00000000000..22f65a71d3b --- /dev/null +++ b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.background.html @@ -0,0 +1,190 @@ + + + + + + + background — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ +
+
+ +
+

background

+

Runs job scripts as Unix background processes.

+

If an execution time limit is specified for a task, its job will +be wrapped by the timeout command.

+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.loadleveler.html b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.loadleveler.html new file mode 100644 index 00000000000..079aa64a400 --- /dev/null +++ b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.loadleveler.html @@ -0,0 +1,228 @@ + + + + + + + loadleveler — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ +
+
+ +
+

loadleveler

+

Submits job scripts to loadleveler by the llsubmit command.

+

Loadleveler directives can be provided in the flow.cylc file:

+
+
global.cylc
+
[platforms]
+    [[myplatform]]
+        job runner = loadleveler
+
+
+
+
+
flow.cylc
+
[runtime]
+    [[my_task]]
+        platform = myplatform
+        execution time limit = PT10M
+        [[[directives]]]
+            foo = bar
+            baz = qux
+
+
+
+

These are written to the top of the job script like this:

+
#!/bin/bash
+# DIRECTIVES
+# @ foo = bar
+# @ baz = qux
+# @ wall_clock_limit = 660,600
+# @ queue
+
+
+

If restart=yes is specified as a directive for loadleveler, the job will +automatically trap SIGUSR1, which loadleveler may use to preempt the job. On +trapping SIGUSR1, the job will inform the workflow that it has been vacated by +loadleveler. This will put it back to the submitted state, until it starts +running again.

+

If execution time limit is specified, it is used to generate the +wall_clock_limit directive. The setting is assumed to be the soft limit. +The hard limit will be set by adding an extra minute to the soft limit. Do not +specify the wall_clock_limit directive explicitly if executiontime limit is specified. Otherwise, the execution time limit known by the +workflow may be out of sync with what is submitted to the job runner.

+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.lsf.html b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.lsf.html new file mode 100644 index 00000000000..69924a3050c --- /dev/null +++ b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.lsf.html @@ -0,0 +1,220 @@ + + + + + + + lsf — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ +
+
+ +
+

lsf

+

Submits job scripts to IBM Platform LSF by the bsub command.

+

LSF directives can be provided in the flow.cylc file:

+
+
global.cylc
+
[platforms]
+    [[myplatform]]
+        job runner = lsf
+
+
+
+
+
flow.cylc
+
[runtime]
+    [[my_task]]
+        platform = myplatform
+        execution time limit = PT10M
+        [[[directives]]]
+            -q = foo
+
+
+
+

These are written to the top of the job script like this:

+
#!/bin/bash
+# DIRECTIVES
+#BSUB -q = foo
+#BSUB -W = 10
+
+
+

If execution time limit is specified, it is used to generate the +-W directive. Do not specify the -W directive +explicitly if execution time limit is specified. Otherwise, the +execution time limit known by the workflow may be out of sync with what is +submitted to the job runner.

+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.moab.html b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.moab.html new file mode 100644 index 00000000000..1fb549ba323 --- /dev/null +++ b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.moab.html @@ -0,0 +1,226 @@ + + + + + + + moab — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ +
+
+ +
+

moab

+

Submits job scripts to the Moab workload manager with msub.

+

Moab directives can be provided in the flow.cylc file; the syntax is +very similar to PBS:

+
+
global.cylc
+
[platforms]
+    [[myplatform]]
+        job runner = moab
+
+
+
+
+
flow.cylc
+
[runtime]
+    [[my_task]]
+        platform = myplatform
+        execution time limit = PT1M
+        [[[directives]]]
+            -V =
+            -q = foo
+            -l nodes = 1
+
+
+
+

These are written to the top of the job script like this:

+
#!/bin/bash
+# DIRECTIVES
+#PBS -V
+#PBS -q foo
+#PBS -l nodes=1
+#PBS -l walltime=60
+
+
+

(Moab understands #PBS directives).

+

If execution time limit is specified, it is used to generate the +-l walltime directive. Do not specify the -l walltime directive +explicitly if execution time limit is specified. Otherwise, the +execution time limit known by the workflow may be out of sync with what is +submitted to the job runner.

+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.pbs.html b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.pbs.html new file mode 100644 index 00000000000..c3ae7f6fe94 --- /dev/null +++ b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.pbs.html @@ -0,0 +1,224 @@ + + + + + + + pbs — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ +
+
+ +
+

pbs

+

Submits job scripts to PBS (or Torque) by the qsub command.

+

PBS directives can be provided in the flow.cylc file:

+
+
global.cylc
+
[platforms]
+    [[myplatform]]
+        job runner = pbs
+
+
+
+
+
flow.cylc
+
[runtime]
+    [[my_task]]
+        platform = myplatform
+        execution time limit = PT1M
+        [[[directives]]]
+            -V =
+            -q = foo
+            -l nodes = 1
+
+
+
+

These are written to the top of the job script like this:

+
#!/bin/bash
+# DIRECTIVES
+#PBS -V
+#PBS -q foo
+#PBS -l nodes=1
+#PBS -l walltime=60
+
+
+

If execution time limit is specified, it is used to generate the +-l walltime directive. Do not specify the -l walltime directive +explicitly if execution time limit is specified. Otherwise, the +execution time limit known by the workflow may be out of sync with what is +submitted to the job runner.

+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.sge.html b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.sge.html new file mode 100644 index 00000000000..780273bc52c --- /dev/null +++ b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.sge.html @@ -0,0 +1,224 @@ + + + + + + + sge — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ +
+
+ +
+

sge

+

Submits job scripts to Sun/Oracle Grid Engine with qsub.

+

SGE directives can be provided in the flow.cylc file:

+
+
global.cylc
+
[platforms]
+    [[sge_platform]]
+        job runner = sge
+
+
+
+
+
flow.cylc
+
[runtime]
+    [[my_task]]
+        platform = sge_platform
+        execution time limit = P1D
+        [[[directives]]]
+            -cwd =
+            -q = foo
+            -l h_data = 1024M
+
+
+
+

These are written to the top of the job script like this:

+
#!/bin/bash
+# DIRECTIVES
+#$ -cwd
+#$ -q foo
+#$ -l h_data=1024M
+#$ -l h_rt=24:00:00
+
+
+

If execution time limit is specified, it is used to generate the +-l h_rt directive. Do not specify the -l h_rt directive explicitly if +execution time limit is specified. Otherwise, the execution time +limit known by the workflow may be out of sync with what is submitted to the +job runner.

+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm.html b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm.html new file mode 100644 index 00000000000..08461c21fe1 --- /dev/null +++ b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm.html @@ -0,0 +1,264 @@ + + + + + + + slurm — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ +
+
+ +
+

slurm

+

Submits job scripts to Simple Linux Utility for Resource Management.

+

Uses the sbatch command. SLURM directives can be provided in the flow.cylc +file:

+
+
global.cylc
+
[platforms]
+    [[slurm_platform]]
+        job runner = slurm
+
+
+
+
+
flow.cylc
+
[runtime]
+    [[my_task]]
+        platform = slurm_platform
+        execution time limit = PT1H
+        [[[directives]]]
+            --nodes = 5
+            --account = QXZ5W2
+
+
+
+
+

Note

+
    +
  • Cylc requires long form directives (e.g. --begin not -b).

  • +
  • Cylc requires an = even if the directive does not have a value +(e.g. --hold= not --hold).

  • +
  • If a directive does not have a value you may use the short form +(e.g. -H=). But the directive must still be suffixed with an =.

  • +
+
+

These are written to the top of the job script like this:

+
#!/bin/bash
+#SBATCH --nodes=5
+#SBATCH --time=60:00
+#SBATCH --account=QXZ5W2
+
+
+

If execution time limit is specified, it is used to generate the +--time directive. Do not specify the --time directive explicitly if +execution time limit is specified. Otherwise, the execution time +limit known by the workflow may be out of sync with what is submitted to the +job runner.

+

Cylc supports heterogeneous Slurm jobs via special numbered directive prefixes +that distinguish repeated directives from one another:

+
[runtime]
+    # run two heterogenous job components:
+    script = srun sleep 10 : sleep 30
+    [[my_task]]
+        execution time limit = PT1H
+        platform = slurm_platform
+        [[[directives]]]
+            --account = QXZ5W2
+            hetjob_0_--mem = 1G  # first prefix must be "0"
+            hetjob_0_--nodes = 3
+            hetjob_1_--mem = 2G
+            hetjob_1_--nodes = 6
+
+
+

The resulting formatted directives are:

+
#!/bin/bash
+#SBATCH --time=60:00
+#SBATCH --account=QXZ5W2
+#SBATCH --mem=1G
+#SBATCH --nodes=3
+#SBATCH hetjob
+#SBATCH --mem=2G
+#SBATCH --nodes=6
+
+
+
+

Note

+

For older Slurm versions with packjob instead of hetjob, use +global.cylc[platforms][<platform name>]job runner=slurm_packjob and directive prefixes packjob_0_ etc.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm_packjob.html b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm_packjob.html new file mode 100644 index 00000000000..3de1911092b --- /dev/null +++ b/nightly_8.4/html/user-guide/task-implementation/job-runner-handlers/cylc.flow.job_runner_handlers.slurm_packjob.html @@ -0,0 +1,190 @@ + + + + + + + slurm_packjob — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ +
+
+ +
+

slurm_packjob

+

SLURM job submission and manipulation.

+

Includes directive prefix workaround for heterogeneous job support, for older +Slurm versions that use “packjob” instead of “hetjob”.

+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/task-implementation/job-scripts.html b/nightly_8.4/html/user-guide/task-implementation/job-scripts.html new file mode 100644 index 00000000000..88e60e6a067 --- /dev/null +++ b/nightly_8.4/html/user-guide/task-implementation/job-scripts.html @@ -0,0 +1,432 @@ + + + + + + + Task Implementation — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Task Implementation

+

Existing scripts and executables can be used as Cylc tasks without +modification so long as they return standard exit status - zero on success, +non-zero for failure - and do not spawn detaching processes internally (see +Avoid Detaching Processes).

+
+

Job Scripts

+

When the scheduler determines that a task is ready to run it +generates a job script for the task, and submits it to run (see +Job Submission and Management).

+

Job scripts encapsulate configured task runtime settings: +script and [environment] items, if defined, are just +concatenated in the order shown below, to make the job script.

+

The job script is separated into two parts. User scripts and environment +(env-script, [environment], pre-script, +script and post-script) are isolated and executed in +a separate subshell process. Any changes to environment, traps, etc., done in +any of them are visible in subsequent parts, but will not interfere with the +parent shell process. This parent shell executes and shares environment with +init-script, exit-script and err-script. +In particular, any environment changes in init-script will be +visible in the parent shell, as well as in the subshell hosting user scripts.

+

The parent shell sets trap handlers for some signals (the exact list depends on +a particular batch system being used) and typically resends any received signal +to the subshell and its children (the whole process group, to be precise), unless +the batch system doesn’t execute the job script as process leader, in which case +the signal is resent to the subshell process only. Immediately after that +err-script is executed without waiting for the subshell process to +finish, unless you start it with the wait command to prevent that.

+
+

digraph example { +rankdir="TB" +packmode="array_u"; + +subgraph cluster_legend { + style="dashed" + label="Legend" + + "user defined script" + "cylc defined script" [shape="rect"] + + "user defined script" -> "cylc defined script" [style="invis"] +} + +subgraph cluster_diagram { + style="invis" + margin=20 + + "cylc-env" [shape="rect"] + "user-env" [shape="rect"] + + "init-script" -> + "cylc-env" -> + "env-script" + + subgraph cluster_subshell { + style="dashed" + label="Subshell process" + + "env-script" -> + "user-env" -> + "pre-script" -> + "script" -> + "post-script" + } + + "post-script" -> "err-script" + "post-script" -> "exit-script" +} +}

+

The two “Cylc defined scripts” are:

+
+
cylc-env

Which provides default CYLC_* environment variables e.g. +CYLC_TASK_NAME.

+
+
user-env

Which is the contents of the [environment] section.

+
+
+

Job scripts are written to the workflow’s job log directory. They can be +printed with cylc cat-log.

+
+
+

Inlined Tasks

+

Task script items can be multi-line strings of bash code, so many tasks +can be entirely inlined in the flow.cylc file.

+

For anything more than a few lines of code, however, we recommend using +external shell scripts to allow independent testing, re-use, and shell mode +editing.

+
+
+

Interpreter

+

The job script (which incorporates the *-script items) runs in the +bash interpreter.

+

Cylc searches for bash in the $PATH by first running a login bash +shell which means you can choose the bash interpreter used by modifying +the $PATH in your bash configuration files (e.g. .bashrc).

+
+
+

Task Messages

+

Jobs send status messages back to the scheduler to report that +execution has started, succeeded, or failed. Custom messages can also be sent +by the same mechanism, with various severity levels. These can be used to +trigger other tasks off specific task outputs (see Message Triggers), or +to trigger execution of event handlers by the scheduler (see +Task Event Handling) +or just to write information to the scheduler log.

+

(If polling is configured as the communication method for a +platform, the messaging system just writes messages to the +local job status file for recovery by the scheduler at the next poll).

+

Normal severity messages are printed to job.out and logged by the scheduler:

+
cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \
+  "Hello from ${CYLC_TASK_ID}"
+
+
+

“CUSTOM” severity messages are printed to job.out, logged by the +scheduler, and can be used to trigger custom +event handlers:

+
cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \
+  "CUSTOM:data available for ${CYLC_TASK_CYCLE_POINT}"
+
+
+

These can be used to signal special events that are neither routine +information nor an error condition, such as production of a particular data +file (a “data availability” event).

+

“WARNING” severity messages are printed to job.err, logged by the +scheduler, and can be passed to warning event handlers:

+
cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \
+  "WARNING:Uh-oh, something's not right here."
+
+
+

“CRITICAL” severity messages are printed to job.err, logged by the +scheduler, and can be passed to critical event handlers:

+
cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \
+  "CRITICAL:ERROR occurred in process X!"
+
+
+

Jobs no longer (since Cylc 8) attempt to resend messages if the server +cannot be reached. Send failures normally imply a network or Cylc +configuration problem that will not recover by itself, in which case a series +of messaging retries just holds up job completion unnecessarily. If a job +status message does not get through, the server will recover the correct task +status by polling on job timeout (or earlier if regular polling is +configured).

+

Task messages are validated by:

+
+
+class cylc.flow.unicode_rules.TaskMessageValidator[source]
+

The rules for valid task messages:

+
    +
  • cannot contain : unless it occurs at the end of the first word

  • +
  • cannot be: expired, submitted, submit-failed, started, succeeded, failed, finished, expire, submit, submit-fail, start, succeed, fail, finish, succeed-all, succeed-any, fail-all, fail-any, finish-all, finish-any, start-all, start-any, submit-all, submit-any, submit-fail-all or submit-fail-any

  • +
  • cannot start with: _cylc

  • +
+
+ +
+
+

Aborting Job Scripts on Error

+

Job scripts use set -e to abort on any error, and trap ERR, EXIT, and +SIGTERM to send task failed messages back to the scheduler before +aborting. Other scripts called from job scripts should therefore abort with +standard non-zero exit status on error, to trigger the job script error trap.

+

To prevent a command that is expected to generate a non-zero exit status from +triggering the exit trap, protect it with a control statement such as:

+
if cmp FILE1 FILE2; then
+    :  # success: do stuff
+else
+    :  # failure: do other stuff
+fi
+
+
+

Job scripts also use set -u to abort on referencing any +undefined variable (useful for picking up typos); and set -o pipefail +to abort if any part of a pipe fails (by default the shell only returns the +exit status of the final command in a pipeline).

+
+

Custom Failure Messages

+

Critical events normally warrant aborting a job script rather than just +sending a message. As described just above, exit 1 or any failing command +not protected by the surrounding scripting will cause a job script to abort +and report failure to the scheduler, potentially triggering a +failed task event handler.

+

For failures detected by the scripting you could send a critical message back +before aborting, potentially triggering a critical task event handler:

+
if ! /bin/false; then
+  cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" \
+    "CRITICAL:ERROR: /bin/false failed!"
+  exit 1
+fi
+
+
+

To abort a job script with a custom message that can be passed to a +failed task event handler, use the built-in cylc__job_abort shell +function:

+
if ! /bin/false; then
+  cylc__job_abort "ERROR: /bin/false failed!"
+fi
+
+
+
+
+
+

Avoid Detaching Processes

+

If a task script starts background sub-processes and does not wait on them, or +internally submits jobs to a job runner and then exits immediately, the +detached processes will not be visible to Cylc and the task will appear to +finish when the top-level script finishes. You will need to modify scripts +like this to make them execute all sub-processes in the foreground (or use the +shell wait command to wait on them before exiting) and to prevent job +submission commands from returning before the job completes (e.g. +llsubmit -s for Loadleveler, +qsub -sync yes for Sun Grid Engine, and +qsub -W block=true for PBS).

+

If this is not possible - perhaps you don’t have control over the script +or can’t work out how to fix it - one alternative approach is to use another +task to repeatedly poll for the results of the detached processes:

+
[scheduling]
+    [[graph]]
+        R1 = "model => checker => post-proc"
+[runtime]
+    [[model]]
+        # Uh-oh, this script does an internal job submission to run model.exe:
+        script = "run-model.sh"
+    [[checker]]
+        # Fail and retry every minute (for 10 tries at the most) if model's
+        # job.done indicator file does not exist yet.
+        script = "[[ ! -f $RUN_DIR/job.done ]] && exit 1"
+        execution retry delays = 10 * PT1M
+
+
+
+
+

Use of Pipes in Job Scripts

+

In bash, the return status of a pipeline is normally the exit status of the +last command. This is unsafe, because if any command in the pipeline fails, the +script will continue nevertheless.

+

For safety, a Cylc job script running in bash will have the +set -o pipefail option turned on automatically. If a pipeline +exists in a task’s script, etc section, the failure of any part of +a pipeline will cause the command to return a non-zero code at the end, which +will be reported as a job failure. Due to the unique nature of a pipeline, +the job file will trap the failure of the individual commands, as well as the +whole pipeline, and will attempt to report a failure back to the workflow twice. +The second message is ignored by the workflow, and so the behaviour can be safely +ignored. (You should probably still investigate the failure, however!)

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/task-implementation/job-submission.html b/nightly_8.4/html/user-guide/task-implementation/job-submission.html new file mode 100644 index 00000000000..aed0a2d1d2e --- /dev/null +++ b/nightly_8.4/html/user-guide/task-implementation/job-submission.html @@ -0,0 +1,463 @@ + + + + + + + Job Submission and Management — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Job Submission and Management

+

This section explains how the Cylc scheduler submits jobs +when they are ready to run, and how to define new job runner handlers.

+
+

Note

+

For the requirements a command, script, or program, must fulfil in order to +function as a Cylc task, see Task Implementation.

+
+

When a task is ready Cylc generates a job script (see Job Scripts). +The job script is submitted to be run by the job runner from the +platform chosen for the task. +Like other runtime properties, you can set a workflow default platform and +override it for specific tasks or families:

+
[runtime]
+   [[root]] # workflow defaults
+        platform = platform_with_loadleveler
+   [[foo]] # just task foo
+        platform = platform_with_at
+
+
+
+

Supported Job Submission Methods

+

Cylc provided built-in support for the following batch submission systems:

+

Cylc provides support for the following job runner handlers.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

cylc.flow.job_runner_handlers.at

Submits job scripts to the rudimentary Unix at scheduler.

cylc.flow.job_runner_handlers.background

Runs job scripts as Unix background processes.

cylc.flow.job_runner_handlers.loadleveler

Submits job scripts to loadleveler by the llsubmit command.

cylc.flow.job_runner_handlers.lsf

Submits job scripts to IBM Platform LSF by the bsub command.

cylc.flow.job_runner_handlers.moab

Submits job scripts to the Moab workload manager with msub.

cylc.flow.job_runner_handlers.pbs

Submits job scripts to PBS (or Torque) by the qsub command.

cylc.flow.job_runner_handlers.sge

Submits job scripts to Sun/Oracle Grid Engine with qsub.

cylc.flow.job_runner_handlers.slurm

Submits job scripts to Simple Linux Utility for Resource Management.

cylc.flow.job_runner_handlers.slurm_packjob

SLURM job submission and manipulation.

+

See Custom Job Submission Methods for how to add new job +submission methods.

+
+

Default Directives Provided

+

For job runners that use job file directives (PBS, Loadleveler, +etc.) default directives are provided to set the job name, stdout and stderr +file paths, and the execution time limit (if specified).

+
+

Tip

+

Use [runtime][<namespace>]execution time limit to set +time limits, rather than setting this as a directive yourself.

+

This allows Cylc to identify execution timeout even if the +job runner cannot be contacted.

+

See Execution Time Limit

+
+

Cylc constructs the job name string using a combination of the task ID and the +workflow name. PBS fails a job submit if the job name in -N name is +too long. For version 12 or below, this is 15 characters. For version 13, this +is 236 characters. The default setting will truncate the job name string to 236 +characters. If you have PBS 12 or older at your site, you should modify your +site’s global configuration file to allow the job name to be truncated at 15 +characters using +global.cylc[platforms][<platform name>]job name length maximum.

+
+
+

Directives Section Quirks (PBS, SGE, …)

+

To specify an option with no argument, such as -V in PBS or +-cwd in SGE you must give a null string as the directive value in +the flow.cylc file.

+

The left hand side of a setting (i.e. the string before the first equal sign) +must be unique. To specify multiple values using an option such as +-l option in PBS, SGE, etc., either specify all items in a single +line:

+
-l=select=28:ncpus=36:mpiprocs=18:ompthreads=2
+
+
+

(Left hand side is -l. A second -l=... line will override the first.)

+

Or separate the items:

+
-l select=28
+-l ncpus=36
+-l mpiprocs=18
+-l ompthreads=2
+
+
+
+

Note

+

There is no equal sign after -l.

+
+

(Left hand sides are now -l select, -l ncpus, etc.)

+
+
+
+

Task stdout and stderr Logs

+

When a task is ready to run Cylc generates a filename root to be used +for the job script and log files. The file path contains the task +name, cycle point, and a submit number that increments if the same task is +re-triggered multiple times:

+
# job script:
+~/cylc-run/my-workflow/basic/log/job/1/hello/01/job
+# stdout:
+~/cylc-run/my-workflow/basic/log/job/1/hello/01/job.out
+# stderr:
+~/cylc-run/my-workflow/basic/log/job/1/hello/01/job.err
+
+
+

How the stdout and stderr streams are directed into these files depends on the +job runner. The +background method just +uses appropriate output redirection on the command line, as shown above. The +loadleveler method writes +appropriate directives to the job script that is submitted to loadleveler.

+

Cylc obviously has no control over the stdout and stderr output from +tasks that do their own internal output management (e.g. tasks +that submit internal jobs and direct the associated output to other +files). For less internally complex tasks, however, the files referred +to here will be complete job logs.

+

Some job runners, such as PBS, +redirect a job’s stdout +and stderr streams to a separate cache area while the job is running. The +contents are only copied to the normal locations when the job completes. This +means that cylc cat-log will be unable to find the +job’s stdout and stderr streams while the job is running. Some sites with these +job runners are known to provide commands for viewing and/or +tail-follow a job’s stdout and stderr streams that are redirected to these +cache areas. If this is the case at your site, you can configure Cylc to make +use of the provided commands by adding some settings to the global site/user +config. E.g.:

+
[hosts]
+    [[HOST]]  # <= replace this with a real host name
+        [[[batch systems]]]
+            [[[[pbs]]]]
+                err tailer = qcat -f -e \%(job_id)s
+                out tailer = qcat -f -o \%(job_id)s
+                err viewer = qcat -e \%(job_id)s
+                out viewer = qcat -o \%(job_id)s
+
+
+
+
+

Overriding The Job Submission Command

+

To change the form of the actual command used to submit a job you +need to define a new +global.cylc[platforms][<platform name>]job runner command template.

+
[platform]
+    [[my_custom_platform]]
+        hosts = host1, host2
+        job runner = loadleveler
+        # Use '-s' to stop llsubmit returning
+        # until all job steps have completed:
+        job runner command template = llsubmit -s %(job)s
+
+
+

The template’s %(job)s will be substituted by the job file path.

+
+
+

Job Polling

+

For supported job runners, jobs can be polled to +check that their true state matches what the scheduler expects based on received +job status messages or previous polls. The scheduler executes a process +on the task host, by non-interactive ssh, to interrogate the job runner, and to +read the job.status file of the task which is automatically generated by the +job script as it runs.

+

Polling may be required to update the workflow state correctly after unusual +events such as

+
    +
  • a job gets killed by the untrappable SIGKILL signal (e.g. kill -9 PID)

  • +
  • a machine being rebooted with tasks running on it

  • +
  • network problems prevent task messages from getting back to the workflow host

  • +
  • the scheduler itself was down when active jobs finished

  • +
+

Tasks can be polled on demand by using the +cylc poll command.

+
+

See also

+
    +
  • cylc poll --help

  • +
+
+

Tasks are polled automatically, once, if they timeout while queueing in a +job runner and submission timeout is set. +(See [runtime][<namespace>][events] +for how to configure timeouts).

+

Tasks are polled multiple times, where necessary, when they exceed their +execution time limits. These are normally set with some initial delays to allow +the job runners to kill the jobs. +(See +execution time limit polling intervals +for how to configure the polling intervals).

+

Any tasks recorded in the submitted or running states at workflow +restart are automatically polled to determine what happened to them while the +workflow was down.

+

By default, regular polling also takes place every 15 minutes whilst a job is +submitted or running. The default polling intervals can be overridden in the +global configuration:

+ +

The polling intervals can also be configured for individual tasks:

+ +

Polling can be used as the sole method of determining task status on hosts that +do not allow task messages to be routed back to the workflow host. +See Polling to Track Job Status.

+
+

Note

+

For polling to work correctly, the job runner queueing system must have a +job listing command for listing your jobs, and that the job listing must +display job IDs as they are returned by the job runner queueing system submit +command. For example, for pbs, moab and sge, the qstat command +should list jobs with their IDs displayed in exactly the same format as they +are returned by the qsub command.

+
+
+
+

Job Killing

+

For supported job runners, the scheduler can execute a process on +the task host, by non-interactive ssh, to kill a submitted or running job +according to its job runner.

+

Tasks can be killed on demand by using the cylc kill command.

+
+
+

Execution Time Limit

+

You can specify an execution time limit for all supported job +submission methods. E.g.:

+
[runtime]
+    [[task-x]]
+        execution time limit = PT1H
+
+
+

For tasks running with +background or +at, their jobs +will be wrapped using the timeout command. For all other methods, +the relevant time limit directive will be added to their job files.

+

The execution time limit setting will also inform the workflow when a +a job should complete by. If a job has not reported completing within +the specified time, the workflow will poll the job. (The default +setting is PT1M, PT2M, PT7M. The accumulated times for these intervals will be +roughly 1 minute, 1 + 2 = 3 minutes and 1 + 2 + 7 = 10 minutes after a job +exceeds its execution time limit.)

+
+

Execution Time Limit and Execution Timeout

+

If you specify an execution time limit the +execution timeout event handler will only be called if the job has +not completed after the final poll (by default, 10 min after the time limit). +This should only happen if the submission method you are using is not enforcing +wallclock limits (unlikely) or you are unable to contact the machine to confirm +the job status.

+

If you specify an [events]execution timeout and not an +execution time limit then the +execution timeout event handler will be called as soon as the +specified time is reached. The job will also be polled to check its latest +status (possibly resulting in an update in its status and the calling of the +relevant event handler). This behaviour is deprecated, which users should avoid +using.

+

If you specify an [events]execution timeout and an +execution time limit then the execution timeout setting will be +ignored.

+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/task-implementation/ssh-job-management.html b/nightly_8.4/html/user-guide/task-implementation/ssh-job-management.html new file mode 100644 index 00000000000..c1a5dbbbc37 --- /dev/null +++ b/nightly_8.4/html/user-guide/task-implementation/ssh-job-management.html @@ -0,0 +1,249 @@ + + + + + + + Remote Job Management — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Remote Job Management

+

Managing tasks in a workflow requires more than just job execution: Cylc +performs additional actions with rsync for file transfer, and +direct execution of cylc sub-commands over non-interactive SSH.

+
+

SSH-free Job Management?

+

Some sites may want to restrict access to job hosts by whitelisting SSH +connections to allow only rsync for file transfer, and allowing job +execution only via a local job runner that sees the job hosts [1] . +We are investigating the feasibility of SSH-free job management when a local +job runner is available, but this is not yet possible unless your workflow +and job hosts also share a filesystem, which allows Cylc to treat jobs as +entirely local [2] .

+
+
+

SSH-based Job Management

+

Cylc does not have persistent agent processes running on job hosts to act on +instructions received over the network [3] so instead we execute job +management commands directly on job hosts over SSH. Reasons for this include:

+
    +
  • It works equally for job runner and background jobs.

  • +
  • SSH is required for background jobs, and for jobs in other job runners if the +job runner is not available on the workflow host.

  • +
  • Querying the job runner alone is not sufficient for full job +polling functionality.

    +
      +
    • This is because jobs can complete (and then be forgotten by +the job runner) while the network, workflow host, or scheduler is +down (e.g. between workflow shutdown and restart).

    • +
    • To handle this we get the automatic job wrapper code to write +job messages and exit status to job status files that are +interrogated by schedulers during job polling +operations.

    • +
    • Job status files reside on the job host, so the interrogation +is done over SSH.

    • +
    +
  • +
  • Job status files also hold job runner name and job ID; this is +written by the job submit command, and read by job poll and kill commands

  • +
+
+
+

Other Cases Where Cylc Uses SSH Directly

+
    +
  • To see if a workflow is running on another host with a shared +filesystem - see cylc/flow/workflow_files:detect_old_contact_file.

  • +
+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/troubleshooting.html b/nightly_8.4/html/user-guide/troubleshooting.html new file mode 100644 index 00000000000..de19b7952b6 --- /dev/null +++ b/nightly_8.4/html/user-guide/troubleshooting.html @@ -0,0 +1,716 @@ + + + + + + + Troubleshooting — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Troubleshooting

+ +
+

Log Files

+

If things have gone wrong and you’re not sure why, there are few files which +you’ll find in the workflow’s run directory that should contain the +required information to work out what’s going on:

+
+
log/scheduler/log

There’s a log file for each workflow in +~/cylc-run/<workflow>/log/scheduler/log.

+

This records all the essential information including every job submission +and task state change.

+

You can view this in the GUI, Tui or on the command line using +cylc cat-log <workflow>.

+
+
job.err

This contains the stderr captured when the job ran. It’s useful for +debugging job failures.

+

You can view this in the GUI, Tui or on the command line using +cylc cat-log <workflow>//<cycle>/<task>/<job> -f e.

+
+
job-activity.log

This file records the interaction Cylc has had with a job, namely submission +and polling. This can be useful in determining the cause of job submission +failures.

+

You can view this in the GUI, Tui or on the command line using +cylc cat-log <workflow>//<cycle>/<task>/<job> -f a.

+
+
+

Additionally, these directories contain extra information which can be useful +for debugging some specific issues:

+
+
log/install/

Contains logging from local workflow installation (e.g.``cylc install``).

+

This can be useful for inspecting Rose file installation.

+
+
log/remote-install/

Records information about file installation on remote platforms +(see Remote Initialization).

+
+
log/config/

Records the workflow configuration (and the Rose suite configuration if one +is used).

+

These files can allow you to see how the configuration was changed between +restarts and reloads.

+

Each time a workflow is started, restarted or reloaded, +the configuration used is recorded in a file in log/config. +This provides a series of snapshots of the configuration. +These files are named:

+

<LOG FILE NUMBER>-<EVENT>-<(RE)START NUMBER>.

+

If for example we did:

+
# Command            # File created
+cylc play workflow   # 01-start-01.cylc
+cylc vr workflow     # 02-reload-01.cylc
+cylc stop workflow
+cylc play workflow   # 03-restart-02.cylc
+
+
+
+
+
+
+

Shell Login/Profile Files

+

Cylc runs many commands using +Bash login shells.

+

This allows you to configure aspects of Cylc’s behaviour using login files +such as .bash_profile and .bashrc.

+

However, it also means that the contents of these files can interfere with +Cylc (and potentially other systems too).

+

If you have things in your login files which are only intended for use in +interactive terminal sessions, wrap them inside an if block so they only +run for interactive sessions like so:

+
if [[ $- == *i* ]]; then
+   # only run this for interactive (terminal) sessions
+   # (and not for non-interactive login sessions)
+   echo "Hello $USER"
+   alias rsync='rsync -v'
+   conda activate my_env
+   export PS1="\$ $(tput bold)[$PREFIX]$(tput sgr 0) "
+fi
+
+# this runs for all sessions including non-interactive login sessions
+export PATH="$HOME/bin:$PATH"
+export MY_LIB_PATH="$HOME/my-lib/1.0/"
+
+
+

Some things to check your login files for:

+
    +
  • Don’t write to stdout (e.g. using echo or printf), this can interfere +with command output.

  • +
  • Avoid loading modules or environments by default, you can create short cuts +for loading these using functions, aliases or commands.

  • +
  • Don’t add non-existent directories into your $PATH, this can cause +commands to hang.

  • +
  • Always prepend or append to $PATH, never overwrite it.

  • +
  • Don’t override (i.e. clobber) standard commands with aliases, functions, +scripts or the like. This can prevent tools from being able to access the +original command.

  • +
+
+
+

Problems

+
+

Job Status Isn’t Updating

+

Cylc keeps track of a job’s progress in one of two ways (according to how +the platform the job was submitted to is configured):

+
    +
  • Jobs send messages to the scheduler (push).

  • +
  • The scheduler polls jobs (pull).

  • +
+

In either case, the job will also write its updates to the job.status file.

+

This is what the job.status file should look like for a successful job, +note the SUCCEEDED line:

+
CYLC_JOB_RUNNER_NAME=background
+CYLC_JOB_ID=12345
+CYLC_JOB_RUNNER_SUBMIT_TIME=2000-01-01T00:00:00
+CYLC_JOB_PID=108179
+CYLC_JOB_INIT_TIME=2000-01-01T00:10:00
+CYLC_JOB_EXIT=SUCCEEDED
+CYLC_JOB_EXIT_TIME=2000-01-01T01:30:00
+
+
+

If the job.status file is showing something different to what the GUI or +Tui is showing, then…

+

If your platform uses push communication:

+

If messages aren’t getting back to the scheduler, there should be some +evidence of this in the job.err file, likely either an error or a +traceback. Likely causes:

+
    +
  • There is a network issue.

  • +
  • TCP ports are not open (zmq communications).

  • +
  • Non-interactive SSH has not been correctly configured (ssh communications).

  • +
+

If your platform uses pull communication:

+

Firstly, check the polling interval, it’s possible that the scheduler has been +configured to poll infrequently and you need to wait for the next poll, or +request a poll manually using the cylc poll command (also available in the +GUI & Tui).

+

Use the cylc config command to inspect the platform’s configuration to +determine the configured polling schedule.

+

Then check the job-activity.log file, there may have been a problem polling +the remote platform, e.g. a network or configuration error.

+

Likely causes:

+
    +
  • The platform is down (e.g. all login nodes are offline).

  • +
  • There is a network issue.

  • +
  • Non-interactive SSH has not been correctly configured.

  • +
+
+
+

My Job Submit-Failed

+

A submit-failed job means one of three things:

+
    +
  1. There is a Bash syntax error in the task configuration.

    +

    E.G. the following script has a syntax error, it is missing a +" character after $WORLD:

    +
    [runtime]
    +    [[foo]]
    +        script = """
    +            echo "Hello $WORLD
    +        """
    +
    +
    +

    This will result in a submission-failure which should appear in the +job-activity.log file (and also the scheduler log) something like this:

    +
    [jobs-submit cmd] (prepare job file)
    +[jobs-submit ret_code] 1
    +[jobs-submit err]
    +/path/to/job.tmp: line 46: unexpected EOF while looking for matching `"'
    +/path/to/job.tmp: line 50: syntax error: unexpected end of file
    +
    +
    +
  2. +
  3. There was an error submitting the job to the specified platform (including +network issues).

    +

    See the job-activity.log and the scheduler log. Diagnostic information +should be in one or both of those files.

    +
  4. +
  5. The platform is not correctly configured.

    +

    See also platform: <name> - initialisation did not complete.

    +
  6. +
+
+
+

My Job Failed

+

This means something went wrong executing the job. +To find out more, see the job.err file.

+
+

Note

+

To ensure Cylc jobs fail when they are supposed to, Cylc configures Bash +to be stricter than it is by default by running set -euo pipefail.

+

This only applies to scripts you’ve configured in the Cylc script +settings (i.e. script, pre-script, post-script, etc), not to any +Bash scripts to call from the job script.

+
+
+

Tip

+

One particularly common issue when developing a workflow is failure +to make a script executable. Use ls -l to check.

+
+

If you’re struggling to track down the error, you might want to put the +workflow into debug mode:

+
cylc verbosity DEBUG <workflow-id>
+
+
+

When a workflow is running in debug mode, all jobs will create a job.xtrace +file when run in addition to job.err. This can help you to locate the error +within the job script.

+

You can also start workflows in debug mode:

+
cylc play --debug <workflow-id>
+
+
+
+
+

My workflow shut down unexpectedly

+

When a Cylc scheduler shuts down, it should leave behind a log message explaining why.

+

E.G. this message means that a workflow shut down because it was told to:

+
Workflow shutting down - REQUEST(CLEAN)
+
+
+

If a workflow shut down due to a critical problem, you should find some +traceback in this log. If this traceback doesn’t look like it comes from your +system, please report it to the Cylc developers for investigation (on +GitHub or Discourse).

+

In some extreme cases, Cylc might not be able to write a log message e.g:

+
    +
  • There’s not enough disk space for Cylc to write a log message.

  • +
  • If the scheduler was killed in a nasty way e.g. kill -9.

  • +
  • If the scheduler host goes down (e.g. power off).

  • +
+

If the issue is external to the workflow, once the issue is resolved it should +be possible to restart it as you would normally using cylc play. Cylc +will pick up where it left off.

+
+
+

Why isn’t my task running?

+

To find out why a task is not being run, use the cylc show command. +This will list the task’s prerequisites and xtriggers.

+

Note, at present cylc show can only display +active tasks. Waiting tasks beyond the +n=0 window have no satisfied prerequisites.

+

Note, tasks which are held task-held will not be run, use cylc release +to release a held task.

+

Note, Cylc will not submit jobs if the scheduler is paused, use cylc play +to resume a paused workflow.

+
+
+

Required files are not being installed on remote platforms

+

Cylc installs selected workflow files onto remote platforms when the first task +submits to it.

+

See Remote Initialization for the list of directories installed and how to +configure them.

+

If something has gone wrong during installation, an error should have been +logged a file in this directory: +$HOME/cylc-run/<workflow-id>/log/remote-install/.

+

If you need to access files from a remote platform (e.g. 2-stage fcm_make), +ensure that a task has submitted to it before you do so. If needed you can use +a blank “dummy” task to ensure that remote installation is completed before +you run any tasks which require this e.g:

+
dummy => fetch_files
+
+
+
+
+

Conda / Mamba environment activation fails

+

Some Conda packages rely on activation scripts which are run when you call the +activate command.

+

Unfortunately, some of these scripts don’t defend against command failure or +unset environment variables causing them to fail when configured in Cylc +*script (see also My Job Failed for details).

+

To avoid this, run set +eu before activating your environment. This turns +off some Bash safety features, allowing environment activation to complete. +Remember to run set -eu afterwards to turn these features back on.

+
[runtime]
+    [[my_task]]
+         script = """
+            set +eu
+            conda activate <my_environment>
+            set -eu
+
+            do-something
+            do-something-else
+         """
+
+
+
+
+
+

Error Messages

+

Cylc should normally present you with a simple, short error message when things +go wrong.

+

To see the full traceback, run the command / workflow in debug mode, e.g. using +the --debug option.

+

If you are presented with traceback when you are not running in debug mode, +then this is not an expected error, please report the traceback to us.

+
+

FileNotFoundError: No such file or directory

+

This is the error message Python gives when you try to call an executable which +does not exist in the $PATH. It means there’s something wrong with the Cylc +installation, or something missing from the environment or system in which Cylc has been installed.

+

E.G. the following error:

+
FileNotFoundError: [Errno 2] No such file or directory: 'ssh'
+
+
+

Means that ssh is not installed or not in your $PATH.

+

See Non-Python Requirements for details on system requirements.

+
+
+

platform: <name> - initialisation did not complete

+

This means that Cylc was unable to install the required workflow files onto +a remote platform.

+

This either means that:

+
    +
  1. The platform is down (e.g. all login nodes are offline).

  2. +
  3. Or, there is a network problem (e.g. you cannot connect to the login nodes).

  4. +
  5. Or, the platform is not correctly configured.

  6. +
+

Check the scheduler log, you might find some stderr associated with this +message.

+

If your site has configured this platform for you, it’s probably (1) or (2), +check you are able to access the platform and notify the site administrator as +appropriate.

+

If you are in the progress of setting up a new platform, it’s probably (3). +You might want to check that you’ve configured the +global.cylc[platforms][<platform name>]install target correctly, +note that this defaults to the platform name if not explicitly set.

+
+
+

OperationalError: disk I/O error

+

This means that Cylc was unable to write to the database.

+

This error usually occurs if when you have exceeded your filesystem quota.

+

If a Cylc scheduler cannot write to the filesystem, it will shut down. Once +you’ve cleared out enough space for the workflow to continue you should be able +to safely restart it as you would normally using cylc play. The workflow +will continue from where it left off.

+
+
+

socket.gaierror

+

This usually means that a host could not be found on the network. The likely +cause is DNS configuration.

+

Cylc is a distributed system so needs to be able to identify the hosts it has +been configured to use (e.g. the servers where you run Cylc workflows or any +login nodes you submit jobs to). +Cylc expects each host to have a unique and stable fully qualified domain name +(FQDN) and to be identifiable from other hosts on the network using this name.

+

I.e., If a host identifies itself with an FQDN, then we should be able to look it +from another host by this FQDN. If we can’t, then Cylc can’t tell which host is +which and will not be able to function properly.

+

If the FQDN of a host is reported differently from different hosts on the +network, then Cylc commands will likely fail. To fix the issue, ensure that the +DNS setup is consistent.

+

Sometimes we do not have control over the platforms we use and it is not +possible to compel system administrators to address these issues. If this is +the case, you can fall back to IP address based host identification which may +work (i.e. use IP addresses rather than host names, which makes logs less human +readable). As a last resort you can also hard-code the host name for each host.

+

For more information, see +global.cylc[scheduler][host self-identification].

+
+
+

failed/XCPU

+

XCPU is the signal that most batch systems will use when a job hits its +execution time limit.

+

Use flow.cylc[runtime][<namespace>]execution time limit to +increase this limit.

+
+
+

Cannot determine whether workflow is running on <host>

+

When Cylc runs a workflow, it creates a contact file which tells us on +which host and port it can be contacted.

+

If the scheduler cannot be contacted, Cylc will attempt to check whether the +process is still running to ensure it hasn’t crashed.

+

If you are seeing this error message, it means that Cylc was unable to +determine whether the workflow is running. Likely cause:

+
    +
  • SSH issues.

  • +
  • Network issues.

  • +
  • Cylc server is down.

  • +
+

It’s possible that this check might not work correctly in some containerised +environments. If you encounter this issue in combination with containers, +please let us know.

+
+
+
+

Debugging Workflow Configurations

+
+

Cylc Debugging Utilities

+
+

See also

+

Cheat Sheet

+
+

Cylc comes with a number of utilities designed to allow inspection of +workflows:

+
+
cylc view

Prints workflow configurations before full parsing by Cylc. This +can include Jinja2 (use -j) +or Empy template processing.

+

Include files can be inlined (use -i).

+
+
cylc config

Prints all or part of the workflow configuration after Cylc has parsed the file +and expanded the runtime inheritance hierarchy. For example:

+
[runtime]
+    [[root]]
+        execution time limit = PT5S
+    [[FAMILY]]
+        pre-script = sleep 15
+    [[foo, bar]]
+        script = echo 'Hello'
+    [[bar]]
+        inherit = FAMILY
+        post-script = echo 'World'
+
+
+

would be shown as (revealing in this example why task bar +always fails):

+
[runtime]
+    [[root]]
+        execution time limit = PT5S
+    [[FAMILY]]
+        execution time limit = PT5S
+        pre-script = sleep 15
+    [[foo]]
+        execution time limit = PT5S
+        script = echo 'Hello'
+    [[bar]]
+        execution time limit = PT5S
+        pre-script = sleep 15
+        script = echo 'Hello'
+        inherit = FAMILY
+        post-script = echo 'World'
+
+
+
+
cylc lint
    +
  1. Checks the config against the Style Guidelines.

  2. +
  3. Looks for deprecated Cylc 7 configurations and recommends +Cylc 8 configurations to replace them.

  4. +
+
+

See also

+

Linting

+
+
+
+

cylc validate

+
+

Validates the workflow configuration.

+
+

See also

+

Validation

+
+
+
+
+

See what the Jinja2 is doing

+

It can sometimes be difficult to understand what Jinja2 +templating is doing to a workflow configuration.

+

cylc view --process (or -p) shows you what the +configuration will look like after Jinja2 processing.

+

For example:

+
{% for n in my_function(3) %}
+    R/1983/P{{n}}Y = cicada_{{n}}[-P{{n}}Y] => cicada_{{n}}
+{% endfor %}
+
+
+

is much easier to understand as:

+
R/1983/P2Y = cicada_2[-P2Y] => cicada_2
+R/1983/P3Y = cicada_3[-P3Y] => cicada_3
+R/1983/P5Y = cicada_5[-P5Y] => cicada_5
+
+
+

If you have installed and played a workflow +(even using play --pause) this processed content +is shown in log/config/flow-processed.cylc.

+
+
+
+

Getting Help

+

If your site has deployed and configured Cylc for you and your issue appears +related to the platforms you are using or the Cylc setup, please contact your +site’s administrator.

+

For general Cylc issues, create a post on the Cylc Discourse forum. +Please include any relevant error messages, workflow configuration and sections +of logs to help us debug your issue.

+

For Cylc / plugin development issues, you might prefer to contact us on the +developer’s chat.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/writing-workflows/configuration.html b/nightly_8.4/html/user-guide/writing-workflows/configuration.html new file mode 100644 index 00000000000..ca1ae77c5de --- /dev/null +++ b/nightly_8.4/html/user-guide/writing-workflows/configuration.html @@ -0,0 +1,705 @@ + + + + + + + Workflow Configuration — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Workflow Configuration

+
+

The flow.cylc File

+

Cylc workflows are defined in flow.cylc files that specify the +tasks to be managed by the Cylc scheduler, the dependencies between them, +and the schedules to run them to.

+

The .cylc file syntax is described in the File Format Reference.

+

The configurations you can use are documented in Workflow Configuration.

+

Cylc also supports two template processors for use in the flow.cylc file:

+ +
+
+

Workflow Configuration Directories

+

A Cylc source directory contains:

+
+
flow.cylc

The file which configures the workflow.

+
+
bin/ (optional)

A directory for scripts and executables used by workflow tasks. It is +added to $PATH in job environments.

+

Jobs can also run scripting defined in the flow.cylc file, +executables installed to user-defined locations of the workflow run +directory, and external executables.

+
+
lib/python/ (optional)

A directory for Python modules. It is added to $PYTHONPATH in +the scheduler and job execution environments. It can be used by:

+ +
+
+

Other files and folders may be placed in the source directory too: +documentation, configuration files, etc. When the workflow is installed these will be copied over to the run directory.

+
+

Note

+

If your workflow needs to create or install scripts or executables at runtime +and you don’t want Cylc to delete them on re-installation, you can use +equivalent directories in the Workflow Share Directories.

+
+
+
+

Understanding Code in Workflow Configurations

+

A workflow configuration is not executable code. It configures the scheduler +program to run your workflow. A flow.cylc file may contain:

+
    +
  • Embedded Python-like Jinja2 or EmPy templating code, such as +{% set PLANET = "earth" %}

  • +
  • Bash shell variable assignments and scripting, such as +script = "run-model.exe /path/to/data"

  • +
+

Jinja2 (or EmPy) templating code gets executed as a preprocessing step, to +programmatically generate the workflow configuration for the scheduler. +To see the result after template processing:

+
# print the workflow configuration, processed but not parsed:
+$ cylc view --process <workflow-id>
+
+# print the workflow configuration, processed and parsed:
+$ cylc config <workflow-id>
+
+
+

The scheduler does not interpret shell syntax, but certain string-valued +config items may contain shell code that gets written verbatim to job scripts, +to be executed by the running job.

+

Some things to be aware of:

+
    +
  • Jinja2 code is evaluated once when the workflow is started.

  • +
  • Jinja2 code can only reference Jinja2 variables, not Cylc config items.

  • +
  • Jinja2 (like Python) has its own syntax for reading environment variables.

  • +
  • Jinja2 code that reads the environment or the filesystem will do so +during config file parsing on the scheduler run host, not on job hosts. +Beware of doing this in task definitions - do you want the scheduler +environment to affect shell code that runs in the job environment?

  • +
  • Shell code destined for the job script can read the environment or +access the filesystem as the job runs on the job host, not on the +scheduler host.

  • +
+
+
+

Syntax Highlighting For Workflow Configuration

+

Cylc provides syntax plugins for the following editors:

+
+
Atom

install the language-cylc extension.

+
+
Emacs

The syntax file can be obtained from the Cylc library by +running the following command +cylc get-resources syntax/cylc-mode.el . +installation instructions are at the top of the file.

+
+
Gedit

The syntax file can be obtained from the Cylc library by +running the following command +cylc get-resources syntax/cylc.lang . +installation instructions are at the top of the file.

+
+
Kate

The syntax file can be obtained from the Cylc library by +running the following command +cylc get-resources syntax/cylc.xml . +installation instructions are at the top of the file.

+
+
PyCharm

Install the Cylc.tmbundle.

+
+
Vim

The syntax file can be obtained from the Cylc library by +running the following command +cylc get-resources syntax/cylc.vim . +installation instructions are at the top of the file.

+
+
Visual Studio Code

Install the vscode-cylc extension.

+
+
Sublime Text 3

Install the Cylc.tmbundle.

+
+
TextMate

Install the Cylc.tmbundle.

+
+
WebStorm

Install the Cylc.tmbundle.

+
+
Nano

The syntax file can be obtained from the Cylc library by +running the following command +cylc get-resources syntax/cylc.nanorc ~/.config/nano +installation instructions are at the top of the file.

+
+
+
+
+

Gross File Structure

+

Cylc flow.cylc files consist of configuration items grouped under +several top level section headings:

+
+
[meta]

Information about the workflow e.g. title and description.

+
+
[scheduler]

Non task-specific workflow configuration.

+
+
[task parameters]

Parameters for use when defining graphs and tasks. +See Task Parameters.

+
+
[scheduling]

Determines when tasks are ready to run.

+
    +
  • special scheduling constraints e.g. +external triggers.

  • +
  • the dependency graph, which defines the relationships +between tasks

  • +
+
+
[runtime]

Determines how, where, and what to execute when tasks are ready

+
    +
  • script, environment, job submission, remote hosting, etc.

  • +
  • workflow-wide defaults in the root family

  • +
  • a nested family hierarchy with common properties +inherited by related tasks

  • +
+
+
+
+
+

Validation

+

The cylc validate command evaluates the flow.cylc file +against a specification that defines all legal entries, values and options. +It also performs some integrity checks designed to catch certain configuration +issues and impossible scheduling constraints.

+

These checks are also performed by cylc play before starting a workflow.

+

All legal entries are documented in the flow.cylc reference.

+

If a flow.cylc file uses include-files cylc view will +show an inlined copy of the workflow with correct line numbers.

+
+
+

Linting

+

The cylc lint command checks code style, deprecated syntax and other +issues in Cylc configuration files.

+
+

See also

+

How to configure Cylc lint at project level +using a pyproject.toml.

+
+
+

cylc lint

+

Cylc configuration linter.

+

Checks code style, deprecated syntax and other issues.

+

Individual errors can be ignored using the # noqa line comment. +It is good practice to specify specific errors you wish to ignore using +# noqa: S002 S007 U999

+
+

Style

+
+
S001
+

Use multiple spaces, not tabs

+
+
+
S002
+

Item not indented.

+
+
+
S003
+

Top level sections should not be indented.

+
+
+
S004
+

Second level sections should be indented exactly 4 spaces.

+
+
+
S005
+

Third level sections should be indented exactly 8 spaces.

+
+
+
S006
+

trailing whitespace.

+
+
+
S007
+

Family name contains lowercase characters.

+
+
+
S008
+

jinja2 found: no shebang (#!jinja2)

+
+
+
S009
+

Host Selection Script may be redundant with platform

+
+
+
S010
+

Using backticks to invoke subshell is deprecated

+
+
+
S011
+

Cylc will process commented Jinja2!

+
+
+
S012
+

line > <max_line_len> characters. Max line length set in pyproject.toml (default 130)

+
+
+
S013
+

Items should be indented in 4 space blocks.

+
+
+
S014
+

Using [runtime][TASK]execution time limit is recommended in preference to using job runner directives because it allows Cylc to retain awareness of whether the job should have finished, even if contact with the target job runner’s platform has been lost.

+
+
The following directives are considered equivelent to execution time limit:
    +
  • wall_clock_limit (loadleveler)

  • +
  • -W (lsf)

  • +
  • -l walltime (moab)

  • +
  • -l walltime (pbs)

  • +
  • -l walltime (pbs_multi_cluster)

  • +
  • -l h_rt (sge)

  • +
  • --time (slurm)

  • +
  • --time (slurm_packjob)

  • +
+
+
+
+

Note

+

Using execution time limit which is automatically translated to the job runner’s timeout directive can make your workflow more portable.

+
+
+
+
+

7 to 8 upgrades

+
+
U001
+

[scheduling][dependencies][<recurrence>]graph = -> [scheduling][graph]<recurrence> = ([dependencies] detected)

+
+
+
U002
+

[scheduling][dependencies][<recurrence>]graph = -> [scheduling][graph]<recurrence> = (graph = detected)

+
+
+
U003
+

settings in [runtime][<namespace>][remote] have been moved to [runtime][<namespace>] and global.cylc[platforms][<platforms name>]

+
+
+
U004
+

settings in [runtime][<namespace>][job] have been moved to [runtime][<namespace>] and global.cylc[platforms][<platforms name>]

+
+
+
U005
+

flow.cylc[runtime][<namespace>][job]batch system -> global.cylc[platforms][<platform name>]job runner

+
+
+
U006
+

Using backticks to invoke subshell will fail at Cylc 8.

+
+
+
U007
+

Use built in platform selection instead of rose host-select.

+
+
+
U008
+

Suicide triggers are not required at Cylc 8.

+
+
+
U009
+

This line contains an obsolete Cylc CLI command.

+
+
+
U010
+

rose suite-hook is deprecated at Rose 2,

+
+
+
U011
+

Leading zeros are no longer valid for Jinja2 integers.

+
+
+
U012
+

The following environment variables are deprecated:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Deprecated Variable

New Variable

CYLC_SUITE_HOST

CYLC_WORKFLOW_HOST

CYLC_SUITE_OWNER

CYLC_WORKFLOW_OWNER

CYLC_SUITE_SHARE_DIR

CYLC_WORKFLOW_SHARE_DIR

CYLC_SUITE_SHARE_PATH

CYLC_WORKFLOW_SHARE_PATH

CYLC_SUITE_NAME

CYLC_WORKFLOW_ID

CYLC_SUITE_LOG_DIR

CYLC_WORKFLOW_LOG_DIR

CYLC_SUITE_INITIAL_CYCLE_POINT

CYLC_WORKFLOW_INITIAL_CYCLE_POINT

CYLC_SUITE_INITIAL_CYCLE_TIME

CYLC_WORKFLOW_INITIAL_CYCLE_TIME

CYLC_SUITE_FINAL_CYCLE_POINT

CYLC_WORKFLOW_FINAL_CYCLE_POINT

CYLC_SUITE_FINAL_CYCLE_TIME

CYLC_WORKFLOW_FINAL_CYCLE_TIME

CYLC_SUITE_WORK_DIR

CYLC_WORKFLOW_WORK_DIR

CYLC_SUITE_UUID

CYLC_WORKFLOW_UUID

CYLC_SUITE_RUN_DIR

CYLC_WORKFLOW_RUN_DIR

+
+
+
U013
+

The following environment variables are obsolete:

+
+
    +
  • CYLC_SUITE_DEF_PATH_ON_SUITE_HOST

  • +
  • CYLC_SUITE_DEF_PATH

  • +
+
+
+
+
U014
+

For datetime operations in task scripts:

+
+
    +
  • Use isodatetime instead of rose date

  • +
  • Use isodatetime ref instead of rose date -c for the current cycle point

  • +
+
+
+
+
U015
+
+
The following template variables, mostly used in event handlers,are deprecated, and should be replaced:
    +
  • suite ⇒ workflow

  • +
  • suite_uuid ⇒ uuid

  • +
  • batch_sys_name ⇒ job_runner_name

  • +
  • batch_sys_job_id ⇒ job_id

  • +
  • user@host ⇒ platform_name

  • +
  • task_urlURL (if set in [meta]URL)

  • +
  • workflow_urlworkflow_URL (if set in [runtime][<namespace>][meta]URL)

  • +
+
+
+
+
+
U016
+

It is no longer necessary to configure the environment variables CYLC_VERSION, ROSE_VERSION or FCM_VERSION.

+
+
+
+

Auto Generated 7 to 8 upgrades

+

U998 and U999 represent automatically generated sets of deprecations and upgrades.

+
    +
  • [runtime][__MANY__][workflow state polling]run-dir is now [runtime][__MANY__][workflow state polling]alt-cylc-run-dir

  • +
  • [cylc][authentication] is not available at Cylc 8

  • +
  • [cylc]include at start-up is not available at Cylc 8

  • +
  • [cylc]exclude at start-up is not available at Cylc 8

  • +
  • [cylc]log resolved dependencies is not available at Cylc 8

  • +
  • [cylc]required run mode is not available at Cylc 8

  • +
  • [cylc]health check interval is not available at Cylc 8

  • +
  • [runtime][__MANY__][events]mail retry delays is not available at Cylc 8

  • +
  • [runtime][__MANY__]extra log files is not available at Cylc 8

  • +
  • [runtime][__MANY__][job]shell is not available at Cylc 8

  • +
  • [runtime][__MANY__][remote]suite definition directory is not available at Cylc 8

  • +
  • [cylc]abort if any task fails is not available at Cylc 8

  • +
  • [cylc]disable automatic shutdown is not available at Cylc 8

  • +
  • [cylc][environment] is not available at Cylc 8

  • +
  • [cylc][reference test] is not available at Cylc 8

  • +
  • [cylc][simulation]disable suite event handlers is not available at Cylc 8

  • +
  • [cylc][simulation] is not available at Cylc 8

  • +
  • [visualization] is not available at Cylc 8

  • +
  • [scheduling]spawn to max active cycle points is not available at Cylc 8

  • +
  • [cylc]task event mail interval is now [cylc][mail]task event batch interval

  • +
  • [runtime][__MANY__][suite state polling] is now [runtime][__MANY__][workflow state polling]

  • +
  • [runtime][__MANY__][workflow state polling]host is not available at Cylc 8

  • +
  • [runtime][__MANY__][workflow state polling]user is not available at Cylc 8

  • +
  • [cylc][parameters] is now [task parameters]

  • +
  • [cylc][parameter templates] is now [task parameters][templates]

  • +
  • [cylc][events]mail to is now [cylc][mail]to

  • +
  • [cylc][events]mail from is now [cylc][mail]from

  • +
  • [cylc][events]mail footer is now [cylc][mail]footer

  • +
  • [runtime][__MANY__][events]mail to is now [runtime][__MANY__][mail]to

  • +
  • [runtime][__MANY__][events]mail from is now [runtime][__MANY__][mail]from

  • +
  • [cylc][events]mail smtp is not available at Cylc 8

  • +
  • [runtime][__MANY__][events]mail smtp is not available at Cylc 8

  • +
  • [scheduling]max active cycle points is now [scheduling]runahead limit

  • +
  • [scheduling]hold after point is now [scheduling]hold after cycle point

  • +
  • [cylc][events]timeout is now [cylc][events]stall timeout

  • +
  • [cylc][events]abort on timeout is now [cylc][events]abort on stall timeout

  • +
  • [cylc][events]inactivity is now [cylc][events]inactivity timeout

  • +
  • [cylc][events]abort on inactivity is now [cylc][events]abort on inactivity timeout

  • +
  • [cylc][events]startup handler is now [cylc][events]startup handlers

  • +
  • [cylc][events]shutdown handler is now [cylc][events]shutdown handlers

  • +
  • [cylc][events]timeout handler is now [cylc][events]stall timeout handlers

  • +
  • [cylc][events]stalled handler is now [cylc][events]stall handlers

  • +
  • [cylc][events]aborted handler is now [cylc][events]abort handlers

  • +
  • [cylc][events]inactivity handler is now [cylc][events]inactivity timeout handlers

  • +
  • [runtime][__MANY__][events]expired handler is now [runtime][__MANY__][events]expired handlers

  • +
  • [runtime][__MANY__][events]late handler is now [runtime][__MANY__][events]late handlers

  • +
  • [runtime][__MANY__][events]submitted handler is now [runtime][__MANY__][events]submitted handlers

  • +
  • [runtime][__MANY__][events]started handler is now [runtime][__MANY__][events]started handlers

  • +
  • [runtime][__MANY__][events]succeeded handler is now [runtime][__MANY__][events]succeeded handlers

  • +
  • [runtime][__MANY__][events]failed handler is now [runtime][__MANY__][events]failed handlers

  • +
  • [runtime][__MANY__][events]submission failed handler is now [runtime][__MANY__][events]submission failed handlers

  • +
  • [runtime][__MANY__][events]warning handler is now [runtime][__MANY__][events]warning handlers

  • +
  • [runtime][__MANY__][events]critical handler is now [runtime][__MANY__][events]critical handlers

  • +
  • [runtime][__MANY__][events]retry handler is now [runtime][__MANY__][events]retry handlers

  • +
  • [runtime][__MANY__][events]submission retry handler is now [runtime][__MANY__][events]submission retry handlers

  • +
  • [runtime][__MANY__][events]execution timeout handler is now [runtime][__MANY__][events]execution timeout handlers

  • +
  • [runtime][__MANY__][events]submission timeout handler is now [runtime][__MANY__][events]submission timeout handlers

  • +
  • [runtime][__MANY__][events]custom handler is now [runtime][__MANY__][events]custom handlers

  • +
  • [cylc][events]abort on stalled is not available at Cylc 8

  • +
  • [cylc][events]abort if startup handler fails is not available at Cylc 8

  • +
  • [cylc][events]abort if shutdown handler fails is not available at Cylc 8

  • +
  • [cylc][events]abort if timeout handler fails is not available at Cylc 8

  • +
  • [cylc][events]abort if inactivity handler fails is not available at Cylc 8

  • +
  • [cylc][events]abort if stalled handler fails is not available at Cylc 8

  • +
  • [cylc] is now [scheduler]

  • +
+
+
+
+

Configure cylc lint at project level

+

You can configure cylc lint for each workflow using a +pyproject.toml file.

+

To define settings for cylc lint use a [tool.cylc.lint] section. +Within the [tool.cylc.lint] section you may define the following:

+
+
rulesets

A list of rulesets to use.

+

Allowed values: '728', 'style', 'all'.

+

(You can override this on the command line.)

+
+
ignore

Individual rules to ignore: A list of rule codes, such as S007.

+
+
exclude

A list of files or glob patterns for files which will not be checked.

+
+
max-line-length

Set longest line length to permit in Cylc configs for this project.

+

Default: 130.

+
+
+
+

Note

+
+

Changed in version 8.3.0: The [cylc-lint] section has been deprecated in favour of +[tool.cylc.lint].

+
+
+

An example pyproject.toml might look like this:

+
[tool.cylc.lint]
+# Enforce a line limit of 99 chars
+max-line-length = 99
+
+# Ignore style [S] rule 007 (It's good practice comment with a reason)
+ignore = ['S007']   # Family names start with lowercase in this workflow
+
+# Don't check files matching these globs
+exclude = ['history/*.old.cylc', 'someother.cylc']
+
+# By default check for style
+rulesets = ['style']
+
+[some-other-section]
+# Cylc lint won't pay any attention to this.
+
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/writing-workflows/empy.html b/nightly_8.4/html/user-guide/writing-workflows/empy.html new file mode 100644 index 00000000000..eaa1bb105ec --- /dev/null +++ b/nightly_8.4/html/user-guide/writing-workflows/empy.html @@ -0,0 +1,282 @@ + + + + + + + EmPy — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ +
+
+ +
+

EmPy

+

Cylc also supports the EmPy template processor in workflow configurations. +Like Jinja2, EmPy provides variables, mathematical +expressions, loop control structures, conditional logic, etc., that gets +expanded to generate the final workflow configuration seen - which must must be +valid Cylc syntax. See EmPy documentation +for details of its templating features and how to use them.

+
+

Note

+

EmPy is not included in the standard Cylc installation. If installing +with pip run pip install cylc-flow[empy] to install it.

+
+

To enable EmPy place an empy hash-bang comment on the first line of +the flow.cylc file:

+
#!empy
+
+
+

As an example, here is the “cities” workflow from the previous section, +implemented with Empy instead of Jinja2.

+
#!EmPy
+[meta]
+    title = "EmPy city workflow example."
+    description = """
+        Illustrates use of variables and math expressions, and programmatic
+        generation of groups of related dependencies and runtime properties.
+    """
+
+[scheduler]
+    allow implicit tasks = True
+
+@{
+HOST = "SuperComputer"
+CITIES = 'NewYork', 'Philadelphia', 'Newark', 'Houston', 'SantaFe', 'Chicago'
+CITYJOBS = 'one', 'two', 'three', 'four'
+LIMIT_MINS = 20
+CLEANUP = True
+}
+
+[scheduling]
+    initial cycle point = 2011-08-08T12
+    [[graph]]
+@[ if CLEANUP ]
+        T23 = clean
+@[ end if ]
+        T00,T12 = """
+            setup => get_lbc & get_ic # foo
+@[ for CITY in CITIES ]@# comment
+            get_lbc => @(CITY)_one
+            get_ic => @(CITY)_two
+            @(CITY)_one & @(CITY)_two => @(CITY)_three & @(CITY)_four
+    @[ if CLEANUP ]
+            @(CITY)_three & @(CITY)_four => cleanup
+    @[ end if ]
+@[ end for ]
+        """
+[runtime]
+    [[on_@HOST ]]
+        [[[remote]]]
+            host = @HOST
+            # (remote cylc directory is set in site/user config for this host)
+        [[[directives]]]
+            wall_clock_limit = "00:@(LIMIT_MINS + 2):00,00:@(LIMIT_MINS):00"
+
+@[ for CITY in CITIES ]
+    [[ @(CITY) ]]
+        inherit = on_@(HOST)
+    @[ for JOB in CITYJOBS ]
+    [[ @(CITY)_@(JOB) ]]
+        inherit = @CITY
+    @[ end for ]
+@[ end for ]
+
+
+

For basic usage, the difference between Jinja2 and EmPy amounts to little more than +a different markup syntax. EmPy might be preferable, however, in cases needing +more complicated processing logic.

+

EmPy is a system for embedding Python expressions and statements in template +text. It makes the full power of Python language and its ecosystem easily +accessible from within the template. This might be desirable for several +reasons:

+
    +
  • No need to learn a different language just for writing template logic

  • +
  • Availability of lambda functions, lists, and dictionary comprehensions +can make template code smaller and more readable compared to Jinja2

  • +
  • Natural and straightforward integration with the Python package ecosystem

  • +
  • No two-language barrier between writing template logic and processing +extensions makes it easier to refactor and maintain the template code +as its complexity grows. Inline Python code can be gathered into subroutines +and eventually into separate modules and packages in a seamless manner.

  • +
+
+

Workflow files and Context Variables

+

The EmPy processor has the same access as Jinja2 to +workflow files and +workflow context variables.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/writing-workflows/external-triggers.html b/nightly_8.4/html/user-guide/writing-workflows/external-triggers.html new file mode 100644 index 00000000000..8f1c6b88f7d --- /dev/null +++ b/nightly_8.4/html/user-guide/writing-workflows/external-triggers.html @@ -0,0 +1,1216 @@ + + + + + + + External Triggers — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

External Triggers

+

External triggers allow tasks to trigger directly off of external events, which +is often preferable to implementing long-running polling tasks in the workflow. +The triggering mechanism described in this section is intended to replace the one +one documented in Push External Triggers (however, that one is a push +mechanism, whereas this one involves regular polling by the scheduler).

+

If you can write a Python function to check the status of an external +condition or event, the scheduler can call it at configurable +intervals until it reports success, at which point dependent tasks can trigger +and data returned by the function will be passed to the job environments of +those tasks. Functions can be written for triggering off of almost anything, +such as delivery of a new dataset, creation of a new entry in a database +table, or appearance of new data availability notifications in a message +broker.

+

Cylc has several built-in external trigger functions:

+ +

Trigger functions are normal Python functions, with certain constraints as +described below in Custom Trigger Functions.

+

External triggers are configured in the +flow.cylc[scheduling][xtriggers] section.

+
+

Built-in Clock Triggers

+

These are more transparent (exposed in the graph) and efficient (shared among +dependent tasks) than the older clock triggers described +in Clock Triggers.

+

Clock triggers, unlike other trigger functions, are executed synchronously in +the main process. The clock trigger function signature looks like this:

+
+
+cylc.flow.xtriggers.wall_clock.wall_clock(offset='PT0S', sequential=True)[source]
+

Trigger at a specific real “wall clock” time relative to the cycle point +in the graph.

+

Clock triggers, unlike other trigger functions, are executed synchronously +in the main process.

+
+
Parameters:
+
    +
  • offset (str) – ISO 8601 interval to wait after the cycle point is reached in real +time before triggering. May be negative, in which case it will +trigger before the real time reaches the cycle point.

  • +
  • sequential (bool) – Wall-clock xtriggers are run sequentially by default. +See Sequential Xtriggers for more details.

  • +
+
+
+
+

Changed in version 8.3.0: The sequential argument was added.

+
+
+ +

The offset argument is a datetime duration (PT1H is 1 +hour) relative to the dependent task’s cycle point (automatically passed to the +function via a second argument not shown above).

+

In the following workflow, task foo has a daily cycle point sequence, +and each task instance can trigger once the wallclock time has passed its +cycle point value by one hour:

+
[scheduling]
+    initial cycle point = 2018-01-01
+    [[xtriggers]]
+        clock_1 = wall_clock(offset=PT1H)
+    [[graph]]
+        P1D = "@clock_1 => foo"
+[runtime]
+    [[foo]]
+        script = run-foo.sh
+
+
+

Notice that the short label clock_1 is used to represent the +trigger function in the graph.

+

Argument keywords can be omitted if called in the right order, so the +clock_1 trigger can also be declared like this:

+
[[xtriggers]]
+    clock_1 = wall_clock(PT1H)
+
+
+

A zero-offset clock trigger does not need to be declared under +the [xtriggers] section:

+
[scheduling]
+    initial cycle point = 2018-01-01
+    [[graph]]
+         # zero-offset clock trigger:
+        P1D = "@wall_clock => foo"
+[runtime]
+    [[foo]]
+        script = run-foo.sh
+
+
+

However, when xtriggers are declared the name used must adhere to the following +rules:

+
+
+class cylc.flow.unicode_rules.XtriggerNameValidator[source]
+

The rules for valid xtrigger labels:

+
    +
  • can only contain: latin letters and numbers, _

  • +
  • cannot start with: _cylc

  • +
+
+ +
+
+

Built-in Workflow State Triggers

+

These can be used instead of the older workflow state polling tasks described +in Triggering Off Of Tasks In Other Workflows for inter-workflow triggering - i.e. to trigger local +tasks off of remote task statuses or messages in other workflows.

+

The workflow state trigger function signature looks like this:

+
+
+cylc.flow.xtriggers.workflow_state.workflow_state(workflow_task_id, offset=None, flow_num=None, is_trigger=False, is_message=False, alt_cylc_run_dir=None)[source]
+

Connect to a workflow DB and check a task status or output.

+

If the status or output has been achieved, return {True, result}.

+
+
Parameters:
+
    +
  • workflow_task_id (str) – ID (workflow//point/task:selector) of the target task.

  • +
  • offset (str | None) – Offset from cycle point as an ISO8601 or integer duration, +e.g. PT1H (1 hour) or P1 (1 integer cycle)

  • +
  • flow_num (int | None) – Flow number of the target task.

  • +
  • is_message (bool) – Interpret the task:selector as a task output message +(the default is a task status or trigger)

  • +
  • is_trigger (bool) – Interpret the task:selector as a task trigger name +(only needed if it is also a valid status name)

  • +
  • alt_cylc_run_dir (str | None) – Alternate cylc-run directory, e.g. for another user.

  • +
+
+
Returns:
+

(satisfied, result)

+
+
satisfied:

True if satisfied else False.

+
+
result:

Dict containing the keys:

+
    +
  • workflow

  • +
  • task

  • +
  • point

  • +
  • offset

  • +
  • status

  • +
  • message

  • +
  • trigger

  • +
  • flow_num

  • +
  • run_dir

  • +
+
+
+

+
+
Return type:
+

tuple

+
+
+
+

Changed in version 8.3.0: The workflow_task_id argument was introduced to replace the +separate workflow, point, task, status, and message +arguments (which are still supported for backwards compatibility). +The flow_num argument was added. The cylc_run_dir argument +was renamed to alt_cylc_run_dir.

+
+
+ +

The first argument identifies the target workflow, cycle, task, and status or +output trigger name. The function arguments mirror the arguments and options of +the cylc workflow-state command - see cylc workflow-state --help.

+

As a simple example, consider the following “upstream” +workflow (which we want to trigger off of):

+
[scheduler]
+    cycle point format = %Y
+[scheduling]
+    initial cycle point = 2005
+    final cycle point = 2015
+   [[graph]]
+      P1Y = "foo => bar"
+[runtime]
+   [[bar]]
+      script = sleep 10
+   [[foo]]
+      script = sleep 5; cylc message "data ready"
+      [[[outputs]]]
+          x = "data ready"
+
+
+

It must be installed and run under the name up, as referenced in the +“downstream” workflow that depends on it:

+
[scheduler]
+  cycle point format = %Y
+[scheduling]
+    initial cycle point = 2010
+    [[xtriggers]]
+         upstream = workflow_state("up//%(point)s/foo:x"):PT10S
+         clock_0 = wall_clock(offset=PT0H)
+   [[graph]]
+        P1Y = """
+            foo
+            @clock_0 & @upstream => FAM:succeed-all => blam
+        """
+[runtime]
+    [[root]]
+        script = sleep 5
+    [[foo, blam]]
+    [[FAM]]
+    [[f1,f2,f3]]
+        inherit = FAM
+
+
+

Try starting the downstream workflow first, then the upstream, and +watch what happens. +In each cycle point the @upstream trigger in the downstream workflow +waits on the task foo (with the same cycle point) in the upstream +workflow to emit the data ready message.

+

Some important points to note about this:

+
    +
  • The function call interval, which determines how often the scheduler +checks the clock, is optional. Here it is +PT10S (i.e. 10 seconds, which is also the default value).

  • +
  • The workflow_state trigger function, like the +cylc workflow-state command, must have read-access to the upstream +workflow’s public database.

  • +
  • The cycle point is supplied by a string template +%(point)s. The string templates available to trigger functions +arguments are described in Custom Trigger Functions).

  • +
+

The return value of the workflow_state trigger function looks like +this:

+
results = {
+    'workflow': workflow_id,
+    'task': task_name,
+    'point': cycle_point,
+    'status': task_status,  # or
+    'trigger': task_output_trigger,  # or
+    'message': task_output_message,
+    'flow_num': flow_num  # if given
+}
+return (satisfied, results)
+
+
+

The satisfied variable is boolean (value True or False, depending +on whether or not the trigger condition was found to be satisfied). The +results dictionary contains the names and values of the +target workflow state parameters. Each name gets qualified with the +unique trigger label (“upstream” here) and passed to the environment of +dependent tasks (the members of the FAM family in this case). +To see this, take a look at the job script for one of the downstream tasks:

+
% cylc cat-log -f j dn//2011/f22011
+...
+cylc__job__inst__user_env() {
+    # TASK RUNTIME ENVIRONMENT:
+    export upstream_workflow upstream_cylc_run_dir upstream_offset \
+      upstream_message upstream_status upstream_point upstream_task
+    upstream_workflow="up"
+    upstream_task="foo"
+    upstream_point="2011"
+    upstream_status="succeeded"
+}
+...
+
+
+
+

Note

+

The dependent task has to know the name of the xtrigger that it +depends on - “upstream” in this case - in order to use this information. +However the name could be given to the task environment in the workflow +configuration.

+
+
+
+

Sequential Xtriggers

+

Parentless tasks (which don’t depend on other tasks upstream in the graph) +naturally spawn out to the runahead limit. This may cause UI clutter, and +unnecessary xtrigger checking if the xtriggers would only be satisfied in +order.

+

You can use sequential xtriggers to avoid this problem: the next instance +of a task (i.e., at the next cycle point) that depends on a sequential xtrigger +will not be spawned until the previous xtrigger is satisfied. The +wall_clock xtrigger is sequential by default.

+

A trigger can be set as sequential in any or all of the following ways.

+

By setting the workflow-wide flow.cylc[scheduling]sequential xtriggers +(defaults to False) and/or keyword argument sequential to True/False in +the xtrigger declaration:

+
[scheduler]
+  cycle point format = %Y
+[scheduling]
+    initial cycle point = 2010
+    sequential xtriggers = True
+    [[xtriggers]]
+         upstream = workflow_state("up//%(point)s/foo:x"):PT10S
+         clock_0 = wall_clock(offset=PT0H, sequential=False)
+   [[graph]]
+        P1Y = """
+            @clock_0 => foo
+            @clock_0 & @upstream => FAM:succeed-all => blam
+        """
+[runtime]
+    [[root]]
+        script = sleep 5
+    [[foo, blam]]
+    [[FAM]]
+    [[f1,f2,f3]]
+        inherit = FAM
+
+
+

When implementing a custom xtrigger, you can +set the default for the sequential keyword argument in the xtrigger function +definition itself:

+
def my_xtrigger(my_in, my_out, sequential=True)
+
+
+

Xtrigger declaration takes precedence over function, and function over workflow +wide setting. So the above workflow definition would read:

+
    +
  • foo spawns out to the runahead limit.

  • +
  • FAM spawns only when @upstream is satisfied.

  • +
  • All associated xtriggers are checked and, as expected, their satisfaction +is a prerequisite to task readiness.

  • +
+
+
+

Custom Trigger Functions

+

Trigger functions are just normal Python functions, with a few special +properties:

+
    +
  • They must:

    +
      +
    • Be defined in a module with the same name as the function, unless +provided using the cylc.xtriggers entry point;

    • +
    • be compatible with the same Python version that runs the scheduler +(see Distribution requirements for the latest version specification).

    • +
    +
  • +
  • They can be located either:

    +
      +
    • In <workflow-dir>/lib/python/;

    • +
    • Anywhere in your $CYLC_PYTHONPATH;

    • +
    • Defined using the cylc.xtriggers entry point for an installed +package - see Developing xtrigger plugins

    • +
    +
  • +
  • They can take arbitrary positional and keyword arguments +(except sequential, which is reserved - see Sequential Xtriggers)

  • +
  • Workflow and task identity, and cycle point, can be passed to trigger +functions by using string templates in function arguments (see below)

  • +
  • Integer, float, boolean, and string arguments will be recognized and +passed to the function as such

  • +
  • If a trigger function depends on files or directories (for example) +that might not exist when the function is first called, just return

  • +
  • The module can also provide a validate function for checking configured +arguments / keyword arguments, see +Xtrigger Validation Functions for details.

  • +
+
+

Note

+

Trigger functions cannot store data Pythonically between invocations +because each call is executed in an independent process in the process +pool. If necessary the filesystem can be used for this purpose.

+
+
+

Templates variables for string replacement in xtrigger functions.

+

The following string templates are available for use, if the trigger +function needs any of this information, in function arguments in the +workflow configuration.

+
[scheduling]
+    initial cycle point = now
+    [[xtriggers]]
+        my_xtrigger = my_xtrigger_fcn('%(workflow)s', '%(point)s')
+
+
+

For an explanation of the substitution syntax, see +String Formatting Operations in the Python documentation.

+
+
+point
+

The cycle point of the dependent task.

+
+ +
+
+debug
+

True if Cylc is being run in debug mode (–debug, -vv).

+
+ +
+
+workflow_run_dir
+

The path to the workflow run directory.

+
+ +
+
+workflow_share_dir
+

The path to the workflow share directory.

+
+ +
+
+id
+

The ID of the dependent task.

+
+ +
+
+name
+

The name of the dependent task.

+
+ +
+
+user_name
+

The user account under which the workflow is being run.

+
+ +
+
+workflow
+

The workflow ID.

+
+ +
+
+workflow_name
+

The workflow ID.

+
+

Deprecated since version 8.0.0: Use workflow instead.

+
+
+ +
+
+suite_name
+

The workflow ID.

+
+

Deprecated since version 8.0.0: Use workflow instead.

+
+
+ +
+
+suite_run_dir
+

The path to the workflow run directory.

+
+

Deprecated since version 8.0.0: Use workflow_run_dir instead.

+
+
+ +
+
+suite_share_dir
+

The path to the workflow share directory.

+
+

Deprecated since version 8.0.0: Use workflow_share_dir instead.

+
+
+ +
+ +

Function return values should be as follows:

+
    +
  • if the trigger condition is not satisfied:

    +
      +
    • return (False, {})

    • +
    +
  • +
  • if the trigger condition is satisfied:

    +
      +
    • return (True, results)

    • +
    +
  • +
+

where results is an arbitrary dictionary of information to be passed to +dependent tasks, which in terms of format must:

+
    +
  • be flat (non-nested);

  • +
  • contain only keys which are +valid as environment variable names.

  • +
+

See Built-in Workflow State Triggers for an example of one such +results dictionary and how it gets processed by the workflow.

+

The scheduler manages trigger functions as follows:

+
    +
  • they are called asynchronously in the process pool +- (except for clock triggers, which are called from the main process)

  • +
  • they are called repeatedly on a configurable interval, until satisfied +- the call interval defaults to PT10S (10 seconds) +- repeat calls are not made until the previous call has returned

  • +
  • they are subject to the normal process pool command time out - if they +take too long to return, the process will be killed

  • +
  • they are shared for efficiency: a single call will be made for all +triggers that share the same function signature - i.e.the same function +name and arguments

  • +
  • their return status and results are stored in the workflow DB and persist across +workflow restarts

  • +
  • their stdout, if any, is redirected to stderr and will be visible in +the workflow log in debug mode (stdout is needed to communicate return values +from the sub-process in which the function executes)

  • +
+
+
+

Xtrigger Validation Functions

+

The arguments you call the xtrigger function with are automatically validated +against the function signature, however, you might wish to add extra validation +logic to your custom xtrigger, e.g. to check argument types or values.

+

If a function named validate is present alongside the xtrigger in its +module, it will be automatically called with a dictionary of all the arguments +passed to the xtrigger function in the workflow config. It should raise a +cylc.flow.exceptions.WorkflowConfigError exception if an error is +detected.

+

The cylc.flow.xtriggers.xrandom xtrigger module contains an example +of an xtrigger validation function.

+
+

Toy Examples

+
+

echo

+

The trivial built-in echo function takes any number of positional +and keyword arguments (from the workflow configuration) and simply prints +them to stdout, and then returns False (i.e. trigger condition not +satisfied).

+
+
+cylc.flow.xtriggers.echo.echo(*args, **kwargs)[source]
+

Print arguments to stdout, return kwargs[‘succeed’] and kwargs.

+

This may be a useful aid to understanding how xtriggers work.

+
+
Parameters:
+
    +
  • succeed – Set the success of failure of this xtrigger.

  • +
  • *args – Print to stdout.

  • +
  • **kwargs – Print to stdout, and return as output.

  • +
+
+
Returns:
+

(True/False, kwargs)

+
+
Return type:
+

Tuple

+
+
+

Examples

+
>>> echo('Breakfast Time', succeed=True, egg='poached')
+echo: ARGS: ('Breakfast Time',)
+echo: KWARGS: {'succeed': True, 'egg': 'poached'}
+(True, {'succeed': True, 'egg': 'poached'})
+
+
+
+ +

Here’s an example echo trigger workflow:

+
[scheduling]
+    initial cycle point = now
+    [[xtriggers]]
+        echo_1 = echo(hello, 99, qux=True, point=%(point)s, foo=10)
+    [[graph]]
+        PT1H = "@echo_1 => foo"
+[runtime]
+    [[foo]]
+        script = exit 1
+
+
+

To see the result, run this workflow in debug mode and take a look at the +workflow log (or run cylc play --debug --no-detach <workflow> and watch +your terminal).

+
+
+

xrandom

+

The built-in xrandom function sleeps for a configurable amount of +time (useful for testing the effect of a long-running trigger function +- which should be avoided) and has a configurable random chance of +success. The function signature is:

+
+
+cylc.flow.xtriggers.xrandom.xrandom(percent, secs=0, _=None)[source]
+

Random xtrigger, with configurable sleep and percent success.

+

Sleep for sec seconds, and report satisfied with percent +likelihood.

+

The _ argument is not used in the function code, but can be used to +specialize the function signature to cycle point or task.

+
+
Parameters:
+
    +
  • percent (float) – Percent likelihood of passing.

  • +
  • secs (int) – Seconds to sleep before starting the trigger.

  • +
  • _ (Any | None) – Used to allow users to specialize the trigger with extra +parameters.

  • +
+
+
Returns:
+

(satisfied, results)

+
+
satisfied:

True if satisfied else False.

+
+
results:

A dictionary containing the following keys:

+
+
COLOR

A random colour (e.g. red, orange, …).

+
+
SIZE

A random size (e.g. small, medium, …).

+
+
+
+
+

+
+
Return type:
+

tuple

+
+
+

Examples

+

If the percent is zero, it returns that the trigger condition was +not satisfied, and an empty dictionary.

+
>>> xrandom(0, 0)
+(False, {})
+
+
+

If the percent is not zero, but the random percent success is not met, +then it also returns that the trigger condition was not satisfied, +and an empty dictionary.

+
>>> import sys
+>>> mocked_random = lambda: 0.3
+>>> sys.modules[__name__].random = mocked_random
+>>> xrandom(15.5, 0)
+(False, {})
+
+
+

Finally, if the percent is not zero, and the random percent success is +met, then it returns that the trigger condition was satisfied, and a +dictionary containing random colour and size as result.

+
>>> import sys
+>>> mocked_random = lambda: 0.9
+>>> sys.modules[__name__].random = mocked_random
+>>> mocked_randint = lambda x, y: 1
+>>> sys.modules[__name__].randint = mocked_randint
+>>> xrandom(99.99, 0)
+(True, {'COLOR': 'orange', 'SIZE': 'small'})
+
+
+
+ +
+
+cylc.flow.xtriggers.xrandom.validate(args)[source]
+

Validate the args that xrandom is called with.

+

Cylc calls this function automatically when parsing the workflow.

+

Here we specify the rules for args are:

+
    +
  • percent: Must be 0 ≤ x ≤ 100

  • +
  • secs: Must be an integer.

  • +
+
+
Parameters:
+

args (Dict[str, Any])

+
+
+
+ +

An example xrandom trigger workflow:

+
[scheduling]
+    cycling mode = integer
+    initial cycle point = 1
+    final cycle point = 5
+    [[xtriggers]]
+        # Called once for all dependent tasks (all cycles).
+        x1 = xrandom(percent=25, secs=2):PT5S
+        # Called once per dependent task name (all cycles).
+        x2 = xrandom(percent=25, secs=2, _=%(name)s):PT5S
+        # Called once per cycle for all dependent tasks.
+        x3 = xrandom(percent=25, secs=2, _=%(point)s):PT5S
+    [[graph]]
+        P1 = """
+            # all instances of foo and bar should trigger at once, together
+            @x1 => foo & bar
+
+            # all instances of cat should trigger at once, and separately, all
+            # instances of baz should trigger at once.
+            @x2 => cat & dog
+
+            # each instance of qux should trigger separately
+            @x3 => qux
+
+            # Result:
+            # - x1 should return True once, and not be called again.
+            # - x2 should return True twice, and not be called again.
+            # - x3 should return True five times, and not be called again.
+            # i.e. 8 True returns in the 5-cycle workflow run.
+        """
+[runtime]
+    [[root]]
+        script = sleep 5
+    [[foo, bar, cat, dog, qux]]
+
+
+
+
+
+
+

Current Limitations

+

The following issues may be addressed in future Cylc releases:

+
    +
  • trigger labels cannot currently be used in conditional (OR) expressions +in the graph; attempts to do so will fail validation.

  • +
  • aside from the predefined zero-offset wall_clock trigger, all +unique trigger function calls must be declared with all of +their arguments under the [xtriggers] section, and +referred to by label alone in the graph. It would be convenient (and less +verbose, although no more functional) if we could just declare a label +against the common arguments, and give remaining arguments (such as +different wallclock offsets in clock triggers) as needed in the graph.

  • +
  • we may move away from the string templating method for providing workflow +and task attributes to trigger function arguments.

  • +
+
+
+

Filesystem Events?

+

Cylc does not have built-in support for triggering off of filesystem events +such as inotify on Linux. There is no cross-platform standard for +this, and in any case filesystem events are not very useful in HPC cluster +environments where events can only be detected at the specific node on which +they were generated.

+
+
+

Continuous Event Watchers?

+

For some applications a persistent process that continually monitors the +external world is better than discrete periodic checking. This would be more +difficult to support as a plugin mechanism in Cylc, but we may decide to do it +in the future. In the meantime, consider implementing a small daemon process as +the watcher (e.g. to watch continuously for filesystem events) and have your +Cylc trigger functions interact with it.

+
+
+

Push External Triggers

+
+

Note

+

The external triggering mechanism described here is harder to use than the +newer method of External Triggers. The trigger is a task +property rather than something the task depends on, it requires the +external system to push a message to the scheduler, and it has a less +flexible way to pass information to downstream tasks. However, a push +mechanism may sometimes be preferred over polling by the scheduler, so we +have retained support pending something better in a future Cylc 8 release.

+
+

These external triggers are hidden task prerequisites that must be satisfied by +using the cylc ext-trigger client command to send a pre-defined message to +the workflow along with an ID string that distinguishes one instance of the +event from another (the name of the target task and its current cycle point are +not required). The event ID is just an arbitrary string to Cylc, but it can be +used to identify something associated with the event to the workflow - such as +the filename of a new externally-generated dataset. When the scheduler +receives the event notification it will trigger the next instance of any task +waiting on that trigger (whatever its cycle point) and then broadcast +(see Cylc Broadcast) the event ID to the cycle point of the triggered +task as $CYLC_EXT_TRIGGER_ID. Downstream tasks with the same cycle +point therefore know the new event ID too and can use it, if they need to, to +identify the same new dataset. In this way a whole workflow can be associated +with each new dataset, and multiple datasets can be processed in parallel if +they happen to arrive in quick succession.

+

An externally-triggered task must register the event it waits on in the workflow +scheduling section:

+
# workflow "sat-proc"
+[scheduling]
+    cycling mode = integer
+    initial cycle point = 1
+    [[special tasks]]
+        external-trigger = get-data("new sat X data avail")
+    [[graph]]
+        P1 = get-data => conv-data => products
+
+
+

Then, each time a new dataset arrives the external detection system should +notify the workflow like this:

+
$ cylc ext-trigger sat-proc "new sat X data avail" passX12334a
+
+
+

where “sat-proc” is the workflow name and “passX12334a” is the ID string for +the new event. The workflow passphrase must be installed on triggering account.

+
+

Note

+

Only one task in a workflow can trigger off a particular external message. +Other tasks can trigger off the externally triggered task as required, +of course.

+
+

Here is a working example of a simulated satellite processing workflow:

+
#!Jinja2
+
+# WARNING: this uses the old-style push external trigger mechanism.
+
+[meta]
+    title = Real time satellite data processing demo, variant 3 of 3
+
+    description = """
+        Successive cycle points retrieve and process the next arbitrarily timed
+        and labelled dataset, in parallel if the data comes in quickly. This
+        variant of the workflow has initial get_data tasks with external triggers:
+        they do not submit until triggered by an external system.
+    """
+
+# Note that the satellite simulator task here that supplies the external event
+# trigger happens to be a workflow task - i.e. it is not really "external" - but
+# this is only a convenience - an easy route to a self-contained example workflow.
+
+# you can monitor output processing with:
+# $ watch -n 1 \
+#    "find ~/cylc-run/<workflow-id>/share; find ~/cylc-run/<workflow-id>/work"
+
+{% set N_DATASETS = 5 %}
+
+# define shared directories (could use runtime namespaces for this)
+{% set DATA_IN_DIR = "$CYLC_WORKFLOW_SHARE_DIR/incoming" %}
+{% set PRODUCT_DIR = "$CYLC_WORKFLOW_SHARE_DIR/products" %}
+
+[scheduling]
+    cycling mode = integer
+    initial cycle point = 1
+    final cycle point = {{N_DATASETS}}
+    [[special tasks]]
+        external-trigger = get_data("new dataset ready for processing")
+    [[graph]]
+        # first cycle
+        R1 = prep => satsim & get_data
+        P1 = """
+            # Processing chain for each dataset
+            get_data => proc1 => proc2 => products
+            # As one dataset is retrieved, start waiting on another.
+            get_data[-P1] => get_data
+        """
+        # last cycle
+        R1//{{N_DATASETS}} = products => collate
+
+[runtime]
+    [[prep]]
+        script = \
+rm -rf $CYLC_WORKFLOW_SHARE_DIR $CYLC_WORKFLOW_WORK_DIR
+        [[[meta]]]
+            title = clean the workflow output directories
+    [[satsim]]
+        pre-script = mkdir -p {{DATA_IN_DIR}}
+        script = """
+            COUNT=0
+            while true; do
+                ((COUNT == {{N_DATASETS}})) && break
+                # sleep $((RANDOM % 20))
+                # Generate datasets very quickly to test parallel processing.
+                DATA_ID=$(date +%s).$((RANDOM % 100))
+                DATA_FILE=dataset-${DATA_ID}.raw
+                touch {{DATA_IN_DIR}}/$DATA_FILE
+                ((COUNT += 1))
+                # (required to distinguish fast-arriving messages).
+                # Trigger downstream processing in the workflow.
+                cylc ext-trigger $CYLC_WORKFLOW_ID \
+                   "new dataset ready for processing" $DATA_ID
+            done
+        """
+        [[[meta]]]
+            title = simulate a satellite data feed
+            description = """
+                Generates {{N_DATASETS}} arbitrarily labelled datasets very
+                quickly, to show parallel processing streams.
+            """
+    [[WORKDIR]]
+        # Define a common cycle-point-specific work-directory for all
+        # processing tasks so that they all work on the same dataset.
+        work sub-directory = proc-$CYLC_TASK_CYCLE_POINT
+        post-script = sleep 5
+        [[[environment]]]
+            DATASET = dataset-$CYLC_EXT_TRIGGER_ID
+
+    [[get_data]]
+        inherit = WORKDIR
+        script = mv {{DATA_IN_DIR}}/${DATASET}.raw $PWD
+        [[[meta]]]
+            title = retrieve next dataset
+            description = just do it - we know it exists already
+  [[proc1]]
+        inherit = WORKDIR
+        script = mv ${DATASET}.raw ${DATASET}.proc1
+        [[[meta]]]
+            title = convert .raw dataset to .proc1 form
+   [[proc2]]
+        inherit = WORKDIR
+        script = mv ${DATASET}.proc1 ${DATASET}.proc2
+        [[[meta]]]
+            title = convert .proc1 dataset to .proc2 form
+   [[products]]
+        inherit = WORKDIR
+        script = """
+            mkdir -p {{PRODUCT_DIR}}
+            mv ${DATASET}.proc2 {{PRODUCT_DIR}}/${DATASET}.prod
+        """
+        [[[meta]]]
+            title = generate products from .proc2 processed dataset
+    [[collate]]
+        # Note you might want to use "cylc workflow-state" to check that
+        # _all_ product tasks have finished before collating results.
+        script = """
+            echo PRODUCTS:
+            ls {{PRODUCT_DIR}}
+            sleep 20
+        """
+        [[[meta]]]
+            title = collate all products from the workflow run
+
+
+

External triggers are not normally needed in datetime cycling workflows driven +by real time data that comes in at regular intervals. In these cases a data +retrieval task can be clock-triggered (and have appropriate retry intervals) to +submit at the expected data arrival time, so little time is wasted in polling. +However, if the arrival time of the cycle-point-specific data is highly +variable, external triggering may be used with the cycle point embedded in the +message:

+
# workflow "data-proc"
+[scheduling]
+    initial cycle point = 20150125T00
+    final cycle point   = 20150126T00
+    [[special tasks]]
+        external-trigger = get-data("data arrived for $CYLC_TASK_CYCLE_POINT")
+    [[graph]]
+        T00 = init-process => get-data => post-process
+
+
+

Once the variable-length waiting is finished, an external detection system +should notify the workflow like this:

+
$ cylc ext-trigger data-proc "data arrived for 20150126T00" passX12334a
+
+
+

where “data-proc” is the workflow name, the cycle point has replaced the +variable in the trigger string, and “passX12334a” is the ID string for +the new event. The workflow passphrase must be installed on the triggering +account. In this case, the event will trigger for the second cycle point but +not the first because of the cycle-point matching.

+
+
+

Triggering Off Of Tasks In Other Workflows

+
+

Note

+

Please read External Triggers before using the older +inter-workflow triggering mechanism described in this section.

+
+

The cylc workflow-state command interrogates workflow run databases. It +has a polling mode that waits for a given task in the target workflow to achieve a +given state, or receive a given message. This can be used to make task +scripting wait for a remote task to succeed (for example).

+

Automatic workflow-state polling tasks can be defined with in the graph. They get +automatically-generated task scripting that uses cylc workflow-state +appropriately (it is an error to give your own script item for these +tasks).

+

Here’s how to trigger a task bar off a task foo in +a remote workflow called other.workflow:

+
[scheduling]
+    [[graph]]
+        T00, T12 = "my-foo<other.workflow::foo> => bar"
+
+
+

Local task my-foo will poll for the success of foo +in workflow other.workflow, at the same cycle point, succeeding only when +or if it succeeds. Other task states can also be polled:

+
T00, T12 = "my-foo<other.workflow::foo:fail> => bar"
+
+
+

The default polling parameters (e.g. maximum number of polls and the interval +between them) are printed by cylc workflow-state --help and can be +configured if necessary under the local polling task runtime section:

+
[scheduling]
+    [[graph]]
+        T00,T12 = "my-foo<other.workflow::foo> => bar"
+[runtime]
+    [[my-foo]]
+        [[[workflow state polling]]]
+            max-polls = 100
+            interval = PT10S
+
+
+

To poll for the target task to receive a message rather than achieve a state, +give the message in the runtime configuration (in which case the task status +inferred from the graph syntax will be ignored):

+
[runtime]
+    [[my-foo]]
+        [[[workflow state polling]]]
+            message = "the quick brown fox"
+
+
+

For workflows owned by others, or those with run databases in non-standard +locations, use the --run-dir option, or in-workflow:

+
[runtime]
+    [[my-foo]]
+        [[[workflow state polling]]]
+            run-dir = /path/to/top/level/cylc/run-directory
+
+
+

If the remote task has a different cycling sequence, just arrange for the +local polling task to be on the same sequence as the remote task that it +represents. For instance, if local task cat cycles 6-hourly at +0,6,12,18 but needs to trigger off a remote task dog +at 3,9,15,21:

+
[scheduling]
+    [[graph]]
+        T03,T09,T15,T21 = "my-dog<other.workflow::dog>"
+        T00,T06,T12,T18 = "my-dog[-PT3H] => cat"
+
+
+

For workflow-state polling, the cycle point is automatically converted to the +cycle point format of the target workflow.

+

The remote workflow does not have to be running when polling commences because the +command interrogates the workflow run database, not the scheduler.

+
+

Note

+

The graph syntax for workflow polling tasks cannot be combined with +cycle point offsets, family triggers, or parameterized task notation. +This does not present a problem because workflow polling tasks can be put on +the same cycling sequence as the remote-workflow target task (as recommended +above), and there is no point in having multiple tasks (family members or +parameterized tasks) performing the same polling operation. Task state +triggers can be used with workflow polling, e.g. to trigger another task if +polling fails after 10 tries at 10 second intervals:

+
[scheduling]
+    [[graph]]
+        R1 = "poller<other-workflow::foo:succeed>:fail => another-task"
+[runtime]
+    [[my-foo]]
+        [[[workflow state polling]]]
+            max-polls = 10
+            interval = PT10S
+
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/writing-workflows/index.html b/nightly_8.4/html/user-guide/writing-workflows/index.html new file mode 100644 index 00000000000..a57b46ebd55 --- /dev/null +++ b/nightly_8.4/html/user-guide/writing-workflows/index.html @@ -0,0 +1,275 @@ + + + + + + + Writing Workflows — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Writing Workflows

+
+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/writing-workflows/jinja2.html b/nightly_8.4/html/user-guide/writing-workflows/jinja2.html new file mode 100644 index 00000000000..d78e15568de --- /dev/null +++ b/nightly_8.4/html/user-guide/writing-workflows/jinja2.html @@ -0,0 +1,985 @@ + + + + + + + Jinja2 — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Jinja2

+ +

Cylc supports the Jinja2 template processor in workflow configurations. +Jinja2 code can appear anywhere in the file. The result after Jinja2 processing +must be valid Cylc syntax.

+

To use Jinja2, put a hash-bang comment in the first line of flow.cylc:

+
#!jinja2
+
+
+

Embedded Jinja2 code should be reasonably easy to understand for those with +coding experience; otherwise Jinja2 is documented here.

+

Uses of Jinja2 in Cylc include:

+
+
    +
  • Inclusion or exclusion of config sections by logical switch, e.g. to make +portable workflows

  • +
  • Computation of config values from input data

  • +
  • Inclusion of files and sub-templates

  • +
  • Looping over parameters to generate groups of similar tasks and associated +dependencies - but see Parameterized Tasks for a +simpler alternative to this where appropriate

  • +
+
+
+../../_images/jinja2-ensemble-graph.png +
+

The Jinja2 ensemble example workflow graph.

+
+
+

The graph above shows an ensemble of similar tasks generated with a Jinja2 loop:

+
#!jinja2
+{% set N_MEMBERS = 5 %}
+[scheduling]
+    [[graph]]
+        R1 = """
+{# generate ensemble dependencies #}
+{% for I in range( 0, N_MEMBERS ) %}
+            foo => mem_{{ I }} => post_{{ I }} => bar
+{% endfor %}
+        """
+
+
+

Note that Jinja2 code is encapsulated in curly braces to distinguish it from +the surrounding text.

+
+
+ + + + + + + + + + + + + + + + +

Jinja2 Syntax

Description

{# comment #}

Comment

{% if true %}

Expression

{{ var }}

Print statement

+
+

Here is the workflow configuration after Jinja2 processing:

+
#!jinja2
+[scheduling]
+    [[graph]]
+        R1 = """
+            foo => mem_0 => post_0 => bar
+            foo => mem_1 => post_1 => bar
+            foo => mem_2 => post_2 => bar
+            foo => mem_3 => post_3 => bar
+            foo => mem_4 => post_4 => bar
+        """
+
+
+

This example illustrates Jinja2 loops nicely, but note it is now easier +to generate task names automatically with built-in +task parameters:

+
[task parameters]
+    m = 0..4
+[scheduling]
+    [[graph]]
+        R1 = "foo => mem<m> => post<m> => bar"
+
+
+

The next workflow, which generates weather forecasts over a number of cities, is +more complex. To add a new city and associated tasks and dependencies just add +the new city name to list at the top of the file. It makes use of Jinja2 +variables, loops, math, and logical flags to include or exclude tasks.

+
+

Tip

+

This example could also be simplified with built in +task parameters

+
+
#!Jinja2
+[meta]
+    title = "Jinja2 city workflow example."
+    description = """
+        Illustrates use of variables and math expressions, and programmatic
+        generation of groups of related dependencies and runtime properties.
+    """
+
+[scheduler]
+    allow implicit tasks = True
+
+{% set HOST = "SuperComputer" %}
+{% set CITIES = 'NewYork', 'Philadelphia', 'Newark', 'Houston', 'SantaFe', 'Chicago' %}
+{% set CITYJOBS = 'one', 'two', 'three', 'four' %}
+{% set LIMIT_MINS = 20 %}
+
+{% set CLEANUP = True %}
+
+[scheduling]
+    initial cycle point = 2011-08-08T12
+    [[graph]]
+{% if CLEANUP %}
+        T23 = "clean"
+{% endif %}
+        T00,T12 = """
+            setup => get_lbc & get_ic # foo
+    {% for CITY in CITIES %} {# comment #}
+            get_lbc => {{ CITY }}_one
+            get_ic => {{ CITY }}_two
+            {{ CITY }}_one & {{ CITY }}_two => {{ CITY }}_three & {{ CITY }}_four
+        {% if CLEANUP %}
+            {{ CITY }}_three & {{ CITY }}_four => cleanup
+    {% endif %}
+{% endfor %}
+        """
+
+[runtime]
+    [[on_{{ HOST }} ]]
+        [[[remote]]]
+            host = {{ HOST }}
+            # (remote cylc directory is set in site/user config for this host)
+        [[[directives]]]
+            wall_clock_limit = "00:{{ LIMIT_MINS|int() + 2 }}:00,00:{{ LIMIT_MINS }}:00"
+
+{% for CITY in CITIES %}
+    [[ {{ CITY }} ]]
+        inherit = on_{{ HOST }}
+    {% for JOB in CITYJOBS %}
+    [[ {{ CITY }}_{{ JOB }} ]]
+        inherit = {{ CITY }}
+    {% endfor %}
+{% endfor %}
+
+
+
+../../_images/jinja2-workflow-graph.png +
+

Jinja2 cities example workflow graph, with the +New York City task family expanded.

+
+
+
+

Access to Workflow Files

+

Your Jinja2 code can see the workflow directory by using +Python code +that simply reads from the current working directory.

+

This will be the source directory if parsing a source workflow, or the run +directory if parsing an installed workflow.

+
+
+

Workflow Context variables

+

Jinja2 CYLC variables available when parsing any workflow (source or installed):

+ + + + + + + + + + + + +

CYLC_VERSION

Version of Cylc parsing the configuration

CYLC_WORKFLOW_NAME

Workflow name (source, or run ID minus run name)

CYLC_TEMPLATE_VARS

Variables set by ‘–set’ CLI options or plugins

+

Additional Jinja2 CYLC variables available when parsing an installed workflow:

+ + + + + + + + + +

CYLC_WORKFLOW_ID

Workflow ID

CYLC_WORKFLOW_RUN_DIR

Workflow run directory

+

Additional Jinja2 CYLC variables available when the scheduler is parsing an +installed workflow at run time:

+ + + + + + + + + + + + +

CYLC_WORKFLOW_LOG_DIR

Workflow log sub-directory

CYLC_WORKFLOW_SHARE_DIR

Workflow share sub-directory

CYLC_WORKFLOW_WORK_DIR

Workflow work sub-directory

+
+

Note

+

Set default values for CYLC variables that are only defined for installed or +running workflows, to allow successful parsing in other contexts as well: +{{CYLC_WORKFLOW_RUN_DIR | default("not-defined")}}.

+
+
+
+

Environment Variables

+

Cylc automatically imports the parse-time environment to the template +processor’s global namespace (see Custom Jinja2 Filters, Tests and Globals), +in a dictionary called environ:

+
#!Jinja2
+#...
+[runtime]
+    [[root]]
+        [[[environment]]]
+            HOME_DIR_ON_WORKFLOW_HOST = {{environ['HOME']}}
+
+
+
+

Warning

+

The environment is read during configuration parsing. It is not the run time +job environment.

+
+
+
+

Custom Jinja2 Filters, Tests and Globals

+

Jinja2 has three namespaces that separate “globals”, “filters” and “tests”. +Globals are template-wide variables and functions. Cylc extends this namespace +with the environ dictionary above, and +raise and assert +functions for raising exceptions to abort Cylc config parsing.

+

Filters can be used to modify variable values and are applied using pipe +notation. For example, the built-in trim filter strips leading +and trailing white space from a string:

+
{% set MyString = "   dog   " %}
+{{ MyString | trim() }}  # "dog"
+
+
+

Variable values can be tested using the is keyword followed by +the name of the test, e.g. {% if VARIABLE is defined %}. See Jinja2 +documentation for available built-in globals, filters and tests.

+

Cylc also supports custom Jinja2 globals, filters and tests. A custom global, +filter or test is a single Python function in a source file with the same name +as the function (plus .py extension). These must be located in a +subdirectory of the run directory called +Jinja2Filters, Jinja2Globals or Jinja2Tests respectively.

+

In the argument list of a filter or test function, the first argument is +the variable value to be filtered or tested, and subsequent arguments can be +whatever is needed. Currently three custom filters are supplied:

+ + + + + + + + + + + + +

cylc.flow.jinja.filters.pad.pad

Pads a string to some length with a fill character

cylc.flow.jinja.filters.strftime.strftime

Format an ISO8601 datetime string using an strftime string.

cylc.flow.jinja.filters.duration_as.duration_as

Format an ISO8601 duration string as the specified units.

+
+
+cylc.flow.jinja.filters.pad.pad(value, length, fillchar=' ')[source]
+

Pads a string to some length with a fill character

+

Useful for generating task names and related values in ensemble workflows.

+
+
Parameters:
+
    +
  • value (str) – The string to pad.

  • +
  • length (int | str) – The length for the returned string.

  • +
  • fillchar (str) – The character to fill in surplus space (space by default).

  • +
+
+
Returns:
+

value padded to the left with fillchar to length length.

+
+
Return type:
+

str

+
+
+
+
Python Examples:
>>> pad('13', 3, '0')
+'013'
+>>> pad('foo', 6)
+'   foo'
+>>> pad('foo', 2)
+'foo'
+
+
+
+
Jinja2 Examples:
{% for i in range(0,100) %}  # 0, 1, ..., 99
+    {% set j = i | pad(2,'0') %}
+    [[A_{{j}}]]         # [[A_00]], [[A_01]], ..., [[A_99]]
+{% endfor %}
+
+
+
+
+
+ +
+
+cylc.flow.jinja.filters.strftime.strftime(iso8601_datetime, strftime_str, strptime_str=None)[source]
+

Format an ISO8601 datetime string using an strftime string.

+
{{ '10661004T08+01' | strftime('%H') }}  # 00
+
+
+

It is also possible to parse non-standard date-time strings by passing a +strptime string as the second argument.

+
+
Parameters:
+
    +
  • iso8601_datetime (str) – Any valid ISO8601 datetime as a string.

  • +
  • strftime_str (str) – A valid strftime string to format the output datetime.

  • +
  • strptime_str (str | None) – A valid strptime string defining the format of the provided +iso8601_datetime.

  • +
+
+
Returns:
+

The result of applying the strftime to the iso8601_datetime as parsed +by the strptime string if provided.

+
+
Raises:
+
    +
  • ISO8601SyntaxError – In the event of an invalid datetime string.

  • +
  • StrftimeSyntaxError – In the event of an invalid strftime string.

  • +
+
+
+
+
Python Examples:
>>> # Basic usage.
+>>> strftime('2000-01-01T00Z', '%H')
+'00'
+>>> strftime('2000', '%H')
+'00'
+>>> strftime('2000', '%Y/%m/%d %H:%M:%S')
+'2000/01/01 00:00:00'
+>>> strftime('10661014T08+01', '%z')  # Timezone offset.
+'+0100'
+>>> strftime('10661014T08+01', '%j')  # Day of the year
+'287'
+
+
+
>>> # Strptime.
+>>> strftime('12,30,2000', '%m', '%m,%d,%Y')
+'12'
+>>> strftime('1066/10/14 08:00:00', '%Y%m%dT%H', '%Y/%m/%d %H:%M:%S')
+'10661014T08'
+
+
+
>>> # Exceptions.
+>>> strftime('invalid', '%H')  
+Traceback (most recent call last):
+<class 'metomi.isodatetime.exceptions.ISO8601SyntaxError'>
+metomi.isodatetime.exceptions.ISO8601SyntaxError: Invalid ISO 8601         date representation: invalid
+>>> strftime('2000', '%invalid')  
+Traceback (most recent call last):
+metomi.isodatetime.exceptions.StrftimeSyntaxError: Invalid         strftime/strptime representation: %i
+>>> strftime('2000', '%Y', '%invalid')
+... 
+Traceback (most recent call last):
+metomi.isodatetime.exceptions.StrftimeSyntaxError: Invalid         strftime/strptime representation: %i
+
+
+
+
Jinja2 Examples:
{% set START_CYCLE = '10661004T08+01' %}
+
+{{START_CYCLE | strftime('%Y')}}  # 1066
+{{START_CYCLE | strftime('%m')}}  # 10
+{{START_CYCLE | strftime('%d')}}  # 14
+{{START_CYCLE | strftime('%H:%M:%S %z')}}  # 08:00:00 +01
+{{'12,30,2000' | strftime('%m', '%m,%d,%Y')}}  # 12
+
+
+
+
+
+ +
+
+cylc.flow.jinja.filters.duration_as.duration_as(iso8601_duration, units)[source]
+

Format an ISO8601 duration string as the specified units.

+

Units for the conversion can be specified in a case-insensitive short or +long form:

+
    +
  • Seconds - “s” or “seconds”

  • +
  • Minutes - “m” or “minutes”

  • +
  • Hours - “h” or “hours”

  • +
  • Days - “d” or “days”

  • +
  • Weeks - “w” or “weeks”

  • +
+

While the filtered value is a floating-point number, it is often required +to supply an integer to workflow entities (e.g. environment variables) that +require it. This is accomplished by chaining filters:

+
    +
  • {{CYCLE_INTERVAL | duration_as('h') | int}} - 24

  • +
  • {{CYCLE_SUBINTERVAL | duration_as('h') | int}} - 0

  • +
  • {{CYCLE_INTERVAL | duration_as('s') | int}} - 86400

  • +
  • {{CYCLE_SUBINTERVAL | duration_as('s') | int}} - 1800

  • +
+
+
Parameters:
+
    +
  • iso8601_duration (str) – Any valid ISO8601 duration as a string.

  • +
  • units (str) – Destination unit for the duration conversion

  • +
+
+
Returns:
+

The total number of the specified unit contained in the specified +duration as a floating-point number.

+
+
Raises:
+

ISO8601SyntaxError – In the event of an invalid datetime string.

+
+
Return type:
+

float

+
+
+
+
Python Examples:
>>> # Basic usage.
+>>> duration_as('PT1M', 's')
+60.0
+>>> duration_as('PT1H', 'seconds')
+3600.0
+
+
+
>>> # Exceptions.
+>>> duration_as('invalid value', 's')  
+Traceback (most recent call last):
+metomi.isodatetime.exceptions.ISO8601SyntaxError: Invalid ISO 8601        duration representation: invalid value
+>>> duration_as('invalid unit', '#')  
+Traceback (most recent call last):
+ValueError: No matching units found for #
+
+
+
+
Jinja2 Examples:
{% set CYCLE_INTERVAL = 'PT1D' %}
+{{ CYCLE_INTERVAL | duration_as('h') }}  # 24.0
+{% set CYCLE_SUBINTERVAL = 'PT30M' %}
+{{ CYCLE_SUBINTERVAL | duration_as('hours') }}  # 0.5
+{% set CYCLE_INTERVAL = 'PT1D' %}
+{{ CYCLE_INTERVAL | duration_as('s') }}  # 86400.0
+{% set CYCLE_SUBINTERVAL = 'PT30M' %}
+{{ CYCLE_SUBINTERVAL | duration_as('seconds') }}  # 1800.0
+
+
+
+
+
+ +
+
+

Associative Arrays In Jinja2

+

Associative arrays (or dictionaries) are very useful. For example:

+
#!Jinja2
+{% set obs_types = ['airs', 'iasi'] %}
+{% set resource = { 'airs':'ncpus=9', 'iasi':'ncpus=20' } %}
+
+[scheduling]
+    [[graph]]
+        R1 = OBS
+[runtime]
+    [[OBS]]
+        platform = platform_using_pbs
+    {% for i in obs_types %}
+    [[ {{i}} ]]
+        inherit = OBS
+        [[[directives]]]
+             -I = {{ resource[i] }}
+     {% endfor %}
+
+
+

Here’s the result:

+
$ cylc config -i [runtime][airs]directives <workflow-id>
+-I = ncpus=9
+
+
+
+
+

Default Values and Template Variables

+

You can provide template variables to Cylc in 4 ways:

+
    +
  • Using the --set-file (-S) option.

  • +
  • Using the --set (-s) option.

  • +
  • Using the --set-list (-z) option.

  • +
  • Using a plugin, such as Cylc Rose.

  • +
+
+

Note

+

If the same variable is set by more than one method, the last source in the +above list is used.

+
+
+

The -s, -z and --set-file Options

+
$ # set the Jinja2 variable "answer" to 42
+$ cylc play <workflow-id> -s answer=42
+
+
+

A Python string-list is a valid value, but a lot to type, so --set-list +(-z) is provided as a convenience:

+
# The set syntax
+$ cylc play <workflow-id> -s "answers=['mice', 'dolphins']"
+# ... can  be shortened to:
+$ cylc play <workflow-id> -z answers=mice,dolphins
+
+
+

If you need to define a lot of variables, you can so in a file +using the --set-file option:

+
$ # create a set file
+$ cat > my-set-file <<__SET_FILE__
+question='the meaning of life, the universe and everything'
+answer=42
+host='deep-thought'
+__SET_FILE__
+
+$ # run using the options in the set file
+$ cylc play <workflow-id> --set-file my-set-file
+
+
+

Values must be Python literals e.g:

+
"string"   # string
+123        # integer
+12.34      # float
+True       # boolean
+None       # None type
+[1, 2, 3]  # list
+(1, 2, 3)  # tuple
+{1, 2, 3}  # set
+{"a": 1, "b": 2, "c": 3}  # dictionary
+
+
+
+

Note

+

On the command line you may need to wrap strings with an extra +pair of quotes as the shell you are using (e.g. Bash) will strip +the outer pair of quotes.

+
$ # wrap the key=value pair in single quotes stop the shell from
+$ # stripping the inner quotes around the string:
+$ cylc play <workflow-id> -s 'my_string="a b c"'
+
+
+
+

Here’s an example:

+
#!Jinja2
+[meta]
+    title = "Jinja2 example: use of defaults and external input"
+
+    description = """
+        The template variable N_MEMBERS can be set on the command line with
+        --set or --set-file=FILE; but if not a default values is supplied.
+    """
+
+[scheduling]
+    initial cycle point = 20100808T00
+    final cycle point   = 20100816T00
+    [[graph]]
+        T00 = """
+            foo => ENS
+            ENS:succeed-all => bar
+        """
+
+[runtime]
+    [[foo, bar]]
+    [[ENS]]
+{% for I in range( 0, N_MEMBERS | default( 3 )) %}
+    [[ mem_{{ I }} ]]
+        inherit = ENS
+{% endfor %}
+
+
+

Here’s the result:

+
$ cylc list <workflow-id>
+Jinja2 Template Error
+'FIRST_TASK' is undefined
+cylc-list <workflow-id>  failed:  1
+
+$ # Note: quoting "bob" so that it is evaluated as a string
+$ cylc list --set 'FIRST_TASK="bob"' <workflow-id>
+bob
+baz
+mem_2
+mem_1
+mem_0
+
+$ cylc list --set 'FIRST_TASK="bob"' --set 'LAST_TASK="alice"' <workflow-id>
+bob
+alice
+mem_2
+mem_1
+mem_0
+
+$ # Note: no quotes required for N_MEMBERS since it is an integer
+$ cylc list --set 'FIRST_TASK="bob"' --set N_MEMBERS=10 <workflow-id>
+mem_9
+mem_8
+mem_7
+mem_6
+mem_5
+mem_4
+mem_3
+mem_2
+mem_1
+mem_0
+baz
+bob
+
+
+

Note also that cylc view --set FIRST_TASK=bob --jinja2 <workflow-id> +will show the workflow with the Jinja2 variables as set.

+
+

Note

+

Workflows started with template variables set on the command +line will restart with the same settings. You can set +them again on the cylc play command line if they need to +be overridden.

+
+
+
+

Using a plugin

+

Template plugins such as Cylc Rose should provide a set of template +variables which can be provided to Cylc. For example, using Cylc Rose you +add a rose-suite.conf file containing a [template variables] +section which the plugin makes available to Cylc:

+
+
rose-suite.conf
+
[template variables]
+ICP=1068
+
+
+
+
+
flow.cylc
+
#!jinja2
+[scheduler]
+   allow implicit tasks = True
+[scheduling]
+   initial cycle point = {{ICP}}
+   [[dependencies]]
+      P1Y = Task1
+
+
+
+
$ cylc config . -i "[scheduling]initial cycle point"
+1068
+
+
+
+
+
+

Jinja2 Variable Scope

+

Jinja2 variable scoping rules may be surprising. For instance, variables set +inside a for loop can’t be accessed outside of the block, +so the following will not print # FOO is True:

+
{% set FOO = False %}
+{% for item in items %}
+    {% if item.check_something() %}
+        {% set FOO = True %}
+    {% endif %}
+{% endfor %}
+# FOO is {{FOO}}
+
+
+

Jinja2 documentation suggests using alternative constructs like the loop +else block or the special loop variable. More complex use cases can be +handled using namespace objects that allow propagating of changes across scopes:

+
{% set ns = namespace(foo=false) %}
+{% for item in items %}
+    {% if item.check_something() %}
+        {% set ns.foo = true %}
+    {% endif %}
+{% endfor %}
+# FOO is {{ns.foo}}
+
+
+

For detail, see +Jinja2 Template Designer Documentation - Assignments

+
+
+

Raising Exceptions

+

Cylc provides two functions for raising exceptions in Jinja2 code. These +exceptions are raised when the flow.cylc file is loaded and will +prevent a workflow from running.

+
+

Note

+

These functions must be contained within {{ Jinja2 print statements, not +{% code blocks.

+
+
+

Raise

+

The raise function will result in an error containing the provided text.

+
{% if not VARIABLE is defined %}
+    {{ raise('VARIABLE must be defined for this workflow.') }}
+{% endif %}
+
+
+
+
+

Assert

+

The assert function will raise an exception containing the text provided in +the second argument providing that the first argument evaluates as False. The +following example is equivalent to the “raise” example above.

+
{{ assert(VARIABLE is defined, 'VARIABLE must be defined for this workflow.') }}
+
+
+
+
+
+

Importing Python modules

+

Jinja2 allows to gather variable and macro definitions in a separate template +that can be imported into (and thus shared among) other templates.

+
{% import "flow-utils.cylc" as utils %}
+{% from "flow-utils.cylc" import VARIABLE as ALIAS %}
+{{ utils.VARIABLE is equalto(ALIAS)) }}
+
+
+

Cylc extends this functionality to allow import of arbitrary Python modules.

+
{% from "itertools" import product %}
+[runtime]
+{% for group, member in product(['a', 'b'], [0, 1, 2]) %}
+    [[{{group}}_{{member}}]]
+{% endfor %}
+
+
+

For better clarity and disambiguation Python modules can be prefixed with +__python__:

+
{% from "__python__.itertools" import product %}
+
+
+
+
+

Logging

+

It is possible to output messages to the Cylc log from within Jinja2, these +messages will appear on the console when validating or starting a workflow. +This can be useful for development or debugging.

+

Example flow.cylc:

+
#!Jinja2
+{% from "cylc.flow" import LOG %}
+{% do LOG.debug("Hello World!") %}
+
+
+

Example output:

+
$ cylc validate . --debug
+DEBUG - Loading site/user config files
+DEBUG - Reading file <file>
+DEBUG - Processing with Jinja2
+DEBUG - Hello World!
+...
+Valid for cylc-<version>
+
+
+

Log messages will appear whenever the workflow configuration is loaded so it is +advisable to use the DEBUG logging level which is suppressed unless the +--debug option is provided.

+
+
+

Debugging

+

It is possible to run Python debuggers from within Jinja2 via the +import mechanism.

+

For example to use a PDB breakpoint you could do the following:

+
#!Jinja2
+
+{% set ANSWER = 42 %}
+
+{% from "pdb" import set_trace %}
+{% do set_trace() %}
+
+
+

The debugger will open within the Jinja2 code, local variables can be accessed +via the _Context__self variable e.g:

+
$ cylc validate <id>
+(Pdb) _Context__self['ANSWER']
+42
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/writing-workflows/parameterized-tasks.html b/nightly_8.4/html/user-guide/writing-workflows/parameterized-tasks.html new file mode 100644 index 00000000000..0d60e15eb94 --- /dev/null +++ b/nightly_8.4/html/user-guide/writing-workflows/parameterized-tasks.html @@ -0,0 +1,719 @@ + + + + + + + Task Parameters — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Task Parameters

+

Cylc can automatically generate related tasks and dependencies by expanding +parameterized names over lists or ranges of +values. Uses for this include:

+
    +
  • Generating an ensemble of similar model runs

  • +
  • Generating chains of tasks to process similar datasets

  • +
  • Replicating an entire workflow, or part thereof, over several runs

  • +
  • Splitting a long model run into smaller chunks

  • +
  • Parameterized cycling

  • +
+
+

Note

+

Cylc supports use of Jinja2 and Empy templating for programmatic generation of workflow +configurations. The built-in parameterization system described here +is a cleaner and easier alternative for generating tasks and families +over a range of parameters, but unlike general templating it can only be +used for that specific purpose.

+
+
+

Parameter Expansion

+

Parameter values can be lists of strings, or lists of integers and +integer ranges (with inclusive bounds). Numeric values in a list of strings are +considered strings. It is not possible to mix strings with integer ranges.

+

For example:

+
[task parameters]
+    # parameters: "ship", "buoy", "plane"
+    # default task suffixes: _ship, _buoy, _plane
+    obs = ship, buoy, plane
+
+    # parameters: 1, 2, 3, 4, 5
+    # default task suffixes: _run1, _run2, _run3, _run4, _run5
+    run = 1..5
+
+    # parameters: 1, 3, 5, 7, 9
+    # default task suffixes: _idx1, _idx3, _idx5, _idx7, _idx9
+    idx = 1..9..2
+
+    # parameters: -11, -1, 9
+    # default task suffixes: _idx-11, _idx-01, _idx+09
+    idx = -11..9..10
+
+    # parameters: 1, 3, 5, 10, 11, 12, 13
+    # default task suffixes: _i01, _i03, _i05, _i10, _i11, _i12, _i13
+    i = 1..5..2, 10, 11..13
+
+    # parameters: "0", "1", "e", "pi", "i"
+    # default task suffixes: _0, _1, _e, _pi, _i
+    item = 0, 1, e, pi, i
+
+    # ERROR: mix strings with int range
+    p = one, two, 3..5
+
+
+

Then angle brackets denote use of these parameters throughout the workflow +configuration. For the values above, this parameterized name:

+
model<run>  # for run = 1..5
+
+
+

expands to these concrete task names:

+
model_run1, model_run2, model_run3, model_run4, model_run5
+
+
+

and this parameterized name:

+
proc<obs>  # for obs = ship, buoy, plane
+
+
+

expands to these concrete task names:

+
proc_ship, proc_buoy, proc_plane
+
+
+

By default, to avoid any ambiguity, the parameter name appears in the expanded +task names for integer values, but not for string values. For example, +model_run1 for run = 1, but proc_ship for +obs = ship. However, the default expansion templates can be +overridden if need be:

+
[task parameters]
+    obs = ship, buoy, plane
+    run = 1..5
+    [[templates]]
+        run = -R%(run)s  # Make foo<run> expand to foo-R1 etc.
+
+
+

See [task parameters][templates] for more on the string +template syntax.

+

Any number of parameters can be used at once. This parameterization:

+
model<run,obs>  # for run = 1..2 and obs = ship, buoy, plane
+model<run><obs> # Alternatively, from Cylc 8.2.0
+
+
+
+

Added in version 8.2.0: From this version you can also use the equivalent model<run><obs> +syntax. This allows more flexibility in templating: You can now construct +names like beginning<run>middle<obs>end.

+
+
+

Note

+

Before Cylc 8.2.0 this syntax worked in many cases, but was +not formally supported, and failed if used in the names of +families.

+
+

expands to these tasks names:

+
model_run1_ship, model_run1_buoy, model_run1_plane,
+model_run2_ship, model_run2_buoy, model_run2_plane
+
+
+

Here’s a simple but complete example workflow:

+
[task parameters]
+        run = 1..2
+[scheduling]
+    [[graph]]
+        R1 = "prep => model<run>"
+[runtime]
+    [[model<run>]]
+        # ...
+
+
+

The result, post parameter expansion, is this:

+
[scheduling]
+    [[graph]]
+        R1 = "prep => model_run1 & model_run2"
+[runtime]
+    [[model_run1]]
+        # ...
+    [[model_run2]]
+        # ...
+
+
+

Here’s a more complex graph using two parameters ([runtime] +omitted):

+
[task parameters]
+        run = 1..2
+        mem = cat, dog
+[scheduling]
+    [[graph]]
+        R1 = """
+            prep => init<run> => model<run,mem> =>
+            post<run,mem> => wrap<run> => done
+        """
+
+
+

The result as visualized by cylc graph is:

+
+../../_images/params1.png +
+

Parameter expansion example.

+
+
+
+

Zero-Padded Integer Values

+

Integer parameter values are given a default template for generating task +suffixes that are zero-padded according to the longest size of their values. +For example, the default template for p = 9..10 would be +_p%(p)02d, so that foo<p> would become foo_p09, foo_p10. +If negative values are present in the parameter list, the +default template will include the sign. +For example, the default template for p = -1..1 would be +_p%(p)+02d, so that foo<p> would become +foo_p-1, foo_p+0, foo_p+1.

+

To get thicker padding and/or alternate suffixes, use a template. E.g.:

+
[task parameters]
+    i = 1..9
+    p = 3..14
+    [[templates]]
+        i = _i%(i)02d  # suffixes = _i01, _i02, ..., _i09
+        # A double-percent gives a literal percent character
+        p = %%p%(p)03d  # suffixes = %p003, %p004, ..., %p013, %p014
+
+
+
+
+

Parameters as Full Task Names

+

Parameter values can be used as full task names, but the default template +should be overridden to remove the initial underscore. For example:

+
[task parameters]
+    i = 1..4
+    obs = ship, buoy, plane
+    [[templates]]
+        i = i%(i)d  # task name must begin with an alphabet
+        obs = %(obs)s
+[scheduling]
+    [[graph]]
+        R1 = """
+            foo => <i>  # foo => i1 & i2 & i3 & i4
+            <obs> => bar  # ship & buoy & plane => bar
+        """
+
+
+
+
+
+

Passing Values To Tasks

+

Parameter values are passed as environment variables to tasks generated by +parameter expansion. For example, if we have:

+
[task parameters]
+        obs = ship, buoy, plane
+        run = 1..5
+[scheduling]
+    [[graph]]
+        R1 = model<run,obs>
+
+
+

Then task model_run2_ship would get the following standard +environment variables:

+
# In a job script of an instance of the "model_run2_ship" task:
+export CYLC_TASK_PARAM_run="2"
+export CYLC_TASK_PARAM_obs="ship"
+
+
+

These variables allow tasks to determine which member of a parameterized +group they are, and so to vary their behaviour accordingly.

+

You can also define custom variables and string templates for parameter value +substitution. For example, if we add this to the above configuration:

+
[runtime]
+    [[model<run,obs>]]
+        [[[environment]]]
+            MYNAME = %(obs)sy-mc%(obs)sface
+            MYFILE = /path/to/run%(run)03d/%(obs)s
+
+
+

Then task model_run2_ship would get the following custom +environment variables:

+
# In a job script of an instance of the "model_run2_ship" task:
+export MYNAME=shipy-mcshipface
+export MYFILE=/path/to/run002/ship
+
+
+
+
+

Selecting Specific Values

+

Specific parameter values can be singled out in the graph and under +[runtime] with the notation <p=5> (for example). +Here’s how to make a special task trigger off just the first of a +set of model runs:

+
[task parameters]
+        run = 1..5
+[scheduling]
+    [[graph]]
+        R1 = """
+            model<run> => post_proc<run>  # general case
+            model<run=1> => check_first_run  # special case
+         """
+[runtime]
+    [[model<run>]]
+        # config for all "model" runs...
+    [[model<run=1>]]
+        # special config (if any) for the first model run...
+    #...
+
+
+
+
+

Selecting Partial Ranges

+

The parameter notation does not currently support partial range selection such +as foo<p=5..10>, but you can achieve the same result by defining a +second parameter that covers the partial range and giving it the same expansion +template as the full-range parameter. For example:

+
[task parameters]
+    run = 1..10  # 1, 2, ..., 10
+    runx = 1..3  # 1, 2, 3
+    [[parameter templates]]
+        run = _R%(run)02d   # _R01, _R02, ..., _R10
+        runx = _R%(runx)02d  # _R01, _R02, _R03
+[scheduling]
+    [[graph]]
+        R1 = """model<run> => post<run>
+                model<runx> => checkx<runx>"""
+[runtime]
+    [[model<run>]]
+        # ...
+    #...
+
+
+
+
+

Offsets in the Graph

+

A negative offset notation <NAME-1> is interpreted as the previous +value in the ordered list of parameter values, while a positive offset is +interpreted as the next value. For example, to split a model run into multiple +steps with each step depending on the previous one, either of these graph lines:

+
model<run-1> => model<run>  # for run = 1, 2, 3
+model<run> => model<run+1>  # for run = 1, 2, 3
+
+
+

expands to:

+
model_run1 => model_run2
+model_run2 => model_run3
+
+# or equivalently:
+
+model_run1 => model_run2 => model_run3
+
+
+

And this graph:

+
proc<size-1> => proc<size>  # for size = small, big, huge
+
+
+

expands to:

+
proc_small => proc_big
+proc_big => proc_huge
+
+# or equivalently:
+
+proc_small => proc_big => proc_huge
+
+
+
+
+

Task Families and Parameters

+

Task family members can be generated by parameter expansion:

+
[runtime]
+    [[FAM]]
+    [[member<r>]]
+        inherit = FAM
+# Result: family FAM contains member_r1, member_r2, etc.
+
+
+

Family names can be parameterized too, just like task names:

+
[runtime]
+    [[RUN<r>]]
+    [[model<r>]]
+        inherit = RUN<r>
+    [[post_proc<r>]]
+        inherit = RUN<r>
+# Result: family RUN_r1 contains model_r1 and post_proc_r1,
+#         family RUN_r2 contains model_r2 and post_proc_r1, etc.
+
+
+

As described in Family Triggers family names can be used to +trigger all members at once:

+
foo => FAMILY
+
+
+

or to trigger off all members:

+
FAMILY:succeed-all => bar
+
+
+

or to trigger off any members:

+
FAMILY:succeed-any => bar
+
+
+

If the members of FAMILY were generated with parameters, you can +also trigger them all at once with parameter notation:

+
foo => member<m>
+
+
+

Similarly, to trigger off all members:

+
member<m> => bar
+# (member<m>:fail etc., for other trigger types)
+
+
+

Family names are still needed in the graph, however, to succinctly express +“succeed-any” triggering semantics, and all-to-all or any-to-all triggering:

+
FAM1:succeed-any => FAM2
+
+
+

(Direct all-to-all and any-to-all family triggering is not recommended for +efficiency reasons though - see Efficient Inter-Family Triggering).

+

For family member-to-member triggering use parameterized members. +For example, if family OBS_GET has members get<obs> and +family OBS_PROC has members proc<obs> then this graph:

+
get<obs> => proc<obs>  # for obs = ship, buoy, plane
+
+
+

expands to:

+
get_ship => proc_ship
+get_buoy => proc_buoy
+get_plane => proc_plane
+
+
+
+
+

Parameterized Cycling

+

For smaller workflows of finite duration, parameter expansion can be used to +generate a sequence of pre-defined tasks as a proxy for cycling.

+

Here’s a cycling workflow of two-monthly model runs for one year, with +previous-instance model dependence:

+
[scheduling]
+    initial cycle point = 2020-01
+    final cycle point = 2020-12
+    [[graph]]
+        # Run once, at the initial point.
+        R1 = "prep => model"
+        # Run at 2-month intervals between the initial and final points.
+        P2M = "model[-P2M] => model => post_proc & archive"
+[runtime]
+    [[model]]
+        script = "run-model $CYLC_TASK_CYCLE_POINT"
+
+
+

And here’s how to do the same thing with parameterized tasks instead of cycling:

+
[task parameters]
+    chunk = 1..6
+[scheduling]
+    [[graph]]
+        R1 = """
+            prep => model<chunk=1>
+            model<chunk-1> => model<chunk> =>
+            post_proc<chunk> & archive<chunk>
+         """
+[runtime]
+    [[model<chunk>]]
+        script = """
+            # Compute start date from chunk index and interval.
+            INITIAL_POINT=2020-01
+            INTERVAL_MONTHS=2
+            OFFSET_MONTHS=(( (CYLC_TASK_PARAM_chunk - 1)*INTERVAL_MONTHS ))
+            OFFSET=P${OFFSET_MONTHS}M  # e.g. P4M for chunk=3
+            # Run the model.
+            run-model $(cylc cyclepoint --offset=$OFFSET $INITIAL_POINT)
+        """
+
+
+

The two workflows achieve the same result, and both can include special +behaviour at the start, end, or anywhere in between.

+
+../../_images/eg2-static.png +
+
+../../_images/eg2-dynamic.png +
+

Parameterized (top) and cycling (bottom) versions of the same +workflow. The first three cycle points are shown in the +cycling case. The parameterized case does not have cycle points (technically +all of its tasks have the cycle point 1).

+
+
+

The parameterized version has several disadvantages, however:

+
+
    +
  • The workflow must be finite in extent and not too large because every +parameterized task generates a new task definition

    +
      +
    • (In a cycling workflow a single task definition acts as a template for +all cycle point instances of a task)

    • +
    +
  • +
  • Datetime arithmetic has to be done manually

    +
      +
    • (This doesn’t apply if it’s not a datetime sequence; parameterized +integer cycling is straightforward.)

    • +
    +
  • +
+
+
+

Parameterized Sub-Cycles

+

A workflow can have multiple main cycling sequences, but sub-cycles within each +main cycle point have to be parameterized. A typical use case for this is +incremental processing of files generated sequentially during a long model run.

+

Here’s a workflow that uses parameters to split a long model run in each +datetime cycle point into four smaller runs:

+
[task parameters]
+    chunk = 1..4
+[scheduling]
+    initial cycle point = 2020-01
+    [[graph]]
+        P1Y = """
+            model<chunk-1> => model<chunk>
+            model<chunk=4>[-P1Y] => model<chunk=1>
+        """
+
+
+

The intercycle trigger connects the first chunk in each cycle point to the +last chunk in the previous cycle point. However, in this particular case it +might be simpler to use a 3-monthly datetime cycle instead:

+
[scheduling]
+    initial cycle point = 2020-01
+    [[graph]]
+        P3M = "model[-P3M] => model"
+
+
+

For another example, here task model generates 10 files in sequence as it +runs. Task proc_file0 triggers when the model starts running, to wait for +and process the first file; when that is done, proc_file1 triggers to wait +for the second file; and so on.

+
[task parameters]
+    file = 0..9
+[scheduling]
+    initial cycle point = 2020-01
+    [[graph]]
+        P1Y = """
+            model:start => proc<file=0>
+            proc<file-1> => proc<file>
+            proc<file=9> => upload_products
+        """
+[runtime]
+    [[proc<file>]]
+    # ...
+
+
+
+
+

Offsets at Sequence Start

+

In cycling workflows, dependence on tasks prior to the start cycle point is +ignored [1]. So this graph:

+
P1D = "model[-P1D] => model"
+
+
+

simplifies at the initial cycle point to this:

+
P1D = "model"
+
+
+

(Note this is a convenient way to bootstrap into an infinite cycle, but special +behaviour at the start point can be configured explicitly if desired).

+

Similarly, parameter offsets that go out of range are ignored. So this graph:

+
# for chunk = 1..4
+R1 = "model<chunk-1> => model<chunk>"
+
+
+

simplifies for chunk=1 to this:

+
R1 = "model_chunk0"
+
+
+ +
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/writing-workflows/runtime.html b/nightly_8.4/html/user-guide/writing-workflows/runtime.html new file mode 100644 index 00000000000..efd4537f383 --- /dev/null +++ b/nightly_8.4/html/user-guide/writing-workflows/runtime.html @@ -0,0 +1,1152 @@ + + + + + + + Task Configuration — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Task Configuration

+
+

Related Tutorial

+

Runtime Tutorial

+
+

The [runtime] section of the flow.cylc file +defines what job each task should run, and where and how to +submit each one to run.

+

It is an inheritance hierarchy that allows common settings to be factored +out and defined once in task families (duplication +of configuration is a maintenance risk in a complex workflow).

+
+

Task and Family Names

+

Task and family names must match in the graph and runtime sections of the +workflow config file. They do not need to match the names of the external +applications wrapped by the tasks.

+
+
+class cylc.flow.unicode_rules.TaskNameValidator[source]
+

The rules for valid task and family names:

+
    +
  • must start with: alphanumeric

  • +
  • can only contain: alphanumeric, -, +, %, @

  • +
  • cannot start with: _cylc

  • +
  • cannot be: root

  • +
+
+ +
+

Note

+

At runtime, tasks can access their own workflow task name as +$CYLC_TASK_NAME in the job environment job environment if needed.

+
+

The following runtime configuration defines one family called FAM and two +member tasks fm1 and fm2 that inherit settings from it. Members can +also override inherited settings and define their own private settings.

+
[runtime]
+    [[FAM]]  # <-- a family
+        #...  settings for all FAM members
+
+    [[fm1]]  # <-- task
+        inherit = FAM
+        #...  fm1-specific settings
+
+    [[fm2]]  # <-- a task
+        inherit = FAM
+        #...  fm2-specific settings
+
+
+

Note that families are not nested in terms of the file sub-heading structure. A +runtime subsection defines a family if others inherit from it, otherwise +it defines a task.

+
+
+

The Root Family

+

All tasks inherit implicitly from a family called root that can provide +default settings for all tasks in the workflow (non-root families require an +explicit inherit statement).

+

For example, if all tasks are to run on the same platform, that could +can be specified once for all tasks under root:

+
[runtime]
+    [[root]]
+        # all tasks run on hpc1 (unless they override this setting)
+        platform = hpc1
+
+
+
+
+

Defining Multiple Tasks or Families at Once

+

Runtime sub-section headings can be a comma-separated list of task or family +names, in which case the settings below it apply to each list member.

+

Here a group of three related tasks all run the same script on the same +platform, but pass their own names to it on the command line:

+
[runtime]
+    [[ENSEMBLE]]
+        platform = hpc1
+        script = "run-model.sh $CYLC_TASK_NAME"
+
+    [[m1, m2, m3]]
+        inherit = ENSEMBLE
+
+    [[m1]]
+        #...  m1-specific settings
+
+
+

Particular tasks (such as m1 above) can still be singled out to add +task-specific settings.

+
+

Note

+

Task parameters or template processing (see +Jinja2 and EmPy) can be used to +programmatically generate family members and associated dependencies.

+
+
+
+

Families of Families

+

Families can inherit from other families, to any depth.

+
[runtime]
+    [[HPC1]]
+        platform = hpc1
+
+    [[BIG-HPC1]]
+        inherit = HPC1
+        #...  add in high memory batch system directives
+
+    [[model]]  # a big task that runs on hpc1
+        inherit = BIG-HPC1
+
+
+

If the same item is defined (and redefined) at several levels in the family +tree, the highest level (closest to the task) takes precedence.

+
+
+

Inheriting from Multiple Parents

+

Sometimes a multi-level single-parent tree is not sufficient to avoid all +duplication of settings. Fortunately tasks can inherit from multiple parents at +once [1]:

+
[runtime]
+    [[HPC1]]
+        platform = hpc1
+
+    [[BIG]]  # high memory batch system directives
+        #...
+
+    [[model]]  # a big task that runs on hpc1
+        inherit = BIG, HPC1
+
+
+
+

Tip

+

Use cylc config to check exactly what settings a task or family ends up +with after inheritance processing:

+
$ cylc config --item "[runtime][model]environment" <workflow-id>
+
+
+
+
+

First-parent Family Hierarchy for Visualization

+

Tasks can be collapsed into first-parent families in the Cylc GUI, so first +parents should reflect the logical purpose of a task where possible, rather +than (say) shared technical settings:

+
[runtime]
+    [[HPC]]
+        # technical platform settings
+
+    [[MODEL]]
+        # atmospheric model tasks
+
+    [[atmos]]
+        inherit = MODEL, HPC  # (not HPC, MODEL)
+
+
+

If this is not what you want, given that the primary purpose of the family +hierarchy is inheritance of runtime settings, a dummy first parent None can +be used to disable the visualization usage without affecting inheritance:

+
[runtime]
+    [[BAR]]
+        #...
+    [[foo]]
+        # inherit from BAR but stay under root for visualization
+        inherit = None, BAR
+
+
+
+
+
+

Job Environment

+

Job scripts export various environment variables before +running script blocks (see Job Submission and Management).

+

Scheduler-defined variables appear first to identify the workflow, the task, +and log directory locations. These are followed by user-defined variables from +[runtime][<namespace>][environment]. Order of variable definition +is preserved so that new variable assignments can reference previous ones.

+
+

Note

+

Task environment variables are evaluated at runtime, by jobs, on the +job platform. So $HOME in a task environment, for instance, evaluates at +runtime to the home directory on the job platform, not on the scheduler +platform.

+
+

In this example the task foo ends up with SHAPE=circle, COLOR=blue, +and TEXTURE=rough in its environment:

+
[runtime]
+    [[root]]
+        [[[environment]]]
+            COLOR = red
+            SHAPE = circle
+    [[foo]]
+        [[[environment]]]
+            COLOR = blue  # root override
+            TEXTURE = rough # new variable
+
+
+

Job access to Cylc itself is configured first so that variable +assignment expressions (as well as scripting) can use Cylc commands:

+
[runtime]
+    [[foo]]
+        [[[environment]]]
+            REFERENCE_TIME = $(cylc cyclepoint --offset-hours=6)
+
+
+
+

Overriding Inherited Environment Variables

+
+

Warning

+

If you override an inherited task environment variable the parent config +item gets replaced before it is ever used to define the shell variable in +the job script. Consequently the job cannot see the parent value as +well as the task value:

+
+
[runtime]
+    [[FOO]]
+        [[[environment]]]
+            COLOR = red
+    [[bar]]
+        inherit = FOO
+        [[[environment]]]
+            tmp = $COLOR  # !! ERROR: $COLOR is undefined here
+            COLOR = dark-$tmp  # !! as this overrides COLOR in FOO.
+
+
+

The compressed variant of this, COLOR = dark-$COLOR, is also an error for +the same reason. To achieve the desired result, use a different name for the +parent variable:

+
[runtime]
+    [[FOO]]
+        [[[environment]]]
+            FOO_COLOR = red
+    [[bar]]
+        inherit = FOO
+        [[[environment]]]
+            COLOR = dark-$FOO_COLOR  # OK
+
+
+
+
+

Job Script Variables

+

These variables provided by the scheduler are available to +job scripts:

+
CYLC_VERSION                       # Version of cylc installation used
+CYLC_VERBOSE                       # Verbose mode, true or false
+CYLC_DEBUG                         # Debug mode (even more verbose), true or false
+
+CYLC_CYCLING_MODE                  # Cycling mode, e.g. gregorian
+ISODATETIMECALENDAR                # Calendar mode for the `isodatetime` command,
+                                   #   defined with the value of CYLC_CYCLING_MODE
+                                   #   when in any datetime cycling mode
+
+CYLC_WORKFLOW_FINAL_CYCLE_POINT    # Final cycle point
+CYLC_WORKFLOW_INITIAL_CYCLE_POINT  # Initial cycle point
+CYLC_WORKFLOW_ID                   # Workflow ID
+                                   # e.g. "a/b/c/run1"
+CYLC_WORKFLOW_NAME                 # Workflow ID with the run name removed
+                                   # (use CYLC_WORKFLOW_ID for most purposes)
+                                   # e.g. "a/b/c"
+CYLC_WORKFLOW_NAME_BASE            # The basename of the workflow name
+                                   # (use CYLC_WORKFLOW_ID for most purposes)
+                                   # e.g. "c"
+CYLC_UTC                           # UTC mode, True or False
+TZ                                 # Set to "UTC" in UTC mode or not defined
+
+CYLC_WORKFLOW_RUN_DIR              # Location of the run directory in
+                                   # job host, e.g. ~/cylc-run/foo
+CYLC_WORKFLOW_HOST                 # Host running the workflow process
+CYLC_WORKFLOW_OWNER                # User ID running the workflow process
+
+CYLC_WORKFLOW_SHARE_DIR            # Workflow (or task!) shared directory (see below)
+CYLC_WORKFLOW_UUID                 # Workflow UUID string
+CYLC_WORKFLOW_WORK_DIR             # Workflow work directory (see below)
+
+CYLC_TASK_JOB                      # Job identifier expressed as
+                                   # CYCLE-POINT/TASK-NAME/SUBMIT-NUMBER
+                                   #   e.g. 20110511T1800Z/t1/01
+
+CYLC_TASK_CYCLE_POINT              # Cycle point, e.g. 20110511T1800Z
+ISODATETIMEREF                     # Reference time for the `isodatetime` command,
+                                   #   defined with the value of CYLC_TASK_CYCLE_POINT
+                                   #   when in any datetime cycling mode
+
+CYLC_TASK_NAME                     # Job's task name, e.g. t1
+CYLC_TASK_ID                       # Task instance identifier CYCLE-POINT/TASK-NAME
+                                   #   e.g. 20110511T1800Z/t1
+
+CYLC_TASK_SUBMIT_NUMBER            # Job's submit number, e.g. 1,
+                                   #   increments with every submit
+CYLC_TASK_TRY_NUMBER               # Number of execution tries, e.g. 1
+                                   #   increments with automatic execution retry delays.
+CYLC_TASK_FLOW_NUMBERS             # Flows this task belongs to, e.g. 1,2
+
+CYLC_TASK_LOG_DIR                  # Location of the job log directory
+                                   #   e.g. ~/cylc-run/foo/log/job/20110511T1800Z/t1/01/
+CYLC_TASK_LOG_ROOT                 # The job script path
+                                   #   e.g. ~/cylc-run/foo/log/job/20110511T1800Z/t1/01/job
+CYLC_TASK_WORK_DIR                 # Location of task work directory (see below)
+                                   #   e.g. ~/cylc-run/foo/work/20110511T1800Z/t1
+
+CYLC_TASK_NAMESPACE_HIERARCHY      # Linearised family namespace of the task,
+                                   #   e.g. root postproc t1
+
+CYLC_TASK_COMMS_METHOD             # Set to "ssh" if communication method is "ssh"
+CYLC_TASK_SSH_LOGIN_SHELL          # With "ssh" communication, if set to "True",
+                                   #   use login shell on workflow host
+
+
+

Some global shell variables are also defined in the job script, but not +exported to subshells:

+
CYLC_FAIL_SIGNALS               # List of signals trapped by the error trap
+CYLC_VACATION_SIGNALS           # List of signals trapped by the vacation trap
+CYLC_TASK_MESSAGE_STARTED_PID   # PID of "cylc message" job started" command
+CYLC_TASK_WORK_DIR_BASE         # Alternate task work directory,
+                                #   relative to the workflow work directory
+
+
+
+
+

Workflow Share Directories

+

The workflow share directory is created automatically under the +workflow run directory as a convenient shared space for tasks. The location is +available to tasks as $CYLC_WORKFLOW_SHARE_DIR. In a cycling workflow, +output files are typically held in cycle point sub-directories of this.

+

The top level share directory location can be changed, e.g. to a large data +area, by global config settings under global.cylc[install][symlink dirs].

+

If your workflow creates or installs executables or Python libraries +as it is running, these can be placed in:

+
    +
  • share/bin/ - for executables. This location is automatically added to PATH +(before the top-level bin/ in the run dir).

  • +
  • share/lib/python/ - for Python modules. This location is automatically added +to $PYTHONPATH (before the top-level lib/python/ in the run dir).

  • +
+
+

Note

+

Cylc will not create these folders.

+
+ +
+
+

Task Work Directories

+

Job scripts are executed from within work directories created automatically under the workflow run directory. A task can +access its own work directory via $CYLC_TASK_WORK_DIR (or simply $PWD +if it does not change to another location at runtime). By default the location +contains task name and cycle point, to provide a unique workspace for every +instance of every task.

+

The top level work directory location can be changed, e.g. to a large data +area, by global config settings under global.cylc[install][symlink dirs].

+
+
+
+

Remote Task Hosting

+

Job platforms are defined in global.cylc[platforms].

+

If a task declares a different platform to that where the scheduler is running, +Cylc uses non-interactive SSH to submit the job to the platform job +runner on one of the platform hosts. Workflow source files will be installed +on the platform, via the associated global.cylc[install targets], just +before the first job is submitted to run there.

+
[runtime]
+   [[foo]]
+       platform = orca
+
+
+

For this to work:

+
    +
  • Non-interactive SSH is required from the scheduler host +to the platform hosts

  • +
  • Cylc must be installed on the hosts of the destination platform

    +
      +
    • If polling task communication is used, there is no other requirement

    • +
    • If SSH task communication is configured, non-interactive SSH is required +from the job platform to the scheduler platform

    • +
    • If TCP (default) task communication is configured, the task platform +should have access to the Cylc ports on the scheduler host

    • +
    +
  • +
+

Platforms, like other runtime settings, can be declared globally in the root +family, or in other families, or for individual tasks.

+
+

Note

+

The platform known as localhost is the platform where the scheduler +is running, in many cases a dedicated server and not your desktop.

+
+
+

Internal Platform and Host Selection

+

The [runtime][<namespace>]platform item points to either a +platform or a +platform group.

+

Cylc platforms allow you to configure compute platforms +you wish Cylc to run jobs on.

+

Platform groups allow you to group together platforms +any of which would be suitable for a given job. +Platform groups can improve robustness by allowing jobs to be submitted on +any platform in the group, as well as providing an interface for +basic load balancing.

+

Platforms are selected from a platform group once, +when a job is submitted.

+

Hosts within a platform are re-selected each time the scheduler +needs to communicate with a job.

+
+

See also

+

Platform Configuration: For details of how Platforms and +Platform Groups are set up and in-depth examples.

+
+
+
+

External Platform Selection Scripts

+
+

Deprecated since version 8.0.0: Cylc 8 can select hosts from a group of suitable hosts listed in the +platform config, so in many cases this logic should no longer be necessary.

+
+

Instead of hardwiring platform names into the workflow configuration you can +give a command that prints a platform name, or an environment variable, as the +value of [runtime][<namespace>]platform.

+

For example:

+
+
flow.cylc
+
[runtime]
+    [[mytask]]
+        platform = $(script-which-returns-a-platform-name)
+
+
+
+

Job hosts are always selected dynamically, for the chosen platform or +platform group.

+
+

Caution

+

If $(script-which-returns-a-platform-name) returns a non-zero exit +code then the scheduler will assign the +submit-failed state to this job. +If you have submit retries set up for the job, the scheduler will retry +running your platform selection script in the same was is it would for +any other submission failure.

+
+
+
+

Remote Job Log Directories

+

Job stdout and stderr streams are written to log files +under the workflow run directory (see Task stdout and stderr Logs). +For remote tasks the same directory is used, on the job host.

+
+
+
+

Implicit Tasks

+

An implicit task is one that appears in the graph but is not defined under +flow.cylc[runtime].

+

Depending on the value of flow.cylc[scheduler]allow implicit tasks, +Cylc can automatically create default task definitions for these, to submit +local dummy jobs that just return the standard job status messages.

+

Implicit tasks can be used to mock up functional workflows very quickly. A +default script can be added to the root family, e.g. to slow job execution +down a little. Here is a complete workflow definition using implicit tasks:

+
[scheduler]
+    allow implicit tasks = True
+[scheduling]
+    [[graph]]
+        R1 = "prep => run-a & run-b => done"
+[runtime]
+    [[root]]
+        script = "sleep 10"
+
+
+
+

Warning

+

Implicit tasks are somewhat dangerous because they can easily be created by +mistake: misspelling a task’s name divorces it from its runtime definition.

+
+

For this reason implicit tasks are not allowed by default, and if used they +should be turned off once the real task definitions are complete.

+

You can get the convenience without the danger with a little more effort, by +adding empty runtime placeholders instead of allowing implicit tasks:

+
[scheduling]
+    [[graph]]
+        R1 = "prep => run-a & run-b => done"
+[runtime]
+    [[root]]
+        script = "sleep 10"
+    [[prep]]
+    [[run-a, run-b]]
+    [[done]]
+
+
+
+
+

Task Retry On Failure

+ +

Tasks can have a list of ISO8601 durations as retry +intervals. If the job fails the task will return to the waiting state +with a clock-trigger configured with the next retry delay.

+
+

Note

+

Tasks only enter the submit-failed state if job submission fails with no +retries left. Otherwise they return to the waiting state, to wait on the +next try.

+

Tasks only enter the failed state if job execution fails with no retries +left. Otherwise they return to the waiting state, to wait on the next try.

+
+

In the following example, tasks bad and flaky each have 3 retries +configured, with a 10 second delay between. On the final try, bad fails +again and goes to the failed state, while flaky succeeds and triggers +task whizz downstream. The scheduler will then stall because +bad failed (which is a final status) with incomplete outputs.

+
[scheduling]
+    [[graph]]
+        R1 = """
+            bad => cheese
+            flaky => whizz
+         """
+[runtime]
+    [[bad]]
+        # retry 3 times then fail
+        script = """
+            sleep 10
+            false
+        """
+        execution retry delays = 3*PT10S
+    [[flaky]]
+        # retry 3 times then succeed
+        script = """
+            sleep 10
+            test $CYLC_TASK_TRY_NUMBER -gt 3
+        """
+        execution retry delays = 3*PT10S
+    [[cheese, whizz]]
+        script = "sleep 10"
+
+
+
+
+

Task Event Handling

+

Task event handlers allow configured commands to run when task events occur.

+
+

Note

+

Cylc supports workflow events e.g. startup and shutdown +and task events e.g. submitted and failed.

+

See also Workflow Events.

+
+

Event handlers can be used to send a message, raise an alarm, or whatever you +like. They can even call cylc commands to intervene in the workflow.

+

Task event handlers are configured by +flow.cylc[runtime][<namespace>][events].

+
+

Note

+

Task event handlers are called by the scheduler, not by the task +jobs that generate the events - so they do not see the job environment.

+
+

Event handlers can be stored in the workflow bin directory, or anywhere in +$PATH in the scheduler environment.

+

They should return quickly to avoid tying up the scheduler process pool - +see External Command Execution.

+
+

Event-Specific Handlers

+

Event-specific handlers are configured by <event> handlers +under [runtime][<namespace>][events], where <event> +can be:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Event

Description

submitted

job submitted

submission retry

job submission failed but will retry later

submission failed

job submission failed

started

job started running

retry

job failed but will retry later

failed

job failed

succeeded

job succeeded

submission timeout

job timed out in the submitted state

execution timeout

job timed out in the running state

warning

scheduler received a message of severity WARNING from job

critical

scheduler received a message of severity CRITICAL from job

custom

scheduler received a message of severity CUSTOM from job
(note: literally, the word CUSTOM)

expired

task expired and will not submit (too far behind)

late

task running later than expected

+

Values should be a list of commands, command lines, or command line templates +(see below) to call if the specified event is triggered.

+
+
+

General Event Handlers

+

Alternatively you can configure a list of generic event handlers to be run +for configured handler events.

+
+
handler events

A list of events which may include any of the above +events (e.g. submission failed or warning) or +any of a task’s custom outputs.

+
+
handlers

A list of commands to be run for these events. +Information about the event can be provided using +Task Event Template Variables.

+
+
+

Example:

+
handlers = """
+   my-handler %(event)s %(workflow)s,
+   echo %(workflow)s-%(event)s >> my-log-file
+"""
+handler events = submission failed, failed, warning, my-custom-output
+
+
+
+
+

Task Event Template Variables

+
+

The following variables are available to task event handlers.

+

They can be templated into event handlers with Python percent style string +formatting e.g:

+
%(workflow)s is running on %(host)s
+
+
+

The %(event)s string, for instance, will be replaced by the actual +event name when the handler is invoked.

+

If no templates or arguments are specified the following default command +line will be used:

+
<event-handler> %(event)s %(workflow)s %(id)s %(message)s
+
+
+
+

Note

+

Substitution patterns should not be quoted in the template strings. +This is done automatically where required.

+
+

For an explanation of the substitution syntax, see +String Formatting Operations in the Python documentation.

+
+
+event
+

Event name.

+
+ +
+
+workflow
+

Workflow ID.

+
+ +
+
+suite
+

Workflow ID.

+
+

Deprecated since version 8.0.0: Use “workflow”.

+
+
+ +
+
+uuid
+

The unique identification string for this workflow run.

+

This string is preserved for the lifetime of the scheduler and is restored +from the database on restart.

+
+ +
+
+suite_uuid
+

The unique identification string for this workflow run.

+
+

Deprecated since version 8.0.0: Use ‘uuid’.

+
+
+ +
+
+point
+

The task’s cycle point.

+
+ +
+
+submit_num
+

The job’s submit number.

+

This starts at 1 and increments with each additional job submission.

+
+ +
+
+try_num
+

The job’s try number.

+

The number of execution attempts. +It starts at 1 and increments with automatic +flow.cylc[runtime][<namespace>]execution retry delays.

+
+ +
+
+id
+

The task ID (i.e. %(point)/%(name)).

+
+ +
+
+message
+

Events message, if any.

+
+ +
+
+job_runner_name
+

The job runner name.

+
+ +
+
+batch_sys_name
+

The job runner name.

+
+

Deprecated since version 8.0.0: Use “job_runner_name”.

+
+
+ +
+
+job_id
+

The job ID in the job runner.

+

I.E. The job submission ID. For background jobs this is the process ID.

+
+ +
+
+batch_sys_job_id
+

The job ID in the job runner.

+
+

Deprecated since version 8.0.0: Use “job_id”.

+
+
+ +
+
+submit_time
+

Date-time when the job was submitted, in ISO8601 format.

+
+ +
+
+start_time
+

Date-time when the job started, in ISO8601 format.

+
+ +
+
+finish_time
+

Date-time when the job finished, in ISO8601 format.

+
+ +
+
+platform_name
+

The name of the platform where the job is submitted.

+
+ +
+
+user@host
+

The name of the platform where the job is submitted.

+
+

Deprecated since version 8.0.0: Use “platform_name”.

+
+
+

Changed in version 8.0.0: This now provides the platform name rather than user@host.

+
+
+ +
+
+name
+

The name of the task.

+
+ +
+
+task_url
+

The URL defined in the task’s metadata.

+
+

Deprecated since version 8.0.0: Use URL from <task metadata>.

+
+
+ +
+
+workflow_url
+

The URL defined in the workflow’s metadata.

+
+

Deprecated since version 8.0.0: Use workflow_URL from workflow_<workflow metadata>.

+
+
+ +
+
+<task metadata>
+

Any task metadata defined in +flow.cylc[runtime][<namespace>][meta] can be used e.g:

+
+
%(title)s

Task title

+
+
%(URL)s

Task URL

+
+
%(importance)s

Example custom task metadata

+
+
+
+ +
+
+workflow_<workflow metadata>
+

Any workflow metadata defined in +flow.cylc[meta] can be used with the workflow_ +e.g. prefix:

+
+
%(workflow_title)s

Workflow title

+
+
%(workflow_URL)s

Workflow URL.

+
+
%(workflow_rating)s

Example custom workflow metadata.

+
+
+
+ +
+ +
+
+

Examples

+

The following flow.cylc snippets illustrate the two (general and +task-specific) ways to configure event handlers:

+
[runtime]
+    [[foo]]
+        script = test ${CYLC_TASK_TRY_NUMBER} -eq 2
+        execution retry delays = PT0S, PT30S
+        [[[events]]]  # event-specific handlers:
+            retry handlers = notify-retry.py
+            failed handlers = notify-failed.py
+
+
+
[runtime]
+    [[foo]]
+        script = """
+            test ${CYLC_TASK_TRY_NUMBER} -eq 2
+            cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" 'oopsy daisy'
+        """
+        execution retry delays = PT0S, PT30S
+        [[[events]]]  # general handlers:
+            handlers = notify-events.py
+            # Note: task output name can be used as an event in this method
+            handler events = retry, failed, oops
+        [[[outputs]]]
+            oops = oopsy daisy
+
+
+
+
+

Built-in Email Event Handler

+

To send an email on task events, configure relevant tasks with a list of events +to handle by email. Custom task output names can also be used as event names, +in which case the event triggers when the output message is received.

+

E.g. to send an email on task failed, retry, and a custom message event:

+
[runtime]
+    [[foo]]
+        script = """
+            test ${CYLC_TASK_TRY_NUMBER} -eq 3
+            cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" 'oopsy daisy'
+        """
+        execution retry delays = PT0S, PT30S
+        [[[events]]]
+            mail events = failed, retry, oops
+        [[[outputs]]]
+            oops = oopsy daisy
+
+
+

By default, event emails will be sent to the current user with:

+
    +
  • to: set as $USER

  • +
  • from: set as notifications@$(hostname)

  • +
  • SMTP server at localhost:25

  • +
+

These can be configured using the settings:

+ +

The scheduler batches events over a 5 minute interval, by default, to avoid +flooding your Inbox if many events occur in a short time. The batching interval +can be configured with [scheduler][mail]task event batch interval.

+
+
+

Late Events

+
+

Warning

+

The scheduler can only check for lateness once a task has appeared in its +active task window. In Cylc 8 this is usually when the task is actually +ready to run, which severely limits the usefulness of late events as +currently implemented.

+
+

If a real time (clock-triggered) workflow performs fairly consistently from one +cycle to the next, you may want to be notified when certain tasks are running +late with respect the time they normally trigger in each cycle.

+

Cylc can generate a late event if a task has not triggered by a given offset +from its cycle point in real time. For example, if a task forecast normally +triggers at 30 minutes after cycle point, a late event could be configured like this:

+
[runtime]
+   [[forecast]]
+        script = run-model.sh
+        [[[events]]]
+            late offset = PT40M  # allow a 10 minute delay
+            late handlers = my-handler %(message)s
+
+
+
+

Warning

+

Late offset intervals are not computed automatically so be careful to update +them after any workflow change that affects triggering times.

+
+ +
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/writing-workflows/scheduler.html b/nightly_8.4/html/user-guide/writing-workflows/scheduler.html new file mode 100644 index 00000000000..2afb5ea6e8d --- /dev/null +++ b/nightly_8.4/html/user-guide/writing-workflows/scheduler.html @@ -0,0 +1,602 @@ + + + + + + + Scheduler Configuration — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Scheduler Configuration

+

The flow.cylc[scheduler] section configures certain aspects of +scheduler behaviour at the workflow level.

+

Many of these configurations can also be defined at the site or user level in +the global.cylc[scheduler] section where it applies to all +workflows.

+
+

Workflow Events

+

There are two types of event in Cylc:

+
    +
  • workflow events e.g. startup and shutdown, which pertain to the scheduler

  • +
  • task events e.g. submitted and failed, which pertain to tasks.

  • +
+

This section covers workflow events, for +task events see Task Event Handling.

+

Event Handlers

+

Workflow events have “handlers” (i.e. hooks) which allow configured commands to +run when workflow events occur. These can be configured by:

+ +

Abort On Event

+

As well as event handlers, you can tell the scheduler to abort (i.e., shut down +immediately with error status) on certain workflow events, using the +abort on ... configurations.

+

Configuration

+

Some workflow events have related configurations e.g. for setting the timeout.

+

List of workflow events:

+
+
+startup
+
+
Event Handler:
+

startup handlers

+
+
+

The scheduler was started or restarted.

+

E.G. using one of these commands cylc play, cylc vip or cylc vr.

+
+ +
+
+shutdown
+
+
Event Handler:
+

shutdown handlers

+
+
+

The scheduler was shut down.

+

E.G. using the cylc stop command.

+
+ +
+
+abort
+
+
Event Handler:
+

abort handlers

+
+
+

The scheduler shut down early with error status, due to a fatal error +condition or a configured timeout.

+
+ +
+
+workflow timeout
+
+
Configuration:
+

workflow timeout

+
+
Event Handler:
+

workflow timeout handlers

+
+
Abort On Event:
+

abort on workflow timeout

+
+
+

The workflow run timed out.

+

The timer starts counting down at scheduler startup. It resets on workflow +restart.

+

Note, the abort event is not raised by “Abort On Event” handlers.

+
+ +
+
+stall
+
+
Event Handler:
+

stall handlers

+
+
+

The workflow stalled (i.e. the scheduler cannot make any +further progress due to runtime events).

+

E.G. a task failure is blocking the pathway through the graph.

+
+ +
+
+stall timeout
+
+
Configuration:
+

stall timeout

+
+
Event Handler:
+

stall timeout handlers

+
+
Abort On Event:
+

abort on stall timeout

+
+
+

The workflow timed out after stalling.

+
+ +
+
+inactivity timeout
+
+
Configuration:
+

inactivity timeout

+
+
Event Handler:
+

inactivity timeout handlers

+
+
Abort On Event:
+

abort on inactivity timeout

+
+
+

The workflow timed out with no activity (i.e. a period with no job +submissions or task messages).

+

This can be useful for system administrators to help catch workflows which +have become stalled on external conditions or system issues.

+
+ +
+
+restart timeout
+
+
Configuration:
+

restart timeout

+
+
+

If a workflow that has run to completion is restarted, the scheduler will +have nothing to do so will shut down. This timeout gives the user a grace +period in which to trigger new tasks to continue the workflow run.

+
+ +
+

Mail Events

+

Cylc can send emails for workflow events, these are configured by +flow.cylc[scheduler][events]mail events.

+

For example with the following configuration, emails will be sent if a +scheduler stalls or shuts down for an unexpected reason.

+
[scheduler]
+    [[events]]
+        mail events = stall, abort
+
+
+

Email addresses and servers are configured by +global.cylc[scheduler][mail].

+

Workflow event emails can be customised using +flow.cylc[scheduler][mail]footer, +Workflow Event Template Variables can be used.

+

For example to integrate with the Cylc 7 web interface (Cylc Review) the mail +footer could be configured with a URL:

+
[scheduler]
+    [[events]]
+        mail footer = http://cylc-review/taskjobs/%(owner)s/?suite=%(workflow)s
+
+
+
+
+

Custom Event Handlers

+

Cylc can also be configured to invoke scripts on workflow events.

+

Event handler scripts can be stored in the workflow bin directory, or +anywhere in $PATH in the scheduler environment.

+

They should return quickly to avoid tying up the scheduler process pool - +see External Command Execution.

+

Contextual information can be passed to the event handler via +Workflow Event Template Variables.

+

For example the following configuration will write some information to a file +when a workflow is started:

+
+
~/cylc-run/<workflow-id>/bin/my-handler
+
#!/bin/bash
+
+echo "Workflow $1 is running on $2:$3" > info
+
+
+
+
+
flow.cylc or global.cylc
+
[scheduler]
+    [[events]]
+        startup handlers = my-handler %(workflow)s %(host) %(port)
+
+
+
+
+

Note

+

If you wish to use custom Python Libraries in an event handler you +need to add these to CYLC_PYTHONPATH rather than PYTHONPATH.

+
+
+
+

Workflow Event Template Variables

+
+

The following variables are available to workflow event handlers.

+

They can be templated into event handlers with Python percent style string +formatting e.g:

+
%(workflow)s is running on %(host)s
+
+
+
+

Note

+

Substitution patterns should not be quoted in the template strings. +This is done automatically where required.

+
+

For an explanation of the substitution syntax, see +String Formatting Operations in the Python documentation.

+
+
+event
+

The type of workflow event that has occurred e.g. stall.

+
+ +
+
+message
+

Additional information about the event.

+
+ +
+
+workflow
+

The workflow ID

+
+ +
+
+host
+

The host where the workflow is running.

+
+ +
+
+port
+

The port where the workflow is running.

+
+ +
+
+owner
+

The user account under which the workflow is running.

+
+ +
+
+uuid
+

The unique identification string for this workflow run.

+

This string is preserved for the lifetime of the scheduler and is restored +from the database on restart.

+
+ +
+
+workflow_url
+

The URL defined in flow.cylc[meta]URL.

+
+ +
+
+suite
+

The workflow ID

+
+

Deprecated since version 8.0.0: Use “workflow”.

+
+
+ +
+
+suite_uuid
+

The unique identification string for this workflow run.

+
+

Deprecated since version 8.0.0: Use “uuid”.

+
+
+ +
+
+suite_url
+

The URL defined in flow.cylc[meta]URL.

+
+

Deprecated since version 8.0.0: Use “workflow_url”.

+
+
+ +
+ +
+
+
+

External Command Execution

+

Job submission commands, event handlers, and job poll and kill commands, are +executed by the scheduler in a subprocess pool. The pool is size can +be configured with global.cylc[scheduler]process pool size.

+

Event handlers should be lightweight and quick-running because they tie up +a process pool member until complete, and the workflow will appear to stall if +the pool is saturated with long-running processes.

+

To protect the scheduler, processes are killed on a timeout +(global.cylc[scheduler]process pool timeout). This will be +logged by the scheduler. If a job submission gets killed, the +associated task goes to the submit-failed state.

+
+
+

Submitting Workflows To a Pool Of Hosts

+
+
Configured by:
+

global.cylc[scheduler][run hosts].

+
+
+

By default cylc play will run workflows on the machine where the command +was invoked.

+

Cylc supports configuring a pool of hosts for workflows to run on, +cylc play will automatically pick a host and submit the workflow to it.

+
+

Host Pool

+
+
Configured by:
+

global.cylc[scheduler][run hosts]available.

+
+
+

The hosts must:

+
    +
  1. Share a common $HOME directory and therefore a common file system +(with each other and anywhere the cylc play command is run).

  2. +
  3. Share a common Cylc global config (global.cylc).

  4. +
  5. Be set up to allow passwordless SSH between them.

  6. +
+

Example:

+
[scheduler]
+    [[run hosts]]
+        available = host_1, host_2, host_3
+
+
+
+
+

Load Balancing

+
+
Configured by:
+

global.cylc[scheduler][run hosts]ranking.

+
+
+

Cylc can balance the load on the configured “run hosts” by ranking them in +order of available resource or by excluding hosts which fail to meet certain +criterion.

+

Example:

+
[scheduler]
+    [[run hosts]]
+        available = host_1, host_2, host_3
+        ranking = """
+            # filter out hosts with high server load
+            getloadavg()[2] < 5
+
+            # pick the host with the most available memory
+            virtual_memory().available
+        """
+
+
+

For more information see global.cylc[scheduler][run hosts]ranking.

+
+
+

Workflow Migration

+
+
Configured by:
+

global.cylc[scheduler][run hosts]condemned.

+
+
+

Cylc has the ability to automatically stop workflows running on a particular +host and optionally, restart them on a different host. This can be useful if a +host needs to be taken off-line, e.g. for scheduled maintenance.

+

Example:

+
[scheduler]
+    [[run hosts]]
+        available = host_1, host_2, host_3
+        # tell workflows on host_1 to move to another available host
+        condemned = host_1
+
+
+
+

Note

+

This feature requires the [auto restart] +plugin to be enabled, e.g. in the configured list of +plugins.

+
+

For more information see: global.cylc[scheduler][run hosts]ranking.

+
+
+

Platform Configuration

+

From the perspective of a running scheduler localhost is the +scheduler host.

+

The localhost platform is configured by +global.cylc[platforms][localhost].

+

It configures:

+ +
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/writing-workflows/scheduling.html b/nightly_8.4/html/user-guide/writing-workflows/scheduling.html new file mode 100644 index 00000000000..7c380d78017 --- /dev/null +++ b/nightly_8.4/html/user-guide/writing-workflows/scheduling.html @@ -0,0 +1,2176 @@ + + + + + + + Scheduling Configuration — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Scheduling Configuration

+
+

Related Tutorial

+

Scheduling Tutorial

+
+

The [scheduling] section of the flow.cylc file +defines what tasks exist in the workflow, in a dependency graph, +and when they should run, relative to each other and to constraints such as +clock triggers, external triggers, and internal queues

+
+

The Graph

+
+

Related Tutorial

+

Graph Tutorial

+
+

The graph defines a workflow in terms of its tasks and +the dependencies between them.

+

A Cylc graph is composed of one or more graph strings which use a special syntax to define the dependencies between tasks:

+
    +
  • arrow symbols => declare dependencies

  • +
  • logical operators & (AND) and | (OR) can be used to write +conditional dependencies.

  • +
+

For example:

+
# baz will not be run until both foo and bar have succeeded
+foo & bar => baz
+
+
+

Graph strings are configured under the [scheduling][graph] section +of the flow.cylc file:

+
[scheduling]
+    [[graph]]
+        R1 = """
+            foo & bar => baz
+        """
+
+
+

In this example R1 is a recurrence expression that +defines how often, and on what cycle interval, to run this part of the graph. +For example, R1 means run once, and P1D means run repeatedly on a 1-day +cycle.

+

Graph strings may contain blank lines, arbitrary white space and comments e.g:

+
[scheduling]
+    [[graph]]
+        R1 = """
+            foo & bar => baz  # baz depends on foo and bar
+
+        """
+
+
+

Graphs can be broken down into pairs of triggers, where the +left side is a single task output, or a logical expression involving several of +them, and the right side is the task or family that triggers when the output +(or expression) is completed.

+

In the case of cycling tasks, triggers are valid for cycle points matching the +recurrence expression for the graph string. For example this graph:

+
[scheduling]
+    [[graph]]
+        T00,T12 = "A => B"
+
+
+

implies that B triggers off of A (i.e. off of the A:succeeded output) +for cycle points where the hour matches 00 or 12. To define intercycle +dependencies, attach an offset indicator to the left side of a pair:

+
[scheduling]
+    [[graph]]
+        T00,T12 = "A[-PT12H] => B"
+
+
+

This means task B triggers off of task A[-PT12H] (12 hours before, with +respect to cycle point) at every point with hours matching 00 and 12 in +a sequence starting at the initial cycle point. +Note: current cycle point is implicit - only offsets need to be specified - +because most tasks depend only on others with the same cycle point.

+

Cycle point offsets can only appear on the left side of an arrow. However, +A => B[-PT6H], which is illegal, can be reformulated as a future +trigger A[+PT6H] => B (see Intercycle Triggers). It is also +possible to combine multiple offsets within a cycle point offset e.g.

+
[scheduling]
+    [[graph]]
+        T00,T12 = "A[-P1D-PT12H] => B"
+
+
+

This means that B triggers off A[-P1D-PT12H] (1 day and 12 hours before) +at each cycle point.

+

Triggers can be chained together. This graph:

+
T00, T12 = """
+    A => B  # B triggers off A
+    B => C  # C triggers off B
+"""
+
+
+

is equivalent to this:

+
T00, T12 = "A => B => C"
+
+
+

All triggers defined for the same task combine, so this:

+
T00, T12 = """
+    A => X  # X triggers off A
+    B => X  # X also triggers off B
+"""
+
+
+

is equivalent to this:

+
T00, T12 = "A & B => X"  # X triggers off A AND B
+
+
+

In summary, the branching tree structure of a dependency graph can +be partitioned into lines (in the flow.cylc graph string) of +dependency pairs or chains, in any way you like. Use white space and comments +to make the graph as clear as possible.

+
# B triggers if A succeeds, then C and D trigger if B succeeds:
+R1 = "A => B => C & D"
+
+# which is equivalent to this:
+R1 = """
+    A => B => C
+    B => D
+"""
+
+# and to this:
+R1 = """
+    A => B => D
+    B => C
+"""
+
+# and to this:
+R1 = """
+    A => B
+    B => C
+    B => D
+"""
+
+# and it can even be written like this:
+R1 = """
+    A => B # blank line follows:
+
+    B => C # comment ...
+    B => D
+"""
+
+
+
+

Splitting Up Long Graph Lines

+

It is not necessary to use the fragile line continuation marker \ to split +long graph lines. You can break at dependency arrows (=>) and operators +(&, |), or split long chains into smaller ones. This graph:

+
R1 = "A & B => C"
+
+
+

is equivalent to this:

+
R1 = """
+    A & B =>
+    C
+"""
+
+
+

and also to this:

+
R1 = """
+    A &
+    B => C
+"""
+
+
+
+

Note

+

Multiple graph strings add together to make the complete workflow graph.

+
+
+

Changed in version 8.0.0: Graph strings can be broken on & and | as well as =>.

+
+
+
+
+

Graph Types

+
+

Non-Cycling

+

The following is a small workflow of non-cycling tasks; these all have a +single cycle point (1), and once they’re all finished the scheduler +shuts down.

+
+
+
[scheduling]
+    [[graph]]
+        R1 = "foo => bar & baz => qux"
+
+
+
+
+
+../../_images/test1.png +
+
+
+
+
+

Cycling Graphs

+

For cycling tasks we give a recurrence expression that defines a sequence of +cycle points for which the graph string is valid, as demonstrated here for a +small workflow of cycling tasks:

+
+
+
[scheduling]
+    [[graph]]
+       # (note no dependence between cycle points)
+        T00,T12 = "foo => bar & baz => qux"
+
+
+
+
+
+../../_images/test2.png +
+
+
+
+

Related Tutorial

+

Datetime Tutorial

+
+

For example in the following scenario:

+
[scheduling]
+    [[graph]]
+        T06 = foo => bar
+
+
+

T06 means “Run every day starting at 06:00 after the +initial cycle point”. Cylc allows you to start (or end) at any particular +time, repeat at whatever frequency you like, and even optionally limit the +number of repetitions.

+
+
+
+

Cycling Syntax Rules

+

Datetime cycling information is made up of:

+
    +
  • a datetime that typically specifies the start +point of the sequence

  • +
  • an interval between points in the sequence

  • +
  • and an optional limit on the number of points in the sequence

  • +
+

The time is assumed to be in UTC unless you set +[scheduler]cycle point time zone.

+
+

Attention

+
+

Changed in version 8.0.0.

+
+

At Cylc 7 the time zone was assumed to be local time unless +[scheduler]cycle point time zone or [scheduler]UTC mode +was set. If your workflow is running in +Cylc 7 compatibility mode +this remains the case.

+
+

The calendar is assumed to be the proleptic Gregorian calendar unless +you set [scheduling]cycling mode.

+

The syntax is based on the ISO 8601 datetime standard, which includes +the representation of datetimes and intervals. Cylc (optionally) allows these +representations to be heavily condensed by omitting information that can be +inferred from context (rules below).

+
+

Important

+

Cycle points in Cylc are just task labels that anchor dependence on +other tasks, and which tasks can use to determine their current cycle +point. Datetime cycle points have no relation to wallclock (real) time +except where specific tasks, if any, depend on clock triggers.

+
+

There are three ISO 8601 recurrence formats supported by Cylc, detailed below +in order from most commonly used to least commonly used.

+
+

Format 3: R[limit?]/[datetime]/[interval]

+

The most common full form for recurrences is +R[limit?]/[datetime]/[interval]. This is format number 3 in the ISO 8601 +standard. The datetime specifies the start of the cycling sequence. +For example, R3/2000-01-01T00Z/P2D means “run 3 times, every 2 days, +starting at 2000-01-01T00Z (midnight, Jan 1st 2000)”; the list of points +on this sequence is:

+
2000-01-01T00Z
+2000-01-03T00Z
+2000-01-05T00Z
+
+
+

In Cylc, this form can be condensed to:

+
R[limit?]/[datetime]
+R[limit?]//[interval]
+[datetime]/[interval]
+R[limit?] # Special limit of 1 case
+[datetime]
+[interval]
+
+
+

Here are some examples for each form:

+
R5/T00            # Run 5 times at 00:00 every day
+R//PT1H           # Run every hour (Note the R// is optional)
+20000101T06Z/P1D  # Run every day starting at 06:00 1st Jan 2000
+R1                # Run once at the initial cycle point
+R1/20000101T00Z   # Run once at 00:00 1st Jan 2000
+P1Y               # Run every year
+
+
+
+

Note

+

T00 is an example of [datetime], with an +inferred 1 day period and no limit (it is short for R/T00).

+
+

Where some or all datetime information is omitted, it is inferred to +be relative to the initial cycle point. For example, T00 +by itself would mean the next occurrence of midnight that follows, or is, the +initial cycle point. +PT6H means 6 hours after the initial cycle point. +-P1D means 1 day before the initial cycle point. The default is the initial +cycle point itself.

+

If the interval is omitted and some (but not all) datetime information is +omitted, it is inferred to be a single unit above the largest given specific +datetime unit. For example, the largest given specific unit in T00 is +hours, so the inferred interval is 1 day (daily), P1D.

+

If the limit is omitted, unlimited cycling is assumed. This will be +bounded by the workflow’s final cycle point if given.

+
+
+

Format 4: R[limit?]/[interval]/[datetime]

+

Another supported recurrence form is: +R[limit?]/[interval]/[datetime] (format number 4 in the ISO 8601 standard). +This uses the datetime as the end of the cycling sequence rather than the start. +For example, R3/P5D/2014-04-30T06 means “run 3 times, every 5 days, ending +at 2014-04-30T06 (06:00, April 30th 2014)”; the list of points on this +sequence is:

+
2014-04-20T06
+2014-04-25T06
+2014-04-30T06
+
+
+

This form can be used to get special behaviour relative to +the final cycle point.

+

We can also represent this in Cylc with a collapsed form:

+
R[limit?]/[interval]
+R[limit?]//[datetime]
+[interval]/[datetime]
+
+
+

So, for example, you can write:

+
R1//+P0D  # Run once at the final cycle point
+R5/P2D    # Run 5 times, every 2 days, ending at the final cycle point
+P2W/T00   # Run every 2 weeks ending at 00:00 before/at the final cycle point
+R//T00    # Run every day ending at 00:00 before/at the final cycle point
+
+
+
+
+

Format 1: R[limit?]/[datetime]/[datetime]

+

A less common recurrence form is R[limit?]/[datetime]/[datetime] +(format number 1 in the ISO 8601 standard). This uses the difference between +the first datetime and the second datetime to set the recurrence interval. +The first datetime is the start point. For example, +R3/2020-07-10/2020-07-15 means “run 3 times, every 5 days, starting at +2020-07-10 (midnight, July 10th 2020)”; the list of points on this sequence is:

+
2020-07-10
+2020-07-15
+2020-07-20
+
+
+
+

Caution

+

Cylc will always calculate the interval in +exact datetime units. So for the example +of R/2004/2005, the interval will be P366D (2004 is a leap year) +rather then P1Y, because year is an +inexact unit.

+
+
+

Note

+

In versions of Cylc prior to 8.0.0, this syntax was undocumented and +behaved differently, in a way which was not in accordance with the +ISO 8601 standard.

+
+
+
+

Referencing The Initial And Final Cycle Points

+

The caret and dollar symbols are shorthand for the initial and final cycle +points:

+
R1/^+PT12H  # Repeat once 12 hours after the initial cycle point
+            # R[limit]/[datetime]
+            # Equivalent to R1/+PT12H
+R1/$        # Repeat once at the final cycle point
+            # R[limit]/[datetime]
+            # Equivalent to R1//+P0D
+$-P2D/PT3H  # Repeat 3 hourly starting two days before the
+            # [datetime]/[interval]
+            # final cycle point
+
+
+
+

Note

+

There are multiple ways to write the same recurrences, for instance +the following all run once at the final cycle point:

+
R1/P0Y       # R[limit]/[interval]
+R1/P0Y/$     # R[limit]/[interval]/[datetime]
+R1/$         # R[limit]/[datetime]
+
+
+
+
+
+

The Initial Cycle Point

+

A workflow normally begins running at the initial cycle point, which defines +the start of the workflow graph:

+
[scheduling]
+    initial cycle point = 20100808T06Z
+
+
+

This can be overridden on the command line:

+
$ cylc play foo --initial-cycle-point=20120808T06Z
+
+
+
+

Setting The Initial Cycle Point Relative To The Current Time

+
+

Warning

+

Setting the initial cycle point relative to the current time only works +for datetime cycling workflows using the Gregorian calendar. +It does not work for alternative calendars like the 360, 365 or 366 day +calendars, or integer cycling.

+
+

The next and previous syntax can be used with truncated ISO 8601 +representations, to set the initial cycle point: +next(Thh:mmZ), previous(T-mm); e.g.

+
    +
  • initial cycle point = next(T15:00Z)

  • +
  • initial cycle point = previous(T09:00)

  • +
  • initial cycle point = next(T12)

  • +
  • initial cycle point = previous(T-20)

  • +
+

A list of times, separated by semicolons, can be provided, e.g. +next(T-00;T-15;T-30;T-45). At least one time is required within the +brackets, and if more than one is given, the major time unit in each (hours +or minutes) should be of the same type.

+
+

Note

+

T-00 means every hour, on the hour. The - is a placeholder for the hours column.

+
+

If an offset from the specified datetime is required, this should be +of the form previous(Thh:mm) +/- PxTy as is used +for determining cycle periods, e.g.

+
    +
  • initial cycle point = previous(T06) +P1D

  • +
  • initial cycle point = next(T-30) -PT1H

  • +
+

The next/previous syntax is interpreted first, then the offset is applied.

+

Offsets used without next or previous are interpreted as offsets from “now”.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Relative initial cycle point examples for now = 2018-03-14T15:12Z

Syntax

Interpretation

next(T-00)

2018-03-14T16:00Z

previous(T-00)

2018-03-14T15:00Z

next(T-00; T-15; T-30; T-45)

2018-03-14T15:15Z

previous(T-00; T-15; T-30; T-45)

2018-03-14T15:00Z

next(T00)

2018-03-15T00:00Z

previous(T00)

2018-03-14T00:00Z

next(T06:30Z)

2018-03-15T06:30Z

previous(T06:30) -P1D

2018-03-13T06:30Z

next(T00; T06; T12; T18)

2018-03-14T18:00Z

previous(T00; T06; T12; T18)

2018-03-14T12:00Z

next(T00; T06; T12; T18) +P1W

2018-03-21T18:00Z

PT1H

2018-03-14T16:12Z

-P1M

2018-02-14T15:12Z

+

Relative initial cycle points also work with truncated dates, including +weeks and ordinal date, using ISO 8601 truncated date representations. +Note that day-of-week should always be specified when using weeks. If a time +is not included, the calculation of the next or previous corresponding +point will be done from midnight of the current day.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Relative initial cycle point examples for now = 2018-03-14T15:12Z + using ISO8601 truncated dates.

Syntax

Description

Interpretation

next(-00)

Any century; next year 00

2100-01-01

previous(--01)

Any year; next month 01

2018-01-01

next(---01)

Any year; any month; next 1st of month

2018-04-01

previous(--1225)

Any year; previous Dec 25

2017-12-25

next(-2006)

Any century; next June in a year ending 20

2020-06-01

previous(-W101)

Any century; previous week 10 day 1

2018-03-05

next(-W-1; -W-3; -W-5)

Any year; any week; next day 1, 3 or 5

2018-03-14

next(-001; -091; -181; -271)

Any year; day 1, 91, 181 or 271

2018-04-01

previous(-365T12Z)

Any year; previous day 356 at 12Z

2017-12-31T12:00Z

+
+
+

The Environment Variable CYLC_WORKFLOW_INITIAL_CYCLE_POINT

+

At start up the initial cycle point is passed to job environments +as $CYLC_WORKFLOW_INITIAL_CYCLE_POINT and stored in the workflow +database to persist across restarts.

+

The $CYLC_WORKFLOW_INITIAL_CYCLE_POINT variable allows tasks to +check if they are running in the initial cycle point, when different behaviour +may be required. Note however that an initial R1 graph section is the +preferred way to get different behaviour at workflow start-up.

+
+
+
+

How Multiple Graph Strings Combine

+

Multiple graph strings add together to make the complete workflow graph. +Recurrences can overlap, and tasks can appear in multiple graph strings. It is +OK (but unnecessary) to define duplicate dependencies.

+
[scheduling]
+    [[graph]]
+        T00,T06,T12,T18 = "A => B => C"
+        T06,T18 = "B => C => X"
+        # duplicate prerequisite: B => C already defined at T06, T18
+
+
+

This graph can be written more concisely, with the same result, like this:

+
[scheduling]
+    [[graph]]
+        T00,T06,T12,T18 = "A => B => C"
+        # X triggers off C only at 6 and 18 hours
+        T06,T18 = "C => X"
+
+
+
+
+

Excluding Dates

+

datetimes can be excluded from a recurrence +by an exclamation mark for example PT1D!20000101 means run daily except on +the first of January 2000.

+

This syntax can be used to exclude multiple datetimes from a recurrence, using +the syntax PT1D!(20000101,20000102,...). All datetimes listed within +the parentheses will be excluded.

+
+

Note

+

The ^ and $ symbols (shorthand for the initial +and final cycle points) are both datetimes so T12!$-PT1D +is valid.

+
+

If using a run limit in combination with an exclusion, the recurrence might not +run the expected number of times. For example, in the following +workflow foo will only run once as its second run is excluded.

+
[scheduling]
+    initial cycle point = 20000101T00Z
+    final cycle point = 20000105T00Z
+    [[graph]]
+        R2/P1D!20000102 = foo
+
+
+
+
+

Excluding Recurrences

+

Exclusions may themselves be datetime recurrence sequences. Any partial +datetime or sequence after the exclamation mark will be excluded from the main +sequence.

+

For example, partial datetimes can be excluded like this:

+
PT1H ! T12                   # Run hourly but not at 12:00 from the initial
+                             # cycle point.
+T-00 ! (T00, T06, T12, T18)  # Run hourly but not at 00:00, 06:00,
+                             # 12:00, 18:00.
+PT5M ! T-15                  # Run 5-minutely but not at 15 minutes past the
+                             # hour from the initial cycle point.
+T00 ! W-1T00                 # Run daily at 00:00 except on Mondays.
+
+
+

And sequences can be excluded like this:

+
PT1H ! PT6H         # Run hourly from the initial cycle point but
+                    # not 6-hourly from the initial cycle point.
+T-00 ! PT6H         # Run hourly on the hour but not 6-hourly on the hour.
+# Same as T-00 ! T-00/PT6H (T-00 context is implied)
+# Same as T-00 ! (T00, T06, T12, T18)
+# Same as PT1H ! (T00, T06, T12, T18) Initial cycle point dependent
+
+T12 ! T12/P15D      # Run daily at 12:00 except every 15th day.
+
+R/^/P1H ! R5/20000101T00/P1D    # Any valid recurrence may be used to
+                                # determine exclusions. This example
+                                # means: Repeat every hour from
+                                # the initial cycle point, but exclude
+                                # 00:00 for 5 days from 1 January 2000.
+
+
+

You can combine exclusion sequences and single point exclusions like this:

+
T-00 ! (20000101T07, PT2H)  # Run hourly on the hour but not at 07:00
+                            # on the 1st Jan, 2000 and not 2-hourly
+                            # on the hour.
+
+
+
+
+

Advanced Examples

+

Here are several examples of Cylc graph recurrence expressions:

+
R1         # Run once at the initial cycle point
+P1D        # Run every day starting at the initial cycle point
+PT5M       # Run every 5 minutes starting at the initial cycle point
+T00/P2W    # Run every 2 weeks starting at 00:00 after the
+           # initial cycle point
++P5D/P1M   # Run every month, starting 5 days after the initial cycle point
+R1/T06     # Run once at 06:00 after the initial cycle point
+R1/P0Y     # Run once at the final cycle point
+R1/$       # Run once at the final cycle point (alternative form)
+R1/$-P3D   # Run once three days before the final cycle point
+R3/T0830   # Run 3 times, every day at 08:30 after the initial cycle point
+R3/01T00   # Run 3 times, every month at 00:00 on the first
+           # of the month after the initial cycle point
+R5/W-1/P1M # Run 5 times, every month starting on Monday
+           # following the initial cycle point
+T00!^      # Run at the first occurrence of T00 that isn't the
+           # initial cycle point
+PT1D!20000101  # Run every day days excluding 1st Jan 2000
+20140201T06/P1D    # Run every day starting at 20140201T06
+R1/min(T00,T06,T12,T18)  # Run once at the first instance
+                         # of either T00, T06, T12 or T18
+                         # starting at the initial cycle point
+
+
+
+
+

Advanced Starting Up

+

Dependencies that are only valid at the initial cycle point can be +written using an R1 recurrence. For example:

+
[scheduling]
+    initial cycle point = 20130808T00
+    final cycle point = 20130812T00
+    [[graph]]
+        R1 = "prep => foo"
+        T00 = "foo[-P1D] => foo => bar"
+
+
+

In the example above, R1 implies R1/20130808T00, so +prep only runs once at that cycle point (the initial cycle point). +foo will depend on prep there, but not at subsequent cycle points.

+

However, it is possible to have a workflow that has multiple effective initial +cycles - for example, one starting at T00 and another starting +at T12. What if they need to share an initial task?

+

Let’s suppose that we add the following section to the workflow example above:

+
[scheduling]
+    initial cycle point = 20130808T00
+    final cycle point = 20130812T00
+    [[graph]]
+        R1 = "prep => foo"
+        T00 = "foo[-P1D] => foo => bar"
+        T12 = "baz[-P1D] => baz => qux"
+
+
+

We’ll also say that there should be a starting dependence between +prep and our new task baz - but we still want to have +a single prep task, at a single cycle.

+

We can write this using a special case of the task[-interval] syntax - +if the interval is null, this implies the task at the initial cycle point.

+

For example, we can write our workflow like so, to produce the graph as shown:

+
+
+

Staggered Start Workflow

+
[scheduling]
+    initial cycle point = 20130808T00
+    final cycle point = 20130812T00
+    [[graph]]
+        R1 = "prep"
+        # ^ implies the initial cycle point:
+        R1/T00 = "prep[^] => foo"
+        # ^ is initial cycle point, as above:
+        R1/T12 = "prep[^] => baz"
+        T00 = "foo[-P1D] => foo => bar"
+        T12 = "baz[-P1D] => baz => qux"
+
+
+
+
+
+../../_images/test4.png +
+
+
+

Usually, we want to specify additional tasks and dependencies at the initial +cycle point. But what if we want our first cycle point to be entirely special, +with some tasks missing compared to subsequent cycle points?

+

In the workflow below, bar will not run at the initial cycle point, but +will still run at subsequent cycle points. +PT6H/PT6H means start at ++PT6H (6 hours after the initial cycle point) and then repeat every +PT6H (6 hours):

+
+
+

Restricted First Cycle Point Workflow

+
[scheduling]
+    initial cycle point = 20130808T00
+    final cycle point = 20130808T18
+    [[graph]]
+        R1 = "setup_foo => foo"
+        +PT6H/PT6H = """
+            foo[-PT6H] => foo
+            foo => bar
+        """
+
+
+
+
+
+../../_images/test5.png +
+
+
+

Some workflows may have staggered start-up sequences where different tasks need +to run once but only at specific cycle points, e.g. because of differing +data sources at different cycle points, with different possible initial cycle +points. To allow this Cylc provides a min( ) function that can be +used as follows:

+
[scheduling]
+    initial cycle point = 20100101T03
+    [[graph]]
+        R1/min(T00,T12) = "prep1 => foo"
+        R1/min(T06,T18) = "prep2 => foo"
+        T00,T06,T12,T18 = "foo => bar"
+
+
+

In this example the initial cycle point is 20100101T03, so the +prep1 task will run once at 20100101T12 and the +prep2 task will run once at 20100101T06 as these are +the first cycle points after the initial cycle point in the respective +min( ) entries.

+
+
+

Integer Cycling

+
+

Related Tutorial

+

Integer Cycling Tutorial

+
+

In addition to non-cycling and datetime cycling workflows, Cylc can do +integer cycling for cycling workflows that are not datetime based.

+

To construct an integer cycling workflow, set +[scheduling]cycling mode=integer, and specify integer values +for the initial cycle point and optionally the +final cycle point. The syntax for intervals, +offsets, and recurrences (sequences) is similar to the +datetime cycling syntax, except for the simple integer values.

+

The full integer recurrence expressions supported are:

+
    +
  • Rn/start-point/interval # e.g. R3/1/P2

  • +
  • Rn/interval/end-point # e.g. R3/P2/9

  • +
+

But, as for datetime cycling, sequence start and end points can be omitted +where workflow initial and final cycle points can be assumed. Some examples:

+
R1        # Run once at the initial cycle point
+          # (short for R1/initial-point/?)
+P1        # Repeat with step 1 from the initial cycle point
+          # (short for R/initial-point/P1)
+P5        # Repeat with step 5 from the initial cycle point
+          # (short for R/initial-point/P5)
+R2//P2    # Run twice with step 3 from the initial cycle point
+          # (short for R2/initial-point/P2)
+R/+P1/P2  # Repeat with step 2, from 1 after the initial cycle point
+R2/P2     # Run twice with step 2, to the final cycle point
+          # (short for R2/P2/final-point)
+R1/P0     # Run once at the final cycle point
+          # (short for R1/P0/final-point)
+
+
+
+

Advanced Integer Cycling Syntax

+

The same syntax used to reference the initial and final cycle points +(introduced in Referencing The Initial And Final Cycle Points) for +use with datetime cycling can also be used for integer cycling. For +example you can write:

+
R1/^     # Run once at the initial cycle point
+R1/$     # Run once at the final cycle point
+R3/^/P2  # Run three times with step two starting at the
+                 # initial cycle point
+
+
+

Likewise the syntax introduced in The Initial Cycle Point for excluding +a particular point from a recurrence also works for integer cycling. For +example:

+
R/P4!8       # Run with step 4, to the final cycle point but not at point 8
+R3/3/P2!5    # Run with step 2 from point 3 but not at point 5
+R/+P1/P6!14  # Run with step 6 from 1 step after the
+             # initial cycle point but not at point 14
+
+
+

Multiple integer exclusions are also valid in the same way as the syntax +in The Initial Cycle Point. Integer exclusions may be a list of single +integer points, an integer sequence, or a combination of both:

+
R/P1!(2,3,7)  # Run with step 1 to the final cycle point,
+              # but not at points 2, 3, or 7.
+P1 ! P2       # Run with step 1 from the initial to final
+              # cycle point, skipping every other step from
+              # the initial cycle point.
+P1 ! +P1/P2   # Run with step 1 from the initial cycle point,
+              # excluding every other step beginning one step
+              # after the initial cycle point.
+P1 !(P2,6,8)  # Run with step 1 from the initial cycle point,
+              # excluding every other step, and also excluding
+              # steps 6 and 8.
+
+
+
+
+

An Integer Cycling Example

+

The following workflow definition, as graphed above, +implements a classical linear pipeline using integer cycling. The workflow +ensures that one instance each of A, B, and C runs concurrently and the +pipeline is kept full: when 1/A has finished processing the first dataset, 2/A +can start on the second one at the same time as 1/B begins processing the +output of 1/A, and so on. The artificial cross-cycle dependence ensures that +only one instance of A can run at a time; and similarly B and C. If available +compute resource supports more than three concurrent jobs, remove the +cross-cycle dependence and Cylc will run many cycles at once. Task runtime +configuration is omitted, but it would likely involve retrieving datasets by +cycle point and processing them in cycle point-specific shared workspaces under +the self-contained run directory.

+
[scheduling]
+    cycling mode = integer
+    initial cycle point = 1
+    [[graph]]
+        R/^/P1 = """
+            A => B => C
+            A[-P1] => A
+            B[-P1] => B
+            C[-P1] => C
+        """
+
+
+
+
+
+
+

Task Triggering

+

A task is said to trigger when it submits its job to run, as soon as all of +its dependencies (also known as its separate “triggers”) are met. Tasks can +be made to trigger off of the state of other tasks (indicated by a +:state qualifier on the upstream task (or family) +name in the graph) and, and off the clock, and arbitrary external events.

+

External triggering is relatively more complicated, and is documented +separately in External Triggers.

+
+

Success Triggers

+

The default, with no trigger type specified, is to trigger off of the +upstream task succeeding:

+
# B triggers if A SUCCEEDS:
+R1 = "A => B"
+
+
+

For consistency and completeness, however, the success trigger can be +explicit:

+
# B triggers if A SUCCEEDS:
+R1 = "A => B"
+
+# or:
+R1 = "A:succeed => B"
+
+
+
+
+

Failure Triggers

+

To trigger off of the upstream task failing:

+
# B triggers if A FAILS:
+R1 = "A:fail => B"
+
+
+
+
+

Start Triggers

+

To trigger off of the upstream task starting:

+
# B triggers if A STARTS EXECUTING:
+R1 = "A:start => B"
+
+
+

This can be used to trigger tasks that monitor the execution of other tasks, +e.g. to process their output files on the fly as they are generated. +Message Triggers can also be useful for this use case.

+
+
+

Finish Triggers

+

To trigger off of the upstream task either succeeding or failing:

+
# B triggers if A either SUCCEEDS or FAILS:
+R1 = "A | A:fail => B"
+
+# or
+R1 = "A:finish => B"
+
+
+
+
+

Message Triggers

+
+

Related Tutorial

+

Message Trigger Tutorial

+
+

We can also trigger off of custom task output messages. These must be +registered in the [runtime][<namespace>][outputs] section +of the emitting task, and sent with cylc message command. +The graph trigger syntax refers to the item name of the registered +output message. Here’s an example workflow that uses message triggers:

+
[scheduling]
+    initial cycle point = 20140801T00
+    final cycle point = 20141201T00
+    [[graph]]
+        P2M = """
+            foo:out1 => bar
+            foo[-P2M]:out2 => baz
+        """
+[runtime]
+    [[foo]]
+        script = """
+            sleep 5
+            cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" "file 1 done"
+            sleep 10
+            cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" "file 2 done"
+            sleep 10
+        """
+        [[[outputs]]]
+            out1 = "file 1 done"
+            out2 = "file 2 done"
+    [[bar, baz]]
+        script = sleep 10
+
+
+
+
+

Job Submission Triggers

+

To trigger off of a task submitting, or failing to submit:

+
# B triggers if A submits successfully:
+R1 = "A:submit? => B"
+
+# D triggers if C fails to submit successfully:
+R1 = "C:submit-fail? => D"
+
+
+

A possible use case for submit-fail triggering: if a task fails to submit, +possibly after multiple retries, another task that inherits (mostly) the same +runtime could be triggered to submit the same job to an alternative platform.

+
+
+

Conditional Triggers

+

Conditional triggers allow the configuration of +more advanced task dependencies.

+

AND operators (&) can appear on both sides of an arrow. They +provide a concise alternative to defining multiple triggers separately:

+
# 1/ this:
+R1 = "A & B => C"
+
+# is equivalent to:
+R1 = """
+    A => C
+    B => C
+"""
+
+# 2/ this:
+R1 = "A => B & C"
+
+# is equivalent to:
+R1 = """
+    A => B
+    A => C
+"""
+
+# 3/ and this:
+R1 = "A & B => C & D"
+
+# is equivalent to this:
+R1 = """
+    A => C
+    B => C
+    A => D
+    B => D
+"""
+
+
+

OR operators (|), for conditional triggers, can only appear on the left:

+
# C triggers when either A or B finishes:
+    R1 = "A | B => C"
+
+
+

Any valid conditional expression can be used.

+
+
+

Conditional trigger example

+
# D triggers if A or (B and C) succeed
+A | B & C => D
+# just to align the two graph sections
+D => W
+# Z triggers if (W or X) and Y succeed
+(W|X) & Y => Z
+
+
+
+
+
+../../_images/conditional-triggers.png +
+
+
+
+
+

Family Triggers

+

Families defined by the runtime inheritance hierarchy +(Task Configuration) can be used in the graph to trigger whole +groups of tasks at the same time (e.g. forecast model ensembles and groups of +tasks for processing different observation types at the same time) and for +triggering downstream tasks off families as a whole. Higher level families, +i.e. families of families, can also be used, and are reduced to the lowest +level member tasks.

+
+

Note

+

Tasks can also trigger off individual family members if necessary.

+
+

To trigger an entire task family at once:

+
[scheduling]
+    [[graph]]
+        R1 = "foo => FAM"
+[runtime]
+    [[FAM]]    # a family (because others inherit from it)
+    [[m1,m2]]  # family members (inherit from FAM)
+        inherit = FAM
+
+
+

This is equivalent to:

+
[scheduling]
+    [[graph]]
+        R1 = "foo => m1 & m2"
+[runtime]
+    [[FAM]]
+    [[m1,m2]]
+        inherit = FAM
+
+
+

To trigger off of a task family you must specify whether the trigger condition +applies to all or any of the member tasks:

+
[scheduling]
+    [[graph]]
+        R1 = """
+            # all-member triggers:
+            FAM:start-all => one
+            FAM:succeed-all => one
+            FAM:fail-all => one
+            FAM:finish-all => one
+            # any-member triggers:
+            FAM:start-any => one
+            FAM:succeed-any => one
+            FAM:fail-any => one
+            FAM:finish-any => one
+        """
+
+
+

Here’s how to trigger downstream processing after if one or more family +members succeed, but only after all members have finished (succeeded or +failed):

+
[scheduling]
+    [[graph]]
+        R1 = """
+           FAM:finish-all & FAM:succeed-any => foo
+        """
+
+
+
+
+

Efficient Inter-Family Triggering

+

While Cylc allows writing dependencies between two +families it is important to consider the number of +dependencies this will generate. In the following example, each member of +FAM2 has dependencies pointing at all the members of FAM1.

+
[scheduling]
+    [[graph]]
+        R1 = """
+            FAM1:succeed-any => FAM2
+        """
+
+
+

Expanding this out, you generate N * M dependencies, where N is the +number of members of FAM1 and M is the number of members of FAM2. +This can result in high memory use as the number of family members grows.

+

You can greatly reduce the number of dependencies generated here by putting +dummy tasks in the graph to represent the state of the upstream family. For +example, if FAM2 should trigger off any member of FAM1 succeeding you +can use a dummy task FAM1_done like this:

+
[scheduling]
+    [[graph]]
+        R1 = """
+            FAM1:succeed-any => FAM1_done => FAM2
+        """
+[runtime]
+# ...
+    [[FAM1_done]]
+        script = true
+# ...
+
+
+

This graph generates only N + M dependencies, which takes +significantly less memory and CPU to store and evaluate.

+
+
+

Intercycle Triggers

+

Most tasks in a workflow typically depend on others with the same +cycle point, but some may depend on other cycle points [1].

+

Intercycle dependence is expressed using +[offset] syntax such as foo[-PT12H] => foo, which means foo at the +current cycle point depends on a previous instance of foo at 12 hours +before the current cycle point. Unlike for recurrences (e.g. T00,T12), +dependency these offsets are relative to the current cycle point, not the +initial cycle point.

+
[[graph]]
+    # B triggers off A in the previous cycle point
+    PT6H = "A[-PT6H] => B"
+
+
+

intercycle and trigger type (or message trigger) syntax can be +combined:

+
# B triggers if A in the previous cycle point fails:
+PT6H = "A[-PT6H]:fail => B"
+
+
+

For convenience, Cylc automatically ignores intercycle triggers that reach back +beyond the initial cycle point. If something special has to happen at start-up, +R1 tasks are the recommended way to make it happen:

+
+
[scheduling]
+    [[graph]]
+        R1 = "prep1 => prep2"
+        R1/T00,R1/T12 = "prep2[^] => foo"
+        T00,T12 = "foo[-PT12H] => foo => bar"
+
+
+
+

Here there is a dependence on the initial R1 task prep for foo at +the first T00 cycle point, and at the first T12 cycle point. +Thereafter, foo just depends on its previous (12 hours ago) instance.

+

It can also be useful to have specific dependencies on tasks at or near +the initial cycle point. You can switch the context of the offset to be +the initial cycle point by using the caret symbol: ^.

+

For example, foo[^] means foo at the initial cycle point, and +foo[^+PT6H] means foo 6 hours after the initial cycle point. Usually, +this kind of dependency will only apply in a limited number of cycle points +near the start of the workflow, so you may want to write it in an R1 graph.

+

Finally, dependence on a task at a specific cycle point is also possible:

+
[scheduling]
+    [[graph]]
+        R1/20200202 = "baz[20200101] => qux"
+
+
+
+

Warning

+

However, in a long running workflow it is best to avoid a repeating cycle +that depends forever on a specific cycle point (such as the initial point) +as this can adversely affect the scheduler’s performance.

+
+
[scheduling]
+    initial cycle point = 2010
+    [[graph]]
+        # Can cause performance issue!
+        P1D = "baz[20200101] => qux"
+
+
+
+
+

Special Sequential Tasks

+

Tasks that depend on their own previous-cycle instance can be declared as +sequential:

+
[scheduling]
+    [[special tasks]]
+        # foo depends on its previous instance:
+        sequential = foo  # deprecated - see below!
+    [[graph]]
+        T00,T12 = "foo => bar"
+
+
+

However, explicit intercycle triggers are generally preferred:

+
[scheduling]
+    [[graph]]
+        # foo depends on its previous instance:
+        T00,T12 = "foo[-PT12H] => foo => bar"
+
+
+

The sequential declaration is arguably convenient in one unusual situation +though: if a task has a non-uniform cycling sequence then multiple explicit +triggers,

+
[scheduling]
+    [[graph]]
+        T00,T03,T11 = "foo => bar"
+        T00 = "foo[-PT13H] => foo"
+        T03 = "foo[-PT3H] => foo"
+        T11 = "foo[-PT8H] => foo"
+
+
+

can be replaced by a single sequential declaration,

+
[scheduling]
+    [[special tasks]]
+        sequential = foo
+    [[graph]]
+        T00,T03,T11 = "foo => bar"
+
+
+
+
+

Future Triggers

+

Cylc also supports intercycle triggering off +tasks “in the future” (with respect to cycle point):

+
[[graph]]
+    T00,T06,T12,T18 = """
+        # A runs in this cycle:
+        A
+        # B in this cycle triggers off A in the next cycle.
+        A[PT6H] => B
+    """
+
+
+

Future triggers present a problem at workflow shutdown rather than at start-up. +Here, B at the final cycle point wants to trigger off an instance +of A that will never exist because it is beyond the workflow stop +point. Consequently Cylc prevents tasks from spawning successors that depend on +other tasks beyond the final point.

+
+
+

Clock Triggers

+
+

Warning

+

This describes a deprecated syntax for defining clock triggers in task +configuration. If used, it will be converted automatically to define +new-style clock triggers. +Support for the old syntax will be removed in an upcoming release.

+
+

By default, datetime cycle points are not connected to the wallclock time. +In real time cycling systems, however, some tasks may need to trigger at +(or at some offset from) their cycle point in real time.

+

Cylc points are full datetimes, not just times of the day, so clock-triggers +provide no constraint if the workflow gets sufficiently far behind the clock, +allowing maximum concurrency until the clock-triggered tasks catch up again.

+
[scheduling]
+    [[special tasks]]
+        clock-trigger = foo(PT2H)
+    [[graph]]
+        T00 = foo
+
+
+

Here, 2025-08-23T00/foo would trigger (other dependencies allowing) +when the wallclock time reaches 2025-08-23T02. Clock-trigger +offsets are normally positive, to trigger after the wallclock time is equal +to the task cycle point.

+
+
+

Clock-Expire Triggers

+

Tasks can be configured to expire if the wall clock +time exceeds some offset from their cycle point.

+

The associated :expire output can be used to +trigger other tasks. It must be marked as an optional output, +i.e. expiry cannot be required.

+

Family triggers are also provided for task expiry:

+
foo:expire? => bar
+FAM:expire-all? => baz
+FAM:expire-any? => qux
+
+
+

Task expiration is configured with +[scheduling][special tasks]clock-expire using a syntax like +clock-trigger +with a datetime offset relative to cycle point.

+

The offset should be positive to make the task expire if the wallclock time +has gone beyond the cycle point.

+
+

Warning

+

The scheduler can only determine that a task has expired once it +enters the n=0 window.

+
+
+
+

External Triggers

+

This is a substantial topic, documented separately +in External Triggers.

+
+
+
+

Required Outputs

+
+

Added in version 8.0.0.

+
+

Task outputs in the graph can be +required (the default) or +optional (marked with ? in the graph).

+

Tasks are expected to complete required outputs at runtime, but +they don’t have to complete optional outputs.

+

This allows the scheduler to correctly diagnose +workflow completion. [2]

+

Tasks that achieve a final status without completing their +outputs [3] are retained in the n=0 window pending user +intervention, e.g. to be retriggered after a bug fix.

+
+

Note

+

Tasks that achieve a final status without completing their outputs will +raise a warning and stall the workflow when there is nothing else for +the scheduler to run (see Workflow Completion). They also count +toward the runahead limit.

+
+

This graph says task bar should trigger if foo succeeds:

+
foo => bar  # short for "foo:succeed => bar"
+
+
+

Additionally, foo is required to succeed, because its success is not marked +as optional. If foo achieves a final status without succeeding the +scheduler will not run bar, and foo will be retained +in n=0 pending user intervention.

+

Here, foo:succeed, bar:x, and baz:fail are all required outputs:

+
foo
+bar:x
+baz:fail
+
+
+

Tasks that appear with only custom outputs in the graph are also required to succeed. +Here, foo:succeed is a required output, as well as foo:x, unless it is +marked as optional elsewhere in the graph:

+
foo:x => bar
+
+
+

If a task generates multiple custom outputs, they should be “required” if you +expect them all to be completed every time the task runs. Here, +model:file1, model:file2, and model:file3 are all required outputs:

+
model:file1 => proc1
+model:file2 => proc2
+model:file3 => proc3
+
+
+
+
+

Optional Outputs

+
+

Added in version 8.0.0.

+
+

Optional outputs are marked with ?. They may or may not be completed by the +task at runtime.

+

Like the first example above, the following graph says task bar should +trigger if foo succeeds:

+
foo? => bar  # short for "foo:succeed? => bar"
+
+
+

But now foo:succeed is optional so we might expect it to fail sometimes. +And if it does fail, it will not be retained in the +n=0 window as incomplete.

+

Here, foo:succeed, bar:x, and baz:fail are all optional outputs:

+
foo?
+bar:x?
+baz:fail?
+
+
+

Success and failure (of the same task) are mutually exclusive, so they must +both be optional if one is optional, or if they both appear in the graph:

+
foo? => bar
+foo:fail? => baz
+
+
+
+

Warning

+

Optional outputs must be marked as optional everywhere they appear in the +graph, to avoid ambiguity.

+
+

If a task generates multiple custom outputs, they should all be declared optional +if you do not expect them to be completed every time the task runs:

+
# model:x, :y, and :z are all optional outputs:
+model:x? => proc-x
+model:y? => proc-y
+model:z? => proc-z
+
+
+

This is an example of graph branching from optional outputs. Whether a +particular branch is taken or not depends on which optional outputs are +completed at runtime. For more information see Graph Branching.

+

Leaf tasks (with nothing downstream of them) can have optional outputs. In the +following graph, foo is required to succeed, but it doesn’t matter whether +bar succeeds or fails:

+
foo => bar?
+
+
+
+

Note

+

Optional outputs do not affect triggering. They just tell the scheduler +what to do with the task if it reaches a final status without +completing the output.

+

This graph triggers bar if foo succeeds, and does not trigger +bar if foo fails:

+
foo => bar
+
+
+

And so does this graph:

+
foo? => bar
+
+
+

The only difference is whether or not the scheduler regards foo as +incomplete if it fails.

+
+
+

Finish Triggers

+

foo:finish is a pseudo output that is short for foo:succeed? | +foo:fail?. This automatically labels the real outputs as optional, because +success and failure can’t both be required.

+

foo:finish? is illegal because it incorrectly suggests that “finishing +is optional” and that a non-optional version of the trigger makes sense.

+
# Good:
+foo:finish => bar
+foo? => baz
+
+# Error:
+foo:finish => bar
+foo => baz  # ERROR : foo:succeed must be optional here!
+
+
+
+
+

Family Triggers

+

Family triggers are based on family pseudo outputs such as FAM:succeed-all +and FAM:fail-any that are short for logical expressions involving the +corresponding member task outputs.

+

If the member outputs are not singled out explicitly elsewhere in the graph, +then they default to being required outputs.

+

For example, if f1 and f2 are members of FAM, then this:

+
FAM:fail-all => a
+
+
+

means:

+
f1:fail & f2:fail => a  # f1:fail and f2:fail are required
+
+
+

and this:

+
FAM:succeed-any => a
+
+
+

means:

+
f1 | f2 => a  # f1:succeed and f2:succeed are required
+
+
+

However, the family default can be changed to optional by using ? on the +family trigger. So this:

+
FAM:fail-all? => a
+
+
+

means this:

+
f1:fail? & f2:fail? => a  # f1:fail and f2:fail are optional
+
+
+

If particular member tasks are singled out elsewhere in the graph, that +overrides the family default for required/optional outputs:

+
# f1:fail is required, and f2:fail is optional:
+FAM:fail-all => a
+f2:fail? => b
+
+
+
+
+

Family Finish Triggers

+

Like task :finish triggers, family :finish-all/any triggers are +different because :finish is a pseudo output involving both :succeed +and :fail, which are mutually exclusive outputs that must both be optional +if both are used.

+

Also like task :finish triggers, use of ? is illegal on a family +finish trigger, because the underlying member outputs must already be optional.

+
FAM:finish-all => a  # f1:succeed/fail and f2:succeed/fail are optional
+FAM:finish-any => a  # (ditto)
+
+FAM:finish-all? => b  # ERROR
+
+
+
+
+
+

Graph Branching

+

Cylc handles workflow graphs in an event-driven way. It can +automatically follow different paths depending on events at runtime. This +relies on optional outputs and is called branching.

+
+

Note

+

In Cylc 7 and earlier, graphs were not event-driven and needed +suicide triggers to clean up unused +branches at runtime.

+

Cylc 8 does not need suicide triggers for branching.

+
+
+

Basic Example

+

Here Cylc will follow one of two “branches” depending on the outcome of task b:

+
    +
  • If b succeeds then the task c will run.

  • +
  • If b fails then the task r will run.

  • +
+

Task d will run after either c or r succeeds.

+
+

digraph example { +subgraph cluster_success { + label = ":succeed" + color = "green" + fontcolor = "green" + style = "dashed" + + c +} + +subgraph cluster_failure { + label = ":fail" + color = "red" + fontcolor = "red" + style = "dashed" + + r +} + +a -> b -> c -> d +b -> r -> d +}

+
+
# the success path
+a => b? => c
+# the fail path
+a => b:fail? => r
+# either way, carry on with the rest of the workflow
+c | r => d
+
+
+

The ? symbol denotes an optional output which allows the graph to +branch.

+

Note the last line of the graph c | r => d allows the graph to +continue on to d regardless of the path taken. This is an artificial +dependency.

+

Branching is often used for automatic failure recovery. Here’s a simple +example:

+
foo => bar?
+bar:fail? => recover
+bar? | recover => baz
+
+
+
+

digraph Example { +subgraph cluster_1 { + label = ":fail" + color = "red" + fontcolor = "red" + style = "dashed" + + recover +} + +foo -> bar +bar -> recover +recover -> baz [arrowhead="onormal"] +bar -> baz [arrowhead="onormal"] +}

+
+

The recover task would (presumably) analyse the failure of bar and, if +the right failure mode is confirmed, attempt to generate the right outputs +another way. Then baz can trigger off of either branch, to process the +outputs.

+

A more realistic example might have several tasks on each branch. The +recover task could, via inheritance, run the same underlying code as +bar, but configured differently to avoid the failure.

+
+
+

Custom Outputs

+

Branching is particularly powerful when using +custom outputs to define alternate parallel paths in the +graph.

+

In the following graph there is a task called showdown which produces one +of three possible custom outputs, good, bad or ugly. Cylc will follow +a different path depending on which of these three outputs is produced.

+

As with the previous example each path begins with a different optional +output of a particular task and ends with an “or” dependency to allow the +workflow to continue regardless of the path taken.

+
# branch the graph depending on the outcome of "showdown"
+showdown:good? => good
+showdown:bad? => bad
+showdown:ugly? => ugly
+# join the graph back together
+good | bad | ugly => fin
+
+
+
+

digraph Example { +subgraph cluster_1 { + label = ":good" + color = "green" + fontcolor = "green" + style = "dashed" + + good +} +subgraph cluster_2 { + label = ":bad" + color = "red" + fontcolor = "red" + style = "dashed" + + bad +} +subgraph cluster_3 { + label = ":ugly" + color = "purple" + fontcolor = "purple" + style = "dashed" + + ugly +} +showdown -> good +showdown -> bad +showdown -> ugly +good -> fin [arrowhead="onormal"] +bad -> fin [arrowhead="onormal"] +ugly -> fin [arrowhead="onormal"] +}

+
+

You can test run this example making showdown randomly generate one of the +three custom outputs:

+
[runtime]
+    [[showdown]]
+        # Randomly return one of the three custom outputs:
+        script = """
+            SEED=$RANDOM
+            if ! (( $SEED % 3 )); then
+                cylc message 'The Good'
+            elif ! (( ( $SEED + 1 ) % 3 )); then
+                cylc message 'The Bad'
+            else
+                cylc message 'The Ugly'
+            fi
+        """
+
+        # Ensure that at least one of the custom outputs is produced:
+        completion = succeeded and (good or bad or ugly)
+
+        # Register the three custom outputs:
+        [[[outputs]]]
+            good = 'The Good'
+            bad = 'The Bad'
+            ugly = 'The Ugly'
+
+
+
+

Completion Expressions

+

The completion configuration above is optional, it adds a basic +validation check which ensures that at least one of the three custom outputs is +produced when the task runs. This protects you against the possibility that +none of the outputs are produced e.g. due to a task implementation error.

+

If the task does not produce at least one of these three outputs, then it will +be marked as having incomplete outputs and will be retained in a similar manner +to if it had failed. This provides you with an opportunity to intervene to +rectify the situation: Without intervention the workflow will stall.

+
+
+

Mutually Exclusive Outputs

+

It is not possible to enforce mutually exclusive outputs in Cylc as +tasks may be re-run multiple times and the outputs from previous runs +accumulate.

+

E.g, this expression ensures that at least one of the three custom outputs +is produced when the task runs:

+
completion = succeeded and (good or bad or ugly)
+
+
+

However, it is not possible to ensure that only one of the three is +produced.

+
+
+

Custom Output Generation Timing

+

Custom outputs are generated before the task succeeds or fails. This is handy +if you don’t want downstream tasks to wait for upstream tasks to finish +executing, e.g:

+
# run "process_file_1" as soon as the output "file_1" is completed, but
+# don't wait for "model" to finish first
+model:file_1_ready => process_file_1
+
+
+
+
+
+
+

Runahead Limiting

+

Runahead limiting prevents a workflow from getting too far ahead of the oldest +active cycle point by holding back tasks in cycles beyond a specified limit.

+

The runahead limit is defined as an interval measured from the oldest active cycle. +A cycle is considered to be “active” if it contains any active tasks +(e.g. running tasks).

+

Tasks in cycles which are beyond the limit are called runahead tasks +and are displayed in the GUI/Tui with small circle above them:

+../../_images/task-isRunahead.png +

As the workflow advances and active cycles complete, the runahead limit moves +forward allowing tasks in later cycles to run.

+

There are two ways of defining the interval which defines the runahead limit, +as an integer number of cycles, or as a datetime interval.

+
+

Integer Format

+

The runahead limit can be defined as an integer interval with the format +P<N>, where N is an integer.

+

For example the default runahead limit is P4 (an interval of four cycles), +which means that up to five cycles may be active simultaneously, the oldest +active cycle and the next four after it.

+

E.G. for this example workflow:

+
[scheduling]
+    cycling mode = integer
+    initial cycle point = 1
+    runahead limit = P4  # max 5 active points (the default)
+    [[graph]]
+        P1 = foo
+
+
+

When this workflow starts, the initial cycle point is 1 and the runahead limit +is four cycles after this (i.e. cycle 4). So the task foo will immediately +submit in cycles 1, 2, 3 and 4, however, the tasks in cycles 5 onwards will +wait until earlier cycles complete, and the runahead limit advances.

+
    +
  • 1 task-submitted - initial cycle point

  • +
  • 2 task-submitted

  • +
  • 3 task-submitted

  • +
  • 4 task-submitted - runahead limit

  • +
  • 5 task-runahead-super (held back by runahead limit)

  • +
  • 6 task-runahead-super (held back by runahead limit)

  • +
  • X task-runahead-super (held back by runahead limit)

  • +
+

As the workflow advances and earlier cycles complete, the runahead limit +moves on. E.G. Once the cycles 1 & 2 have completed, the runahead limit will +advance to cycle 6.

+

The integer format counts the number of cycles irrespective of the cycling +interval, so if we change the cycling interval from P1 to P2Y:

+
 [scheduling]
+     initial cycle point = 2000  # date time cycling
+     runahead limit = P4  # max 5 active points
+     [[graph]]
+         P2Y = foo  # cycle points 1, 3, 5, 7, 9, ...
+
+
+

Then, the task foo would submit immediately in the cycles 1, 3, 5 and 7. +Cycles from 9 onwards will be held back.

+
    +
  • 2000 task-submitted - initial cycle point

  • +
  • 2002 task-submitted

  • +
  • 2004 task-submitted

  • +
  • 2006 task-submitted - runahead limit

  • +
  • 2008 task-runahead-super (held back by runahead limit)

  • +
  • 2010 task-runahead-super (held back by runahead limit)

  • +
  • XXXX task-runahead-super (held back by runahead limit)

  • +
+
+
+

Datetime Format

+

The runahead interval can also be specified as an ISO8601 duration. +This approach does depend on the cycling intervals, e.g:

+
 [scheduling]
+     initial cycle point = 2000
+     runahead limit = P4Y  # max active point: base point + P4Y
+     [[graph]]
+         P2Y = foo  # cycle points 2050, 2052, 2054, ...
+
+
+

When this workflow starts, the task foo in the first three cycles will run:

+
    +
  • 2000 task-submitted - initial cycle point

  • +
  • 2002 task-submitted

  • +
  • 2004 task-submitted - runahead limit

  • +
  • 2006 task-runahead-super (held back by runahead limit)

  • +
  • 2008 task-runahead-super (held back by runahead limit)

  • +
  • XXXX task-runahead-super (held back by runahead limit)

  • +
+
+
+

Runahead Limit Notes

+

To restrict activity to a single cycle point at a time (just the base point) +use a null runahead interval: P0 or (e.g.) PT0H.

+

Runahead limiting does not restrict activity within a cycle point. +Workflows with a large number of tasks per cycle may need internal +queues to constrain activity in absolute terms.

+

The scheduler may automatically raise the runahead limit to accommodate +future triggered tasks without stalling the workflow.

+
+
+
+

Internal Queues

+

Large workflows can potentially overwhelm the system by submitting too many +jobs at once. Internal queues can prevent this by limiting the number of +tasks that can be active (submitted or running) at the same time.

+

Internal queues are FIFO (first-in-first-out): tasks are released in the same +order that they were queued. They are configured under +[scheduling][queues] with a name; a list of members assigned +by task or family name; and a limit, which is the maximum number of active +members allowed.

+

By default every task is assigned to the default queue, which by default +has a zero limit (interpreted by Cylc as no limit). To use a single queue for +the whole workflow just set the default queue limit:

+
[scheduling]
+    [[queues]]
+        # limit the entire workflow to 5 active tasks at once
+        [[[default]]]
+            limit = 5
+
+
+

To use additional queues just name them, set limits, and assign members:

+
[scheduling]
+    [[queues]]
+        [[[q_foo]]]
+            limit = 5
+            members = foo, bar, baz
+
+
+

Any tasks not assigned to a particular queue will remain in the default +queue. The following example illustrates how queues work by running two task +trees side by side, limited to 2 and 3 tasks respectively:

+
[meta]
+    title = demonstrates internal queueing
+    description = """
+        Two trees of tasks: the first uses the default queue set to a limit of
+        two active tasks at once; the second uses another queue limited to three
+        active tasks at once.
+    """
+
+[scheduler]
+    allow implicit tasks = True
+
+[scheduling]
+    [[queues]]
+        [[[default]]]
+            limit = 2
+        [[[foo]]]
+            limit = 3
+            members = n, o, p, FAM2, u, v, w, x, y, z
+    [[graph]]
+        R1 = """
+            a => b & c => FAM1
+            n => o & p => FAM2
+            FAM1:succeed-all => h & i & j & k & l & m
+            FAM2:succeed-all => u & v & w & x & y & z
+        """
+
+[runtime]
+    [[FAM1, FAM2]]
+    [[d,e,f,g]]
+        inherit = FAM1
+    [[q,r,s,t]]
+        inherit = FAM2
+
+
+
+
+

Valid Task Cycle Points

+

Graph triggers determine the sequence of valid cycle points (via the +recurrence value of the associated graph string) and the prerequisites, for +each downstream task in a dependency. In the absence of a cycle point offset +(intercycle trigger) they also determine the sequence of cycle points for +the upstream tasks:

+
[scheduling]
+    initial cycle point = 2025-01-01T00
+    [[graph]]
+        P2D = "foo & bar => baz"
+
+
+

This says baz depends on foo and bar for every point in the +sequence defined by the recurrence P2D (i.e. R/^/P2D).

+

Cylc does not infer the cyclepoint sequence for upstream tasks in intercycle +triggers, however. All tasks must be tied to the right sequence by appearing +somewhere in the graph with no offset. This prevents unintentional creation of +off-sequence tasks by an offset error in the graph.

+

For instance, the following example fails validation with no cycling sequences +defined for foo:

+
[scheduling]
+    initial cycle point = 2025-01-01T00
+    [[graph]]
+        # ERROR!
+        P2D = "foo[-P1D] & bar"
+
+
+

To fix this, foo should be explicitly tied to the P2D cycle, and the +correct offset used:

+
[scheduling]
+    initial cycle point = 2025-01-01T00
+    [[graph]]
+        P2D = """
+            foo
+            foo[-P2D] & bar
+        """
+
+
+

Or it should be explicitly tied to the intermediate cycle, if the P1D offset +is actually correct:

+
[scheduling]
+    initial cycle point = 2025-01-01T00
+    [[graph]]
+        R/+P1D/P2D = foo  # day 2, 4, 6, ...
+        P2D = "foo[-P1D] & bar"  # day 1, 3, 5, ...
+
+
+

Note that validation does not detect this sort of error if the target task has +cyclepoint sequences defined but the offset does not land on them. For example, +the following graph will validate but bar will only run once in the first +cycle point (where its pre-initial dependence is ignored):

+
[scheduling]
+    initial cycle point = 2025-01-01T00
+    [[graph]]
+        P2D = """
+            foo
+            foo[-P1D] => bar  # ERROR: foo doesn't exist at -P1D
+        """
+
+
+

To fix this, the offset [-P1D] should be changed to [-P2D], or else +another graph line is needed to generate foo instances on the P1D sequence:

+
[scheduling]
+    initial cycle point = 2025-01-01T00
+    [[graph]]
+        P1D = "foo"
+        P2D = "foo[-P1D] => bar"
+
+
+
+
+

Omitting Tasks

+

It can sometimes be useful to temporarily remove tasks by simply commenting +them out of the graph. Validation warns about tasks defined under +[runtime] but not used in the graph, as a reminder to restore them +or remove them.

+

You can also use logical Jinja2 switches (Jinja2) to +include or exclude tasks (or anything else) from workflow.

+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/user-guide/writing-workflows/suicide-triggers.html b/nightly_8.4/html/user-guide/writing-workflows/suicide-triggers.html new file mode 100644 index 00000000000..0316320197e --- /dev/null +++ b/nightly_8.4/html/user-guide/writing-workflows/suicide-triggers.html @@ -0,0 +1,243 @@ + + + + + + + Suicide Triggers — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Suicide Triggers

+
+

Warning

+

Suicided triggers were needed in Cylc 7 and earlier to remove pre-spawned +waiting tasks from graph branches not taken at runtime, which would stall +the workflow.

+

However, Cylc 8 does not need suicide triggers for graph +branching.

+

They remain supported, and documented, for backward compatibility and for +a rare edge case.

+
+

Suicide triggers remove waiting tasks from the +scheduler’s active active window at runtime.

+

They are activated just like normal task triggers but +they remove the downstream task (prefixed with !) instead of triggering it +to run.

+

Here, the task bar will be removed if foo succeeds:

+
foo => !bar
+
+
+

Suicide triggers combine in the same way as normal triggers, so this graph:

+
foo => !baz
+bar => !baz
+
+
+

is equivalent to this:

+
foo & bar => !baz
+
+
+

i.e. both foo and bar must succeed for baz to be removed.

+

To remove a task after any one of several events, use an OR operator:

+
foo | bar => !baz
+
+
+
+

Note

+

At present, only active tasks that are waiting +(e.g. queued tasks) can be removed by cylc remove.

+
+
+

Remaining Use Case

+

Suicide triggers may be needed to remove a waiting active task when it +can be inferred from the status of another task that the external trigger will +never be satisfied.

+

In the following example imagine that the two xtriggers watch two locations for +the same file to appear. The file will be delivered to one location or the +other but not to both, so if one xtrigger is satisfied the other will never be. +The stuck waiting task can be removed with a suicide trigger, so that it +doesn’t stall the workflow:

+
@xtrigger1 => A
+@xtrigger2 => B
+
+A => !B  # If A succeeds, remove B
+B => !A  # If B succeeds, remove A
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/workflow-design-guide/efficiency.html b/nightly_8.4/html/workflow-design-guide/efficiency.html new file mode 100644 index 00000000000..e29b230beb8 --- /dev/null +++ b/nightly_8.4/html/workflow-design-guide/efficiency.html @@ -0,0 +1,476 @@ + + + + + + + Efficiency And Maintainability — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Efficiency And Maintainability

+

Efficiency (in the sense of economy of workflow definition) and +maintainability go hand in hand. This section describes techniques for clean +and efficient construction of complex workflows that are easy to understand, +maintain, and modify.

+
+

The Task Family Hierarchy

+

A properly designed family hierarchy fulfils three purposes in Cylc:

+
    +
  • efficient sharing of configuration common to groups of related tasks

  • +
  • efficient bulk triggering, for clear scheduling graphs

  • +
  • collapsible families in workflow visualization and UI views

  • +
+
+

Sharing By Inheritance

+

Duplication is a maintenance risk because changes have to be repeated in +multiple places without mistakes. On the other hand, unnecessary sharing of +items via global variables is also bad because it is hard to be sure which +tasks are using which variables. A properly designed runtime inheritance +hierarchy can give every task exactly what it needs, and nothing that it +doesn’t need.

+

If a group of related tasks has some configuration in common, it can be +factored out into a task family inherited by all.

+
[runtime]
+    [[OBSPROC]]
+        # Settings common to all obs processing tasks.
+    [[obs1]]
+        inherit = OBSPROC
+    [[obs2]]
+        inherit = OBSPROC
+
+
+

If several families have settings in common, they can in turn can inherit +from higher-level families.

+

Multiple inheritance allows efficient sharing even for overlapping categories +of tasks. For example consider that some obs processing tasks in the following +workflow run parallel jobs and some serial:

+
[runtime]
+    [[SERIAL]]
+        # Serial job settings.
+    [[PARALLEL]]
+        # Parallel job settings.
+    [[OBSPROC]]
+        # Settings for all obs processing tasks.
+    [[obs1, obs2, obs3]]
+        # Serial obs processing tasks.
+        inherit = OBSPROC, SERIAL
+    [[obs4, obs5]]
+        # Parallel obs processing tasks.
+        inherit = OBSPROC, PARALLEL
+
+
+

Note that workflow parameters should really be used to define family members +efficiently - see Generating Tasks Automatically.

+

Cylc provides tools to help make sense of your inheritance hierarchy:

+
    +
  • cylc graph -n/--namespaces - plot the full multiple +inheritance graph (not the dependency graph)

  • +
  • cylc config <workflow-id> - print selected sections or items +after inheritance processing

  • +
  • cylc graph <workflow-id> - plot the dependency graph, with +collapsible first-parent families +(see Task Families And Visualization)

  • +
  • cylc list -t/--tree <workflow-id> - print the first-parent +inheritance hierarchy

  • +
  • cylc list -m/--mro <workflow-id> - print the inheritance +precedence order for each runtime namespace

  • +
+
+
+

Family Triggering

+

Task families can be used to simplify the scheduling graph wherever many +tasks need to trigger at once:

+
[scheduling]
+    [[graph]]
+        R1 = pre => MODELS
+[runtime]
+    [[MODELS]]
+    [[model1, model2, model3, ...]]
+        inherit = MODELS
+
+
+

To trigger off of many tasks at once, family names need to be qualified +by <state>-all or <state>-any to indicate the desired +member-triggering semantics:

+
[scheduling]
+    [[graph]]
+        R1 = """
+           pre => MODELS
+           MODELS:succeed-all => post
+        """
+
+
+

Note that this can be simplified further because Cylc ignores trigger +qualifiers like :succeed-all on the right of trigger arrows +to allow chaining of dependencies:

+
[scheduling]
+    [[graph]]
+        R1 = pre => MODELS:succeed-all => post
+
+
+
+
+

Family-to-Family Triggering

+
[scheduling]
+    [[graph]]
+        R1 = BIG_FAM_1:succeed-all => BIG_FAM_2
+
+
+

This means every member of BIG_FAM_2 depends on every member +of BIG_FAM_1 succeeding. For very large families this can create so +many dependencies that it affects the performance of Cylc at run time, as +well as cluttering graph visualizations with unnecessary edges. Instead, +interpose a blank task that signifies completion of the first family:

+
[scheduling]
+    [[graph]]
+        R1 = BIG_FAM_1:succeed-all => big_fam_1_done => BIG_FAM_2
+
+
+

For families with M and N members respectively, this +reduces the number of dependencies from M*N to M+N +without affecting the scheduling.

+../_images/fam-to-fam-1.png +../_images/fam-to-fam-2.png +
+
+

Task Families And Visualization

+

First parents in the inheritance hierarchy double as collapsible summary +groups for visualization and monitoring. Tasks should generally be grouped into +visualization families that reflect their logical purpose in the workflow rather +than technical detail such as inherited job submission or host settings. So in +the example under Sharing By Inheritance above all +obs<n> tasks collapse into OBSPROC but not into +SERIAL or PARALLEL.

+

If necessary you can introduce new namespaces just for visualization:

+
[runtime]
+    [[MODEL]]
+        # (No settings here - just for visualization).
+    [[model1, model2]]
+        inherit = MODEL, HOSTX
+    [[model3, model4]]
+        inherit = MODEL, HOSTY
+
+
+

To stop a solo parent being used in visualization, demote it to secondary with +a null parent like this:

+
[runtime]
+    [[SERIAL]]
+    [[foo]]
+        # Inherit settings from SERIAL but don't use it in visualization.
+        inherit = None, SERIAL
+
+
+
+
+
+

Generating Tasks Automatically

+

Groups of tasks that are closely related such as an ensemble of model runs or +a family of obs processing tasks, or sections of workflow that are repeated +with minor variations, can be generated automatically by iterating over +some integer range (e.g. model<n> for n = 1..10) or +list of strings (e.g. obs<type> for +type = ship, buoy, radiosonde, ...).

+
+

Jinja2 Loops

+

Task generation was traditionally done in Cylc with explicit Jinja2 loops, +like this:

+
# Task generation the old way: Jinja2 loops (NO LONGER RECOMMENDED!)
+{% set PARAMS = range(1,11) %}
+[scheduling]
+    [[graph]]
+        R1 = """
+{% for P in PARAMS %}
+            pre => model_p{{P}} => post
+    {% if P == 5 %}
+            model_p{{P}} => check
+    {% endif %}
+{% endfor %}    """
+[runtime]
+{% for P in PARAMS %}
+    [[model_p{{P}}]]
+        script = echo "my parameter value is {{P}}"
+    {% if P == 1 %}
+        # special case...
+    {% endif %}
+{% endfor %}
+
+
+

Unfortunately this makes a mess of the workflow definition, particularly the +scheduling graph, and it gets worse with nested loops over multiple parameters.

+../_images/param-1.png +
+
+

Parameterized Tasks

+

Cylc-6.11 introduced built-in workflow parameters for generating tasks +without destroying the clarity of the base workflow definition. Here’s the same +example using workflow parameters instead of Jinja2 loops:

+
# Task generation the new way: workflow parameters.
+[scheduler]
+    [[parameters]]
+        p = 1..10
+[scheduling]
+    [[graph]]
+        R1 = """
+            pre => model<p> => post
+            model<p=5> => check
+        """
+[runtime]
+    [[pre, post, check]]
+    [[model<p>]]
+        script = echo "my parameter value is ${CYLC_TASK_PARAM_p}"
+    [[model<p=7>]]
+        # special case ...
+
+
+

Here model<p> expands to model_p7 for p=7, +and so on, via the default expansion template for integer-valued parameters, +but custom templates can be defined if necessary. Parameters can also be +defined as lists of strings, and you can define dependencies between different +values: chunk<p-1> => chunk<p>. Here’s a multi-parameter example:

+
[scheduler]
+    allow implicit tasks = True
+    [[parameters]]
+        run = a, b, c
+        m = 1..5
+[scheduling]
+    [[graph]]
+        R1 = pre => init<run> => sim<run,m> => close<run> => post
+[runtime]
+    [[sim<run,m>]]
+
+
+../_images/param-2.png +

If family members are defined by workflow parameters, then parameterized +trigger expressions are equivalent to family :<state>-all triggers. +For example, this:

+
[scheduler]
+    [[parameters]]
+        n = 1..5
+[scheduling]
+    [[graph]]
+        R1 = pre => model<n> => post
+[runtime]
+    [[pre, post]]
+    [[MODELS]]
+    [[model<n>]]
+        inherit = MODELS
+
+
+

is equivalent to this:

+
[scheduler]
+    [[parameters]]
+        n = 1..5
+[scheduling]
+    [[graph]]
+        R1 = pre => MODELS:succeed-all => post
+[runtime]
+    [[pre, post]]
+    [[MODELS]]
+    [[model<n>]]
+        inherit = MODELS
+
+
+

(but future plans for family triggering may make the second case more +efficient for very large families).

+

For more information on parameterized tasks see the Cylc user guide.

+
+
+
+

Optional App Config Files

+

Closely related tasks with few configuration differences between them - such as +multiple UM forecast and reconfiguration apps in the same workflow - should use +the same Rose app configuration with the differences supplied by optional +configs, rather than duplicating the entire app for each task.

+

Optional app configs should be valid on top of the main app config and not +dependent on the use of other optional app configs. This ensures they will +work correctly with macros and can therefore be upgraded automatically.

+

Optional app configs can be loaded by command line switch:

+
rose task-run -O key1 -O key2
+
+
+

or by environment variable:

+
ROSE_APP_OPT_CONF_KEYS = key1 key2
+
+
+

The environment variable is generally preferred in workflows because you don’t +have to repeat and override the root-level script configuration:

+
[runtime]
+    [[root]]
+        script = rose task-run -v
+    [[foo]]
+        [[[environment]]]
+            ROSE_APP_OPT_CONF_KEYS = key1 key2
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/workflow-design-guide/general-principles.html b/nightly_8.4/html/workflow-design-guide/general-principles.html new file mode 100644 index 00000000000..04cdec1783b --- /dev/null +++ b/nightly_8.4/html/workflow-design-guide/general-principles.html @@ -0,0 +1,778 @@ + + + + + + + Basic Principles — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Basic Principles

+

This section covers general principles that should be kept in mind when +writing any workflow. More advanced topics are covered later: +Efficiency And Maintainability and Portable Workflows.

+
+

Cycle point time zone

+

Cylc has full local timezone support if needed, but the default cycle point time +zone is UTC. See flow.cylc[scheduler]cycle point time zone.

+
+
+

Fine Or Coarse-Grained Workflows

+

Workflows can have many small simple tasks, fewer large complex tasks, or anything +in between. A task that runs many distinct processes can be split into many +distinct tasks. The fine-grained approach is more transparent and it allows +more task level concurrency and quicker failure recovery - you can rerun just +what failed without repeating anything unnecessarily.

+
+

rose bunch

+

One caveat to our fine-graining advice is that submitting a large number of +small tasks at once may be a problem on some platforms. If you have many +similar concurrent jobs you can use rose bunch to pack them into a +single task with incremental rerun capability: retriggering the task will rerun +just the component jobs that did not successfully complete earlier.

+
+
+
+

Monolithic Or Interdependent Workflows

+

When writing workflows from scratch you may need to decide between putting +multiple loosely connected sub-workflows into a single large workflow, or +constructing a more modular system of smaller workflows that depend on each other +through inter-workflow triggering. +Each approach has its pros and cons, depending on your requirements and +preferences with respect to the complexity and manageability of the resulting +system.

+
+
+

Self-Contained Workflows

+

All files generated by Cylc during a workflow run are confined to the workflow +run directory $HOME/cylc-run/<workflow-id>. However, Cylc has no +control over the locations of the programs, scripts, and files, that are +executed, read, or generated by your tasks at runtime. It is up to you to +ensure that all of this is confined to the run directory too, as far as +possible.

+

Self-contained workflows are more robust, easier to work with, and more portable. +Multiple instances of the same workflow (with different workflow names) should be +able to run concurrently under the same user account without mutual +interference.

+
+

Avoiding External Files

+

Workflows that use external scripts, executables, and files beyond the essential +system libraries and utilities are vulnerable to external changes: someone +else might interfere with these files without telling you.

+

In some case you may need to symlink to large external files anyway, if space +or copy speed is a problem, but otherwise workflows with private copies of all the +files they need are more robust.

+
+
+

Confining Output To The Run Directory

+

Output files should be confined to the run directory tree. Then all +output is easy to find, multiple instances of the same workflow can run +concurrently without interference, and other users should be able to copy and +run your workflow with few modifications. Cylc provides a share +directory for generated files that are used by several tasks in a workflow +(see Shared Task IO Paths). Archiving tasks can use rose arch +to copy or move selected files to external locations as needed (see +Workflow Housekeeping).

+
+
+
+

Task Host Selection

+

The rose host-select command is now deprecated. Workflows should migrate +to using platforms which provide a more efficient +solution. +See Platforms for details.

+
+
+

Task Scripting

+

Non-trivial task scripting should be held in separate script files rather than +inlined in flow.cylc. This keeps the workflow definition tidy, and it +allows proper shell-mode text editing and independent testing of task scripts.

+

For automatic access by jobs, task-specific scripts should be kept in +Rose app bin directories, and shared scripts kept in (or installed to) the +workflow bin directory.

+
+

Coding Standards

+

When writing your own task scripts make consistent use of appropriate coding +standards such as:

+ +
+
+

Basic Functionality

+

In consideration of future users who may not be expert on the internals of your +workflow and its tasks, all task scripts should:

+
    +
  • Print clear usage information if invoked incorrectly (and via the +standard options -h, --help).

  • +
  • Print useful diagnostic messages in case of error. For example, if a +file was not found, the error message should contain the full path to the +expected location.

  • +
  • Always return correct shell exit status - zero for success, non-zero +for failure. This is used by Cylc job wrapper code to detect success and +failure and report it back to the scheduler.

  • +
  • In shell scripts use set -u to abort on any reference to +an undefined variable. If you really need an undefined variable to evaluate +to an empty string, make it explicit: FOO=${FOO:-}.

  • +
  • In shell scripts use set -e to abort on any error without +having to failure-check each command explicitly.

  • +
  • In shell scripts use set -o pipefail to abort on any error +within a pipe line. Note that all commands in the pipe line will still +run, it will just exit with the right most non-zero exit status.

  • +
+
+

Note

+

Examples and more details are available +for the above three set commands.

+

Inline scripts (defined in the job-script section of the +workflow configuration) do not need to set -euo pipefail: +It is already set as part of the +job script’s error handling.

+
+
+
+
+

Rose Apps

+

Rose apps allow all non-shared task configuration - which is not relevant to +workflow automation - to be moved from the workflow definition into app config +files. This makes workflows tidier and easier to understand, and it allows +rose edit to provide a unified metadata-enhanced view of the workflow +and its apps (see Rose Metadata Compliance).

+

Rose apps are a clear winner for tasks with complex configuration requirements. +It matters less for those with little configuration, but for consistency and to +take full advantage of rose edit it makes sense to use Rose apps +for most tasks.

+

When most tasks are Rose apps, set the app-run command as a root-level default, +and override it for the occasional non Rose app task:

+
[runtime]
+    [[root]]
+        script = rose task-run -v
+    [[rose-app1]]
+        #...
+    [[rose-app2]]
+        #...
+    [[hello-world]]  # Not a Rose app.
+        script = echo "Hello World"
+
+
+
+
+

Rose Metadata Compliance

+

Rose metadata drives page layout and sort order in rose edit, plus +help information, input validity checking, macros for advanced checking and app +version upgrades, and more.

+

To ensure the workflow and its constituent applications are being run as intended +it should be valid against any provided metadata: launch the +rose edit GUI or run rose macro --validate on the +command line to highlight any errors, and correct them prior to use. If errors +are flagged incorrectly you should endeavour to fix the metadata.

+

When writing a new workflow or application, consider creating metadata to +facilitate ease of use by others.

+
+
+

Task Independence

+

Essential dependencies must be encoded in the workflow graph, but +tasks should not rely unnecessarily on the action of other tasks. +For example, tasks should create their own output directories if they don’t +already exist, even if they would normally be created by an earlier task +in the workflow. This makes it is easier to run tasks alone during +development and testing.

+
+
+

Clock-Triggered Tasks

+

Tasks that wait on real time data should use +clock triggers +to delay job submission until the expected data arrival time:

+
[scheduling]
+    initial cycle point = now
+    [[xtriggers]]
+        # Trigger 5 min after wallclock time is equal to cycle point.
+        clock = wall_clock(offset=PT5M)
+    [[graph]]
+        T00 = @clock => get-data => process-data
+
+
+

Clock-triggered tasks typically have to handle late data arrival. Task +execution retry delays can be used to simply retrigger +the task at intervals until the data is found, but frequently retrying small +tasks is inefficient, and multiple task +failures will be logged for what is a essentially a normal condition (at least +it is normal until the data is really late).

+

Rather than using task execution retry delays to repeatedly trigger a task that +checks for a file, it may be better to have the task itself repeatedly poll for +the data (see Custom Trigger Functions).

+
+
+

Rose App File Polling

+

Rose apps have built-in polling functionality to check repeatedly for the +existence of files before executing the main app. See the [poll] +section in Rose app config documentation. This is a good way to implement +check-and-wait functionality in clock-triggered tasks +(Clock-Triggered Tasks), for example.

+

It is important to note that frequent polling may be bad for some filesystems, +so be sure to configure a reasonable interval between polls.

+
+
+

Task Execution Time Limits

+

Instead of setting job wallclock limits directly in job runner +directives, use +flow.cylc[runtime][<namespace>]execution time limit. +Cylc automatically derives the correct job runner directives from this, +and it is also used to run background and at jobs via +the timeout command, and to poll tasks that haven’t reported in +finished by the configured time limit.

+
+
+

Restricting Workflow Activity

+

It may be possible for large workflows to overwhelm a job host by submitting too +many jobs at once:

+
    +
  • Large workflows that are not sufficiently limited by real time clock +triggering or intercycle dependence may generate a lot of runahead +(this refers to Cylc’s ability to run multiple cycles at once, restricted +only by the dependencies of individual tasks).

  • +
  • Some workflows may have large families of tasks whose members all +become ready at the same time.

  • +
+

These problems can be avoided with runahead limiting and internal +queues, respectively.

+
+

Runahead Limiting

+

By default Cylc allows a maximum of five cycle points to be active at the same +time, but this value is configurable:

+
[scheduling]
+    initial cycle point = 2020-01-01T00
+    # Don't allow any cycle interleaving:
+    runahead limit = P0
+
+
+
+
+

Internal Queues

+

Tasks can be assigned to named internal queues that limit the number of members +that can be active (i.e. submitted or running) at the same time:

+
[scheduling]
+    initial cycle point = 2020-01-01T00
+    [[queues]]
+        # Allow only 2 members of BIG_JOBS to run at once:
+        [[[big_jobs_queue]]]
+            limit = 2
+            members = BIG_JOBS
+    [[graph]]
+        T00 = pre => BIG_JOBS
+[runtime]
+    [[BIG_JOBS]]
+    [[foo, bar, baz, ...]]
+        inherit = BIG_JOBS
+
+
+
+
+
+

Workflow Housekeeping

+

Ongoing cycling workflows can generate an enormous number of output files and logs +so regular housekeeping is very important. Special housekeeping tasks, +typically the last tasks in each cycle, should be included to archive selected +important files and then delete everything at some offset from the current +cycle point.

+

The Rose built-in apps rose_arch and rose_prune +provide an easy way to do this. They can be configured easily with +file-matching patterns and cycle point offsets to perform various housekeeping +operations on matched files.

+
+
+

Complex Jinja2 Code

+

The Jinja2 template processor provides general programming constructs, +extensible with custom Python filters, that can be used to generate the +workflow definition. This makes it possible to write flexible multi-use +workflows with structure and content that varies according to various input +switches. There is a cost to this flexibility however: excessive use of Jinja2 +can make a workflow hard to understand and maintain. It is difficult to say +exactly where to draw the line, but we recommend erring on the side of +simplicity and clarity: write workflows that are easy to understand and therefore +easy to modify for other purposes, rather than extremely complicated workflows +that attempt do everything out of the box but are hard to maintain and modify.

+

Note that use of Jinja2 loops for generating tasks is now deprecated in favour +of built-in parameterized tasks - see Task Parameters.

+
+
+

Shared Configuration

+

Configuration that is common to multiple tasks should be defined in one +place and used by all, rather than duplicated in each task. Duplication is +a maintenance risk because changes have to be made consistently in several +places at once.

+
+

Jinja2 Variables

+

In simple cases you can share by passing a Jinja2 variable to all the tasks +that need it:

+
{% set JOB_VERSION = 'A23' %}
+[runtime]
+    [[foo]]
+        script = run-foo --version={{JOB_VERSION}}
+    [[bar]]
+        script = run-bar --version={{JOB_VERSION}}
+
+
+
+
+

Inheritance

+

Sharing by inheritance of task families is recommended when more than a few +configuration items are involved.

+

The simplest application of inheritance is to set global defaults in the +[runtime][root] namespace that is inherited by all tasks. +However, this should only be done for settings that really are used +by the vast majority of tasks. Over-sharing of via root, particularly of +environment variables, is a maintenance risk because it can be very +difficult to be sure which tasks are using which global variables.

+

Any [runtime] settings can be shared - scripting, platform +configuration, environment variables, and so on - from +single items up to complete task or app configurations. At the latter extreme, +it is quite common to have several tasks that inherit the same complete +job configuration followed by minor task-specific additions:

+
[runtime]
+    [[FILE-CONVERT]]
+        script = convert-netcdf
+        #...
+    [[convert-a]]
+        inherit = FILE-CONVERT
+        [[[environment]]]
+              FILE_IN = file-a
+    [[convert-b]]
+        inherit = FILE-CONVERT
+        [[[environment]]]
+              FILE_IN = file-b
+
+
+

Inheritance is covered in more detail from an efficiency perspective in +The Task Family Hierarchy.

+
+
+

Shared Task IO Paths

+

If one task uses files generated by another task (and both see the same +filesystem) a common IO path should normally be passed to both tasks via a +shared environment variable. As far as Cylc is concerned this is no different +to other shared configuration items, but there are some additional aspects +of usage worth addressing here.

+

Primarily, for self-containment (see Self-Contained Workflows) shared IO +paths should be under the workflow share directory, the location of which is +passed to all tasks as $CYLC_WORKFLOW_SHARE_DIR.

+

The rose task-env utility can provide additional environment +variables that refer to static and cyclepoint-specific locations under the +workflow share directory.

+
[runtime]
+    [[my-task]]
+        env-script = $(eval rose task-env -T P1D -T P2D)
+
+
+

For a current cycle point of 20170105 this will make the following +variables available to tasks:

+
ROSE_DATA=$CYLC_WORKFLOW_SHARE_DIR/data
+ROSE_DATAC=$CYLC_WORKFLOW_SHARE_DIR/cycle/20170105
+ROSE_DATACP1D=$CYLC_WORKFLOW_SHARE_DIR/cycle/20170104
+ROSE_DATACP2D=$CYLC_WORKFLOW_SHARE_DIR/cycle/20170103
+
+
+

Subdirectories of $ROSE_DATAC etc. should be agreed between +different sub-systems of the workflow; typically they are named for the +file-generating tasks, and the file-consuming tasks should know to look there.

+

The share-not-duplicate rule can be relaxed for shared files whose names are +agreed by convention, so long as their locations under the share directory are +proper shared workflow variables. For instance the Unified Model uses a large +number of files whose conventional names (glu_snow, for example) +can reasonably be expected not to change, so they are typically hardwired into +app configurations (as $ROSE_DATA/glu_snow, for example) to avoid +cluttering the workflow definition.

+

Here two tasks share a workspace under the workflow share directory +by inheritance:

+
# Sharing an I/O location via inheritance.
+[scheduling]
+    [[graph]]
+        R1 = write_data => read_data
+[runtime]
+    [[root]]
+        env-script = $(eval rose task-env)
+    [[WORKSPACE]]
+        [[[environment]]]
+            DATA_DIR = ${ROSE_DATA}/png
+    [[write_data]]
+        inherit = WORKSPACE
+        script = """
+            mkdir -p $DATA_DIR
+            write-data.exe -o ${DATA_DIR}
+        """
+    [[read_data]]
+        inherit = WORKSPACE
+        script = read-data.exe -i ${DATA_DIR}
+
+
+

In simple cases where an appropriate family does not already exist paths can +be shared via Jinja variables:

+
# Sharing an I/O location with Jinja2.
+{% set DATA_DIR = '$ROSE_DATA/stuff' %}
+[scheduling]
+    [[graph]]
+        R1 = write_data => read_data
+[runtime]
+    [[write_data]]
+        script = """
+            mkdir -p {{DATA_DIR}}
+            write-data.exe -o {{DATA_DIR}}
+        """
+    [[read_data]]
+        script = read-data.exe -i {{DATA_DIR}}
+
+
+

For completeness we note that it is also possible to configure multiple tasks +to use the same work directory so they can all share files in $PWD. +(Cylc executes tasks in special work directories that by default are unique +to each task). This may simplify the workflow slightly, and it may be useful if +you are unfortunate enough to have executables that are designed for IO in +$PWD, but it is not recommended. There is a higher risk +of interference between tasks; it will break rose task-run +incremental file creation mode; and rose task-run --new will in +effect delete the work directories of tasks other than its intended target.

+
# Shared work directory: tasks can read and write in $PWD - use with caution!
+[scheduling]
+    initial cycle point = 2018
+    [[graph]]
+        P1Y = write_data => read_data
+[runtime]
+    [[WORKSPACE]]
+        work sub-directory = $CYLC_TASK_CYCLE_POINT/datadir
+    [[write_data]]
+        inherit = WORKSPACE
+        script = write-data.exe
+    [[read_data]]
+        inherit = WORKSPACE
+        script = read-data.exe
+
+
+
+
+

Varying Behaviour By Cycle Point

+

To make a cycling job behave differently at different cycle points you +could use a single task with scripting that reacts to the cycle point it finds +itself running at, but it is better to use different tasks (in different +cycling sections) that inherit the same base job configuration. This results +in a more transparent workflow that can be understood just by inspecting the +graph:

+
# Run the same job differently at different cycle points.
+[scheduling]
+    initial cycle point = 2020-01-01T00
+    [[graph]]
+        T00 = pre => long_fc => post
+        T12 = pre => short_fc => post
+[runtime]
+    [[MODEL]]
+        script = run-model.sh
+    [[long_fc]]
+        inherit = MODEL
+        execution time limit = PT30M
+        [[[environment]]]
+            RUN_LEN = PT48H
+    [[short_fc]]
+        inherit = MODEL
+        execution time limit = PT10M
+        [[[environment]]]
+            RUN_LEN = PT12H
+
+
+

The few differences between short_fc and long_fc, +including job runner resource requests, can be configured after common +settings are inherited.

+
+
+

At Start-Up

+

Similarly, if a cycling job needs special behaviour at the initial (or any +other) cycle point, just use a different logical task in an R1 graph and +have it inherit the same job as the general cycling task, not a single task +with scripting that behaves differently if it finds itself running at the +initial cycle point.

+
+
+
+

Automating Failure Recovery

+
+

Job Submission Retries

+

When submitting jobs to a remote host, use job submission retries to +automatically resubmit tasks in the event of network outages.

+

Note that this is distinct from job retries for +job execution failure (just below).

+
+
+

Job Execution Retries

+

Automatic retry on job execution failure is useful if you have good reason to +believe that a simple retry will usually succeed. This may be the case if the +job host is known to be flaky, or if the job only ever fails for one known +reason that can be fixed on a retry. For example, if a model fails occasionally +with a numerical instability that can be remedied with a short timestep rerun, +then an automatic retry may be appropriate.

+
[runtime]
+    [[model]]
+        script = """
+            if [[ $CYLC_TASK_TRY_NUMBER > 1 ]]; then
+                SHORT_TIMESTEP=true
+            else
+                SHORT_TIMESTEP=false
+            fi
+            model.exe
+        """
+        execution retry delays = 1*PT0M
+
+
+
+
+

Failure Recovery Workflows

+

For recovery from failures that require explicit diagnosis you can configure +alternate graph branches. In the following example, if the model fails a +diagnosis task will trigger; if it determines the cause of the failure is a +known numerical instability (e.g. by parsing model job logs) it will succeed, +triggering a short timestep run. Postprocessing can proceed from either the +original or the short-step model run.

+
+
+
+../_images/failure-recovery.png +
+
+
+
[scheduling]
+    [[graph]]
+        R1 = """
+            model | model_short => postproc
+            model:fail => diagnose => model_short
+        """
+
+
+
+
+
+
+
+

Include Files

+

Include-files should not be overused, but they can sometimes be useful +(e.g. see Portable Workflows):

+
#...
+{% include 'inc/foo.cylc' %}
+
+
+

(Technically this inserts a Jinja2-rendered file template). Cylc also has a +native include mechanism that pre-dates Jinja2 support and literally inlines +the include-file:

+
#...
+%include 'inc/foo.cylc'
+
+
+

The two methods normally produce the same result, but use the Jinja2 version if +you need to construct an include-file name from a variable (because Cylc +include-files get inlined before Jinja2 processing is done):

+
#...
+{% include 'inc/' ~ SITE ~ '.cylc' %}
+
+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/workflow-design-guide/index.html b/nightly_8.4/html/workflow-design-guide/index.html new file mode 100644 index 00000000000..5fc2b5790c5 --- /dev/null +++ b/nightly_8.4/html/workflow-design-guide/index.html @@ -0,0 +1,249 @@ + + + + + + + Workflow Design Guide — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Workflow Design Guide

+

Cylc/Rose Workflow Design Best Practice Guide.

+

This document provides guidance on making complex Cylc + Rose workflows that +are clear, maintainable, and portable. Note that best practice advice may +evolve over time with the capabilities of Rose and Cylc.

+

Content is drawn from the Rose and Cylc user guides, earlier Met Office workflow +design and operational workflow review documents, experience with real workflows +across the Unified Model Consortium, and discussion among members of the UM +TISD (Technical Infrastructure Workflow Design) working group.

+

We start with the most general topics (coding style, general principles), +move on to more advanced topics (efficiency and maintainability, portable +workflows), and end with some pointers to future developments.

+
+

Note

+

A good working knowledge of Cylc and Rose is assumed. For further details, +please consult the:

+ +
+
+

Note

+

For non-Rose users: this document comes out of the Unified Model +Consortium wherein Cylc is used within the Rose workflow management +framework. However, the bulk of the information in this guide is about +Cylc workflow design; which parts are Rose-specific should be clear from +context.

+
+ +
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/workflow-design-guide/portable-workflows.html b/nightly_8.4/html/workflow-design-guide/portable-workflows.html new file mode 100644 index 00000000000..b61140d737f --- /dev/null +++ b/nightly_8.4/html/workflow-design-guide/portable-workflows.html @@ -0,0 +1,596 @@ + + + + + + + Portable Workflows — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Portable Workflows

+

A portable or interoperable workflow can run “out of the box” at +different sites, or in different environments such as research and operations +within a site. For convenience we just use the term site portability.

+

Lack of portability is a major barrier to collaborative development when +sites need to run more or less the same workflow, because it is very +difficult to translate changes manually between large, complicated workflows.

+

Most workflows are riddled with site-specific details such as local build +configurations, file paths, host names, and batch scheduler directives, etc.; +but it is possible to cleanly factor all this out to make a portable workflow. +Significant variations in workflow structure can even be accommodated quite +easily. If the site workflows are too different, however, you may decide +that it is appropriate for each site to maintain separate workflows.

+

The recommended way to do this, which we expand on below, is:

+
    +
  • Put all site-specific settings in include-files loaded at the end +of a generic “core” workflow definition.

  • +
  • Use “optional” app config files for site-specific variations +in the core workflow’s Rose apps.

  • +
  • (Make minimal use of inlined site switches too, if necessary).

  • +
  • When referencing files, reference them within the workflow structure and +use an install task to link external files in.

  • +
+

The result should actually be tidier than the original in one respect: all +the messy platform-specific resource directives etc., will be hidden away in +the site include-files.

+
+

The Jinja2 SITE Variable

+

First a workflow Jinja2 variable called SITE should be set to the site +name, either in rose-suite.conf, or in the workflow definition itself +(perhaps automatically, by querying the local environment in some way).

+
#!Jinja2
+{% set SITE = "niwa" %}
+#...
+
+
+

This will be used to select site-specific configuration, as described below.

+
+
+

Site Include-Files

+

If a section heading in a flow.cylc file is repeated the items +under it simply add to or override those defined under the same section earlier +in the file. +For example, this task definition:

+
[runtime]
+    [[foo]]
+        script = run-foo.sh
+        platform = niwa_hpc
+
+
+

can equally be written like this:

+
[runtime]  # Part 1 (site-agnostic).
+    [[foo]]
+        script = run-foo.sh
+[runtime]  # Part 2 (site-specific).
+    [[foo]]
+        platform = niwa_hpc
+
+
+
+

Note

+

If Part 2 had also defined script the new value would +override the original. It can sometimes be useful to set a widely used +default and override it in a few cases, but be aware that this can +make it more difficult to determine the origin of affected values.

+
+

In this way all site-specific [runtime] settings, with their +respective sub-section headings, can be moved to the end of the file, and then +out into an include-file (file inclusion is essentially just literal inlining):

+
#...
+{% set SITE = "niwa" %}
+
+# Core site-agnostic settings:
+#...
+[runtime]
+    [[foo]]
+        script = run-foo.sh
+#...
+
+# Site-specific settings:
+{% include 'site/' ~ SITE ~ '.cylc' %}
+
+
+

where the site include-file site/niwa.cylc contains:

+
# site/niwa.cylc
+[runtime]
+    [[foo]]
+        platform = niwa_hpc
+
+
+
+
+

Site-Specific Graphs

+

Repeated graph strings under the same graph section headings are +always additive (graph strings are the only exception to the normal repeat item +override semantics). So, for instance, this graph:

+
[scheduling]
+    initial cycle point = 2025
+    [[graph]]
+        P1Y = "pre => model => post => niwa_archive"
+
+
+

can be written like this:

+
[scheduling]
+    initial cycle point = 2025
+    [[graph]]
+        P1Y = "pre => model => post"
+        P1Y = "post => niwa_archive"
+
+
+

and again, the site-specific part can be taken out to a site include-file:

+
#...
+{% set SITE = "niwa" %}
+
+# Core site-agnostic settings.
+#...
+[scheduling]
+    initial cycle point = 2025
+    [[graph]]
+        P1Y = "pre => model => post"
+#...
+# Site-specific settings:
+{% include 'site/' ~ SITE ~ '.cylc' %}
+
+
+

where the site include-file site/niwa.cylc contains:

+
# site/niwa.cylc
+[scheduling]
+    [[graph]]
+        P1Y = "post => niwa_archive"
+
+
+

Note that the site-file graph needs to define the dependencies of the +site-specific tasks, and thus their points of connection to the core +workflow - which is why the core task post appears in the graph here (if +post had any site-specific runtime settings, to get it to run at +this site, they would also be in the site-file).

+
+
+

Inlined Site-Switching

+

It may be tempting to use inlined switch blocks throughout the workflow instead of +site include-files, but this is not recommended - it is verbose and +untidy (the greater the number of supported sites, the bigger the +mess) and it exposes all site configuration to all users:

+
#...
+[runtime]
+    [[model]]
+        script = run-model.sh
+{# Site switch blocks not recommended:#}
+{% if SITE == 'niwa' %}
+        platform = niwa_loadleveler_platform
+        [[[directives]]]
+            # NIWA Loadleveler directives...
+{% elif SITE == 'metoffice' %}
+        platform = metoffice_pbs_platform
+        [[[directives]]]
+            # Met Office PBS directives...
+{% elif SITE == ... %}
+            #...
+{% else %}
+    {{raise('Unsupported site: ' ~ SITE)}}
+{% endif %}
+    #...
+
+
+

Inlined switches can be used, however, to configure exceptional behaviour at +one site without requiring the other sites to duplicate the default behaviour. +But be wary of accumulating too many of these switches:

+
# (core flow.cylc file)
+#...
+{% if SITE == 'small' %}
+   {# We can't run 100 members... #}
+   {% set ENSEMBLE_SIZE = 25 %}
+{% else %}
+   {# ...but everyone else can! #}
+   {% set ENSEMBLE_SIZE = 100 %}
+{% endif %}
+#...
+
+
+

Inlined switches can also be used to temporarily isolate a site-specific +change to a hitherto non site-specific part of the workflow, thereby avoiding the +need to update all site include-files before getting agreement from the workflow +owner and collaborators.

+
+
+

Site-Specific Workflow Variables

+

It can sometimes be useful to set site-specific values of workflow variables that +aren’t exposed to users via rose-suite.conf. For example, consider +a workflow that can run a special post-processing workflow of some kind at sites +where IDL is available. The IDL-dependence switch can be set per site like this:

+
#...
+{% from SITE ~ '-vars.cylc' import HAVE_IDL, OTHER_VAR %}
+R1 = """
+    pre => model => post
+{% if HAVE_IDL %}
+    post => idl-1 => idl-2 => idl-3
+{% endif %}
+"""
+
+
+

where for SITE = niwa the file niwa-vars.cylc contains:

+
{# niwa-vars.cylc #}
+{% set HAVE_IDL = True %}
+{% set OTHER_VAR = "the quick brown fox" %}
+
+
+

Note we are assuming there are significantly fewer options (IDL or not, in this +case) than sites, otherwise the IDL workflow should just go in the site +include-files of the sites that need it.

+
+
+

Site-Specific Optional Workflow Configs

+

During development and testing of a portable workflow you can use an optional Rose +workflow config file to automatically set site-specific workflow inputs and thereby +avoid the need to make manual changes every time you check out and run a new +version. The site switch itself has to be set of course, but there may be other +settings too such as model parameters for a standard local test domain. Just +put these settings in opt/rose-suite-niwa.conf (for site niwa).

+
+
+

Site-Agnostic File Paths in App Configs

+

Where possible apps should be configured to reference files within the workflow +structure itself rather than outside of it. This makes the apps themselves +portable and it becomes the job of the install task to ensure all required +source files are available within the workflow structure e.g. via symlink into +the share directory. Additionally, by moving the responsibility of linking +files into the workflow to an install task you gain the added benefit of knowing +if a file is missing at the start of a workflow rather than part way into a run.

+
+
+

Site-Specific Optional App Configs

+

Typically a few but not all apps will need some site customization, e.g. for +local archive configuration, local science options, or whatever. To avoid +explicit site-customization of individual task-run command lines use Rose’s +built-in optional app config capability:

+
[runtime]
+    [[root]]
+        script = rose task-run -v -O '({{SITE}})'
+
+
+

Normally a missing optional app config is considered to be an error, but the +round parentheses here mean the named optional config is optional - i.e. +use it if it exists, otherwise ignore.

+

With this setting in place we can simply add a opt/rose-app-niwa.conf to +any app that needs customization at SITE = niwa.

+
+
+

An Example

+

The following small workflow is not portable because all of its tasks are +submitted to a NIWA HPC host; two task are entirely NIWA-specific in that they +respectively install files from a local database and upload products to a local +distribution system; and one task runs a somewhat NIWA-specific configuration +of a model. The remaining tasks are site-agnostic apart from local job host +and batch scheduler directives.

+
[scheduler]
+    UTC mode = True
+[scheduling]
+    initial cycle point = 2017-01-01
+    [[graph]]
+        R1 = install_niwa => preproc
+        P1D = """
+            preproc & model[-P1D] => model => postproc => upload_niwa
+            postproc => idl-1 => idl-2 => idl-3
+        """
+[runtime]
+    [[root]]
+        script = rose task-run -v
+    [[HPC]]  # NIWA job host and batch scheduler settings.
+        platform = niwa_loadleveler_platform
+        [[[directives]]]
+            account_no = NWP1623
+            class = General
+            job_type = serial  # (most jobs in this workflow are serial)
+    [[install_niwa]]  # NIWA-specific file installation task.
+        inherit = HPC
+    [[preproc]]
+        inherit = HPC
+    [[model]]  # Run the model on a local test domain.
+        inherit = HPC
+        [[[directives]]]  # Override the serial job_type setting.
+            job_type = parallel
+        [[[environment]]]
+            SPEED = fast
+    [[postproc]]
+        inherit = HPC
+    [[upload_niwa]]  # NIWA-specific product upload.
+        inherit = HPC
+
+
+

To make this portable, refactor it into a core flow.cylc file that +contains the clean site-independent workflow configuration and loads all +site-specific settings from an include-file at the end:

+
# flow.cylc: CORE SITE-INDEPENDENT CONFIGURATION.
+{% set SITE = 'niwa' %}
+{% from 'site/' ~ SITE ~ '-vars.cylc' import HAVE_IDL %}
+[scheduler]
+    UTC mode = True
+[scheduling]
+    initial cycle point = 2017-01-01
+    [[graph]]
+        P1D = """
+            preproc & model[-P1D] => model => postproc
+{% if HAVE_IDL %}
+            postproc => idl-1 => idl-2 => idl-3
+{% endif %}
+        """
+[runtime]
+    [[root]]
+        script = rose task-run -v -O '({{SITE}})'
+    [[preproc]]
+        inherit = HPC
+    [[preproc]]
+        inherit = HPC
+    [[model]]
+        inherit = HPC
+        [[[environment]]]
+            SPEED = fast
+{% include 'site/' ~ SITE ~ '.cylc' %}
+
+
+

plus site files site/niwa-vars.cylc:

+
# site/niwa-vars.cylc: NIWA SITE SETTINGS FOR THE EXAMPLE WORKFLOW.
+{% set HAVE_IDL = True %}
+
+
+

and site/niwa.cylc:

+
# site/niwa.cylc: NIWA SITE SETTINGS FOR THE EXAMPLE WORKFLOW.
+[scheduling]
+    [[graph]]
+        R1 = install_niwa => preproc
+        P1D = postproc => upload_niwa
+[runtime]
+    [[HPC]]
+        platform = niwa_loadleveler_platform
+        [[[directives]]]
+            account_no = NWP1623
+            class = General
+            job_type = serial  # (most jobs in this workflow are serial)
+    [[install_niwa]]  # NIWA-specific file installation.
+    [[model]]
+        [[[directives]]]  # Override the serial job_type setting.
+            job_type = parallel
+    [[upload_niwa]]  # NIWA-specific product upload.
+
+
+

and finally, an optional app config file for the local model domain:

+
app/model/rose-app.conf  # Main app config.
+app/model/opt/rose-app-niwa.conf  # NIWA site settings.
+
+
+

Some points to note:

+
    +
  • It is straightforward to extend support to a new site by copying an +existing site file(s) and adapting it to the new job host and batch +scheduler etc.

  • +
  • Batch system directives should be considered site-specific unless +all supported sites have the same batch system and the same host +architecture (including CPU clock speed and memory size etc.).

  • +
  • We’ve assumed that all tasks run on a single HPC host at both +sites. If that’s not a valid assumption the HPC family +inheritance relationships would have to become site-specific.

  • +
  • Core task runtime configuration aren’t needed in site files at all +if their job host and batch system settings can be defined in common +families that are (HPC in this case).

  • +
+
+
+

Collaborative Development Model

+

Official releases of a portable workflow should be made from the workflow trunk.

+

Changes should be developed on feature branches so as not to affect other users +of the workflow.

+

Site-specific changes shouldn’t touch the core flow.cylc file, +just the relevant site include-file, and therefore should not need close +scrutiny from other sites.

+

Changes to the core flow.cylc file should be agreed by all +stakeholders, and should be carefully checked for effects on site +include-files:

+
    +
  • Changing the name of tasks or families in the core workflow may break +sites that add configuration to the original runtime namespace.

  • +
  • Adding new tasks or families to the core workflow may require +corresponding additions to the site files.

  • +
  • Deleting tasks or families from the core workflow may require +corresponding parts of the site files to be removed. And also, check for +site-specific triggering off of deleted tasks or families.

  • +
+

However, if the owner site has to get some changes into the trunk before all +collaborating sites have time to test them, version control will of course +protect those lagging behind from any immediate ill effects.

+

When a new feature is complete and tested at the developer’s site, the workflow +owner should check out the branch, review and test it, and if necessary request +that other sites do the same and report back. The owner can then merge the +new feature to the trunk once satisfied.

+

All planning and discussion associated with the change should be documented on +MOSRS Trac tickets associated with the workflow.

+
+
+

Research-To-Operations Transition

+

Under this collaborative development model it is possible to use the +same workflow in research and operations, largely eliminating the difficult +translation between the two environments. Where appropriate, this can save +a lot of work.

+

Operations-specific parts of the workflow should be factored out (as for site +portability) into include-files that are only loaded in the operational +environment. Improvements and upgrades can be developed on feature branches in +the research environment. Operations staff can check out completed feature +branches for testing in the operational environment before merging to trunk or +referring back to research if problems are found. After sufficient testing the +new workflow version can be deployed into operations.

+
+

Note

+

This obviously glosses over the myriad complexities of the technical +and scientific testing and validation of workflow upgrades; it merely describes +what is possible from a workflow design and collaborative development +perspective.

+
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/html/workflow-design-guide/style-guide.html b/nightly_8.4/html/workflow-design-guide/style-guide.html new file mode 100644 index 00000000000..2a21e299006 --- /dev/null +++ b/nightly_8.4/html/workflow-design-guide/style-guide.html @@ -0,0 +1,428 @@ + + + + + + + Style Guidelines — Cylc 8.4.0.dev documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Style Guidelines

+

Coding style is largely subjective, but for collaborative development of +complex systems it is important to settle on a clear and consistent style to +avoid getting into a mess. The following style rules are recommended.

+
+

See also

+

cylc lint -r style is a tool designed to help +you check your code style.

+
+
+

Tab Characters

+

Do not use tab characters. Tab width depends on editor settings, so a mixture +of tabs and spaces in the same file can render to a mess.

+

Use grep -InPr "\t" * to find tabs recursively in files in +a directory.

+

In vim use %retab to convert existing tabs to spaces, +and set expandtab to automatically convert new tabs.

+

In emacs use whitespace-cleanup.

+

In gedit, use the Draw Spaces plugin to display tabs and spaces.

+
+
+

Trailing Whitespace

+

Trailing whitespace is untidy, it makes quick reformatting of paragraphs +difficult, and it can result in hard-to-find bugs (space after intended +line continuation markers).

+

To remove existing trailing whitespace in a file use a sed or +perl one-liner:

+
$ perl -pi -e "s/ +$//g" /path/to/file
+# or:
+$ sed --in-place 's/[[:space:]]\+$//' path/to/file
+
+
+

Or do a similar search-and-replace operation in your editor. Editors like +vim and emacs can also be configured to highlight or automatically +remove trailing whitespace on the fly.

+
+
+

Indentation

+

Consistent indentation makes a workflow definition more readable, it shows section +nesting clearly, and it makes block re-indentation operations easier in text +editors. Indent flow.cylc syntax four spaces per nesting level:

+
+

Settings (Config Items)

+
[SECTION]
+    # A comment.
+    title = the quick brown fox
+    [[SUBSECTION]]
+        # Another comment.
+        a short item = value1
+        a very very long item = value2
+
+
+

Don’t align item = value pairs on the = character +like this:

+
[SECTION]  # Avoid this.
+             a short item = value1
+    a very very long item = value2
+
+
+

or like this:

+
[SECTION]  # Avoid this.
+    a short item          = value1
+    a very very long item = value2
+
+
+

because the whole block may need re-indenting after a single change, which will +pollute your revision history with spurious changes.

+

Comments should be indented to the same level as the section or item they refer +to, and trailing comments should be preceded by two spaces, as shown above.

+
+
+

Script String Lines

+

Script strings are written verbatim to job scripts.

+
[runtime]
+    [[foo]]
+        script = echo "Hello, Mr. Thompson"
+
+
+

If using a triple-quoted string, any common leading whitespace is trimmed +using the logic of textwrap.dedent(). As such, it is recommended to +indent like any other triple-quoted string setting in Cylc:

+
[runtime]
+    [[foo]]
+        # Recommended.
+        script = """
+            if [[ "$RESULT" == "bad" ]]; then
+                echo "Goodbye World!"
+                exit 1
+            fi
+        """
+
+
+

The example above would result in the following being written to the job +script:

+
if [[ "$RESULT" == "bad" ]]; then
+    echo "Goodbye World!"
+    exit 1
+fi
+
+
+
+

Tip

+

Take care when indenting here documents (aka heredocs) to match the +common leading whitespace.

+

For the following example, each line in log.txt would end up with +4 leading white spaces:

+
[runtime]
+    [[foo]]
+     script = """
+         cat >> log.txt <<_EOF_
+             The quick brown fox jumped
+             over the lazy dog.
+         _EOF_
+     """
+
+
+

The following will give you lines with no white spaces:

+
[runtime]
+    [[foo]]
+     script = """
+         cat >> log.txt <<_EOF_
+         The quick brown fox jumped
+         over the lazy dog.
+         _EOF_
+     """
+
+
+
+
+
+

Graph String Lines

+

Whitespace is ignored in graph string parsing so internal graph lines +should be indented as if part of the flow.cylc syntax:

+
[scheduling]
+    [[graph]]
+        R1 = """
+            # Main workflow:
+            FAMILY:succeed-all => bar & baz => qux
+
+            # Housekeeping:
+            qux => rose_arch => rose_prune
+        """
+
+
+
+
+

Jinja2 Code

+

A flow.cylc file with embedded Jinja2 code is essentially a Jinja2 program to +generate a Cylc workflow definition. It is not possible to consistently indent the +Jinja2 as if it were part of the flow.cylc syntax (which to the Jinja2 processor +is just arbitrary text), so it should be indented from the left margin on +its own terms:

+
[runtime]
+    [[OPS]]
+{% for T in OPS_TASKS %}
+    {% for M in range(M_MAX) %}
+    [[ops_{{T}}_{{M}}]]
+        inherit = OPS
+    {% endfor %}
+{% endfor %}
+
+
+
+
+
+

Comments

+

Comments should be minimal, but not too minimal. If context and clear +task and variable names will do, leave it at that. Extremely verbose comments +tend to get out of sync with the code they describe, which can be worse +than having no comments.

+

Avoid long lists of numbered comments - future changes may require mass +renumbering.

+

Avoid page-width “section divider” comments, especially if they are not +strictly limited to the standard line length (see Line Length And Continuation).

+

Indent comments to the same level as the config items they describe.

+
+
+

Titles, Descriptions, And URLs

+

Document the workflow and its tasks with title, +description, and url items instead of comments. +See the flow.cylc[meta] and +flow.cylc[runtime][<namespace>][meta] sections.

+
+
+

Line Length And Continuation

+

Keep to the standard maximum line length of 79 characters where possible. Very +long lines affect readability and make side-by-side diffs hard to view.

+

Backslash line continuation markers can be used anywhere in the flow.cylc file +but should be avoided if possible because they are easily broken by invisible +trailing whitespace.

+

Continuation markers are not needed in graph strings where trailing +trigger arrows and boolean operators imply line continuation:

+
[scheduling]
+    [[graph]]
+        # No line continuation marker is needed here.
+        R1 = """
+            prep => one => two => three =>
+            four => five six => seven => eight &
+            nine & ten =>
+            eleven |
+            twelve
+        """
+[runtime]
+    [[MY_TASKS]]
+    # A line continuation marker *is* needed here:
+    [[one, two, three, four, five, six, seven, eight, nine, ten, \
+      eleven, twelve, thirteen]]
+        inherit = MY_TASKS
+
+
+
+
+

Task Naming Conventions

+

Use UPPERCASE for family names and lowercase +for tasks, so you can distinguish them at a glance.

+

Choose a convention for multi-component names and use it consistently. Put the +most general name components first for natural grouping, e.g. +obs_sonde, obs_radar (not sonde_obs etc.)

+

Within your convention keep names as short as possible.

+
+

UM System Task Names

+

For UM System workflows we recommend the following full task naming convention:

+
model_system_function[_member]
+
+
+

For example, glu_ops_process_scatwind where glu refers +to the global (deterministic model) update run, ops is the system +that owns the task, and process_scatwind is the function it +performs. The optional member suffix is intended for use with +ensembles as needed.

+

Within this convention keep names as short as possible, e.g. use +fcst instead of forecast.

+

UM forecast apps should be given names that reflect their general science +configuration rather than geographic domain, to allow use on other model +domains without causing confusion.

+
+
+
+

Rose Config Files

+

Use rose config-dump to load and re-save new rose.conf files. This +puts the files in a standard format (ordering of lines etc.) to ensure that +spurious changes aren’t generated when you next use rose edit.

+

See also Optional App Config Files on optional app config files.

+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2008-2024 NIWA & British Crown (Met Office) & Contributors. + Last updated on Sep 19, 2024. +

+
+ + + +
+
+
+
+
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/nightly_8.4/index.html b/nightly_8.4/index.html new file mode 100644 index 00000000000..23c8291012d --- /dev/null +++ b/nightly_8.4/index.html @@ -0,0 +1,11 @@ + + + + Cylc Documentation + + + +

If not automatically redirected, please click + Cylc Documentation.

+ + diff --git a/nightly_8.4/linkcheck/_sphinx_design_static/design-tabs.js b/nightly_8.4/linkcheck/_sphinx_design_static/design-tabs.js new file mode 100644 index 00000000000..b25bd6a4fa1 --- /dev/null +++ b/nightly_8.4/linkcheck/_sphinx_design_static/design-tabs.js @@ -0,0 +1,101 @@ +// @ts-check + +// Extra JS capability for selected tabs to be synced +// The selection is stored in local storage so that it persists across page loads. + +/** + * @type {Record} + */ +let sd_id_to_elements = {}; +const storageKeyPrefix = "sphinx-design-tab-id-"; + +/** + * Create a key for a tab element. + * @param {HTMLElement} el - The tab element. + * @returns {[string, string, string] | null} - The key. + * + */ +function create_key(el) { + let syncId = el.getAttribute("data-sync-id"); + let syncGroup = el.getAttribute("data-sync-group"); + if (!syncId || !syncGroup) return null; + return [syncGroup, syncId, syncGroup + "--" + syncId]; +} + +/** + * Initialize the tab selection. + * + */ +function ready() { + // Find all tabs with sync data + + /** @type {string[]} */ + let groups = []; + + document.querySelectorAll(".sd-tab-label").forEach((label) => { + if (label instanceof HTMLElement) { + let data = create_key(label); + if (data) { + let [group, id, key] = data; + + // add click event listener + // @ts-ignore + label.onclick = onSDLabelClick; + + // store map of key to elements + if (!sd_id_to_elements[key]) { + sd_id_to_elements[key] = []; + } + sd_id_to_elements[key].push(label); + + if (groups.indexOf(group) === -1) { + groups.push(group); + // Check if a specific tab has been selected via URL parameter + const tabParam = new URLSearchParams(window.location.search).get( + group + ); + if (tabParam) { + console.log( + "sphinx-design: Selecting tab id for group '" + + group + + "' from URL parameter: " + + tabParam + ); + window.sessionStorage.setItem(storageKeyPrefix + group, tabParam); + } + } + + // Check is a specific tab has been selected previously + let previousId = window.sessionStorage.getItem( + storageKeyPrefix + group + ); + if (previousId === id) { + // console.log( + // "sphinx-design: Selecting tab from session storage: " + id + // ); + // @ts-ignore + label.previousElementSibling.checked = true; + } + } + } + }); +} + +/** + * Activate other tabs with the same sync id. + * + * @this {HTMLElement} - The element that was clicked. + */ +function onSDLabelClick() { + let data = create_key(this); + if (!data) return; + let [group, id, key] = data; + for (const label of sd_id_to_elements[key]) { + if (label === this) continue; + // @ts-ignore + label.previousElementSibling.checked = true; + } + window.sessionStorage.setItem(storageKeyPrefix + group, id); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/nightly_8.4/linkcheck/_sphinx_design_static/sphinx-design.min.css b/nightly_8.4/linkcheck/_sphinx_design_static/sphinx-design.min.css new file mode 100644 index 00000000000..860c36da0fa --- /dev/null +++ b/nightly_8.4/linkcheck/_sphinx_design_static/sphinx-design.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative;font-size:var(--sd-fontsize-dropdown)}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary.sd-summary-title{padding:.5em .6em .5em 1em;font-size:var(--sd-fontsize-dropdown-title);font-weight:var(--sd-fontweight-dropdown-title);user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;list-style:none;display:inline-flex;justify-content:space-between}details.sd-dropdown summary.sd-summary-title::-webkit-details-marker{display:none}details.sd-dropdown summary.sd-summary-title:focus{outline:none}details.sd-dropdown summary.sd-summary-title .sd-summary-icon{margin-right:.6em;display:inline-flex;align-items:center}details.sd-dropdown summary.sd-summary-title .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary.sd-summary-title .sd-summary-text{flex-grow:1;line-height:1.5;padding-right:.5rem}details.sd-dropdown summary.sd-summary-title .sd-summary-state-marker{pointer-events:none;display:inline-flex;align-items:center}details.sd-dropdown summary.sd-summary-title .sd-summary-state-marker svg{opacity:.6}details.sd-dropdown summary.sd-summary-title:hover .sd-summary-state-marker svg{opacity:1;transform:scale(1.1)}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown .sd-summary-chevron-right{transition:.25s}details.sd-dropdown[open]>.sd-summary-title .sd-summary-chevron-right{transform:rotate(90deg)}details.sd-dropdown[open]>.sd-summary-title .sd-summary-chevron-down{transform:rotate(180deg)}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-bg: rgba(0, 113, 188, 0.2);--sd-color-secondary-bg: rgba(108, 117, 125, 0.2);--sd-color-success-bg: rgba(40, 167, 69, 0.2);--sd-color-info-bg: rgba(23, 162, 184, 0.2);--sd-color-warning-bg: rgba(240, 179, 126, 0.2);--sd-color-danger-bg: rgba(220, 53, 69, 0.2);--sd-color-light-bg: rgba(248, 249, 250, 0.2);--sd-color-muted-bg: rgba(108, 117, 125, 0.2);--sd-color-dark-bg: rgba(33, 37, 41, 0.2);--sd-color-black-bg: rgba(0, 0, 0, 0.2);--sd-color-white-bg: rgba(255, 255, 255, 0.2);--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem;--sd-fontsize-dropdown: inherit;--sd-fontsize-dropdown-title: 1rem;--sd-fontweight-dropdown-title: 700} diff --git a/nightly_8.4/linkcheck/_static/_sphinx_javascript_frameworks_compat.js b/nightly_8.4/linkcheck/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 00000000000..81415803ec2 --- /dev/null +++ b/nightly_8.4/linkcheck/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,123 @@ +/* Compatability shim for jQuery and underscores.js. + * + * Copyright Sphinx contributors + * Released under the two clause BSD licence + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/nightly_8.4/linkcheck/_static/css/addons.css b/nightly_8.4/linkcheck/_static/css/addons.css new file mode 100644 index 00000000000..dec298db63f --- /dev/null +++ b/nightly_8.4/linkcheck/_static/css/addons.css @@ -0,0 +1,129 @@ +/* ---------------------------------------------------------------------------- + * THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. + * Copyright (C) NIWA & British Crown (Met Office) & Contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- */ + +/* (1) + * Correct the behaviour of nested admonitions. Sometimes the admonition-header + * inherits its parents styling. */ +.rst-content .error .admonition-title, .rst-content .danger .admonition-title { + background: red +} +.rst-content .warning .admonition-title, +.rst-content .caution .admonition-title, +.rst-content .attention .admonition-title { + background: orange +} + + +/* (2) + * Enable theme handling of pilcrow symbols for code-block captions and + * admonitions. */ +.rst-content p.admonition-title .pull-left.headerlink, +.rst-content div.code-block-caption .pull-left.headerlink { + margin-right:.3em +} +.rst-content p.admonition-title .pull-right.headerlink, +.rst-content div.code-block-caption .pull-right.headerlink { + margin-left:.3em +} +.rst-content p.admonition-title .headerlink:before, +.rst-content div.code-block-caption .headerlink:before { + font-family:"FontAwesome"; + display:inline-block; + font-style:normal; + font-weight:normal; + line-height:1; + text-decoration:inherit; + font-size:14px; + vertical-align:-15%; + -webkit-font-smoothing:antialiased +} +.rst-content p.admonition-title .headerlink:after, +.rst-content div.code-block-caption .headerlink:after { + visibility:visible; + content:""; + font-family:FontAwesome; + display:inline-block; + color:#2980B9 +} +.rst-content p.admonition-title:hover .headerlink, +.rst-content div.code-block-caption:hover .headerlink { + display:inline-block +} +.rst-content p.admonition-title .headerlink, +.rst-content div.code-block-caption .headerlink { + font:normal normal normal 14px/1 FontAwesome; + text-rendering:auto; + -webkit-font-smoothing:antialiased; + -moz-osx-font-smoothing:grayscale; + display:none; + visibility:hidden; + color:#fcfcfc; + text-decoration:inherit +} + + +/* (3) + * Add warning symbol before deprecated items. */ +.deprecated p:before { + font-family:FontAwesome; + content:"\f071 "; + color: rgb(200, 90, 70); +} +.deprecated p { + font-weight: bold; +} + + + +/* (4) + * Make version-modified more prominent. */ +span.versionmodified{ + font-weight: bold; +} + + +/* (5) + * Restyle code-block captions. */ +.code-block-caption { + font-style: italic; + color: #808080; +} +.code-block-caption span { + font-size: 1.2em; +} + + +/* (6) + * Fix the lack of space underneath lists inside admonitions. */ +.rst-content div.admonition ul, +.rst-content div.admonition ol > li { + padding-bottom: 0.5em; +} + + +/* (7) + * Improve sidebar scrolling */ +.wy-nav-size { + overflow-x: hidden!important; + overflow-y: hidden!important; +} + +/* Remove awkward margin for config reference "Path", "Type" etc. */ +.rst-content .cylc.conf .field-list { + margin-bottom: 0; +} diff --git a/nightly_8.4/linkcheck/_static/css/diff_selector.css b/nightly_8.4/linkcheck/_static/css/diff_selector.css new file mode 100644 index 00000000000..38cd2807a03 --- /dev/null +++ b/nightly_8.4/linkcheck/_static/css/diff_selector.css @@ -0,0 +1,36 @@ +/* ---------------------------------------------------------------------------- + * THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. + * Copyright (C) NIWA & British Crown (Met Office) & Contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- */ + +/* Block an element from being included in text selections. */ +.noselect { + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +/* Extension to Pygments to insert the "added" and "unchanged" characters in + * a "diff" code block using CSS so that they aren't included when copied as + * text. */ +.highlight-diff .gi:before { + content: '+'; +} +.highlight-diff .gn:before { + content: ' '; +} diff --git a/nightly_8.4/linkcheck/_static/css/grid_table.css b/nightly_8.4/linkcheck/_static/css/grid_table.css new file mode 100644 index 00000000000..53b63b3612d --- /dev/null +++ b/nightly_8.4/linkcheck/_static/css/grid_table.css @@ -0,0 +1,43 @@ +/* ---------------------------------------------------------------------------- + * THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. + * Copyright (C) NIWA & British Crown (Met Office) & Contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- */ + +/* Implement grid-table class for plain style grid layouts. */ +.grid-table { + width: 100% !important; + border: 0 !important; /* Remove table border. */ +} +.grid-table tbody tr td:first-child { + padding-left: 0 !important; /* Grid flush with the left-hand content edge. */ +} +.grid-table tbody tr td:last-child { + padding-right: 0 !important; /* Grid flush with the right-hand edge */ +} +.grid-table tbody tr td { + background-color: rgba(255,255,255,0) !important; + border: 0 !important; /* Remove cell border. */ + vertical-align: top !important; /* All content should float to the top. */ +} +.grid-table td { + /* docutils sticks tables inside an align-center class, correct this */ + text-align: left; +} + +/* Tables handle their own margin, this prevents getting a double margin. */ +.grid-table div.highlight { + margin-bottom: 0; +} diff --git a/nightly_8.4/linkcheck/_static/css/hieroglyph_theme_addons.css b/nightly_8.4/linkcheck/_static/css/hieroglyph_theme_addons.css new file mode 100644 index 00000000000..055353e558d --- /dev/null +++ b/nightly_8.4/linkcheck/_static/css/hieroglyph_theme_addons.css @@ -0,0 +1,38 @@ +/* (1) + * Make quotations small enough to fit on the slide. */ +.slide q { + font-size: 1em; +} + + +/* (2) + * Add a bit of space between slide titles and images. */ +.slide object, .slide img { + margin: 1em 0 1em 0; +} + + +/* (3) + * Don't display glossary terms as hyperlinks. */ +.slide a.reference { + text-decoration: none +} +.slide a.reference span.std { + text-decoration: underline; +} +.slide a.reference span.xref { + text-decoration: none; + color: #909090; + font-style: italic; +} +.slide a.reference span.xref:hover { + text-decoration: underline; + color: #0066CC; +} + + +/* (4) + * Make code block captions legible. */ +.slide .code-block-caption span { + font-size: 2em; +} diff --git a/nightly_8.4/linkcheck/_static/css/tutorial.css b/nightly_8.4/linkcheck/_static/css/tutorial.css new file mode 100644 index 00000000000..42330f4c6da --- /dev/null +++ b/nightly_8.4/linkcheck/_static/css/tutorial.css @@ -0,0 +1,3 @@ +.admonition.tutorial-ref .admonition-title:before { + content: ""; +} diff --git a/nightly_8.4/linkcheck/_static/jquery.js b/nightly_8.4/linkcheck/_static/jquery.js new file mode 100644 index 00000000000..c4c6022f298 --- /dev/null +++ b/nightly_8.4/linkcheck/_static/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0. + * ------------------------------------------------------------------------- */ + +/* (2) + * Make admonitions linkable. */ +$(document).ready(function() { + var id; + $('p.admonition-title').each(function(itt, element) { + id = 'admonition-' + itt; + $(element).attr({'id': id}); + $(element).append($('') + .attr({'href': '#' + id}) + .addClass('headerlink') + .append('¶') + ); + }); +}); diff --git a/nightly_8.4/linkcheck/_static/js/diff_selector.js b/nightly_8.4/linkcheck/_static/js/diff_selector.js new file mode 100644 index 00000000000..183d98b6ae1 --- /dev/null +++ b/nightly_8.4/linkcheck/_static/js/diff_selector.js @@ -0,0 +1,122 @@ +/* ---------------------------------------------------------------------------- + * THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. + * Copyright (C) NIWA & British Crown (Met Office) & Contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- */ + +/* Return a list of matches for the provided string, see also String.indexOf. */ +String.prototype.indicesOf = function (sub) { + var str = String(this); + var index = str.indexOf(sub); + var count = 0; + var ret = []; + while (index != -1) { + str = str.substr(index + 1); + ret.push(index + count); + count += index + 1; + index = str.indexOf(sub); + } + return ret; +} + + +/* Split a text node on the newline character, see also Text.splitText. */ +Text.prototype.splitLines = function () { + var indices = $(this).text().indicesOf('\n'); + if (indices && indices[0] == 0) { + // ignore leading new line characters + indices.shift(); + } + if (indices.length < 1) { + // no line breaks - skip + return []; + } + var node = this; + var offset = 0; + for (let index of indices) { + node = node.splitText(index - offset); + offset = index; + } +} + +/* Remove the leading (+| ) character from each line of a diff block and + * re-insert them with CSS so that they are not included in the copy selection. + * + * Add the ".noselect" class to lines prefixed (-) to make them disappear from + * copied text. */ +$(document).ready(function() { + $('div.highlight-diff pre').each(function () { + // Unformatted text is represented as text nodes which don't fit into + // the DOM in the way regular HTML elements do so we cannot iterate + // over .children() but must use childNodes instead. + for (let node of this.childNodes) { + if (node.nodeName == '#text') { // "unchanged" line. + // Split multi-line text nodes into separate lines so we can + // remove the leading whitespace. + node.splitLines(); + } else { + text = $(node).html().substr(1); + if ($(node).hasClass('gi')) { // "added" line. + // Remove leading character. + $(node).html($(node).html().substr(1)); + } else if ($(node).hasClass('gd')) { // "removed" line. + // Make un-selectable. + $(node).addClass('noselect'); + } + } + } + }); + + // Iterate again to remove the leading whitespace from unchanged lines. + var node, text, newnode; + $('div.highlight-diff pre').each(function () { + node = this.childNodes[0]; + while (node) { + // Skip nodes if they just contain whitespace (including new + // line characters). + if (node.nodeName == '#text' && $(node).text().trim()) { + text = $(node).text(); + if (text[0] == '\n') { + // Move leading new lines onto the end of the string. + text = text.substr(1); + node = node.splitText(1); + } + if (text[0] == ' ') { + // Remove leading whitespace, this will be provided via + // CSS. + text = text.substr(1); + } + + // Create a new span to represent this text node. Apply the 'gn' + // class which will provide leading whitespace. + $('') + .append(text) + .addClass('gn') + .insertBefore(node); + + // Move on to the next node and remove the current text node. + newnode = node.nextSibling; + $(node).remove(); + node = newnode; + } else { + // To avoid iterating over any nodes we are adding (infinite loop) + // we use node.nextSibling to get the next node and insert any + // new nodes before the current one. + node = node.nextSibling; + } + } + }); + +}); diff --git a/nightly_8.4/linkcheck/_static/js/minicylc.js b/nightly_8.4/linkcheck/_static/js/minicylc.js new file mode 100644 index 00000000000..d6f2fa90ced --- /dev/null +++ b/nightly_8.4/linkcheck/_static/js/minicylc.js @@ -0,0 +1,354 @@ +/* ---------------------------------------------------------------------------- + * THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. + * Copyright (C) NIWA & British Crown (Met Office) & Contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- */ + +/*eslint no-console: off*/ + +// Default Cylc colour theme. +var minicylc_default_theme = { + 'waiting_fill': 'none', + 'waiting_stroke': 'black', + 'running_fill': '#55c3e5ff', + 'running_stroke': 'black', + 'succeed_fill': '#64c77eff', + 'succeed_stroke': 'black' +} + +// Old Cylc 7 theme. +var minicylc_cylc7_theme = { + 'waiting_fill': 'none', + 'waiting_stroke': '#88c6ff', + 'running_fill': '#00c410', + 'running_stroke': 'black', + 'succeed_fill': '#ada5a5', + 'succeed_stroke': 'black' +} + +// Demo colour theme for demmonstrating workflow logic. +var minicylc_demo_theme = { + 'succeed_fill': '#aabbff', + 'succeed_stroke': 'black' +} + + +class MiniCylc { + /** + * Class for animating SVG graphs. + * + * Attributes: + * - nodes: A dictionary of task names against a list of SVG nodes. + * - edges: A dictionary of task edges against a list SVG nodes. + * - dependencies: A dictionary of task names against a list of + * conditional expressions. + */ + + constructor(div) { + /** + * Initiate the object. + * @param div The
element containing the SVG. + * */ + this.div = div; + this.load(); + } + + load() { + /** + * Obtain nodes and edges from svg. + * + * This function calls itself recursively until the SVG is loaded. + * + * This function starts the animation when finished. + */ + const svg = ($(this.div).find('object:first')[0]).contentDocument; + const self = this; + + if (!svg) { + console.log('Wait for SVG load: Gecko'); + // this retry loop works for Firefox, etc + setTimeout(function() { + self.load(); + }, 500) + return; + } + var eles = $(svg).find('g'); + if (!eles.length) { + console.log('Wait for SVG load: Blink'); + // this retry loop works for Chrome, etc + setTimeout(function() { + self.load(); + }, 500) + return; + } + + this._find_svg_elements(svg); + + // Parse dependencies. + var deps = this._get_dependencies_from_graph(this.div); + this._construct_dependency_map(deps); + + // Process colour theme. + this.setup_colours($(this.div).data('theme')); + + this.run() + } + + setup_colours(theme) { + /** + * Set the colour theme. + * @param theme The name of a colour theme as a string. + */ + if (!theme || theme == 'default') { + this.theme = minicylc_default_theme; + } else if (theme == 'demo') { + this.theme = minicylc_demo_theme; + } else if (theme == 'cylc7') { + this.theme = minicylc_cylc7_theme; + } else { + console.log('Warning: Invalid theme detected "' + theme + + '", defaulting to black.'); + this.theme = {}; + } + } + + _find_svg_elements(svg) { + /** + * Associate task/dependency names with SVG nodes. + * + * Associations stored as dictionaries this.nodes and this.edges. + * @param svg The element containing the workflow. + */ + var nodes = {}; + var edges = {}; + $(svg).find('g').each(function() { + var node = $(this)[0]; + var node_class = $(node).attr('class'); + if (node_class == 'node') { + nodes[node.textContent.trim().split('\n')[0]] = node; + } else if (node_class == 'edge') { + edges[node.textContent.trim().split('\n')[0]] = node; + } + }); + this.nodes = nodes; + this.edges = edges; + } + + _get_dependencies_from_graph(div) { + /** + * Extract, parse and return a list of dependencies. + * @param div The minicylc
element. + * @return A list of [left, right] lists e.g. ['a & b', 'c']. + */ + var deps = []; + var ind = 0; + var parts; + for (let dep of $(div).data('dependencies').split('//')) { + parts = dep.split('=>'); + if (parts.length == 0) { + continue; // Graph line does not contain a dependency => skip. + } + for(ind = 0; ind < parts.length-1; ind++) { + deps.push([parts[ind].trim(), parts[ind + 1].trim()]); // [left, right]. + } + } + + return deps; + } + + _construct_dependency_map(deps) { + /** + * Associate tasks with conditional expressions. + * + * Associations stored as a dictionary - this.dependencies. + * @param deps A list of dependencies in the form [[left, right], ...]. + */ + var condition; + var conditional_regex = /[()&]/; + var conditional_regex2 = /([()&|])/; + var conditional_chars = ['(', ')', '|', '&']; + this.dependencies = {}; + for (let dep of deps) { + // Build a javascript parsable conditional statement. + condition = []; + for (let left of dep[0].split(conditional_regex2)) { + left = left.trim(); + if (left) { + if (!conditional_chars.includes(left)) { + // All dependencies are :succeed by default, + // dependencies are checked using + // this.succeed.has(task). + condition.push('this.succeed.has("' + left + '")'); + } else { + // conditional character. + condition.push(left); + } + } + } + condition = condition.join(' '); + + // Associate conditional statements with tasks. + for (let right of dep[1].split(conditional_regex)) { + right = right.trim(); + if (!this.dependencies[right]) { + this.dependencies[right] = []; + } + this.dependencies[right].push(condition); + } + } + } + + evaluate_dependencies(task) { + /** + * Check if a task's dependencies are satisfied. + * @param task The name of the task to evaluate. + * @return true if satisfied else false. + */ + var deps = this.dependencies[task]; + if (!deps) { + return true; + } + for (let dep of deps) { + if (eval(dep) == 0) { + return false; + } + } + return true; + } + + _style_node(node, fill, stroke) { + /** + * Style a graphviz node. + * @param fill The fill colour for SVG e.g. 'none', '#aabbcc', 'black'. + * @param stroke The stroke colour for SVG. + */ + if (!fill) { + fill = 'none'; // Default to an unfilled node. + } + if (!stroke) { + stroke = 'black'; // Default to a black border. + } + // Style nodes. + $($(this.nodes[node]).find('ellipse:first')).attr({ + 'fill': fill, + 'stroke': stroke + }); + } + + _style() { + /** + * Refresh the style of graph nodes based on their state. + */ + for (let task of this.waiting) { + this._style_node(task, + this.theme['waiting_fill'], + this.theme['waiting_stroke']); + } + for (let task of this.running) { + this._style_node(task, + this.theme['running_fill'], + this.theme['running_stroke']); + } + for (let task of this.succeed) { + this._style_node(task, + this.theme['succeed_fill'], + this.theme['succeed_stroke']); + } + } + + _init() { + /** + * Initiate the simulation / animation. + */ + this.waiting = new Set(); + this.running = new Set(); + this.succeed = new Set(); + for (let task in this.nodes) { + this.waiting.add(task); + } + this._style(); + } + + _advance() { + /* + * To be called with each main loop. + * @return true if the task pool has changed else false. + */ + var changed = false; + for (let task of this.running) { + this.running.delete(task); + this.succeed.add(task); + changed = true; + } + for (let task of this.waiting) { + if (this.evaluate_dependencies(task)) { + this.waiting.delete(task); + this.running.add(task); + changed = true; + } + } + return changed; + } + + _main_loop(itt) { + /* + * The main loop - runs the simulation and handles restyling of nodes. + * Note function calls itself recursively. + */ + var exit = false; + + // Action. + if (this._advance()) { // Advance the task pool. + // If anything has changed restyle. + this._style(); + } else { + // If nothing has changed... + if (this.waiting.size == 0 && this.running.size == 0) { + // The simulation has ended, reset and restart. + this._init(); + } else { + // The worklfow stalled, log a console message and do nothing. + exit = true; + console.log('Workflow stalled :('); + } + } + + // Callback. + if (!exit) { + var self_ref = this; + setTimeout(function(){ + self_ref._main_loop(itt + 1); + }, 3000); + } + } + + run() { + /* + * Run this simulation. + */ + this._init(); + this._main_loop(0); + } + +} + + +// Activate minicylc. +$(document).ready(function() { + $('.minicylc').each(function() { + var obj = this; + new MiniCylc(obj); + }); +}); diff --git a/nightly_8.4/linkcheck/_static/js/spoiler.js b/nightly_8.4/linkcheck/_static/js/spoiler.js new file mode 100644 index 00000000000..55c3715010d --- /dev/null +++ b/nightly_8.4/linkcheck/_static/js/spoiler.js @@ -0,0 +1,67 @@ +/* ---------------------------------------------------------------------------- + * THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. + * Copyright (C) NIWA & British Crown (Met Office) & Contributors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- */ + +/* This file implements spoiler sections which are hidden by default. */ + +// sphinx_admonition_class: bootstrap_button_class +const sphinx_admonition_classes = { + 'attention': 'warning', + 'caution': 'warning', + 'error': 'danger', + 'hint': 'success', + 'important': 'success', + 'note': 'info', + 'tip': 'success', + 'warning': 'warning', + 'danger': 'danger' +} + +$(document).ready(function() { + var button_class; + var spoilers = $('.spoiler'); + for (let spoiler of spoilers) { + // Hide content. + $(spoiler).children().hide(); + $(spoiler).find('.admonition-title').show(); + + // Determine button class. + button_class = 'default'; + for (let css_class of $(spoiler).attr('class').split(' ')) { + if (css_class in sphinx_admonition_classes) { + button_class = sphinx_admonition_classes[css_class]; + break; + } + } + + // Add button + $(spoiler).append( + $('