|
| 1 | +# Copyright 2022-2024 The Ramble Authors |
| 2 | +# |
| 3 | +# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| 4 | +# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| 5 | +# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your |
| 6 | +# option. This file may not be copied, modified, or distributed |
| 7 | +# except according to those terms. |
| 8 | + |
| 9 | +import os |
| 10 | +from ramble.appkit import * |
| 11 | +from ramble.expander import Expander |
| 12 | + |
| 13 | + |
| 14 | +class OpenfoamOrg(SpackApplication): |
| 15 | + '''Define the Openfoam application''' |
| 16 | + name = 'openfoam-org' |
| 17 | + |
| 18 | + maintainers('douglasjacobsen') |
| 19 | + |
| 20 | + tags('cfd', 'fluid', 'dynamics') |
| 21 | + |
| 22 | + define_compiler( 'gcc9', spack_spec='[email protected]') |
| 23 | + |
| 24 | + software_spec('ompi412', |
| 25 | + spack_spec='[email protected] +legacylaunchers +cxx', |
| 26 | + compiler='gcc9') |
| 27 | + |
| 28 | + software_spec('openfoam-org', |
| 29 | + spack_spec='openfoam-org@10', |
| 30 | + compiler='gcc9') |
| 31 | + |
| 32 | + required_package('openfoam-org') |
| 33 | + |
| 34 | + workload('motorbike', executables=['clean', 'get_inputs', 'configure_mesh', 'surfaceFeatures', |
| 35 | + 'blockMesh', 'decomposePar1', 'snappyHexMesh', |
| 36 | + 'configure_simplefoam', |
| 37 | + 'redistributePar', |
| 38 | + 'decomposePar2', 'patchSummary', |
| 39 | + 'potentialFoam', 'checkMesh', |
| 40 | + 'simpleFoam']) |
| 41 | + |
| 42 | + workload('motorbike_20m', executables=['clean', 'get_inputs', 'configure_mesh', 'surfaceFeatures', |
| 43 | + 'blockMesh', 'decomposePar1', 'snappyHexMesh', |
| 44 | + 'configure_simplefoam', |
| 45 | + 'redistributePar', |
| 46 | + 'decomposePar2', 'patchSummary', |
| 47 | + 'potentialFoam', 'checkMesh', |
| 48 | + 'simpleFoam']) |
| 49 | + |
| 50 | + workload('motorbike_42m', executables=['clean', 'get_inputs', 'configure_mesh', 'surfaceFeatures', |
| 51 | + 'blockMesh', 'decomposePar1', 'snappyHexMesh', |
| 52 | + 'configure_simplefoam', |
| 53 | + 'redistributePar', |
| 54 | + 'decomposePar2', 'patchSummary', |
| 55 | + 'potentialFoam', 'checkMesh', |
| 56 | + 'simpleFoam']) |
| 57 | + |
| 58 | + workload_variable('input_path', default='$FOAM_TUTORIALS/incompressible/simpleFoam/motorBike', |
| 59 | + description='Path to the tutorial input', |
| 60 | + workloads=['motorbike*']) |
| 61 | + workload_variable('geometry_path', default='$FOAM_TUTORIALS/resources/geometry/motorBike.obj.gz', |
| 62 | + description='Path to the geometry resource', |
| 63 | + workloads=['motorbike*']) |
| 64 | + workload_variable('decomposition_path', default='system/decomposeParDict', |
| 65 | + description='Path to decomposition files', |
| 66 | + workloads=['motorbike*']) |
| 67 | + workload_variable('control_path', default='system/controlDict', |
| 68 | + description='Path to control file', |
| 69 | + workloads=['motorbike*']) |
| 70 | + workload_variable('block_mesh_path', default='system/blockMeshDict', |
| 71 | + description='Path to block mesh file', |
| 72 | + workloads=['motorbike*']) |
| 73 | + workload_variable('hex_mesh_path', default='system/snappyHexMeshDict', |
| 74 | + description='Path to hexh mesh file', |
| 75 | + workloads=['motorbike*']) |
| 76 | + |
| 77 | + workload_variable('end_time', default='250', |
| 78 | + description='End time for simulation', |
| 79 | + workloads=['motorbike*']) |
| 80 | + workload_variable('write_interval', default='500', |
| 81 | + description='Interval to write output files', |
| 82 | + workloads=['motorbike*']) |
| 83 | + workload_variable('start_from', default='startTime', |
| 84 | + description='How to start a new simulation', |
| 85 | + workloads=['motorbike*']) |
| 86 | + workload_variable('mesh_size', default='(20 8 8)', |
| 87 | + description='Mesh size for simulation', |
| 88 | + workload='motorbike') |
| 89 | + workload_variable('mesh_size', default='(100 40 40)', |
| 90 | + description='Mesh size for simulation', |
| 91 | + workload='motorbike_20m') |
| 92 | + workload_variable('mesh_size', default='(130 52 52)', |
| 93 | + description='Mesh size for simulation', |
| 94 | + workload='motorbike_42m') |
| 95 | + workload_variable('max_local_cells', default='100000', |
| 96 | + description='Max local cells for simulation', |
| 97 | + workloads=['motorbike*']) |
| 98 | + workload_variable('max_global_cells', default='50000000', |
| 99 | + description='Max global cells for simulation', |
| 100 | + workloads=['motorbike*']) |
| 101 | + |
| 102 | + workload_variable('n_ranks_hex', default='16', |
| 103 | + description='Number of ranks to use for snappyHexMesh', |
| 104 | + workloads=['motorbike*']) |
| 105 | + workload_variable('hex_flags', default='-overwrite', |
| 106 | + description='Flags for snappyHexMesh', |
| 107 | + workloads=['motorbike*']) |
| 108 | + workload_variable('potential_flags', default='-writePhi', |
| 109 | + description='Flags for potentialFoam', |
| 110 | + workloads=['motorbike*']) |
| 111 | + workload_variable('simple_flags', default='', |
| 112 | + description='Flags for simpleFoam', |
| 113 | + workloads=['motorbike*']) |
| 114 | + |
| 115 | + workload_variable('dict_delim', description='Delimiter for dictionary entries', |
| 116 | + default='/', workloads=['motorbike*']) |
| 117 | + |
| 118 | + workload_variable('coeffs_dict', description='Coeffs dictionary name', |
| 119 | + default='hierarchicalCoeffs', workloads=['motorbike*']) |
| 120 | + |
| 121 | + executable('clean', template=['rm -rf processor* constant system log.*']) |
| 122 | + |
| 123 | + executable('get_inputs', template=['cp -Lr {input_path}/* {experiment_run_dir}/.', |
| 124 | + 'mkdir -p constant/triSurface', |
| 125 | + 'mkdir -p constant/geometry', |
| 126 | + 'cp {geometry_path} constant/triSurface/.', |
| 127 | + 'cp {geometry_path} constant/geometry/.', |
| 128 | + 'ln -sf {experiment_run_dir}0/U.orig {experiment_run_dir}/0/U'], |
| 129 | + use_mpi=False) |
| 130 | + |
| 131 | + executable('configure_mesh', template=['. $WM_PROJECT_DIR/bin/tools/RunFunctions', |
| 132 | + 'foamDictionary -entry "numberOfSubdomains" -set "{n_ranks_hex}" {decomposition_path}', |
| 133 | + 'foamDictionary -entry "{coeffs_dict}{dict_delim}n" -set "({min({n_ranks_hex}, {processes_per_node})} {ceil({n_ranks_hex}/{processes_per_node})} 1)" {decomposition_path}', |
| 134 | + 'foamDictionary -entry "castellatedMeshControls{dict_delim}maxLocalCells" -set "{max_local_cells}" {hex_mesh_path}', |
| 135 | + 'foamDictionary -entry "castellatedMeshControls{dict_delim}maxGlobalCells" -set "{max_global_cells}" {hex_mesh_path}', |
| 136 | + 'sed "s/(20 8 8)/{mesh_size}/" -i {block_mesh_path}'], |
| 137 | + use_mpi=False) |
| 138 | + |
| 139 | + executable('configure_simplefoam', template=['. $WM_PROJECT_DIR/bin/tools/RunFunctions', |
| 140 | + 'foamDictionary -entry "numberOfSubdomains" -set "{n_ranks}" {decomposition_path}', |
| 141 | + 'foamDictionary -entry "{coeffs_dict}{dict_delim}n" -set "({processes_per_node} {n_nodes} 1)" {decomposition_path}', |
| 142 | + 'foamDictionary -entry "endTime" -set "{end_time}" {control_path}', |
| 143 | + 'foamDictionary -entry "writeInterval" -set "{write_interval}" {control_path}', |
| 144 | + 'foamDictionary -entry "startFrom" -set "{start_from}" {control_path}', |
| 145 | + 'foamDictionary system/fvSolution -entry relaxationFactors{dict_delim}fields -add "{}"', |
| 146 | + 'foamDictionary system/fvSolution -entry relaxationFactors{dict_delim}fields{dict_delim}p -set "0.3"', |
| 147 | + 'foamDictionary system/fvSolution -entry solvers{dict_delim}p{dict_delim}nPreSweeps -set "0"', |
| 148 | + 'foamDictionary system/fvSolution -entry solvers{dict_delim}p{dict_delim}nPostSweeps -set "2"', |
| 149 | + 'foamDictionary system/fvSolution -entry solvers{dict_delim}p{dict_delim}cacheAgglomeration -set "on"', |
| 150 | + 'foamDictionary system/fvSolution -entry solvers{dict_delim}p{dict_delim}agglomerator -set "faceAreaPair"', |
| 151 | + 'foamDictionary system/fvSolution -entry solvers{dict_delim}p{dict_delim}nCellsInCoarsestLevel -set "10"', |
| 152 | + 'foamDictionary system/fvSolution -entry solvers{dict_delim}p{dict_delim}mergeLevels -set "1"', |
| 153 | + 'foamDictionary system/fvSolution -entry SIMPLE{dict_delim}consistent -set "yes"'], |
| 154 | + use_mpi=False) |
| 155 | + |
| 156 | + executable('surfaceFeatures', template=['surfaceFeatures', 'surfaceFeatureExtract'], |
| 157 | + use_mpi=False, |
| 158 | + redirect='{experiment_run_dir}/log.surfaceFeatures') |
| 159 | + |
| 160 | + executable('blockMesh', 'blockMesh', |
| 161 | + use_mpi=False, |
| 162 | + redirect='{experiment_run_dir}/log.blockMesh') |
| 163 | + |
| 164 | + executable('decomposePar1', template=['decomposePar -noZero -force'], |
| 165 | + use_mpi=False, |
| 166 | + redirect='{experiment_run_dir}/log.decomposePar1') |
| 167 | + |
| 168 | + executable('decomposePar2', template=['rm -rf processor*/0', 'decomposePar -copyZero -fields'], |
| 169 | + use_mpi=False, |
| 170 | + redirect='{experiment_run_dir}/log.decomposePar2') |
| 171 | + |
| 172 | + executable('snappyHexMesh', template=['snappyHexMesh -parallel {hex_flags}'], use_mpi=True, variables={'n_ranks': '{n_ranks_hex}'}, |
| 173 | + redirect='{experiment_run_dir}/log.snappyHexMesh') |
| 174 | + |
| 175 | + executable('redistributePar', 'redistributePar -noZero -overwrite -parallel', use_mpi=True, |
| 176 | + redirect='{experiment_run_dir}/log.redistributePar') |
| 177 | + |
| 178 | + executable('patchSummary', 'patchSummary -parallel', use_mpi=True, |
| 179 | + redirect='{experiment_run_dir}/log.patchSummary') |
| 180 | + executable('checkMesh', "checkMesh -parallel -constant", use_mpi=True, |
| 181 | + redirect='{experiment_run_dir}/log.checkMesh') |
| 182 | + executable('potentialFoam', 'potentialFoam -parallel {potential_flags}', use_mpi=True, |
| 183 | + redirect='{experiment_run_dir}/log.potentialFoam') |
| 184 | + executable('simpleFoam', 'simpleFoam -parallel {simple_flags}', use_mpi=True, |
| 185 | + redirect='{experiment_run_dir}/log.simpleFoam') |
| 186 | + |
| 187 | + workload_variable('export_prefix', default='-x', |
| 188 | + description='Prefix for exporting an environment variable with mpirun', |
| 189 | + workloads=['*']) |
| 190 | + |
| 191 | + workload_variable('workload_exports', default='', |
| 192 | + description='Placeholder variable which holds all variable exports. Defined during setup.', |
| 193 | + workloads=['*']) |
| 194 | + |
| 195 | + workload_variable('export_variables', |
| 196 | + description='Comma separated list of all env-var names that need to be exported', |
| 197 | + default="PATH,LD_LIBRARY_PATH,FOAM_APP,FOAM_APPBIN,FOAM_ETC," + |
| 198 | + "FOAM_EXT_LIBBIN,FOAM_INST_DIR,FOAM_JOB_DIR,FOAM_LIBBIN," + |
| 199 | + "FOAM_MPI,FOAM_RUN,FOAM_SETTINGS,FOAM_SIGFPE,FOAM_SITE_APPBIN," + |
| 200 | + "FOAM_SITE_LIBBIN,FOAM_SOLVERS,FOAM_SRC,FOAM_TUTORIALS," + |
| 201 | + "FOAM_USER_APPBIN,FOAM_USER_LIBBIN,FOAM_UTILITIES,WM_ARCH," + |
| 202 | + "WM_ARCH_OPTION,WM_CC,WM_CFLAGS,WM_COMPILER,WM_COMPILER_LIB_ARCH," + |
| 203 | + "WM_COMPILER_TYPE,WM_COMPILE_OPTION,WM_CXX,WM_CXXFLAGS,WM_DIR," + |
| 204 | + "WM_LABEL_OPTION,WM_LABEL_SIZE,WM_LDFLAGS,WM_LINK_LANGUAGE,WM_MPLIB," + |
| 205 | + "WM_OPTIONS,WM_OSTYPE,WM_PRECISION_OPTION,WM_PROJECT,WM_PROJECT_DIR," + |
| 206 | + "WM_PROJECT_INST_DIR,WM_PROJECT_USER_DIR,WM_PROJECT_VERSION," + |
| 207 | + "WM_THIRD_PARTY_DIR,MPI_ARCH_FLAGS,MPI_ARCH_INC,MPI_ARCH_LIBS," + |
| 208 | + "MPI_ARCH_PATH,MPI_BUFFER_SIZE,MPI_ROOT", |
| 209 | + workloads=['*']) |
| 210 | + |
| 211 | + log_prefix = os.path.join(Expander.expansion_str('experiment_run_dir'), 'log.') |
| 212 | + |
| 213 | + figure_of_merit('Number of cells', log_file=(log_prefix + 'snappyHexMesh'), |
| 214 | + fom_regex=r'Layer mesh\s+:\s+cells:(?P<ncells>[0-9]+)\s+.*', |
| 215 | + group_name='ncells', units='') |
| 216 | + |
| 217 | + figure_of_merit('snappyHexMesh Time ({n_ranks_hex} ranks)', log_file=(log_prefix + 'snappyHexMesh'), |
| 218 | + fom_regex=r'Finished meshing in = (?P<mesh_time>[0-9]+\.?[0-9]*).*', |
| 219 | + group_name='mesh_time', units='s') |
| 220 | + |
| 221 | + figure_of_merit('simpleFoam Time ({n_ranks} ranks)', log_file=(log_prefix + 'simpleFoam'), |
| 222 | + fom_regex=r'\s*ExecutionTime = (?P<foam_time>[0-9]+\.?[0-9]*).*', |
| 223 | + group_name='foam_time', units='s') |
| 224 | + |
| 225 | + figure_of_merit('potentialFoam Time ({n_ranks} ranks)', log_file=(log_prefix + 'potentialFoam'), |
| 226 | + fom_regex=r'\s*ExecutionTime = (?P<foam_time>[0-9]+\.?[0-9]*).*', |
| 227 | + group_name='foam_time', units='s') |
| 228 | + |
| 229 | + success_criteria('snappyHexMesh_completed', mode='string', match='Finalising parallel run', |
| 230 | + file='{experiment_run_dir}/log.snappyHexMesh') |
| 231 | + |
| 232 | + success_criteria('simpleFoam_completed', mode='string', match='Finalising parallel run', |
| 233 | + file='{experiment_run_dir}/log.simpleFoam') |
| 234 | + |
| 235 | + def _define_commands(self, exec_graph): |
| 236 | + export_prefix = self.expander.expand_var_name('export_prefix') |
| 237 | + export_vars = self.expander.expand_var_name('export_variables').split(',') |
| 238 | + |
| 239 | + export_args = [] |
| 240 | + for var in export_vars: |
| 241 | + export_args.append(f'{export_prefix} {var}') |
| 242 | + |
| 243 | + export_str = " ".join(export_args) |
| 244 | + |
| 245 | + self.define_variable('workload_exports', export_str) |
| 246 | + |
| 247 | + super()._define_commands(exec_graph) |
0 commit comments