Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
Material and Environment Management.

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:

#include <arcane/materials/IMeshMaterial.h>
using namespace Arcane::Materials;
Always enables tracing in Arcane parts concerning materials.

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.

Warning
For now, material and environment management is incompatible with mesh topology modifications. In particular, this includes repartitioning due to load balancing.
Note
The use of constituents is compatible with mesh topology changes. Nevertheless, for this support to be active, the method IMeshMaterialMng::setMeshModificationNotified(true) must be called before creating environments and materials.

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.

Note
You must not manually destroy instances of IMeshMaterialMng. They will be automatically destroyed when the associated mesh is deleted.

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.

// Creation or retrieval of the manager from a mesh.
Arcane::Materials::IMeshMaterialMng* material_mng = nullptr;

Creating materials, environments, and blocks

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.

// Example of creating 3 materials:
material_mng->registerMaterialInfo("MAT1");
material_mng->registerMaterialInfo("MAT2");
material_mng->registerMaterialInfo("MAT3");

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.

// Creation of environment ENV1 containing materials MAT1 and MAT2
Arcane::Materials::MeshEnvironmentBuildInfo ebi1("ENV1");
ebi1.addMaterial("MAT1");
ebi1.addMaterial("MAT2");
Arcane::Materials::IMeshEnvironment* env1 = material_mng->createEnvironment(ebi1);
// Creation of environment ENV2 containing material MAT2
Arcane::Materials::MeshEnvironmentBuildInfo ebi2("ENV2");
ebi2.addMaterial("MAT2");
Arcane::Materials::IMeshEnvironment* env2 = material_mng->createEnvironment(ebi2);
// Creation of environment ENV3 containing materials MAT3 and MAT1
Arcane::Materials::MeshEnvironmentBuildInfo ebi3("ENV3");
ebi3.addMaterial("MAT3");
ebi3.addMaterial("MAT1");
Arcane::Materials::IMeshEnvironment* env3 = material_mng->createEnvironment(ebi3);
// Creation of block BLOCK1 on the group of all cells
// and containing environments ENV1 and ENV2
Arcane::Materials::MeshBlockBuildInfo mb1("BLOCK1", allCells());
mb1.addEnvironment(env1);
mb1.addEnvironment(env2);
Arcane::Materials::IMeshBlock* block = material_mng->createBlock(mb1);
// Indicates to the manager that initialization is complete
material_mng->endCreate();

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:

info() << env1->id(); // Displays '0'
info() << env1->materials()[0]->id(); // Displays '0'
info() << env1->materials()[1]->id(); // Displays '1'
info() << env2->id(); // Displays '1'
info() << env2->materials()[0]->id(); // Displays '2'
info() << env3->id(); // Displays '2'
info() << env3->materials()[0]->id(); // Displays '3'
info() << env3->materials()[1]->id(); // Displays '4'
info() << block->id(); // Displays '0'

Adding or removing cells for a material

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.

Note
For now, the partial values of materials are automatically initialized to 0 in the new cells of a material. For performance reasons, this may no longer be the case, and in that case, the values will not be initialized.
{
// Created the modification instance. The modifications
// will be effective when the destructor of
// this class is called.
Arcane::Materials::MeshMaterialModifier modifier(material_mng);
// Adds cells of material 1 or 2 based on
// their localId()
Arcane::UniqueArray<Arcane::Int32> mat1_indexes;
Arcane::UniqueArray<Arcane::Int32> mat2_indexes;
const Arcane::Int32 nb_cell = allCells().size();
ENUMERATE_CELL (icell, allCells()) {
Arcane::Int32 local_id = icell.itemLocalId();
Arcane::Int32 z = icell.index();
bool add_to_mat1 = (z < (nb_cell / 2) && z > (nb_cell / 4));
bool add_to_mat2 = (z >= (nb_cell / 2) || z < (nb_cell / 3));
if (add_to_mat1)
mat1_indexes.add(local_id);
if (add_to_mat2)
mat2_indexes.add(local_id);
}
// Adds cells of material 1
modifier.addCells(env1->materials()[0], mat1_indexes);
// Adds cells of material 2
modifier.addCells(env1->materials()[1], mat2_indexes);
}
// From here, the materials are updated.
info() << env1->materials()[0]->cells().size(); // Number of cells for the material

