Building WRF

Before Installing

add "Installing deps libraries" in the future

詳細的相依函式庫安裝請參考系統環境測試建立函式庫函式庫兼容性測試。為了讓各位同學們更快速進入狀況,這次助教已將環境以模組化方式安裝。

建立WRF和WPS的libraries。我們需要依序安裝「NetCDF」、「MPICH」、「zlib」、「libpng」、「JasPer」。這邊要注意的是,編譯 libraries 和 WRF/WPS 都必須在相同的環境設定下編譯安裝,不然過程中很可能會出錯。除了建立 WRF 要使用的 libraries 的還要安裝 NCL ,由於國網的 ${HOME} 資料夾下是不會定時刪除的,所以建議國網使用者可以安裝在 ${HOME} 下,建一個 WRF 專用的 libraries 目錄在下方安裝,名稱可以隨意,本文件使用 ${HOME}/WRF_LIB 於臺灣杉一號或 ${prefix}/usr.i/netcdf/3_classic 使用於臺灣杉三號 (T3) 及 實驗室計算平台 [VAPOR] 。

Setting up the Environment Variables

方法一、使用 environment-modules 更改環境設定

首先GNU/Linux基本上都是預設GNU體系的 GCC (GNU Compiler Collection) 編譯器,課程中我們使用的Intel Compiler Classic 跟 GCC 雖然有一定程度的 compatibility ,為了避免出錯的麻煩,基本上大家還是將他們想像是互相衝突的,會比較單純一些,因此建議將不同編譯器編譯後的軟體/套件/程式執行檔分類存放。編譯完的程式基本上只要是設定好路徑,就能夠讓系統順著環境變數設置的路徑依序尋找bin下的執行檔、include下的檔頭描述文件、lib/lib64下的函式庫。

本次(NWP-2024)課程助教已經設定好 [VAPOR] 主機上的 env-modules ,不須額外設定 env-modules 的環境,可以直接執行 module 指令,即完成環境設定:

[USER@VAPOR ***]$ module purge[USER@VAPOR ***]$ module load Compilers/intel/2023.1.0[USER@VAPOR ***]$ module load Libraries/netcdf/classic/22.01

使用環境模組( environment-modules )的好處是可以隨時加入要的環境,同時也提供快速移除環境的功能。如果使用傳統的方法二,去修改 "${HOME}/.bashrc" source  "${HOME}/.bashrc" 是較難去移除已經添加的環境,通常就選擇直接重開一個 Terminal 視窗重新讀一遍最新的  "${HOME}/.bashrc" ,如果瞭解父程序和子程序的概念,其實將開啟 Terminal 視為是執行 bash 的行為,那開啟這件事就是父程序,在 Terminal 中所打的指令都只是 Terminal 下的子程序而已,終止父程序當然以下附屬的子程序也會同時被終止。所以若 shell 腳本中使用 /bin/bash 執行 module load ,也就表示 /bin/bash 執行完腳本後,環境也被取消了。因此要多試試看,比較能釐清何時該用 /bin/source 何時該用 /bin/bash  。另一方面,直接把 module 指令寫進 ${HOME}/.bashrc 裡面,這樣一登入就能直接取得設定好的環境喔,不用每次登入都要重新下好幾次 module purge/load/list

Added - 2024.04.27

方法二、修改 "${HOME}/.bashrc" 後 source "${HOME}/.bashrc" 的方式更改環境設定

先 cat 觀察一下 ${HOME}/.bashrc 這個檔案寫了什麼內容, ${HOME}/.bashrc 這個檔案只有在帳號以 interactive 方式(簡單來說就是模擬或實際使用 Terminal 的形式,登入電腦的方式)登入的時候才會被讀取,不然則是讀取另一個 ${HOME}/.bash_profile 的檔案。最後一行就是助教事先幫大家加上去的模組環境。

[USER@VAPOR ***]$ cat "${HOME}/.bashrc"# .bashrc# Source global definitionsif [ -f /etc/bashrc ]; then  /etc/bashrcfidateuname -acat /etc/redhat-release
# User specific aliases and functionsalias rm='rm -i'alias mv='mv -i'alias vi='vim'alias diff='colordiff'
# Uncomment the following line if you don't like systemctl's auto-paging feature:# export SYSTEMD_PAGER=
LESS='-R'LESSOPEN='|~/.lessfilter %s'export LESS LESSOPEN
module use /work3/NWP2024SP/env-modules

