Metafor

ULiege - Aerospace & Mechanical Engineering

User Tools

Site Tools


commit:2007:11_19



Commit 2007-11-19

Ceci est un commit assez important - J'ai essayé de “vulgariser” ma description des modifs DB - ça devrait être compréhensible par un débutant - prenez donc le temps de lire le texte ci-dessous pour pouvoir modifier vos cas-tests sans mon aide.

Refonte du système Key/Lock - gestion des ddls

Pourquoi?

L'idée est d'étendre et de clarifier les choses dans la gestion des degrés de libertés. Le but premier est l'intégration des éléments XFEM 3D de Lara qui font “déborder” les Locks. Pour rappel, celles-ci sont codées sur 32 bits et sont composées de 3 parties:

Ancien codage des Locks

Revenons au tout début: qu'est ce qu'une Key, qu'est ce qu'une Lock? Lisez la suite et regardez le beau schéma ci-dessus.

Ancien système (OE)

J'ai remarqué que presque personne ne comprennais l'ancien système de DB d'Oofelie. J'essaye ici de résumer la situation. Il n'est pas trop tard pour comprendre: la DB n'a pas encore disparu (ça viendra).

Keys

Une Key est un moyen de coder le type d'une grandeur stockée dans la base de données (DB) d'Oofelie. Par exemple les composantes du déplacement, la température, des multiplicateurs de lagrange, etc). Ce codage est effectué en deux parties distinctes: une “Nature” et un “Set_Nature”.

La partie “Set_Nature” est composée de 4 ensembles de flags. En choisissant un et un seul flag dans chacun de ces 4 ensembles, on va composer un “Set_Nature”. La combinaison se fait par l'opérateur “pipe” (puisqu'il correspond en interne à un “bitwise or”). Par exemple: AB|RL|GV|I1 désigne “la contribution 1 (I1) d'une vitesse (GV) d'une valeur absolue (AB) réelle (RL)”. La partie “Nature” désigne le type de valeur. Donc si on ajoute TO à l'exemple précédent, on a “la contribution 1 (I1) de la dérivée (GV) d'une température absolue (AB) réelle (RL)” (ne cherchez pas à comprendre ce que ça veut dire vraiment - comme dirait Ludo, on ne fait pas de la science ici).

La partie “Nature” désigne donc de manière très abstraite, un type de champ.

Pourquoi ce codage en deux parties? simplement pour pouvoir obtenir plusieurs types de valeurs (Set_Nature) à partir d'une Nature. Par exemple, si on prend la Nature TO (le champ thermique), on peut facilement obtenir toutes les grandeurs thermiques en ajoutant un “Set_Nature” approprié:

  • TO | AB|RL|GD|I1 : la température “absolue” (la référence)
  • TO | RE|RL|GD|I1 : l'incrément de température
  • TO | RE|RL|GV|I1 : la dérivée temporelle de la température
  • etc

Il est important à ce stade de savoir que, pour simplifier l'écriture, un malheureux système de remplissage des Keys incomplètes a été mis en place dans Oofelie. Ceci veut dire que si une clef est incomplète, elle sera automatiquement complétée par le système par la coûteuse fonction “Key:cure”. Outre cette perte de temps passée le plus souvent à corriger des Keys qui sont complètes, ce mécanisme fait que:

  • plus personne ne comprend le système (question: “dois-je mettre TX|GD, TX|RL ou GD pour les déplacements?” - réponse: “n'importe: le système corrigera en TX|RE|RL|GD|I1 car toutes ces Keys sont identiques!!”)
  • on confond la notion de “champ” (“Nature”) avec sa valeur par défaut. Par exemple, TO c'est l'incrément de température ⇒ NON!

On voit déjà un premier ensemble de problèmes à ce système:

  • le système possède un système de correction implicite très dangereux (pour le C++, l'implicite, c'est pas une bonne idée).
  • le système se veut trop général ⇒ il est possible de créer des valeurs qui n'ont pas de sens physique (la partie imaginaire de l'incrément de température, etc).
  • le système est figé à ces 4 ensembles de flags. Si on voulait ajouter des qualificatifs supplémentaires, il faut recompiler…

