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"
21#include "arcane/utils/Convert.h"
23#define INSURE_CONSTRAINTS
25#include "arcane/core/ServiceBuildInfo.h"
26#include "arcane/core/IMesh.h"
27#include "arcane/core/IMeshModifier.h"
28#include "arcane/core/IMeshSubMeshTransition.h"
29#include "arcane/core/IMeshUtilities.h"
30#include "arcane/core/IItemFamily.h"
31#include "arcane/core/ItemGroup.h"
32#include "arcane/core/ItemPrinter.h"
33#include "arcane/core/ISubDomain.h"
34#include "arcane/core/IParallelMng.h"
36#include "arcane/core/IVariableMng.h"
37#include "arcane/core/VariableTypes.h"
38#include "arcane/core/CommonVariables.h"
39#include "arcane/core/IMeshPartitionConstraintMng.h"
40#include "arcane/core/ILoadBalanceMng.h"
41#include "arcane/core/MeshKind.h"
42#include "arcane/core/internal/ILoadBalanceMngInternal.h"
44#include "arcane/std/MeshPartitionerBase.h"
58, m_sub_domain(sbi.subDomain())
60, m_cell_family(sbi.
mesh()->cellFamily())
61, m_lbMng(sbi.subDomain()->loadBalanceMng())
62, m_lb_mng_internal(sbi.subDomain()->loadBalanceMng()->_internalApi())
64 IParallelMng* pm = m_mesh->parallelMng();
66 m_is_non_manifold_mesh = m_mesh->meshKind().isNonManifold();
76 delete m_unique_id_reference;
82void* MeshPartitionerBase::
83getCommunicator()
const
85 return m_pm_sub->getMPICommunicator();
91Parallel::Communicator MeshPartitionerBase::
94 return m_pm_sub->communicator();
100void MeshPartitionerBase::
101changeOwnersFromCells()
103 m_mesh->utilities()->changeOwnersFromCells();
109void MeshPartitionerBase::
110initConstraints(
bool uidref)
112 m_mesh_dimension = m_mesh->dimension();
114 _initArrayCellsWithConstraints();
116 _initFilterLidCells();
121 _initLid2LidCompacted();
123 _initNbCellsWithConstraints();
125 m_lb_mng_internal->initAccess(m_mesh);
127 info() <<
"Weight (" << subDomain()->commonVariables().globalIteration()
128 <<
"): " << m_lb_mng_internal->nbCriteria(m_mesh);
134void MeshPartitionerBase::
137 m_lb_mng_internal->endAccess();
139 m_cells_with_constraints.clear();
140 m_cells_with_weak_constraints.clear();
141 m_nb_cells_with_constraints = 0;
142 m_filter_lid_cells.clear();
143 m_local_id_2_local_id_compacted.clear();
144 delete m_unique_id_reference;
145 m_unique_id_reference =
nullptr;
152bool MeshPartitionerBase::
153_createConstraintsLists(Int64MultiArray2& tied_uids)
158 m_cells_with_constraints.clear();
160 IItemFamily* cellFamily = m_mesh->itemFamily(IK_Cell);
163 for (Integer i = 0, n = tied_uids.dim1Size(); i < n; ++i) {
169 cellFamily->itemsUniqueIdToLocalId(lids, uids,
false);
174 for (Integer j = 0, js = lids.size(); j < js; ++j) {
176 if (lid != NULL_ITEM_LOCAL_ID)
181 ItemVectorView items_view = cellFamily->view(lids_loc);
182 SharedArray<Cell> cells;
183 for (Integer j = 0, js = items_view.size(); j < js; j++)
184 if (items_view[j].isOwn())
185 cells.add(items_view[j].toCell());
188 allLocal += (((cells.size() == 0) ||
189 (cells.size() == uids.size()))
195 m_cells_with_constraints.add(cells);
197 IParallelMng* pm = m_mesh->parallelMng();
200 int sum = pm->reduce(Parallel::ReduceSum, allLocal);
207void MeshPartitionerBase::
208_initArrayCellsWithConstraints()
211 m_cells_with_constraints.clear();
212 m_cells_with_weak_constraints.clear();
214 if (!m_mesh->partitionConstraintMng())
226 m_mesh->partitionConstraintMng()->computeConstraintList(tied_uids);
228#ifdef INSURE_CONSTRAINTS
229 if (!_createConstraintsLists(tied_uids)) {
230 if (m_is_non_manifold_mesh)
231 ARCANE_FATAL(
"Constraints are not supported for non manifold mesh");
235 cells_new_owner[icell] = (*icell).owner();
237 m_mesh->modifier()->setDynamic(
true);
238 m_mesh->partitionConstraintMng()->computeAndApplyConstraints();
239 m_mesh->utilities()->changeOwnersFromCells();
240 m_mesh->toPrimaryMesh()->exchangeItems();
242 if (!_createConstraintsLists(tied_uids))
243 throw FatalErrorException(A_FUNCINFO,
"Issue with constraints !");
244#ifdef INSURE_CONSTRAINTS
246 m_mesh->partitionConstraintMng()->computeWeakConstraintList(tied_uids);
248 for (Integer i = 0; i < tied_uids.dim1Size(); ++i) {
249 std::pair<Int64, Int64> ids(tied_uids[i][0], tied_uids[i][1]);
250 m_cells_with_weak_constraints.insert(ids);
257void MeshPartitionerBase::
260 CellGroup all_cells = m_mesh->allCells();
263 m_filter_lid_cells.resize(m_mesh->cellFamily()->maxLocalId());
264 m_filter_lid_cells.fill(eCellGhost);
267 m_filter_lid_cells[icell->localId()] = eCellClassical;
270 for (Integer i = 0; i < m_cells_with_constraints.size(); ++i) {
271 Array<Cell>& listCell = m_cells_with_constraints[i];
272 m_filter_lid_cells[listCell[0].localId()] = eCellReference;
273 for (Integer j = 1; j < listCell.size(); ++j) {
275 if (m_filter_lid_cells[listCell[j].localId()] != eCellClassical)
276 info() <<
"Pb in constraint " << i <<
" with cell[" << j
277 <<
"] = " << listCell[j].uniqueId();
279 m_filter_lid_cells[listCell[j].localId()] = eCellGrouped;
287void MeshPartitionerBase::
290 if (!m_unique_id_reference)
291 m_unique_id_reference =
new VariableCellInt64(VariableBuildInfo(m_mesh,
"CellUniqueIdRef", IVariable::PNoDump));
297void MeshPartitionerBase::
306 uids_ref[icell] = icell->uniqueId();
308 for (Integer i = 0; i < m_cells_with_constraints.size(); ++i) {
309 Array<Cell>& listCell = m_cells_with_constraints[i];
310 Int64 id_ref = listCell[0].uniqueId();
311 for (Integer j = 1; j < listCell.size(); ++j)
312 uids_ref[listCell[j]] = id_ref;
314 uids_ref.synchronize();
320void MeshPartitionerBase::
321_initUidRef(VariableCellInteger& cell_renum_uid)
330 uids_ref[icell] = cell_renum_uid[icell];
332 for (Integer i = 0; i < m_cells_with_constraints.size(); ++i) {
333 Array<Cell>& listCell = m_cells_with_constraints[i];
334 Int64 id_ref = cell_renum_uid[listCell[0]];
335 for (Integer j = 1; j < listCell.size(); ++j)
336 uids_ref[listCell[j]] = id_ref;
338 uids_ref.synchronize();
344void MeshPartitionerBase::
345_initLid2LidCompacted()
350 m_local_id_2_local_id_compacted.resize(m_mesh->cellFamily()->maxLocalId());
351 m_check.resize(m_mesh->cellFamily()->maxLocalId());
355 switch (m_filter_lid_cells[icell.itemLocalId()]) {
358 m_local_id_2_local_id_compacted[icell->localId()] = index++;
363 m_local_id_2_local_id_compacted[icell->localId()] = -1;
375void MeshPartitionerBase::
376_initNbCellsWithConstraints()
379 m_nb_cells_with_constraints = m_mesh->ownCells().size();
380 for (
Integer i = 0; i < m_cells_with_constraints.size(); ++i) {
381 m_nb_cells_with_constraints -= (m_cells_with_constraints[i].size() - 1);
385 for (Integer i=0; i<m_cells_with_constraints.size(); ++i){
386 Array<Cell> & listCell = m_cells_with_constraints[i];
387 for (Integer j = 1 ; j < listCell.size() ; ++j) {
388 if (m_filter_lid_cells[listCell[j].localId()] != eCellGrouped) {
389 info() <<
"Pb in group " << i <<
" " << listCell[j].localId() <<
"is not grouped";
392 info() <<
"Group of size " << i <<
" : " << listCell.size();
396 info() <<
"allCells().size() = " << m_mesh->allCells().size();
397 info() <<
"ownCells().size() = " << m_mesh->ownCells().size();
398 info() <<
"m_nb_cells_with_constraints = " << m_nb_cells_with_constraints;
402Int32 MeshPartitionerBase::
403nbOwnCellsWithConstraints()
const
405 return m_nb_cells_with_constraints;
411nbNeighbourCellsWithConstraints(Cell cell)
415 if (m_filter_lid_cells[cell.localId()] == eCellClassical || m_filter_lid_cells[cell.localId()] == eCellReference) {
418 getNeighbourCellsUidWithConstraints(cell, neighbors);
419 nbNeighbors = neighbors.size();
423 return (nbNeighbors);
428Real MeshPartitionerBase::
429_addNgb(
const Cell& cell,
const Face& face,
430 Int64Array& neighbourcells, Array<bool>& contrib,
431 HashTableMapT<Int64, Int32>& map,
432 Array<float>* ptrcommWeights, Int32 offset,
433 HashTableMapT<Int32, Int32>& lids,
bool special)
435 ARCANE_UNUSED(contrib);
438 Int64 uid = (*m_unique_id_reference)[cell];
440 Int32 myoffset = neighbourcells.size();
443 const float face_comm_cost =
static_cast<float>(commCost[face]);
445 if ((!special) && (m_filter_lid_cells[cell.localId()] == eCellClassical))
448 HashTableMapT<Int64, Int32>::Data* ptr;
449 ptr = map.lookupAdd(uid, myoffset, toAdd);
450 if (!toAdd && ptrcommWeights) {
451 myoffset = ptr->value();
452 (*ptrcommWeights)[offset + myoffset] += face_comm_cost;
456 neighbourcells.add(uid);
457 if (ptrcommWeights) {
458 (*ptrcommWeights).add(face_comm_cost);
478Real MeshPartitionerBase::
479getNeighbourCellsUidWithConstraints(Cell cell, Int64Array& neighbourcells,
480 Array<float>* ptrcommWeights,
481 bool no_cell_contrib)
483 ARCANE_UNUSED(no_cell_contrib);
488 if ((m_filter_lid_cells[cell.localId()] != eCellClassical) && (m_filter_lid_cells[cell.localId()] != eCellReference))
492 offset = (*ptrcommWeights).size();
494 neighbourcells.resize(0);
498 Int64 uid = uids_ref[cell];
502 Integer nbFaces = cell.nbFace();
505 if (m_filter_lid_cells[cell.localId()] == eCellReference) {
506 for (index = 0; index < m_cells_with_constraints.size() && m_cells_with_constraints[index][0] != cell; ++index) {
508 if (index == m_cells_with_constraints.size())
509 throw FatalErrorException(A_FUNCINFO,
"Unable to find cell");
511 Array<Cell>& listCell = m_cells_with_constraints[index];
514 for (Integer j = 1; j < listCell.size(); ++j) {
515 m_filter_lid_cells[listCell[j].localId()] = eCellInAConstraint;
516 nbFaces += listCell[j].nbFace();
520 HashTableMapT<Int64, Int32> difficultNgb(nbFaces,
true);
521 HashTableMapT<Int32, Int32> lids(nbFaces,
true);
522 UniqueArray<bool> contrib(nbFaces);
526 if (m_filter_lid_cells[cell.localId()] == eCellClassical) {
527 if (m_is_non_manifold_mesh && cell.hasFlags(ItemFlags::II_HasEdgeFor1DItems)) {
533 for (Edge sub_edge : cell.edges()) {
535 if (sub_edge.nbCell() >= 2) {
536 for (Cell sub_cell : sub_edge.cells()) {
537 if (sub_cell != cell && sub_cell.hasFlags(ItemFlags::II_HasEdgeFor1DItems)) {
539 neighbourcells.add((*m_unique_id_reference)[sub_cell]);
542 (*ptrcommWeights).add(1.0f);
549 for (Integer z = 0; z < cell.nbFace(); ++z) {
550 Face face = cell.face(z);
552 if (face.nbCell() == 2) {
554 Cell opposite_cell = (face.cell(0) != cell ? face.cell(0) : face.cell(1));
555 hg_contrib += _addNgb(opposite_cell, face, neighbourcells, contrib, difficultNgb,
556 ptrcommWeights, offset, lids);
569 Array<Cell>& listCell = m_cells_with_constraints[index];
570 m_filter_lid_cells[listCell[0].localId()] = eCellInAConstraint;
572 for (Integer j = 0; j < listCell.size(); ++j) {
576 for (Integer z = 0; z < listCell[j].nbFace(); ++z) {
577 const Face& face = listCell[j].face(z);
579 if ((face.nbCell() == 2) && (m_filter_lid_cells[face.cell(0).localId()] != eCellInAConstraint || m_filter_lid_cells[face.cell(1).localId()] != eCellInAConstraint)) {
581 const Cell& opposite_cell = (m_filter_lid_cells[face.cell(0).localId()] != eCellInAConstraint ? face.cell(0) : face.cell(1));
582 hg_contrib += _addNgb(opposite_cell, face, neighbourcells, contrib, difficultNgb,
583 ptrcommWeights, offset, lids,
true);
594 m_filter_lid_cells[listCell[0].localId()] = eCellReference;
595 for (Integer j = 1; j < listCell.size(); ++j)
596 m_filter_lid_cells[listCell[j].localId()] = eCellGrouped;
604void MeshPartitionerBase::
605getNeighbourNodesUidWithConstraints(Cell cell, Int64UniqueArray neighbournodes)
607 neighbournodes.resize(cell.nbNode());
609 for (Integer z = 0; z < cell.nbNode(); ++z) {
610 neighbournodes[z] = cell.node(z).uniqueId();
615Int32 MeshPartitionerBase::
616localIdWithConstraints(Cell cell)
618 return m_local_id_2_local_id_compacted[cell.localId()];
621Int32 MeshPartitionerBase::
622localIdWithConstraints(Int32 cell_lid)
625 return m_local_id_2_local_id_compacted[cell_lid];
629void MeshPartitionerBase::
630invertArrayLid2LidCompacted()
634 for (Integer i = 0; i < m_mesh->allCells().size(); i++) {
635 if (m_local_id_2_local_id_compacted[i] != -1)
636 m_local_id_2_local_id_compacted[index++] = i;
638 for (; index < m_mesh->allCells().size(); index++)
639 m_local_id_2_local_id_compacted[index] = -2;
643SharedArray<float> MeshPartitionerBase::
644cellsSizeWithConstraints()
647 return _cellsProjectWeights(mWgt);
650SharedArray<float> MeshPartitionerBase::
651cellsWeightsWithConstraints(Int32 max_nb_weight,
bool ask_lb_cells)
653 ARCANE_UNUSED(ask_lb_cells);
655 Int32 nb_weight = max_nb_weight;
657 Int32 nb_criteria = m_lb_mng_internal->nbCriteria(m_mesh);
659 if (max_nb_weight <= 0 || max_nb_weight > nb_criteria)
660 nb_weight = nb_criteria;
662 info() <<
"Number of weights " << nb_weight <<
" / " << nb_criteria;
665 return _cellsProjectWeights(mWgt, nb_weight);
671SharedArray<float> MeshPartitionerBase::
672_cellsProjectWeights(VariableCellArrayReal& cellWgtIn, Int32 nbWgt)
const
674 SharedArray<float> cellWgtOut(nbOwnCellsWithConstraints() * nbWgt);
675 if (nbWgt > cellWgtIn.arraySize()) {
676 ARCANE_FATAL(
"Asked for too many weights n={0} array_size={1}", nbWgt, cellWgtIn.arraySize());
680 if (m_filter_lid_cells[icell->localId()] == eCellClassical)
681 for (
int i = 0; i < nbWgt; ++i) {
682 float v =
static_cast<float>(cellWgtIn[icell][i]);
683 cellWgtOut[m_local_id_2_local_id_compacted[icell->localId()] * nbWgt + i] = v;
687 for (
auto& ptr : m_cells_with_constraints) {
689 for (
const auto& cell : ptr) {
690 for (
int i = 0; i < nbWgt; ++i)
691 w[i] += cellWgtIn[cell][i];
693 for (
int i = 0; i < nbWgt; ++i)
694 cellWgtOut[m_local_id_2_local_id_compacted[ptr[0].localId()] * nbWgt + i] = (float)(w[i]);
702SharedArray<float> MeshPartitionerBase::
703_cellsProjectWeights(VariableCellReal& cellWgtIn)
const
705 SharedArray<float> cellWgtOut(nbOwnCellsWithConstraints());
708 if (m_filter_lid_cells[icell->localId()] == eCellClassical)
709 cellWgtOut[m_local_id_2_local_id_compacted[icell->localId()]] = (float)cellWgtIn[icell];
711 for (
auto& ptr : m_cells_with_constraints) {
713 for (Cell cell : ptr) {
714 w += cellWgtIn[cell];
716 cellWgtOut[m_local_id_2_local_id_compacted[ptr[0].localId()]] = (float)w;
723bool MeshPartitionerBase::
724cellUsedWithConstraints(Cell cell)
726 eMarkCellWithConstraint marque = m_filter_lid_cells[cell.localId()];
728 return (marque == eCellClassical || marque == eCellReference);
731bool MeshPartitionerBase::
732cellUsedWithWeakConstraints(std::pair<Int64, Int64>& paired_item)
734 std::pair<Int64, Int64> other_pair(paired_item.second, paired_item.first);
735 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());
739void MeshPartitionerBase::
740changeCellOwner(Item cell, VariableItemInt32& cells_new_owner, Int32 new_owner)
745 cells_new_owner[cell] = new_owner;
747 if (m_filter_lid_cells[cell.localId()] == eCellReference) {
749 for (index = 0; index < m_cells_with_constraints.size() && m_cells_with_constraints[index][0] != cell; ++index) {
751 if (index == m_cells_with_constraints.size())
752 throw FatalErrorException(
"MeshPartitionerBase::changeCellOwner(): unable to find cell");
754 Array<Cell>& listCell = m_cells_with_constraints[index];
756 for (Integer i = 1; i < listCell.size(); i++)
757 cells_new_owner[listCell[i]] = new_owner;
767 m_lb_mng_internal->reset(m_mesh);
770 for (
int i = 0; i < nb_weight; ++i) {
777 (myvar)[icell] = weights[icell->localId() * nb_weight + i];
779 m_lb_mng_internal->addCriterion(myvar, m_mesh);
782 m_lb_mng_internal->initAccess(m_mesh);
783 m_lb_mng_internal->setMassAsCriterion(m_mesh,
false);
784 m_lb_mng_internal->setNbCellsAsCriterion(m_mesh,
false);
793 return math::max(m_lb_mng_internal->nbCriteria(m_mesh), 1);
796ArrayView<float> MeshPartitionerBase::
802void MeshPartitionerBase::
812template <
class ArrayType> Parallel::Request
819 mysize[0] = data.
size();
829 if (!header.
null()) {
834 ofile << sum << std::endl;
837 for (
int rank = 0; rank < pm->
commSize(); ++rank) {
839 pm->
recv(otherdata, rank,
true);
841 for (
int j = 0; (j < step) && myiter(); ++j, ++myiter)
842 ofile << *myiter <<
" ";
868 if ((m_filter_lid_cells[icell->localId()] != eCellClassical) && (m_filter_lid_cells[icell->localId()] != eCellReference))
871 uid[i++] = uids_ref[icell];
885 myiterf(); ++myiterf, ++myiterr)
886 (*myiterr) = (
Real)(*myiterf);
896 if ((m_filter_lid_cells[icell->localId()] != eCellClassical) && (m_filter_lid_cells[icell->localId()] != eCellReference))
900 for (
Integer z = 0, zs = (*icell).nbNode(); z < zs; ++z) {
901 const Node& node = (*icell).node(z);
902 my_coords[i] += coords[node];
916 if ((m_filter_lid_cells[icell->localId()] != eCellClassical) && (m_filter_lid_cells[icell->localId()] != eCellReference))
918 getNeighbourCellsUidWithConstraints(*icell, neighbourcells, &commWeights);
919 Int64 my_uid = uids_ref[icell];
920 for (
Integer j = 0; j < neighbourcells.
size(); ++j) {
921 if (neighbourcells[j] > my_uid)
923 Real3 tmp(
static_cast<Real>(my_uid + 1),
static_cast<Real>(neighbourcells[j] + 1), commWeights[j]);
929 StringBuilder myheader =
"%%MatrixMarket matrix coordinate real symmetric\n";
930 myheader += nbvertices;
932 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.