14#include "arcane/cartesianmesh/CartesianMeshCoarsening.h"
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/ValueConvert.h"
19#include "arcane/core/IMesh.h"
20#include "arcane/core/ItemGroup.h"
21#include "arcane/core/IParallelMng.h"
22#include "arcane/core/CartesianGridDimension.h"
23#include "arcane/core/IMeshModifier.h"
24#include "arcane/core/SimpleSVGMeshExporter.h"
25#include "arcane/core/ItemPrinter.h"
26#include "arcane/core/MeshStats.h"
28#include "arcane/cartesianmesh/ICartesianMesh.h"
29#include "arcane/cartesianmesh/CellDirectionMng.h"
31#include <unordered_set>
42CartesianMeshCoarsening::
47 if (
auto v = Convert::Type<Int32>::tryParseFromEnvironment(
"ARCANE_CARTESIANMESH_COARSENING_VERBOSITY_LEVEL",
true))
48 m_verbosity_level = v.value();
55Int64 CartesianMeshCoarsening::
56_getMaxUniqueId(
const ItemGroup& group)
61 if (max_offset < item.uniqueId())
62 max_offset = item.uniqueId();
70void CartesianMeshCoarsening::
73 if (m_is_create_coarse_called)
75 m_is_create_coarse_called =
true;
77 const bool is_verbose = m_verbosity_level > 0;
78 IMesh* mesh = m_cartesian_mesh->mesh();
79 Integer nb_patch = m_cartesian_mesh->nbPatch();
81 ARCANE_FATAL(
"This method is only valid for 1 patch (nb_patch={0})", nb_patch);
83 if (!mesh->isAmrActivated())
90 Integer nb_dir = mesh->dimension();
96 info() <<
"CoarseCartesianMesh nb_direction=" << nb_dir;
98 for (
Integer idir = 0; idir < nb_dir; ++idir) {
101 info() <<
"NB_OWN_CELL dir=" << idir <<
" n=" << nb_own_cell;
102 if ((nb_own_cell % 2) != 0)
103 ARCANE_FATAL(
"Invalid number of cells ({0}) for direction {1}. Should be a multiple of 2",
111 Int64 max_cell_uid = _getMaxUniqueId(mesh->allCells());
112 Int64 max_face_uid = _getMaxUniqueId(mesh->allFaces());
114 m_first_own_cell_unique_id_offset = coarse_grid_cell_offset;
123 CartesianGridDimension::CellUniqueIdComputer2D refined_cell_uid_computer(refined_grid_dim.getCellComputer2D(0));
124 CartesianGridDimension::NodeUniqueIdComputer2D refined_node_uid_computer(refined_grid_dim.getNodeComputer2D(0));
125 CartesianGridDimension::CellUniqueIdComputer2D coarse_cell_uid_computer(coarse_grid_dim.getCellComputer2D(coarse_grid_cell_offset));
126 CartesianGridDimension::FaceUniqueIdComputer2D coarse_face_uid_computer(coarse_grid_dim.getFaceComputer2D(coarse_grid_cell_offset));
136 Int32 nb_coarse_face = 0;
137 Int32 nb_coarse_cell = 0;
143 Int64x3 cell_xy = refined_cell_uid_computer.compute(cell_uid);
144 const Int64 cell_x = cell_xy.x;
145 const Int64 cell_y = cell_xy.y;
148 if ((cell_x % 2) != 0 || (cell_y % 2) != 0)
151 info() <<
"CELLCoarse uid=" << cell_uid <<
" x=" << cell_x <<
" y=" << cell_y;
152 const Int64 coarse_cell_x = cell_x / 2;
153 const Int64 coarse_cell_y = cell_y / 2;
154 std::array<Int64, 4> node_uids_container;
156 node_uids[0] = refined_node_uid_computer.compute(cell_x + 0, cell_y + 0);
157 node_uids[1] = refined_node_uid_computer.compute(cell_x + 2, cell_y + 0);
158 node_uids[2] = refined_node_uid_computer.compute(cell_x + 2, cell_y + 2);
159 node_uids[3] = refined_node_uid_computer.compute(cell_x + 0, cell_y + 2);
161 info() <<
"CELLNodes uid=" << node_uids;
162 std::array<Int64, 4> coarse_face_uids = coarse_face_uid_computer.computeForCell(coarse_cell_x, coarse_cell_y);
165 for (
Int32 z = 0; z < 4; ++z) {
167 faces_infos.
add(IT_Line2);
168 faces_infos.
add(coarse_face_uids[z]);
169 faces_infos.
add(node_uids[lface.
node(0)]);
170 faces_infos.
add(node_uids[lface.
node(1)]);
175 cells_infos.
add(IT_Quad4);
176 cells_infos.
add(coarse_cell_uid_computer.compute(coarse_cell_x, coarse_cell_y));
177 for (
Int32 z = 0; z < 4; ++z)
178 cells_infos.
add(node_uids[z]);
186 cells_local_ids.
resize(nb_coarse_cell);
187 faces_local_ids.
resize(nb_coarse_face);
221 mesh->modifier()->endUpdate();
225 m_coarse_cells.resize(nb_coarse_cell);
226 m_refined_cells.resize(nb_coarse_cell, 4);
232 Int32 coarse_index = 0;
233 std::array<Int32, 4> sub_cell_lids_container;
237 Cell coarse_cell = *icell;
242 m_coarse_cells[coarse_index] = coarse_cell.
itemLocalId();
243 Cell first_child_cell = cells[first_child_cell_local_ids[coarse_index]];
246 sub_cell_lids[0] = first_child_cell.
localId();
247 sub_cell_lids[1] = cdm_x[first_child_cell].next().localId();
248 sub_cell_lids[2] = cdm_y[CellLocalId(sub_cell_lids[1])].next().localId();
249 sub_cell_lids[3] = cdm_y[first_child_cell].next().localId();
251 info() <<
"AddChildForCoarseCell i=" << coarse_index <<
" coarse=" <<
ItemPrinter(coarse_cell)
252 <<
" children_lid=" << sub_cell_lids;
253 for (
Int32 z = 0; z < 4; ++z) {
254 CellLocalId sub_local_id = CellLocalId(sub_cell_lids[z]);
255 m_refined_cells[coarse_index][z] = sub_local_id;
257 info() <<
" AddParentCellToCell: z=" << z <<
" child=" <<
ItemPrinter(cells[sub_local_id]);
270 const bool dump_coarse_mesh =
false;
271 if (dump_coarse_mesh) {
272 String filename = String::format(
"mesh_coarse_{0}.svg", my_rank);
273 std::ofstream ofile(filename.
localstr());
275 writer.
write(mesh->allCells());
282void CartesianMeshCoarsening::
285 if (!m_is_create_coarse_called)
286 ARCANE_FATAL(
"You need to call createCoarseCells() before");
287 if (m_is_remove_refined_called)
289 m_is_remove_refined_called =
true;
291 IMesh* mesh = m_cartesian_mesh->mesh();
296 std::unordered_set<Int32> coarse_cells_set;
297 for (
Int32 cell_lid : m_coarse_cells)
298 coarse_cells_set.insert(cell_lid);
302 Int32 local_id = icell.itemLocalId();
304 if (!cell.
isOwn() || (coarse_cells_set.find(local_id) != coarse_cells_set.end()))
305 cells_to_remove.
add(local_id);
321 _recomputeMeshGenerationInfo();
324 m_cartesian_mesh->computeDirections();
332void CartesianMeshCoarsening::
333_recomputeMeshGenerationInfo()
335 IMesh* mesh = m_cartesian_mesh->mesh();
336 auto* cmgi = ICartesianMeshGenerationInfo::getReference(mesh,
false);
345 cmgi->setOwnCellOffsets(v[0] / cf, v[1] / cf, v[2] / cf);
348 ConstArrayView<Int64> v = cmgi->globalNbCells();
349 cmgi->setGlobalNbCells(v[0] / cf, v[1] / cf, v[2] / cf);
352 ConstArrayView<Int32> v = cmgi->ownNbCells();
353 cmgi->setOwnNbCells(v[0] / cf, v[1] / cf, v[2] / cf);
355 cmgi->setFirstOwnCellUniqueId(m_first_own_cell_unique_id_offset);
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Modifiable view of an array of type T.
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.
Information about the dimensions of a Cartesian grid.
Info about the cells in a specific X, Y, or Z direction of a structured mesh.
Int64 globalNbCell() const
Global number of cells in this direction.
Int32 ownNbCell() const
Number of own cells in this direction.
View of cell information.
CellLocalId itemLocalId() const
Local identifier of the entity in the processor subdomain.
Constant view of an array of type T.
Interface of a Cartesian mesh.
Interface of an entity family.
virtual void notifyItemsOwnerChanged()=0
Notifies that the entities specific to the family's subdomain have been modified.
virtual ItemVectorView view(Int32ConstArrayView local_ids)=0
View on the entities.
virtual void itemsUniqueIdToLocalId(Int32ArrayView local_ids, Int64ConstArrayView unique_ids, bool do_fatal=true) const =0
Converts an array of unique numbers to local numbers.
Mesh modification interface.
virtual void updateGhostLayers()=0
Updates the ghost layer.
virtual void setDynamic(bool v)=0
Sets the property indicating whether the mesh can evolve.
virtual void removeCells(Int32ConstArrayView cells_local_id)=0
Removes cells.
virtual void endUpdate()=0
Notifies the instance that mesh modification is finished.
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual char reduce(eReduceType rt, char v)=0
Performs a reduction of type rt on the real v and returns the value.
Int32 flags() const
Flags of the entity.
Utility class for printing information about an entity.
Local information about a cell face.
Integer node(Integer i) const
Local index in the cell of the i-th node of the face.
Info on a mesh entity type.
LocalFace localFace(Integer id) const
Local connectivity of the i-th face of the cell.
Node node(Int32 i) const
i-th node of the entity
const ItemTypeInfo * typeInfo() const
Information about the entity type.
impl::MutableItemBase mutableItemBase() const
Mutable internal part of the entity.
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Int32 owner() const
Owner subdomain number of the entity.
ItemUniqueId uniqueId() const
Unique identifier across all domains.
constexpr bool isOwn() const
true if the entity belongs to the subdomain
impl::ItemBase itemBase() const
Internal part of the entity.
Arguments for IMeshModifier::addCells().
Arguments for IMeshModifier::addFaces().
void dumpStats() override
Prints mesh information.
void setOwner(Integer suid, Int32 current_sub_domain)
Sets the sub-domain number of the entity owner.
void addFlags(Int32 added_flags)
Adds the flags added_flags to those of the entity.
void removeFlags(Int32 removed_flags)
Removes the flags removed_flags from those of the entity.
void write(const CellGroup &cells)
Exports the entities of the cells group.
Unicode character string.
const char * localstr() const
Returns the conversion of the instance into UTF-8 encoding.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
T max(const T &a, const T &b, const T &c)
Returns the maximum of three elements.
@ ReduceMax
Maximum of values.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
std::int32_t Int32
Signed integer type of 32 bits.