Iterating over material cells

There are three classes to reference the material cell notions:

  • AllEnvCell is a class that allows access to all environments of a cell.
  • EnvCell corresponds to an environment of a cell and allows access to the values of this environment for this cell and to all the values of this cell for the materials of this environment.
  • MatCell corresponds to a value of a material of an environment of a cell.

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:

// Iteration over all environments, then all materials and
// all cells of this material
ENUMERATE_ENV (ienv, material_mng) {
Arcane::Materials::IMeshEnvironment* env = *ienv;
ENUMERATE_MAT (imat, env) {
Arcane::Materials::IMeshMaterial* mat = *imat;
ENUMERATE_MATCELL (imatcell, mat) {
Arcane::Materials::MatCell mc = *imatcell;
info() << "Cell mat=" << mc.materialId();
}
}
ENUMERATE_ENVCELL (ienvcell, env) {
Arcane::Materials::EnvCell mmcell = *ienvcell;
info() << "Cell env=" << mmcell.environmentId();
}
}

It is also possible to use a block to iterate only over the environments of that block instead of iterating over all environments:

// Iteration over all cells of materials in a block's environments.
ENUMERATE_ENV (ienv, block) {
Arcane::Materials::IMeshEnvironment* env = *ienv;
ENUMERATE_MAT (imat, env) {
Arcane::Materials::IMeshMaterial* mat = *imat;
ENUMERATE_MATCELL (imatcell, mat) {
Arcane::Materials::MatCell mc = *imatcell;
info() << "Cell mat=" << mc.materialId();
}
}
}

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())

// Iteration over all environments and all materials of a cell.
ENUMERATE_ALLENVCELL (iallenvcell, material_mng, allCells()) {
Arcane::Materials::AllEnvCell all_env_cell = *iallenvcell;
ENUMERATE_CELL_ENVCELL (ienvcell, all_env_cell) {
Arcane::Materials::EnvCell env_cell = *ienvcell;
info() << "Cell env=" << env_cell.environmentId();
ENUMERATE_CELL_MATCELL (imatcell, env_cell) {
Arcane::Materials::MatCell mc = *imatcell;
info() << "Cell mat=" << mc.materialId();
}
}
}

Similarly, by iterating over all cells of a block:

// Iteration over all environments and all materials of a cell.
ENUMERATE_ALLENVCELL (iallenvcell, block) {
Arcane::AllEnvCell all_env_cell = *iallenvcell;
ENUMERATE_CELL_ENVCELL (ienvcell, all_env_cell) {
Arcane::EnvCell env_cell = *ienvcell;
info() << "Cell env=" << env_cell.environmentId();
ENUMERATE_CELL_MATCELL (imatcell, env_cell) {
Arcane::MatCell mc = *imatcell;
info() << "Cell mat=" << mc.materialId();
}
}
}

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:

Arcane::Materials::IMeshMaterial* mat = env1->materials()[0];
Arcane::Materials::MatCellVector mat_cells(cells, mat);
ENUMERATE_MATCELL (imatcell, mat_cells) {
mat_density[imatcell] = 2.3;
}
Arcane::Materials::IMeshEnvironment* env = env1;
Arcane::Materials::EnvCellVector env_cells(cells, env);
ENUMERATE_ENVCELL (imatcell, env_cells) {
mat_density[imatcell] = 3.1;
}
Note
Currently, the classes MatCellVector and EnvCellVector are not copyable and are only valid as long as the material (for MatCellVector) or the environment (for EnvCellVector) and the associated cell group do not change. Furthermore, keeping the information consumes memory and creation has a calculation time cost proportional to the number of cells in the group.

Converting Cell to AllEnvCell, MatCell, or EnvCell

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.

