u2.51.02 Tracé de courbes avec Code_Aster#

Résumé :

Ce document explique comment, à partir d’un résultat de calcul, on peut produire des tables ou des fonctions, extraire les valeurs de ces tables ou fonctions, les manipuler, et enfin en dernier lieu utiliser les commandes d’impression pour tracer des courbes.

Si vous disposez d’une fonction ou d’une table et que vous souhaitez simplement la représenter sous forme d’une courbe, allez directement au paragraphe [§ 4 ], et consultez les documentations des commandes IMPR_FONCTION [U4.33.01] et IMPR_TABLE [U4.91.03].

Remarque préliminaire

Le post-traitement doit être effectué en POURSUITEet non pas à la suite du calcul. Plusieurs raisons à cela:

  1. en cas d’erreur , on ne perd pas les heures de calcul qui ont permis d’atteindre le résultat ,

  2. on peut effectuer de nombreux post-traitements directement en lançant Stanley sur la base résultat du calcul (voir astk [U1.04.00] ou STANLEY [U4.81.31]),

  3. pour simplifier le post-traitement, on peut utiliser les possibilités offertes par Python qui nécessitent d’être en PAR_LOT=’NON’dans POURSUITEce qui empêche l’utilisation d’eficas pour ce type de post-traitement, alors qu’il est plus simple d’utiliser eficas pour construire le jeu de données principal.

Transformer les valeurs d’une table ou d’une fonction en objets Python#

Remarque

Les traitements en Python qui sont utilisés à partir de maintenant imposent d’être en PAR_LOT=’NON’dans POURSUITE(ou DEBUT).

L’objet est ici de récupérer les valeurs d’une table ou d’une fonction dans un objet Python pour les manipuler ensuite. Notons qu’il est parfois pratique de produire une fonction à partir des données d’une table, en filtrant éventuellement certaines lignes de la table; c’est une utilisation de RECU_FONCTION [U4.32.03], que nous n’aborderons pas ici.

Sur les objets de type fonction, on dispose des méthodes:

  1. Valeurs pour récupérer les abscisses et les ordonnées dans 2 listes Python de réels.

Avec les données du paragraphe précédent:

>>> lx, ly = fDY2.Valeurs()

On obtient:

>>> print lx

[1.0, 1.1, 1.2, 1.8, 2.45]

>>> print ly

[0.207127, 0.414928, 0.792728, 0.688227, 0.343029]

  1. Absc et Ordo permettent de récupérer les abscisses et les ordonnées séparément.

>>> lx = fDY2.Absc()
>>> lx = fDY2.Ordo()

On peut accéder au contenu d’une cellule d’une table avec [ nom_paramètre , numéro_ligne ]:

>>> print tab[‘DY’, 2]

-8.14498E-2

On peut également transformer l’objet (JEVEUX) table en une instance de la classe Python Table.

>>> tabpy = tab.EXTR_TABLE()

Le document [U1.03.02] détaille les méthodes Python disponibles sur les objets de type Table. Pour l’extraction des valeurs, on dispose notamment d’un méthode values() qui retourne un dictionnaire dont les clés sont les noms de paramètres (ex ‘DY’) et les valeurs les listes des valeurs de la table.

Attention

Les listes Python sont indexées de \(0\) à \(n-1\) (pour \(n\) éléments), l’équivalent de tab[‘DY’, 2] est donc tabpy[‘DY’][1]!

Pour le tracé de courbes à partir de listes de réels Python, voir [§ 4 ].

Manipuler les valeurs en Python#

On donne ici quelques exemples de manipulation des valeurs obtenues précédemment sous forme de listes ou de tableaux Numeric.

Numeric est un module Python optionnel (c’est à dire non inclus à la distribution de Python fournie sur www.python.org) mais indispensable pour utiliser Code_Aster , on peut donc faire import Numeric sur toutes installations de Code_Aster .

Avec des listes Python#

Les listes Python sont facilement manipulables en utilisant les boucles. Prenons l’exemple de la notice [U2.51.01] pour \(–10.<x<10.\) en \(100\) pas:

\(y=-1.5\)

si \(\sin(x)<0\)

