• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Open-Sn / opensn / 20388244010

20 Dec 2025 12:27AM UTC coverage: 74.437% (+0.02%) from 74.415%
20388244010

push

github

web-flow
Merge pull request #882 from andrsd/issue/90-local-cell-idxs

Unifying integer types for local cell face/side indices

13 of 15 new or added lines in 2 files covered. (86.67%)

43 existing lines in 8 files now uncovered.

18677 of 25091 relevant lines covered (74.44%)

66914505.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.89
/python/lib/mesh.cc
1
// SPDX-FileCopyrightText: 2025 The OpenSn Authors <https://open-sn.github.io/opensn/>
2
// SPDX-License-Identifier: MIT
3

4
#include "python/lib/py_wrappers.h"
5
#include "framework/runtime.h"
6
#include "framework/graphs/graph_partitioner.h"
7
#include "framework/graphs/kba_graph_partitioner.h"
8
#include "framework/graphs/linear_graph_partitioner.h"
9
#include "framework/graphs/petsc_graph_partitioner.h"
10
#include "framework/mesh/io/mesh_io.h"
11
#include "framework/mesh/logical_volume/logical_volume.h"
12
#include "framework/mesh/mesh_continuum/mesh_continuum.h"
13
#include "framework/mesh/mesh_generator/mesh_generator.h"
14
#include "framework/mesh/mesh_generator/extruder_mesh_generator.h"
15
#include "framework/mesh/mesh_generator/orthogonal_mesh_generator.h"
16
#include "framework/mesh/mesh_generator/from_file_mesh_generator.h"
17
#include "framework/mesh/mesh_generator/split_file_mesh_generator.h"
18
#include "framework/mesh/mesh_generator/distributed_mesh_generator.h"
19
#include "framework/mesh/surface_mesh/surface_mesh.h"
20
#include "framework/utils/timer.h"
21
#include <pybind11/functional.h>
22
#include <pybind11/stl.h>
23
#include <cstdint>
24
#include <functional>
25
#include <memory>
26
#include <stdexcept>
27
#include <string>
28
#include <vector>
29

30
namespace opensn
31
{
32

33
// Wrap mesh continuum
34
void
35
WrapMesh(py::module& mesh)
483✔
36
{
37
  // clang-format off
38
  // mesh continuum
39
  auto mesh_continuum = py::class_<MeshContinuum, std::shared_ptr<MeshContinuum>>(
483✔
40
    mesh,
41
    "MeshContinuum",
42
    R"(
43
    Mesh continuum.
44

45
    Wrapper of :cpp:class:`opensn::MeshContinuum`.
46
    )"
47
  );
483✔
48
  mesh_continuum.def_property(
483✔
49
    "dimension",
50
    &MeshContinuum::GetDimension,
966✔
51
    &MeshContinuum::SetDimension,
483✔
52
    "Number of dimensions of the mesh."
53
  );
54
  mesh_continuum.def(
483✔
55
    "SetUniformBlockID",
56
    &MeshContinuum::SetUniformBlockID,
966✔
57
    "Set block ID's for all cells to the specified block ID.",
58
    py::arg("mat_id")
483✔
59
  );
60
  mesh_continuum.def(
483✔
61
    "SetBlockIDFromLogicalVolume",
62
    &MeshContinuum::SetBlockIDFromLogicalVolume,
966✔
63
    R"(
64
    Set block ID's using a logical volume.
65

66
    Parameters
67
    ----------
68
    log_vol: pyopensn.logvol.LogicalVolume
69
        Logical volume that determines which mesh cells will be selected.
70
    block_id: int
71
        Block ID that will be assigned.
72
    inside: bool
73
        If true, the selected mesh cells are the ones whose centroids are inside the logival volume.
74
        Otherwise, the selected meshes are the ones whose centroids are outside of the logical
75
        volume.
76
    )",
77
    py::arg("log_vol"),
966✔
78
    py::arg("block_id"),
966✔
79
    py::arg("inside")
483✔
80
  );
