Coverage for src/beamme/mesh_creation_functions/nurbs_generic.py: 96%

193 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-30 18:48 +0000

1# The MIT License (MIT) 

2# 

3# Copyright (c) 2018-2025 BeamMe Authors 

4# 

5# Permission is hereby granted, free of charge, to any person obtaining a copy 

6# of this software and associated documentation files (the "Software"), to deal 

7# in the Software without restriction, including without limitation the rights 

8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 

9# copies of the Software, and to permit persons to whom the Software is 

10# furnished to do so, subject to the following conditions: 

11# 

12# The above copyright notice and this permission notice shall be included in 

13# all copies or substantial portions of the Software. 

14# 

15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 

16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 

17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 

18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 

19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 

20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 

21# THE SOFTWARE. 

22"""Generic function used to create NURBS meshes.""" 

23 

24from typing import Type as _Type 

25 

26from beamme.core.conf import mpy as _mpy 

27from beamme.core.geometry_set import GeometryName as _GeometryName 

28from beamme.core.geometry_set import GeometrySetNodes as _GeometrySetNodes 

29from beamme.core.mesh import Mesh as _Mesh 

30from beamme.core.node import ControlPoint as _ControlPoint 

31from beamme.core.nurbs_patch import NURBSSurface as _NURBSSurface 

32from beamme.core.nurbs_patch import NURBSVolume as _NURBSVolume 

33 

34 

35def add_splinepy_nurbs_to_mesh( 

36 mesh: _Mesh, 

37 splinepy_obj, 

38 *, 

39 material=None, 

40 data: dict | None = None, 

41) -> _GeometryName: 

42 """Add a splinepy NURBS to the mesh. 

43 

44 Args: 

45 mesh: Mesh that the created NURBS geometry will be added to. 

46 splinepy_obj (splinepy object): NURBS geometry created using splinepy. 

47 material (Material): Material for this geometry. 

48 data: General element data, e.g., material, formulation, ... 

49 

50 Returns: 

51 GeometryName: 

52 Set with the control points that form the topology of the mesh. 

53 

54 For a surface, the following information is stored: 

55 Vertices: 'vertex_u_min_v_min', 'vertex_u_max_v_min', 'vertex_u_min_v_max', 'vertex_u_max_v_max' 

56 Edges: 'line_v_min', 'line_u_max', 'line_v_max', 'line_u_min' 

57 Surface: 'surf' 

58 

59 For a volume, the following information is stored: 

60 Vertices: 'vertex_u_min_v_min_w_min', 'vertex_u_max_v_min_w_min', 'vertex_u_min_v_max_w_min', 'vertex_u_max_v_max_w_min', 

61 'vertex_u_min_v_min_w_max', 'vertex_u_max_v_min_w_max', 'vertex_u_min_v_max_w_max', 'vertex_u_max_v_max_w_max' 

62 Edges: 'line_v_min_w_min', 'line_u_max_w_min', 'line_v_max_w_min', 'line_u_min_w_min', 

63 'line_u_min_v_min', 'line_u_max_v_min', 'line_u_min_v_max', 'line_u_max_v_max' 

64 'line_v_min_w_max', 'line_u_max_w_max', 'line_v_max_w_max', 'line_u_min_w_max' 

65 Surfaces: 'surf_w_min', 'surf_w_max', 'surf_v_min', 'surf_v_max', 'surf_v_max', 'surf_u_min' 

66 Volume: 'vol' 

67 """ 

68 

69 # Make sure the material is in the mesh 

70 mesh.add_material(material) 

71 

72 # Fill control points 

73 control_points = [ 

74 _ControlPoint(coord, weight[0]) 

75 for coord, weight in zip(splinepy_obj.control_points, splinepy_obj.weights) 

76 ] 

77 

78 # Fill element 

79 manifold_dim = len(splinepy_obj.knot_vectors) 

80 nurbs_object: _Type[_NURBSSurface] | _Type[_NURBSVolume] 

81 if manifold_dim == 2: 

82 nurbs_object = _NURBSSurface 

83 elif manifold_dim == 3: 

84 nurbs_object = _NURBSVolume 

85 else: 