\(y=-5.\)

sinon

On cherche donc à construire deux listes de réels, \(\mathrm{lx}\) et \(\mathrm{ly}\) .

Comme toujours en Python, il y a plusieurs moyens de faire, plus ou moins simplement, plus ou moins élégamment!

x0=-10.

pas=20./100

lx=[]

ou bien

lx=[x0+i*pas for i in range(101)]

for i in range(101):

lx.append(x0+i*pas)

def f(x):

if sin(x)<0.:

return -1.5

else:

return -5.

ly=map(f, lx)

qui applique la fonction \(f\) à tous les éléments de \(\mathrm{lx}\)

On peut tracer cette courbe en utilisant les mots-clés ABSCISSE et ORDONNEE de IMPR_FONCTION (cf. [§ 4 ]).

Avec des tableaux Numeric#

La manipulation des données sous forme de tableaux Numeric est simplifiée par l’utilisation d’opérations très performantes (appelées ufunc ) sur le tableau entier (dans l’exemple suivant on utilise sin()). Numeric gère également les tableaux à plusieurs dimensions.

En reprenant l’exemple précédent:

from Numeric import *

lx = arrayrange(-10., 10.+0.2, 0.2, Float)

ly = array(map(f, lx))

ou bien sans utiliser f:

ly = -1.5*less(sin(lx), 0.) + (-5.)*(1.-less(sin(lx), 0.))

Notons que map() retourne une liste et non un tableau Numeric. La deuxième expression est entre 10et 20 fois plus rapide sur de très gros tableaux (\({10}^{5}\)\({10}^{6}\) termes), ce qui est cependant assez peu souvent le cas des fonctions ou tables issues d’ Aster .

On peut tracer cette courbe en utilisant les mots-clés ABSCISSE et ORDONNEE de IMPR_FONCTION en prenant soin de convertir les tableaux Numeric en liste, par exemple (cf. [§ 4 ]):

ABSCISSE = lx.tolist()

Exemples d’utilisation de IMPR_FONCTION/IMPR_TABLE#

Fonction reconstruite à partir de deux listes Python#

Exemple où l’on recale les résultats obtenus pour pouvoir les comparer à une solution de référence (les abscisses sont inversées, il faut comparer la valeur absolue, [SSLS501a]), on utilise les méthodes permettant d’extraire les abscisses et les ordonnées d’une fonction:

IMPR_FONCTION(FORMAT=”XMGRACE”,

UNITE=53,

COURBE=_F(ABSCISSE=[57766.1-x for x in MTAST.Absc()],

ORDONNEE=[abs(y) for y in MTAST.Ordo()],),

TITRE=”Courbe recalée”,

LEGENDE_X=”P2”,

LEGENDE_Y=”MT”,)

Tracé d’un résultat en fonction d’un autre#

Cet exemple est extrait en partie du cas-test [FORMA03a], il s’agit d’une plaque trouée en traction.

Après un calcul réalisé avec STAT_NON_LINE, on souhaite tracer l’effort résultant de traction en fonction du déplacement vertical moyen de la partie supérieure de l’éprouvette.

Détails du post-traitement:

POURSUITE()

SOLNL2=CALC_CHAMP( Calcul des forces nodales

reuse = SOLNL2, RESULTAT = SOLNL2,

OPTION = “FORC_NODA”,)

M=DEFI_GROUP( Définition du groupe de nœuds de

reuse=M, dépouillement, la ligne supérieure de la plaque

MAILLAGE=M,

CREA_GROUP_NO=_F(GROUP_MA = “LFG”,

NOM = “LIGNE”,),

)

tab=POST_RELEVE_T(

ACTION=(

_F(INTITULE = “Umoyen”, Relevé du déplacement moyen à tous les

RESULTAT = SOLNL2, instants du calcul

NOM_CHAM = “DEPL”,

NOM_CMP = “DY”,

TOUT_ORDRE = “OUI”,

GROUP_NO = “LIGNE”,

OPERATION = “MOYENNE”,

),

_F(INTITULE = “Fresultante”, Relevé de l’effort résultant

RESULTAT = SOLNL2,

NOM_CHAM = “FORC_NODA”,

TOUT_ORDRE = “OUI”,

GROUP_NO = “LIGNE”,

RESULTANTE = “DY”,

OPERATION = “EXTRACTION”,),),)

