Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
MeshMaterialVariable.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/* MeshMaterialVariable.cc (C) 2000-2025 */
9/* */
10/* Variable on a mesh material. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/materials/MeshMaterialVariable.h"
15
16#include "arcane/utils/NotImplementedException.h"
17#include "arcane/utils/TraceInfo.h"
18#include "arcane/utils/ITraceMng.h"
19#include "arcane/utils/Real2.h"
20#include "arcane/utils/Real3.h"
21#include "arcane/utils/Real2x2.h"
22#include "arcane/utils/Real3x3.h"
23#include "arcane/utils/Mutex.h"
25#include "arcane/utils/PlatformUtils.h"
26
27#include "arcane/core/materials/IMeshMaterial.h"
28#include "arcane/core/materials/ComponentItemVectorView.h"
29#include "arcane/core/Variable.h"
30#include "arcane/core/VariableDependInfo.h"
31#include "arcane/core/MeshVariable.h"
32#include "arcane/core/IItemFamily.h"
33#include "arcane/core/IMesh.h"
34#include "arcane/core/IObserver.h"
35#include "arcane/core/IParallelMng.h"
37#include "arcane/core/materials/internal/IMeshComponentInternal.h"
38#include "arcane/core/materials/internal/IMeshMaterialMngInternal.h"
39
40#include "arcane/materials/MaterialVariableBuildInfo.h"
41#include "arcane/materials/MatItemEnumerator.h"
42#include "arcane/materials/MeshMaterialVariableRef.h"
43#include "arcane/materials/MeshMaterialVariableDependInfo.h"
44#include "arcane/materials/IMeshMaterialVariableComputeFunction.h"
45#include "arcane/materials/IMeshMaterialVariableSynchronizer.h"
46#include "arcane/materials/internal/MeshMaterialVariablePrivate.h"
47#include "arcane/materials/internal/MeshMaterialVariableIndexer.h"
48
49#include "arcane/accelerator/RunCommandLoop.h"
50
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
54namespace Arcane::Materials
55{
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59
60MeshMaterialVariablePrivate::
61MeshMaterialVariablePrivate(const MaterialVariableBuildInfo& v, MatVarSpace mvs,
62 MeshMaterialVariable* variable)
63: m_name(v.name())
64, m_material_mng(v.materialMng())
65, m_var_space(mvs)
66, m_variable(variable)
67{
68 // For testing only
69 if (!platform::getEnvironmentVariable("ARCANE_NO_RECURSIVE_DEPEND").null())
70 m_has_recursive_depend = false;
71}
72
73/*---------------------------------------------------------------------------*/
74/*---------------------------------------------------------------------------*/
75
76MeshMaterialVariablePrivate::
77~MeshMaterialVariablePrivate()
78{
79 if (m_global_variable_changed_observer)
80 std::cerr << "WARNING: MeshMaterialVariablePrivate: in destructor: observer is not destroyed\n";
81}
82
83/*---------------------------------------------------------------------------*/
84/*---------------------------------------------------------------------------*/
85
86Int32 MeshMaterialVariablePrivate::
87dataTypeSize() const
88{
89 return m_variable->dataTypeSize();
90}
91
92/*---------------------------------------------------------------------------*/
93/*---------------------------------------------------------------------------*/
94
95void MeshMaterialVariablePrivate::
96copyToBuffer(SmallSpan<const MatVarIndex> matvar_indexes,
97 Span<std::byte> bytes, RunQueue* queue) const
98{
99 m_variable->_copyToBuffer(matvar_indexes, bytes, queue);
100}
101
102/*---------------------------------------------------------------------------*/
103/*---------------------------------------------------------------------------*/
104
105void MeshMaterialVariablePrivate::
106copyFromBuffer(SmallSpan<const MatVarIndex> matvar_indexes,
107 Span<const std::byte> bytes, RunQueue* queue)
108{
109 m_variable->_copyFromBuffer(matvar_indexes, bytes, queue);
110}
111
112/*---------------------------------------------------------------------------*/
113/*---------------------------------------------------------------------------*/
114
115Ref<IData> MeshMaterialVariablePrivate::
116internalCreateSaveDataRef(Integer nb_value)
117{
118 return m_variable->_internalCreateSaveDataRef(nb_value);
119}
120
121/*---------------------------------------------------------------------------*/
122/*---------------------------------------------------------------------------*/
123
124void MeshMaterialVariablePrivate::
125saveData(IMeshComponent* component, IData* data)
126{
127 m_variable->_saveData(component, data);
128}
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
132
133void MeshMaterialVariablePrivate::
134restoreData(IMeshComponent* component, IData* data, Integer data_index,
135 Int32ConstArrayView ids, bool allow_null_id)
136{
137 m_variable->_restoreData(component, data, data_index, ids, allow_null_id);
138}
139
140/*---------------------------------------------------------------------------*/
141/*---------------------------------------------------------------------------*/
142
143void MeshMaterialVariablePrivate::
144copyBetweenPartialAndGlobal(const CopyBetweenPartialAndGlobalArgs& args)
145{
146 m_variable->_copyBetweenPartialAndGlobal(args);
147}
148
149/*---------------------------------------------------------------------------*/
150/*---------------------------------------------------------------------------*/
151
152void MeshMaterialVariablePrivate::
153initializeNewItemsWithZero(InitializeWithZeroArgs& args)
154{
155 m_variable->_initializeNewItemsWithZero(args);
156}
157
158/*---------------------------------------------------------------------------*/
159/*---------------------------------------------------------------------------*/
160
161void MeshMaterialVariablePrivate::
162syncReferences(bool check_resize)
163{
164 m_variable->_syncReferences(check_resize);
165}
166
167/*---------------------------------------------------------------------------*/
168/*---------------------------------------------------------------------------*/
169
170void MeshMaterialVariablePrivate::
171resizeForIndexer(ResizeVariableIndexerArgs& args)
172{
173 m_variable->_resizeForIndexer(args);
174}
175
176/*---------------------------------------------------------------------------*/
177/*---------------------------------------------------------------------------*/
178
179/*---------------------------------------------------------------------------*/
180/*---------------------------------------------------------------------------*/
181
182MeshMaterialVariable::
183MeshMaterialVariable(const MaterialVariableBuildInfo& v, MatVarSpace mvs)
184: m_p(new MeshMaterialVariablePrivate(v, mvs, this))
186{
187}
188
189/*---------------------------------------------------------------------------*/
190/*---------------------------------------------------------------------------*/
191
192MeshMaterialVariable::
193~MeshMaterialVariable()
194{
195 delete m_p;
196}
197
198/*---------------------------------------------------------------------------*/
199/*---------------------------------------------------------------------------*/
200
201void MeshMaterialVariable::
202incrementReference()
203{
204 // This method should only be called by the copy constructor
205 // of a reference. In other cases, the reference counter is incremented
206 // automatically.
207 // TODO: check if using an AtomicInt32 for the reference counter is
208 // preferable, which would allow removing the lock.
209 Mutex::ScopedLock sl(m_p->materialMng()->variableLock());
210 ++m_p->m_nb_reference;
211}
212
213/*---------------------------------------------------------------------------*/
214/*---------------------------------------------------------------------------*/
215
216void MeshMaterialVariable::
217addVariableRef(MeshMaterialVariableRef* ref)
218{
219 Mutex::ScopedLock sl(m_p->materialMng()->variableLock());
220 // The increment of m_p->m_nb_reference is done in getReference()
221 ref->setNextReference(m_p->m_first_reference);
222 if (m_p->m_first_reference) {
223 MeshMaterialVariableRef* _list = m_p->m_first_reference;
224 if (_list->previousReference())
225 _list->previousReference()->setNextReference(ref);
226 _list->setPreviousReference(ref);
227 }
228 else {
229 ref->setPreviousReference(nullptr);
230 }
231 m_p->m_first_reference = ref;
232}
233
234/*---------------------------------------------------------------------------*/
235/*---------------------------------------------------------------------------*/
236
237void MeshMaterialVariable::
238removeVariableRef(MeshMaterialVariableRef* ref)
239{
240 Mutex::ScopedLock sl(m_p->materialMng()->variableLock());
241
242 MeshMaterialVariableRef* tmp = ref;
243 if (tmp->previousReference())
244 tmp->previousReference()->setNextReference(tmp->nextReference());
245 if (tmp->nextReference())
246 tmp->nextReference()->setPreviousReference(tmp->previousReference());
247 if (m_p->m_first_reference == tmp)
248 m_p->m_first_reference = m_p->m_first_reference->nextReference();
249
250 // The reference may be used later, so we must not forget
251 // to remove the previous and next.
252 ref->setNextReference(nullptr);
253 ref->setPreviousReference(nullptr);
254
255 Int32 nb_ref = --m_p->m_nb_reference;
256
257 // Checks that the number of references is valid.
258 // In case of an error, we cannot display anything, because it is possible that m_p has
259 // already been destroyed.
260 if (nb_ref < 0)
261 ARCANE_FATAL("Invalid reference number for variable");
262
263 // When there are no more references on this variable, it signals to the
264 // variable manager and destroys itself
265 if (nb_ref == 0) {
266 // Warning: the observer must first be destroyed,
267 // because removeVariable() may destroy the global variable if there are no
268 // more references on it and since an observer will remain on it,
269 // this will cause a memory leak because the associated observer will not be
270 // destroyed.
271 delete m_p->m_global_variable_changed_observer;
272 m_p->m_global_variable_changed_observer = nullptr;
273 m_p->materialMng()->_internalApi()->removeVariable(this);
274 delete this;
275 }
276}
277
278/*---------------------------------------------------------------------------*/
279/*---------------------------------------------------------------------------*/
280
281MeshMaterialVariableRef* MeshMaterialVariable::
282firstReference() const
283{
284 return m_p->m_first_reference;
285}
286
287/*---------------------------------------------------------------------------*/
288/*---------------------------------------------------------------------------*/
289
290String MeshMaterialVariable::
291name() const
292{
293 return m_p->name();
294}
295
296/*---------------------------------------------------------------------------*/
297/*---------------------------------------------------------------------------*/
298
299IVariable* MeshMaterialVariable::
300materialVariable(IMeshMaterial* mat)
301{
302 Int32 index = mat->_internalApi()->variableIndexer()->index() + 1;
303 return m_p->m_refs[index]->variable();
304}
305
306/*---------------------------------------------------------------------------*/
307/*---------------------------------------------------------------------------*/
308
309void MeshMaterialVariable::
310setKeepOnChange(bool v)
311{
312 m_p->m_keep_on_change = v;
313}
314
315/*---------------------------------------------------------------------------*/
316/*---------------------------------------------------------------------------*/
317
318bool MeshMaterialVariable::
319keepOnChange() const
320{
321 return m_p->m_keep_on_change;
322}
323
324/*---------------------------------------------------------------------------*/
325/*---------------------------------------------------------------------------*/
326
327void MeshMaterialVariable::
328update(IMeshMaterial* mat)
329{
330 if (m_p->hasRecursiveDepend()) {
331 for (VariableDependInfo& vdi : m_p->m_depends) {
332 vdi.variable()->update();
333 }
334
335 for (MeshMaterialVariableDependInfo& vdi : m_p->m_mat_depends) {
336 vdi.variable()->update(mat);
337 }
338 }
339 Int32 mat_id = mat->id();
340
341 bool need_update = false;
342 Int64 modified_time = m_p->m_modified_times[mat_id];
343 for (VariableDependInfo& vdi : m_p->m_depends) {
344 Int64 mt = vdi.variable()->modifiedTime();
345 if (mt > modified_time) {
346 need_update = true;
347 break;
348 }
349 }
350 if (!need_update) {
351 for (MeshMaterialVariableDependInfo& vdi : m_p->m_mat_depends) {
352 Int64 mt = vdi.variable()->modifiedTime(mat);
353 if (mt > modified_time) {
354 need_update = true;
355 break;
356 }
357 }
358 }
359
360 if (need_update) {
361 IMeshMaterialVariableComputeFunction* cf = m_p->m_compute_function.get();
362 if (cf) {
363 cf->execute(mat);
364 }
365 else {
366 ARCANE_FATAL("no compute function for variable '{0}'", name());
367 }
368 }
369}
370
371/*---------------------------------------------------------------------------*/
372/*---------------------------------------------------------------------------*/
373
374void MeshMaterialVariable::
375setUpToDate(IMeshMaterial* mat)
376{
377 Int32 id = mat->id();
378 m_p->m_modified_times[id] = IVariable::incrementModifiedTime();
379}
380
381Int64 MeshMaterialVariable::
382modifiedTime(IMeshMaterial* mat)
383{
384 Int32 id = mat->id();
385 return m_p->m_modified_times[id];
386}
387
388void MeshMaterialVariable::
389addDepend(IMeshMaterialVariable* var)
390{
391 m_p->m_mat_depends.add(MeshMaterialVariableDependInfo(var, TraceInfo()));
392}
393
394void MeshMaterialVariable::
395addDepend(IMeshMaterialVariable* var, const TraceInfo& tinfo)
396{
397 m_p->m_mat_depends.add(MeshMaterialVariableDependInfo(var, tinfo));
398}
399
400void MeshMaterialVariable::
401removeDepend(IMeshMaterialVariable* var)
402{
403 ARCANE_UNUSED(var);
404 throw NotImplementedException(A_FUNCINFO);
405}
406
407void MeshMaterialVariable::
408addDepend(IVariable* var)
409{
410 m_p->m_depends.add(VariableDependInfo(var, IVariable::DPT_CurrentTime, TraceInfo()));
411}
412
413void MeshMaterialVariable::
414addDepend(IVariable* var, const TraceInfo& tinfo)
415{
416 m_p->m_depends.add(VariableDependInfo(var, IVariable::DPT_CurrentTime, tinfo));
417}
418
419void MeshMaterialVariable::
420removeDepend(IVariable* var)
421{
422 ARCANE_UNUSED(var);
423 throw NotImplementedException(A_FUNCINFO);
424}
425
426void MeshMaterialVariable::
427setComputeFunction(IMeshMaterialVariableComputeFunction* v)
428{
429 m_p->m_compute_function = v;
430}
431
433computeFunction()
434{
435 return m_p->m_compute_function.get();
436}
437
438void MeshMaterialVariable::
439dependInfos(Array<VariableDependInfo>& infos,
441{
442 for (VariableDependInfo& vdi : m_p->m_depends) {
443 infos.add(vdi);
444 }
445
446 for (MeshMaterialVariableDependInfo& vdi : m_p->m_mat_depends) {
447 mat_infos.add(vdi);
448 }
449}
450
451ITraceMng* MeshMaterialVariable::
452_traceMng() const
453{
454 return m_p->materialMng()->traceMng();
455}
456
457/*---------------------------------------------------------------------------*/
458/*---------------------------------------------------------------------------*/
459
460MatVarSpace MeshMaterialVariable::
461space() const
462{
463 return m_p->space();
464}
465
466/*---------------------------------------------------------------------------*/
467/*---------------------------------------------------------------------------*/
468
469/*!
470 * \brief Converts a view of MatVarIndex to a view of Int32.
471 *
472 * Assumes that a MatVarIndex contains 2 Int32.
473 */
474SmallSpan<const Int32> MeshMaterialVariable::
475_toInt32Indexes(SmallSpan<const MatVarIndex> indexes)
476{
477 static_assert(sizeof(MatVarIndex) == 2 * sizeof(Int32), "Bad size for MatVarIndex");
478 auto* ptr = reinterpret_cast<const Int32*>(indexes.data());
479 return { ptr, indexes.size() * 2 };
480}
481
482/*---------------------------------------------------------------------------*/
483/*---------------------------------------------------------------------------*/
484
485void MeshMaterialVariable::
486_copyToBuffer(SmallSpan<const MatVarIndex> matvar_indexes,
487 Span<std::byte> bytes, RunQueue* queue) const
488{
489 const Integer one_data_size = dataTypeSize();
490 SmallSpan<const Int32> indexes(_toInt32Indexes(matvar_indexes));
491 const Int32 nb_item = matvar_indexes.size();
492 MutableMemoryView destination_buffer(makeMutableMemoryView(bytes.data(), one_data_size, nb_item));
493 ConstMultiMemoryView source_view(m_views_as_bytes.view(), one_data_size);
494 MemoryUtils::copyWithIndexedSource(destination_buffer, source_view, indexes, queue);
495}
496
497/*---------------------------------------------------------------------------*/
498/*---------------------------------------------------------------------------*/
499
500void MeshMaterialVariable::
501_copyFromBuffer(SmallSpan<const MatVarIndex> matvar_indexes,
502 Span<const std::byte> bytes, RunQueue* queue)
503{
504 const Int32 one_data_size = dataTypeSize();
505 SmallSpan<const Int32> indexes(_toInt32Indexes(matvar_indexes));
506 const Int32 nb_item = matvar_indexes.size();
507 MutableMultiMemoryView destination_view(m_views_as_bytes.view(), one_data_size);
508 ConstMemoryView source_buffer(makeConstMemoryView(bytes.data(), one_data_size, nb_item));
509 MemoryUtils::copyWithIndexedDestination(destination_view, source_buffer, indexes, queue);
510}
511
512/*---------------------------------------------------------------------------*/
513/*---------------------------------------------------------------------------*/
514
515void MeshMaterialVariable::
516_genericCopyTo(Span<const std::byte> input,
517 SmallSpan<const Int32> input_indexes,
518 Span<std::byte> output,
519 SmallSpan<const Int32> output_indexes,
520 const RunQueue& queue, Int32 data_type_size)
521{
522 // TODO: verify identical index sizes
523 Integer nb_value = input_indexes.size();
524 auto command = makeCommand(queue);
525
526 ARCANE_CHECK_ACCESSIBLE_POINTER(queue, output.data());
527 ARCANE_CHECK_ACCESSIBLE_POINTER(queue, input.data());
528 ARCANE_CHECK_ACCESSIBLE_POINTER(queue, input_indexes.data());
529 ARCANE_CHECK_ACCESSIBLE_POINTER(queue, output_indexes.data());
530 const Int32 dim2_size = data_type_size;
531
532 command << RUNCOMMAND_LOOP1(iter, nb_value)
533 {
534 auto [i] = iter();
535
536 Int32 output_base = output_indexes[i] * dim2_size;
537 Int32 input_base = input_indexes[i] * dim2_size;
538 for (Int32 j = 0; j < dim2_size; ++j)
539 output[output_base + j] = input[input_base + j];
540 };
541}
542
543/*---------------------------------------------------------------------------*/
544/*---------------------------------------------------------------------------*/
545
546IMeshMaterialVariableInternal* MeshMaterialVariable::
547_internalApi()
548{
549 return m_p->_internalApi();
550}
551
552/*---------------------------------------------------------------------------*/
553/*---------------------------------------------------------------------------*/
554
555} // End namespace Arcane::Materials
556
557/*---------------------------------------------------------------------------*/
558/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
File containing declarations concerning the message passing model.
Memory and allocator management functions.
#define RUNCOMMAND_LOOP1(iter_name, x1,...)
1D loop on accelerator with additional arguments.
Base class for 1D data vectors.
void add(ConstReferenceType val)
Adds element val to the end of the array.
Interface of a variable.
Definition IVariable.h:40
virtual Int64 modifiedTime()=0
Time when the variable was updated.
static Int64 incrementModifiedTime()
Increments the modification counter and returns its value before modification.
Definition Variable.cc:206
virtual void update()=0
Recalculates the variable if necessary.
virtual Int32 id() const =0
Component identifier.
virtual IMeshComponentInternal * _internalApi()=0
Internal API.
virtual void execute(IMeshMaterial *mat)=0
Executes the calculation function.
Interface of a material variable on a mesh.
virtual Int64 modifiedTime(IMeshMaterial *mat)=0
Time when the variable was updated.
Represents an index on material and environment variables.
MeshMaterialVariableRef * nextReference()
Next reference (or null) on variable().
MeshMaterialVariableRef * previousReference()
Previous reference (or null) on variable().
String name() const override
Name of the variable.
View of an array of elements of type T.
Definition Span.h:805
constexpr __host__ __device__ pointer data() const noexcept
Pointer to the start of the view.
Definition Span.h:539
constexpr __host__ __device__ SizeType size() const noexcept
Returns the size of the array.
Definition Span.h:327
Information about a variable dependency.
IVariable * variable() const
Variable.
RunCommand makeCommand(const RunQueue &run_queue)
Creates a command associated with the queue run_queue.
Always enables tracing in Arcane parts concerning materials.
MatVarSpace
Definition space for a material variable.
MemoryAllocationOptions getAllocatorForMostlyReadOnlyData()
Default allocator for mostly read-only data.
ARCANE_DATATYPE_EXPORT Integer dataTypeSize(eDataType type)
Size of data type type (which must be different from DT_String).
Definition DataTypes.cc:111
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstMemoryView makeConstMemoryView(const void *ptr, Int32 datatype_size, Int64 nb_element)
Creates a read-only memory view.
Definition MemoryView.cc:36
std::int32_t Int32
Signed integer type of 32 bits.
Memory management utility functions.