|
| 1 | +#!/usr/bin/env python-cubit |
| 2 | +# |
| 3 | +# creates a quad mesh for all surfaces |
| 4 | +# |
| 5 | +from __future__ import print_function |
| 6 | +import os |
| 7 | +import sys |
| 8 | + |
| 9 | +# to run this script from command line, python must have its PATH environment set such that it |
| 10 | +# includes the path to CUBIT/Trelis (cubit.py). |
| 11 | +# |
| 12 | +# you can also explicitly set it here e.g. like: |
| 13 | +#sys.path.append('/Applications/Coreform-Cubit-2023.11.app/Contents/lib') |
| 14 | + |
| 15 | +try: |
| 16 | + import cubit |
| 17 | +except ImportError: |
| 18 | + print("Error: Importing cubit as python module failed") |
| 19 | + print("could not import cubit, please check your PYTHONPATH settings...") |
| 20 | + print("") |
| 21 | + print("current path: ") |
| 22 | + print(sys.path) |
| 23 | + print("") |
| 24 | + print("try to include path to directory which includes file cubit.py, e.g. /opt/Trelis-15.0/bin/") |
| 25 | + print("") |
| 26 | + sys.exit("Import cubit failed") |
| 27 | + |
| 28 | +####################################################################### |
| 29 | +# USER PARAMETERS |
| 30 | + |
| 31 | +# small curve length threshold |
| 32 | +THRESHOLD_CURVE_LENGTH = 1.0 |
| 33 | + |
| 34 | +# mesh minimum element size |
| 35 | +# hi-res |
| 36 | +#elem_size_min = 1.0 |
| 37 | +# low-res |
| 38 | +elem_size_min = 10.0 |
| 39 | + |
| 40 | +# mesh maximum element size |
| 41 | +# hi-res |
| 42 | +#elem_size_max = 5.0 |
| 43 | +# low-res |
| 44 | +elem_size_max = 25.0 # must be <= 25 |
| 45 | + |
| 46 | +####################################################################### |
| 47 | + |
| 48 | +#debug |
| 49 | +#print(sys.path) |
| 50 | + |
| 51 | +# initializes cubit |
| 52 | +cubit.init(["-noecho","-nojournal"]) |
| 53 | + |
| 54 | +# gets version string |
| 55 | +cubit_version = cubit.get_version() |
| 56 | +print("# version: ",cubit_version) |
| 57 | + |
| 58 | +# extracts major number |
| 59 | +v = cubit_version.split('.') |
| 60 | +cubit_version_major = int(v[0]) |
| 61 | +print("# major version number: ",cubit_version_major) |
| 62 | + |
| 63 | +# current work directory |
| 64 | +cubit.cmd('pwd') |
| 65 | +cubit.cmd('reset') |
| 66 | + |
| 67 | +#checks if new file available |
| 68 | +if not os.path.exists("mesh_1_surfaces.cub"): |
| 69 | + print("#") |
| 70 | + print("# file mesh_1_surfaces.cub not found, please check ...") |
| 71 | + print("#") |
| 72 | + cubit.cmd('pause') |
| 73 | +cubit.cmd('open "mesh_1_surfaces.cub"') |
| 74 | + |
| 75 | + |
| 76 | +# surface count |
| 77 | +nsurf = cubit.get_surface_count() |
| 78 | +print("#") |
| 79 | +print("# number of surfaces = ",nsurf) |
| 80 | +if nsurf != 435: |
| 81 | + print("Error: wrong number of surfaces, must be 435 for this Marmousi model") |
| 82 | + cubit.cmd('pause') |
| 83 | +else: |
| 84 | + print("# surface number okay") |
| 85 | +print("#") |
| 86 | + |
| 87 | +# note: the imprint and merge commands will create a very small curve (0.15m length) |
| 88 | +# due to an offset at one of the faults. |
| 89 | +# |
| 90 | +# this small curve is a challenge for meshing, as it will create distorted elements |
| 91 | +# |
| 92 | +# small curves |
| 93 | +surface_list = [] |
| 94 | +small_curve_list = [] |
| 95 | +for i in range(1,nsurf+1): |
| 96 | + #print("surface: ",i) |
| 97 | + curves = cubit.get_relatives("surface",i,"curve") |
| 98 | + has_small_curve = 0 |
| 99 | + min_length = 1.e30 |
| 100 | + min_curve = 0 |
| 101 | + for c in curves: |
| 102 | + length = cubit.get_curve_length(c) |
| 103 | + # stores curve if below threshold |
| 104 | + if length < THRESHOLD_CURVE_LENGTH: |
| 105 | + has_small_curve = 1 |
| 106 | + # total minimum length |
| 107 | + if length < min_length: |
| 108 | + min_length = length |
| 109 | + min_curve = c |
| 110 | + if c not in small_curve_list: |
| 111 | + small_curve_list.append(c) |
| 112 | + #print("curve: ",c," is smaller than threshold and has length = ",length) |
| 113 | + # stores surface if it contains a small curve |
| 114 | + if has_small_curve == 1: |
| 115 | + #print("# surface: ",i) |
| 116 | + #print("# has small curves of minimum length ",min_length) |
| 117 | + #print("#") |
| 118 | + surface_list.append([i,min_curve,min_length]) |
| 119 | + |
| 120 | +# output |
| 121 | +if len(surface_list) > 0: |
| 122 | + print("# small feature surfaces:") |
| 123 | + for s in surface_list: |
| 124 | + print("# surface ",s[0]," has curve ",s[1]," with minimum length ",s[2]) |
| 125 | + print("#") |
| 126 | + |
| 127 | +# collapses minimum curves |
| 128 | +# will not work for current topology... |
| 129 | +if len(small_curve_list) > 0: |
| 130 | + print("# small curves:") |
| 131 | + for c in small_curve_list: |
| 132 | + vert = cubit.get_relatives("curve",c,"vertex") |
| 133 | + print("# curve ",c," has vertices ",vert) |
| 134 | + # not working... |
| 135 | + #cubit.cmd('collapse curve '+str(c)+' vertex '+str(vert[0])) |
| 136 | + print("#") |
| 137 | + |
| 138 | +# removing small curves |
| 139 | +# will not work... |
| 140 | +#cubit.cmd('tweak remove_topology curve all small_curve_size 0.5 backoff_distance 1') |
| 141 | + |
| 142 | +# validation (closed surface?) |
| 143 | +cubit.cmd('validate surface all') |
| 144 | + |
| 145 | +# curve count |
| 146 | +#n = cubit.get_curve_count() |
| 147 | +#print("") |
| 148 | +#print("# number of curves = ",n) |
| 149 | +#print("") |
| 150 | + |
| 151 | +# skew control will fail... |
| 152 | +#cubit.cmd('control skew surface all') |
| 153 | + |
| 154 | +######################################################################## |
| 155 | +# meshing |
| 156 | + |
| 157 | +# paving |
| 158 | +cubit.cmd('surface all scheme pave') |
| 159 | + |
| 160 | +#original |
| 161 | +cubit.cmd('surface 186 size '+str(elem_size_min)) # otherwise a meshing error occurs.. |
| 162 | +cubit.cmd('surface all except 186 size '+str(elem_size_max)) |
| 163 | + |
| 164 | + |
| 165 | +# geometry adaptive |
| 166 | +#cubit.silent_cmd('surface all sizing function type skeleton' + \ |
| 167 | +# ' min_size '+ str(elem_size_min) + \ |
| 168 | +# ' max_size ' + str(elem_size_max) + \ |
| 169 | +# ' max_gradient 1.0 min_num_layers_2d 1 min_num_layers_1d 1') |
| 170 | + |
| 171 | + |
| 172 | +# problematic surface |
| 173 | +if 0 == 1: |
| 174 | + # large curve |
| 175 | + cubit.cmd('curve 227 to 229 size ' + str(elem_size)) |
| 176 | + cubit.cmd('curve 227 to 229 scheme equal') |
| 177 | + cubit.cmd('mesh curve 227 to 229') |
| 178 | + # progressive sizes |
| 179 | + cubit.cmd('curve 230 scheme bias fine size 0.2 coarse size ' + str(elem_size) + ' start vertex 290') |
| 180 | + cubit.cmd('mesh curve 230') |
| 181 | + # small curve |
| 182 | + cubit.cmd('curve 231 size 1') |
| 183 | + cubit.cmd('curve 231 scheme equal') |
| 184 | + cubit.cmd('mesh curve 231') |
| 185 | + # progressive sizes |
| 186 | + cubit.cmd('curve 581 scheme bias fine size 0.2 coarse size ' + str(elem_size) + ' start vertex 291') |
| 187 | + cubit.cmd('mesh curve 581') |
| 188 | + |
| 189 | + # problematic surfaces |
| 190 | + cubit.cmd('mesh surface 149') |
| 191 | + cubit.cmd('quality surface 149 condition no. global') |
| 192 | +#else: |
| 193 | + #cubit.cmd('mesh surface 149') |
| 194 | + #cubit.cmd('quality surface 149 condition no. global') |
| 195 | + |
| 196 | +# meshes small curves |
| 197 | +if 0 == 1: |
| 198 | + for c in small_curve_list: |
| 199 | + length = cubit.get_curve_length(c) |
| 200 | + print("# meshing small curve: ",c,"length = ",length," - mesh size min/max = ",elem_size_min,elem_size_max) |
| 201 | + if length < elem_size_min: |
| 202 | + # equal sizes |
| 203 | + cubit.cmd('curve ' + str(c) + ' size ' + str(elem_size_min)) |
| 204 | + cubit.cmd('curve ' + str(c) + ' scheme equal') |
| 205 | + else: |
| 206 | + # equal sizes |
| 207 | + cubit.cmd('curve ' + str(c) + ' size ' + str(elem_size_max)) |
| 208 | + cubit.cmd('curve ' + str(c) + ' scheme equal') |
| 209 | + |
| 210 | + # progressive sizes |
| 211 | + #vert = cubit.get_relatives("curve",c,"vertex") |
| 212 | + #cubit.cmd('curve ' + str(c) + ' scheme bias' + \ |
| 213 | + # ' fine size ' + str(elem_size_min) + \ |
| 214 | + # ' coarse size ' + str(elem_size_max) + ' start vertex ' + str(vert[0])) |
| 215 | + cubit.cmd('mesh curve ' + str(c)) |
| 216 | + |
| 217 | +def mesh_surface(i,elem_size_min,elem_size_max): |
| 218 | + """ |
| 219 | + meshes a surface |
| 220 | + """ |
| 221 | + print("# meshing surface: ",i) |
| 222 | + #print("# surface area = ",cubit.get_surface_area(i)) |
| 223 | + if cubit.is_meshed("surface",i): |
| 224 | + print("# already done") |
| 225 | + print("#") |
| 226 | + return |
| 227 | + |
| 228 | + elem_size1 = elem_size_min |
| 229 | + elem_size2 = elem_size_max |
| 230 | + cubit.cmd('mesh surface '+str(i)) |
| 231 | + # retry if there was an error |
| 232 | + itry = 0 |
| 233 | + while cubit.get_error_count() > 0 and itry < 8: |
| 234 | + # retry with smaller size |
| 235 | + #cubit.cmd('delete mesh surface '+str(i)+' propagate') |
| 236 | + cubit.cmd('delete mesh surface '+str(i)) |
| 237 | + cubit.cmd('reset errors') |
| 238 | + itry += 1 |
| 239 | + elem_size2 = elem_size2 / 2.0 |
| 240 | + print("# ",itry,"retrying with maximum element size = ",elem_size2) |
| 241 | + cubit.cmd('surface '+str(i)+' size '+str(elem_size2)) |
| 242 | + |
| 243 | + # geometry adaptive |
| 244 | + #if elem_size1 > elem_size2: |
| 245 | + # elem_size1 = elem_size2 |
| 246 | + # cubit.cmd('surface '+str(i)+' size '+str(elem_size1)) |
| 247 | + #else: |
| 248 | + # cubit.cmd('surface '+str(i)+' sizing function type skeleton min_size '+str(elem_size1) + ' max_size '+str(elem_size2) + ' max_gradient 2.0 min_num_layers_2d 1 min_num_layers_1d 1') |
| 249 | + cubit.cmd('mesh surface '+str(i)) |
| 250 | + |
| 251 | + # check mesh |
| 252 | + if 0 == 1: |
| 253 | + #cubit.cmd('group "myfaces" add face in surface ' + str(i)) |
| 254 | + #group1 = cubit.get_id_from_name("myfaces") |
| 255 | + #quads = cubit.get_group_quads(group1) |
| 256 | + #print("# mesh quads ",quads) |
| 257 | + #for j in quads: |
| 258 | + # print("# mesh quad ",j) |
| 259 | + #not working... |
| 260 | + #print("# mesh condition number quality = ",cubit.get_quality_value("quad",group1,"condition")) |
| 261 | + #print("# mesh skew quality = ",cubit.get_quality_value("quad",group1,"skew")) |
| 262 | + #print("# mesh shape quality = ",cubit.get_quality_value("quad",group1,"shape")) |
| 263 | + #print("") |
| 264 | + #cubit.cmd('del group myfaces') |
| 265 | + # counts quads with low shape metric (between 0 and 0.1) |
| 266 | + shape_min = 0.0 |
| 267 | + shape_max = 0.01 |
| 268 | + # |
| 269 | + cubit.silent_cmd('group "poor" add quality surface ' + str(i) + \ |
| 270 | + ' shape low ' + str(shape_min) + ' high ' + str(shape_max)) |
| 271 | + group2 = cubit.get_id_from_name("poor") |
| 272 | + quads = cubit.get_group_quads(group2) |
| 273 | + cubit.delete_group(group2) |
| 274 | + print("# number of quads with poor shape = ",len(quads)) |
| 275 | + print("#") |
| 276 | + # retry |
| 277 | + itry = 0 |
| 278 | + while len(quads) > 0 and itry < 8: |
| 279 | + # retry with smaller size |
| 280 | + #cubit.cmd('delete mesh surface '+str(i)+' propagate') |
| 281 | + cubit.cmd('delete mesh surface '+str(i)) |
| 282 | + itry += 1 |
| 283 | + elem_size2 = elem_size2 / 2.0 |
| 284 | + print("# ",itry,"retrying with maximum element size = ",elem_size2) |
| 285 | + if elem_size1 > elem_size2: |
| 286 | + elem_size1 = elem_size2 |
| 287 | + cubit.cmd('surface '+str(i)+' size '+str(elem_size1)) |
| 288 | + else: |
| 289 | + cubit.cmd('surface '+str(i)+' sizing function type skeleton min_size '+str(elem_size1) + ' max_size '+str(elem_size2) + ' max_gradient 2.0 min_num_layers_2d 1 min_num_layers_1d 1') |
| 290 | + cubit.cmd('mesh surface '+str(i)) |
| 291 | + # check mesh |
| 292 | + cubit.silent_cmd('group "poor" add quality surface ' + str(i) + \ |
| 293 | + ' shape low ' + str(shape_min) + ' high ' + str(shape_max)) |
| 294 | + group2 = cubit.get_id_from_name("poor") |
| 295 | + quads = cubit.get_group_quads(group2) |
| 296 | + cubit.delete_group(group2) |
| 297 | + print("# number of quads with poor shape = ",len(quads)) |
| 298 | + print("") |
| 299 | + |
| 300 | + # safety check |
| 301 | + if cubit.get_error_count() > 0: |
| 302 | + print("# mesh: generated error") |
| 303 | + print("#") |
| 304 | + cubit.cmd('stop') |
| 305 | + sys.exit(1) |
| 306 | + |
| 307 | + |
| 308 | +cubit.cmd('reset errors') |
| 309 | + |
| 310 | +# small curve surface meshing |
| 311 | +#for s in surface_list: |
| 312 | +# i = s[0] |
| 313 | +# print('# surface with small curve ',i) |
| 314 | +# mesh_surface(i,elem_size_min,elem_size_max) |
| 315 | + |
| 316 | +# gets list |
| 317 | +surface_area = [] |
| 318 | +for i in range(1,nsurf+1): |
| 319 | + area = cubit.get_surface_area(i) |
| 320 | + surface_area.append(area) |
| 321 | + |
| 322 | +# gets index of sorted areas |
| 323 | +surface_sorted = [i[0] for i in sorted(enumerate(surface_area), key=lambda x:x[1])] |
| 324 | +icount = 0 |
| 325 | +for i in surface_sorted: |
| 326 | + icount += 1 |
| 327 | + # surface id = list id + 1 |
| 328 | + id = i + 1 |
| 329 | + print("# ",icount," surface ",id,"area = ",surface_area[i]) |
| 330 | + #mesh_surface(id,elem_size_min,elem_size_max) |
| 331 | + |
| 332 | +cubit.cmd('mesh surface all') |
| 333 | + |
| 334 | +# checks if all surfaces are meshed |
| 335 | +for i in range(1,nsurf+1): |
| 336 | + if not cubit.is_meshed("surface",i): |
| 337 | + print("# mesh failed for surface ",i) |
| 338 | + print("#") |
| 339 | + sys.exit(1) |
| 340 | + else: |
| 341 | + print("# meshed surface ",i) |
| 342 | + |
| 343 | +# error check |
| 344 | +if cubit.get_error_count() > 0: |
| 345 | + print("#") |
| 346 | + print("# mesh: generated errors, aborting... ") |
| 347 | + print("#") |
| 348 | + cubit.cmd('stop') |
| 349 | + sys.exit(1) |
| 350 | +else: |
| 351 | + print("#") |
| 352 | + print("# mesh: all done") |
| 353 | + print("#") |
| 354 | + |
| 355 | + |
| 356 | +# warning info - not supported anymore... |
| 357 | +#if cubit.get_warning_count() > 0: |
| 358 | +# print("") |
| 359 | +# print("meshing generated warnings: ",n) |
| 360 | +# print("") |
| 361 | + |
| 362 | +# validate |
| 363 | +cubit.cmd('validate surface all mesh') |
| 364 | + |
| 365 | +#c_min = cubit.get_quality_value("QUAD",149,"condition no") |
| 366 | +#print("") |
| 367 | +#print("# mesh: minimum surface mesh quality value = ",c_min) |
| 368 | +#print("") |
| 369 | + |
| 370 | +print("#") |
| 371 | +print("# mesh: total number of QUAD elements = ",cubit.get_quad_count()) |
| 372 | +print("#") |
| 373 | + |
| 374 | +# mesh quality summary |
| 375 | +cubit.cmd('quality surface all condition no. global') |
| 376 | +print('#') |
| 377 | + |
| 378 | +# save |
| 379 | +cubit.cmd('save as "mesh_2_marmousi.cub" overwrite') |
| 380 | + |
| 381 | +print("#") |
| 382 | +print("# done: see file mesh_2_marmousi.cub") |
| 383 | +print("#") |
| 384 | + |
0 commit comments