IMPR_TABLE(TABLE=tab,) Juste pour repérer le nom des paramètres

Contenu (partiel, limité aux 3 premiers instants) de la table:

INTITULE NOEUD RESU NOM_CHAM NUME_ORDRE INST DY SIYY QUANTITE

Umoyen - SOLNL2 DEPL 1 1.00000E+00 2.38745E-02 - MOMENT_0

Umoyen - SOLNL2 DEPL 1 1.00000E+00 -3.70291E-04 - MOMENT_1

Umoyen - SOLNL2 DEPL 1 1.00000E+00 2.36709E-02 - MINIMUM

Umoyen - SOLNL2 DEPL 1 1.00000E+00 2.40291E-02 - MAXIMUM

Umoyen - SOLNL2 DEPL 1 1.00000E+00 2.40597E-02 - MOYE_INT

Umoyen - SOLNL2 DEPL 1 1.00000E+00 2.36894E-02 - MOYE_EXT

Umoyen - SOLNL2 DEPL 2 1.20000E+00 2.86494E-02 - MOMENT_0

Umoyen - SOLNL2 DEPL 2 1.20000E+00 -4.44349E-04 - MOMENT_1

Umoyen - SOLNL2 DEPL 2 1.20000E+00 2.84050E-02 - MINIMUM

Umoyen - SOLNL2 DEPL 2 1.20000E+00 2.88350E-02 - MAXIMUM

Umoyen - SOLNL2 DEPL 2 1.20000E+00 2.88716E-02 - MOYE_INT

Umoyen - SOLNL2 DEPL 2 1.20000E+00 2.84273E-02 - MOYE_EXT

Umoyen - SOLNL2 DEPL 3 1.40000E+00 3.34244E-02 - MOMENT_0

Umoyen - SOLNL2 DEPL 3 1.40000E+00 -5.18504E-04 - MOMENT_1

Umoyen - SOLNL2 DEPL 3 1.40000E+00 3.31393E-02 - MINIMUM

Umoyen - SOLNL2 DEPL 3 1.40000E+00 3.36410E-02 - MAXIMUM

Umoyen - SOLNL2 DEPL 3 1.40000E+00 3.36837E-02 - MOYE_INT

Umoyen - SOLNL2 DEPL 3 1.40000E+00 3.31652E-02 - MOYE_EXT

[…]

Fresultante - SOLNL2 FORC_NODA 1 1.00000E+00 2.50000E+03 - -

Fresultante - SOLNL2 FORC_NODA 2 1.20000E+00 3.00000E+03 - -

Fresultante - SOLNL2 FORC_NODA 3 1.40000E+00 3.50000E+03 - -

[…]

Dy=RECU_FONCTION( Filtrage de la table pour en extraire \(\mathrm{Dy}=f(t)\)

TABLE = tab,

PARA_X = “INST”,

PARA_Y = “DY”,

FILTRE = (

_F(NOM_PARA = “INTITULE”,

VALE_K = “Umoyen”,),

_F(NOM_PARA = “QUANTITE”,

VALE_K = “MOMENT_0”,),),)

Fy=RECU_FONCTION( Filtrage de la table pour en extraire \(\mathrm{Fy}=f(t)\)

TABLE = tab,

PARA_X = “INST”,

PARA_Y = “DY”,

FILTRE = (

_F(NOM_PARA = “INTITULE”,

VALE_K = “Fresultante”,),),)

IMPR_FONCTION( Tracé des ordonnées de \(\mathrm{Fy}\) en fonction de \(\mathrm{Dy}\)

UNITE = 29,

FORMAT = “XMGRACE”,

COURBE = (

_F(FONC_X = Dy,

FONC_Y = Fy,),),

TITRE = “Plaque trouée en traction”,

LEGENDE_X = “Déplacement moyen”,

LEGENDE_Y = “Effort résultant”,)

Ce qui nous donne la courbe suivante:

