diff --git a/.gitignore b/.gitignore index cb98282bfb904d03ac706cc8740ee1ad922c8851..9666458274aaceba1d7d4b2f914ec0ca2459d738 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ GTAGS /doc/lisp/.fltk/ /doc/*.msh /doc/*.vtu +/doc/checkpoint.h5 diff --git a/cmake/PugsDoc.cmake b/cmake/PugsDoc.cmake index 7718046e21b5de20bc5f4a6aeb5c451ca9757890..318e694b2a883ff77bd638b9faf30ccc2e99e65b 100644 --- a/cmake/PugsDoc.cmake +++ b/cmake/PugsDoc.cmake @@ -37,6 +37,7 @@ if (EMACS AND GNUPLOT_FOUND AND GMSH) COMMAND ${CMAKE_COMMAND} -E env PUGS=${PUGS_BINARY_DIR}/pugs + PUGS_CHECKPOINT=${PUGS_BINARY_DIR}/pugs_checkpoint HOME=${PUGS_SOURCE_DIR}/doc/lisp PUGS_SOURCE_DIR=${PUGS_SOURCE_DIR} PUGS_BINARY_DIR=${PUGS_BINARY_DIR} @@ -51,6 +52,7 @@ if (EMACS AND GNUPLOT_FOUND AND GMSH) COMMAND ${CMAKE_COMMAND} -E env PUGS=${PUGS_BINARY_DIR}/pugs + PUGS_CHECKPOINT=${PUGS_BINARY_DIR}/pugs_checkpoint HOME=${PUGS_SOURCE_DIR}/doc/lisp PUGS_SOURCE_DIR=${PUGS_SOURCE_DIR} PUGS_BINARY_DIR=${PUGS_BINARY_DIR} @@ -59,6 +61,7 @@ if (EMACS AND GNUPLOT_FOUND AND GMSH) "${PUGS_SOURCE_DIR}/doc/userdoc.org" "${PUGS_SOURCE_DIR}/doc/lisp/userdoc-html.el" pugs + pugs_checkpoint pugsdoc-dir pugsdoc-download-elpa ${ORG_GENERATOR_FILES} @@ -77,6 +80,7 @@ if (EMACS AND GNUPLOT_FOUND AND GMSH) COMMAND ${CMAKE_COMMAND} -E env PUGS=${PUGS_BINARY_DIR}/pugs + PUGS_CHECKPOINT=${PUGS_BINARY_DIR}/pugs_checkpoint HOME=${PUGS_SOURCE_DIR}/doc/lisp PUGS_SOURCE_DIR=${PUGS_SOURCE_DIR} PUGS_BINARY_DIR=${PUGS_BINARY_DIR} @@ -87,6 +91,7 @@ if (EMACS AND GNUPLOT_FOUND AND GMSH) "${PUGS_SOURCE_DIR}/tools/pgs-pygments.sh" "${PUGS_SOURCE_DIR}/tools/pgs-pygments.py" pugs + pugs_checkpoint pugsdoc-dir pugsdoc-download-elpa ${ORG_GENERATOR_FILES} diff --git a/doc/lisp/build-doc-config.el b/doc/lisp/build-doc-config.el index 6f06400a6dc1176370550342ea7bfb04ac976c11..ee9826245dcf4ed0671070eb9d6b172ba7b34369 100644 --- a/doc/lisp/build-doc-config.el +++ b/doc/lisp/build-doc-config.el @@ -51,7 +51,7 @@ '(org-latex-listings 'minted)) (setq org-latex-minted-options - '(("linenos=true") ("breaklines"))) + '(("linenos=true") ("breaklines") ("autogobble"))) (defun org-export-output-file-name-modified (orig-fun extension &optional subtreep pub-dir) (unless pub-dir diff --git a/doc/userdoc.org b/doc/userdoc.org index e9ba680359c371e480f525378931928127c1177d..8901f2d93968259a3f8b8dc3b718d35264673b2c 100644 --- a/doc/userdoc.org +++ b/doc/userdoc.org @@ -32,6 +32,12 @@ #+LATEX_HEADER_EXTRA: \usepackage{mathpazo} #+LATEX_HEADER_EXTRA: \usepackage{inconsolata} +#+LATEX_HEADER_EXTRA: %Patch accsupp to avoid copying line numbers when copying from listing +#+LATEX_HEADER_EXTRA: \usepackage{accsupp} +#+LATEX_HEADER_EXTRA: \newcommand\emptyaccsupp[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}} +#+LATEX_HEADER_EXTRA: \let\theHFancyVerbLine\theFancyVerbLine +#+LATEX_HEADER_EXTRA: \def\theFancyVerbLine{\rmfamily\tiny\emptyaccsupp{\arabic{FancyVerbLine}}} + #+LATEX_HEADER_EXTRA: \BeforeBeginEnvironment{tabular}{\rowcolors[]{2}{orange!5}{orange!10}} #+LATEX_HEADER_EXTRA: \BeforeBeginEnvironment{minted}{\begin{mdframed}[linecolor=blue,backgroundcolor=blue!10]} #+LATEX_HEADER_EXTRA: \AfterEndEnvironment{minted}{\end{mdframed}} @@ -2541,11 +2547,200 @@ to files for instance) as we will see below. **** ~core~ provided functions -***** ~exit: Z -> void~ +***** execution control functions + +Here are functions that allow to control the execution of the +script. These can stop the execution if some conditions are met or +create checkpoint that may be used to stop and then resume the +execution. + +****** ~exit: Z -> void~ This function interrupts the execution of the script. The integer (~Z~) value is the code that is returned when ~pugs~ exits. +#+NAME: exit-function +#+BEGIN_SRC pugs :exports both :results output + for (let i:N, i = 1; i < 10; ++i) { + cout << "i = " << i << "\n"; + if (i==3) { + exit(0); + } + } +#+END_SRC +The output shows that the execution is interrupted (in a clean way) if +the condition (here ~i == 3~) is met. +#+RESULTS: exit-function + +****** ~stop: void -> B~ + +This is an interactive function that is used to notify the code to +stop its execution. It returns ~true~ if one of the following stopping +condition is met. +- If a ~stop~ file is created *after* the beginning of the execution in + the *execution directory*. This file can be created using the ~touch~ + command for instance + #+BEGIN_SRC shell :exports source + touch stop + #+END_SRC +- If ~pugs~ was compiled using ~Slurm~ support (this can be checked using + the command ~./pugs -v~) then during batch execution the ~stop~ function + will also return ~true~ as soon as the remaining execution time is + less than $150s$. + +In the following example the function ~stop~ returns always ~false~ since +none of the above conditions are satisfied. +#+NAME: stop-function +#+BEGIN_SRC pugs :exports both :results output + for (let i:N, i = 1; i <= 5; ++i) { + cout << "i = " << i << "\n"; + if (stop()) { + exit(0); + } + } +#+END_SRC +The output shows that the execution reaches ~i == 5~. +#+RESULTS: stop-function + +****** ~checkpoint: void -> void~ + +This function creates a checkpoint that can be used as a starting +point for another execution. This function can be placed anywhere in +the script and possibly multiple times. The checkpoint storage file is +~checkpoint.h5~ and it is created in the current execution directory. + +*This functionality requires ~pugs~ to be compiled with ~HDF5~ support*. + +The following example creates two checkpoints. +#+NAME: checkpoint-function +#+BEGIN_SRC pugs :exports both :results output + let n:N, n = 4; + cout << "n = " << n << "\n"; + checkpoint(); + let x:R^3, x = [1, 2, 3]; + cout << "x = " << x << "\n"; + checkpoint(); +#+END_SRC +The output displays the creation of two checkpoints in the file ~checkpoint.h5~. +#+RESULTS: checkpoint-function +The command +#+BEGIN_SRC shell :exports code + pugs_checkpoint --info checkpoint.h5 +#+END_SRC +displays a simple execution state for each checkpoint stored in the +file in order to help user to choose the appropriate resuming +checkpoint. +#+NAME: checkpoint-info +#+BEGIN_SRC shell :exports results :results output + ${PUGS_CHECKPOINT} --no-color --info checkpoint.h5 +#+END_SRC +#+RESULTS: checkpoint-info +One can notice that the ~x~ variable does not appear in the first +checkpoint since it was not created at this point. Also two pointers +are defined: +- ~last_checkpoint~ that displays the more recent checkpoint, + and +- ~resuming_checkpoint~ that indicates which checkpoint will be used when + resuming. + +Proceeding with this example, one can change the resuming checkpoint +with the command +#+BEGIN_SRC shell :exports code + pugs_checkpoint --resume-from 0 checkpoint.h5 +#+END_SRC +which displays +#+NAME: checkpoint-resume-from +#+BEGIN_SRC shell :exports results :results output + ${PUGS_CHECKPOINT} --no-color --resume-from 0 checkpoint.h5 +#+END_SRC +#+RESULTS: checkpoint-resume-from +Running again +#+BEGIN_SRC shell :exports code + pugs_checkpoint --info checkpoint.h5 +#+END_SRC +now prints +#+NAME: checkpoint-info0 +#+BEGIN_SRC shell :exports results :results output + ${PUGS_CHECKPOINT} --no-color --info checkpoint.h5 +#+END_SRC +#+RESULTS: checkpoint-info0 +One notices that ~resuming_checkpoint~ now points to ~checkpoint_0~. + +It is now possible to resume the execution using the command +#+BEGIN_SRC shell :exports code + pugs --resume checkpoint.h5 +#+END_SRC +The output is now +#+NAME: checkpoint-resume0 +#+BEGIN_SRC shell :exports results :results output + ${PUGS} --no-exec-stat --no-preamble --no-color --threads=1 --resume checkpoint.h5 +#+END_SRC +#+RESULTS: checkpoint-resume0 +Observe that the random seed is reset to the value that was stored at +checkpoint 0. + +Also each checkpoint whose number is greater than the resuming +checkpoint (here 0) are removed when the next checkpoint (here 1) is +written. + +#+BEGIN_note +One may have noticed that the script file that is used for resuming is +actually stored in the ~checkpoint.h5~ file, the script is not a command +line argument. + +By now, it is not possible to *simply* modify the script while +resuming. This is done in purpose since it remains unclear if such a +dangerous functionality should be make easy. Indeed allowing +script modifications may lead to undefined behaviors. +#+END_note + +#+BEGIN_warning +The number of ~MPI~ ranks *cannot* be changed when resuming. + +This is not likely to change since it is a very specific +functionality. However, a post-processing tool rewriting checkpoints +may be developed to achieve it, but it is not a priority. +#+END_warning + +****** ~checkpoint_and_exit: void -> void~ + +This is an advanced version of the ~checkpoint~ function that cause a +clean ~exit~ of the code after writing a checkpoint. + +The use case for this function is batch execution and is generally +triggered by the ~stop~ function. + +We give here a simple example. +#+NAME: checkpoint-exit-function +#+BEGIN_SRC pugs :exports both :results output + for (let i:N, i = 1; i<=10; ++i) { + cout << "i = " << i << "\n"; + if (i==5) { + checkpoint_and_exit(); + } + } +#+END_SRC +The output is +#+RESULTS: checkpoint-exit-function + +Then one can resume the execution as previously by +#+BEGIN_SRC shell :exports code + pugs --resume checkpoint.h5 +#+END_SRC +It gives the output +The output is now +#+NAME: checkpoint-resume1 +#+BEGIN_SRC shell :exports results :results output + ${PUGS} --no-exec-stat --no-preamble --no-color --threads=1 --resume checkpoint.h5 +#+END_SRC +#+RESULTS: checkpoint-resume1 + +# Clean-up +#+BEGIN_SRC shell :exports results :results none + /bin/rm -f checkpoint.h5 +#+END_SRC + + ***** ~getAvailableModules: void -> string~ This function that is used in the preamble of this section is a