From 3c243723567c9203ed8e2f7679eef48782e6fc53 Mon Sep 17 00:00:00 2001 From: atteggiani Date: Wed, 28 Jun 2023 18:49:39 +1000 Subject: [PATCH 1/7] Added content until "Edit configuration" --- docs/css/access-nri.css | 91 +- docs/js/terminal_animation.js | 1032 +++++++++++++++++ .../running-a-model/running-access-cm.md | 8 +- .../running-a-model/running-access-esm.md | 262 +++++ mkdocs.yml | 5 +- 5 files changed, 1392 insertions(+), 6 deletions(-) create mode 100644 docs/js/terminal_animation.js diff --git a/docs/css/access-nri.css b/docs/css/access-nri.css index 2e8b2ad87..f49855196 100644 --- a/docs/css/access-nri.css +++ b/docs/css/access-nri.css @@ -129,7 +129,7 @@ ACCESS gold */ /* Header */ .md-header { - padding-top: 1em; + /* padding-top: 1em; */ box-shadow: 0 0 0.2rem rgb(0 0 0 / 10%), 0 0rem 0.4rem rgb(0 0 0 / 20%); } @@ -401,4 +401,93 @@ ACCESS gold */ color: #F9A61C; transition-duration: 0.4s; } + +.md-typeset h3 { + margin: 1em 0 0.4em; +} + +/* Justified text */ +.justified { + text-align: justify; +} + +/* Show different markers for different hieratchy of points (up to 3d hierarchy) */ +ul:not([class^='md-']) li { + list-style-type: disc; +} + +ul:not([class^='md-']) li ul li { + list-style-type: circle; +} + +ul:not([class^='md-']) li ul li ul li { + list-style-type: square; +} + +/* Code block */ +pre:has(code) { + display: flow-root !important; + text-align: left !important; + padding: 0 0 !important; + margin-top: 0.5em !important; + margin-bottom: 0.5em !important; +} + +pre>code { + display: block !important; + white-space: pre-line !important; + padding: 0.5em 0.8em !important; + word-break: break-all !important; +} + +/* References */ +.references { + font-size:0.8em; +} + +/* Page summary ('on this page' section) */ +div.page-summary { + max-width: 100%; + border: solid 0.5px var(--md-typeset-color); + border-radius: 3px; + padding: 0 15px 10px; + line-height: 1.2em; + margin: 20px 0; +} + +.page-summary h4 { + margin: 0.7em 0; +} + +.page-summary ol { + list-style-type: none !important; + counter-reset: item !important; + margin: 0 !important; + padding: 0 !important; +} + +.page-summary li { + display: table !important; + counter-increment: item !important; + margin: 0 0 0.5em 0.5em !important; +} + +.page-summary li:before { + content: counters(item, ".") ". " !important; + display: table-cell !important; + padding-right: 0.3em !important; +} + +.page-summary li li { + margin: 0.1em 0 0 0 !important; +} + +.page-summary li li:before { + content: counters(item, ".") ". " !important; +} + +div.version label { + font-size: 1rem !important; +} + /* -------------------------------------------- */ diff --git a/docs/js/terminal_animation.js b/docs/js/terminal_animation.js new file mode 100644 index 000000000..e2d702c06 --- /dev/null +++ b/docs/js/terminal_animation.js @@ -0,0 +1,1032 @@ +/** + * terminal-animation components + * Components based on the animated terminal app 'termynal.js' by Ines Montani . + * + * @author Davide Marchegiani + * @version 1.0.0 + * + * The usage is as follow: + * + * + * First input line + * Second input line + * Third input with red span + * First output line + * + * + * The tag allows only and tags inside it. All the other nodes will be removed. + * E.g.: + * + * This line will be removed + * This line will be kept + *
Also this line will be removed
+ *
+ * + * The tag allows only text nodes or tags inside it. All the other nodes will be removed. + * E.g.: + * All this line will be kept + * This will be kept but
this will be removed
+ * + * The animation starts only when the terminal becomes visible, unless the 'init' + * attribute is present (in that case the animation starts right after the page loads). + * To know all the other possible attributes and what they do please read the specific components. + * + * + * List of sub-components editable with the CSS ::part pseudo-element: + * - Terminal Container -> ::part(terminal-container) + * - Fast Button -> ::part(fast-button) + * - Restart Button -> ::part(restart-button) + * - Directory -> ::part(directory) + * - Input Character(s) -> ::part(input-character) + * - Prompt Character(s) -> ::part(prompt-character) +*/ +'use strict'; + + +const terminalTemplate = document.createElement('template'); +terminalTemplate.innerHTML = ` + + +
+ +
+` +/* Terminal component */ +class TerminalAnimation extends HTMLElement { + /** + * Custom attributes for the component: + * + * @param {string} mode - 'light' for light mode; 'dark' for dark mode (default). + * @param {string} data - Type of prompt for each line of the entire terminal. Choices can be: + * - 'output': Output of the terminal. Written all at once; (default) + * - 'input': Input to the terminal. Written with typing animation after 'directory' and 'inputChar' attributes; + * - 'prompt': Same as input, but with written with typing animation after 'promptChar' attribute; + * - 'progress' Line with progress bar animation. + * @param {number || string} startDelay - Delay before the start of terminal animation, in ms. + * @param {number || string} lineDelay - Delay before the start of each terminal line animation, in ms. + * @param {number || string} typingDelay - Delay between each typed character in the terminal, in ms. + * @param {string} progressChar – Character(s) to use for progress bar for the entire terminal, defaults to █. + * @param {number || string} progressPercent - Max percent of progress for the entire terminal, default 100%. + * @param {string} cursor – Character to use for cursor for the entire terminal, defaults to ▋. + * @param {string} inputChar – Character(s) to use before the 'input' prompt for the entire terminal, defaults to '$'. + * @param {string} directory – Directory to write in the 'input' prompt before the input character for the entire terminal. + * @param {string} promptChar – Character(s) to use before the 'prompt' prompt for the entire terminal, defaults to '>>>'. + * @param {string} PS1 – String to write in the 'input' prompt before the actual line for the entire terminal. + * If present, any 'directory' or 'input' attribute will be disregarded. + * Accepts HTML format. E.g.: "This is a valid PS1 attribute" + * @param {boolean} init - Initialise the terminal animation at page load. + * @param {boolean} static - Create a static terminal without animation. + */ + constructor() { + super(); + this.attachShadow({ mode: "open" }); + this.shadowRoot.appendChild(terminalTemplate.content.cloneNode(true)); + this.applyMode(); + this.ALLOWED_TAGS = ['terminal-line','img']; + this.DATA_TYPES = ['input','prompt','progress','output']; + this.keepLines(); + if (!this.static) { + this.setTerminal(); + if (this.init) { + this.initialiseAnimation(); + } else { + this.initialiseWhenVisible(); + } + } else { + this.generateAllProgress(); + } + } + + get container() { + const container = this.shadowRoot.querySelector(".terminal-container"); + if (this.hasAttribute('lineDelay')) { + container.setAttribute('lineDelay',parseFloat(this.getAttribute('lineDelay'))) + } + if (this.hasAttribute('typingDelay')) { + container.setAttribute('typingDelay',parseFloat(this.getAttribute('typingDelay'))) + } + return container + } + + get mode() { + /** + * Getter for the mode property + */ + if (this.getAttribute('mode')?.toString().toLowerCase() == 'light') { + return 'light'; + } else { + return 'dark'; + } + } + + get data() { + /** + * Getter for the data property + */ + let attr = this.getAttribute('data'); + if (this.DATA_TYPES.includes(attr)) { + return attr; + } else { + return 'output' + } + } + + get startDelay() { + /** + * Resets startDelay property. + */ + return parseFloat(this.getAttribute('startDelay')) || 300; + } + + get progressChar() { + /** + * Getter for the progressChar property + */ + return this.getAttribute('progressChar')?.toString() || '█'; + } + + get progressPercent() { + /** + * Getter for the progressPercent property + */ + return parseFloat(this.getAttribute('progressPercent')) || 100; + } + + get cursor() { + /** + * Getter for the cursor property + */ + return this.getAttribute('cursor')?.toString() || '▋'; + } + + get inputChar() { + /** + * Getter for the inputChar property + */ + if (this.hasAttribute('PS1')) { + return ''; + } else { + return this.getAttribute('inputChar')?.toString() || '$'; + } + } + + get promptChar() { + /** + * Getter for the promptChar property + */ + return this.getAttribute('promptChar')?.toString() || '>>>'; + } + + get directory() { + /** + * Getter for the directory property + */ + if (this.hasAttribute('PS1')) { + return ''; + } else { + return this.getAttribute('directory')?.toString() || ''; + } + } + + get PS1() { + /** + * Getter for the PS1 property + */ + if (this.hasAttribute('PS1')) { + return this.getAttribute('PS1'); + } else { + return `${this.directory}${this.inputChar} `; + } + } + + get static() { + /** + * Getter for the static property + */ + let attr = this.getAttribute('static') + if (attr == 'false') { + return false + } else if (attr == "") { + return true + } else { + return !!attr + } + } + + get init() { + /** + * Getter for the init property + */ + let attr = this.getAttribute('init') + if (attr == 'false') { + return false + } else if (attr == "") { + return true + } else { + return !!attr + } + } + + applyMode() { + /** + * Sets the color scheme according to the mode selected. + */ + const colors = document.createElement('style'); + if (this.mode == 'dark') { + colors.innerHTML = ` + :host { + --color-bg: #252a33; + --color-text: #eee; + --color-control-buttons: #FAA619; + --color-control-buttons-hover: #115D97; + --color-scrollbar: rgba(255, 255, 255, .6); + ` + } else { + colors.innerHTML = ` + :host { + --color-text: #252a33; + --color-bg: #eee; + --color-control-buttons-hover: #FAA619; + --color-control-buttons: #115D97; + --color-scrollbar: rgba(0, 0, 0, .6); + ` + } + this.shadowRoot.appendChild(colors); + } + + keepLines() { + /* + * Delete all terminal lines without tags or whose tags are not within the elementList + * and create the lines property with the kept ones. + */ + for (let i=0; i { + if (line.data == 'progress') { + line.generateProgress(); + } + }) + } + + hide(element) { + /** + * Change element's style to 'hidden' + */ + element.style.visibility = 'hidden'; + } + + show(element) { + /** + * Change element's style to 'visible' + */ + element.style.visibility = 'visible'; + } + + sleep(time) { + /** + * Sleep for an amount of time + */ + return new Promise(resolve => setTimeout(resolve, time)); + } + + resetDelays() { + this.lines.forEach(line => { + line._lineDelay; + line._typingDelay; + }) + } + + hideLines() { + /** + * Hide lines inside the terminal + */ + this.lines.forEach(line => this.hide(line)); + } + + generateRestartButton() { + /** + * Generate restart button and adds it hidden to 'this.container' + */ + const restart = document.createElement('a') + restart.setAttribute('part','restart-button') + restart.onclick = e => { + e.preventDefault(); + this.hideAll(); + this.scrollToTop(); + this.mutationObserver.disconnect(); + this.initialiseAnimation(); + } + restart.href = ''; + restart.classList.add('restart-button'); + restart.innerHTML = "restart ↻"; + this.hide(restart); + restart.addEventListener('click', e => this.hide(restart)); + this.restartButton = restart; + this.container.appendChild(restart); + } + + generateFastButton() { + /** + * Generate fast button and adds it hidden to 'this.container' + */ + function nullifyDelays(_this) { + _this.lines.forEach(line => { + line._lineDelay = 0; + line._typingDelay = 0; + }) + } + const fast = document.createElement('a') + fast.setAttribute('part','fast-button') + fast.onclick = (e) => { + e.preventDefault(); + nullifyDelays(this); + } + fast.href = ''; + fast.classList.add('fast-button'); + fast.innerHTML = "fast ❯❯❯"; + this.hide(fast); + fast.addEventListener('click', e => this.hide(fast)); + this.addFocusOnTerminalContainerOnClick(fast); + this.fastButton = fast; + this.container.prepend(fast); + } + + setTerminal() { + /** + * Clear container and generate restart/fast buttons. + */ + this.hideLines(); + this.generateRestartButton(); + this.generateFastButton(); + this.generateObservers(); + } + + hidePS1AndPromptChar() { + /** + * Hides PS1 and Prompt Char for terminal reset + */ + this.lines.forEach(line => { + let elem = line.shadowRoot?.querySelector('.ps1, .promptChar'); + if (elem) { + this.hide(elem); + } + }) + } + + hideAll() { + this.hideLines(); + this.hidePS1AndPromptChar(); + } + + async initialiseAnimation() { + /** + * Start the animation and render the lines + */ + // while (this.container.scrollTop != 0) {await this.sleep(50)} //Start when the container is scroll up to the top. + this.autoScroll(); + await this.sleep(this.startDelay); + this.show(this.fastButton); + for (let line of this.lines) { + line.classList.add('isBeingTyped'); + if (line.tagName.toLowerCase() == 'terminal-line') { + // Handle lines + await line.type(); + } else if (line.tagName.toLowerCase() == 'img') { + // Handle lines + this.show(line); + // await this.sleep(2000); + // this.hide(line); + } + line.classList.remove('isBeingTyped'); + } + this.hide(this.fastButton); + this.resetDelays(); + this.show(this.restartButton); + } + + initialiseWhenVisible() { + /** + * Initialise the terminal only when it becomes visible + */ + let observer = new IntersectionObserver(entries => { + entries.forEach(entry => { + if (entry.isIntersecting) { + this.initialiseAnimation(); + observer.unobserve(this); + } + }) + }, + { + rootMargin: "-50px", + }) + observer.observe(this); + } + + addFocusOnTerminalContainerOnClick(elem) { + elem.addEventListener('click',() => this.container.focus()) + } + + scrollToTop() { + // Scroll to the bottom of the container. + this.container.scrollTop = 0; + } + + scrollToBottom() { + // Scroll to the bottom of the container. + this.container.scrollTop = this.container.scrollHeight; + } + + scrollOneLine(line) { + const nPix = parseInt(getComputedStyle(line).height); + this.container.scrollBy(0,nPix); + } + + generateObservers() { + const intersectionFunction = entry => { + if (entry.intersectionRatio == 1) { + intersectionObserver.unobserve(entry.target); + } else { + if (entry.target.nextSibling) { + this.scrollOneLine(entry.target); + } + intersectionObserver.unobserve(entry.target); + } + } + + let margin = `${parseInt(getComputedStyle(this.container).marginBottom) - 5}px` // Margin of the intersectionObserver computed as bottom margin - 5px (5px padding) + let intersectionObserver = new IntersectionObserver(entries => { + entries.forEach(entry => { + console.log(entry.intersectionRatio) + console.log(this.container.scrollTop) + intersectionFunction(entry) + }) + }, + { + root: this.container, + rootMargin: `0px 0px ${margin} 0px`, + }) + + const mutationFunction = entry => { + if (entry.target.nextSibling) { + intersectionObserver.observe(entry.target.nextSibling) + } else { + this.scrollToBottom(); + } + } + + this.mutationObserver = new MutationObserver(entries => { + entries.forEach(entry => { + if (entry.oldValue?.includes("isBeingTyped")) { + mutationFunction(entry) + } + }) + }) + } + + autoScroll() { + /** + * Auto scrolls 1 line if the terminal content exceeds the terminal max-height. + */ + this.lines.forEach(line => { + this.mutationObserver.observe(line,{ + attributes: true, + attributeOldValue: true, + attributeFilter: ["class"] + }) + }); + + this.addEventListener('wheel', e => { + this.mutationObserver.disconnect(); + }) + + this.addEventListener('keydown', e => { + if (['ArrowDown','Space','ArrowUp'].includes(e.code)) { + this.mutationObserver.disconnect(); + } + }) + } +} + +/* ============================================================================================================= + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== */ + + /* Terminal line */ +const lineTemplate = document.createElement('template'); +lineTemplate.innerHTML = ` + + + +
+ + +` + +class TerminalLine extends HTMLElement { + /** + * Defining custom attributes for component + // * @param {string} data - Type of prompt for the current line. Choices can be: + // * - 'output': Output of the terminal. Written all at once; (default) + // * - 'input': Input to the terminal. Written with typing animation after 'directory' and 'inputChar' attributes; + // * - 'prompt': Same as input, but with written with typing animation after 'promptChar' attribute; + // * - 'progress' Line with progress bar animation. + // * @param {number} lineDelay - Delay before the start of the line animation, in ms. + // * @param {number} typingDelay - Delay between each typed character in the line, in ms. + // * @param {string} progressChar – Character to use for progress bar in the line, defaults to █. + // * @param {number} progressPercent - Max percent of progress in the line, default 100%. + // * @param {string} cursor – Character to use for cursor in the line, defaults to ▋. + // * @param {string} inputChar – Character(s) to use before the 'input' prompt in the line, defaults to '$'. + // * @param {string} directory – Directory to write in the 'input' prompt before the input character in the line. + // * @param {string} promptChar – Character(s) to use before the 'prompt' prompt in the line, defaults to '>>>'. + // * @param {string} PS1 – String to write in the 'input' prompt before the actual line. + If present, any 'directory' or 'input' attribute will be disregarded. + Accepts HTML format. E.g.: "This is a valid PS1 attribute" + // */ + constructor() { + super(); + const shadow = this.attachShadow({ mode: "open" }); + shadow.appendChild(lineTemplate.content.cloneNode(true)); + this.ALLOWED_NODES = ["span"]; + this.line = this.shadowRoot.querySelector(".terminal-line"); + this.setCursorChar(); + this.keepNodes(); + this.generatePS1AndPromptCharElements(); + this.resetDelays(); + this.container.addFocusOnTerminalContainerOnClick(this); + } + + get container() { + if (this.parentElement.tagName.toLowerCase() != 'terminal-animation') { + throw new Error("A 'terminal-line' tag can only be placed inside a 'terminal-animation' tag."); + } + return this.parentElement; + } + + get data() { + /** + * Getter for the data property + */ + if (this.hasAttribute('data')) { + let attr = this.getAttribute('data'); + if (this.container.DATA_TYPES.includes(attr)) { + return attr; + } else { + return 'output'; + } + } else { + return this.container.data; + } + } + + get _lineDelay() { + /** + * Resets lineDelay property. + */ + if (this.hasAttribute('lineDelay')) { + this.lineDelay = parseFloat(this.getAttribute('lineDelay')); + } else if (this.container.hasAttribute('lineDelay')) { + this.lineDelay = parseFloat(this.container.getAttribute('lineDelay')); + } else if (["input","prompt"].includes(this.data)) { + this.lineDelay = 600; + } else { + this.lineDelay = 100; + } + } + + set _lineDelay(time) { + /** + * Sets lineDelay property. + */ + this.lineDelay = time; + } + + get _typingDelay() { + /** + * Resets typingDelay property. + */ + if (this.hasAttribute('typingDelay')) { + this.typingDelay = parseFloat(this.getAttribute('typingDelay')); + } else if (this.container.hasAttribute('typingDelay')) { + this.typingDelay = parseFloat(this.container.getAttribute('typingDelay')); + } else if (["progress"].includes(this.data)) { + this.typingDelay = 30; + } else { + this.typingDelay = 80; + } + } + + set _typingDelay(time) { + /** + * Sets typingDelay property. + */ + this.typingDelay = time; + } + + resetDelays() { + this._lineDelay; + this._typingDelay; + } + + get progressChar() { + /** + * Getter for the progressChar property + */ + return this.getAttribute('progressChar')?.toString() || this.container.progressChar; + } + + get progressPercent() { + /** + * Getter for the progressPercent property + */ + return parseFloat(this.getAttribute('progressPercent')) || this.container.progressPercent; + } + + get cursor() { + /** + * Getter for the cursor property + */ + return this.getAttribute('cursor')?.toString() || this.container.cursor; + } + + get inputChar() { + /** + * Getter for the inputChar property + */ + if (this.hasAttribute('PS1')) { + return ''; + } else { + return this.getAttribute('inputChar')?.toString() || this.container.inputChar; + } + } + + get promptChar() { + /** + * Getter for the promptChar property + */ + return this.getAttribute('promptChar')?.toString() || this.container.promptChar; + } + + get directory() { + /** + * Getter for the directory property + */ + if (this.hasAttribute('PS1')) { + return ''; + } else { + return this.getAttribute('directory')?.toString() || this.container.directory; + } + } + + get PS1() { + /** + * Getter for the PS1 property + */ + if (this.hasAttribute('PS1')) { + return this.getAttribute('PS1'); + } else if (this.hasAttribute('directory') || this.hasAttribute('inputChar')) { + return `${this.directory}${this.inputChar} `; + } else { + return this.container.PS1; + } + } + + setCursorChar() { + const style = document.createElement('style'); + style.innerHTML=` + .cursor::after { + content: '${this.cursor}'; + font-family: monospace; + -webkit-animation: blink 1s infinite; + animation: blink 1s infinite; + } + + @-webkit-keyframes blink { + 50% { + opacity: 0; + } + } + + @keyframes blink { + 50% { + opacity: 0; + } + } + ` + this.shadowRoot.appendChild(style); + } + + keepNodes(elementList=this.ALLOWED_NODES) { + /* + * Delete all line nodes whose tags are not within the elementList, + * create tags around textNodes, + * and create the nodes property with the kept ones. + */ + for (let i=0; i setTimeout(resolve, time)); + } + + showPS1() { + this.show(this.shadowRoot.querySelector('.ps1')); + } + + showPromptChar() { + this.show(this.shadowRoot.querySelector('.promptChar')); + } + + async type() { + /** + * Function that handles the animation of the current line based on its data property + */ + if (this.data == 'input') { + this.showPS1(); + await this.typeInput(); + } else if (this.data == 'progress') { + await this.sleep(this.lineDelay); + await this.typeProgress(); + return; + } else if (this.data == 'prompt') { + this.showPromptChar(); + await this.typeInput(); + } else { + await this.sleep(this.lineDelay); + this.show() + } + + } + + measureChar(char=this.progressChar) { + const ruler = document.createElement('span'); + ruler.innerHTML = char; + ruler.style.whiteSpace = 'pre'; + this.appendChild(ruler); + const width = ruler.offsetWidth; + this.removeChild(ruler); + return width; + } + + async typeProgress() { + /** + * Animate a progress bar. + */ + const progressCharWidth = this.measureChar(); + const progressSteps = Math.round((parseInt(getComputedStyle(this).width)*0.8*(this.progressPercent/100))/progressCharWidth); + let percent = 0; + this.textContent = '0%'; + this.show(); + for (let i=1; i<=progressSteps; i++) { + await this.sleep(this.typingDelay); + percent = Math.round(this.progressPercent/progressSteps*i) + this.textContent = `${this.progressChar.repeat(i)} ${percent}%`; + } + } + + generateProgress() { + const progressCharWidth = this.measureChar(); + const progressLength = Math.round((parseInt(getComputedStyle(this).width)*0.8*(this.progressPercent/100))/progressCharWidth); + this.textContent = `${this.progressChar.repeat(progressLength)} ${this.progressPercent}%`; + } + + async typeInput() { + /** + * Animate an input line. + */ + let textArray = this.getAndRemoveTextContent(); + this.show(); + this.addCursor(); + await this.sleep(this.lineDelay); + for (let i=0; i -ACCESS-CM2 is a set of sub-models (eg. UM, MOM, CICE, CABLE, OASIS) with a range of model parameters, input data, and computer related information, that need to be packaged together as a suite in order to run. +ACCESS-CM2 is a set of submodels (eg. UM, MOM, CICE, CABLE, OASIS) with a range of model parameters, input data, and computer related information, that need to be packaged together as a suite in order to run.
Each ACCESS-CM2 suite has an ID, in the format u-<suite-name>, with <suite-name> being a unique identifier (e.g. u-br565 is the CMIP6 release preindustrial experiment suite).
@@ -218,11 +218,11 @@ After completing all the modifications to the suite, we are ready to run it.
ACCESS-CM2 suites run on Gadi through a PBS job submission.
-When the suite gets run, the suite configuration files are copied on Gadi under /scratch/<$PROJECT>/$USER/cylc-run/<suite-ID>, and a symbolic link to this folder is also created in the $USER's home directory under ~/cylc-run/<suite-ID>. +When the suite gets run, its configuration files are copied on Gadi under /scratch/$PROJECT/$USER/cylc-run/<suite-ID>, and a symbolic link to this folder is also created in the $USER's home directory under ~/cylc-run/<suite-ID>.
An ACCESS-CM2 suite is constituted by several tasks (such as checking out code repositories, compiling and building the different model components, running the model, etc.). The workflow of these tasks is controlled by Cylc.
-Cylc (pronounced ‘silk’), is a workflow manager that automatically executes tasks according to the model main cycle script suite.rc. Cylc deals with how the job will be run and manages the time steps of each sub-model, as well as monitoring all the tasks and reporting any error that might occur. +Cylc (pronounced ‘silk’), is a workflow manager that automatically executes tasks according to the model main cycle script suite.rc. Cylc deals with how the job will be run and manages the time steps of each submodel, as well as monitoring all the tasks and reporting any error that might occur.
To run an ACCESS-CM2 suite, on accessdev:
    @@ -515,7 +515,7 @@ This directory contains 2 subdirectories:
    References
    -
      +
      • https://confluence.csiro.au/display/ACCESS/Using+CM2+suites+in+Rose+and+Cylc
      • diff --git a/docs/models/running-a-model/running-access-esm.md b/docs/models/running-a-model/running-access-esm.md index e69de29bb..8786a06e5 100644 --- a/docs/models/running-a-model/running-access-esm.md +++ b/docs/models/running-a-model/running-access-esm.md @@ -0,0 +1,262 @@ +--- +hide: + - toc +--- +#
        Run ACCESS-ESM
        + + +##
        Requirements
        +
        +Before running ACCESS-ESM, you need to make sure to possess the right tools and to have an account with specific institutions. +
        + +###
        General requirements
        +
        +For the general requirements needed to run all ACCESS models, please refer to the Getting Started (TO DO check link) page. +
        + +###
        Model-specific requirements
        +
        +
          +
        • + Payu +
          + To get payu on Gadi, run: +
          module use /g/data/hh5/public/modules
          +            module load conda/analysis3
          +        
          + To avoid running the lines above every time you need to run ACCESS-ESM, you may add the following lines to your ~/bashrc file: +
          if in_interactive_shell && in_login_shell; then
          +              module use /g/data3/hh5/public/modules
          +              module load conda/analysis3
          +            fi
          +        
          +
        • +
        +
        +---------------------------------------------------------------------------------------- + +##
        Get ACCESS-ESM configuration
        +
        +A suitable ACCESS-ESM pre-industrial configuration is avaible on the coecms GitHub. +
        +In order to get it, on Gadi, create a directory where to keep the model configuration, and clone the GitHub repo in it by running: +
        git clone https://github.com/coecms/esm-pre-industrial
        + + mkdir -p ~/access-esm + cd ~/access-esm + git clone https://github.com/coecms/esm-pre-industrial + Cloning into 'esm-pre-industrial'... + remote: Enumerating objects: 767, done. + remote: Counting objects: 100% (295/295), done. + remote: Compressing objects: 100% (138/138), done. + remote: Total 767 (delta 173), reused 274 (delta 157), pack-reused 472 + Receiving objects: 100% (767/767), 461.57 KiB | 5.24 MiB/s, done. + Resolving deltas: 100% (450/450), done. + +Note: Some modules might interfere with the git commands (for example matlab/R2018a). If you are running into issues during the cloning of the repository, it might be a good idea to run
        module purge
        first, before trying again. +
        +---------------------------------------------------------------------------------------- + +##
        Edit ACCESS-ESM configuration
        +
        +In order to modify an ACCESS-ESM configuration, it is worth understanding a bit more how its job scheduler Payu works. +
        + +###
        Payu
        +
        +Payu is a workflow management tool for running numerical models in supercomputing environments. +
        +The general layout of a payu-supported model run consists of two main directories: +
          +
        • + The laboratory is the directory where all parts of the model are kept. For ACCESS-ESM, it is typically /scratch/$PROJECT/$USER/access-esm. +
        • +
        • + The control directory, where the model configuration is kept and from where the model is run (in our case is the cloned directory ~/access-esm/esm-pre-industrial). +
        • +
        +This separation allows to run multiple self-resubmitting experiments simultaneously that might share common executables and input data. +
        +To setup the laboratory, from the control directory run: +
        payu init
        +This will create the laboratory directory, along with 4 subdirectories: +
          +
        • bin → directory containing the model binaries.
        • +
        • input → directory containing all the input files.
        • +
        • work → temporary directory where the model is actually run. It gets cleaned after each run.
        • +
        • archive → directory where the output is placed after each run.
        • + + cd ~/access-esm/esm-pre-industrial + payu init + laboratory path: /scratch/$PROJECT/$USER/access-esm + binary path: /scratch/$PROJECT/$USER/access-esm/bin + input path: /scratch/$PROJECT/$USER/access-esm/input + work path: /scratch/$PROJECT/$USER/access-esm/work + archive path: /scratch/$PROJECT/$USER/access-esm/archive + +
        +
        + +###
        Edit the Master Configuration file
        +
        +The config.yaml file, located in the control directory, is the Master Configuration file. +
        +This file controls the general model configuration and if we open it in a text editor, we can see different parts: +
          +
        • + PBS resources +
          +
          jobname: pre-industrial
          +            queue: normal
          +            walltime: 20:00:00
          +        
          + These are settings for the PBS scheduler. Edit lines in this section to change any of the PBS resources. +
          + For example, to run ACCESS-ESM under a specific project, add the following line to this section: +
          project: <PROJECT>
          +
        • +
        • + Link to the laboratory directory +
          +
          # note: if laboratory is relative path, it is relative to /scratch/$PROJECT/$USER
          +            laboratory: access-esm
          +        
          + This will set the laboratory directory. Relative paths are relative to /scratch/$PROJECT/$USER. Absolute paths can be specified as well. +
        • +
        • + Model +
          model: access
          + The main model. This tells payu which driver to use (access stands for access-esm). +
        • +
        • + Submodels +
          +
          submodels:
          +              - name: atmosphere
          +                model: um
          +                ncpus: 192
          +                exe: /g/data/access/payu/access-esm/bin/coe/um7.3x
          +                input:
          +                  - /g/data/access/payu/access-esm/input/pre-industrial/atmosphere
          +                  - /g/data/access/payu/access-esm/input/pre-industrial/start_dump
          +   - name: ocean +     model: mom +     ncpus: 180 +     exe: /g/data/access/payu/access-esm/bin/coe/mom5xx +     input: +       - /g/data/access/payu/access-esm/input/pre-industrial/ocean/common +       - /g/data/access/payu/access-esm/input/pre-industrial/ocean/pre-industrial
          +   - name: ice +     model: cice +     ncpus: 12 +     exe: /g/data/access/payu/access-esm/bin/coe/cicexx +     input: +       - /g/data/access/payu/access-esm/input/pre-industrial/ice
          +   - name: coupler +     model: oasis +     ncpus: 0 +     input: +       - /g/data/access/payu/access-esm/input/pre-industrial/coupler +
          + access (i.e. ACCESS-ESM) is a coupled model, which means it has multiple submodels (i.e. model components). +
          + In this section, some of the parameters of the configurations of all ACCESS-ESM's submodels are specified. The full configuration of a specific submodel can be found in the subdirectory of the laboratory having the name of the submodel (e.g. the configuration for the atmosphere submodel, i.e. the UM, will be in the directory ) +
        • +
        • + collate +
          +
          collate:
          +              exe: /g/data/access/payu/access-esm/bin/mppnccombine
          +              restart: true
          +              mem: 4GB
          +        
          + The collate process joins a number of smaller files, which contain different parts of the model grid, together into target output files. The restart files are typically tiled in the same way. +
        • +
        • + collate +
          +
          restart: /g/data/access/payu/access-esm/restart/pre-industrial
          + The location of the files used for a warm restart. +
        • +
        • + Start date and internal run length +
          +
          calendar:
          +              start:
          +                year: 101
          +                month: 1
          +                days: 1
          +   runtime: +     years: 1 +     months: 0 +     days: 0 +
          + This section specifies the start date and internal run length. +
          + Note: The internal run length (controlled by runtime) can be different from the total run length. Also, the runtime value can be lowered, but should not be increased to a total of more than 1 year, to avoid errors. If you want to know more about the difference between internal run and total run lenghts, or if you want to run the model for more than 1 year, check Run ACCESS-ESM configuration. +
        • +
        • + Number of runs per PBS submission +
          +
          runspersub: 5
          + ACCESS-ESM configurations are often run in multiple steps (or cycles), with Payu running runspersub internal runs for every PBS submission, and resubmitting the job until the total run length is met. +
          + Note: If we increase runspersub, we might need to increate the walltime in the PBS resources. +
        • +
        +To know more about other configuration settings for the config.yaml file, please check Payu configuration settings documentation. +
        +---------------------------------------------------------------------------------------- + +##
        Run ACCESS-ESM configuration
        +
        +ACCESS-ESM suites run on Gadi through a PBS job submission managed by Payu. +
        +When the suite gets run, the suite configuration files are copied on Gadi under /scratch/<$PROJECT>/$USER/cylc-run/, and a symbolic link to this folder is also created in the $USER's home directory under ~/cylc-run/. +An ACCESS-CM2 suite is constituted by several tasks (such as checking out code repositories, compiling and building the different model components, running the model, etc.). The workflow of these tasks is controlled by Cylc. +Cylc (pronounced ‘silk’), is a workflow manager that automatically executes tasks according to the model main cycle script suite.rc. Cylc deals with how the job will be run and manages the time steps of each sub-model, as well as monitoring all the tasks and reporting any error that might occur. +
        +---------------------------------------------------------------------------------------- + +##
        Monitoring runs
        +
        +
        +---------------------------------------------------------------------------------------- + +##
        Model outputs
        +
        +
        + + + +
        +
        References
        + \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index f513d5f1c..db4994423 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -78,6 +78,8 @@ markdown_extensions: - pymdownx.details - pymdownx.superfences - pymdownx.inlinehilite + - pymdownx.tabbed: + alternate_style: true - def_list - footnotes - tables @@ -218,8 +220,8 @@ extra: community: '' extra_css: - - css/termynal.css - css/access-nri.css + - css/termynal.css - css/fontello.css - "https://fonts.googleapis.com/icon?family=Material+Icons" # Material Icons Reference - https://material.io/resources/icons/?style=baseline - css/fontawesome-free-6.4.0-web/css/fontawesome.css @@ -227,5 +229,6 @@ extra_css: extra_javascript: - js/termynal.js + - js/terminal_animation.js - https://unpkg.com/tablesort@5.3.0/dist/tablesort.min.js # For tablesort functionality - js/tablesort.js From 82aabad1c55b6f75c3e205453e688334a4ecd60c Mon Sep 17 00:00:00 2001 From: atteggiani Date: Wed, 28 Jun 2023 20:54:28 +1000 Subject: [PATCH 2/7] imp --- docs/css/access-nri.css | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/css/access-nri.css b/docs/css/access-nri.css index f49855196..273431c13 100644 --- a/docs/css/access-nri.css +++ b/docs/css/access-nri.css @@ -6,13 +6,14 @@ @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap'); :root > * { + --nri-green: #A6CE39; + --nri-orange: #FAA619; + --nri-dark-blue: #115D97; + --nri-blue: #06AEEF; + --nri-light-blue: #8ED7F8; --md-primary-fg-color: rgb(30, 29, 29); --md-primary-fg-color--light: #f5edd5; - --md-primary-fg-color--dark: #074473; - /* --md-primary-fg-color--dark: #FFA629; */ - - /* --md-primary-fg-color--dark: #105D98; */ - /* --md-primary-fg-color--dark: #a26d11; original */ + --md-primary-fg-color--dark: #074473; --md-accent-fg-color: #f5c533; --md-primary-tab-color: #2e303e; --md-primary-hover-tab-color: #444448; @@ -247,7 +248,7 @@ ACCESS gold */ } /* Highlight the background of headings ------------ */ -.highlight-bg { +.md-typeset .highlight-bg { background-color: rgba(29, 28, 28, 0.622); color: white; padding-top: 0.2em; From a9526c700ad7ddec0cfcd5ad9fcf039e367bccde Mon Sep 17 00:00:00 2001 From: atteggiani Date: Wed, 28 Jun 2023 20:55:11 +1000 Subject: [PATCH 3/7] improvements --- docs/css/custom.css | 75 ------------ docs/js/custom.js | 115 ------------------ .../running-a-model/running-access-esm.md | 40 +++--- 3 files changed, 20 insertions(+), 210 deletions(-) delete mode 100644 docs/css/custom.css delete mode 100644 docs/js/custom.js diff --git a/docs/css/custom.css b/docs/css/custom.css deleted file mode 100644 index 8a3e7adda..000000000 --- a/docs/css/custom.css +++ /dev/null @@ -1,75 +0,0 @@ -/* References: */ -/* https://github.com/tiangolo/fastapi/blob/master/docs/en/docs/css/custom.css */ - -.termynal-comment { - color: #4a968f; - font-style: italic; - display: block; -} - -.termy [data-termynal] { - white-space: pre-wrap; -} - -a.external-link::after { - /* \00A0 is a non-breaking space - to make the mark be on the same line as the link - */ - content: "\00A0[↪]"; -} - -a.internal-link::after { - /* \00A0 is a non-breaking space - to make the mark be on the same line as the link - */ - content: "\00A0↪"; -} - -.shadow { - box-shadow: 5px 5px 10px #999; -} - -/* Give space to lower icons so Gitter chat doesn't get on top of them */ -.md-footer-meta { - padding-bottom: 2em; -} - -.user-list { - display: flex; - flex-wrap: wrap; - margin-bottom: 2rem; -} - -.user-list-center { - justify-content: space-evenly; -} - -.user { - margin: 1em; - min-width: 7em; -} - -.user .avatar-wrapper { - width: 80px; - height: 80px; - margin: 10px auto; - overflow: hidden; - border-radius: 50%; - position: relative; -} - -.user .avatar-wrapper img { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); -} - -.user .title { - text-align: center; -} - -.user .count { - font-size: 80%; - text-align: center; -} diff --git a/docs/js/custom.js b/docs/js/custom.js deleted file mode 100644 index 39174f9ec..000000000 --- a/docs/js/custom.js +++ /dev/null @@ -1,115 +0,0 @@ -// References: -// https://github.com/tiangolo/fastapi/blob/master/docs/en/docs/js/custom.js - -function setupTermynal() { - document.querySelectorAll(".use-termynal").forEach(node => { - node.style.display = "block"; - new Termynal(node, { - lineDelay: 500 - }); - }); - const progressLiteralStart = "---> 100%"; - const promptLiteralStart = "$ "; - const customPromptLiteralStart = "# "; - const termynalActivateClass = "termy"; - let termynals = []; - - function createTermynals() { - document.querySelectorAll(`.${termynalActivateClass} .highlight`) - .forEach(node => { - const text = node.textContent; - const lines = text.split("\n"); - const useLines = []; - let buffer = []; - function saveBuffer() { - if (buffer.length) { - let isBlankSpace = true; - buffer.forEach(line => { - if (line) { - isBlankSpace = false; - } - }); - dataValue = {}; - if (isBlankSpace) { - dataValue["delay"] = 0; - } - if (buffer[buffer.length - 1] === "") { - // A last single
        won't have effect - // so put an additional one - buffer.push(""); - } - const bufferValue = buffer.join("
        "); - dataValue["value"] = bufferValue; - useLines.push(dataValue); - buffer = []; - } - } - for (let line of lines) { - if (line === progressLiteralStart) { - saveBuffer(); - useLines.push({ - type: "progress" - }); - } else if (line.startsWith(promptLiteralStart)) { - saveBuffer(); - const value = line.replace(promptLiteralStart, "").trimEnd(); - useLines.push({ - type: "input", - value: value - }); - } else if (line.startsWith("// ")) { - saveBuffer(); - const value = "💬 " + line.replace("// ", "").trimEnd(); - useLines.push({ - value: value, - class: "termynal-comment", - delay: 0 - }); - } else if (line.startsWith(customPromptLiteralStart)) { - saveBuffer(); - const promptStart = line.indexOf(promptLiteralStart); - if (promptStart === -1) { - console.error("Custom prompt found but no end delimiter", line) - } - const prompt = line.slice(0, promptStart).replace(customPromptLiteralStart, "") - let value = line.slice(promptStart + promptLiteralStart.length); - useLines.push({ - type: "input", - value: value, - prompt: prompt - }); - } else { - buffer.push(line); - } - } - saveBuffer(); - const div = document.createElement("div"); - node.replaceWith(div); - const termynal = new Termynal(div, { - lineData: useLines, - noInit: true, - lineDelay: 500 - }); - termynals.push(termynal); - }); - } - - function loadVisibleTermynals() { - termynals = termynals.filter(termynal => { - if (termynal.container.getBoundingClientRect().top - innerHeight <= 0) { - termynal.init(); - return false; - } - return true; - }); - } - window.addEventListener("scroll", loadVisibleTermynals); - createTermynals(); - loadVisibleTermynals(); -} - -async function main() { - setupTermynal(); -} - -main() diff --git a/docs/models/running-a-model/running-access-esm.md b/docs/models/running-a-model/running-access-esm.md index 8786a06e5..907a60383 100644 --- a/docs/models/running-a-model/running-access-esm.md +++ b/docs/models/running-a-model/running-access-esm.md @@ -2,7 +2,7 @@ hide: - toc --- -#
        Run ACCESS-ESM
        +# Run ACCESS-ESM

        On this page

          @@ -25,23 +25,23 @@ hide:
        -##
        Requirements
        +## Requirements
        Before running ACCESS-ESM, you need to make sure to possess the right tools and to have an account with specific institutions.
        -###
        General requirements
        +### General requirements
        -For the general requirements needed to run all ACCESS models, please refer to the Getting Started (TO DO check link) page. +For the general requirements needed to run all ACCESS models, please refer to the Getting Started (TO DO check link) page.
        -###
        Model-specific requirements
        +### Model-specific requirements
        • Payu
          - To get payu on Gadi, run: + To get Payu on Gadi, run:
          module use /g/data/hh5/public/modules
                       module load conda/analysis3
                   
          @@ -56,7 +56,7 @@ For the general requirements needed to run all ACCESS models, please refer to th
        ---------------------------------------------------------------------------------------- -##
        Get ACCESS-ESM configuration
        +## Get ACCESS-ESM configuration
        A suitable ACCESS-ESM pre-industrial configuration is avaible on the coecms GitHub.
        @@ -78,16 +78,16 @@ In order to get it, on Gadi, create a directory where to keep the model configur
        ---------------------------------------------------------------------------------------- -##
        Edit ACCESS-ESM configuration
        +## Edit ACCESS-ESM configuration
        In order to modify an ACCESS-ESM configuration, it is worth understanding a bit more how its job scheduler Payu works.
        -###
        Payu
        +### Payu
        Payu is a workflow management tool for running numerical models in supercomputing environments.
        -The general layout of a payu-supported model run consists of two main directories: +The general layout of a Payu-supported model run consists of two main directories:
        • The laboratory is the directory where all parts of the model are kept. For ACCESS-ESM, it is typically /scratch/$PROJECT/$USER/access-esm. @@ -118,7 +118,7 @@ This will create the laboratory directory, along with 4 subdirectories:
        -###
        Edit the Master Configuration file
        +### Edit the Master Configuration file
        The config.yaml file, located in the control directory, is the Master Configuration file.
        @@ -133,8 +133,8 @@ This file controls the general model configuration and if we open it in a text e These are settings for the PBS scheduler. Edit lines in this section to change any of the PBS resources.
        - For example, to run ACCESS-ESM under a specific project, add the following line to this section: -
        project: <PROJECT>
        + For example, to run ACCESS-ESM under the tm70 project (TO DO add NCI Project link), add the following line to this section: +
        project: tm70
      • Link to the laboratory directory @@ -142,12 +142,12 @@ This file controls the general model configuration and if we open it in a text e
        # note: if laboratory is relative path, it is relative to /scratch/$PROJECT/$USER
                     laboratory: access-esm
                 
        - This will set the laboratory directory. Relative paths are relative to /scratch/$PROJECT/$USER. Absolute paths can be specified as well. + This will set the laboratory directory. Relative paths are relative to /scratch/$PROJECT/$USER. Absolute paths can be specified as well.
      • Model
        model: access
        - The main model. This tells payu which driver to use (access stands for access-esm). + The main model. This tells Payu which driver to use (access stands for ACCESS-ESM).
      • Submodels @@ -222,14 +222,14 @@ This file controls the general model configuration and if we open it in a text e
        runspersub: 5
        ACCESS-ESM configurations are often run in multiple steps (or cycles), with Payu running runspersub internal runs for every PBS submission, and resubmitting the job until the total run length is met.
        - Note: If we increase runspersub, we might need to increate the walltime in the PBS resources. + Note: If we increase runspersub, we might need to increase the walltime in the PBS resources.
      -To know more about other configuration settings for the config.yaml file, please check Payu configuration settings documentation. +To know more about other configuration settings for the config.yaml file, please check how to configure your experiment with Payu. ---------------------------------------------------------------------------------------- -##
      Run ACCESS-ESM configuration
      +## Run ACCESS-ESM configuration
      ACCESS-ESM suites run on Gadi through a PBS job submission managed by Payu.
      @@ -239,12 +239,12 @@ Cylc (pronounced ‘silk’), is a workflow manager that automatically executes
      ---------------------------------------------------------------------------------------- -##
      Monitoring runs
      +## Monitoring runs
      ---------------------------------------------------------------------------------------- -##
      Model outputs
      +## Model outputs
      From 2c32abc70b0cf653194866b2c42efaf921c7280d Mon Sep 17 00:00:00 2001 From: atteggiani Date: Wed, 5 Jul 2023 19:16:57 +1000 Subject: [PATCH 4/7] Added how to run --- docs/css/access-nri.css | 3 +- .../running-a-model/running-access-esm.md | 136 ++++++++++++++++-- 2 files changed, 126 insertions(+), 13 deletions(-) diff --git a/docs/css/access-nri.css b/docs/css/access-nri.css index 273431c13..cc72f113f 100644 --- a/docs/css/access-nri.css +++ b/docs/css/access-nri.css @@ -412,7 +412,7 @@ ACCESS gold */ text-align: justify; } -/* Show different markers for different hieratchy of points (up to 3d hierarchy) */ +/* Show different markers for different hierarchy of points (up to 3d hierarchy) */ ul:not([class^='md-']) li { list-style-type: disc; } @@ -435,7 +435,6 @@ pre:has(code) { } pre>code { - display: block !important; white-space: pre-line !important; padding: 0.5em 0.8em !important; word-break: break-all !important; diff --git a/docs/models/running-a-model/running-access-esm.md b/docs/models/running-a-model/running-access-esm.md index 907a60383..556714fba 100644 --- a/docs/models/running-a-model/running-access-esm.md +++ b/docs/models/running-a-model/running-access-esm.md @@ -19,8 +19,15 @@ hide:
    • Edit the Master Configuration file
-
  • Run ACCESS-ESM configuration
  • -
  • Monitoring runs
  • +
  • Run ACCESS-ESM configuration +
      +
    1. Payu setup (optional)
    2. +
    3. Run configuration
    4. +
    5. Run configuration for multiple years
    6. +
    7. Understand runtime, runspersub, and -n parameters
    8. +
    +
  • +
  • Monitor runs
  • Model outputs
  • @@ -179,9 +186,9 @@ This file controls the general model configuration and if we open it in a text e     input:       - /g/data/access/payu/access-esm/input/pre-industrial/coupler - access (i.e. ACCESS-ESM) is a coupled model, which means it has multiple submodels (i.e. model components). + ACCESS-ESM is a coupled model, which means it has multiple submodels (i.e. model components).
    - In this section, some of the parameters of the configurations of all ACCESS-ESM's submodels are specified. The full configuration of a specific submodel can be found in the subdirectory of the laboratory having the name of the submodel (e.g. the configuration for the atmosphere submodel, i.e. the UM, will be in the directory ) + In this section, some of the parameters of the configurations of all ACCESS-ESM's submodels are specified. The full configuration of a specific submodel can be found in the subdirectory of the laboratory having the name of the submodel (e.g. in our case the configuration for the atmosphere submodel, i.e. the UM, will be in the directory ~/access-esm/esm-pre-industrial/atmosphere).
  • collate @@ -214,13 +221,13 @@ This file controls the general model configuration and if we open it in a text e This section specifies the start date and internal run length.
    - Note: The internal run length (controlled by runtime) can be different from the total run length. Also, the runtime value can be lowered, but should not be increased to a total of more than 1 year, to avoid errors. If you want to know more about the difference between internal run and total run lenghts, or if you want to run the model for more than 1 year, check Run ACCESS-ESM configuration. + Note: The internal run length (controlled by runtime) can be different from the total run length. Also, the runtime value can be lowered, but should not be increased to a total of more than 1 year, to avoid errors. If you want to know more about the difference between internal run and total run lenghts, or if you want to run the model for more than 1 year, check Run configuration for multiple years.
  • Number of runs per PBS submission
    runspersub: 5
    - ACCESS-ESM configurations are often run in multiple steps (or cycles), with Payu running runspersub internal runs for every PBS submission, and resubmitting the job until the total run length is met. + ACCESS-ESM configurations are often run in multiple steps (or cycles), with Payu running a maximum of runspersub internal runs for every PBS job submission.
    Note: If we increase runspersub, we might need to increase the walltime in the PBS resources.
  • @@ -230,17 +237,124 @@ To know more about other configuration settings for the config.yaml ---------------------------------------------------------------------------------------- ## Run ACCESS-ESM configuration -
    +After editing the configuration, we are ready to run ACCESS-ESM. +
    ACCESS-ESM suites run on Gadi through a PBS job submission managed by Payu. + +### Payu setup (optional) +
    +As a first step, from the control directory, is good practice to run: +
    payu setup
    +This will prepare the model run, based on the experiment configuration. + + payu setup + laboratory path: /scratch/$PROJECT/$USER/access-esm + binary path: /scratch/$PROJECT/$USER/access-esm/bin + input path: /scratch/$PROJECT/$USER/access-esm/input + work path: /scratch/$PROJECT/$USER/access-esm/work + archive path: /scratch/$PROJECT/$USER/access-esm/archive + Loading input manifest: manifests/input.yaml + Loading restart manifest: manifests/restart.yaml + Loading exe manifest: manifests/exe.yaml + Setting up atmosphere + Setting up ocean + Setting up ice + Setting up coupler + Checking exe and input manifests + Updating full hashes for 3 files in manifests/exe.yaml + Creating restart manifest + Updating full hashes for 30 files in manifests/restart.yaml + Writing manifests/restart.yaml + Writing manifests/exe.yaml + +Note: You can skip this step as it is included also in the run command. However, runnning it explicitly helps to check for errors. +
    + +### Run configuration +
    +To run ACCESS-ESM configuration for one internal run length (controlled by runtime in the config.yaml file), run: +
    payu run
    +This will submit a single job to the queue with a total run length of runtime. It there is no previous run, it will start from the start date indicated in the config.yaml file, otherwise it will perform a warm restart from a precedently saved restart file. + + payu run + Loading input manifest: manifests/input.yaml + Loading restart manifest: manifests/restart.yaml + Loading exe manifest: manifests/exe.yaml + payu: Found modules in /opt/Modules/v4.3.0 + qsub -q normal -P <project> -l walltime=11400 -l ncpus=384 -l mem=1536GB -N pre-industrial -l wd -j n -v PAYU_PATH=/g/data/hh5/public/apps/miniconda3/envs/analysis3-23.01/bin,MODULESHOME=/opt/Modules/v4.3.0,MODULES_CMD=/opt/Modules/v4.3.0/libexec/modulecmd.tcl,MODULEPATH=/g/data3/hh5/public/modules:/etc/scl/modulefiles:/opt/Modules/modulefiles:/opt/Modules/v4.3.0/modulefiles:/apps/Modules/modulefiles -W umask=027 -l storage=gdata/access+gdata/hh5 -- /g/data/hh5/public/apps/miniconda3/envs/analysis3-23.01/bin/python3.9 /g/data/hh5/public/apps/miniconda3/envs/analysis3-23.01/bin/payu-run + <job-ID>.gadi-pbs + +
    + +### Run configuration for multiple years +
    +If you want to run ACCESS-ESM configuration for multiple internal run lengths (controlled by runtime in the config.yaml file), you can use the option -n: +
    payu run -n <number-of-runs>
    +This will submit a job to the queue (or multiple jobs, depending on the runspersub value specified in the config.yaml file), with a total run length of runtime * number-of-runs. +
    + +### Understand runtime, runspersub, and -n parameters +
    +With the correct use of runtime, runspersub, and -n parameters, we can have full control of our run.
    -When the suite gets run, the suite configuration files are copied on Gadi under /scratch/<$PROJECT>/$USER/cylc-run/, and a symbolic link to this folder is also created in the $USER's home directory under ~/cylc-run/. -An ACCESS-CM2 suite is constituted by several tasks (such as checking out code repositories, compiling and building the different model components, running the model, etc.). The workflow of these tasks is controlled by Cylc. -Cylc (pronounced ‘silk’), is a workflow manager that automatically executes tasks according to the model main cycle script suite.rc. Cylc deals with how the job will be run and manages the time steps of each sub-model, as well as monitoring all the tasks and reporting any error that might occur. +
      +
    • + runtime defines the internal run length. +
    • +
    • + runspersub defines the maximum number of internal runs for every PBS job submission. +
    • +
    • + -n sets the number of internal runs to be performed. +
    • +
    +Let's have some practical examples: +
      +
    • + Run 20 years of simulation, with resubmission every 5 years +
      + To have a total run length of 20 years, with a resubmition cycle of 5 years, we can leave runtime to the default value of 1 year, set runspersub to 5, and run the configuration using -n 20: +
      payu run -n 20
      + This will submit subsequent jobs for the following years: 1 to 5, 6 to 10, 11 to 15, and 16 to 20. With a total of 4 PBS jobs. +
    • +
    • + Run 7 years of simulation, with resubmission every 3 years +
      + To have a total run length of 7 years, with a resubmition cycle of 3 years, we can leave runtime to the default value of 1 year, set runspersub to 3, and run the configuration using -n 7: +
      payu run -n 7
      + This will submit subsequent jobs for the following years: 1 to 3, 4 to 6, and 7. With a total of 3 PBS jobs. +
    • +
    • + Run 3 months and 10 days of simulation, in one single submission +
      + To have a total run length of 3 months and 10 days, all in a single submission, we have to set runtime to: +
      years: 0
      +            months: 3
      +            days: 10
      +        
      + set runspersub to 1 (or any value > 1), and run the configuration wihtout -n (or with -n equals 1): +
      payu run
      +
    • +
    • + Run 1 year and 4 months of simulation, with resubmission every 4 months +
      + To have a total run length of 1 year and 4 months (16 months), we will have to split it into multiple internal runs. For example, we can have 4 internal runs of 4 months each. Therefore, we will have to set runtime to: +
      years: 0
      +            months: 4
      +            days: 0
      +        
      + Since the internal run length is set to 4 months, to resubmit our jobs every 4 months (i.e. every internal run), we have to set runspersub to 1. Finally, we will perform 4 internal runs by running the configuration with -n 4: +
      payu run -n 4
      +
    • +
    ---------------------------------------------------------------------------------------- -## Monitoring runs +## Monitor runs
    +Currently, there is no specific tool to monitor ACCESS-ESM runs. +
    +One way to check
    ---------------------------------------------------------------------------------------- From 2bb42dd6964eaacbe2a733deec5bb985942fb254 Mon Sep 17 00:00:00 2001 From: atteggiani Date: Fri, 7 Jul 2023 11:38:33 +1000 Subject: [PATCH 5/7] Ripristinated toc and hid custom summary; Made borders 1px and same color as top tab --- docs/css/access-nri.css | 50 ++++++-- docs/css/termynal.css | 114 ------------------ .../running-a-model/running-access-esm.md | 39 ++++-- mkdocs.yml | 7 +- overrides/partials/toc.html | 3 +- 5 files changed, 78 insertions(+), 135 deletions(-) delete mode 100644 docs/css/termynal.css diff --git a/docs/css/access-nri.css b/docs/css/access-nri.css index 6afa60c4d..ae3cfd451 100644 --- a/docs/css/access-nri.css +++ b/docs/css/access-nri.css @@ -55,6 +55,7 @@ --md-typeset-kbd-accent-color: rgb(126, 126, 126, .16); /* keyboard key inner border ( tag) */ --md-typeset-kbd-border-color: rgb(30, 30, 30); /* text as keyboard outer border ( tag) */ --navigation-borders: var(--md-default-fg-color--lighter); /* Left border on the toc and navigation, border of cards */ + --navigation-borders: var(--md-primary-fg-color--dark); /* Left border on the toc and navigation, border of cards */ --md-typeset-table-color: var(--navigation-borders); /* table borders ( tag) */ --md-admonition-fg-color: var(--md-typeset-color); /* Main text warnings */ --md-admonition-bg-color: var(--md-default-bg-color); /* Background warnings */ @@ -70,7 +71,10 @@ --card-shadows: #00000075; /* Shadows on cards and other elements */ --card-shadows-hover: #00000090; /* Shadows hover on cards and other elements */ --img-background: #FFFFFF; /* Background for transparent images */ - --shadow-hover-background: rgba(29, 28, 28, 0.185) /* Shadow Background on hover */ + --shadow-hover-background: rgba(29, 28, 28, 0.185); /* Shadow Background on hover */ + --terminal-animation-directory: var(--nri-green); + --terminal-animation-buttons: var(--nri-orange); + --terminal-animation-buttons-hover: var(--nri-dark-blue); } [data-md-color-scheme="custom-light"] { @@ -100,7 +104,7 @@ --md-accent-bg-color: var(--nri-orange); /* back to top button text hover */ --md-accent-bg-color--light: #115D97B0; --md-code-fg-color: rgb(33, 36, 44); /* code element text */ - --md-code-bg-color: #c3c3c3; /* code element background */ + --md-code-bg-color: #dedede; /* code element background */ --md-code-hl-color: rgba(255,255,0,.5); --md-code-hl-number-color: #d52a2a; --md-code-hl-special-color: #db1457; @@ -122,7 +126,7 @@ --md-typeset-kbd-color: rgb(226, 226, 226); /* keyboard key background ( tag) */ --md-typeset-kbd-accent-color: rgb(255, 255, 255, .78); /* keyboard key inner border ( tag) */ --md-typeset-kbd-border-color: rgb(212, 212, 212); /* text as keyboard outer border ( tag) */ - --navigation-borders: var(--md-default-fg-color--lighter); /* Left border on the toc and navigation, border of cards */ + --navigation-borders: var(--md-primary-fg-color--dark); /* Left border on the toc and navigation, border of cards */ --md-typeset-table-color: var(--navigation-borders); /* table borders (
    tag) */ --md-admonition-fg-color: var(--md-typeset-color); /* Main text warnings */ --md-admonition-bg-color: var(--md-default-bg-color); /* Background warnings */ @@ -138,7 +142,10 @@ --card-shadows: #00000075; /* Shadows on cards and other elements */ --card-shadows-hover: #00000090; /* Shadows hover on cards and other elements */ --img-background: #FFFFFF; /* Background for transparent images */ - --shadow-hover-background: rgba(29, 28, 28, 0.185) /* Shadow Background on hover */ + --shadow-hover-background: rgba(29, 28, 28, 0.185); /* Shadow Background on hover */ + --terminal-animation-directory: var(--nri-blue); + --terminal-animation-buttons: var(--nri-dark-blue); + --terminal-animation-buttons-hover: var(--nri-orange); } @@ -385,7 +392,7 @@ h3 { display: flex; justify-content: center; align-items: center; - border: 2px solid var(--navigation-borders); + border: 1px solid var(--navigation-borders); border-radius: 15px; box-shadow: 6px 6px 10px var(--card-shadows); } @@ -560,6 +567,34 @@ pre>code { word-break: break-all !important; } +/* =============================================================== + Terminal animations +*/ +::part(terminal-container) { + background-color: var(--md-code-bg-color); + color: var(--md-code-fg-color); + font-family: var(--md-code-font-family); + font-weight: unset; +} + +::part(input-character) { + color: var(--terminal-animation-buttons); +} + +::part(directory) { + color: var(--terminal-animation-directory); +} + +::part(fast-button), ::part(restart-button) { + color: var(--terminal-animation-buttons); + font-weight: 700; +} + +::part(fast-button):hover, ::part(restart-button):hover { + color: var(--terminal-animation-buttons-hover); +} + + /* =============================================================== Miscellaneous */ @@ -592,7 +627,8 @@ pre>code { /* With borders */ .with-border { border-radius: 7px; - border: 2px solid var(--navigation-borders); + /* border: 2px solid var(--navigation-borders); */ + border: 1px solid var(--navigation-borders); box-sizing: border-box; } @@ -603,4 +639,4 @@ pre>code { .bold { font-weight: 600 !important; -} +} \ No newline at end of file diff --git a/docs/css/termynal.css b/docs/css/termynal.css deleted file mode 100644 index a11274415..000000000 --- a/docs/css/termynal.css +++ /dev/null @@ -1,114 +0,0 @@ -/** - * termynal.js - * - * @author Ines Montani - * @version 0.0.1 - * @license MIT - */ - - -:root { - --color-bg: #252a33; - --color-text: #eee; - --color-text-subtle: #a2a2a2; - --color-text-directory: var(--nri-green); /* Colour taken from ACCESS-NRI website */ - --color-text-symlink: var(--nri-blue); /* Colour taken from ACCESS-NRI website */ - --color-text-dollar-sign: var(--nri-orange); /* Colour taken from ACCESS-NRI website */ - --color-control-buttons: #115D97; -} - -.termynal { - /* width: 750px; */ - max-width: 100%; - background: var(--color-bg); - color: var(--color-text); - display: flex; - flex-direction: column; - justify-content: flex-start; - font-size: 13px; - font-family: 'Roboto Mono', 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace; - font-weight: bold; - border-radius: 4px; - padding: 35px 25px 25px; - position: relative; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} - -.termynal::before { - content: ''; - position: absolute; - top: 15px; - left: 15px; - display: inline-block; - width: 15px; - height: 15px; - border-radius: 50%; - /* A little hack to display the window buttons in one pseudo element. */ - background: #d9515d; - -webkit-box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; - box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; -} - -[data-ty] { - line-height: 2; - justify-self: center; -} - -[data-ty]::before { - /* Set up defaults and ensure empty lines are displayed. */ - content: ''; - display: inline-block; -} - -[data-ty][prompt]::before { - content: attr(prompt); - color: var(--color-text-subtle); -} - -[data-ty="input"][directory]::before { - content: attr(directory); - color: var(--color-text-directory); -} - -[cursor]::after { - content: attr(cursor); - font-family: monospace; - -webkit-animation: blink 1s infinite; - animation: blink 1s infinite; -} - -a[termynal-control-buttons] { - align-self: flex-end; - color: var(--color-control-buttons); -} - -.directory-text { - color: var(--color-text-directory); -} - -.symlink-text { - color: var(--color-text-symlink); -} - -.double-spaced { - word-spacing: 1em; -} - -[charBeforeInput] { - color: var(--color-text-dollar-sign); -} - -/* Cursor animation */ - -@-webkit-keyframes blink { - 50% { - opacity: 0; - } -} - -@keyframes blink { - 50% { - opacity: 0; - } -} diff --git a/docs/models/running-a-model/running-access-esm.md b/docs/models/running-a-model/running-access-esm.md index 556714fba..e7852225a 100644 --- a/docs/models/running-a-model/running-access-esm.md +++ b/docs/models/running-a-model/running-access-esm.md @@ -1,7 +1,4 @@ ---- -hide: - - toc ---- + ## Requirements
    @@ -354,7 +355,31 @@ Let's have some practical examples:
    Currently, there is no specific tool to monitor ACCESS-ESM runs.
    -One way to check +One way to check the status of our run is running: +
    qstat -u $USER
    +This will show the status of all your PBS jobs (if there is any PBS job submitted): + + qstat -u $USER + Job id                Name             User             Time Use S Queue + --------------------- ---------------- ---------------- -------- - ----- + <job-ID>.gadi-pbs     pre-industrial   <$USER>            <time> R normal-exec + <job-ID>.gadi-pbs     <other-job-name> <$USER>            <time> R normal-exec + <job-ID>.gadi-pbs     <other-job-name> <$USER>            <time> R normal-exec + +If you changed the jobname in the PBS resources of the Master Configuration file, that will be your job's Name instead of pre-industrial. +
    +S indicates the status of your run: +
      +
    • Q → Job waiting in the queue to start
    • +
    • R → Job running
    • +
    • E → Job ending
    • +
    +If no listed job has your jobname (or if there is no job submitted at all), your run might have successfully completed, or might have been terminated due to an error. +
    + +### Check the output and error log files +
    +
    ---------------------------------------------------------------------------------------- diff --git a/mkdocs.yml b/mkdocs.yml index 95ef384bb..59655644d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -41,11 +41,6 @@ theme: - search.share - toc.follow # the sidebar is automatically scrolled to the active anchor - # - navigation.expand - # - navigation.path - # - toc.integrate - # - navigation.sections - logo: assets/ACCESS_icon_HIVE.png favicon: assets/ACCESS_icon_HIVE.png icon: @@ -81,6 +76,8 @@ markdown_extensions: - footnotes - tables - pymdownx.keys + - toc: + title: On this page # Navigation nav: diff --git a/overrides/partials/toc.html b/overrides/partials/toc.html index 524a211d0..45f92e04e 100644 --- a/overrides/partials/toc.html +++ b/overrides/partials/toc.html @@ -1,8 +1,7 @@ {#- This file was automatically generated - do not edit -#} - - {% set title = "On this page" %} + {% set title = lang.t("toc") %} {% if config.mdx_configs.toc and config.mdx_configs.toc.title %} {% set title = config.mdx_configs.toc.title %} {% endif %} From 83e51734badecdfd97da62f53370a8229366bed7 Mon Sep 17 00:00:00 2001 From: atteggiani Date: Fri, 7 Jul 2023 17:07:40 +1000 Subject: [PATCH 6/7] Completed output + fixed with Aidan's comments --- docs/css/access-nri.css | 26 ++++-- .../access_to_gadi_at_nci.md | 2 +- .../getting_started/access_to_gadi_at_nci.md | 0 .../getting_started/index.md | 0 .../{running-a-model => run-a-model}/index.md | 0 .../run-access-am.md} | 0 .../run-access-cm.md} | 0 .../run-access-esm.md} | 79 +++++++++++-------- .../run-access-om.md} | 0 .../running-a-model/running-access-s.md | 0 mkdocs.yml | 37 +++------ 11 files changed, 76 insertions(+), 68 deletions(-) rename docs/models/{running-a-model => run-a-model}/getting_started/access_to_gadi_at_nci.md (100%) rename docs/models/{running-a-model => run-a-model}/getting_started/index.md (100%) rename docs/models/{running-a-model => run-a-model}/index.md (100%) rename docs/models/{running-a-model/running-access-am.md => run-a-model/run-access-am.md} (100%) rename docs/models/{running-a-model/running-access-cm.md => run-a-model/run-access-cm.md} (100%) rename docs/models/{running-a-model/running-access-esm.md => run-a-model/run-access-esm.md} (76%) rename docs/models/{running-a-model/running-access-om.md => run-a-model/run-access-om.md} (100%) delete mode 100644 docs/models/running-a-model/running-access-s.md diff --git a/docs/css/access-nri.css b/docs/css/access-nri.css index ae3cfd451..1d219b6bf 100644 --- a/docs/css/access-nri.css +++ b/docs/css/access-nri.css @@ -54,9 +54,9 @@ --md-typeset-kbd-color: rgb(39, 39, 39); /* keyboard key background ( tag) */ --md-typeset-kbd-accent-color: rgb(126, 126, 126, .16); /* keyboard key inner border ( tag) */ --md-typeset-kbd-border-color: rgb(30, 30, 30); /* text as keyboard outer border ( tag) */ - --navigation-borders: var(--md-default-fg-color--lighter); /* Left border on the toc and navigation, border of cards */ - --navigation-borders: var(--md-primary-fg-color--dark); /* Left border on the toc and navigation, border of cards */ - --md-typeset-table-color: var(--navigation-borders); /* table borders (
    tag) */ + --navigation-borders: #115D9750; /* Left border on the toc and navigation */ + --card-borders: var(--md-primary-fg-color--dark); /* Borders of cards */ + --md-typeset-table-color: var(--card-borders); /* table borders (
    tag) */ --md-admonition-fg-color: var(--md-typeset-color); /* Main text warnings */ --md-admonition-bg-color: var(--md-default-bg-color); /* Background warnings */ --md-footer-fg-color: var(--md-primary-bg-color); /* footer text (not much used) */ @@ -75,6 +75,7 @@ --terminal-animation-directory: var(--nri-green); --terminal-animation-buttons: var(--nri-orange); --terminal-animation-buttons-hover: var(--nri-dark-blue); + } [data-md-color-scheme="custom-light"] { @@ -126,8 +127,9 @@ --md-typeset-kbd-color: rgb(226, 226, 226); /* keyboard key background ( tag) */ --md-typeset-kbd-accent-color: rgb(255, 255, 255, .78); /* keyboard key inner border ( tag) */ --md-typeset-kbd-border-color: rgb(212, 212, 212); /* text as keyboard outer border ( tag) */ - --navigation-borders: var(--md-primary-fg-color--dark); /* Left border on the toc and navigation, border of cards */ - --md-typeset-table-color: var(--navigation-borders); /* table borders (
    tag) */ + --navigation-borders: #FAA61950; /* Left border on the toc and navigation */ + --card-borders: var(--md-primary-fg-color--dark); /* Borders of cards */ + --md-typeset-table-color: var(--card-borders); /* table borders (
    tag) */ --md-admonition-fg-color: var(--md-typeset-color); /* Main text warnings */ --md-admonition-bg-color: var(--md-default-bg-color); /* Background warnings */ --md-footer-fg-color: var(--md-primary-bg-color); /* footer text (not much used) */ @@ -157,6 +159,10 @@ h1 { font-weight: 600 !important; } +h2 { + font-weight: 500 !important; +} + h3 { margin: 1em 0 0.4em !important; } @@ -392,7 +398,7 @@ h3 { display: flex; justify-content: center; align-items: center; - border: 1px solid var(--navigation-borders); + border: 1px solid var(--card-borders); border-radius: 15px; box-shadow: 6px 6px 10px var(--card-shadows); } @@ -594,6 +600,11 @@ pre>code { color: var(--terminal-animation-buttons-hover); } +/* Try to format like the output of `ls` command */ +.ls-output-format { + word-spacing: 2em; + word-break: normal; +} /* =============================================================== Miscellaneous @@ -627,8 +638,7 @@ pre>code { /* With borders */ .with-border { border-radius: 7px; - /* border: 2px solid var(--navigation-borders); */ - border: 1px solid var(--navigation-borders); + border: 1px solid var(--card-borders); box-sizing: border-box; } diff --git a/docs/model_evaluation/model_evaluation_getting_started/access_to_gadi_at_nci.md b/docs/model_evaluation/model_evaluation_getting_started/access_to_gadi_at_nci.md index 3832a8d1b..c123b346d 120000 --- a/docs/model_evaluation/model_evaluation_getting_started/access_to_gadi_at_nci.md +++ b/docs/model_evaluation/model_evaluation_getting_started/access_to_gadi_at_nci.md @@ -1 +1 @@ -../../models/running-a-model/getting_started/access_to_gadi_at_nci.md \ No newline at end of file +/Users/davide/access-nri/access-hive.github.io/docs/models/run-a-model/getting_started/access_to_gadi_at_nci.md \ No newline at end of file diff --git a/docs/models/running-a-model/getting_started/access_to_gadi_at_nci.md b/docs/models/run-a-model/getting_started/access_to_gadi_at_nci.md similarity index 100% rename from docs/models/running-a-model/getting_started/access_to_gadi_at_nci.md rename to docs/models/run-a-model/getting_started/access_to_gadi_at_nci.md diff --git a/docs/models/running-a-model/getting_started/index.md b/docs/models/run-a-model/getting_started/index.md similarity index 100% rename from docs/models/running-a-model/getting_started/index.md rename to docs/models/run-a-model/getting_started/index.md diff --git a/docs/models/running-a-model/index.md b/docs/models/run-a-model/index.md similarity index 100% rename from docs/models/running-a-model/index.md rename to docs/models/run-a-model/index.md diff --git a/docs/models/running-a-model/running-access-am.md b/docs/models/run-a-model/run-access-am.md similarity index 100% rename from docs/models/running-a-model/running-access-am.md rename to docs/models/run-a-model/run-access-am.md diff --git a/docs/models/running-a-model/running-access-cm.md b/docs/models/run-a-model/run-access-cm.md similarity index 100% rename from docs/models/running-a-model/running-access-cm.md rename to docs/models/run-a-model/run-access-cm.md diff --git a/docs/models/running-a-model/running-access-esm.md b/docs/models/run-a-model/run-access-esm.md similarity index 76% rename from docs/models/running-a-model/running-access-esm.md rename to docs/models/run-a-model/run-access-esm.md index e7852225a..d012ce066 100644 --- a/docs/models/running-a-model/running-access-esm.md +++ b/docs/models/run-a-model/run-access-esm.md @@ -1,6 +1,6 @@ -