../../../../_images/100000000000034A0000025336075C546C624E20.png

Tracé d’un grand nombre de courbes#

Dans certaines applications, on est amené à tracer de nombreuses courbes. Supposons que l’on souhaite comparer nos résultats à 50 points de mesure obtenus par ailleurs. Il serait alors fastidieux de définir 50 fichiers dans astk et d’utiliser 50 unités logiques différentes dans le fichier de commandes!

Il suffit alors d’utiliser le type «repe» en résultat dans astk (cf. [U1.04.00]):

../../../../_images/10000000000002820000001A609F5D738459A97E.png

On procède ensuite ainsi dans le fichier de commandes en PAR_LOT=’NON’ dans POURSUITE:

# définition des 50 groupes de nœuds de dépouillement

lgrno = [:ref:` “point01”, “point02”, …, “point50” < “point01”, “point02”, …, “point50” >`]

# pour chaque nœud de dépouillement…

for point in lgrno:

unit = 29

# les fichiers DEPL_point0i.dat seront recopiés dans Resultats/courbes/

DEFI_FICHIER(UNITE=unit, FICHIER=‘./REPE_OUT/DEPL_’+point+’.dat’)

tab=POST_RELEVE_T(

ACTION=_F(INTITULE = “VonMises”,

RESULTAT = resM,

NOM_CHAM = “SIEQ_ELNO”,

NOM_CMP = “VMIS”,

TOUT_ORDRE = “OUI”,

GROUP_NO = point,

OPERATION = “EXTRACTION”,),)

IMPR_TABLE(

UNITE = unit,

TABLE = tab,

FORMAT = “XMGRACE”,

NOM_PARA = (“INST”, “VMIS”),)

# on “libère” l’unité pour la réutiliser pour la courbe suivante

DEFI_FICHIER(UNITE=unit, ACTION=‘LIBERER’)

Quelques astuces utiles#

On propose ici quelques manipulations des données des tables en Python récurrentes lorsque de l’on veut aller plus loin dans la génération de courbes depuis Code_Aster .

Extraire de la table issue de POST_RELEVE_Tla liste des nœuds de post-traitement:

Lorsque l’on post-traite une grandeur sur un groupe de nœuds (à plus d’un nœud) pour plusieurs instants, les nœuds apparaissent pour chaque instant, il est donc nécessaire d’extraire la liste de ces nœuds sans répétition.

tabpy = tab.EXTR_TABLE()

Création de l’objet Table Python

tno = tabpy.NOEUD.values()

On extrait les valeurs de la colonne NOEUD

lno = list(set([i.strip() for i in tno]))

Méthode performante pour éliminer les

doublons utilisant set

lno.sort()

Tri par ordre croissant

Construire un ou plusieurs mots-clés dynamiquement:

Ceci peut notamment être utile pour renseigner le mot-clé facteur FILTRE d’IMPR_TABLE en fonction du contexte; on construit dans ce cas un dictionnaire qui est ensuite fourni en argument de la commande.

Ceci:

IMPR_TABLE(

UNITE = unit,

TABLE = tab,

FORMAT = “XMGRACE”,

FILTRE = (_F(NOM_PARA=”NOEUD”,

VALE_K = “N4”,),

_F(NOM_PARA=”NOEUD”,

VALE_K = “N4”,),),

NOM_PARA = (“INST”, “VMIS”),

)

est équivalent à cela:

mfac = {‘FILTRE’ : [{‘NOM_PARA’:‘NOEUD’, ‘VALE_K’: ‘N4’},

{‘NOM_PARA’:‘INTITULE’, ‘VALE_K’: ‘exemple’},],

‘NOM_PARA’ : [‘INST’, ‘VMIS’],

‘UNITE’ : unit,

‘FORMAT’ : “XMGRACE”,}

IMPR_TABLE(

TABLE = tab,

**mfac

)

L’intérêt étant bien entendu de pouvoir construire le dictionnaire comme on le souhaite.

Remarque

Les mots-clés facteurs (ici FILTRE) peuvent être construits en utilisant _F(mot_clé = valeur), mais il est plus souple de les voir comme une liste de dictionnaires.