…et c'est bien là le problème: Nous avons ajouté depuis l'évolution de Metafor une série de choses dans ce codage (Par exemple, récemment, les degrés de libertés XFEM 2D) si bien qu'il ne reste plus de place pour stocker de nouveaux flags dans les 32 bits utilisés. Bien sûr, on pourrait se la jouer à la OE en disant: “le système est pourri mais on va arranger ça rapidement en utilisant un nouveau codage 64 bits.”… Mais que fera-t-on quand les 64 bits seront remplis??

Pour comprendre que le système est pourri, il est utile de comprendre les autres concepts qui ont été introduits dans le système de Keys pour essayer très maladroitement de réutiliser ce qui existait déjà:

Degrés de liberté

Les degrés de libertés: dans Oofelie, un degré de liberté est obligatoirement associé à la base de données (limitation qu'on fera sauter plus tard).

Un degré de liberté = un numéro et la partie “Nature”+“Set_Nature” d'une Key (+ des flags).

Attention: la partie “Set_Nature” permet de désigner un ddl mais, par construction, des ddls qui diffèrent uniquement par le “Set_Nature” seront traités de manière identique!!

Au niveau du ddl, seule la “Nature” compte. C'est donc “un champ” dans son concept le plus vague. Par exemple “translation X” (rien n'indiquera dans l'algorithme s'il s'agit d'un X (TX|AB), d'un dX (TX|RE) ou même d'un dX/dt (TX|GV).

Conséquence, il est impossible d'avoir dans le même système d'équations des différentes grandeurs relatives à un même champs. Par exemple, il ne serait pas possible de définir les positions “remeshed” de l'ALE par un “Set_Nature” si on voulait faire de l'ALE couplé.

Flags

Les flags : Un autre concept mélangé à tout ce qui précède est la partie bleue du schéma ci-dessus. Ce sont les flags des degrés de libertés. Cela répond par exemple à la question “le degré de liberté est-il fixé ou libre?… ou … les deux??…”

… ceci nous amène au concept de Lock…

Locks

Les Locks: initialement ce sont des “masques binaires” basés donc sur le même système de codage que les Keys. Ces Locks vont permettre de regrouper des types de grandeurs ensemble. Par exemple, si on crée une Lock qui contient FI|FR, elle permettra de rassembler les degrés de libertés qu'ils soient libres ou fixés.

Idéalement les Locks ne devraient intervenir que dans une très petite partie du code.

  • dans le partitionnement du système: chaque partition doit pouvoir regrouper certains types de ddls.
  • dans des routines qui agissent sur plusieurs types de grandeurs à la fois. Par exemple, la définition d'une fixation TX|TY|TZ|RE|GD|RL|I1 pour fixer les composantes x,y et z en une seule commande.

En pratique, ce n'est pas le cas. les locks apparaissent partout pour remplacer les coûteuses vérifications des Keys!! et, le comble:

  • un degré de liberté contient une Lock!! et pas une Key (juste pour des raisons de perfs)
  • les partitions sont créées avec des objets “UnionLock” puisqu'un simple masque binaire ne permet pas de dire par exemple je veux TX|RE et TO|AB dans cette partition (on risque d'avoir aussi TX|AB et TO|RE) !!

En résumé, des Locks est utilisé partout où OE voulait utiliser initialement des Keys…

DBValue 1D et 3D

Un problème de cet ancien système que nous n'avons pas abordé est la gestion des types d'entrées dans la base de données. En effet: les grandeurs utilisant un TY, TY ou TZ sont stockées en tant que vecteurs à 3 composantes (Vect3). Il a donc été mis en place un système de déduction de numéro de composante à partir d'une Key pour que, lorsqu'on donne TY, le système sache qu'il s'agit de la deuxième composante d'un Vect3.

Nous voulons également unifier ce système, le généraliser et pouvoir l'étendre à d'autres types (matrices, tenseurs, etc)

Nouveau système

Le nouveau système mis en place par ce commit à beaucoup d'avantages sur l'ancien même s'il n'est pas encore parfait:

Voici les idées principales:

  • Redéfinition & Séparation de tous les concepts mélangés dans Key, Lock, etc.
  • Possibilité d'extension en vue de supprimer la base de données monolitique actuelle (⇒ base de données diffuse)
  • Typage fort de toutes les entités.
  • Nombre illimité de “Nature”, “Set_Nature” et “Flags” en vue de l'intégration de XFEM
  • Suppression de toutes les conversions implicites.