86 raise NotImplementedError( 

87 "Error, not implemented for a NURBS {}!".format(type(splinepy_obj)) 

88 ) 

89 

90 element = nurbs_object( 

91 splinepy_obj.knot_vectors, 

92 splinepy_obj.degrees, 

93 nodes=control_points, 

94 material=material, 

95 data=data, 

96 ) 

97 

98 # Add element and control points to the mesh 

99 mesh.elements.append(element) 

100 mesh.nodes.extend(control_points) 

101 

102 # Create geometry sets that will be returned 

103 return_set = create_geometry_sets(element) 

104 

105 return return_set 

106 

107 

108def add_geomdl_nurbs_to_mesh( 

109 mesh: _Mesh, 

110 geomdl_obj, 

111 *, 

112 material=None, 

113 data: dict | None = None, 

114) -> _GeometryName: 

115 """Add a geomdl NURBS to the mesh. 

116 

117 Args: 

118 mesh: Mesh that the created NURBS geometry will be added to. 

119 geomdl_obj (geomdl object): NURBS geometry created using geomdl. 

120 material (Material): Material for this geometry. 

121 data: General element data, e.g., material, formulation, ... 

122 

123 Returns: 

124 GeometryName: 

125 Set with the control points that form the topology of the mesh. 

126 

127 For a surface, the following information is stored: 

128 Vertices: 'vertex_u_min_v_min', 'vertex_u_max_v_min', 'vertex_u_min_v_max', 'vertex_u_max_v_max' 

129 Edges: 'line_v_min', 'line_u_max', 'line_v_max', 'line_u_min' 

130 Surface: 'surf' 

131 

132 For a volume, the following information is stored: 

133 Vertices: 'vertex_u_min_v_min_w_min', 'vertex_u_max_v_min_w_min', 'vertex_u_min_v_max_w_min', 'vertex_u_max_v_max_w_min', 

134 'vertex_u_min_v_min_w_max', 'vertex_u_max_v_min_w_max', 'vertex_u_min_v_max_w_max', 'vertex_u_max_v_max_w_max' 

135 Edges: 'line_v_min_w_min', 'line_u_max_w_min', 'line_v_max_w_min', 'line_u_min_w_min', 

136 'line_u_min_v_min', 'line_u_max_v_min', 'line_u_min_v_max', 'line_u_max_v_max' 

137 'line_v_min_w_max', 'line_u_max_w_max', 'line_v_max_w_max', 'line_u_min_w_max' 

138 Surfaces: 'surf_w_min', 'surf_w_max', 'surf_v_min', 'surf_v_max', 'surf_v_max', 'surf_u_min' 

139 Volume: 'vol' 

140 """ 

141 

142 # Make sure the material is in the mesh 

143 mesh.add_material(material) 

144 

145 # Fill control points 

146 control_points = [] 

147 nurbs_dimension = len(geomdl_obj.knotvector) 

148 if nurbs_dimension == 2: 

149 control_points = create_control_points_surface(geomdl_obj) 

150 elif nurbs_dimension == 3: 

151 control_points = create_control_points_volume(geomdl_obj) 

152 else: 

153 raise NotImplementedError( 

154 "Error, not implemented for NURBS with dimension {}!".format( 

155 nurbs_dimension 

156 ) 

157 ) 

158 

159 # Fill element 

160 manifold_dim = len(geomdl_obj.knotvector) 

161 nurbs_object: _Type[_NURBSSurface] | _Type[_NURBSVolume] 

162 if manifold_dim == 2: 

163 nurbs_object = _NURBSSurface 

164 elif manifold_dim == 3: 

165 nurbs_object = _NURBSVolume 

166 else: 

167 raise NotImplementedError( 

168 "Error, not implemented for a NURBS {}!".format(type(geomdl_obj)) 

169 ) 

170 

171 element = nurbs_object( 

172 geomdl_obj.knotvector, 

173 geomdl_obj.degree, 

174 nodes=control_points, 

175 material=material, 

176 data=data, 

177 ) 

178 

179 # Add element and control points to the mesh 

180 mesh.elements.append(element) 

181 mesh.nodes.extend(control_points) 

182 