Arcane::Materials::CellToAllEnvCellConverter all_env_cell_converter(m_material_mng);
Arcane::Cell cell = ...;
Arcane::Materials::AllEnvCell allenvcell = all_env_cell_converter[cell];
Cell of a mesh.
Definition Item.h:1300
Arcane cell with material and environment information.

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:

Arcane::Materials::MatCell matcell = mat->findMatCell(allenvcell);
if (matcell.null())
// Material absent from the cell
...
Arcane::Materials::IMeshEnvironment* env = ...;
Arcane::Materials::EnvCell envcell = env->findEnvCell(allenvcell);
if (envcell.null())
// Environment absent from the cell.
...
__host__ __device__ bool null() const
Indicates if it is the null cell.
Arcane cell of an environment.
virtual MatCell findMatCell(AllEnvCell c) const =0
Cell of this material for cell c.
Represents a material in a multi-material cell.

Unification

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:

// Iteration over all environments, then all materials and
// all cells of this material via the ComponentCell
ENUMERATE_ENV (ienv, material_mng) {
Arcane::Materials::IMeshEnvironment* env = *ienv;
ENUMERATE_MAT (imat, env) {
Arcane::Materials::IMeshMaterial* mat = *imat;
ENUMERATE_COMPONENTCELL (iccell, mat) {
Arcane::Materials::ComponentCell cc = *iccell;
info() << "Cell mat=" << cc.componentId();
mat_density[cc] = 3.1; // Updates the material density
}
}
ENUMERATE_COMPONENTCELL (iccell, env) {
Arcane::Materials::ComponentCell cc = *iccell;
info() << "Cell env=" << cc.componentId();
mat_density[cc] = 2.5; // Updates the environment density
}
}

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():

Arcane::Materials::MatCell mc;
Arcane::Materials::ComponentCell cc = mc;
// Returns the environment cell (EnvCell) of the material:
Arcane::Materials::ComponentCell cc2 = cc.superCell();
// Iterates over the material cells of the environment
}
// Returns the AllEnvCell cell of the environment:
Arcane::Materials::ComponentCell cc3 = cc2.superCell();
// Iterates over the environment cells of the cell.
}

Finally, there is a macro ENUMERATE_COMPONENT() which allows iterating over a list of components, and thus can replace ENUMERATE_MAT() or ENUMERATE_ENV().

Material Variables

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".

NameDescription

MaterialVariableCellByte

material variable of type Byte

MaterialVariableCellReal

material variable of type Real

MaterialVariableCellInt16

material variable of type Int16

MaterialVariableCellInt32

material variable of type Int32

MaterialVariableCellInt64

material variable of type Int64

MaterialVariableCellReal2

material variable of type Real2

MaterialVariableCellReal3

material variable of type Real3

MaterialVariableCellReal2x2

material variable of type Real2x2

MaterialVariableCellReal3x3

material variable of type Real3x3

It is also possible to define array variables on materials, which have the following type:

NameDescription

MaterialVariableCellArrayByte

material variable of type array of Byte

MaterialVariableCellArrayReal

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

Note
For information, internally in Arcane, these partial values are managed as a classic array variable, but this implementation may evolve. Since version 2.0 of Arcane, in order to distinguish these variables from classical variables, they are tagged with the value "Material". For example, the command
Arcane::IVariable* var = ...;
if (var->hasTag("Material")){
// This is a partial value.
}
Interface of a variable.
Definition IVariable.h:40

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.

Construction

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.

<variable field-name="mat_density"
name="Density"
data-type="real"
item-kind="cell"
dim="0"
material="true"
/>

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:

Arcane::IMesh* mesh = defaultMesh();
Arcane::Materials::MaterialVariableBuildInfo mvbinfo(material_mng, "Density");
Arcane::Materials::MaterialVariableCellReal mat_pressure(Arcane::VariableBuildInfo(mesh, "Pressure"));
Note
The construction of material variables is thread-safe.

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.

Usage

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.