81
  mesh_continuum.def(
483✔
82
    "SetUniformBoundaryID",
83
    &MeshContinuum::SetUniformBoundaryID,
966✔
84
    R"(
85
    Assign all boundary faces to a single name
86

87
    Parameters
88
    ----------
89
    boundary_name: str
90
        Name of the boundary to assign to all boundary faces
91
    )",
92
    py::arg("boundary_name")
483✔
93
  );
94
  mesh_continuum.def(
966✔
95
    "SetBoundaryIDFromLogicalVolume",
96
    &MeshContinuum::SetBoundaryIDFromLogicalVolume,
966✔
97
    R"(
98
    Set boundary ID's using a logical volume.
99

100
    Parameters
101
    ----------
102
    log_vol: pyopensn.logvol.LogicalVolume
103
        Logical volume that determines which mesh cells will be selected.
104
    boundary_name: str
105
        Name of the boundary.
106
    inside: bool, default=True
107
        If true, the selected cell facess are the ones whose centroids are inside the logival
108
        volume. Otherwise, the selected meshes are the ones whose centroids are outside of the
109
        logical volume.
110
    )",
111
    py::arg("log_vol"),
966✔
112
    py::arg("boundary_name"),
483✔
113
    py::arg("inside") = true
483✔
114
  );
115
  mesh_continuum.def(
483✔
116
    "SetOrthogonalBoundaries",
117
    &MeshContinuum::SetOrthogonalBoundaries,
483✔
118
    "Set boundary IDs for xmin/xmax, ymin/ymax, zmin/zmax for a right parallelpiped domain."
119
  );
120
  mesh_continuum.def(
483✔
121
    "ExportToPVTU",
122
    [](std::shared_ptr<MeshContinuum> self, const std::string& file_name) {
502✔
123
      MeshIO::ToPVTU(self, file_name);
19✔
124
    },
19✔
125
    R"(
126
    Write grid cells into PVTU format.
127

128
    Parameters
129
    ----------
130
    file_base_name: str
131
        Base name of the output file.
132
    )",
133
    py::arg("file_base_name")
483✔
134
  );
135
  mesh_continuum.def(
483✔
136
    "ComputeVolumePerBlockID",
137
    &MeshContinuum::ComputeVolumePerBlockID,
483✔
138
    R"(
139
    Compute volume per block ID
140

141
    Returns
142
    -------
143
    Dict[int, float]
144
        Key is the block ID and the value is the computed volume
145
    )"
146
  );
147
  mesh_continuum.def(
483✔
148
    "SetBlockIDFromFunction",
149
    [](MeshContinuum& self, const std::function<unsigned int(Vector3, unsigned int)>& func)
487✔
150
    {
151
      int local_num_cells_modified = 0;
4✔
152
      // change local cells
153
      for (Cell& cell : self.local_cells)
376,004✔
154
      {
155
        auto new_block_id = func(cell.centroid, cell.block_id);
376,000✔
156
        if (cell.block_id != new_block_id)
376,000✔
157
        {
158
          cell.block_id = new_block_id;
4,514✔
159
          ++local_num_cells_modified;
4,514✔
160
        }
161
      }
162
      // change ghost cells
163
      std::vector<std::uint64_t> ghost_ids = self.cells.GetGhostGlobalIDs();
4✔
164
      for (std::uint64_t ghost_id : ghost_ids)
4✔
165
      {
166
        Cell& cell = self.cells[ghost_id];
×
167
        auto new_block_id = func(cell.centroid, cell.block_id);
×
168
        if (cell.block_id != new_block_id)
×
169
        {
170
          cell.block_id = new_block_id;
×
171
          ++local_num_cells_modified;
×
172
        }
173
      }
174
      // print number of modified cells
175
      int global_num_cells_modified = 0;
4✔
176
      mpi_comm.all_reduce(local_num_cells_modified, global_num_cells_modified, mpi::op::sum<int>());
4✔
177
      log.Log0Verbose1() << program_timer.GetTimeString()
12✔
178
                         << " Done setting block id from Python function. "
4✔
179
                         << "Number of cells modified = " << global_num_cells_modified << ".";
8✔
180
    },
4✔
181
    R"(
182
    Set block ID from a function.
183

184
    Parameters
185
    ----------
186
    func: Callable[[pyopensn.math.Vector3, int], int]
187
        Function/lambda computing new block ID from cell centroid and old block ID.
188

189
    Examples
190
    --------
191
    >>> # Change block ID from 0 to 1 for cells inside the unit sphere.
192
    >>> def block_id_setter(cell_centroid, old_id):
193
    ...     if (old_id == 0) and (cell_centroid.Norm() < 1.0):
194
    ...         return 1
195
    ...     return old_id
196
    >>> mesh.SetBlockIDFromFunction(block_id_setter)
197
    )",