183 # Create geometry sets that will be returned 

184 return_set = create_geometry_sets(element) 

185 

186 return return_set 

187 

188 

189def create_control_points_surface(geomdl_obj): 

190 """Creates a list with the ControlPoint objects of a surface created with 

191 geomdl.""" 

192 control_points = [] 

193 for dir_v in range(geomdl_obj.ctrlpts_size_v): 

194 for dir_u in range(geomdl_obj.ctrlpts_size_u): 

195 weight = geomdl_obj.ctrlpts2d[dir_u][dir_v][3] 

196 

197 # As the control points are scaled with their weight, divide them to get 

198 # their coordinates 

199 coord = [ 

200 geomdl_obj.ctrlpts2d[dir_u][dir_v][0] / weight, 

201 geomdl_obj.ctrlpts2d[dir_u][dir_v][1] / weight, 

202 geomdl_obj.ctrlpts2d[dir_u][dir_v][2] / weight, 

203 ] 

204 

205 control_points.append(_ControlPoint(coord, weight)) 

206 

207 return control_points 

208 

209 

210def create_control_points_volume(geomdl_obj): 

211 """Creates a list with the ControlPoint objects of a volume created with 

212 geomdl.""" 

213 control_points = [] 

214 for dir_w in range(geomdl_obj.ctrlpts_size_w): 

215 for dir_v in range(geomdl_obj.ctrlpts_size_v): 

216 for dir_u in range(geomdl_obj.ctrlpts_size_u): 

217 # Obtain the id of the control point 

218 cp_id = ( 

219 dir_v 

220 + geomdl_obj.ctrlpts_size_v * dir_u 

221 + geomdl_obj.ctrlpts_size_u * geomdl_obj.ctrlpts_size_v * dir_w 

222 ) 

223 

224 weight = geomdl_obj.ctrlptsw[cp_id][3] 

225 

226 # As the control points are scaled with their weight, divide them to get 

227 # their coordinates 

228 coord = [ 

229 geomdl_obj.ctrlptsw[cp_id][0] / weight, 

230 geomdl_obj.ctrlptsw[cp_id][1] / weight, 

231 geomdl_obj.ctrlptsw[cp_id][2] / weight, 

232 ] 

233 

234 control_points.append(_ControlPoint(coord, weight)) 

235 

236 return control_points 

237 

238 

239def create_geometry_sets(element: _NURBSSurface | _NURBSVolume) -> _GeometryName: 

240 """Function that returns a GeometryName object. 

241 

242 For more information of the return item, look into 

243 `add_splinepy_nurbs_to_mesh` and `add_geomdl_nurbs_to_mesh`. 

244 """ 

245 

246 def get_patch_vertices(return_set, num_cps_uvw, nurbs_dimension, element): 

247 """Get the control points positioned over the vertices of a patch.""" 

248 

249 if nurbs_dimension == 2: 

250 # Vertex 1 is positioned on u = 0, v = 0 

251 return_set["vertex_u_min_v_min"] = _GeometrySetNodes( 

252 _mpy.geo.point, nodes=element.nodes[0] 

253 ) 

254 

255 # Vertex 2 is positioned on u = 1, v = 0 

256 return_set["vertex_u_max_v_min"] = _GeometrySetNodes( 

257 _mpy.geo.point, nodes=element.nodes[num_cps_uvw[0] - 1] 

258 ) 

259 

260 # Vertex 3 is positioned on u = 0, v = 1 

261 return_set["vertex_u_min_v_max"] = _GeometrySetNodes( 

262 _mpy.geo.point, 

263 nodes=element.nodes[num_cps_uvw[0] * (num_cps_uvw[1] - 1)], 

264 ) 

265 

266 # Vertex 4 is positioned on u = 1, v = 1 

267 return_set["vertex_u_max_v_max"] = _GeometrySetNodes( 

268 _mpy.geo.point, nodes=element.nodes[num_cps_uvw[0] * num_cps_uvw[1] - 1] 

269 ) 

270 

271 elif nurbs_dimension == 3: 

272 # Vertex 1 is positioned on u = 0, v = 0, w = 

