Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
Gestion des matériaux et des milieux.

Cette page décrit la gestion des matériaux et des milieux dans Arcane.

L'ensemble des classes associées aux matériaux et milieux se trouvent dans le namespace Materials de Arcane (voir Matériaux et des milieux.). Le plus simple pour utiliser ces classes est d'utiliser le mot clé using. Par exemple :

#include <arcane/materials/IMeshMaterial.h>
using namespace Arcane::Materials;
Active toujours les traces dans les parties Arcane concernant les matériaux.

L'ensemble des milieux et des matériaux est gérée par la classe IMeshMaterialMng. Une instance de cette classe est associée à un maillage IMesh. Il est possible d'avoir plusieurs instances de IMeshMaterialMng par IMesh mais cela n'est pas utilisé pour l'instant.

Avertissement
Pour l'instant, la gestion des matériaux et milieux est incompatible avec les modifications de la topologie de maillage. En particulier, cela inclue le repartionnement dû à l'équilibrage de charge.
Note
A partir de la version 1.20.2, il est possible de modifier partiellement la topologie du maillage. Néanmoins, il s'agit uniquement d'un mode de test, sans garantie sur les résultats. De plus, il faut respecter les contraintes suivantes :
  • appeler IMeshMaterialMng::setMeshModificationNotified(true) avant de créer les milieux et matériaux.
  • uniquement en mode séquentiel
  • uniquement en supprimant des mailles.

Une instance de IMeshMaterialMng décrit un ensemble de milieux, chaque milieu étant composé d'un ou plusieurs matériaux. La liste des milieux et des matériaux doit aussi être créé lors de l'initialisation du calcul et ne plus évoluer par la suite. Il est aussi possible d'avoir la notion de bloc au-dessus de la motion de milieu, un bloc comprenant un ou plusieurs milieux. Cette notion de bloc est optionnel et n'est pas indispensable à l'utilisation des milieux ou des matériaux

Dans l'implémentation actuelle, les milieux et les matériaux ne sont associées qu'aux mailles et pas aux autres entités du maillage. La liste des mailles d'un milieu ou d'un matériau est dynamique et peut évoluer au cours du calcul. De même, il est possible d'avoir plusieurs milieux et plusieurs matériaux par maille.

Note
Il ne faut pas détruire manuellement les instances de IMeshMaterialMng. Elles seront automatiquement détruites lorsque le maillage associé sera supprimé.

L'instance par défaut de IMeshMaterialMng pour un maillage ne se créée pas directement. Pour la récupérer, il faut utiliser la méthode IMeshMaterialMng::getReference() avec comme argument le maillage concerné. L'appel à cette fonction provoque la création du gestionnaire si ce n'est pas déjà fait. Cette fonction à un coût CPU non négligeable et il est donc préférable de stocker l'instance retournée plutôt que d'appeler la fonction plusieurs fois.

// Création ou récupération du gestionnaire depuis un maillage.
IMeshMaterialMng* material_mng = IMeshMaterialMng::getReference(defaultMesh());

Création des matériaux, des milieux et des blocs

Une fois le gestionnaire créé, il faut enregistrer les matériaux et les milieux. La première chose à faire est d'enregistrer les caractéristiques des matériaux. Pour l'instant, il s'agit uniquement du nom du matériau. On enregistre uniquement les caractéristiques des matériaux et pas les matériaux eux-mêmes car ces derniers sont créés lors de la création des milieux.

// Exemple de création de 3 matériaux:
material_mng->registerMaterialInfo("MAT1");
material_mng->registerMaterialInfo("MAT2");
material_mng->registerMaterialInfo("MAT3");

Une fois les caractéristiques enregistrées, il est possible de créer les milieux, en spécifiant leur nom et la liste de leurs matériaux. Il faut noter que deux milieux (ou plus) peuvent être constitués du même matériau. Dans ce cas, Arcane créé deux instances différentes du même matériau et ces dernières sont indépendantes. Ainsi, dans l'exemple suivant, le matériau MAT1 est présent dans ENV1 et ENV3, ce qui fait deux matériaux distincts avec chacun leurs valeurs partielles. Une fois les milieux créés, il est possible de les associés dans des blocs. Un bloc est défini par un nom, le groupe de maille associé et sa liste des milieux, qui est donc fixe.

// Création du milieu ENV1 contenant les matériaux MAT1 et MAT2
MeshEnvironmentBuildInfo ebi1("ENV1");
ebi1.addMaterial("MAT1");
ebi1.addMaterial("MAT2");
IMeshEnvironment* env1 = material_mng->createEnvironment(ebi1);
// Création du milieu ENV2 contenant le matériau MAT2
MeshEnvironmentBuildInfo ebi2("ENV2");
ebi2.addMaterial("MAT2");
IMeshEnvironment* env2 = material_mng->createEnvironment(ebi2);
// Création du milieu ENV3 contenant les matériaux MAT3 et MAT1
MeshEnvironmentBuildInfo ebi3("ENV3");
ebi3.addMaterial("MAT3");
ebi3.addMaterial("MAT1");
IMeshEnvironment* env3 = material_mng->createEnvironment(ebi3);
// Création du bloc BLOCK1 sur le groupe de toutes les mailles
// et contenant les milieux ENV1 et ENV2
MeshBlockBuildInfo mb1("BLOCK1",allCells());
mb1.addEnvironment(env1);
mb1.addEnvironment(env2);
IMeshBlock* block = material_mng->createBlock(mb1);
// Indique au gestionnaire que l'initialisation est terminée
material_mng->endCreate();

Une fois tous les milieux et blocs créés, il faut appeler IMeshMaterialMng::endCreate() pour signaler au gestionnaire que l'initialisation est terminée et qu'il peut allouer les variables. Une fois cette méthode appelée, il ne faut plus créer de blocs, ni de milieux ni de matériaux.

Note
Depuis la version 2.3.3 de Arcane, il est possible d'ajouter des milieux à un bloc entre sa création (IMeshMaterialMng::createBlock()) et l'appel à IMeshMaterialMng::endCreate(), via la méthode IMeshMaterialMng::addEnvironmentToBlock().
Depuis la version 2.3.4 de Arcane, il est possible de supprimer des milieux à un bloc entre sa création (IMeshMaterialMng::createBlock()) et l'appel à IMeshMaterialMng::endCreate(), via la méthode IMeshMaterialMng::removeEnvironmentToBlock().

Les instances de IMeshMaterial, IMeshEnvironment et IMeshBlock restent valident durant toute l'existence du IMeshMaterialMng correspondant. Elles peuvent donc être conservées et il est possible d'utiliser l'opérateur d'égalité pour savoir si deux instances correspondent au même matériau.

Note
A partir de la version 1.21.1, les informations concernant les blocs, les matériaux et les milieux sont sauvegardées et peuvent être relues en reprise. Néanmoins, cela n'est pas automatique pour des raisons de compatibilité. Si on souhaite relire les informations sauvegardées, il faut appeler IMeshMaterialMng::recreateFromDump() et ne plus créér manuellement les informations ni appeler la méthode IMeshMaterialMng::endCreate().

Chaque matériau IMeshMaterial, milieu IMeshEnvironment et bloc IMeshBlock possède un identifiant unique, de type Int32, qui est accessible via les méthodes IMeshMaterial::id(), IMeshEnvironment::id() ou IMeshBlock::id(). Ces identifiants commencent à 0 et sont incrémentés pour chaque matériau, milieu ou bloc. Par exemple, avec la construction de l'exemple précédent, on a :

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

Ajout ou suppression de mailles d'un matériau

Une fois les matériaux et milieux créés, il est possible d'ajouter ou de supprimer des mailles pour un matériau. Il n'est pas nécessaire de modifier les mailles par milieu : Arcane se charge de recalculer automatiquement la liste des mailles d'un milieu en fonction de celles de ses matériaux.

Toute modification se fait via la classe MeshMaterialModifier. Il suffit de créer une instance de cette classe et d'appeler autant de fois que nécessaire les méthodes MeshMaterialModifier::addCells() ou MeshMaterialModifier::removeCells(). Il faut noter que ceux deux méthodes permettent uniquement d'indiquer les mailles à ajouter ou supprimer. La modification effective n'a lieu que lors de l'appel à MeshMaterialModifier::endUpdate() ou de la destruction l'instance de MeshMaterialModifier. C'est seulement à ce moment là que les valeurs partielles sont mises à jour et qu'il est possible d'y accéder.

Note
Pour l'instant, les variables partielles des matériaux sont automatiquement initialisées à 0 dans les nouvelles mailles d'un matériau. Pour des raisons de performance, il est possible que cela ne soit plus le cas et alors les valeurs ne seront pas initialisées.
{
// Créé l'instance de modification. Les modifications
// seront effectives lors de l'appel au destructeur de
// cette classe.
MeshMaterialModifier modifier(material_mng);
// Ajoute les mailles du matériau 1 ou 2 en fonction
// de leur localId()
Int32UniqueArray mat1_indexes;
Int32UniqueArray mat2_indexes;
Integer nb_cell = allCells().size();
ENUMERATE_CELL(icell,allCells()){
Int32 local_id = icell.itemLocalId();
Integer 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);
}
// Ajoute les mailles du matériau 1
modifier.addCells(env1->materials()[0],mat1_indexes);
// Ajoute les mailles du matériau 2
modifier.addCells(env1->materials()[1],mat2_indexes);
}
// A partir d'ici, les matériaux sont mis à jour.
info() << env1->materials()[0]->cells().size(); // Nombre de mailles du matériau
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.

Itération sur les mailles matériaux

Il existe trois classes pour faire référence aux notions de maille matériaux :

  • AllEnvCell est une classe permettant d'accéder à l'ensemble des milieux d'une maille.
  • EnvCell correspond à un milieu d'une maille et permet d'accéder aux valeurs de ce milieu pour cette maille et à l'ensemble des valeurs de cette maille pour les matériaux de ce milieu.
  • MatCell correspondant à une valeur d'un matériau d'un milieu d'une maille.

Il existe une quatrième classe ComponentCell qui n'est pas une maille spécifique mais qui peut représenter un des trois types ci-dessus et permet d'unifier les traitements (voir Unification).

Il existe deux manières d'itérer sur les mailles matériaux.

La première est d'itérer sur tous les milieux, pour chaque milieu d'itérer sur les matériaux de ce milieu et pour chacun de ces matériaux d'itérer sur ces mailles. Par exemple :

// Itération sur tous les milieux, puis tous les matériaux et
// toutes les mailles de ce matériau
ENUMERATE_ENV(ienv,material_mng){
IMeshEnvironment* env = *ienv;
ENUMERATE_MAT(imat,env){
IMeshMaterial* mat = *imat;
ENUMERATE_MATCELL(imatcell,mat){
MatCell mc = *imatcell;
info() << "Cell mat=" << mc.materialId();
}
}
ENUMERATE_ENVCELL(ienvcell,env){
EnvCell mmcell = *ienvcell;
info() << "Cell env=" << mmcell.environmentId();
}
}
#define ENUMERATE_ENV(ienv, container)
Macro pour itérer sur une liste de milieux.
#define ENUMERATE_ENVCELL(iname, env)
Macro pour itérer sur toutes les mailles d'un milieu.
#define ENUMERATE_MATCELL(iname, mat)
Macro pour itérer sur toutes les mailles d'un matériau.
#define ENUMERATE_MAT(imat, container)
Macro pour itérer sur une liste de matériaux.

Il est aussi possible d'utiliser un bloc pour itérer uniquement sur les milieux de ce bloc au lieu d'itérer sur tous les milieux :

// Itération sur tous les mailles des matériaux des milieux d'un bloc.
ENUMERATE_ENV(ienv,block){
IMeshEnvironment* env = *ienv;
ENUMERATE_MAT(imat,env){
IMeshMaterial* mat = *imat;
ENUMERATE_MATCELL(imatcell,mat){
MatCell mc = *imatcell;
info() << "Cell mat=" << mc.materialId();
}
}
}

La seconde manière est de parcourir toutes les mailles d'un groupe de maille, puis pour chaque maille d'itérer sur ses milieux et sur les matériaux de ses milieux. Pour cela, on peut utiliser la macro ENUMERATE_ALLENVCELL, de la même manière que la macro ENUMERATE_CELL, mais en spécifiant en plus le gestionnaire de matériaux. Par exemple, si on souhaite itérer sur toutes les mailles (groupe allCells())

// Itération sur tous les milieux et tous les matériaux d'une maille.
ENUMERATE_ALLENVCELL(iallenvcell,material_mng,allCells()){
AllEnvCell all_env_cell = *iallenvcell;
ENUMERATE_CELL_ENVCELL(ienvcell,all_env_cell){
EnvCell env_cell = *ienvcell;
info() << "Cell env=" << env_cell.environmentId();
ENUMERATE_CELL_MATCELL(imatcell,env_cell){
MatCell mc = *imatcell;
info() << "Cell mat=" << mc.materialId();
}
}
}
#define ENUMERATE_CELL_MATCELL(iname, env_cell)
Macro pour itérer sur tous les matériaux d'une maille.
#define ENUMERATE_CELL_ENVCELL(iname, all_env_cell)
Macro pour itérer sur tous les milieux d'une maille.
#define ENUMERATE_ALLENVCELL(iname,...)
Macro pour itérer sur toutes les mailles AllEnvCell d'un groupe.

De la même manière, en itérant sur toutes les mailles d'un bloc :

// Itération sur tous les milieux et tous les matériaux d'une maille.
ENUMERATE_ALLENVCELL(iallenvcell,block){
AllEnvCell all_env_cell = *iallenvcell;
ENUMERATE_CELL_ENVCELL(ienvcell,all_env_cell){
EnvCell env_cell = *ienvcell;
info() << "Cell env=" << env_cell.environmentId();
ENUMERATE_CELL_MATCELL(imatcell,env_cell){
MatCell mc = *imatcell;
info() << "Cell mat=" << mc.materialId();
}
}
}

Il existe une troisième manière pour itérer sur les mailles d'un matériau ou d'un milieu. Les classes MatCellVector et EnvCellVector permettent d'obtenir une liste de MatCell ou de EnvCell à partir d'un groupe de mailles et d'un matériau ou d'un mileu. L'exemple suivant montre comment récupérer la liste des mailles du matériau mat et du milieu \env correspondant au groupe cells pour positionner une variable mat_density :

CellGroup cells;
IMeshMaterial* mat = env1->materials()[0];
MatCellVector mat_cells(cells,mat);
ENUMERATE_MATCELL(imatcell,mat_cells){
mat_density[imatcell] = 2.3;
}
IMeshEnvironment* env = env1;
EnvCellVector env_cells(cells,env);
ENUMERATE_ENVCELL(imatcell,env_cells){
mat_density[imatcell] = 3.1;
}
Note
Actuellement, les classes MatCellVector et EnvCellVector ne sont pas copiables et ne sont valides que tant que le matériau (pour MatCellVector) ou le milieu (pour EnvCellVector) et le groupe de maille associé ne change pas. De plus, la conservation des informations consomme de la mémoire et la création à un cout en temps de calcul proportionnel au nombre de mailles du groupe.

Conversion Cell vers AllEnvCell, MatCell ou EnvCell

La plupart des méthodes sur les entités retournent des objets de type Cell. Pour convertir ces objets en le type AllEnvCell afin d'avoir les infos sur les matériaux, il faut passer par une instance de CellToAllEnvCellConverter. Ce convertisseur peut par exemple être créé en début de fonction car son coût de création est négligeable.

CellToAllEnvCellConverter all_env_cell_converter(m_material_mng);
Cell cell = ...;
AllEnvCell allenvcell = all_env_cell_converter[cell];
Maille d'un maillage.
Definition Item.h:1178
Maille arcane avec info matériaux et milieux.

À partir d'une AllEnvCell, il est possible de récupérer directement une maille pour un matériau ou un milieu donné via IMeshMaterial::findMatCell() ou IMeshEnvironment::findEnvCell(). Ces méthodes retournent respectivement une MatCell ou une EnvCell correspondant à la maille matériau ou milieu souhaité. L'instance retournée peut-être nulle si le matériau ou le milieu n'est pas présent dans la maille. Par exemple :

AllEnvCell allenvcell = ...;
IMeshMaterial* mat = ...;
MatCell matcell = mat->findMatCell(allenvcell);
if (matcell.null())
// Materiau absent de la maille
...
IMeshEnvironment* env = ...;
EnvCell envcell = env->findEnvCell(allenvcell);
if (envcell.null())
// Milieu absent de la maille.
...
__host__ __device__ bool null() const
Indique s'il s'agit de la maille nulle.
Maille arcane d'un milieu.
Interface d'un matériau d'un maillage.
virtual MatCell findMatCell(AllEnvCell c) const =0
Maille de ce matériau pour la maille c.
Représente un matériau d'une maille multi-matériau.

Unification

Depuis la version 1.21.0 de Arcane, il est possible de traiter les mailles matériaux et milieu de manière générique. La classe ComponentCell permet cette unification et peut s'utiliser pour tous les types de mailles MatCell, EnvCell ou AllEnvCell. La macro ENUMERATE_COMPONENTCELL() permet d'itérer sur des mailles de ce type :

// Itération sur tous les milieux, puis tous les matériaux et
// toutes les mailles de ce matériau via la ComponentCell
ENUMERATE_ENV(ienv,material_mng){
IMeshEnvironment* env = *ienv;
ENUMERATE_MAT(imat,env){
IMeshMaterial* mat = *imat;
ComponentCell cc = *iccell;
info() << "Cell mat=" << cc.componentId();
mat_density[cc] = 3.1; // Met à jour la densité du matériau
}
}
ComponentCell cc = *iccell;
info() << "Cell env=" << cc.componentId();
mat_density[cc] = 2.5; // Met à jour la densité du milieu
}
}
#define ENUMERATE_COMPONENTCELL(iname, component)
Macro pour itérer sur toutes les mailles d'un composant.

La classe ComponentCell peut aussi servir à indexer une variable comme le ferait une MatCell ou une EnvCell.

De la même manière, l'interface IMeshComponent est maintenant l'interface de base de IMeshMaterial et IMeshEnvironment et les méthodes IMeshMaterialMng::materialsAsComponents() et IMeshMaterialMng::environmentsAsComponents() permettent de traiter les listes de matériaux et milieux de la même manière sous forme de liste de IMeshComponent. Enfin, la classe ComponentCellVector permet de créer un vecteur de ComponentCell et s'utiliser comme un EnvCellVector ou MatCellVector

La méthode ComponentCell::superCell() retourne la ComponentCell de niveau hiérarchique immédiatement supérieur. Il est aussi possible d'itérer sur les sous-mailles d'une ComponantCell via la macro ENUMERATE_CELL_COMPONENTCELL() :

MatCell mc;
ComponentCell cc = mc;
// Retourne la maille milieu (EnvCell) du matériau:
ComponentCell cc2 = cc.superCell();
// Itère sur les mailles matériaux du milieu
}
// Retourne la maille AllEnvCell du milieu:
ComponentCell cc3 = cc2.superCell();
// Itère sur les mailles milieu de la maille.
}
#define ENUMERATE_CELL_COMPONENTCELL(iname, component_cell)
Macro pour itérer sur tous les composants d'une maille.

Enfin, il existe une macro ENUMERATE_COMPONENT() qui permet d'itérer sur une liste de composants, et qui peut donc se substituer à ENUMERATE_MAT() ou ENUMERATE_ENV().

Variables matériaux

Note
Depuis la version 2.4.0 il est possible de déclarer des variables uniquement sur les milieux et qui n'ont pas de valeurs sur les matériaux. Pour plus d'infos voir la section Variables d'environnement.

Les variables matériaux sont similaires aux variables de maillage mais possèdent en plus de la valeur aux mailles classiques une valeur par matériau et par milieu présent dans la maille. Pour une maille qui a 3 milieux, avec 2 matériaux pour le milieu 1, 3 pour le milieu 2 et 5 pour le milieu 3, le nombre de valeurs est donc de 14 (10 pour les matériaux, 3 pour les milieux et 1 pour la valeur globale). Les valeurs par matériaux et par milieux sont appelées des valeurs partielles.

Actuellement, les variables matériaux sont uniquement disponibles aux mailles. La classe de base gérant ces variables est MeshMaterialVariableRef. Les types possibles sont les suivants et sont définis dans le fichier "MeshMaterialVariableRef.h".

NomDescription
#MaterialVariableCellBytevariable matériau de type '#Byte'
#MaterialVariableCellRealvariable matériau de type '#Real'
#MaterialVariableCellInt16variable matériau de type 'Int16'
#MaterialVariableCellInt32variable matériau de type 'Int32'
#MaterialVariableCellInt64variable matériau de type 'Int64'
#MaterialVariableCellReal2variable matériau de type '#Real2'
#MaterialVariableCellReal3variable matériau de type '#Real3'
#MaterialVariableCellReal2x2variable matériau de type '#Real2x2'
#MaterialVariableCellReal3x3variable matériau de type '#Real3x3'

Depuis la version 2.3.8, il est possible de définir des variables tableaux sur les matériaux, qui ont le type suivant :

NomDescription
#MaterialVariableCellArrayBytevariable matériau de type tableau de '#Byte'
#MaterialVariableCellArrayRealvariable matériau de type tableau de '#Real'
#MaterialVariableCellArrayInt16variable matériau de type tableau de 'Int16'
#MaterialVariableCellArrayInt32variable matériau de type tableau de 'Int32'
#MaterialVariableCellArrayInt64variable matériau de type tableau de 'Int64'
#MaterialVariableCellArrayReal2variable matériau de type tableau de '#Real2'
#MaterialVariableCellArrayReal3variable matériau de type tableau de '#Real3'
#MaterialVariableCellArrayReal2x2variable matériau de type tableau de '#Real2x2'
#MaterialVariableCellArrayReal3x3variable matériau de type tableau de '#Real3x3'
Note
Pour information, en interne d'Arcane, ces valeurs partielles sont gérées sous forme de variable tableau classique mais cette implémentation peut évoluer. Depuis la version 2.0 de Arcane, pour pouvoir distinguer ces variables des variables classiques, elles sont taggées avec la valeur "Material". Par exemple, la commande
IVariable* var = ...;
if (var->hasTag("Material")){
// Il s'agit d'une valeur partielle.
}

Pour l'instant, il n'est possible de créer que des variables scalaires aux mailles, avec l'un des types de donnée suivante : #Real, Int32, Int64, Real2, Real3, Real2x2 ou Real3x3. Le nom de la classe correspondante est le même que pour les variables classiques, mais préfixé de 'Material'. Par exemple, pour une variable de type Real3, le nom est MaterialVariableCellReal3.

Construction

La déclaration des variables matériaux se fait d'une manière similaire à celle des variables du maillage. Il est aussi possible de les déclarer dans le fichier axl, de la même manière qu'une variable classique, en ajoutant l'attribut material avec la valeur true. Les valeurs valides pour dimension sont 0 ou 1.

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

La construction se fait avec un objet du type MaterialVariableBuildInfo qui référence le IMeshMaterialMng correspondant ou alors de la même manière qu'une variable classique, via le VariableBuildInfo. Par exemple :

IMesh* mesh = defaultMesh();
MaterialVariableBuildInfo mvbinfo(material_mng,"Density");
MaterialVariableCellReal mat_density(mvbinfo);
MaterialVariableCellReal mat_pressure(VariableBuildInfo(mesh,"Pressure"));
Note
La construction des variables matériaux est thread-safe.

Comme pour les variables classiques, les instructions précédentes ne créent une variable que si aucune de même nom n'existe. Dans le cas contraire, elles récupèrent une référence à la variable déjà créé correspondante.

Utilisation

Pour accéder à une valeur d'une variable matériau, il suffit d'utiliser l'opérateur [] avec comme argument un des types ComponentCell, Cell, MatCell, EnvCell ou AllEnvCell.

Cell global_cell;
MatCell mat_cell;
EnvCell env_cell;
mat_density[global_cell]; // Valeur globale
mat_density[mat_cell]; // Valeur pour un matériau
mat_density[env_cell]; // Valeur pour un milieu.

La valeur globale est partagée avec celle des variables standards Arcane de même nom. Par exemple :

IMeshMaterialMng* material_mng = ...;
MaterialVariableBuildInfo mat_info(material_mng,"Density"))
MaterialVariableCellReal mat_density(mat_info);
VariableBuildInfo info(defaultMesh(),"Density"))
VariableCellReal density(info);
mat_density[global_cell] = 3.0;
info() << density[global_cell]; // Affiche 3.0
Interface du gestionnaire des matériaux et des milieux d'un maillage.
Paramètres nécessaires à la construction d'une variable.
CellMaterialVariableScalarRef< Real > MaterialVariableCellReal
Variable matériau de type #Real

Il est aussi possible de récupérer la variable globale associée à une variable matériaux, via la méthode globalVariable():

IMeshMaterialMng* material_mng = ...;
MaterialVariableCellReal mat_density(MaterialVariableBuildInfo(material_mng,"Density"));
VariableCellReal& density(mat_density.globalVariable());

L'implémentation des variables matériaux a pour but de limiter l'utilisation mémoire. Dans cette optique, les valeurs aux milieux et aux matériaux peuvent utiliser la même zone mémoire et dans ce cas modifier la valeur milieu modifie aussi la valeur matériau et réciproquement. Cela est le cas si les conditions suivantes sont respectées dans une maille cell :

  • un seul matériau (MAT) dans un milieu (ENV), alors var[MAT]==var[ENV]
  • un seul milieu (ENV) dans la maille, alors var[ENV] == var[cell]

Synchronisations

Il est possible de synchroniser les valeurs des variables matériaux, de la même manière que les variables classiques via la fonction MeshMaterialVariableRef::synchronize().

Avertissement
Attention, il faut tout de même que les informations sur les matériaux présents soient cohérentes entre tous les sous-domaines : si une maille existe dans plusieurs sous-domaines, elle doit avoir les mêmes matériaux et milieux dans chaque sous-domaine.
Note
Depuis la version 1.22.3, il est possible de garantir que toutes les informations sur les matériaux et les milieux sont cohérentes entre les sous-domaines en appelant la méthode IMeshMaterialMng::synchronizeMaterialsInCells(). Il est aussi possible de vérifier cette cohérence en appelant IMeshMaterialMng::checkMaterialsInCells().

Depuis la version 2.3.7, il existe plusieurs implémentations pour la synchronisation. La version par défaut n'est pas optimisée et effectue une synchronisation par matériau enregistré dans IMeshMaterialMng. La version optimisée conseillée est la version 6. Pour l'utiliser, il faut appeler la méthode IMeshMaterialMng::setSynchronizeVariableVersion() avec la valeur 6. Il est aussi possible d'effectuer plusieurs synchronisations en une seule fois via la classe MeshMaterialVariableSynchronizerList. Cela permet d'optimiser les communications en réduisant le nombre de messages entre les processeurs. Par exemple :

IMeshMaterialMng* material_mng = ...;
MaterialVariableCellReal temperature = ...;
MaterialVariableCellInt32 mat_index = ...;
MaterialVariableCellReal pressure = ...;
// Création de la liste de variables à synchroniser.
// Ajoute 3 variables à la liste.
temperatture.synchronize(mmvsl);
mat_index.synchronize(mmvsl);
pressure.synchronize(mmvsl);
// Exécute la synchronisation sur les 3 variables en une fois.
mmvsl.apply();
CellMaterialVariableScalarRef< Int32 > MaterialVariableCellInt32
Variable matériau de type Int32

Depuis la version 3.6 de Arcane, il existe deux autres versions de la synchronisation qui fonctionne de manière identique à la version 6 mais avec les modifications suivantes :

  • La version 7 n'effectue qu'une seule allocation mémoire pour les buffers d'envoi et de réception (alors que la version 6 effectue autant d'allocation qu'il y a de sous-domaines voisins)
  • La version 8 qui est identique à la version 7 au détail près que les buffers alloués sont conservés entre deux synchronisations. Cette version permet d'éviter des allocations/désallocations successives au prix d'une augmentation mémoire. Ces deux versions ont pour but d'éviter de faire trop de cycles d'allocations/désallocations qui peuvent demander une charge de travail importante pour les cartes réseaux pour accès directs à la mémoire (RMA).

Gestion des dépendances

Depuis la version 1.22.1, il est possible d'utiliser le mécanisme de dépendance sur les variables matériaux. Ce mécanisme est similaire à celui des variables classiques mais permet de gérer les dépendances par matériaux.

Note
Contrairement aux dépendances sur les variables classiques, les dépendances sur les matériaux ne gèrent pas le temps physique et il n'est pas possible par exemple de faire des dépendances sur le temps physique précédent (en spécifiant IVariable::DPT_PreviousTime par exemple).

Le fonctionnement est le suivant :

// Positionne la méthode de calcul.
mat_density.setMaterialComputeFunction(this,&Sample::_computeDensity);
// Ajoute dépendance sur une variable matériau
mat_density.addMaterialDepend(mat_pressure);
// Ajoute dépendance sur variables globales
mat_density.addMaterialDepend(defaultMesh()->nodesCoordinates());
mat_density.addMaterialDepend(m_global_time);
ENUMERATE_MAT(imat,material_mng){
IMeshMaterial* mat = *imat;
// Met à jour la variable sur le matériau \a mat si besoin.
mat_density.update(mat);
}

Lors de l'appel à MeshMaterialVariableRef::update(), il est nécessaire de spécifier en argument le matériau sur lequel on souhaite faire la mise à jour. La méthode de calcul doit donc avoir comme argument un matériau, et en fin de calcul appeler MeshMaterialVariableRef::setUpToDate(mat) avec mat le matériau recalculé. Par exemple :

void _computeDensity(IMeshMaterial* mat)
{
MatCell mc = *imc;
m_mat_density[mc] = 1.0;
}
// Indique que la variable est à jour.
m_mat_density.setUpToDate(mat);
}

Variables milieux

Depuis la version 2.4.0 de Arcane, il est possible de définir des variables qui n'ont de valeurs partielles que sur les milieux et pas sur les matériaux. Mise à part cette différence, elles se comportent comme les variables matériaux. Les variables milieux disponibles sont les suivantes :

NomDescription
#EnvironmentVariableCellBytevariable milieu de type '#Byte'
#EnvironmentVariableCellRealvariable milieu de type '#Real'
#EnvironmentVariableCellInt16variable milieu de type 'Int16'
#EnvironmentVariableCellInt32variable milieu de type 'Int32'
#EnvironmentVariableCellInt64variable milieu de type 'Int64'
#EnvironmentVariableCellReal2variable milieu de type 'Real2'
#EnvironmentVariableCellReal3variable milieu de type 'Real3'
#EnvironmentVariableCellReal2x2variable milieu de type 'Real2x2'
#EnvironmentVariableCellReal3x3variable milieu de type 'Real3x3'
#EnvironmentVariableCellArrayBytevariable milieu de type tableau de '#Byte'
#EnvironmentVariableCellArrayRealvariable milieu de type tableau de '#Real'
#EnvironmentVariableCellArrayInt16variable milieu de type tableau de 'Int16'
#EnvironmentVariableCellArrayInt32variable milieu de type tableau de 'Int32'
#EnvironmentVariableCellArrayInt64variable milieu de type tableau de 'Int64'
#EnvironmentVariableCellArrayReal2variable milieu de type tableau de 'Real2'
#EnvironmentVariableCellArrayReal3variable milieu de type tableau de 'Real3'
#EnvironmentVariableCellArrayReal2x2variable milieu de type tableau de 'Real2x2'
#EnvironmentVariableCellArrayReal3x3variable milieu de type tableau de 'Real3x3'

Dans le fichier axl, ces variables peuvent être définies en spécifiant l'attribut environment à true.

<variable field-name="mat_density"
name="Density"
data-type="real"
item-kind="cell"
dim="0"
environment="true"
/>
Avertissement
Comme les structures internes des mailles matériaux et milieux sont unifiées, il est possible à la compilation d'indexer une variable milieu avec une MatCell. Comme il n'y a pas de valeurs matériaux associées, cela provoquera un accès mémoire invalide qui a de fortes chance de se solder par une erreur de segmentation (SegmentationFault). Ces erreurs sont détectées en mode CHECK et il est donc préférable d'utiliser ce mode pour les développements.

Parallélisation des boucles sur les matériaux et milieux

De la même manière que les boucles sur les entités (voir Concurrence et multi-threading), il est possible d'exécuter en parallèle des boucles sur les milieux où les matériaux. Cela se fait de manière similaire aux boucles sur les entités, en utilisant la méthode Parallel::Foreach. Par exemple :

// Boucle parallèle sur les mailles du milieu env1
IMeshEnvironment* env = env1;
Parallel::Foreach(env->envView(),[&](EnvItemVectorView view)
{
ENUMERATE_ENVCELL(ienvcell,view){
mat_density[ienvcell] = 2.5;
}
});
// Boucle parallèle sur les mailles du premier matériaux de env1
IMeshMaterial* mat = env1->materials()[0];
Parallel::Foreach(mat->matView(),[&](MatItemVectorView view)
{
ENUMERATE_MATCELL(imatcell,view){
mat_density[imatcell] = 2.5;
}
});
// Functor générique sur un matériau ou milieu.
auto func = [&](ComponentItemVectorView view)
{
mat_density[iccell] = 2.5;
}
};
// Application en parallèle de \a func sur le matériau
Parallel::Foreach(mat->view(),func);
// Application en parallèle de \a func sur le milieu
Parallel::Foreach(env->view(),func);
// Application en parallèle de \a func sur le milieu avec options
ParallelLoopOptions options;
Parallel::Foreach(env->view(),options,func);

Optimisation des modifications sur les matériaux et les milieux.

La modification des mailles matériaux et milieux se fait via la classe MeshMaterialModifier. Cette modification se fait via des appels successifs à MeshMaterialModifier::addCells() ou MeshMaterialModifier::removeCells(). Ces méthodes permettent d'enregistrer la liste des modifications mais ces dernières ne sont réellement exécutées que lors de la destruction de l'instance MeshMaterialModifier.

Par défaut, le comportement est le suivant :

  • sauvegarde des valeurs de toutes les variables matériaux
  • application des modifications (qui consiste uniquement à modifier la liste des entités des groupes de mailles associées aux matériaux et milieux)
  • restauration des valeurs de toutes les variables matériaux. Lors de la restauration, si une nouvelle maille matériau est créée, sa valeur dépend de IMeshMaterialMng::isDataInitialisationWithZero().

La sauvegarde et la restauration des valeurs sont des opérations couteuses en temps CPU et mémoire. Il est possible de désactiver ces opérations via setKeepValuesAfterChange() mais bien entendu dans ce cas les valeurs partielles ne sont pas conservées.

Afin d'optimiser ces modifications de matériaux, il est possible de se passer de ces opérations de sauvegarde/restauration. Pour cela, il faut utiliser la méthode IMeshMaterialMng::setModificationFlags(int v). Cette méthode doit être appelée avant IMeshMaterialMng::endCreate(). L'argument utilisé est une combinaison de bits de l'énumération eModificationFlags:

  • eModificationFlags::GenericOptimize : indique qu'on souhaite activer les optimisations.
  • eModificationFlags::OptimizeMultiAddRemove: indique qu'on active les optimisations dans le cas où il y a plusieurs ajouts ou suppressions avec un même MeshMaterialModifier.
  • eModificationFlags::OptimizeMultiMaterialPerEnvironment indique qu'on active les optimisations dans le cas où il y a plusieurs matériaux dans le milieu.
Avertissement
La valeur eModificationFlags::OptimizeMultiMaterialPerEnvironment n'est disponible qu'à partir de la version 2.3.2 de Arcane. Sur les versions antérieures, aucune optimisation n'est effectuée si un des matériaux modifié n'est pas le seul matériau du milieu.

Par exemple, on suppose les trois séries de modifications :

{
MeshMaterialModifier m1(m_material_mng);
m1.addCells(mat1,ids);
}
{
MeshMaterialModifier m2(m_material_mng);
m2.addCells(mat1,ids1);
m2.addCells(mat2,ids2);
m2.removeCells(mat1,ids3);
}
{
MeshMaterialModifier m3(m_material_mng);
m3.removeCells(mat2,ids);
}
Objet permettant de modifier les matériaux ou les milieux.

Suivant les valeurs spécifiées lors de l'init, on aura :

int flags1 = (int)eModificationFlags::GenericOptimize;
m_material_mng->setModificationFlags(flags1);
// Seuls m1 et m3 sont optimisés.
int flags2 = (int)eModificationFlags::GenericOptimize | (int)eModificationFlags::OptimizeMultiAddRemove;
m_material_mng->setModificationFlags(flags2);
// m1, m2 et m3 sont optimisés.

Il est possible de surcharger les optimisations utilisées via la variable d'environnement ARCANE_MATERIAL_MODIFICATION_FLAGS. Cette variable doit contenir une valeur entière correspondant à celle utilisée en argument de IMeshMaterialMng::setModificationFlags() (à savoir 1 pour l'optimisation générale, 3 pour en plus optimiser les ajouts/suppressions multiples, et 7 pour optimiser aussi les cas des milieux multi-matériaux).

Notes sur l'implémentation

IMPORTANT

NOTE 1

Actuellement, les méthodes optimisées ne réutilisent pas les valeurs partielles lorsque des mailles sont supprimées puis ajoutées à un même matériau ce qui conduit à une augmentation progressive de la mémoire utilisée par les valeurs partielles. Il est néanmoins possible de libérer cette mémoire supplémentaire via l'appel à IMeshMaterialMng::forceRecompute().

NOTE 2

Le comportement en mode optimisé lorsqu'il y a suppression puis ajout d'une même maille dans un même matériau est différent du mode classique. Par exemple :

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);
Classe de base des vecteurs 1D de données.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.

La maille de localId() 5 est d'abord supprimée puis remise dans le matériau. En mode classique, la valeur de la maille sera la même qu'avant la modification car on restaure la valeur depuis la sauvegarde. En mode optimisé, avec eModificationFlags::OptimizeMultiAddRemove spécifié, on supprime d'abord la maille du matériau puis on l'a recréé. Sa valeur sera donc celle d'une nouvelle maille matériau crée, donc 0 si IMeshMaterialMng::isDataInitialisationWithZero() ou la valeur de la maille globale associée sinon.

NOTE 3

Enfin, les méthodes optimisées sont plus strictes que les méthodes classiques et certaines opérations qui étaient tolérées en mode classique ne le sont plus :

  • spécifier dans la liste des mailles à ajouter une maille qui est déjà dans le matériau.
  • spécifier dans la liste des mailles à supprimer une maille qui n'est pas dans le matériau.
  • spécifier plusieurs fois la même maille dans la liste des mailles à supprimer ou ajouter.
MeshMaterialModifier mm(m_material_mng);
ids.add(5);
mm.addCells(mat1,ids); // Erreur si la maille 5 est déjà dans mat1
mm.removeCells(mat1,ids); // Erreur si la maille 5 n'est pas mat1
ids.add(6);
ids.add(6); // Erreur si \a ids contient plusieurs fois la même maille.

Si on se trouve dans un des cas précédent, il y a de fortes chances que cela fasse planter le code. Pour éviter cela, le mode CHECK détecte ces erreurs, les signale dans le listing et les filtre pour que cela fonctionne correctement. Ces erreurs sont signalées dans le listing par des messages du style suivant :

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

En mode release, la détection et la correction ne se fait que si la variable d'environnement ARCANE_CHECK est positionnée et vaut 1. */