14#include "arcane/utils/ArcanePrecomp.h"
15#include "arcane/utils/HashTableMap.h"
16#include "arcane/utils/ArgumentException.h"
17#include "arcane/utils/FatalErrorException.h"
18#include "arcane/utils/PlatformUtils.h"
19#include "arcane/utils/StringBuilder.h"
20#include "arcane/utils/MultiArray2.h"
22#define INSURE_CONSTRAINTS
24#include "arcane/core/ServiceBuildInfo.h"
25#include "arcane/core/IMesh.h"
26#include "arcane/core/IMeshModifier.h"
27#include "arcane/core/IMeshSubMeshTransition.h"
28#include "arcane/core/IMeshUtilities.h"
29#include "arcane/core/IItemFamily.h"
30#include "arcane/core/ItemGroup.h"
31#include "arcane/core/ItemPrinter.h"
32#include "arcane/core/ISubDomain.h"
33#include "arcane/core/IParallelMng.h"
35#include "arcane/core/IVariableMng.h"
36#include "arcane/core/VariableTypes.h"
37#include "arcane/core/CommonVariables.h"
38#include "arcane/core/IMeshPartitionConstraintMng.h"
39#include "arcane/core/ILoadBalanceMng.h"
40#include "arcane/core/MeshKind.h"
41#include "arcane/core/internal/ILoadBalanceMngInternal.h"
43#include "arcane/std/MeshPartitionerBase.h"
57, m_sub_domain(sbi.subDomain())
59, m_cell_family(sbi.
mesh()->cellFamily())
60, m_lbMng(sbi.subDomain()->loadBalanceMng())
61, m_lb_mng_internal(sbi.subDomain()->loadBalanceMng()->_internalApi())
63 IParallelMng* pm = m_mesh->parallelMng();
65 m_is_non_manifold_mesh = m_mesh->meshKind().isNonManifold();
75 delete m_unique_id_reference;
81void* MeshPartitionerBase::
82getCommunicator()
const
84 return m_pm_sub->getMPICommunicator();
90Parallel::Communicator MeshPartitionerBase::
93 return m_pm_sub->communicator();
99void MeshPartitionerBase::
100changeOwnersFromCells()
102 m_mesh->utilities()->changeOwnersFromCells();
108void MeshPartitionerBase::
109initConstraints(
bool uidref)
111 m_mesh_dimension = m_mesh->dimension();
113 _initArrayCellsWithConstraints();
115 _initFilterLidCells();
120 _initLid2LidCompacted();
122 _initNbCellsWithConstraints();
124 m_lb_mng_internal->initAccess(m_mesh);
126 info() <<
"Weight (" << subDomain()->commonVariables().globalIteration()
127 <<
"): " << m_lb_mng_internal->nbCriteria(m_mesh);
133void MeshPartitionerBase::
136 m_lb_mng_internal->endAccess();
138 m_cells_with_constraints.clear();
139 m_cells_with_weak_constraints.clear();
140 m_nb_cells_with_constraints = 0;
141 m_filter_lid_cells.clear();
142 m_local_id_2_local_id_compacted.clear();
143 delete m_unique_id_reference;
144 m_unique_id_reference =
nullptr;
151bool MeshPartitionerBase::
152_createConstraintsLists(Int64MultiArray2& tied_uids)
157 m_cells_with_constraints.clear();
159 IItemFamily* cellFamily = m_mesh->itemFamily(IK_Cell);
162 for (Integer i = 0, n = tied_uids.dim1Size(); i < n; ++i) {
168 cellFamily->itemsUniqueIdToLocalId(lids, uids,
false);
173 for (Integer j = 0, js = lids.size(); j < js; ++j) {
175 if (lid != NULL_ITEM_LOCAL_ID)
180 ItemVectorView items_view = cellFamily->view(lids_loc);
181 SharedArray<Cell> cells;
182 for (Integer j = 0, js = items_view.size(); j < js; j++)
183 if (items_view[j].isOwn())
184 cells.add(items_view[j].toCell());
187 allLocal += (((cells.size() == 0) ||
188 (cells.size() == uids.size()))
194 m_cells_with_constraints.add(cells);
196 IParallelMng* pm = m_mesh->parallelMng();
199 int sum = pm->reduce(Parallel::ReduceSum, allLocal);
206void MeshPartitionerBase::
207_initArrayCellsWithConstraints()
210 m_cells_with_constraints.clear();
211 m_cells_with_weak_constraints.clear();
213 if (!m_mesh->partitionConstraintMng())
225 m_mesh->partitionConstraintMng()->computeConstraintList(tied_uids);
227#ifdef INSURE_CONSTRAINTS
228 if (!_createConstraintsLists(tied_uids)) {
229 if (m_is_non_manifold_mesh)
230 ARCANE_FATAL(
"Constraints are not supported for non manifold mesh");
234 cells_new_owner[icell] = (*icell).owner();
236 m_mesh->modifier()->setDynamic(
true);
237 m_mesh->partitionConstraintMng()->computeAndApplyConstraints();
238 m_mesh->utilities()->changeOwnersFromCells();
239 m_mesh->toPrimaryMesh()->exchangeItems();
241 if (!_createConstraintsLists(tied_uids))
242 throw FatalErrorException(A_FUNCINFO,
"Issue with constraints !");
243#ifdef INSURE_CONSTRAINTS
245 m_mesh->partitionConstraintMng()->computeWeakConstraintList(tied_uids);
247 for (Integer i = 0; i < tied_uids.dim1Size(); ++i) {
248 std::pair<Int64, Int64> ids(tied_uids[i][0], tied_uids[i][1]);
249 m_cells_with_weak_constraints.insert(ids);
256void MeshPartitionerBase::
259 CellGroup all_cells = m_mesh->allCells();
262 m_filter_lid_cells.resize(m_mesh->cellFamily()->maxLocalId());
263 m_filter_lid_cells.fill(eCellGhost);
266 m_filter_lid_cells[icell->localId()] = eCellClassical;
269 for (Integer i = 0; i < m_cells_with_constraints.size(); ++i) {
270 Array<Cell>& listCell = m_cells_with_constraints[i];
271 m_filter_lid_cells[listCell[0].localId()] = eCellReference;
272 for (Integer j = 1; j < listCell.size(); ++j) {
274 if (m_filter_lid_cells[listCell[j].localId()] != eCellClassical)
275 info() <<
"Pb in constraint " << i <<
" with cell[" << j
276 <<
"] = " << listCell[j].uniqueId();
278 m_filter_lid_cells[listCell[j].localId()] = eCellGrouped;
286void MeshPartitionerBase::
289 if (!m_unique_id_reference)
290 m_unique_id_reference =
new VariableCellInt64(VariableBuildInfo(m_mesh,
"CellUniqueIdRef", IVariable::PNoDump));
296void MeshPartitionerBase::
305 uids_ref[icell] = icell->uniqueId();
307 for (Integer i = 0; i < m_cells_with_constraints.size(); ++i) {
308 Array<Cell>& listCell = m_cells_with_constraints[i];
309 Int64 id_ref = listCell[0].uniqueId();
310 for (Integer j = 1; j < listCell.size(); ++j)
311 uids_ref[listCell[j]] = id_ref;
313 uids_ref.synchronize();
319void MeshPartitionerBase::
320_initUidRef(VariableCellInteger& cell_renum_uid)
329 uids_ref[icell] = cell_renum_uid[icell];
331 for (Integer i = 0; i < m_cells_with_constraints.size(); ++i) {
332 Array<Cell>& listCell = m_cells_with_constraints[i];
333 Int64 id_ref = cell_renum_uid[listCell[0]];
334 for (Integer j = 1; j < listCell.size(); ++j)
335 uids_ref[listCell[j]] = id_ref;
337 uids_ref.synchronize();
343void MeshPartitionerBase::
344_initLid2LidCompacted()
349 m_local_id_2_local_id_compacted.resize(m_mesh->cellFamily()->maxLocalId());
350 m_check.resize(m_mesh->cellFamily()->maxLocalId());
354 switch (m_filter_lid_cells[icell.itemLocalId()]) {
357 m_local_id_2_local_id_compacted[icell->localId()] = index++;
362 m_local_id_2_local_id_compacted[icell->localId()] = -1;
374void MeshPartitionerBase::
375_initNbCellsWithConstraints()
378 m_nb_cells_with_constraints = m_mesh->ownCells().size();
379 for (
Integer i = 0; i < m_cells_with_constraints.size(); ++i) {
380 m_nb_cells_with_constraints -= (m_cells_with_constraints[i].size() - 1);
384 for (Integer i=0; i<m_cells_with_constraints.size(); ++i){
385 Array<Cell> & listCell = m_cells_with_constraints[i];
386 for (Integer j = 1 ; j < listCell.size() ; ++j) {
387 if (m_filter_lid_cells[listCell[j].localId()] != eCellGrouped) {
388 info() <<
"Pb in group " << i <<
" " << listCell[j].localId() <<
"is not grouped";
391 info() <<
"Group of size " << i <<
" : " << listCell.size();
395 info() <<
"allCells().size() = " << m_mesh->allCells().size();
396 info() <<
"ownCells().size() = " << m_mesh->ownCells().size();
397 info() <<
"m_nb_cells_with_constraints = " << m_nb_cells_with_constraints;
401Int32 MeshPartitionerBase::
402nbOwnCellsWithConstraints()
const
404 return m_nb_cells_with_constraints;
410nbNeighbourCellsWithConstraints(Cell cell)
414 if (m_filter_lid_cells[cell.localId()] == eCellClassical || m_filter_lid_cells[cell.localId()] == eCellReference) {
417 getNeighbourCellsUidWithConstraints(cell, neighbors);
418 nbNeighbors = neighbors.size();
422 return (nbNeighbors);
427Real MeshPartitionerBase::
428_addNgb(
const Cell& cell,
const Face& face,
429 Int64Array& neighbourcells, Array<bool>& contrib,
430 HashTableMapT<Int64, Int32>& map,
431 Array<float>* ptrcommWeights, Int32 offset,
432 HashTableMapT<Int32, Int32>& lids,
bool special)
434 ARCANE_UNUSED(contrib);
437 Int64 uid = (*m_unique_id_reference)[cell];
439 Int32 myoffset = neighbourcells.size();
442 const float face_comm_cost =
static_cast<float>(commCost[face]);
444 if ((!special) && (m_filter_lid_cells[cell.localId()] == eCellClassical))
447 HashTableMapT<Int64, Int32>::Data* ptr;
448 ptr = map.lookupAdd(uid, myoffset, toAdd);
449 if (!toAdd && ptrcommWeights) {
450 myoffset = ptr->value();
451 (*ptrcommWeights)[offset + myoffset] += face_comm_cost;
455 neighbourcells.add(uid);
456 if (ptrcommWeights) {
457 (*ptrcommWeights).add(face_comm_cost);
477Real MeshPartitionerBase::
478getNeighbourCellsUidWithConstraints(Cell cell, Int64Array& neighbourcells,
479 Array<float>* ptrcommWeights,
480 bool no_cell_contrib)
482 ARCANE_UNUSED(no_cell_contrib);
487 if ((m_filter_lid_cells[cell.localId()] != eCellClassical) && (m_filter_lid_cells[cell.localId()] != eCellReference))
491 offset = (*ptrcommWeights).size();
493 neighbourcells.resize(0);
497 Int64 uid = uids_ref[cell];
501 Integer nbFaces = cell.nbFace();
504 if (m_filter_lid_cells[cell.localId()] == eCellReference) {
505 for (index = 0; index < m_cells_with_constraints.size() && m_cells_with_constraints[index][0] != cell; ++index) {
507 if (index == m_cells_with_constraints.size())
508 throw FatalErrorException(A_FUNCINFO,
"Unable to find cell");
510 Array<Cell>& listCell = m_cells_with_constraints[index];
513 for (Integer j = 1; j < listCell.size(); ++j) {
514 m_filter_lid_cells[listCell[j].localId()] = eCellInAConstraint;
515 nbFaces += listCell[j].nbFace();
519 HashTableMapT<Int64, Int32> difficultNgb(nbFaces,
true);
520 HashTableMapT<Int32, Int32> lids(nbFaces,
true);
521 UniqueArray<bool> contrib(nbFaces);
525 if (m_filter_lid_cells[cell.localId()] == eCellClassical) {
526 if (m_is_non_manifold_mesh && cell.hasFlags(ItemFlags::II_HasEdgeFor1DItems)) {
532 for (Edge sub_edge : cell.edges()) {
534 if (sub_edge.nbCell() >= 2) {
535 for (Cell sub_cell : sub_edge.cells()) {
536 if (sub_cell != cell && sub_cell.hasFlags(ItemFlags::II_HasEdgeFor1DItems)) {
538 neighbourcells.add((*m_unique_id_reference)[sub_cell]);
541 (*ptrcommWeights).add(1.0f);
548 for (Integer z = 0; z < cell.nbFace(); ++z) {
549 Face face = cell.face(z);
551 if (face.nbCell() == 2) {
553 Cell opposite_cell = (face.cell(0) != cell ? face.cell(0) : face.cell(1));
554 hg_contrib += _addNgb(opposite_cell, face, neighbourcells, contrib, difficultNgb,
555 ptrcommWeights, offset, lids);
568 Array<Cell>& listCell = m_cells_with_constraints[index];
569 m_filter_lid_cells[listCell[0].localId()] = eCellInAConstraint;
571 for (Integer j = 0; j < listCell.size(); ++j) {
575 for (Integer z = 0; z < listCell[j].nbFace(); ++z) {
576 const Face& face = listCell[j].face(z);
578 if ((face.nbCell() == 2) && (m_filter_lid_cells[face.cell(0).localId()] != eCellInAConstraint || m_filter_lid_cells[face.cell(1).localId()] != eCellInAConstraint)) {
580 const Cell& opposite_cell = (m_filter_lid_cells[face.cell(0).localId()] != eCellInAConstraint ? face.cell(0) : face.cell(1));
581 hg_contrib += _addNgb(opposite_cell, face, neighbourcells, contrib, difficultNgb,
582 ptrcommWeights, offset, lids,
true);
593 m_filter_lid_cells[listCell[0].localId()] = eCellReference;
594 for (Integer j = 1; j < listCell.size(); ++j)
595 m_filter_lid_cells[listCell[j].localId()] = eCellGrouped;
603void MeshPartitionerBase::
604getNeighbourNodesUidWithConstraints(Cell cell, Int64UniqueArray neighbournodes)
606 neighbournodes.resize(cell.nbNode());
608 for (Integer z = 0; z < cell.nbNode(); ++z) {
609 neighbournodes[z] = cell.node(z).uniqueId();
614Int32 MeshPartitionerBase::
615localIdWithConstraints(Cell cell)
617 return m_local_id_2_local_id_compacted[cell.localId()];
620Int32 MeshPartitionerBase::
621localIdWithConstraints(Int32 cell_lid)
624 return m_local_id_2_local_id_compacted[cell_lid];
628void MeshPartitionerBase::
629invertArrayLid2LidCompacted()
633 for (Integer i = 0; i < m_mesh->allCells().size(); i++) {
634 if (m_local_id_2_local_id_compacted[i] != -1)
635 m_local_id_2_local_id_compacted[index++] = i;
637 for (; index < m_mesh->allCells().size(); index++)
638 m_local_id_2_local_id_compacted[index] = -2;
642SharedArray<float> MeshPartitionerBase::
643cellsSizeWithConstraints()
646 return _cellsProjectWeights(mWgt);
649SharedArray<float> MeshPartitionerBase::
650cellsWeightsWithConstraints(Int32 max_nb_weight,
bool ask_lb_cells)
652 ARCANE_UNUSED(ask_lb_cells);
654 Int32 nb_weight = max_nb_weight;
656 Int32 nb_criteria = m_lb_mng_internal->nbCriteria(m_mesh);
658 if (max_nb_weight <= 0 || max_nb_weight > nb_criteria)
659 nb_weight = nb_criteria;
661 info() <<
"Number of weights " << nb_weight <<
" / " << nb_criteria;
664 return _cellsProjectWeights(mWgt, nb_weight);
670SharedArray<float> MeshPartitionerBase::
671_cellsProjectWeights(VariableCellArrayReal& cellWgtIn, Int32 nbWgt)
const
673 SharedArray<float> cellWgtOut(nbOwnCellsWithConstraints() * nbWgt);
674 if (nbWgt > cellWgtIn.arraySize()) {
675 ARCANE_FATAL(
"Asked for too many weights n={0} array_size={1}", nbWgt, cellWgtIn.arraySize());
679 if (m_filter_lid_cells[icell->localId()] == eCellClassical)
680 for (
int i = 0; i < nbWgt; ++i) {
681 float v =
static_cast<float>(cellWgtIn[icell][i]);
682 cellWgtOut[m_local_id_2_local_id_compacted[icell->localId()] * nbWgt + i] = v;
686 for (
auto& ptr : m_cells_with_constraints) {
688 for (
const auto& cell : ptr) {
689 for (
int i = 0; i < nbWgt; ++i)
690 w[i] += cellWgtIn[cell][i];
692 for (
int i = 0; i < nbWgt; ++i)
693 cellWgtOut[m_local_id_2_local_id_compacted[ptr[0].localId()] * nbWgt + i] = (float)(w[i]);
701SharedArray<float> MeshPartitionerBase::
702_cellsProjectWeights(VariableCellReal& cellWgtIn)
const
704 SharedArray<float> cellWgtOut(nbOwnCellsWithConstraints());
707 if (m_filter_lid_cells[icell->localId()] == eCellClassical)
708 cellWgtOut[m_local_id_2_local_id_compacted[icell->localId()]] = (float)cellWgtIn[icell];
710 for (
auto& ptr : m_cells_with_constraints) {
712 for (Cell cell : ptr) {
713 w += cellWgtIn[cell];
715 cellWgtOut[m_local_id_2_local_id_compacted[ptr[0].localId()]] = (float)w;
722bool MeshPartitionerBase::
723cellUsedWithConstraints(Cell cell)
725 eMarkCellWithConstraint marque = m_filter_lid_cells[cell.localId()];
727 return (marque == eCellClassical || marque == eCellReference);
730bool MeshPartitionerBase::
731cellUsedWithWeakConstraints(std::pair<Int64, Int64>& paired_item)
733 std::pair<Int64, Int64> other_pair(paired_item.second, paired_item.first);
734 return ((m_cells_with_weak_constraints.find(paired_item) != m_cells_with_weak_constraints.end()) || m_cells_with_weak_constraints.find(other_pair) != m_cells_with_weak_constraints.end());
738void MeshPartitionerBase::
739changeCellOwner(Item cell, VariableItemInt32& cells_new_owner, Int32 new_owner)
744 cells_new_owner[cell] = new_owner;
746 if (m_filter_lid_cells[cell.localId()] == eCellReference) {
748 for (index = 0; index < m_cells_with_constraints.size() && m_cells_with_constraints[index][0] != cell; ++index) {
750 if (index == m_cells_with_constraints.size())
751 throw FatalErrorException(
"MeshPartitionerBase::changeCellOwner(): unable to find cell");
753 Array<Cell>& listCell = m_cells_with_constraints[index];
755 for (Integer i = 1; i < listCell.size(); i++)
756 cells_new_owner[listCell[i]] = new_owner;
766 m_lb_mng_internal->reset(m_mesh);
769 for (
int i = 0; i < nb_weight; ++i) {
776 (myvar)[icell] = weights[icell->localId() * nb_weight + i];
778 m_lb_mng_internal->addCriterion(myvar, m_mesh);
781 m_lb_mng_internal->initAccess(m_mesh);
782 m_lb_mng_internal->setMassAsCriterion(m_mesh,
false);
783 m_lb_mng_internal->setNbCellsAsCriterion(m_mesh,
false);
792 return math::max(m_lb_mng_internal->nbCriteria(m_mesh), 1);
795ArrayView<float> MeshPartitionerBase::
801void MeshPartitionerBase::
811template <
class ArrayType> Parallel::Request
818 mysize[0] = data.
size();
828 if (!header.
null()) {
833 ofile << sum << std::endl;
836 for (
int rank = 0; rank < pm->
commSize(); ++rank) {
838 pm->
recv(otherdata, rank,
true);
840 for (
int j = 0; (j < step) && myiter(); ++j, ++myiter)
841 ofile << *myiter <<
" ";
867 if ((m_filter_lid_cells[icell->localId()] != eCellClassical) && (m_filter_lid_cells[icell->localId()] != eCellReference))
870 uid[i++] = uids_ref[icell];
884 myiterf(); ++myiterf, ++myiterr)
885 (*myiterr) = (
Real)(*myiterf);
895 if ((m_filter_lid_cells[icell->localId()] != eCellClassical) && (m_filter_lid_cells[icell->localId()] != eCellReference))
899 for (
Integer z = 0, zs = (*icell).nbNode(); z < zs; ++z) {
900 const Node& node = (*icell).node(z);
901 my_coords[i] += coords[node];
915 if ((m_filter_lid_cells[icell->localId()] != eCellClassical) && (m_filter_lid_cells[icell->localId()] != eCellReference))
917 getNeighbourCellsUidWithConstraints(*icell, neighbourcells, &commWeights);
918 Int64 my_uid = uids_ref[icell];
919 for (
Integer j = 0; j < neighbourcells.
size(); ++j) {
920 if (neighbourcells[j] > my_uid)
922 Real3 tmp(
static_cast<Real>(my_uid + 1),
static_cast<Real>(neighbourcells[j] + 1), commWeights[j]);
928 StringBuilder myheader =
"%%MatrixMarket matrix coordinate real symmetric\n";
929 myheader += nbvertices;
931 myheader += nbvertices;
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Integer size() const
Number of elements in the vector.
Modifiable view of an array of type T.
void fill(ConstReferenceType value)
Fills the array with the value value.
void resize(Int64 s)
Changes the number of elements in the array to s.
void add(ConstReferenceType val)
Adds element val to the end of the array.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
Constant iterator interval.
Exception when a fatal error has occurred.
Interface of the parallelism manager for a subdomain.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual bool isMasterIO() const =0
true if the instance is a master I/O manager.
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual void waitAllRequests(ArrayView< Request > rvalues)=0
Blocks while waiting for the rvalues requests to complete.
virtual void gather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf, Int32 rank)=0
Performs a gather operation onto a processor. This is a collective operation. The array send_buf must...
virtual Integer masterIORank() const =0
Rank of the instance managing I/O (for which isMasterIO() is true).
virtual char reduce(eReduceType rt, char v)=0
Performs a reduction of type rt on the real v and returns the value.
@ PTemporary
Indicates that the variable is temporary.
@ PExecutionDepend
Indicates that the variable value is dependent on the execution.
@ PNoDump
Indicates that the variable should not be saved.
Iterator intervalThis class manages an iterator pair allowing modification of the elements of the con...
void setCellsWeight(ArrayView< float > weights, Integer nb_weight) override
Allows defining the weights of objects to be partitioned: ILoadBalanceMng must now be used.
IMesh * mesh() const override
Mesh associated with the partitioner.
virtual void dumpObject(String filename="toto")
Dumps the partitioning information to disk.
Class managing a 3-dimensional real vector.
Structure containing the information to create a service.
Unicode character string constructor.
String toString() const
Returns the constructed character string.
Unicode character string.
bool null() const
Returns true if the string is null.
const char * localstr() const
Returns the conversion of the instance into UTF-8 encoding.
1D data vector with value semantics (STL style).
Parameters necessary for building a variable.
T max(const T &a, const T &b, const T &c)
Returns the maximum of three elements.
ItemGroupT< Cell > CellGroup
Group of cells.
MeshVariableScalarRefT< Cell, Real > VariableCellReal
Real type quantity at cell center.
MeshVariableScalarRefT< Cell, Int64 > VariableCellInt64
Quantity at the cell center of 64-bit integer type.
ItemVariableScalarRefT< Real > VariableItemReal
Real type quantity.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
MeshVariableArrayRefT< Cell, Real > VariableCellArrayReal
Quantity at the cell center of real array type.
ItemVariableScalarRefT< Int32 > VariableItemInt32
32-bit integer type quantity
double toDouble(Real r)
Converts a Real to double.
@ ReduceSum
Sum of values.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Parallel::Request centralizePartInfo(String filename, IParallelMng *pm, UniqueArray< ArrayType > data, String header, int step=1)
Auxiliary function to dump the graph.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
MultiArray2< Int64 > Int64MultiArray2
2D variable size array of 64-bit integers
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
UniqueArray< Real > RealUniqueArray
Dynamic 1D array of reals.
double Real
Type representing a real number.
@ Cell
The mesh is AMR by cell.