273 return_set["vertex_u_min_v_min_w_min"] = _GeometrySetNodes( 

274 _mpy.geo.point, nodes=element.nodes[0] 

275 ) 

276 

277 # Vertex 2 is positioned on u = 1, v = 0, w = 0 

278 return_set["vertex_u_max_v_min_w_min"] = _GeometrySetNodes( 

279 _mpy.geo.point, nodes=element.nodes[num_cps_uvw[0] - 1] 

280 ) 

281 

282 # Vertex 3 is positioned on u = 0, v = 1, w = 0 

283 return_set["vertex_u_min_v_max_w_min"] = _GeometrySetNodes( 

284 _mpy.geo.point, 

285 nodes=element.nodes[num_cps_uvw[0] * (num_cps_uvw[1] - 1)], 

286 ) 

287 

288 # Vertex 4 is positioned on u = 1, v = 1, w = 0 

289 return_set["vertex_u_max_v_max_w_min"] = _GeometrySetNodes( 

290 _mpy.geo.point, nodes=element.nodes[num_cps_uvw[0] * num_cps_uvw[1] - 1] 

291 ) 

292 

293 # Vertex 5 is positioned on u = 0, v = 0, w = 1 

294 return_set["vertex_u_min_v_min_w_max"] = _GeometrySetNodes( 

295 _mpy.geo.point, 

296 nodes=element.nodes[ 

297 num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) 

298 ], 

299 ) 

300 

301 # Vertex 6 is positioned on u = 1, v = 0, w = 1 

302 return_set["vertex_u_max_v_min_w_max"] = _GeometrySetNodes( 

303 _mpy.geo.point, 

304 nodes=element.nodes[ 

305 num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) 

306 + (num_cps_uvw[0] - 1) 

307 ], 

308 ) 

309 

310 # Vertex 7 is positioned on u = 0, v = 1, w = 1 

311 return_set["vertex_u_min_v_max_w_max"] = _GeometrySetNodes( 

312 _mpy.geo.point, 

313 nodes=element.nodes[ 

314 num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) 

315 + num_cps_uvw[0] * (num_cps_uvw[1] - 1) 

316 ], 

317 ) 

318 

319 # Vertex 8 is positioned on u = 1, v = 1, w = 1 

320 return_set["vertex_u_max_v_max_w_max"] = _GeometrySetNodes( 

321 _mpy.geo.point, 

322 nodes=element.nodes[ 

323 num_cps_uvw[0] * num_cps_uvw[1] * num_cps_uvw[2] - 1 

324 ], 

325 ) 

326 

327 else: 

328 raise NotImplementedError( 

329 "Error, not implemented for NURBS with dimension {}!".format( 

330 nurbs_dimension 

331 ) 

332 ) 

333 

334 def get_patch_lines(return_set, num_cps_uvw, nurbs_dimension, element): 

335 """Get the control points positioned over the lines of a patch.""" 

336 

337 if nurbs_dimension == 2: 

338 name_dir = ["v", "u"] 

339 name_other_dir = ["min", "min_next", "max_next", "max"] 

340 

341 for i_dir, i_other_dir in ((0, 1), (1, 0)): 

342 n_cp_dir = num_cps_uvw[i_dir] 

343 n_cp_other_dir = num_cps_uvw[i_other_dir] 

344 factor_dir = 1 if i_dir == 0 else n_cp_other_dir 

345 factor_other_dir = n_cp_dir if i_dir == 0 else 1 

346 

347 for index, i_along_other_dir in enumerate( 

348 ( 

349 0, 

350 1, 

351 n_cp_other_dir - 2, 

352 n_cp_other_dir - 1, 

353 ) 

354 ): 

355 cp_indices = [] 

356 for i_along_dir in range(n_cp_dir): 

357 cp_indices.append( 

358 i_along_other_dir * factor_other_dir 

359 + i_along_dir * factor_dir 

360 ) 

361 set_name = f"line_{name_dir[i_dir]}_{name_other_dir[index]}" 

362 return_set[set_name] = _GeometrySetNodes( 

363 _mpy.geo.line, 

364 nodes=[element.nodes[i_node] for i_node in cp_indices], 

365 ) 

366 