NatureID/VariantID

Reprenons les choses depuis le début. Il faut d'abord pouvoir nommer une valeur de la base de données comme on le faisait avec la partie Nature/Set_Nature d'une Key.

Nous créons donc deux nouvelles classes: NatureID et VariantID. Le suffixe ID fait référence au template des identifiacteurs dynamiques mis au point il y a quelques temps pour faire sauter toutes les enums d'Oofelie. Les mécaniqmes d'initialisation ont été testés dans le passé et permettent une initialisation fiable même à travers plusieurs DLLs.

NatureID

Nous définissons donc 19 objets NatureID correspondants aux anciens 19 champs ou ddl/noeuds. c'est ici que Lara pourra ajouter ses nouveaux champs XFEM 3D..

Les objets NatureID comme TX, TO, TM, … se comportent exactement comme les anciennes Locks correspondantes à part que j'ai renforcé leur caratère “const”.

C'est ici qu'il faut étendre le système d'accès aux composantes des vecteurs 3D de type TX, TY, TZ. Nous allons dériver NatureID en plusieurs types. Ces types se chargeront de l'accès aux données et gèreront en interne les composantes.

La NatureID TXTYTZ désigne une nature vectorielle et TX, TY, TZ deviennent des composantes scalaires de cette nature vectorielle.

VariantID

Pour VariantID, on veut simuler le “Set_Nature”. Pour faciliter les choses et éviter de jongler avec 4 ensembles de bits dont la plupart des combinaisons ne signifient rien, nous nous limiterons à un seul ensemble. Ceci n'est pas restrictif puisque nous disposons d'au maximum 2^64=18446744073709551616 VariantID au lieu des 2*2*4*3=48 anciens!