198
    py::arg("func")
483✔
199
  );
200

201
  // surface mesh
202
  auto surface_mesh = py::class_<SurfaceMesh, std::shared_ptr<SurfaceMesh>>(
483✔
203
    mesh,
204
    "SurfaceMesh",
205
    R"(
206
    Surface mesh.
207

208
    Wrapper of :cpp:class:`opensn::SurfaceMesh`.
209
    )"
210
  );
483✔
211
  surface_mesh.def(
966✔
212
    py::init(
483✔
213
      [](py::kwargs& params)
1✔
214
      {
215
        return SurfaceMesh::Create(kwargs_to_param_block(params));
1✔
216
      }
217
    ),
218
    R"(
219
    Construct a surface mesh.
220

221
    This function does not take any arguments.
222
    )"
223
  );
224
  surface_mesh.def(
966✔
225
    "ImportFromOBJFile",
226
    &SurfaceMesh::ImportFromOBJFile,
966✔
227
    R"(
228
    Loads a surface mesh from a wavefront .obj file.
229

230
    Parameters
231
    ----------
232
    file_name: str
233
        Surface mesh filename.
234
    as_poly: bool, default=False
235
        Indicate if the surface mesh is allowed to contain polygonal facets (as opposed to only
236
        triangular faces).
237
    translation: pyopensn.math.Vector3, default=(0.0, 0.0, 0.0)
238
        Translation to perform on the mesh.
239
    )",
240
    py::arg("file_name"),
483✔
241
    py::arg("as_poly") = false,
966✔
242
    py::arg("transform") = Vector3()
483✔
243
  );
244
  surface_mesh.def(
483✔
245
    "ImportFromTriangleFiles",
246
    &SurfaceMesh::ImportFromTriangleFiles,
966✔
247
    R"(
248
    Loads a surface mesh from triangle's file format.
249

250
    Parameters
251
    ----------
252
    file_name: str
253
        Surface mesh filename.
254
    as_poly: bool
255
        Indicate if the surface mesh is allowed to contain polygonal facets (as opposed to only
256
        triangular faces).
257
    )",
258
    py::arg("file_name"),
966✔
259
    py::arg("as_poly")
483✔
260
  );
261
  surface_mesh.def(
483✔
262
    "ImportFromMshFiles",
263
    &SurfaceMesh::ImportFromMshFiles,
966✔
264
    R"(
265
    Loads a surface mesh from gmsh's file format.
266

267
    Parameters
268
    ----------
269
    file_name: str
270
        Surface mesh filename.
271
    as_poly: bool
272
        Indicate if the surface mesh is allowed to contain polygonal facets (as opposed to only
273
        triangular faces).
274
    )",
275
    py::arg("file_name"),
966✔
276
    py::arg("as_poly")
483✔
277
  );
278
  // clang-format on
279
}
483✔
280