Arcane::Cell global_cell;
mat_density[global_cell]; // Global value
mat_density[mat_cell]; // Value for a material
mat_density[env_cell]; // Value for an environment.

The global value is shared with that of standard Arcane variables of the same name. For example:

Arcane::Materials::MaterialVariableBuildInfo mat_info(material_mng,"Density"))
Arcane::VariableBuildInfo info(defaultMesh(),"Density"))
mat_density[global_cell] = 3.0;
info() << density[global_cell]; // Displays 3.0
Interface for the material and environment manager of a mesh.
Parameters necessary for building a variable.
MeshVariableScalarRefT< Cell, Real > VariableCellReal
Real type quantity at cell center.
CellMaterialVariableScalarRef< Real > MaterialVariableCellReal
Material variable of type Real

It is also possible to retrieve the global variable associated with a material variable via the globalVariable() method:

Arcane::VariableCellReal& density(mat_density.globalVariable());

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:

  • only one material (MAT) in an environment (ENV), then var[MAT]==var[ENV]
  • only one environment (ENV) in the cell, then var[ENV] == var[cell]

Synchronizations

It is possible to synchronize the values of material variables, just like classic variables, using the MeshMaterialVariableRef::synchronize() function.

Warning
Attention, it is still necessary that the information about the present materials is consistent across all subdomains: if a cell exists in multiple subdomains, it must have the same materials and environments in each subdomain.

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:

// Creation of the list of variables to synchronize.
// Adds 3 variables to the list.
temperatture.synchronize(mmvsl);
mat_index.synchronize(mmvsl);
pressure.synchronize(mmvsl);
// Executes the synchronization for the 3 variables at once.
mmvsl.apply();
CellMaterialVariableScalarRef< Int32 > MaterialVariableCellInt32
Material variable of type Int32

Since version 3.6, there are two other versions of synchronization that function identically to version 6 but with the following modifications:

  • Version 7 performs only one memory allocation for the send and receive buffers (whereas version 6 performs as many allocations as there are neighboring subdomains)
  • Version 8, which is identical to version 7 in detail, keeps the allocated buffers between two synchronizations. This version avoids successive allocations/deallocations at the cost of increased memory usage. These two versions aim to avoid too many allocation/deallocation cycles, which can demand a significant workload for network cards for direct memory access (RMA).

Dependency Management

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.

Note
Unlike dependencies on classic variables, dependencies on materials do not manage physical time, and it is not possible, for example, to make dependencies on the previous physical time (by specifying IVariable::DPT_PreviousTime, for example).

The operation works as follows:

// Sets the calculation method.
mat_density.setMaterialComputeFunction(this, &Sample::_computeDensity);
// Adds dependency on a material variable
mat_density.addMaterialDepend(mat_pressure);
// Adds dependency on global variables
mat_density.addMaterialDepend(defaultMesh()->nodesCoordinates());
mat_density.addMaterialDepend(m_global_time);
ENUMERATE_MAT (imat, material_mng) {
Arcane::Materials::IMeshMaterial* mat = *imat;
// Updates the variable on the material \a mat if needed.
mat_density.update(mat);
}

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:

void _computeDensity(Arcane::Materials::IMeshMaterial* mat)
{
ENUMERATE_MATCELL (imc, mat) {
Arcane::MatCell mc = *imc;
m_mat_density[mc] = 1.0;
}
// Indicates that the variable is up to date.
m_mat_density.setUpToDate(mat);
}

Environment Variables

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:

NameDescription

EnvironmentVariableCellByte

environment variable of type Byte

EnvironmentVariableCellReal

environment variable of type Real

EnvironmentVariableCellInt16

environment variable of type Int16

EnvironmentVariableCellInt32

environment variable of type Int32

EnvironmentVariableCellInt64

environment variable of type Int64

EnvironmentVariableCellReal2

environment variable of type Real2

EnvironmentVariableCellReal3

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.