367 elif nurbs_dimension == 3: 

368 # Define the rest of the lines to define a volume 

369 control_points_line_1 = [] 

370 control_points_line_2 = [] 

371 control_points_line_3 = [] 

372 control_points_line_4 = [] 

373 control_points_line_5 = [] 

374 control_points_line_6 = [] 

375 control_points_line_7 = [] 

376 control_points_line_8 = [] 

377 control_points_line_9 = [] 

378 control_points_line_10 = [] 

379 control_points_line_11 = [] 

380 control_points_line_12 = [] 

381 

382 # Fill line 1, 3, 9 and 11 with their control points 

383 for i in range(num_cps_uvw[0]): 

384 # Line 1 has the control points on u = [0,1], v = 0, w = 0 

385 cpgid_l1 = num_cps_uvw[0] * 0 + i 

386 control_points_line_1.append(element.nodes[cpgid_l1]) 

387 

388 # Line 3 has the control points on u = [0,1], v = 1, w = 0 

389 cpgid_l3 = num_cps_uvw[0] * (num_cps_uvw[1] - 1) + i 

390 control_points_line_3.append(element.nodes[cpgid_l3]) 

391 

392 # Line 9 has the control points on u = [0,1], v = 0, w = 1 

393 cpgid_l9 = num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) + i 

394 control_points_line_9.append(element.nodes[cpgid_l9]) 

395 

396 # Line 11 has the control points on u = [0,1], v = 1, w = 1 

397 cpgid_l11 = ( 

398 num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) 

399 + num_cps_uvw[0] * (num_cps_uvw[1] - 1) 

400 + i 

401 ) 

402 control_points_line_11.append(element.nodes[cpgid_l11]) 

403 

404 # Fill line 2, 4, 10 and 12 with their control points 

405 for j in range(num_cps_uvw[1]): 

406 # Line 2 has the control points on u = 1, v = [0,1] , w = 0 

407 cpgid_l2 = num_cps_uvw[0] * j + (num_cps_uvw[0] - 1) 

408 control_points_line_2.append(element.nodes[cpgid_l2]) 

409 

410 # Line 4 has the control points on u = 0, v = [0,1] , w = 0 

411 cpgid_l4 = num_cps_uvw[0] * j + 0 

412 control_points_line_4.append(element.nodes[cpgid_l4]) 

413 

414 # Line 10 has the control points on u = 1, v = [0,1] , w = 1 

415 cpgid_l10 = ( 

416 num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) 

417 + num_cps_uvw[0] * j 

418 + (num_cps_uvw[0] - 1) 

419 ) 

420 control_points_line_10.append(element.nodes[cpgid_l10]) 

421 

422 # Line 12 has the control points on u = 0, v = [0,1] , w = 1 

423 cpgid_l12 = ( 

424 num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) 

425 + num_cps_uvw[0] * j 

426 ) 

427 control_points_line_12.append(element.nodes[cpgid_l12]) 

428 

429 # Fill line 5, 6, 7 and 8 with their control points 

430 for k in range(num_cps_uvw[2]): 

431 # Line 5 has the control points on u = 0, v = 0 , w = [0,1] 

432 cpgid_l5 = num_cps_uvw[0] * num_cps_uvw[1] * k 

433 control_points_line_5.append(element.nodes[cpgid_l5]) 

434 

435 # Line 6 has the control points on u = 1, v = 0 , w = [0,1] 

436 cpgid_l6 = num_cps_uvw[0] * num_cps_uvw[1] * k + num_cps_uvw[0] - 1 

437 control_points_line_6.append(element.nodes[cpgid_l6]) 

438 

439 # Line 7 has the control points on u = 0, v = 1 , w = [0,1] 

440 cpgid_l7 = num_cps_uvw[0] * num_cps_uvw[1] * k + num_cps_uvw[0] * ( 

441 num_cps_uvw[1] - 1 

442 ) 

443 control_points_line_7.append(element.nodes[cpgid_l7]) 

444 

445 # Line 8 has the control points on u = 1, v = 1 , w = [0,1] 

446 cpgid_l8 = ( 

447 num_cps_uvw[0] * num_cps_uvw[1] * k 

448 + num_cps_uvw[0] * num_cps_uvw[1] 

449 - 1 

450 ) 

451 control_points_line_8.append(element.nodes[cpgid_l8]) 

452 

453 # Create geometric sets for lines 

454 return_set["line_v_min_w_min"] = _GeometrySetNodes( 

455 _mpy.geo.line, nodes=control_points_line_1 

456 ) 

457 return_set["line_u_max_w_min"] = _GeometrySetNodes( 

458 _mpy.geo.line, nodes=control_points_line_2 

459 ) 

460 return_set["line_v_max_w_min"] = _GeometrySetNodes( 

461 _mpy.geo.line, nodes=control_points_line_3 

462 ) 

463 return_set["line_u_min_w_min"] = _GeometrySetNodes( 

464 _mpy.geo.line, nodes=control_points_line_4 

465 ) 

466 return_set["line_u_min_v_min"] = _GeometrySetNodes( 

467 _mpy.geo.line, nodes=control_points_line_5 

468 ) 

469 return_set["line_u_max_v_min"] = _GeometrySetNodes( 

470 _mpy.geo.line, nodes=control_points_line_6 

471 ) 

472 return_set["line_u_min_v_max"] = _GeometrySetNodes( 

473 _mpy.geo.line, nodes=control_points_line_7 

474 ) 

475 return_set["line_u_max_v_max"] = _GeometrySetNodes( 

476 _mpy.geo.line, nodes=control_points_line_8 

477 ) 

478 return_set["line_v_min_w_max"] = _GeometrySetNodes( 

479 _mpy.geo.line, nodes=control_points_line_9 

480 ) 

481 return_set["line_u_max_w_max"] = _GeometrySetNodes( 

482 _mpy.geo.line, nodes=control_points_line_10 

483 ) 

484 return_set["line_v_max_w_max"] = _GeometrySetNodes( 

485 _mpy.geo.line, nodes=control_points_line_11 

486 ) 

487 return_set["line_u_min_w_max"] = _GeometrySetNodes( 

488 _mpy.geo.line, nodes=control_points_line_12 

489 ) 

490 

491 else: 

492 raise NotImplementedError( 

493 "Error, not implemented for NURBS with dimension {}!".format( 

494 nurbs_dimension 

495 ) 

496 ) 

497 

498 def get_patch_surfaces(return_set, num_cps_uvw, nurbs_dimension, element): 

499 """Get the control points positioned over the surfaces of a patch.""" 

500 

501 control_points_surface_1 = [] 

502 

503 if nurbs_dimension == 2: 

504 # As there is only one surface, it collects all the control points 

505 control_points_surface_1.extend( 

506 element.nodes[: (num_cps_uvw[0] * num_cps_uvw[1])] 

507 ) 

508 

509 # Create geometric sets for surfaces 

510 return_set["surf"] = _GeometrySetNodes( 

511 _mpy.geo.surface, nodes=control_points_surface_1 

512 ) 

513 

514 elif nurbs_dimension == 3: 

515 control_points_surface_2 = [] 

516 control_points_surface_3 = [] 

517 control_points_surface_4 = [] 

518 control_points_surface_5 = [] 

519 control_points_surface_6 = [] 

520 

521 # Surface defined on w = 0 

522 control_points_surface_1.extend( 

523 element.nodes[: (num_cps_uvw[0] * num_cps_uvw[1])] 

524 ) 

525 

526 # Surface defined on w = 1 

527 control_points_surface_2.extend( 

528 element.nodes[ 

529 (num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1)) : ( 

530 num_cps_uvw[0] * num_cps_uvw[1] * num_cps_uvw[2] 

531 ) 

532 ] 

533 ) 

534 

535 for layers_w_dir in range(num_cps_uvw[2]): 

536 # Calculate the number of control points on the w-plane 

537 num_cps_plane_w = num_cps_uvw[0] * num_cps_uvw[1] 

538 

539 for layers_u_dir in range(num_cps_uvw[0]): 

540 # Surface defined on v = 0 

541 cpgid_l1 = num_cps_uvw[0] * 0 + layers_u_dir 