281
// Wrap mesh generator
282
void
283
WrapMeshGenerator(py::module& mesh)
483✔
284
{
285
  // clang-format off
286
  // base mesh generator
287
  auto mesh_generator = py::class_<MeshGenerator, std::shared_ptr<MeshGenerator>>(
483✔
288
    mesh,
289
    "MeshGenerator",
290
    R"(
291
    Generic mesh generator.
292

293
    Wrapper of :cpp:class:`opensn::MeshGenerator`.
294
    )"
295
  );
483✔
296
  mesh_generator.def(
483✔
297
    "Execute",
298
    &MeshGenerator::Execute,
483✔
299
    "Final execution step."
300
  );
301

302
  // extruded mesh generator
303
  auto extruder_mesh_generator = py::class_<ExtruderMeshGenerator,
483✔
304
                                            std::shared_ptr<ExtruderMeshGenerator>, MeshGenerator>(
305
    mesh,
306
    "ExtruderMeshGenerator",
307
    R"(
308
    Extruded mesh generator.
309

310
    Wrapper of :cpp:class:`opensn::ExtruderMeshGenerator`.
311
    )"
312
  );
483✔
313
  extruder_mesh_generator.def(
966✔
314
    py::init(
483✔
315
      [](py::kwargs& params)
57✔
316
      {
317
        return ExtruderMeshGenerator::Create(kwargs_to_param_block(params));
57✔
318
      }
319
    ),
320
    R"(
321
    Construct an extruded mesh generator.
322

323
    Extrude 2D geometry using extrusion layers. Each layer is specified by either:
324

325
     - ``n`` and ``z`` to compute the z-levels automatically.
326
     - ``n`` and ``h`` to compute the h-levels automatically.
327

328
    The list of layers can be specified with a mixture of both ways.
329

330
    Parameters
331
    ----------
332
    scale: float, default=1.0
333
        Uniform scale to apply to the mesh after reading.
334
    inputs: List[pyopensn.mesh.MeshGenerator], default=[]
335
        A list of MeshGenerator objects.
336
    partitioner: pyopensn.mesh.GraphPartitioner, default=None
337
        Handle to a GraphPartitioner object to use for parallel partitioning. This will default to
338
        PETScGraphPartitioner with a "parmetis" setting.
339
    replicated_mesh: bool, default=False
340
        Flag, when set, makes the mesh appear in full fidelity on each process.
341
    layers: List[Dict]
342
        List of layers. Each layer is a dictionary with entries:
343
          - n: int, default=1
344
              Number of sub-layers in this layer.
345
          - h: float, default=1.0
346
              Layer height. Cannot be specified if ``z`` is specified.
347
          - z: float, default=0.0
348
              Z-coordinate at the top of the layer. Cannot be specified if ``h`` is specified.
349
    top_boundary_name: str, default='ZMAX'
350
        The name to associate with the top boundary.
351
    bottom_boundary_name: str, default='ZMIN'
352
        The name to associate with the bottom boundary.
353

354
    Examples
355
    --------
356
    >>> emg = ExtruderMeshGenerator(
357
    ...     layers=[{"n": 1, "z": 2}, {"n": 2, "h": 0.5}]
358
    ... )
359
    )"
360
  );
361

362
  // orthogonal mesh generator
363
  auto orthogonal_mesh_generator = py::class_<OrthogonalMeshGenerator,
483✔
364
                                              std::shared_ptr<OrthogonalMeshGenerator>,
365
                                              MeshGenerator>(
366
    mesh,
367
    "OrthogonalMeshGenerator",
368
    R"(
369
    Orthogonal mesh generator.
370

371
    Wrapper of :cpp:class:`opensn::OrthogonalMeshGenerator`.
372
    )"
373
  );