如果使用者使用的環境很單純,例如從頭到尾都只使用 GCC 或者都只使用 ICC ,那有 module load 能使用,就直接把 module load 寫進 ${HOME}/.bashrc 就很方便。但如果一下要GCC、一下要用ICC、又用NVCC等等環境複雜的情況,又沒有 environment-modules 安裝,則建議將各自的環境額外各自寫成一個 shell 檔會比較單純容易一些。需要時再去 source 那份 shell 即可,,或是自己想辦法把所有程式跟軟體都用同一種編譯器編譯完成(這個困難度或許又更高了)囉。

intel compiler 自帶 modulefiles 所以系統有安裝 environment-modules 的情況下省事很多,不然要加入的路徑很多,不小心 key-in 錯字沒有找到路徑下的文件倒是還容易,萬一 key-in 錯字的路徑還真的存在,除了整個大錯特錯還很難 debug。

除了 environment-modules 的模組外, 已經模組化的 Intel oneAPI Toolkits 工具組還有提供模組的環境變數設定檔給大家 source。針對增加 intel 編譯器模組的3種示範如下:

1 使用 Intel API Toolkits 所提供的 modulefiles 

[USER@VAPOR ***]$ cat >> "${HOME}/.bashrc" << "eof"> module load Compilers/intel/2023.1.0> eof

2 使用Intel API Toolkits所提供的環境腳本

[USER@VAPOR ***]$ export intelROOT="/aracbox/intel/oneapi"[USER@VAPOR ***]$ cat >> ${HOME}/.bashrc << "eof"> source "${intelROOT}/tbb/2021.9.0/env/vars.sh"> source "${intelROOT}/compiler/2023.1.0/env/vars.sh"> source "${intelROOT}/mkl/2023.1.0/env/vars.sh"> source "${intelROOT}/mpi/2021.9.0/env/vars.sh"> eof

3 老實的加上路徑,應該不會有人選這個方法吧...

[ 太複雜 收疊起來 眼不見為淨 ]

[USER@VAPOR ***]$ export intelROOT="/aracbox/intel/oneapi"[USER@VAPOR ***]$ cat >> ${HOME}/.bashrc << "eof"># module load tbb/2021.9.0> export LIBRARY_PATH="${intelROOT}/tbb/2021.9.0/lib/intel64/gcc4.8:${LIBRARY_PATH}"> export LD_LIBRARY_PATH="${intelROOT}/tbb/2021.9.0/lib/intel64/gcc4.8:${LIBRARY_PATH}"> export CPATH="${intelROOT}/tbb/2021.9.0/include:${CPATH}"> export CMAKE_PREFIX_PATH="${intelROOT}/tbb/2021.9.0:${CMAKE_PREFIX_PATH}"> # module load compiler-rt/2023.1.0> export LIBRARY_PATH="${intelROOT}/compiler/2023.1.0/linux/lib:${LIBRARY_PATH}"> export LD_LIBRARY_PATH="${intelROOT}/compiler/2023.1.0/linux/lib:${intelROOT}/compiler/2023.1.0/linux/lib/x64:${intelROOT}/compiler/2023.1.0/linux/compiler/lib/intel64_lin:${LD_LIBRARY_PATH}"> export DIAGUTIL_PATH="${intelROOT}/compiler/2023.1.0/sys_check/sys_check.sh"> # module load icc/2023.1.0> export  MANPATH="${MANPATH}:${intelROOT}/compiler/2023.1.0/documentation/en/man/common"> export PATH="${intelROOT}/compiler/2023.1.0/linux/bin/intel64:${PATH}"> # module load mkl/2023.1.0> export LIBRARY_PATH="${intelROOT}/mkl/2023.1.0/lib/intel64:${LIBRARY_PATH}"> export LD_LIBRARY_PATH="${intelROOT}/mkl/2023.1.0/lib/intel64:${LD_LIBRARY_PATH}"> export CPATH="${intelROOT}/mkl/2023.1.0/include"> export NLSPATH="${intelROOT}/mkl/2023.1.0/lib/intel64/locale/%l_%t/%N"> export PKG_CONFIG_PATH="${intelROOT}/mkl/2023.1.0/lib/pkgconfig"> # module load mpi/2021.9.0> export MANPATH="${MANPATH}:${intelROOT}/mpi/2021.9.0/man"> export LIBRARY_PATH="${intelROOT}/mpi/2021.9.0/lib:${LIBRARY_PATH}"> export LIBRARY_PATH="${intelROOT}/mpi/2021.9.0/lib/release:${LIBRARY_PATH}"> export LIBRARY_PATH="${intelROOT}/mpi/2021.9.0/libfabric/lib:${LIBRARY_PATH}"> export LD_LIBRARY_PATH="${intelROOT}/mpi/2021.9.0/lib:${LD_LIBRARY_PATH}"> export LD_LIBRARY_PATH="${intelROOT}/mpi/2021.9.0/lib/release:${LD_LIBRARY_PATH}"> export LD_LIBRARY_PATH="${intelROOT}/mpi/2021.9.0/libfabric/lib:${LD_LIBRARY_PATH}"> export FI_PROVIDER_PATH="/usr/lib64/libfabric"> export FI_PROVIDER_PATH="${intelROOT}/mpi/2021.9.0/libfabric/lib/prov:${FI_PROVIDER_PATH}"> export PATH="${intelROOT}/mpi/2021.9.0/include:${CPATH}"> export PATH="${intelROOT}/mpi/2021.9.0/libfabric/bin:${PATH}"> export PATH="${intelROOT}/mpi/2021.9.0/bin:${PATH}"> export CLASSPATH="${intelROOT}/mpi/2021.9.0/lib/mpi.jar"