<variable field-name="mat_density"
name="Density"
data-type="real"
item-kind="cell"
dim="0"
environment="true"
/>
Warning
Since the internal structures of material and environment cells are unified, it is possible at compilation time to index an environment variable with a MatCell. Since there are no associated material values, this will cause an invalid memory access which is highly likely to result in a segmentation fault (SegmentationFault). These errors are detected in CHECK mode, so it is preferable to use this mode for development.

Parallelization of Loops on Materials and Environments

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:

// Parallel loop over the environment cells of env1
Arcane::Materials::IMeshEnvironment* env = env1;
Arcane::Parallel::Foreach(env->envView(), [&](Arcane::Materials::EnvItemVectorView view) {
ENUMERATE_ENVCELL (ienvcell, view) {
mat_density[ienvcell] = 2.5;
}
});
// Parallel loop over the cells of the first material in env1
Arcane::Materials::IMeshMaterial* mat = env1->materials()[0];
Arcane::Parallel::Foreach(mat->matView(), [&](Arcane::Materials::MatItemVectorView view) {
ENUMERATE_MATCELL (imatcell, view) {
mat_density[imatcell] = 2.5;
}
});
// Generic functor on a material or environment.
auto func = [&](Arcane::Materials::ComponentItemVectorView view) {
ENUMERATE_COMPONENTCELL (iccell, view) {
mat_density[iccell] = 2.5;
}
};
// Parallel application of \a func on the material
// Parallel application of \a func on the environment
// Parallel application of \a func on the environment with options
Arcane::ParallelLoopOptions options;
Arcane::Parallel::Foreach(env->view(), options, func);

Optimization of Modifications on Materials and Environments.

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 the values of all material variables
  • applying the modifications (which consists only of modifying the list of entities of the cell groups associated with materials and environments)
  • restoring the values of all material variables. During restoration, if a new material cell is created, its value depends on IMeshMaterialMng::isDataInitialisationWithZero().

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:

Warning
The value eModificationFlags::OptimizeMultiMaterialPerEnvironment is only available from version 2.3.2 of Arcane. On earlier versions, no optimization is performed if one of the modified materials is not the only material in the environment.

For example, suppose the three series of modifications:

{
m1.addCells(mat1,ids);
}
{
m2.addCells(mat1,ids1);
m2.addCells(mat2,ids2);
m2.removeCells(mat1,ids3);
}
{
m3.removeCells(mat2,ids);
}
Object allowing modification of materials or media.

Depending on the values specified during initialization, you will have:

m_material_mng->setModificationFlags(flags1);
// Only m1 and m3 are optimized.
m_material_mng->setModificationFlags(flags2);
// m1, m2 and m3 are optimized.
@ GenericOptimize
Activates generic optimizations.
@ OptimizeMultiAddRemove
Activates optimizations for multiple additions/removals.

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).

Notes on Implementation

IMPORTANT

NOTE 1

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().

NOTE 2

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:

MeshMaterialModifier m1(m_material_mng);
Array<Int32> add_ids;
Array<Int32> remove_ids;
remove_ids.add(5);
remove_ids.add(9);
add_ids.add(5);
add_ids.add(7);
m1.removeCells(mat1,remove_ids);
m1.addCells(mat1,add_ids);
Base class for 1D data vectors.
void add(ConstReferenceType val)
Adds element val to the end of the array.

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.

NOTE 3

Finally, the optimized methods are stricter than the classic methods, and certain operations that were tolerated in classic mode are no longer tolerated:

  • specifying in the list of cells to add a cell that is already in the material.
  • specifying in the list of cells to remove a cell that is not in the material.
  • specifying the same cell multiple times in the list of cells to remove or add.
MeshMaterialModifier mm(m_material_mng);
ids.add(5);
mm.addCells(mat1,ids); // Error if mesh 5 is already in mat1
mm.removeCells(mat1,ids); // Error if mesh 5 is not in mat1
ids.add(6);
ids.add(6); // Error if \a ids contains the same cells multiple times.
Array< Int32 > Int32Array
Dynamic one-dimensional array of 32-bit integers.
Definition UtilsTypes.h:127

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.