483✔
374
  orthogonal_mesh_generator.def(
966✔
375
    py::init(
483✔
376
      [](py::kwargs& params)
242✔
377
      {
378
        return OrthogonalMeshGenerator::Create(kwargs_to_param_block(params));
242✔
379
      }
380
    ),
381
    R"(
382
    Construct an orthogonal mesh generator.
383

384
    Parameters
385
    ----------
386
    scale: float, default=1.0
387
        Uniform scale to apply to the mesh after reading.
388
    inputs: List[pyopensn.mesh.MeshGenerator], default=[]
389
        A list of MeshGenerator objects.
390
    partitioner: pyopensn.mesh.GraphPartitioner, default=None
391
        Handle to a GraphPartitioner object to use for parallel partitioning. This will default to
392
        PETScGraphPartitioner with a "parmetis" setting.
393
    replicated_mesh: bool, default=False
394
        Flag, when set, makes the mesh appear in full fidelity on each process.
395
    node_sets: List[List[float]]
396
        Sets of nodes per dimension. Node values must be monotonically increasing.
397
    coord_sys: {'cartesian', 'cylindrical', 'spherical'}
398
        The coordinate system of the mesh.
399
    )"
400
  );
401

402
  // from file mesh generator
403
  auto from_file_mesh_generator = py::class_<FromFileMeshGenerator,
483✔
404
                                             std::shared_ptr<FromFileMeshGenerator>, MeshGenerator>(
405
    mesh,
406
    "FromFileMeshGenerator",
407
    R"(
408
    From file mesh generator.
409

410
    Wrapper of :cpp:class:`opensn::FromFileMeshGenerator`.
411
    )"
412
  );
483✔
413
  from_file_mesh_generator.def(
966✔
414
    py::init(
483✔
415
      [](py::kwargs & params)
223✔
416
      {
417
        return FromFileMeshGenerator::Create(kwargs_to_param_block(params));
223✔
418
      }
419
    ),
420
    R"(
421
    Construct a from-file mesh generator.
422

423
    Parameters
424
    ----------
425
    scale: float, default=1.0
426
        Uniform scale to apply to the mesh after reading.
427
    inputs: List[pyopensn.mesh.MeshGenerator], default=[]
428
        A list of MeshGenerator objects.
429
    partitioner: pyopensn.mesh.GraphPartitioner, default=None
430
        Handle to a GraphPartitioner object to use for parallel partitioning. This will default to
431
        PETScGraphPartitioner with a "parmetis" setting.
432
    replicated_mesh: bool, default=False
433
        Flag, when set, makes the mesh appear in full fidelity on each process.
434
    filename: str
435
        Path to the file.
436
    block_id_fieldname: str, default='BlockID'
437
        The name of the field storing cell block/block ids. Only really used for .vtu, .pvtu and
438
        .e files.
439
    boundary_id_fieldname: str, default=''
440
        The name of the field storing boundary-ids.
441
    coord_sys: {'cartesian', 'cylindrical', 'spherical'}
442
        The coordinate system of the mesh.
443
    )"
444
  );
445

446
  // split file mesh generator
447
  auto split_file_mesh_generator = py::class_<SplitFileMeshGenerator,
483✔
448
                                              std::shared_ptr<SplitFileMeshGenerator>,
449
                                              MeshGenerator>(
450
    mesh,
451
    "SplitFileMeshGenerator",
452
    R"(
453
    Split file mesh generator.
454

455
    Wrapper of :cpp:class:`opensn::SplitFileMeshGenerator`.
456

457
    Generates the mesh only on rank 0. After partitioning, the mesh is not broadcast
458
    to other ranks; instead, a binary mesh file for each is written .
459
    )"
460
  );