環境變數增加到 ${HOME}/.bashrc 文件中之後,不要忘了要「重新登入一遍」,讓 ${HOME}/.bashrc 被讀取執行,更簡單的方法是直接 source ${HOME}/.bashrc 就假裝是有重新登入一遍的概念。

如何檢驗自己目前的環境呢?使用 env 看全部環境變數或 echo 取出特定的變數查看

Checking the Environment Variables

檢驗環境的撇步 1

[USER@VAPOR ***]$ echo ${variables_you_want}

錯誤訊息說缺什麼變數,我們就要補給他什麼變數,但不知道有沒有設定好,就不要客氣的直接把他印出來吧,有的話就會印出變數被賦予的值。針對特定變數取值檢查。

檢驗環境的撇步 2

非預設路徑的指令、函示庫、檔頭文件、使用文件等位置加入環境變數中。

[USER@VAPOR ***]$ env | grep PATH

跟編譯有關的主要環境變數名稱命名通常都有「PATH」出現,例如:PATH, CPATH, LIBRARY_PATH, LD_LIBRARY_PATH, ...等等。

或是路徑名稱有共同特色,例如 intel 編譯完成的套件都放在 usr.i 目錄下。

檢驗環境的撇步 3

編譯選項的環境設定, CPPFLAGS 和 LDFLAGS 跟編譯器連結環境有關,其他帶有 FLAGS 跟的變數不加上去也還是能編譯安裝成功,多半是加入優化選項或精度浮點數設定等等。

[USER@VAPOR ***]$ env | grep FLAGS

編譯器後方接的編譯選項變數名稱通常以FLAGS結尾,例如:CFLAGS, LDFLAGS, CPPFLAGS, ...等等,2024年NWP課程的編譯選項,助教已經直接在模組中寫好了,可以直接檢查看看最重要的兩個 FLAGS 有沒有出現

所以編譯 WRF & WPS 所需要的環境變數設定完整版如下:(以modules方式載入者,額外給定 $WRF_DIR 變數)

Summary for Environment Setup

[USER@VAPOR ***]$ cat >> "${HOME}/.bashrc" << "eof"module load Compilers/intel/2023.1.0module load Libraries/netcdf/classic/22.01### Please check the necessity of the "VARS" (added/modified/removed) below before you copy & paste them QUICK and DIRTY. export   CC="icc"export  CXX="icpc"export FORT="ifort"export   FC="ifort"export  F9X="ifort"export  F90="ifort"export  F77="ifort"export NETCDF="${HOME}/netcdf"export WRF_DIR="/work/${USER}/WRF"export CPPFLAGS="-I${NETCDF}/include"export  LDFLAGS="-L${NETCDF}/lib"export     LIBS="${LDFLAGS} -lnetcdff -lnetcdf -ljasper -lpng -lz"export JASPERINC="${NETCDF}/include"export JASPERLIB="${NETCDF}/lib"### The "FLAGS" below should be used PROPERLY. Check out before you copy & paste them QUICK and DIRTY.  export   CFLAGS="-O3 -ip -fp-model precise -w -ftz -xHOST"export CXXFLAGS="-O3 -ip -fp-model precise -w -ftz -xHOST"export  FCFLAGS="-m64 -O3 -ip -fp-model precise -w -ftz -xHOST"export   FFLAGS="-m64 -O3 -ip -fp-model precise -w -ftz -xHOST"eof

檢查一下環境變數沒問題就可以準備開始編譯囉!