• Construct the lmod parameter list based on the name of the module file.

    From Hongyi Zhao@21:1/5 to All on Sun Feb 20 00:19:49 2022
    Currently, I'm using lmod [1] to dynamically change the users’ environment through module files of HPC related software packages.

    For ease of use lmod, I try to construct the lmod parameter list based on the name of the module file. For example, I've the following tcl based module file located on my MODULEPATH:

    vasp/6.3.0/intel_omp-compiler.2022.0.2-mkl.2022.0.2-mpi.2021.4.0

    The meaning of the full path shown above is explained below:

    vasp: The name of the package, in this case vasp [2].
    6.3.0: The version of the package, in this case 6.3.0.
    intel_omp: The name of the toolchain used to compile this package.

    compiler.2022.0.2-mkl.2022.0.2-mpi.2021.4.0: The components of the toolchain, each separated by a hyphen. In this case, there are three components:

    compiler.2022.0.2
    mkl.2022.0.2
    mpi.2021.4.0

    In each component shown above, its name is constructed by the following rules, taking compiler.2022.0.2 as an example:

    The part from the beginning to the first dot is the component name, in this case: compiler.
    The point immediately after the above part should be converted to a path separator, i.e., /.
    The rest corresponds to the component version, in this case: 2022.0.2.

    Finally, based on the above information, the following module command should be constructed and run from within this module file:

    module load compiler/2022.0.2 mkl/2022.0.2 mpi/2021.4.0

    Any hints for achieving this aim programmatically with tcl?

    Note: The number of components in the toolchain used to compile a package may vary, the only invariant rule is that each part of the components is separated with a hyphen, as represented above.

    [1] https://lmod.readthedocs.io
    [2] https://www.vasp.at/

    Regards,
    HZ

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From saitology9@gmail.com@21:1/5 to Hongyi Zhao on Sun Feb 20 16:38:44 2022
    On 2/20/22 3:19 AM, Hongyi Zhao wrote:

    Finally, based on the above information, the following module command should be constructed and run from within this module file:

    module load compiler/2022.0.2 mkl/2022.0.2 mpi/2021.4.0

    Any hints for achieving this aim programmatically with tcl?

    Note: The number of components in the toolchain used to compile a package may vary, the only invariant rule is that each part of the components is separated with a hyphen, as represented above.



    Hello,

    Not completely certain of what output you want but this piece of code
    should get you going:



    set mod_file
    "vasp/6.3.0/intel_omp-compiler.2022.0.2-mkl.2022.0.2-mpi.2021.4.0"


    set parts [split $mod_file /]
    if {[llength $parts] != 3} { puts "not a module file?"; exit }
    set p_name [lindex $parts 0]
    set p_vers [lindex $parts 1]
    set comp_info [lindex $parts 2]

    set comp_parts [list]
    foreach part [split $comp_info -] {
    set idx [string first . $part]
    if {$idx < 0} { continue }
    incr idx -1
    set compo_name [string range $part 0 $idx]
    incr idx +2
    set compo_vers [string range $part $idx end]

    lappend comp_parts "${compo_name}/${compo_vers}"
    }

    set final_cmd "module load [join $comp_parts { }]"

    puts "MODULE LOAD COMMAND: \n $final_cmd"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hongyi Zhao@21:1/5 to saito...@gmail.com on Sun Feb 20 21:02:40 2022
    On Monday, February 21, 2022 at 5:38:49 AM UTC+8, saito...@gmail.com wrote:
    On 2/20/22 3:19 AM, Hongyi Zhao wrote:

    Finally, based on the above information, the following module command should be constructed and run from within this module file:

    module load compiler/2022.0.2 mkl/2022.0.2 mpi/2021.4.0

    Any hints for achieving this aim programmatically with tcl?

    Note: The number of components in the toolchain used to compile a package may vary, the only invariant rule is that each part of the components is separated with a hyphen, as represented above.

    Hello,

    Not completely certain of what output you want but this piece of code
    should get you going:



    set mod_file "vasp/6.3.0/intel_omp-compiler.2022.0.2-mkl.2022.0.2-mpi.2021.4.0"


    set parts [split $mod_file /]
    if {[llength $parts] != 3} { puts "not a module file?"; exit }
    set p_name [lindex $parts 0]
    set p_vers [lindex $parts 1]
    set comp_info [lindex $parts 2]

    set comp_parts [list]
    foreach part [split $comp_info -] {
    set idx [string first . $part]
    if {$idx < 0} { continue }
    incr idx -1
    set compo_name [string range $part 0 $idx]
    incr idx +2
    set compo_vers [string range $part $idx end]

    lappend comp_parts "${compo_name}/${compo_vers}"
    }

    set final_cmd "module load [join $comp_parts { }]"

    puts "MODULE LOAD COMMAND: \n $final_cmd"

    Wonderful solution. It is ready to work if the following issue is resolved:

    In my case, the constructed `module load` command must be run as follows from within the module file itself:

    module load [lindex $comp_parts 0] [lindex $comp_parts 1] [lindex $comp_parts 2]

    The above command will be converted to the following lmod command before execution:

    load("compiler/2022.0.2","mkl/2022.0.2","mpi/2021.4.0")

    While your version "module load [join $comp_parts { }]" will be converted into the following one which doesn't work:

    load("compiler/2022.0.2 mkl/2022.0.2 mpi/2021.4.0")

    But I can't figure out how to traverse the list gracefully to generate the format required by lmod as represented above.

    According to your suggested code here, the full content of the module file is as follows:

    ``` #%Module######################################################################

    # Set variables #https://stackoverflow.com/questions/5511017/read-bash-environment-variable-in-tcl
    set HOME $env(HOME)
    set module_fullname [module-info name]

    set parts [split $module_fullname /]
    if {[llength $parts] != 3} { puts "not a module file?"; exit }
    set p_name [lindex $parts 0]
    set p_vers [lindex $parts 1]
    set comp_info [lindex $parts 2]

    set comp_parts [list]
    foreach part [split $comp_info -] {
    set idx [string first . $part]
    if {$idx < 0} { continue }
    incr idx -1
    set compo_name [string range $part 0 $idx]
    incr idx +2
    set compo_vers [string range $part $idx end]

    lappend comp_parts "${compo_name}/${compo_vers}"
    }

    # See Public/repo/github.com/TACC/Lmod.git.bash
    #$ cd /opt/intel/oneapi && sudo ./modulefiles-setup.sh
    #$ module use /opt/intel/oneapi/modulefiles
    #module --force purge
    module load [lindex $comp_parts 0] [lindex $comp_parts 1] [lindex $comp_parts 2]
    prepend-path PATH $HOME/Public/hpc/$p_name/$p_vers/bin/$comp_info

    module-whatis "$p_name $p_vers"

    # Help message
    proc ModulesHelp { } {
    set module_fullname [module-info name]
    puts stderr "\tLoads the $module_fullname environment."
    }
    ```
    Regards,
    HZ

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hongyi Zhao@21:1/5 to clt.to...@dfgh.net on Sun Feb 20 23:03:11 2022
    On Monday, February 21, 2022 at 2:41:02 PM UTC+8, clt.to...@dfgh.net wrote:
    In my case, the constructed `module load` command must be run as follows from within the module file itself:

    module load [lindex $comp_parts 0] [lindex $comp_parts 1] [lindex $comp_parts 2]

    The above command will be converted to the following lmod command before execution:

    load("compiler/2022.0.2","mkl/2022.0.2","mpi/2021.4.0")

    While your version "module load [join $comp_parts { }]" will be converted into the following one which doesn't work:

    load("compiler/2022.0.2 mkl/2022.0.2 mpi/2021.4.0")

    The problem appears to be the module list is seen as a single item on the command line
    You might try:

    module load {*}$comp_parts

    It should allow as many modules as are found.

    Thank you. It does the trick.

    If the TCL version is reasonably recent,

    My TCL version is shown below:

    ```
    werner@X10DAi-00:~$ tclsh <<< 'puts [info patchlevel]'
    8.6.10
    werner@X10DAi-00:~$ echo 'puts [info patchlevel];exit 0' | tclsh
    8.6.10
    ```

    another way to generate the comp_parts list is:

    lassign [split $str "/"] pkg pkg_ver other
    set comp_parts [lmap comp [lassign [split $other "-"] toolchain] {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }]

    pkg, pkg_ver and tool chain have values set as well.

    Thank you for your enhancement. Based on your suggestion above, I changed to the following code, and it works:

    ```
    set HOME $env(HOME)
    set module_fullname [module-info name]

    lassign [split $module_fullname "/"] pkg pkg_ver comp_info
    set comp_parts [lmap comp [lassign [split $comp_info "-"] toolchain] {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }]

    # See Public/repo/github.com/TACC/Lmod.git.bash
    #$ cd /opt/intel/oneapi && sudo ./modulefiles-setup.sh
    #$ module use /opt/intel/oneapi/modulefiles
    #module --force purge
    module load {*}$comp_parts
    prepend-path PATH $HOME/Public/hpc/$pkg/$pkg_ver/bin/$comp_info

    module-whatis "$pkg $pkg_ver"

    # Help message
    proc ModulesHelp { } {
    set module_fullname [module-info name]
    puts stderr "\tLoads the $module_fullname environment."
    }
    ```

    Regards,
    HZ

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From clt.to.davebr@dfgh.net@21:1/5 to All on Mon Feb 21 06:40:57 2022
    In my case, the constructed `module load` command must be run as follows from within the module file itself:

    module load [lindex $comp_parts 0] [lindex $comp_parts 1] [lindex $comp_parts 2]

    The above command will be converted to the following lmod command before execution:

    load("compiler/2022.0.2","mkl/2022.0.2","mpi/2021.4.0")

    While your version "module load [join $comp_parts { }]" will be converted into the following one which doesn't work:

    load("compiler/2022.0.2 mkl/2022.0.2 mpi/2021.4.0")


    The problem appears to be the module list is seen as a single item on the command line
    You might try:

    module load {*}$comp_parts

    It should allow as many modules as are found.

    If the TCL version is reasonably recent, another way to generate the comp_parts list is:

    lassign [split $str "/"] pkg pkg_ver other
    set comp_parts [lmap comp [lassign [split $other "-"] toolchain] {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }]

    pkg, pkg_ver and tool chain have values set as well.

    Dave B

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hongyi Zhao@21:1/5 to Hongyi Zhao on Sun Feb 20 23:44:08 2022
    On Monday, February 21, 2022 at 3:03:16 PM UTC+8, Hongyi Zhao wrote:
    On Monday, February 21, 2022 at 2:41:02 PM UTC+8, clt.to...@dfgh.net wrote:
    In my case, the constructed `module load` command must be run as follows from within the module file itself:

    module load [lindex $comp_parts 0] [lindex $comp_parts 1] [lindex $comp_parts 2]

    The above command will be converted to the following lmod command before execution:

    load("compiler/2022.0.2","mkl/2022.0.2","mpi/2021.4.0")

    While your version "module load [join $comp_parts { }]" will be converted into the following one which doesn't work:

    load("compiler/2022.0.2 mkl/2022.0.2 mpi/2021.4.0")

    The problem appears to be the module list is seen as a single item on the command line
    You might try:

    module load {*}$comp_parts

    It should allow as many modules as are found.
    Thank you. It does the trick.
    If the TCL version is reasonably recent,
    My TCL version is shown below:

    ```
    werner@X10DAi-00:~$ tclsh <<< 'puts [info patchlevel]'
    8.6.10
    werner@X10DAi-00:~$ echo 'puts [info patchlevel];exit 0' | tclsh
    8.6.10
    ```
    another way to generate the comp_parts list is:

    lassign [split $str "/"] pkg pkg_ver other
    set comp_parts [lmap comp [lassign [split $other "-"] toolchain] {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }]

    pkg, pkg_ver and tool chain have values set as well.
    Thank you for your enhancement. Based on your suggestion above, I changed to the following code, and it works:

    ```
    set HOME $env(HOME)
    set module_fullname [module-info name]
    lassign [split $module_fullname "/"] pkg pkg_ver comp_info
    set comp_parts [lmap comp [lassign [split $comp_info "-"] toolchain] {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }]

    Though it works, this part of your suggested code is rathere obsure to understand. Why the variable "toolchain" only appeared once in this method?

    # See Public/repo/github.com/TACC/Lmod.git.bash
    #$ cd /opt/intel/oneapi && sudo ./modulefiles-setup.sh
    #$ module use /opt/intel/oneapi/modulefiles
    #module --force purge
    module load {*}$comp_parts
    prepend-path PATH $HOME/Public/hpc/$pkg/$pkg_ver/bin/$comp_info

    module-whatis "$pkg $pkg_ver"
    # Help message
    proc ModulesHelp { } {
    set module_fullname [module-info name]
    puts stderr "\tLoads the $module_fullname environment."
    }
    ```

    Regards,
    HZ

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From clt.to.davebr@dfgh.net@21:1/5 to All on Mon Feb 21 16:24:35 2022
    set HOME $env(HOME)
    set module_fullname [module-info name]
    lassign [split $module_fullname "/"] pkg pkg_ver comp_info
    set comp_parts [lmap comp [lassign [split $comp_info "-"] toolchain] {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }]

    Though it works, this part of your suggested code is rathere obsure to understand. Why the variable "toolchain" only appeared once in this method?

    After splitting up the list of tool chain components (everything after the last "/")
    on "-", the first entry is the toolchain name. The command fragment:

    [lassign [...] toolchain]

    saves the first entry in the list in the toolchain variable,
    and returns the rest of the list for further processing

    If the tool chain name is not needed, this command fragment could be replaced with
    [lrange [...] 1 end]

    Dave B

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hongyi Zhao@21:1/5 to clt.to...@dfgh.net on Tue Feb 22 06:46:52 2022
    On Monday, February 21, 2022 at 2:41:02 PM UTC+8, clt.to...@dfgh.net wrote:
    In my case, the constructed `module load` command must be run as follows from within the module file itself:

    module load [lindex $comp_parts 0] [lindex $comp_parts 1] [lindex $comp_parts 2]

    The above command will be converted to the following lmod command before execution:

    load("compiler/2022.0.2","mkl/2022.0.2","mpi/2021.4.0")

    While your version "module load [join $comp_parts { }]" will be converted into the following one which doesn't work:

    load("compiler/2022.0.2 mkl/2022.0.2 mpi/2021.4.0")

    The problem appears to be the module list is seen as a single item on the command line
    You might try:

    module load {*}$comp_parts

    It should allow as many modules as are found.

    If the TCL version is reasonably recent, another way to generate the comp_parts list is:

    lassign [split $str "/"] pkg pkg_ver other
    set comp_parts [lmap comp [lassign [split $other "-"] toolchain] {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }]

    I copied and pasted your above code snippet into Komodo as follows:

    ```
    set str "vasp/6.3.0/intel_omp-compiler.2022.0.2-mkl.2022.0.2-mpi.2021.4.0"

    lassign [split $str "/"] pkg pkg_ver other
    set comp_parts [lmap comp [lassign [split $other "-"] toolchain]
    {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }
    ]
    ```
    But Komodo complains that the following line has syntax error:

    set comp_parts [lmap comp [lassign [split $other "-"] toolchain]

    The error is as follows:

    wrong # args

    I am a beginner of Tcl, and don't know how to fix it. Can you check again to see if there's a problem as reported by Komodo?

    HZ

    pkg, pkg_ver and tool chain have values set as well.

    Dave B

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From clt.to.davebr@dfgh.net@21:1/5 to All on Tue Feb 22 15:57:43 2022
    lassign [split $str "/"] pkg pkg_ver other
    set comp_parts [lmap comp [lassign [split $other "-"] toolchain] {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }]

    I copied and pasted your above code snippet into Komodo as follows:

    ```
    set str "vasp/6.3.0/intel_omp-compiler.2022.0.2-mkl.2022.0.2-mpi.2021.4.0"

    lassign [split $str "/"] pkg pkg_ver other
    set comp_parts [lmap comp [lassign [split $other "-"] toolchain]
    {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }
    ]
    ```
    But Komodo complains that the following line has syntax error:

    set comp_parts [lmap comp [lassign [split $other "-"] toolchain]

    The error is as follows:

    wrong # args


    There are changes in the copied code. Unless a line break is within "" or {} or is immediately (no extra white space) preceded by a "\" it ends a command. In this case the lmap command is expecting a block of code to execute once for each set of data in
    the list, which is now on the next line, and is not seen as part of the current command.

    set comp_parts [lmap comp [lassign [split $other "-"] toolchain] --------------------------- this line break is seen as an early end of the lmap command -----------------------
    {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }
    --------------------------- this line break will cause trouble for the lmap command too -------------------------
    ]


    There are several tutorials on the web, one is on the TCL wiki:

    https://wiki.tcl-lang.org/page/Tcl+Tutorial+Lesson+0

    There are books as well. I learned TCL about 20 years ago from "Practical Programming in Tcl and Tk". It is available on the web now. There are more recent books on TCL which cover all the latest changes in TCL and Tk.

    I suggest you start a new thread asking for tutorials or books.

    Dave B

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hongyi Zhao@21:1/5 to clt.to...@dfgh.net on Tue Feb 22 17:17:36 2022
    On Tuesday, February 22, 2022 at 11:57:48 PM UTC+8, clt.to...@dfgh.net wrote:
    lassign [split $str "/"] pkg pkg_ver other
    set comp_parts [lmap comp [lassign [split $other "-"] toolchain] {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }]

    I copied and pasted your above code snippet into Komodo as follows:

    ```
    set str "vasp/6.3.0/intel_omp-compiler.2022.0.2-mkl.2022.0.2-mpi.2021.4.0"

    lassign [split $str "/"] pkg pkg_ver other
    set comp_parts [lmap comp [lassign [split $other "-"] toolchain]
    {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }
    ]
    ```
    But Komodo complains that the following line has syntax error:

    set comp_parts [lmap comp [lassign [split $other "-"] toolchain]

    The error is as follows:

    wrong # args

    There are changes in the copied code. Unless a line break is within "" or {} or is immediately (no extra white space) preceded by a "\" it ends a command. In this case the lmap command is expecting a block of code to execute once for each set of data
    in the list, which is now on the next line, and is not seen as part of the current command.
    set comp_parts [lmap comp [lassign [split $other "-"] toolchain] --------------------------- this line break is seen as an early end of the lmap command -----------------------
    {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    }
    --------------------------- this line break will cause trouble for the lmap command too -------------------------
    ]

    Thank you for pointing this out. The following format fixed this error:

    ```tcl
    set str "vasp/6.3.0/intel_omp-compiler.2022.0.2-mkl.2022.0.2-mpi.2021.4.0"

    lassign [split $str "/"] pkg pkg_ver other
    set comp_parts [lmap comp [lassign [split $other "-"] toolchain] {
    set sepi [string first "." $comp]
    string replace $comp $sepi $sepi "/"
    } ]
    ```
    But when I debug the above code fragment in Komodo or Eclipse, I can only see the following four variables are displayed:

    str pkg pkg_ver other

    I want to step into the code fragment through debug to see the values of all variables and their changes.


    There are several tutorials on the web, one is on the TCL wiki:

    https://wiki.tcl-lang.org/page/Tcl+Tutorial+Lesson+0

    There are books as well. I learned TCL about 20 years ago from "Practical Programming in Tcl and Tk". It is available on the web now. There are more recent books on TCL which cover all the latest changes in TCL and Tk.

    I suggest you start a new thread asking for tutorials or books.

    Thank you for your advice and information.

    HZ

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)