Les nouveaux VariantID seront donc:

  • AB, RE, GV, GA: la même signification que leur ancienne valeur corrigée par le défaut.
  • GF1, GF2, GF3: sont des raccourcis pour les anciens codes de type GF|I1 qu'on n'utilisait que pour les forces.
  • RRE, RGV, RGA: valeurs de la config “remaillée” pour l'ALE (ça me semble mieux que de les stocker dans la partie imaginaire des déplacements!).
  • DX: le delta de N-R. (doit être dans la DB à cause du thermomec full couplé (la résolution se fait en bloc alors que la mise à jour des inconnues se fait mecanique et thermique séparés).

Les nouvelles Keys = Field(NatureID, VariantID)

A partir de ces deux objets, nous définissons un nouvel objet qui va nous servir à qualifier les ensembles de la base de données: les Field. ils sont obligatoirement composés d'une nature et d'une variante (plus de remplissage ou du Key::cure par défaut!). En interne, c'est juste 2 const pointeurs.

Chaque ensemble de la base de données possède donc son propre Field. C'est donc aussi un Field qu'on passe à la routine findDBSet (ex get_properties())

A partir de ces Fields, on dérive des Field1D ou Field3D en fonction du type de NatureID (1D ou 3D)

Parmi ces Fields seuls les Field1D peuvent être utilisés pour qualifier un degré de liberté!

Dof: Field1D / DofFlags

Nous arrivons aux degrés de libertés. Chacun de ceux-ci regroupe un Field1D (ancienne partie Nature/Set_Nature), un index dans la DB (nouvelle classe DBIndex qui remplace le int) et une nouvelle classe nommée DofFlags qui contient actuellement l'attribut libre OU fixé ( OU, pas ET).

L'indexation des ddls dans le DofSet s'effectue toujours de la même manière mis à part le fait que le nombre de degrés de libertés maximum (MAXNATURE) aux noeuds est une variable lue à partir du singleton des NatureID.

Partitions : les nouvelles Locks = DofTypeMask

Jusqu'à ici, nous avons remplacé le concept initial de Key par celui de Field et DofFlags. Je dis initial car c'est bien le concept idéal initialement pensé par OE qui a été traduit! En pratique, nous avons remplacé beaucoup de Locks qui n'étaient là que pour des raisons de perfs afin d'éviter les Key::cure.

Nous arrivons au concept de Lock (ou plutôt d' UnionLock) qui se veut être un masque permettant de trier des grandeurs dans des ensembles distincts…

Nous avons codé un nouveau système basé sur la nouvelle classe DofTypeMask qui pourrait être rebaptisée simplement Mask. Il s'agit d'un système générique qui va étendre les UnionLock à tout type de tests. L'idée est de créer une série de masques sous la forme d'une expression logique avec des classes dérivées de DofTypeMask.

Par exemple, le masque suivant sera utilisé pour regrouper les ddls non thermique et non fixés dans une partition:

new AndMask(new NotMask(new NatureMask(TO)), new FlagsMask(DofFlags(false))) )

Le système est très général et la syntaxe pourrait être réécrite en surdéfinissant les opérateurs logiques classiques (ça n'a pas encore été fait).

Typage fort - sécurité

Pour garantir un typage fort et virer tous ces “int” qui peuvent être pris les uns pour les autres, notamment dans les LOCELs, j'ai défini des classes encapsulant un size_t (index non signé 64 bits):

  • DBIndex : index de la DB
  • DofIndex : numero interne d'un ddl dans le DofSet.
  • PartIndex : numéro de partition
  • PartDofIndex : numéro d'un ddl dans une partition

Ces classes suppriment tous les opérateurs classques sur les “int” (par exemple, on ne peut pas additionner 2 DofIndex!) et surtout tous les casts implicites (leur constructeur est défini explict). De plus tout est non signé, ce qui nous imunise définitivement contre les “put a minus sign”…

Il est donc impossible maintenant de prendre un numéro d'index de ddl et d'indexer la base de données sans passer par des casts explicites qui ne passent pas inaperçus.

Changements de syntaxe

Attention: les nouveaux facs sont hautement incompatibles avec les anciens. La nouvelle version est incapable de charger des facs avec des anciennes Locks. La bonne nouvelle, c'est que j'ai décidé de sauvegarder les nouveaux codes au format “texte”; ce qui va améliorer la compatibilité du fac dans le futur. en particulier, si Lara ajoute ses degrés de libertés, le Fac ne sera pas perturbé!

Dans les cas-tests

  • Toutes les Keys et Locks s'écrivent avec des Fields:
    • TX|REField1D(TX,RE) (ou Field(TX,RE) si la commande ne prend pas explicitement une valeur scalaire)
    • TOField1D(TO,RE)
    • GF|I2Field1D(TX,GF2)
  • defineRot prend un Field3D = Field3D(TXTYTZ,RE) et s'écrit dorénavant en une seule ligne

Dans le code

  • Un beau paquet de int ont été mieux typés (soit size_t, soit DBIndex, soit DofIndex, etc). Idéalement, je vois pas où Metafor devrait utiliser un seul int! ⇒ Il y a encore du boulot!
  • J'ai remplacé ALL par un pointeur NULL. En pratique, ce pointeur devrait être remplacé par AllMash() mais ça nécessite un bon gros powergrep supplémentaire (et peut être des problèmes de perfs). Bref, ce sera réglé plus tard. Autre conséquence, j'ai réécris des tests du type if(lock==ALL | lock=TXTYTZ) par if(lock || lock.getNature()==TXTYTZ). Vu que le compilateur est succeptible d'évaluer la deuxième expression avant la première, ça peut crasher, d'après la norme… mais au final, ça crashe pas…
  • La Lock NOTHING a tout simplement disparu! Elle servait à retourner une Lock vide si une erreur se produisait (mais de toutes façons aucun appel ne faisait de tests en retour) ⇒ à remplacer par un système d'erreur par exceptions.
  • Les DBSet ont été supprimés. Ca simplifie la gestion de la DB. Mais seront peut être réimplémentés pour une raison de sécurité (voir + bas)
  • Les accès au valeurs de la DB s'écrivent:

pour un accès scalaire (via un Field1D):

field1D.getValue(set.define(n));

pour un accès vectoriel:

field3D.getV3Value(set.define(n));

On voit ici qu'il y a un risque de demander par erreur un Vect3 à un set scalaire. Avant, ce genre de risque existait aussi mais renvoyait un vecteur de 0 (philosophie OE face à une erreur: on ferme les yeux et on continue…). Maintenant, ça crashe à l'exécution (je préfère). L'idéal serait de réimplémenter DBSet3 et d'effectuer un accès fortement typé du genre:

set3.getFilter().getV3Value(set3, n);

Sécurité maximale mais perfs moindres…

Divers

  • les déplacements radiaux étaient bugués (ça marchait par hasard pour le seul test de la batterie).

A Faire

  • restreindre l'utilisation du “define” de DBSet ⇒ suppression de la possiblité de laisser des “trous” dans la DB.
  • Utilisation de masques pour le Element::generalForce et pour le loadingSet - éviter de passer des Fields inutiles dans le calcul des forces.
  • Suppression des int restants.
  • Utilisation de pointeurs dans la gestion des dofs (LOCELs, etc)
  • Faire un meilleur Fac texte/XML une fois pour toute (histoire de pouvoir debuguer plus facilement)

Les trucs bizarres que j'ai rencontrés

  • l'incrément dX est sauvé dans la DB et donc dans le Fac!
  • la plupart des sets thermomec sont alloués quel que soit le schéma.
  • Certains tests implicites-explicites rechargent une DB plus petite que l'actuelle ⇒ actuellement, les valeurs “en trop” sont conservées (j'imagine que c'est ce que Ludo veut).

Fichiers ajoutés/supprimés

Certains fichiers ne sont pas splittés. D'autres devront passer de Oofelie à Metafor.

mtFEMBase/DofFlags.cpp	added
mtKernel/DBIndex.cpp	added
mtKernel/DBPointer.cpp	added
mtKernel/Field.cpp	added
mtKernel/NatureID.cpp	added
mtKernel/NatureIDList.cpp	added
mtKernel/NatureIDs.cpp	added
mtKernel/VariantID.cpp	added
mtKernel/VariantIDList.cpp	added
mtKernel/VariantIDs.cpp	added
mtFEMBase/DofFlags.h	added
mtFEMBase/DofIndex.h	added
mtFEMBase/DofType.h	added
mtFEMBase/DofTypeList.h	added
mtFEMBase/PartIndex.h	added
mtKernel/DBIndex.h	added
mtKernel/DBPointer.h	added
mtKernel/Field.h	added
mtKernel/NatureID.h	added
mtKernel/NatureIDList.h	added
mtKernel/NatureIDs.h	added
mtKernel/VariantID.h	added
mtKernel/VariantIDList.h	added
mtKernel/VariantIDs.h	added
mtFEMBase/DofFlags.inl	added
mtKernel/LockData.cpp	deleted
mtKernel/LockEntry.cpp	deleted
mtKernel/LockData.h	deleted
mtKernel/LockEntry.h	deleted
oeFEMBase/DofFlagCmd.cpp	added (+)
oeFEMBase/DofFlagCmdSet.cpp	added (+)
oeFEMBase/DofFlagCmd.h	added (+)
oeFEMBase/DofFlagCmdSet.h	added (+)
oeFEMBase/DofFlagCmdSet.inl	added (+)
oeFEMBase/DofFlag.cpp	deleted
oeFEMBase/DofFlagSet.cpp	deleted
oeFEMBase/UnionLock.cpp	deleted
oeKernel/DBLock.cpp	deleted
oeKernel/DBSet3.cpp	deleted
oeKernel/Field.cpp	deleted
oeKernel/Key.cpp	deleted
oeKernel/Lock.cpp	deleted
oeKernel/Locks.cpp	deleted
oeFEMBase/DofFlag.h	deleted
oeFEMBase/DofFlagSet.h	deleted
oeFEMBase/UnionLock.h	deleted
oeKernel/DBLock.h	deleted
oeKernel/DBSet3.h	deleted
oeKernel/Field.h	deleted
oeKernel/Key.h	deleted
oeKernel/Lock.h	deleted
oeKernel/Locks.h	deleted
oeFEMBase/DofFlagSet.inl	deleted
oeKernel/DBLock.inl	deleted
oeKernel/Key.inl	deleted
oeKernel/Lock.inl	deleted

Romain BOMAN 2007/11/19 10:34

commit/2007/11_19.txt · Last modified: 2016/03/30 15:23 (external edit)