主流CAE仿真软件如何在Linux&HPC并行计算集群上使用pbs或slurm脚本提交作业(下)?
·
内容介绍:
本文主要介绍,主流CAE仿真软件,如大型有限元分析软件ANSYS FLUENT、ANSYS MECHANICAL、ANSYS CFX、ANSYS LS-DYNA,ABAQUS、HFSS、NASTRAN、CST、STAR-CCM+、NUMECA、FEKO、COMSOL在HPC或Linux并行计算集群上如何使用pbs或slurm作业调度系统脚本提交作业以及如何使用软件在命令行提交作业,旨在帮助初入科研行业的小伙伴们,轻松使用以上软件在集群上快速运行自己的算例,不再为软件工具的使用或如何批量提交作业而煞费心思,从而回归到科研本身,欢迎有需要的伙伴学习!
软件下载请到HPC&Linux并行计算CAE常用软件网盘下载链接-CSDN博客下载
一、CAE仿真软件标准测试
1.1 ABAQUS 标准测试
1.1.1 使用slurm作业调度系统提交作业测试
#!/bin/bash
#SBATCH -J test
#SBATCH -N 1
#SBATCH -n 36
#SBATCH -p intel36_2
#SBATCH --ntasks-per-node=36
#SBATCH -o %x_%j.log
### Configure environment variables, need to unset SLURM's Global Task ID for ABAQUS's PlatformMPI to work
unset SLURM_GTIDS
### Create ABAQUS environment file for current job, you can set/add your own options (Python syntax)
env_file=abaqus_v6.env
node_list=$(scontrol show hostname ${SLURM_NODELIST} | sort -u)
mp_host_list="["
for host in ${node_list}; do
mp_host_list="${mp_host_list}['$host', ${SLURM_CPUS_ON_NODE}],"
done
mp_host_list=$(echo ${mp_host_list} | sed -e "s/,$/]/") ##获取运行节点列表
echo "mp_host_list=${mp_host_list}" > ${env_file}
### Set input file and job (file prefix) name here
job_name=${SLURM_JOB_NAME}
### ABAQUS parallel execution
input_file=test.inp
/public/software/test/abaqus2020/DassaultSystemes/SIMULIA/Commands/abq2020 analysis job=${job_name} input=${input_file} double=both cpus=${SLURM_NTASKS} mp_mode=mpi memory=80% thread=4 scratch=./ interactive >& "$job_name".log ##job 作业名 input输入文件 double=both双精度计算 cpus总核数 mp_mode mpi并行 memory内存上限 thread每个进程跑的线程数 scratch 临时结果文件夹 interactive 交互式运行
1.1.2 使用pbs作业调度系统提交作业测试
#!/bin/bash
#PBS -N test ##作业名自定义
#PBS -q normal ##替换成实际的队列
#PBS -l nodes=node1:32 ##替换成实际的资源
#PBS -o std.out
#PBS -e std.err
NP=`cat $PBS_NODEFILE | wc -l` ##计算总核数
##定义并行文件节点和核数
env_file=abaqus_v6.env
echo "mp_host_list=`cat $PBS_NODEFILE | sort | uniq -c| awk '{print a""b$2c","$1d}' a=[ b=\' c=\' d=]|sed ':a;N;s/\n/,/g;t a'|sed 's/^/&[/g;s/$/&]/g'`" > ${env_file}
### ABAQUS parallel execution
input_file=test.inp ##输入文件,改成自己的
job_name=`sh -c "basename $input_file .inp"`
APP=/public/software/test/abaqus2020/DassaultSystemes/SIMULIA/Commands/abq2020 ## 替换成自己的可执行文件路径
$APP analysis job="$job_name" input=${input_file} double=both cpus=${NP} mp_mode=mpi memory=80% thread=4 scratch=./ interactive >& "$job_name" .log
1.1.3 使用命令行方式提交作业测试
- SMP提交方式:
/public/software/test/abaqus2020/DassaultSystemes/SIMULIA/Commands/abq2020 analysis job=${job_name} input=${input_file} double=both cpus=${SLURM_NTASKS} mp_mode=threads memory=80% scratch=./ interactive >& "$job_name".log ##job 作业名 input输入文件 double=both双精度计算 cpus总核数 mp_mode threads smp方式运行 memory内存上限 scratch 临时结果文件夹 interactive 交互式运行
- MPP提交方式:
/public/software/test/abaqus2020/DassaultSystemes/SIMULIA/Commands/abq2020 analysis job=${job_name} input=${input_file} double=both cpus=${SLURM_NTASKS} mp_mode=mpi memory=80% thread=4 scratch=./ interactive >& "$job_name".log ##job 作业名 input输入文件 double=both双精度计算 cpus总核数 mp_mode mpi并行 memory内存上限 thread每个进程跑的线程数 scratch 临时结果文件夹 interactive 交互式运行
1.2 HFSS标准测试
1.2.1 使用slurm作业调度系统提交作业测试
脚本范例
#!/bin/bash
#SBATCH -J test
#SBATCH -N 1
#SBATCH -n 36
#SBATCH -p intel36_2
#SBATCH --ntasks-per-node=36
#SBATCH -o %x_%j.log
srun hostname|sort|uniq -c|awk '{print $2":"$1":"$1}' > hosts
/public/software/AnsysEM_2020R1/AnsysEM20.1/Linux64/ansysedt -monitor -Batchsolve -Batchoptions "'HFSS/HPCLicenseType'=pack 'HFSS/MPIVendor'=Intel" -Distributed -machinelist file=hosts $FileName >& HFSS.log ##-monitor作业监控 -Batchsolve 批处理方式求解 -Batchoptions 批处理选项 指定lic类型和mpi类型 -Distributed 分布式计算 file 并行节点文件 $FileName .aedt输入文件
1.2.2 使用pbs作业调度系统提交作业测试
脚本范例
#!/bin/bash
#PBS -N test ##作业名自定义
#PBS -q normal ##替换成实际的队列
#PBS -l nodes=node1:32 ##替换成实际的资源
#PBS -o std.out
#PBS -e std.err
cat $PBS_NODEFILE|sort|uniq -c|awk '{print $2":"$1":"$1}' > hosts
/public/software/AnsysEM_2020R1/AnsysEM20.1/Linux64/ansysedt -monitor -Batchsolve -Batchoptions "'HFSS/HPCLicenseType'=pack 'HFSS/MPIVendor'=Intel" -Distributed -machinelist file=hosts $FileName >& HFSS.log ##-monitor作业监控 -Batchsolve 批处理方式求解 -Batchoptions 批处理选项 指定lic类型和mpi类型 -Distributed 分布式计算 file 并行节点文件 $FileName .aedt输入文件
1.2.3 使用命令行方式提交作业
- SMP提交方式:
/public/software/AnsysEM_2020R1/AnsysEM20.1/Linux64/ansysedt -Ng -monitor -Batchsolve -Batchoptions "'HFSS/HPCLicenseType'=pack '" -Local $FileName >& HFSS.log ##-Ng 不开启图形界面 -monitor作业监控 -Batchsolve 批处理方式求解 -Batchoptions 批处理选项 指定lic类型
- MPP提交方式:
/public/software/AnsysEM_2020R1/AnsysEM20.1/Linux64/ansysedt -Ng -monitor -Batchsolve -Batchoptions "'HFSS/HPCLicenseType'=pack 'HFSS/MPIVendor'=Intel" -Distributed -machinelist file=hosts $FileName >& HFSS.log ##-Ng 不开启图形界面-monitor作业监控 -Batchsolve 批处理方式求解 -Batchoptions 批处理选项 指定lic类型和mpi类型 -Distributed 分布式计算 file 并行节点文件 $FileName .aedt输入文件
1.3 NASTRAN标准测试
1.3.1 使用slurm作业调度系统提交作业测试
#!/bin/bash
#SBATCH -J test
#SBATCH -N 1
#SBATCH -n 36
#SBATCH -p intel36_2
#SBATCH --ntasks-per-node=36
#SBATCH -o %x_%j.log
HOST_STRING=`scontrol show hostname | paste -d: -s`
INPUT_FILE=Nastran_Example_New.bdf
/public/software/msc/nastran2012.2/bin/nast20122 jid=$INPUT_FILE dmp=$SLURM_NPROCS hosts=$HOST_STRING memory=estimate sdir=./ out=./ ##jid输入文件 dmp 分布式并行计算 hosts 计算节点和核数 memory自动分配 sdir临时文件夹 out输出结果文件夹
1.3.2 使用pbs作业调度系统提交作业测试
#!/bin/bash
#PBS -N test ##作业名自定义
#PBS -q normal ##替换成实际的队列
#PBS -l nodes=node1:32 ##替换成实际的资源
#PBS -o std.out
#PBS -e std.err
HOST_STRING=`cat $PBS_NODEFILE | sort | uniq -c | awk '{print $2":"$1}' | tr '\n' ':' | sed 's/:$//'`
INPUT_FILE=Nastran_Example_New.bdf
/public/software/msc/nastran2012.2/bin/nast20122 jid=$INPUT_FILE dmp=$SLURM_NPROCS hosts=$HOST_STRING memory=estimate sdir=./ out=./##jid输入文件 dmp 分布式并行计算 hosts 计算节点和核数 memory自动分配 sdir临时文件夹 out输出结果文件夹
1.3.3 使用命令行方式提交作业测试
- SMP提交方式:
/public/software/msc/nastran2012.2/bin/nast20122 jid=$INPUT_FILE smp=$SLURM_NPROCS memory=estimate sdir=./ out=./##jid输入文件 smp 共享内存式计算 memory内存分配方式 sdir临时文件夹 out输出结果文件夹
- MPP提交方式:
/public/software/msc/nastran2012.2/bin/nast20122 jid=$INPUT_FILE dmp=$SLURM_NPROCS hosts=$HOST_STRING memory=estimate sdir=./ out=./##jid输入文件 dmp 分布式并行计算 hosts 计算节点和核数 memory内存分配方式 sdir临时文件夹 out输出结果文件夹
1.4 CST标准测试
1.4.1 使用slurm作业调度系统提交作业测试
#!/bin/bash
#SBATCH -J test
#SBATCH -N 1
#SBATCH -n 36
#SBATCH -p intel36_2
#SBATCH --ntasks-per-node=36
#SBATCH -o %x_%j.log
#SBATCH –gres=gpu:2
INPUT_FILE=test.cst
/public/software/CST/CST_STUDIO_SUITE_2019/LinuxAMD64/cst_design_environment_AMD64 -m -r -numthreads=16 -withgpu=2 -dump 1 $ INPUT_FILE ##-m -r微波时域模块 -numthreads 线程数 –withgpu使用的gpu卡数 -dump 每隔多少步输出一次
1.4.2 使用pbs作业调度系统提交作业测试
#!/bin/bash
#PBS -N test ##作业名自定义
#PBS -q normal ##替换成实际的队列
#PBS -l nodes=node1:32:gpu=2 ##替换成实际的资源
#PBS -o std.out
#PBS -e std.err
INPUT_FILE=test.cst
/public/software/CST/CST_STUDIO_SUITE_2019/LinuxAMD64/cst_design_environment_AMD64 -m -r -numthreads=16 -withgpu=2 -dump 1 $ INPUT_FILE ##-m -r微波时域模块 -numthreads 线程数 –withgpu使用的gpu卡数 -dump 每隔多少步输出一次
1.4.3 使用命令行方式提交作业测试
/public/software/CST/CST_STUDIO_SUITE_2019/LinuxAMD64/cst_design_environment_AMD64 -m -r -numthreads=16 -withgpu=2 -dump 1 $ INPUT_FILE ##-m -r微波时域模
1.5 STAR-CCM+标准测试
1.5.1 使用slurm作业调度系统提交作业测试
#!/bin/bash
#SBATCH -J test
#SBATCH -N 1
#SBATCH -n 36
#SBATCH -p intel36_2
#SBATCH --ntasks-per-node=36
#SBATCH -o %x_%j.log
srun hostname | sort | uniq -c | awk '{print $2":"$1}' > hosts
INPUT_FILE=External_aero_template_v3_cleared.sim
/public/software/starccm/2020.3/15.06.008-R8/STAR-CCM+15.06.008-R8/star/bin/starccm+ -batch run -np $NP -mpi intel -machinefile hosts -fabric ibv -dp $INPUT_FILE ##-batch批处理方式运行 -np总核数 -mpi mpi类型 -machinefile 机器列表 -fabric 通信方式 -dp双精度 INPUT_FILE 输入文件
1.5.2 使用pbs作业调度系统提交作业测试
#!/bin/bash
#PBS -N test ##作业名自定义
#PBS -q normal ##替换成实际的队列
#PBS -l nodes=node1:32 ##替换成实际的资源
#PBS -o std.out
#PBS -e std.err
NP=`cat $PBS_NODEFILE | wc -l` ##计算总核数
machines=$(cat $PBS_NODEFILE|sort|uniq -c|awk '{print $2":"$1}') ##获取节点列表
INPUT_FILE=External_aero_template_v3_cleared.sim
/public/software/starccm/2020.3/15.06.008-R8/STAR-CCM+15.06.008-R8/star/bin/starccm+ -power -batch run -np $NP -mpi intel -machinefile hosts -fabric ibv $INPUT_FILE ##-batch批处理方式运行 -np总核数 -mpi mpi类型 -machinefile 机器列表 -fabric 通信方式 -dp双精度 INPUT_FILE 输入文件
1.5.3 使用命令行方式提交作业测试
- SMP提交方式:
public/software/starccm/2020.3/15.06.008-R8/STAR-CCM+15.06.008-R8/star/bin/starccm+ -power -batch run -dp -np $NP $INPUT_FILE ##-batch批处理方式运行 -np总核数 -dp双精度 INPUT_FILE 输入文件
- MPP提交方式:
/public/software/starccm/2020.3/15.06.008-R8/STAR-CCM+15.06.008-R8/star/bin/starccm+ -power -batch run -np $NP -mpi intel -machinefile hosts -fabric ibv $INPUT_FILE ##-batch批处理方式运行 -np总核数 -mpi mpi类型 -machinefile 机器列表 -fabric 通信方式 -dp双精度 INPUT_FILE 输入文件
1.6 NUMECA标准测试
1.6.1 使用slurm作业调度系统提交作业测试
#!/bin/bash
#SBATCH -J test
#SBATCH -N 2
#SBATCH -n 10
#SBATCH -p normal
#SBATCH --ntasks-per-node=5
#SBATCH -o %x_%j.log
export NUMECA_LICENSE_FILE=26001@amd1
FileName=DemoCase8.iec
/public/software/NUMECA/bin/fine131 -batch -project DemoCase8.iec
WORK_DIR=$(sh -c "basename $FileName .iec")"_000"
cd $WORK_DIR
srun hostname | sort | uniq -c | awk '{print $2" "($1-1)}' > hosts
srun hostname | sort | uniq -c | awk '{if(NR==1){print $2":"$1}else{print $2":"($1-1}}' > HOSTS
/public/software/NUMECA/bin/fine131 -batch -partition -computation DemoCase8_000.run -nproc $((SLURM_NPROCS-2)) -machine_file hosts
export NUMECA_LICENSE_FILE=26001@amd1
export NI_VERSIONS_DIR=/public/software/NUMECA
export TMP_DIR=/public/home/yaolang/NUMECA_TEST/DemoCase8_000
export NUMECA_DIR=${NI_VERSIONS_DIR}/fine131
export NUMECA_BIN=${NUMECA_DIR}/LINUX
export MPIR_HOME=${NUMECA_BIN}/_mpi/_impi5.1.3/intel64
export OPAL_PREFIX=$MPIR_HOME
export PATH=${MPIR_HOME}/bin:${PATH}
export LD_LIBRARY_PATH=$MPIR_HOME/lib:${NUMECA_BIN}/_lib_sx86_64:${NUMECA_BIN}/_lib_sicc15:${LD_LIBRARY_PATH}
export BIN=${NUMECA_BIN}/euranus/euranusTurbodpx86_64_impi_icc
MPIRUN=$MPIR_HOME/bin/mpiexec.hydra
RUN_FILE=DemoCase8_000.run
STEERING_FILE=DemoCase8_000.steering
mpirun -np 9 -machinefile HOSTS ${BIN} $RUN_FILE -steering $STEERING_FILE -fullflex
1.6.2 使用pbs作业调度系统提交作业测试
#!/bin/bash
#PBS -N test ##作业名自定义
#PBS -q normal ##替换成实际的队列
#PBS -l nodes=node1:5:node2:5 ##替换成实际的资源
#PBS -o std.out
#PBS -e std.err
NP=`cat $PBS_NODEFILE | wc -l` ##计算总核数
export NUMECA_LICENSE_FILE=26001@amd1
FileName=DemoCase8.iec
/public/software/NUMECA/bin/fine131 -batch -project DemoCase8.iec
WORK_DIR=$(sh -c "basename $FileName .iec")"_000"
cd $WORK_DIR
cat $PBS_NODEFILE | sort | uniq -c | awk '{print $2" "($1-1)}' > hosts
cat $PBS_NODEFILE | sort | uniq -c | awk '{if(NR==1){print $2":"$1}else{print $2":"($1-1}}' > HOSTS
/public/software/NUMECA/bin/fine131 -batch -partition -computation DemoCase8_000.run -nproc $((NP-2)) -machine_file hosts
export NUMECA_LICENSE_FILE=26001@amd1
export NI_VERSIONS_DIR=/public/software/NUMECA
export TMP_DIR=/public/home/yaolang/NUMECA_TEST/DemoCase8_000
export NUMECA_DIR=${NI_VERSIONS_DIR}/fine131
export NUMECA_BIN=${NUMECA_DIR}/LINUX
export MPIR_HOME=${NUMECA_BIN}/_mpi/_impi5.1.3/intel64
export OPAL_PREFIX=$MPIR_HOME
export PATH=${MPIR_HOME}/bin:${PATH}
export LD_LIBRARY_PATH=$MPIR_HOME/lib:${NUMECA_BIN}/_lib_sx86_64:${NUMECA_BIN}/_lib_sicc15:${LD_LIBRARY_PATH}
export BIN=${NUMECA_BIN}/euranus/euranusTurbodpx86_64_impi_icc
MPIRUN=$MPIR_HOME/bin/mpiexec.hydra
RUN_FILE=DemoCase8_000.run
STEERING_FILE=DemoCase8_000.steering
mpirun -np $((NP-1)) -machinefile HOSTS ${BIN} $RUN_FILE -steering $STEERING_FILE -fullflex
1.6.3 使用命令行方式提交作业测试
export NUMECA_LICENSE_FILE=26001@amd1
FileName=DemoCase8.iec
/public/software/NUMECA/bin/fine131 -batch -project DemoCase8.iec
WORK_DIR=$(sh -c "basename $FileName .iec")"_000"
cd $WORK_DIR
cat $PBS_NODEFILE | sort | uniq -c | awk '{print $2" "($1-1)}' > hosts
cat $PBS_NODEFILE | sort | uniq -c | awk '{if(NR==1){print $2":"$1}else{print $2":"($1-1}}' > HOSTS
/public/software/NUMECA/bin/fine131 -batch -partition -computation DemoCase8_000.run -nproc $((NP-2)) -machine_file hosts
export NUMECA_LICENSE_FILE=26001@amd1
export NI_VERSIONS_DIR=/public/software/NUMECA
export TMP_DIR=/public/home/yaolang/NUMECA_TEST/DemoCase8_000
export NUMECA_DIR=${NI_VERSIONS_DIR}/fine131
export NUMECA_BIN=${NUMECA_DIR}/LINUX
export MPIR_HOME=${NUMECA_BIN}/_mpi/_impi5.1.3/intel64
export OPAL_PREFIX=$MPIR_HOME
export PATH=${MPIR_HOME}/bin:${PATH}
export LD_LIBRARY_PATH=$MPIR_HOME/lib:${NUMECA_BIN}/_lib_sx86_64:${NUMECA_BIN}/_lib_sicc15:${LD_LIBRARY_PATH}
export BIN=${NUMECA_BIN}/euranus/euranusTurbodpx86_64_impi_icc
MPIRUN=$MPIR_HOME/bin/mpiexec.hydra
RUN_FILE=DemoCase8_000.run
STEERING_FILE=DemoCase8_000.steering
mpirun -np $((NP-1)) -machinefile HOSTS ${BIN} $RUN_FILE -steering $STEERING_FILE -fullflex
1.7 FEKO标准测试
1.7.1 使用slurm作业调度系统提交作业测试
#!/bin/bash
#SBATCH -J feko
#SBATCH -N 1
#SBATCH -n 8
#SBATCH -p normal
#SBATCH --ntasks-per-node=8
#SBATCH -o %x_%j.log
#export I_MPI_FABRICS=shm:dapl
#srun hostname | sort > hosts
srun hostname | sort | uniq -c | awk '{print $2":"$1}' > hosts
job_name=${SLURM_JOB_NAME}
INPUT_FILE=dual_antenna.cfx
/public/software/FEKO/2017/altair/scripts/runfeko "$INPUT_FILE" --priority 4 -np all --machines-file hosts >& "$job_name".log
1.7.2 使用pbs作业调度系统提交作业测试
#!/bin/bash
#PBS -N test ##作业名自定义
#PBS -q normal ##替换成实际的队列
#PBS -l nodes=node1:32 ##替换成实际的资源
#PBS -o std.out
#PBS -e std.err
NP=`cat $PBS_NODEFILE | wc -l` ##计算总核数
cat $PBS_NODEFILE|sort|uniq -c|awk '{print $2":"$1}' > hosts ##获取节点列表
INPUT_FILE=dual_antenna.cfx
/public/software/FEKO/2017/altair/scripts/runfeko "$INPUT_FILE" --priority 4 -np all --machines-file hosts >& "$job_name".log
1.7.3 使用命令行方式提交作业测试
- SMP并行方式
/public/software/FEKO/2017/altair/scripts/runfeko dual_antenna.cfx --priority 4 -np 8 --use-openmp-threading >& dual_antenna.log
- MPP并行方式
/public/software/FEKO/2017/altair/scripts/runfeko dual_antenna.cfx --priority 4 -np all --machines-file hosts >& dual_antenna.log
1.8 COMSOL标准测试
1.8.1 使用slurm作业调度系统提交作业测试
#!/bin/bash
#SBATCH -J test
#SBATCH -N 16
#SBATCH -n 576
#SBATCH -p normal
#SBATCH --ntasks-per-node=36
job_name=${SLURM_JOB_NAME}
INPUT_FILE=test.mph
FileName=`sh -c "basename ${INPUT_FILE} .mph"`
OUTPUT_FILE_LOCATION=`pwd`
scontrol show hostnames > hostfiles
/public/software/comsol55/multiphysics/bin/comsol batch -clustersimple -nn "$SLURM_JOB_NUM_NODES" -np "$SLURM_NTASKS_PER_NODE" -f hostfile -mpirsh ssh -inputfile "${FileName}.mph" -outputfile "${FileName}_out.mph" -batchlog "${FileName}_out.log" -tmpdir "$OUTPUT_FILE_LOCATION"
1.8.2 使用pbs作业调度系统提交作业测试
#!/bin/bash
#PBS -N test ##作业名自定义
#PBS -q normal ##替换成实际的队列
#PBS -l nodes=node1:32 ##替换成实际的资源
#PBS -o std.out
#PBS -e std.err
NP=`cat $PBS_NODEFILE | wc -l` ##计算总核数
NNODE=` cat $PBS_NODEFILE|sort|uniq |wc -l`
NCORE=$((NP/NNODE))
cat $PBS_NODEFILE|sort|uniq > hosts ##获取节点列表
INPUT_FILE= test.mph
FileName=`sh -c "basename ${INPUT_FILE} .mph"`
OUTPUT_FILE_LOCATION=`pwd`
/public/software/comsol55/multiphysics/bin/comsol batch -clustersimple -nn "$NNODE" -np "$NCORE" -f hosts -mpirsh ssh -inputfile "${FileName}.mph" -outputfile "${FileName}_out.mph" -batchlog "${FileName}_out.log" -tmpdir "$PWD"
1.8.3 使用命令行方式提交作业测试
- SMP并行方式
/public/software/comsol55/multiphysics/bin/comsol batch -np 16 -inputfile "${FileName}.mph" -outputfile "${FileName}_out.mph" -batchlog "${FileName}_out.log" -tmpdir "$PWD"
- MPP并行方式
/public/software/comsol55/multiphysics/bin/comsol batch -clustersimple -nn 2 -np 16 -f hosts -mpirsh ssh -inputfile "${FileName}.mph" -outputfile "${FileName}_out.mph" -batchlog "${FileName}_out.log" -tmpdir "$PWD"
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)