Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
MaterialModifierOperation.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* MaterialModifierOperation.cc (C) 2000-2024 */
9/* */
10/* Operation for adding/removing cells from a material. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/materials/internal/MaterialModifierOperation.h"
15
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/FatalErrorException.h"
19#include "arcane/utils/IMemoryRessourceMng.h"
20
21#include "arcane/core/ItemPrinter.h"
22#include "arcane/core/ItemGroup.h"
23#include "arcane/core/IItemFamily.h"
24#include "arcane/core/materials/IMeshMaterial.h"
25#include "arcane/core/materials/internal/IMeshComponentInternal.h"
26
27#include "arcane/materials/internal/MeshMaterialVariableIndexer.h"
28
29/*---------------------------------------------------------------------------*/
30/*---------------------------------------------------------------------------*/
31
32namespace Arcane::Materials
33{
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38MaterialModifierOperation::
39MaterialModifierOperation()
40: m_ids(MemoryUtils::getDefaultDataAllocator())
41{
42}
43
44/*---------------------------------------------------------------------------*/
45/*---------------------------------------------------------------------------*/
46
47MaterialModifierOperation::
48MaterialModifierOperation(IMeshMaterial* mat, SmallSpan<const Int32> ids, bool is_add)
49: MaterialModifierOperation()
50{
51 m_mat = mat;
52 m_is_add = is_add;
53 m_ids.resize(ids.size());
54 MemoryUtils::copy<Int32>(m_ids, ids);
55}
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59
60/*!
61 * \brief Checks if the cells \a ids are already in the material \a mat.
62 *
63 * If \a operation==eOperation::Add, checks that the cells of \a ids
64 * are not already in the material and if \a operation==eOperation::Remove, checks
65 * that the cells of \a ids are in the material.
66 *
67 * Also checks that an element is present only once in the list \a ids.
68 *
69 * Returns the number of errors.
70 */
71Int32 MaterialModifierOperation::
72_checkMaterialPresence(MaterialModifierOperation* operation)
73{
74 IMeshMaterial* mat = operation->material();
75 SmallSpan<const Int32> ids = operation->ids();
76
77 const MeshMaterialVariableIndexer* indexer = mat->_internalApi()->variableIndexer();
78 IItemFamily* item_family = mat->cells().itemFamily();
79 ItemInfoListView items_internal(item_family);
80 Integer max_local_id = item_family->maxLocalId();
81 UniqueArray<bool> presence_flags(max_local_id, false);
82 SmallSpan<const Int32> mat_local_ids = indexer->localIds();
83 Integer nb_error = 0;
84 String name = mat->name();
85 ITraceMng* tm = mat->traceMng();
86
87 for (Int32 lid : ids) {
88 if (presence_flags[lid]) {
89 tm->info() << "ERROR: item " << ItemPrinter(items_internal[lid])
90 << " is present several times in add/remove list for material mat=" << name;
91 ++nb_error;
92 }
93 presence_flags[lid] = true;
94 }
95
96 if (operation->isAdd()) {
97 for (Int32 lid : mat_local_ids) {
98 if (presence_flags[lid]) {
99 tm->info() << "ERROR: item " << ItemPrinter(items_internal[lid])
100 << " is already in material mat=" << name;
101 ++nb_error;
102 }
103 }
104 }
105 else {
106 for (Int32 lid : mat_local_ids) {
107 presence_flags[lid] = false;
108 }
109
110 for (Int32 lid : ids) {
111 if (presence_flags[lid]) {
112 tm->info() << "ERROR: item " << ItemPrinter(items_internal[lid])
113 << " is not in material mat=" << name;
114 ++nb_error;
115 }
116 }
117 }
118
119 return nb_error;
120}
121
122/*---------------------------------------------------------------------------*/
123/*---------------------------------------------------------------------------*/
124
125/*!
126 * \brief Filters the array of cells \a ids so that it is valid.
127 *
128 * This method allows filtering the values of \a ids so that
129 * only valid values remain so that they can be added
130 * (if \a do_add is true) or removed (if \a do_add is false) from the material
131 * \a mat.
132 *
133 * The valid values are stored in \a valid_ids.
134 */
135void MaterialModifierOperation::
136_filterValidIds(MaterialModifierOperation* operation, Int32Array& valid_ids)
137{
138 IMeshMaterial* mat = operation->material();
139 const bool do_add = operation->isAdd();
140 SmallSpan<const Int32> ids = operation->ids();
141 const MeshMaterialVariableIndexer* indexer = mat->_internalApi()->variableIndexer();
142 const IItemFamily* item_family = mat->cells().itemFamily();
143 Integer max_local_id = item_family->maxLocalId();
144 UniqueArray<bool> presence_flags(max_local_id, false);
145 SmallSpan<const Int32> mat_local_ids = indexer->localIds();
146 ITraceMng* tm = mat->traceMng();
147
148 UniqueArray<Int32> unique_occurence_lids;
149 unique_occurence_lids.reserve(ids.size());
150
151 for (Int32 lid : ids) {
152 if (!presence_flags[lid]) {
153 unique_occurence_lids.add(lid);
154 presence_flags[lid] = true;
155 }
156 }
157
158 valid_ids.clear();
159
160 if (do_add) {
161 for (Int32 lid : mat_local_ids) {
162 if (presence_flags[lid]) {
163 ;
164 }
165 else
166 valid_ids.add(lid);
167 }
168 }
169 else {
170 for (Int32 lid : mat_local_ids)
171 presence_flags[lid] = false;
172
173 for (Int32 lid : unique_occurence_lids) {
174 if (presence_flags[lid]) {
175 ;
176 }
177 else
178 valid_ids.add(lid);
179 }
180 }
181 tm->info(4) << "FILTERED_IDS n=" << valid_ids.size() << " ids=" << valid_ids;
182}
183
184/*---------------------------------------------------------------------------*/
185/*---------------------------------------------------------------------------*/
186
187void MaterialModifierOperation::
188filterIds()
189{
190 // TODO: change the default to 'false' and test both configurations
191 const bool filter_invalid = true;
192 Integer nb_error = _checkMaterialPresence(this);
193 if (nb_error != 0) {
194 if (filter_invalid) {
195 UniqueArray<Int32> filtered_ids;
196 _filterValidIds(this, filtered_ids);
197 m_ids.swap(filtered_ids);
198 }
199 else
200 ARCANE_FATAL("Invalid values for adding items in material name={0} nb_error={1}",
201 m_mat->name(), nb_error);
202 }
203}
204
205/*---------------------------------------------------------------------------*/
206/*---------------------------------------------------------------------------*/
207
208} // End namespace Arcane::Materials
209
210/*---------------------------------------------------------------------------*/
211/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Memory and allocator management functions.
Always enables tracing in Arcane parts concerning materials.
IMemoryAllocator * getDefaultDataAllocator()
Default allocator for data.
Int32 Integer
Type representing an integer.