483✔
461
  split_file_mesh_generator.def(
966✔
462
    py::init(
483✔
463
      [](py::kwargs & params)
8✔
464
      {
465
        return SplitFileMeshGenerator::Create(kwargs_to_param_block(params));
8✔
466
      }
467
    ),
468
    R"(
469
    Construct a split-file mesh generator.
470

471
    Parameters
472
    ----------
473
    scale: float, default=1.0
474
        Uniform scale to apply to the mesh after reading.
475
    inputs: List[pyopensn.mesh.MeshGenerator], default=[]
476
        A list of MeshGenerator objects.
477
    partitioner: pyopensn.mesh.GraphPartitioner, default=None
478
        Handle to a GraphPartitioner object to use for parallel partitioning. This will default to
479
        PETScGraphPartitioner with a "parmetis" setting.
480
    replicated_mesh: bool, default=False
481
        Flag, when set, makes the mesh appear in full fidelity on each process.
482
    num_partitions: int, default=0
483
        The number of partitions to generate. If zero, it will default to the number of MPI
484
        processes. Automatically ignored if the number of MPI processes greater 1.
485
    split_mesh_dir_path: str, default='split_mesh'
486
        Path of the directory to be created for containing the split meshes.
487
    file_prefix: str, default=''
488
        Prefix to use for all split mesh files. If not provided, it default to the input path's
489
        folder.
490
    read_only: bool, default=False
491
        Controls whether the split mesh is recreated or just read.
492
    verbosity_level: int, default=1
493
        Verbosity level. 1 will report each 10% complete. 2 will print each part and the number of
494
        local cells it wrote.
495
    )"
496
  );
497

498
  // distributed mesh generator
499
  auto distributed_mesh_generator = py::class_<DistributedMeshGenerator,
483✔
500
                                               std::shared_ptr<DistributedMeshGenerator>,
501
                                               MeshGenerator>(
502
    mesh,
503
    "DistributedMeshGenerator",
504
    R"(
505
    Distributed mesh generator.
506

507
    This class is responsible for generating a mesh, partitioning it, and distributing the
508
    individual partitions to different MPI locations. The mesh is generated on location 0,
509
    partitioned into multiple parts, serialized, and distributed to all other MPI ranks.
510

511
    Wrapper of :cpp:class:`opensn::DistributedMeshGenerator`.
512
    )"
513
  );
483✔
514
  distributed_mesh_generator.def(
966✔
515
    py::init(
483✔
516
      [](py::kwargs & params)
8✔
517
      {
518
        return DistributedMeshGenerator::Create(kwargs_to_param_block(params));
8✔
519
      }
520
    ),
521
    R"(
522
    Construct a distributed mesh generator.
523

524
    Parameters
525
    ----------
526
    scale: float, default=1.0
527
        Uniform scale to apply to the mesh after reading.
528
    inputs: List[pyopensn.mesh.MeshGenerator], default=[]
529
        A list of MeshGenerator objects.
530
    partitioner: pyopensn.mesh.GraphPartitioner, default=None
531
        Handle to a GraphPartitioner object to use for parallel partitioning. This will default to
532
        PETScGraphPartitioner with a "parmetis" setting.
533
    replicated_mesh: bool, default=False
534
        Flag, when set, makes the mesh appear in full fidelity on each process.
535
    coord_sys: {'cartesian', 'cylindrical', 'spherical'}
536
        The coordinate system of the mesh.
537
    )"
538
  );
539
  // clang-format on
540
}
483✔
541

542
// Wrap graph partitioner
543
void
544
WrapGraphPartitioner(py::module& mesh)
483✔
545
{
546
  // clang-format off
547
  // base graph partitioner
548
  auto graph_partitioner = py::class_<GraphPartitioner, std::shared_ptr<GraphPartitioner>>(
483✔
549
    mesh,
550
    "GraphPartitioner",
551
    R"(
552
    Generic graph partitioner.
553

554
    Wrapper of :cpp:class:`opensn::GraphPartitioner`.
555
    )");
483✔
556

557
  // KBA graph partitioner
558
  auto kba_graph_partitioner = py::class_<KBAGraphPartitioner, std::shared_ptr<KBAGraphPartitioner>,
483✔
559
                                          GraphPartitioner>(
560
    mesh,
561
    "KBAGraphPartitioner",
562
    R"(
563
    Koch, Baker and Alcouffe based partitioning.
564

565
    This is an overlayed ortho-grid based partitioner.
566

567
    Wrapper of :cpp:class:`opensn::KBAGraphPartitioner`.
568
    )"
569
  );