542 control_points_surface_3.append( 

543 element.nodes[cpgid_l1 + num_cps_plane_w * layers_w_dir] 

544 ) 

545 

546 # Surface defined on v = 1 

547 cpgid_l3 = num_cps_uvw[0] * (num_cps_uvw[1] - 1) + layers_u_dir 

548 control_points_surface_5.append( 

549 element.nodes[cpgid_l3 + num_cps_plane_w * layers_w_dir] 

550 ) 

551 

552 for layers_v_dir in range(num_cps_uvw[1]): 

553 # Surface defined on u = 1 

554 cpgid_l2 = num_cps_uvw[0] * layers_v_dir + (num_cps_uvw[0] - 1) 

555 control_points_surface_4.append( 

556 element.nodes[cpgid_l2 + num_cps_plane_w * layers_w_dir] 

557 ) 

558 

559 # Surface defined on u = 0 

560 cpgid_l4 = num_cps_uvw[0] * layers_v_dir + 0 

561 control_points_surface_6.append( 

562 element.nodes[cpgid_l4 + num_cps_plane_w * layers_w_dir] 

563 ) 

564 

565 # Create geometric sets for surfaces 

566 return_set["surf_w_min"] = _GeometrySetNodes( 

567 _mpy.geo.surface, nodes=control_points_surface_1 

568 ) 

569 return_set["surf_w_max"] = _GeometrySetNodes( 

570 _mpy.geo.surface, nodes=control_points_surface_2 

571 ) 

572 return_set["surf_v_min"] = _GeometrySetNodes( 

573 _mpy.geo.surface, nodes=control_points_surface_3 

574 ) 

575 return_set["surf_u_max"] = _GeometrySetNodes( 

576 _mpy.geo.surface, nodes=control_points_surface_4 

577 ) 

578 return_set["surf_v_max"] = _GeometrySetNodes( 

579 _mpy.geo.surface, nodes=control_points_surface_5 

580 ) 

581 return_set["surf_u_min"] = _GeometrySetNodes( 

582 _mpy.geo.surface, nodes=control_points_surface_6 

583 ) 

584 

585 else: 

586 raise NotImplementedError( 

587 "Error, not implemented for NURBS with dimension {}!".format( 

588 nurbs_dimension 

589 ) 

590 ) 

591 

592 def get_patch_volume(return_set, num_cps_uvw, nurbs_dimension, element): 

593 """Get the control points positioned in the volume of a patch.""" 

594 

595 control_points_volume_1 = [] 

596 

597 if nurbs_dimension == 2: 

598 # As this is a surface, it's not necessary to get a volume GeometrySet 

599 pass 

600 

601 elif nurbs_dimension == 3: 

602 # As there is only one volume, it collects all the control points 

603 control_points_volume_1.extend( 

604 element.nodes[: (num_cps_uvw[0] * num_cps_uvw[1] * num_cps_uvw[2])] 

605 ) 

606 

607 # Create geometric sets for surfaces 

608 return_set["vol"] = _GeometrySetNodes( 

609 _mpy.geo.volume, nodes=control_points_volume_1 

610 ) 

611 

612 else: 

613 raise NotImplementedError( 

614 "Error, not implemented for NURBS with dimension {}".format( 

615 nurbs_dimension 

616 ) 

617 ) 

618 

619 # Create return set 

620 return_set = _GeometryName() 

621 

622 # Get the number of control points on each parametric direction that define the patch 

623 num_cps_uvw = element.get_number_of_control_points_per_dir() 

624 

625 # Get the NURBS dimension 

626 nurbs_dimension = len(element.knot_vectors) 

627 

628 # Obtain the vertices of the patch 

629 get_patch_vertices(return_set, num_cps_uvw, nurbs_dimension, element) 

630 

631 # Obtain the lines of the patch 

632 get_patch_lines(return_set, num_cps_uvw, nurbs_dimension, element) 

633 

634 # Obtain the surfaces of the patch 

635 get_patch_surfaces(return_set, num_cps_uvw, nurbs_dimension, element) 

636 

637 # Obtain the volume of the patch 

638 get_patch_volume(return_set, num_cps_uvw, nurbs_dimension, element) 

639 

640 return return_set