This page describes the management of materials and environments in Arcane.
The set of classes associated with materials and environments is found in the Materials namespace of Arcane (see Materials and Media.). The simplest way to use these classes is to use the using keyword. For example:
The set of environments and materials is managed by the class IMeshMaterialMng. An instance of this class is associated with a mesh IMesh. It is possible to have multiple instances of IMeshMaterialMng per IMesh but this is not used for the moment.
An instance of IMeshMaterialMng describes a set of environments, each environment being composed of one or more materials. The list of environments and materials must also be created during the calculation initialization and must not evolve afterward. It is also possible to have the notion of a block above the environment motion, a block comprising one or more environments. This block notion is optional and is not essential for using environments or materials.
In the current implementation, environments and materials are associated only with mesh cells and not with other mesh entities. The list of cells for an environment or a material is dynamic and can evolve during the calculation. Similarly, it is possible to have multiple environments and multiple materials per cell.
The default instance of IMeshMaterialMng for a mesh is not created directly. To retrieve it, you must use the method IMeshMaterialMng::getReference() with the mesh concerned as an argument. Calling this function triggers the creation of the manager if it has not already been done. This function has a non-negligible CPU cost, so it is preferable to store the returned instance rather than calling the function multiple times.
Once the manager is created, you must register the materials and environments. The first thing to do is to register the material properties. For now, this is only the material name. We only register the material properties and not the materials themselves because the latter are created when the environments are created.
Once the properties are registered, it is possible to create the environments, specifying their name and the list of their materials. It should be noted that two (or more) environments can be composed of the same material. In this case, Arcane creates two different instances of the same material, and these are independent. Thus, in the following example, the material MAT1 is present in ENV1 and ENV3, which results in two distinct materials, each with its partial values. Once the environments are created, it is possible to associate them in blocks. A block is defined by a name, the associated cell group, and its list of environments, which is therefore fixed.
Once all environments and blocks are created, you must call IMeshMaterialMng::endCreate() to signal to the manager that initialization is complete and that it can allocate the variables. Once this method is called, you must no longer create blocks, environments, or materials.
It is possible to add environments to a block between its creation (IMeshMaterialMng::createBlock()) and the call to IMeshMaterialMng::endCreate(), via the method IMeshMaterialMng::addEnvironmentToBlock().
It is possible to remove environments from a block between its creation (IMeshMaterialMng::createBlock()) and the call to IMeshMaterialMng::endCreate(), via the method IMeshMaterialMng::removeEnvironmentToBlock().
Instances of IMeshMaterial, IMeshEnvironment, and IMeshBlock remain valid throughout the existence of the corresponding IMeshMaterialMng. They can therefore be kept, and it is possible to use the equality operator to know if two instances correspond to the same material.
Information concerning blocks, materials, and environments is saved and can be reloaded upon restart. Nevertheless, this is not automatic for compatibility reasons. If you wish to reload the saved information, you must call IMeshMaterialMng::recreateFromDump() and must no longer manually create the information or call the method IMeshMaterialMng::endCreate().
Each material IMeshMaterial, environment IMeshEnvironment, and block IMeshBlock has a unique identifier, of type Int32, which is accessible via the methods IMeshMaterial::id(), IMeshEnvironment::id(), or IMeshBlock::id(). These identifiers start at 0 and are incremented for each material, environment, or block. For example, with the construction of the previous example, we have:
Once materials and environments are created, it is possible to add or remove cells for a material. It is not necessary to modify the cells by environment: Arcane automatically handles recalculating the list of cells for an environment based on those of its materials.
All modifications are made via the class MeshMaterialModifier. You simply need to create an instance of this class and call the methods MeshMaterialModifier::addCells() or MeshMaterialModifier::removeCells() as many times as necessary. It should be noted that these two methods only allow indicating the cells to be added or removed. The effective modification only takes place when calling MeshMaterialModifier::endUpdate() or when the instance of MeshMaterialModifier is destroyed. Only at that moment are the partial values updated and accessible.
There are three classes to reference the material cell notions:
There is a fourth class ComponentCell which is not a specific cell but can represent one of the three types above and allows unifying the treatments (see Unification).
There are two ways to iterate over material cells.
The first is to iterate over all environments, for each environment iterate over the materials of that environment, and for each of these materials iterate over their cells. For example:
It is also possible to use a block to iterate only over the environments of that block instead of iterating over all environments:
The second way is to traverse all cells of a cell group, and then for each cell iterate over its environments and over the materials of its environments. To do this, you can use the macro ENUMERATE_ALLENVCELL, in the same way as the macro ENUMERATE_CELL, but by specifying the material manager additionally. For example, if you want to iterate over all cells (group allCells())
Similarly, by iterating over all cells of a block:
There is a third way to iterate over the cells of a material or an environment. The classes MatCellVector and EnvCellVector allow obtaining a list of MatCell or EnvCell from a cell group and a material or an environment. The following example shows how to retrieve the list of cells for the material mat and the environment \env corresponding to the group cells to position a variable mat_density:
Most methods on the entities return objects of type Cell. To convert these objects to the type \ref Arcane::Materials::AllEnvCell "AllEnvCell" in order to get information about the materials, you must go through an instance of CellToAllEnvCellConverter. This converter can, for example, be created at the beginning of the function because its creation cost is negligible.
From an AllEnvCell, it is possible to directly retrieve a cell for a given material or environment via IMeshMaterial::findMatCell() or IMeshEnvironment::findEnvCell(). These methods return a MatCell or an EnvCell corresponding to the desired material cell or environment cell. The returned instance may be null if the material or environment is not present in the cell. For example:
It is possible to treat material and environment cells generically. The class ComponentCell allows this unification and can be used for all types of cells MatCell, EnvCell, or AllEnvCell. The macro ENUMERATE_COMPONENTCELL() allows iterating over cells of this type:
The class ComponentCell can also be used to index a variable as would a MatCell or an EnvCell.
Similarly, the interface IMeshComponent is now the base interface for IMeshMaterial and IMeshEnvironment, and the methods IMeshMaterialMng::materialsAsComponents() and IMeshMaterialMng::environmentsAsComponents() allow treating the lists of materials and environments in the same way as a list of IMeshComponent. Finally, the class ComponentCellVector allows creating a vector of ComponentCell and can be used as an EnvCellVector or MatCellVector.
The method ComponentCell::superCell() returns the ComponentCell of the immediately higher hierarchical level. It is also possible to iterate over the sub-cells of an ComponentCell via the macro ENUMERATE_CELL_COMPONENTCELL():
Finally, there is a macro ENUMERATE_COMPONENT() which allows iterating over a list of components, and thus can replace ENUMERATE_MAT() or ENUMERATE_ENV().
It is also possible to declare variables only on environments that do not have values on materials. For more information, see section Environment Variables.
Material variables are similar to mesh variables but in addition to having a value on classical cells, they have a value per material and per environment present in the cell. For a cell that has 3 environments, with 2 materials for environment 1, 3 for environment 2, and 5 for environment 3, the number of values is therefore 14 (10 for materials, 3 for environments, and 1 for the global value). The values per materials and per environments are called partial values.
Currently, material variables are only available on cells. The base class managing these variables is MeshMaterialVariableRef. The possible types are as follows and are defined in the file "MeshMaterialVariableRef.h".
| Name | Description |
|---|
material variable of type Byte
material variable of type Real
material variable of type Int16
material variable of type Int32
material variable of type Int64
material variable of type Real2
material variable of type Real3
material variable of type Real2x2
material variable of type Real3x3
It is also possible to define array variables on materials, which have the following type:
| Name | Description |
|---|
material variable of type array of Byte
material variable of type array of Real
MaterialVariableCellArrayInt16
material variable of type array of Int16
MaterialVariableCellArrayInt32
material variable of type array of Int32
MaterialVariableCellArrayInt64
material variable of type array of Int64
MaterialVariableCellArrayReal2
material variable of type array of Real2
MaterialVariableCellArrayReal3
material variable of type array of Real3
MaterialVariableCellArrayReal2x2
material variable of type array of Real2x2
MaterialVariableCellArrayReal3x3
material variable of type array of Real3x3
For now, it is only possible to create scalar variables on cells, with one of the following data types: #Real, #Int32, #Int64, Real2, Real3, Real2x2, or Real3x3. The name of the corresponding class is the same as for classical variables, but prefixed with 'Material'. For example, for a Real3 variable, the name is MaterialVariableCellReal3.
The declaration of material variables is done in a manner similar to that of mesh variables. It is also possible to declare them in the axl file, in the same way as a classical variable, by adding the attribute material with the value true. The valid values for dimension are 0 or 1.
The construction is done with an object of type MaterialVariableBuildInfo which references the corresponding IMeshMaterialMng or in the same way as a classical variable, via the VariableBuildInfo. For example:
As with classic variables, the previous instructions create a variable only if none with the same name exists. Otherwise, they retrieve a reference to the corresponding already created variable.
To access a material variable's value, simply use the [] operator with one of the following types as an argument: ComponentCell, Cell, MatCell, EnvCell, or AllEnvCell.
The global value is shared with that of standard Arcane variables of the same name. For example:
It is also possible to retrieve the global variable associated with a material variable via the globalVariable() method:
The implementation of material variables aims to limit memory usage. With this goal in mind, values in environments and materials can use the same memory area, and in this case, modifying the environment value also modifies the material value and vice versa. This is the case if the following conditions are met in a cell cell:
It is possible to synchronize the values of material variables, just like classic variables, using the MeshMaterialVariableRef::synchronize() function.
It is possible to guarantee that all information about materials and environments is consistent across subdomains by calling the IMeshMaterialMng::synchronizeMaterialsInCells() method. It is also possible to check this consistency by calling IMeshMaterialMng::checkMaterialsInCells().
Since version 2.3.7, there are several implementations for synchronization. The default version is not optimized and performs synchronization per material registered in IMeshMaterialMng. The recommended optimized version is version 6. To use it, you must call the IMeshMaterialMng::setSynchronizeVariableVersion() method with the value 6. It is also possible to perform multiple synchronizations at once using the MeshMaterialVariableSynchronizerList class. This allows optimizing communications by reducing the number of messages between processors. For example:
Since version 3.6, there are two other versions of synchronization that function identically to version 6 but with the following modifications:
It is possible to use the dependency mechanism on material variables. This mechanism is similar to that of classic variables but allows managing dependencies per material.
The operation works as follows:
When calling MeshMaterialVariableRef::update(), it is necessary to specify the material on which the update should be performed as an argument. The calculation method must therefore have a material as an argument, and at the end of the calculation, call MeshMaterialVariableRef::setUpToDate(mat) with mat being the recalculated material. For example:
It is also possible to define variables that only have partial values in environments and not in materials. Apart from this difference, they behave like material variables. The available environment variables are as follows:
| Name | Description |
|---|
environment variable of type Byte
environment variable of type Real
environment variable of type Int16
environment variable of type Int32
environment variable of type Int64
environment variable of type Real2
environment variable of type Real3
EnvironmentVariableCellReal2x2
environment variable of type Real2x2
EnvironmentVariableCellReal3x3
environment variable of type Real3x3
EnvironmentVariableCellArrayByte
environment variable of type array of Byte
EnvironmentVariableCellArrayReal
environment variable of type array of Real
EnvironmentVariableCellArrayInt16
environment variable of type array of Int16
EnvironmentVariableCellArrayInt32
environment variable of type array of Int32
EnvironmentVariableCellArrayInt64
environment variable of type array of Int64
EnvironmentVariableCellArrayReal2
environment variable of type array of Real2
EnvironmentVariableCellArrayReal3
environment variable of type array of Real3
EnvironmentVariableCellArrayReal2x2
environment variable of type array of Real2x2
EnvironmentVariableCellArrayReal3x3
environment variable of type array of Real3x3
In the axl file, these variables can be defined by specifying the environment attribute to true.
Just like loops on entities (see Concurrency and Multi-threading), it is possible to execute loops on environments or materials in parallel. This is done similarly to loops on entities, using the Parallel::Foreach method. For example:
Modification of material and environment cells is done via the MeshMaterialModifier class. This modification is done through successive calls to MeshMaterialModifier::addCells() or MeshMaterialModifier::removeCells(). These methods allow recording the list of modifications, but they are only actually executed upon the destruction of the MeshMaterialModifier instance.
By default, the behavior is as follows:
Saving and restoring values are CPU and memory-intensive operations. It is possible to disable these operations via setKeepValuesAfterChange(), but of course, in this case, partial values are not preserved.
To optimize these material modifications, it is possible to bypass these save/restore operations. To do this, you must use the IMeshMaterialMng::setModificationFlags(int v) method. This method must be called before IMeshMaterialMng::endCreate(). The argument used is a combination of bits from the eModificationFlags enumeration:
For example, suppose the three series of modifications:
Depending on the values specified during initialization, you will have:
It is possible to override the used optimizations via the environment variable ARCANE_MATERIAL_MODIFICATION_FLAGS. This variable must contain an integer value corresponding to the one used as an argument for IMeshMaterialMng::setModificationFlags() (namely 1 for general optimization, 3 to further optimize multiple additions/removals, and 7 to also optimize multi-material environments).
IMPORTANT
Currently, the optimized methods do not reuse partial values when cells are deleted and then added to the same material, which leads to a gradual increase in the memory used by partial values. However, it is possible to free up this extra memory by calling IMeshMaterialMng::forceRecompute().
The behavior in optimized mode when there is deletion followed by addition of the same cell in the same material is different from classic mode. For example:
The cell with localId() 5 is first deleted and then put back into the material. In classic mode, the cell value will be the same as before the modification because the value is restored from the save. In optimized mode, with eModificationFlags::OptimizeMultiAddRemove specified, the cell is first removed from the material and then recreated. Its value will therefore be that of a newly created material cell, so 0 if IMeshMaterialMng::isDataInitialisationWithZero() or the value of the associated global cell otherwise.
Finally, the optimized methods are stricter than the classic methods, and certain operations that were tolerated in classic mode are no longer tolerated:
If one of the previous cases occurs, there is a high chance that the code will crash. To prevent this, CHECK mode detects these errors, signals them in the listing, and filters them so that it works correctly. These errors are signaled in the listing with messages such as the following:
ERROR: item ... is present several times in add/remove list for material mat=... ERROR: item ... is already in material mat=... ERROR: item ... is not in material mat=...
In release mode, detection and correction only happen if the ARCANE_CHECK environment variable is set and equals 1.