483✔
570
  kba_graph_partitioner.def(
966✔
571
    py::init(
483✔
572
      [](py::kwargs& params)
82✔
573
      {
574
        return KBAGraphPartitioner::Create(kwargs_to_param_block(params));
82✔
575
      }
576
    ),
577
    R"(
578
    Construct a KBA graph partitioner.
579

580
    Parameters
581
    ----------
582
    nx: int, default=1
583
        Number of partitions in x.
584
    ny: int, default=1
585
        Number of partitions in y.
586
    nz: int, default=1
587
        Number of partitions in z.
588
    xcuts: List[float], default=[]
589
        Location of the internal x-cuts. Requires ``nx - 1`` entries.
590
    ycuts: List[float], default=[]
591
        Location of the internal y-cuts. Requires ``ny - 1`` entries.
592
    zcuts: List[float], default=[]
593
        Location of the internal z-cuts. Requires ``nz - 1`` entries.
594
    )"
595
  );
596

597
  // linear graph partitioner
598
  auto linear_graph_partitioner = py::class_<LinearGraphPartitioner,
483✔
599
                                             std::shared_ptr<LinearGraphPartitioner>,
600
                                             GraphPartitioner>(
601
    mesh,
602
    "LinearGraphPartitioner",
603
    R"(
604
    Basic linear partitioning.
605

606
    This type of partitioner works basically only for testing.
607

608
    Orthogonal meshes can produce decent partitioning but for unstructured grids it can be pretty
609
    bad. It partitions cells based on their linear index ``global_id`` instead of actually
610
    working with the graph.
611

612
    Wrapper of :cpp:class:`opensn::LinearGraphPartitioner`.
613
    )"
614
  );
483✔
615
  linear_graph_partitioner.def(
966✔
616
    py::init(
483✔
UNCOV
617
      [](py::kwargs & params)
×
618
      {
UNCOV
619
        return LinearGraphPartitioner::Create(kwargs_to_param_block(params));
×
620
      }
621
    ),
622
    R"(
623
    Construct a linear graph partitioner.
624

625
    Parameters
626
    ----------
627
    all_to_rank: int, default=-1
628
        Rank to which all cells are restricted if non-zero. Otherwise, the partitioner is equivalent
629
        to a single-rank partitioner.
630
    )"
631
  );
632

633
  // PETSc graph partitioner
634
  auto petsc_graph_partitioner = py::class_<PETScGraphPartitioner,
483✔
635
                                            std::shared_ptr<PETScGraphPartitioner>,
636
                                            GraphPartitioner>(
637
    mesh,
638
    "PETScGraphPartitioner",
639
    R"(
640
    PETSc based partitioning.
641

642
    Wrapper of :cpp:class:`opensn::PETScGraphPartitioner`.
643
    )"
644
  );
483✔
645
  petsc_graph_partitioner.def(
966✔
646
    py::init(
483✔
647
      [](py::kwargs & params) {
28✔
648
        return PETScGraphPartitioner::Create(kwargs_to_param_block(params));
28✔
649
      }
650
    ),
651
    R"(
652
    Construct a PETSc based graph partitioner.
653

654
    Parameters
655
    ----------
656
    type: {'parmetis', 'ptscotch'}, default='parmetis'
657
        Type of PETSc partitioner.
658
    )"
659
  );
660
  // clang-format on
661
}
483✔
662

663
void
664
py_mesh(py::module& pyopensn)
62✔
665
{
666
  py::module mesh = pyopensn.def_submodule("mesh", "Mesh generation module.");
62✔
667
  WrapMesh(mesh);
62✔
668
  WrapMeshGenerator(mesh);
62✔
669
  WrapGraphPartitioner(mesh);
62✔
670
}
62✔
671

672
} // namespace opensn
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc