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 :
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.
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.
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.
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.
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.
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.
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.
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 :
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.
Il existe trois classes pour faire référence aux notions de maille matériaux :
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 :
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 :
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())
De la même manière, en itérant sur toutes les mailles d'un bloc :
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 :
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.
À 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 :
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 :
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() :
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().
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"
.
Nom | Description |
---|---|
#MaterialVariableCellByte | variable matériau de type '#Byte' |
#MaterialVariableCellReal | variable matériau de type '#Real' |
#MaterialVariableCellInt16 | variable matériau de type 'Int16' |
#MaterialVariableCellInt32 | variable matériau de type 'Int32' |
#MaterialVariableCellInt64 | variable matériau de type 'Int64' |
#MaterialVariableCellReal2 | variable matériau de type '#Real2' |
#MaterialVariableCellReal3 | variable matériau de type '#Real3' |
#MaterialVariableCellReal2x2 | variable matériau de type '#Real2x2' |
#MaterialVariableCellReal3x3 | variable 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 :
Nom | Description |
---|---|
#MaterialVariableCellArrayByte | variable matériau de type tableau de '#Byte' |
#MaterialVariableCellArrayReal | variable matériau de type tableau de '#Real' |
#MaterialVariableCellArrayInt16 | variable matériau de type tableau de 'Int16' |
#MaterialVariableCellArrayInt32 | variable matériau de type tableau de 'Int32' |
#MaterialVariableCellArrayInt64 | variable matériau de type tableau de 'Int64' |
#MaterialVariableCellArrayReal2 | variable matériau de type tableau de '#Real2' |
#MaterialVariableCellArrayReal3 | variable matériau de type tableau de '#Real3' |
#MaterialVariableCellArrayReal2x2 | variable matériau de type tableau de '#Real2x2' |
#MaterialVariableCellArrayReal3x3 | variable matériau de type tableau de '#Real3x3' |
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.
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
.
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 :
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.
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.
La valeur globale est partagée avec celle des variables standards Arcane de même nom. Par exemple :
Il est aussi possible de récupérer la variable globale associée à une variable matériaux, via la méthode 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 :
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().
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 :
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 :
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.
Le fonctionnement est le suivant :
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 :
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 :
Nom | Description |
---|---|
#EnvironmentVariableCellByte | variable milieu de type '#Byte' |
#EnvironmentVariableCellReal | variable milieu de type '#Real' |
#EnvironmentVariableCellInt16 | variable milieu de type 'Int16' |
#EnvironmentVariableCellInt32 | variable milieu de type 'Int32' |
#EnvironmentVariableCellInt64 | variable milieu de type 'Int64' |
#EnvironmentVariableCellReal2 | variable milieu de type 'Real2' |
#EnvironmentVariableCellReal3 | variable milieu de type 'Real3' |
#EnvironmentVariableCellReal2x2 | variable milieu de type 'Real2x2' |
#EnvironmentVariableCellReal3x3 | variable milieu de type 'Real3x3' |
#EnvironmentVariableCellArrayByte | variable milieu de type tableau de '#Byte' |
#EnvironmentVariableCellArrayReal | variable milieu de type tableau de '#Real' |
#EnvironmentVariableCellArrayInt16 | variable milieu de type tableau de 'Int16' |
#EnvironmentVariableCellArrayInt32 | variable milieu de type tableau de 'Int32' |
#EnvironmentVariableCellArrayInt64 | variable milieu de type tableau de 'Int64' |
#EnvironmentVariableCellArrayReal2 | variable milieu de type tableau de 'Real2' |
#EnvironmentVariableCellArrayReal3 | variable milieu de type tableau de 'Real3' |
#EnvironmentVariableCellArrayReal2x2 | variable milieu de type tableau de 'Real2x2' |
#EnvironmentVariableCellArrayReal3x3 | variable milieu de type tableau de 'Real3x3' |
Dans le fichier axl, ces variables peuvent être définies en spécifiant l'attribut environment
à true
.
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 :
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 :
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:
Par exemple, on suppose les trois séries de modifications :
Suivant les valeurs spécifiées lors de l'init, on aura :
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).
IMPORTANT
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().
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 :
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.
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 :
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. */