Salome HOME
CCAR: merge de la version 1.14 dans la branche principale
[tools/eficas.git] / Aster / Cata / cataSTA9 / Macro / post_gp_ops.py
index c72135c1bf817a98af792424143b9df4b2f15510..a66baa1fb5372a697274a6a6e57f629484669fa9 100644 (file)
@@ -1,4 +1,4 @@
-#@ MODIF post_gp_ops Macro  DATE 31/10/2006   AUTEUR REZETTE C.REZETTE 
+#@ MODIF post_gp_ops Macro  DATE 15/04/2008   AUTEUR MACOCCO K.MACOCCO 
 # -*- coding: iso-8859-1 -*-
 #            CONFIGURATION MANAGEMENT OF EDF VERSION
 # ======================================================================
@@ -6,7 +6,7 @@
 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY  
 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY  
 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR     
-# (AT YOUR OPTION) ANY LATER VERSION.                                                  
+# (AT YOUR OPTION) ANY LATER VERSION.                                   
 #                                                                       
 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT   
 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF            
@@ -27,12 +27,14 @@ def post_gp_ops(self, **args):
    """
       Corps de la macro POST_GP
    """
+   import pdb
    macro = 'POST_GP'
    ier=0
    from Accas import _F
    from Utilitai.Utmess     import UTMESS
-   from Utilitai.Table      import Table, merge
+   from Utilitai.Table      import Table, merge, Colonne
    from Utilitai.t_fonction import t_fonction
+   from Cata.cata import evol_noli
    import aster
    
    # ----- On importe les definitions des commandes a utiliser dans la macro
@@ -41,6 +43,13 @@ def post_gp_ops(self, **args):
    POST_ELEM     = self.get_cmd('POST_ELEM')
    POST_RELEVE_T = self.get_cmd('POST_RELEVE_T')
    CREA_TABLE    = self.get_cmd('CREA_TABLE')
+   DEFI_LIST_ENTI= self.get_cmd('DEFI_LIST_ENTI')
+   CALC_ELEM     = self.get_cmd('CALC_ELEM')
+   RECU_FONCTION = self.get_cmd('RECU_FONCTION')
+   DETRUIRE      = self.get_cmd('DETRUIRE')
+   DEFI_GROUP    = self.get_cmd('DEFI_GROUP')
+   IMPR_CO       = self.get_cmd('IMPR_CO')
+   FIN           = self.get_cmd('FIN')
    
    # ----- Comptage, commandes + déclaration concept sortant
    self.set_icmd(1)
@@ -51,7 +60,7 @@ def post_gp_ops(self, **args):
    # 0. ----- Type de calcul
    identification = self['IDENTIFICATION'] != None
    if identification:
-      # 0.1. --- identification : on boule sur les valeurs de TEMP.
+      # 0.1. --- identification : on boucle sur les valeurs de TEMP.
       #          Pour chaque couple (T, Kjc(T)), on évalue les Ki, Kmoy et
       #          les valeurs de Gpmax, DeltaLmax, inst.max correspondantes.
       mccalc = self['IDENTIFICATION']
@@ -74,100 +83,434 @@ def post_gp_ops(self, **args):
    if not type(l_crit) in EnumTypes:
       l_crit = [l_crit,]
    
+
+   # Maillage associe au modele
+   __MAIL = aster.getvectjev( self['MODELE'].nom.ljust(8) + '.MODELE    .LGRF        ' )
+   nom_maillage = __MAIL[0].strip()
+   
+   jdc = CONTEXT.get_current_step().jdc
+   maya = jdc.sds_dict[nom_maillage]
+   
    # 1. ----- calcul de G-theta
-   nbcour = len(self['THETA_2D'])
-   l_tab = []
-   for occ in self['THETA_2D']:
-      dMC = occ.cree_dict_valeurs(occ.mc_liste)
-      
-      __theta = CALC_THETA(MODELE=self['MODELE'],
-                           DIRECTION=self['DIRECTION'],
-                           THETA_2D=_F(GROUP_NO=dMC['GROUP_NO'],
-                                       MODULE=1.0,
-                                       R_INF=dMC['R_INF'],
-                                       R_SUP=dMC['R_SUP']),)
-
-      __gtheta = CALC_G(THETA=_F(THETA=__theta),
-                        EXCIT=self['EXCIT'].List_F(),
-                        RESULTAT=self['RESULTAT'],
-                        TOUT_ORDRE='OUI',
-                        SYME_CHAR=self['SYME_CHAR'],
-                        COMP_ELAS=self['COMP_ELAS'].List_F(),)
-
-      tab = __gtheta.EXTR_TABLE()
-      
-      # une Table par couronne
-      l_tab.append(tab)
+   
+   # Cas 2D
+   if self['THETA_2D'] is not None:
+      is_2D = True
+   else:
+      is_2D = False
+   
+   if is_2D:
+      nbcour = len(self['THETA_2D'])
+      nb_tranches = 1
+      ep_z = 1
+      l_tab = []
+      for occ in self['THETA_2D']:
+         dMC = occ.cree_dict_valeurs(occ.mc_liste)
+         
+         __theta = CALC_THETA(MODELE=self['MODELE'],
+                              DIRECTION=self['DIRECTION'],
+                              THETA_2D=_F(GROUP_NO=dMC['GROUP_NO'],
+                                          MODULE=1.0,
+                                          R_INF=dMC['R_INF'],
+                                          R_SUP=dMC['R_SUP']),)
+   
+         __gtheta = CALC_G(THETA=_F(THETA=__theta),
+                           EXCIT=self['EXCIT'].List_F(),
+                           RESULTAT=self['RESULTAT'],
+                           TOUT_ORDRE='OUI',
+                           SYME_CHAR=self['SYME_CHAR'],
+                           COMP_ELAS=self['COMP_ELAS'].List_F(),)
+   
+         tab = __gtheta.EXTR_TABLE()
+         
+         # une Table par couronne
+         l_tab.append(tab)
+         
+   else:
+      #Cas 3D
+      nbcour = len(self['THETA_3D'])
+      nb_tranches = self['NB_TRANCHES']
+      l_tab = []
+      l_noeuds_fissure, pas = getFondFissInfo(self['FOND_FISS'])
+      nb_noeuds_fissure = len(l_noeuds_fissure)
+      
+      for occ in self['THETA_3D']:
+         dMC = occ.cree_dict_valeurs(occ.mc_liste)
+         
+         # on met les mots-clés facultatifs dans des dictionnaires
+         dpar_theta = {}
+         if self['DIRECTION'] is not None:
+            dpar_theta['DIRECTION'] = self['DIRECTION']
+         
+         __gtheta = CALC_G(
+                           THETA=_F(R_INF=dMC['R_INF'],
+                                    R_SUP=dMC['R_SUP'],
+                                    MODULE=1.0,
+                                    FOND_FISS=self['FOND_FISS'],
+                                    **dpar_theta),
+                           EXCIT=self['EXCIT'].List_F(),
+                           RESULTAT=self['RESULTAT'],
+                           TOUT_ORDRE='OUI',
+                           SYME_CHAR=self['SYME_CHAR'],
+                           COMP_ELAS=self['COMP_ELAS'].List_F(),
+                           LISSAGE=self['LISSAGE'].List_F()
+                           )
+
+         tab = __gtheta.EXTR_TABLE()
+         
+         # une Table par couronne
+         l_tab.append(tab)
+
+   
 
    # 2. ----- Calcul de l'energie élastique en exploitant les groupes de
    #          mailles fournis par la procedure de maillage
-   l_copo = [grma.strip() for grma in self['GROUP_MA']]
-   nbcop = len(l_copo)
-   l_charg = [charg['CHARGE'] for charg in self['EXCIT']]
-   
-   __ener = POST_ELEM(MODELE=self['MODELE'],
-                        RESULTAT=self['RESULTAT'],
-                        CHARGE=l_charg,
-                        TOUT_ORDRE='OUI',
-                        ENER_ELAS=_F(GROUP_MA=l_copo),
-                        TITRE='Energie élastique',)
-
-   t_enel = __ener.EXTR_TABLE()
-   
-   # 2.1. ----- Indice de chaque copeau et deltaL
-   d_icop = dict(zip(l_copo, range(1, nbcop + 1)))
-   
-   l_lieu = [grma.strip() for grma in t_enel.LIEU.values()]
-   l_icop = [d_icop[grma] for grma in l_lieu]
-   t_enel['ICOP'] = l_icop
-   t_enel.fromfunction('DELTAL', fDL, 'ICOP', { 'pascop' : self['PAS_ENTAILLE'] })
-   
-   # 2.2. ----- Calcul de Gp fonction de Ener.Totale et de deltaL
-   t_enel.fromfunction('GP', fGp_Etot, ('TOTALE', 'ICOP'),
-         { 'pascop' : self['PAS_ENTAILLE'],
-           'syme'   : self['SYME_CHAR'] != 'SANS',
-           'R'      : self['RAYON_AXIS'] })
-   
-   # 2.3. ----- Tableau de Gp = f(icop) pour chaque instant
-   if info >= 2:
-      tGp_t_icop = t_enel['INST', 'DELTAL', 'GP']
-      tGp_t_icop.titr = "Gp à chaque instant en fonction de la distance au " \
-                        "fond d'entaille"
-      tGp_t_icop.ImprTabCroise()
-   
-   # 2.4. ----- Table Gpmax
-   ttmp = t_enel['NUME_ORDRE', 'INST', 'ICOP', 'DELTAL', 'GP']
-   l_numord = list(Set(ttmp.NUME_ORDRE.values()))
-   l_numord.sort()
-   for j in l_numord:
-      tj = ttmp.NUME_ORDRE == j
-      if self['CRIT_MAXI_GP'] == 'ABSOLU':
-         t = tj.GP.MAXI()
+
+   l_copo_tot = [grma.strip() for grma in self['GROUP_MA']]
+   nbcop_tot = len(l_copo_tot)
+   nbcop = nbcop_tot/nb_tranches
+   
+   if self['LIST_EP_COPEAUX'] is not None:
+      l_ep_copeaux_tot = self['LIST_EP_COPEAUX']
+   
+   l_t_enel = []
+   
+   if self['TRAC_COMP']=='OUI':
+      # prise en compte de la traction-compression dans le calcul de l'energie
+      resu2=CALC_ELEM(OPTION=('EQUI_ELNO_SIGM'),
+                     RESULTAT=self['RESULTAT'],
+                     )
+                     
+      # indices des mailles du dernier group_ma
+      # (pour avoir le nombre de mailles par tranche)
+      l_mailles_last_gm = maya.GROUPEMA.get()[l_copo_tot[-1].ljust(8)]
+      
+      # initialisation des concepts reutilises dans la boucle
+      # on suppose que chaque tranche a le meme nombre de mailles
+      
+      kk = 0
+      
+      E_el = [None]*len(l_mailles_last_gm)*nb_tranches
+
+      T_el = [None]*len(l_mailles_last_gm)*nb_tranches
+      
+      # on recupere les sd en dehors de la boucle
+      maya_GROUPEMA = maya.GROUPEMA.get()
+      maya_NOMMAI = maya.NOMMAI.get()
+      maya_CONNEX = maya.CONNEX.get()
+      maya_NOMNOE = maya.NOMNOE.get()
+
+   # liste des tables tb_Gpmax repartie aux noeuds
+   l_tb_Gpmax_noeuds = []
+      
+   for i in range(0,nb_tranches):
+      l_copo = l_copo_tot[i*nbcop:(i+1)*nbcop]   
+      l_charg = [charg['CHARGE'] for charg in self['EXCIT']]
+      
+      if info >= 2 and not is_2D:
+         print "<I> Calcul de la tranche %i"%(i+1)
+      
+      if self['TRAC_COMP']=='OUI':
+         
+         # l_copo est une liste commulative de mailles
+         # il faut lancer POST_ELEM sur chaque maille de chaque copeau
+         # puis regarder la trace de SIEF_ELGA sur ce copeau
+         
+         # on fera attention a ne pas lancer POST_ELEM sur une maille qui 
+         # a deja ete calculee en stockant son resultat pour la maille en question
+         d_groupma={}
+         d_nomma={}
+         
+         # indices des mailles des copeaux
+         for group_ma in l_copo:
+            d_groupma[group_ma] = maya_GROUPEMA[group_ma.ljust(8)]
+         
+         # le dernier copeau contient tous les elements
+         # on calcule l energie de chaque element de ce copeau
+         last_copo = l_copo[-1]
+         
+         d_ener = {}
+         
+         d_nomma = {}
+         
+         for k, id_elem in enumerate(d_groupma[last_copo]):
+            
+            
+            # les id des elements dans Aster commencent a 1
+            # la liste python commence a 0
+            elem = maya_NOMMAI[id_elem-1]
+            d_nomma[id_elem]=elem
+            
+            E_el[kk] = POST_ELEM(MODELE=self['MODELE'],
+                                 RESULTAT=self['RESULTAT'],
+                                 CHARGE=l_charg,
+                                 TOUT_ORDRE='OUI',
+                                 ENER_ELAS=_F(MAILLE=elem),
+                                 TITRE='Energie élastique',)
+            
+            T_el[kk] = E_el[kk].EXTR_TABLE()
+            
+            l_enel = T_el[kk].TOTALE.values()
+            
+            # signe de la trace <=> signe de la composante VMIS_SG du tenseur EQUI_ELNO_SIGM,
+            # mais E_enel est par element => on fait une moyenne sur les noeuds de l'element
+            
+            list_no = []
+            for ind_no in maya_CONNEX[id_elem] :
+               nomnoe = maya_NOMNOE[ind_no-1]
+               if nomnoe not in list_no :
+                  list_no.append(nomnoe)
+            
+            # print "liste des noeuds de la maille ", id_elem, ": ", list_no
+            
+            l_inst = T_el[kk].INST.values()
+            nb_inst = len(l_inst)
+            
+            T_noeuds = Table()
+            T_noeuds['INST']=l_inst
+               
+            # pour chaque noeud de l'element on recupere sa trace
+            for noeud in list_no:
+               
+               VM=RECU_FONCTION(RESULTAT=resu2,
+                                    TOUT_INST='OUI',
+                                    NOM_CHAM='EQUI_ELNO_SIGM',
+                                    NOM_CMP='VMIS_SG',
+                                    MAILLE=elem,
+                                    NOEUD=noeud);
+   
+               T_noeuds[noeud]=VM.Ordo()
+               
+               DETRUIRE(CONCEPT=(_F(NOM=VM)))
+               
+            T_noeuds.fromfunction('VM_MAIL', moyenne, list_no)
+            
+            l_VM_MAIL = T_noeuds.VM_MAIL.values()
+            
+            for j, vm in enumerate(l_VM_MAIL):
+               if vm < 0:
+                  l_enel[j]=-l_enel[j]
+                  
+            del T_el[kk]['TOTALE']
+            T_el[kk][elem]=l_enel
+   
+            if k==0:
+            
+               # Table de l'energie elastique sur le GROUP_MA
+               T_el_gm = Table()
+               T_el_gm['NUME_ORDRE'] = T_el[kk].NUME_ORDRE.values()
+               T_el_gm['INST'] = T_el[kk].INST.values()
+               T_el_gm['LIEU'] = [last_copo]*nb_inst
+               T_el_gm['ENTITE'] = ['GROUP_MA']*nb_inst
+               
+            T_el_gm[elem]=l_enel
+            
+            kk+=1
+         
+         # sommation sur les mailles du group_ma:
+         l_nomma = d_nomma.values()
+         T_el_gm.fromfunction('TOTALE', mysum, l_nomma)
+         
+         # Table totale
+         t_enel=Table(titr="Energie élastique")
+         t_enel['NUME_ORDRE']=T_el_gm.NUME_ORDRE.values()
+         t_enel['INST']=T_el_gm.INST.values()
+         t_enel['LIEU']=T_el_gm.LIEU.values()
+         t_enel['ENTITE']=T_el_gm.ENTITE.values()
+         t_enel['TOTALE']=T_el_gm.TOTALE.values()
+   
+         # t_enel ne contient jusqu'ici que l'energie elastique du dernier copeau
+         
+         # calcul de l'energie elastique pour les autres copeaux
+         T_el_sub = T_el_gm.copy()
+         
+         for k in range(len(l_copo)-2,-1,-1):
+            group_ma = l_copo[k]
+            T_el_sub = T_el_sub.copy()
+            del T_el_sub['LIEU']
+            del T_el_sub['TOTALE']
+            T_el_sub['LIEU']=[group_ma]*nb_inst
+            l_id_elem = d_groupma[group_ma]
+            l_nom_elem = []
+            
+            for id_elem, nom_elem in d_nomma.items():
+               if not id_elem in l_id_elem:
+                  # colonne a supprimer
+                  del T_el_sub[nom_elem]
+                  del d_nomma[id_elem]
+               else:
+                  l_nom_elem.append(nom_elem)
+            
+            T_el_sub.fromfunction('TOTALE', sum_and_check, l_nom_elem)
+            
+            # Table de l'energie elastique sur le GROUP_MA               
+            T_el_gm_k = Table()
+            T_el_gm_k['NUME_ORDRE'] =T_el_sub.NUME_ORDRE.values()
+            T_el_gm_k['INST'] = T_el_sub.INST.values()
+            T_el_gm_k['LIEU'] = [group_ma]*nb_inst
+            T_el_gm_k['ENTITE'] = ['GROUP_MA']*nb_inst
+            T_el_gm_k['TOTALE'] = T_el_sub.TOTALE.values()
+            
+            # contribution du group_ma a la table totale:
+            t_enel = merge(t_enel, T_el_gm_k)
+   
+         t_enel.sort('NUME_ORDRE')
+      
+      else:
+         # si self['TRAC_COMP']!='OUI'
+         # calcul classique de l'energie elastique
+      
+         __ener = POST_ELEM(MODELE=self['MODELE'],
+                                 RESULTAT=self['RESULTAT'],
+                                 CHARGE=l_charg,
+                                 TOUT_ORDRE='OUI',
+                                 ENER_ELAS=_F(GROUP_MA=l_copo),
+                                 TITRE='Energie élastique',)
+      
+         t_enel = __ener.EXTR_TABLE()
+   
+      # 2.1. ----- Indice de chaque copeau et deltaL
+      d_icop = dict(zip(l_copo, range(1, nbcop + 1)))
+      
+      l_lieu = [grma.strip() for grma in t_enel.LIEU.values()]
+      
+      l_icop = [d_icop[grma] for grma in l_lieu]
+      
+      t_enel['ICOP'] = l_icop
+   
+      l_numord = list(Set(t_enel.NUME_ORDRE.values()))
+      l_numord.sort()
+
+      if self['PAS_ENTAILLE'] is not None:
+         t_enel.fromfunction('DELTAL', fDL, 'ICOP', { 'pascop' : self['PAS_ENTAILLE'] })
+      else:
+         l_ep_copeaux_tranche = l_ep_copeaux_tot[i*nbcop:(i+1)*nbcop]
+         t_enel['DELTAL'] = l_ep_copeaux_tranche*len(l_numord)
+
+      # 2.2. ----- Calcul de Gp fonction de Ener.Totale et de deltaL
+      if is_2D:
+         t_enel.fromfunction('GP', fGp_Etot, ('TOTALE', 'DELTAL'),
+            {'syme'   : self['SYME_CHAR'] != 'SANS',
+             'R'      : self['RAYON_AXIS'],})
       else:
-         t = MaxRelatif(tj, 'GP')
-      if j == 1:
-         tb_Gpmax = t
+         ep_tranche = largeur_tranche(nom_maillage, l_noeuds_fissure, pas, i)
+         #print "ep_tranche %i: "%i, ep_tranche
+         t_enel.fromfunction('GP', fGp_Etot, ('TOTALE', 'DELTAL'),
+               {'syme'   : self['SYME_CHAR'] != 'SANS',
+                'R'      : ep_tranche })
+      
+      #if info >= 2:
+      #   print "Table de l'énergie élastique: ", t_enel
+      
+      l_t_enel.append(t_enel)
+      # 2.3. ----- Tableau de Gp = f(icop) pour chaque instant
+      if info >= 2:
+         tGp_t_icop = t_enel['INST', 'DELTAL', 'GP']
+         tGp_t_icop.titr = "Gp à chaque instant en fonction de la distance au " \
+                           "fond d'entaille"
+         tGp_t_icop.ImprTabCroise()
+   
+      # 2.4. ----- Table Gpmax
+      ttmp = t_enel['NUME_ORDRE', 'INST', 'ICOP', 'DELTAL', 'GP']
+
+      for j in l_numord:
+         tj = ttmp.NUME_ORDRE == j
+         
+         ## pour tester le comportement de Gpmax quand GP est identiquement nul
+         #del tj['GP']
+         #tj['GP']=[0]*len(tj.GP.values())
+         
+         if self['CRIT_MAXI_GP'] == 'ABSOLU':
+            t = tj.GP.MAXI()
+         else:
+            t = MaxRelatif(tj, 'GP')
+         
+         # cas GP identiquement nul: plusieurs max de GP
+         # on prend le DELTAL minimum
+         if len(t.GP.values())>1:
+            t = t.DELTAL.MINI()
+         
+         if j == 1:
+            tb_Gpmax_i = t
+         else:
+            tb_Gpmax_i = tb_Gpmax_i | t
+      
+      
+      tb_Gpmax_i.Renomme('GP', 'GPMAX')
+      tb_Gpmax_i.Renomme('ICOP', 'ICOPMAX')
+      tb_Gpmax_i.Renomme('DELTAL', 'DELTALMAX')
+      tb_Gpmax_i.titr = 'Gpmax à chaque instant'
+      
+      # On transfert Gpmax au noeud sommet à gauche et au milieu (si cas quadratique)
+      # sauf pour la dernière tranche où on transfère également au noeud sommet de droite.
+      # Tout cela pour pouvoir avoir une table complète avec les G et les Gpmax.
+      if not is_2D:
+         tb_Gpmax_i['NUME_TRANCHE']=[i+1]*len(tb_Gpmax_i['GPMAX'])
+         if i==0:
+            l_inst = tb_Gpmax_i.INST.values()
+            nb_inst = len(l_inst)
+         if pas==1:
+            tb_Gpmax_i_noeuds = tb_Gpmax_i.copy()
+            tb_Gpmax_i_noeuds['NOEUD']=[l_noeuds_fissure[i]]*nb_inst
+            l_tb_Gpmax_noeuds.append(tb_Gpmax_i_noeuds)
+         else:
+            tb_Gpmax_i_noeuds_1 = tb_Gpmax_i.copy()
+            tb_Gpmax_i_noeuds_1['NOEUD'] = [l_noeuds_fissure[pas*i]]*nb_inst
+            l_tb_Gpmax_noeuds.append(tb_Gpmax_i_noeuds_1)
+            tb_Gpmax_i_noeuds_2 = tb_Gpmax_i.copy()
+            tb_Gpmax_i_noeuds_2['NOEUD'] = [l_noeuds_fissure[pas*i+1]]*nb_inst
+            l_tb_Gpmax_noeuds.append(tb_Gpmax_i_noeuds_2)
+         if i==nb_tranches-1:
+            tb_Gpmax_i_noeuds_3 = tb_Gpmax_i.copy()
+            tb_Gpmax_i_noeuds_3['NOEUD'] = [l_noeuds_fissure[-1]]*nb_inst
+            l_tb_Gpmax_noeuds.append(tb_Gpmax_i_noeuds_3)
+            
+
+      
+      if i == 0:
+         tb_Gpmax = tb_Gpmax_i
       else:
-         tb_Gpmax = tb_Gpmax | t
-   tb_Gpmax.Renomme('GP', 'GPMAX')
-   tb_Gpmax.Renomme('ICOP', 'ICOPMAX')
-   tb_Gpmax.Renomme('DELTAL', 'DELTALMAX')
-   tb_Gpmax.titr = 'Gpmax à chaque instant'
-   if info >= 2:
-      print tb_Gpmax
+         tb_Gpmax = merge(tb_Gpmax, tb_Gpmax_i)
+   
+   # FIN BOUCLE SUR LES TRANCHES
+   
+   if not is_2D:
+      tb_Gpmax_noeuds = Table(para=tb_Gpmax.para+['NOEUD'])
+      for j, tb in enumerate(l_tb_Gpmax_noeuds):
+         if j==0:
+            tb_Gpmax_noeuds = tb
+         else:
+            tb_Gpmax_noeuds = merge(tb_Gpmax_noeuds, tb)
+   
    
    # 2.5. ----- extraction de la température en fond d'entaille
+   #voir le cas 3D => THETA_3D, mais qu'en est-il des tranches?
    if self['RESU_THER']:
-      grno_fond = self['THETA_2D'][0]['GROUP_NO']
+      #sur un seul noeud ou sur tous les noeuds du fond d'entaille?
+      
+      if is_2D:
+         grno_fond = self['THETA_2D'][0]['GROUP_NO']
+      else:
+         grma_fond = self['THETA_3D'][0]['GROUP_MA']
+         grno_fond = "GRNOFOND"
+         DEFI_GROUP(reuse =maya,
+                    MAILLAGE=maya,
+                    CREA_GROUP_NO=_F(GROUP_MA=grma_fond,
+                                     NOM=grno_fond,),);
+      
+      l_ordres = DEFI_LIST_ENTI(VALE=l_numord)
       __relev = POST_RELEVE_T(ACTION=_F(RESULTAT=self['RESU_THER'],
                                         OPERATION='EXTRACTION',
                                         INTITULE='Temperature',
                                         NOM_CHAM='TEMP',
-                                        TOUT_ORDRE='OUI',
+                                        LIST_ORDRE=l_ordres,
                                         NOM_CMP='TEMP',
                                         GROUP_NO=grno_fond,),)
-      t_relev = __relev.EXTR_TABLE()['NUME_ORDRE', 'TEMP']
-   
+
+      t_relev = __relev.EXTR_TABLE()['NUME_ORDRE', 'NOEUD', 'TEMP']
    
    # 3. ----- boucle sur les mots-clés facteurs
    #          opérations dépendant de la température
@@ -178,7 +521,7 @@ def post_gp_ops(self, **args):
       # 3.0. ----- Temperature fonction du temps : si on n'a pas de RESU_THER,
       #            on prend la température d'identification.
       if not self['RESU_THER']:
-         l_rows = [{'NUME_ORDRE' : i, 'TEMP' : TEMP} for i in l_numord]
+         l_rows = [{'NUME_ORDRE' : j, 'TEMP' : TEMP} for j in l_numord]
          t_relev = Table(rows=l_rows, para=('NUME_ORDRE', 'TEMP'), typ=('R', 'R'))
          flag_mat = True
       
@@ -188,44 +531,73 @@ def post_gp_ops(self, **args):
                { 'para' : 'E', 'MATER' : MATER })
          t_relev.fromfunction('NU', CallRCVALE, 'TEMP',
                { 'para' : 'NU', 'MATER' : MATER })
-         #tb_Gpmax = merge(tb_Gpmax, t_relev, 'NUME_ORDRE')
          flag_mat = False
       
       # 3.2. ----- paramètres
       dict_constantes = {
          'YOUNG' : CallRCVALE(TEMP, 'E', MATER),
          'NU'    : CallRCVALE(TEMP, 'NU', MATER),
-         'R'     : self['RAYON_AXIS'],
       }
+      if is_2D:
+         dict_constantes['R'] = self['RAYON_AXIS']
+      else:
+         dict_constantes['R'] = ep_tranche
+         
       
       # 3.3. ----- calcul de Kj(G)
       l_tabi = []
       for k, tab in enumerate(l_tab):
-         # fusion avec TEMP, E et nu.
-         tab = merge(tab, t_relev, 'NUME_ORDRE')
+         #tab: table de la couronne k
          
          # calcul de Kj(G) = K_i
          new_para = 'K_%d' % (k + 1)
-         tab.fromfunction(new_para, fKj, ('G', 'YOUNG', 'NU'),
-                          { 'R' : self['RAYON_AXIS'] })
-         
-         # renomme G en G_i
-         tab.Renomme('G', 'G_%d' % (k + 1))
+         if is_2D:
+            # fusion avec TEMP, E et nu
+            tab = merge(tab, t_relev, 'NUME_ORDRE')
+            tab.fromfunction(new_para, fKj, ('G', 'YOUNG', 'NU'),
+                           { 'R' : self['RAYON_AXIS'] })
+            # renomme G en G_i
+            tab.Renomme('G', 'G_%d' % (k + 1))
+         else:
+            if self['RESU_THER']:
+               tab=merge(tab, t_relev, ['NUME_ORDRE', 'NOEUD'])
+            else:
+               tab=mergeLineInTable(tab, t_relev, nb_noeuds_fissure)
+
+            # en 3D, le paramètre R n'intervient pas
+            tab.fromfunction(new_para, fKj, ('G_LOCAL', 'YOUNG', 'NU'))
+            tab.Renomme('G_LOCAL', 'G_%d' % (k + 1))
+
          l_tabi.append(tab)
       
       # 3.4 ----- Table des Gi, Ki sur les differentes couronnes + Kmoyen
-      tabK_G = l_tabi[0]['NUME_ORDRE']
-      for tab in l_tabi:
-         tabK_G = merge(tabK_G, tab, 'NUME_ORDRE')
+      if is_2D:
+         tabK_G = l_tabi[0]['NUME_ORDRE']
+         for tab in l_tabi:
+            tabK_G = merge(tabK_G, tab, 'NUME_ORDRE')
+      else:
+         tabK_G=l_tabi[0]
+         for i in range(1,len(l_tabi)):
+            tabK_G = merge(tabK_G, l_tabi[i], ['NUME_ORDRE', 'NOEUD'])
       tabK_G.titr = 'G et K sur les differentes couronnes + moyennes'
-      tabK_G.fromfunction('GMOY', moyenne, ['G_%d' % (k + 1) for k in range(nbcour)])
+      tabK_G.fromfunction('GMOY', moyenne_positive, ['G_%d' % (k + 1) for k in range(nbcour)])
       tabK_G.fromfunction('KMOY', moyenne, ['K_%d' % (k + 1) for k in range(nbcour)])
       
       # 3.5. ----- Contribution à la table globale
-      tabres = merge(tabK_G, tb_Gpmax, 'NUME_ORDRE')
-      tabres['OCCURRENCE'] = [iocc + 1] * len(l_numord)
-      if info >= 2:
-         print tabres
+      
+      if is_2D:
+         tabres = merge(tabK_G, tb_Gpmax, 'NUME_ORDRE')
+         tabres['OCCURRENCE'] = [iocc + 1] * len(l_numord)
+      else:
+         # tb_Gpmax est une table sur les tranches, 
+         # on l'ajoute dans la table aux noeuds tabres avec la convention:
+         # au 1er noeud et noeud milieu de la tranche on affecte la valeur de la tranche
+         # sauf pour la derniere tranche où on affecte la valeur sur les 3 noeuds de la tranche
+         tabres = tabK_G         
+         tabres = merge(tabK_G, tb_Gpmax_noeuds, ['NUME_ORDRE', 'NOEUD'])
+         tabres['OCCURRENCE'] = [iocc + 1] * len(l_numord) * nb_noeuds_fissure
+      #if info >= 2:
+      #   print tabres
       
       # 3.5.1. --- Table globale
       if iocc == 0:
@@ -242,37 +614,122 @@ def post_gp_ops(self, **args):
          'PROL_DROITE' : 'CONSTANT',
          'PROL_GAUCHE' : 'CONSTANT',
       }
-      # Gpmax fonction du temps
-      d_para.update({ 'NOM_RESU' : 'GPMAX' })
-      fGp = t_fonction(tabres.INST.values(), tabres.GPMAX.values(), d_para)
       
       # 3.6.1. --- identification
       if identification:
          KJ_CRIT = l_crit[iocc]
-         # définition des fonctions pour faire les interpolations
-         d_para.update({ 'NOM_RESU' : 'DELTALMAX' })
-         fdL = t_fonction(tabres.INST.values(), tabres.DELTALMAX.values(), d_para)
-   
-         d_para.update({ 'NOM_PARA' : 'KMOY',
-                         'NOM_RESU' : 'INST', })
-         valkmoy = tabres.KMOY.values()
-         finv = t_fonction(valkmoy, tabres.INST.values(), d_para)
-         
+         # on verifie que KJ_CRIT soit compris dans l'intervalle [KMOY_min, KMOY_max]
+         valkmoy = tabres.KMOY.values()            
          if not (min(valkmoy) <= KJ_CRIT <= max(valkmoy)):
-            UTMESS('A', macro, 'Interpolation hors du domaine (prolongement ' \
-                               'constant utilisé).')
-         # valeurs à mettre dans la table
-         ti   = finv(KJ_CRIT)
-         Gpi  = fGp(ti)
-         d_ident = {
-            'KJ_CRIT'   : KJ_CRIT,
-            'INST'      : ti,
-            'GPMAX'     : Gpi,
-            'KGPMAX'    : fKj(Gpi, **dict_constantes),
-            'DELTALMAX' : fdL(ti),
-         }
-         lv_ident.append(d_ident)
-      
+#                               'constant utilisé).')
+            UTMESS('A','RUPTURE0_1')
+         if is_2D:
+            # définition des fonctions pour faire les interpolations
+            d_para.update({ 'NOM_RESU' : 'DELTALMAX' })
+            # DeltaMax en fonction du temps
+            fdL = t_fonction(tb_Gpmax.INST.values(), tb_Gpmax.DELTALMAX.values(), d_para)
+            # Gpmax fonction du temps
+            d_para.update({ 'NOM_RESU' : 'GPMAX' })
+            fGp = t_fonction(tb_Gpmax.INST.values(), tb_Gpmax.GPMAX.values(), d_para)
+            
+            d_para.update({ 'NOM_PARA' : 'KMOY',
+                           'NOM_RESU' : 'INST', })
+            valkmoy = tabres.KMOY.values()
+            # temps en fonction de Kmoy
+            finv = t_fonction(valkmoy, tabres.INST.values(), d_para)
+
+            # valeurs à mettre dans la table
+            # temps correspondant à KJ_CRIT
+            ti   = finv(KJ_CRIT)
+            # GP correspondant au temps critique
+            Gpi  = fGp(ti)
+            d_ident = {
+               'KJ_CRIT'   : KJ_CRIT,
+               'INST'      : ti,
+               'GPMAX'     : Gpi,
+               'KGPMAX'    : fKj(Gpi, **dict_constantes),
+               'DELTALMAX' : fdL(ti),
+            }
+            lv_ident.append(d_ident)
+         else:
+            
+            l_i_noeuds_sommets = range(0,len(l_noeuds_fissure),pas)
+            t_noeud_Kcrit = Table(para=tabres.para)
+            
+            # On determine quel noeud sommet maximise KMOY au cours du temps:
+            
+            row_KMOY_max = tabres.KMOY.MAXI()
+            noeud_KMOY_max = row_KMOY_max.NOEUD.values()[0]
+            
+            # avec le noeud ou KJ_CRIT est atteint, on regarde GP a gauche et a droite. 
+            # le GP le plus grand correspond au GPmax
+            # on garde la tranche ou GP est le plus grand            
+            
+            id_noeud_KMOY_max = list(l_noeuds_fissure).index(noeud_KMOY_max)
+            if id_noeud_KMOY_max==0:
+               # "Gpmax sur la 1ere tranche"
+               nume_tranche_Gpmax = 1
+            elif id_noeud_KMOY_max==(len(l_noeuds_fissure)-1):
+               # "Gpmax sur la derniere tranche"
+               nume_tranche_Gpmax = nb_tranches
+            else:
+               # "Gpmax sur une tranche intermediaire"
+               Gpi_tot = Table(para=tb_Gpmax.para)
+               Gpi_gauche = tb_Gpmax.NUME_TRANCHE==(id_noeud_KMOY_max/pas)
+               Gpi_tot.append(Gpi_gauche.rows[0])
+               Gpi_droite = tb_Gpmax.NUME_TRANCHE==(id_noeud_KMOY_max/pas+1)
+               Gpi_tot.append(Gpi_droite.rows[0])
+               Gpi_tab = Gpi_tot.GPMAX.MAXI()
+               nume_tranche_Gpmax = Gpi_tab.NUME_TRANCHE.values()[0]
+            
+            # tb_Gpmax_TrancheCrit est une table de la meme nature que la table 2D tb_Gpmax
+            # i.e. valeurs sur la seule tranche qui nous interesse (ou on sait
+            # que KJ_CRIT sera atteint)
+            
+            tb_Gpmax_TrancheCrit = tb_Gpmax.NUME_TRANCHE==nume_tranche_Gpmax
+            
+            # avec le noeud ou KJ_CRIT est atteint, on determine le temps
+            # critique par interpolation            
+            tabres_NoeudCrit = tabres.NOEUD==noeud_KMOY_max
+            
+            # la suite est idem 2D, seuls les noms des tables changent
+    
+            # définition des fonctions pour faire les interpolations
+            d_para.update({ 'NOM_RESU' : 'DELTALMAX' })
+            # DeltaMax en fonction du temps
+            fdL = t_fonction(tb_Gpmax_TrancheCrit.INST.values(),
+                              tb_Gpmax_TrancheCrit.DELTALMAX.values(),
+                              d_para)
+            
+            # Gpmax fonction du temps
+            d_para.update({ 'NOM_RESU' : 'GPMAX' })
+            fGp = t_fonction(tb_Gpmax_TrancheCrit.INST.values(),
+                              tb_Gpmax_TrancheCrit.GPMAX.values(),
+                              d_para)
+            
+    
+            d_para.update({ 'NOM_PARA' : 'KMOY',
+                           'NOM_RESU' : 'INST', })
+            valkmoy = tabres_NoeudCrit.KMOY.values()
+            # temps en fonction de Kmoy
+            finv = t_fonction(valkmoy, tabres_NoeudCrit.INST.values(), d_para)
+   
+            # valeurs à mettre dans la table
+            # temps correspondant a KJ_CRIT
+            ti   = finv(KJ_CRIT)
+            # GP correspondant au temps critique
+            Gpi  = fGp(ti)
+            # par rapport a 2D, on ajoute 'NUME_TRANCHE'
+            d_ident = {
+               'KJ_CRIT'      : KJ_CRIT,
+               'INST'         : ti,
+               'NUME_TRANCHE' : int(nume_tranche_Gpmax),
+               'GPMAX'        : Gpi,
+               'KGPMAX'       : fKj(Gpi, **dict_constantes),
+               'DELTALMAX'    : fdL(ti),
+            }
+            lv_ident.append(d_ident)
+            
       # 3.6.2. --- prédiction
       else:
          pass
@@ -280,9 +737,13 @@ def post_gp_ops(self, **args):
    # 4. ----- Construction de la table résultat si demandée
    # 4.1. --- identification
    if identification:
+      if is_2D:
+         para_tab_ident=('KJ_CRIT', 'INST', 'GPMAX', 'KGPMAX', 'DELTALMAX')
+      else:
+         para_tab_ident=('KJ_CRIT', 'INST', 'NUME_TRANCHE', 'GPMAX', 'KGPMAX', 'DELTALMAX')
       tab_ident = Table(rows=lv_ident,
-                        para=('KJ_CRIT', 'INST', 'GPMAX', 'KGPMAX', 'DELTALMAX'),
-                        typ= ('R',       'R',    'R',     'R',      'R'),
+                        para=para_tab_ident,
+                        typ = ('R')*len(para_tab_ident),
                         titr='Identification aux valeurs de tenacités critiques')
       dprod_result = tab_ident.dict_CREA_TABLE()
       if info >= 2:
@@ -295,7 +756,25 @@ def post_gp_ops(self, **args):
                       'NOM_RESU' : 'GP_CRIT', })
       fGpc = t_fonction(mccalc['TEMP'], mccalc['GP_CRIT'], d_para)
       
-      tab_pred = tabl_glob['NUME_ORDRE', 'INST', 'TEMP', 'DELTALMAX', 'GPMAX']
+      # en 3D, GPMAX et DELTALMAX ne sont pas dans tab_glob: les recuperer de tb_Gpmax
+      
+      if is_2D:
+         tab_pred = tabl_glob['NUME_ORDRE', 'INST', 'TEMP', 'DELTALMAX', 'GPMAX']
+      else:
+         tab_pred = tb_Gpmax['NUME_ORDRE', 'INST', 'NUME_TRANCHE', 'DELTALMAX', 'GPMAX']
+         # on recupere TEMP de tabl_glob
+         tab_temp_tranche=Table(para=['NUME_ORDRE', 'NUME_TRANCHE', 'TEMP'])
+         # on fait une moyenne de la temperature sur les noeuds d'une tranche
+         for ordre in l_numord:
+            tabl_glob_ORDRE_i = tabl_glob.NUME_ORDRE==ordre
+            temp_ORDRE_i = tabl_glob_ORDRE_i.TEMP.values()
+            for i_tranche in range(nb_tranches):
+               l_temp_noeuds_tranche_i = temp_ORDRE_i[i_tranche : i_tranche+pas+1]
+               temp_tranche_i = moyenne(*l_temp_noeuds_tranche_i)
+               d = {'NUME_ORDRE': ordre, 'NUME_TRANCHE': i_tranche+1, 'TEMP': temp_tranche_i}
+               tab_temp_tranche.append(d)
+         tab_pred = merge(tab_pred, tab_temp_tranche, ['NUME_ORDRE', 'NUME_TRANCHE'])
+      
       tab_pred.fromfunction('GP_CRIT', fGpc, 'TEMP')
       tab_pred.fromfunction('PREDICTION', crit, ('GP_CRIT', 'GPMAX'))
       tab_pred.titr = 'Comparaison Gpmax à Gpcrit(T)'
@@ -318,10 +797,12 @@ def CallRCVALE(TEMP, para, MATER):
    return valres
 
 # -----------------------------------------------------------------------------
-def fKj(G, YOUNG, NU, R):
+def fKj(G, YOUNG, NU, R=1):
    """Calcul de Kj à partir de G (formule d'Irwin)
+      R n'intervient pas en 3D
    """
-   return (G / R * YOUNG / (1.0 - NU**2))**0.5
+   Kj=(abs(G / R * YOUNG / (1.0 - NU**2)))**0.5
+   return Kj
 
 # -----------------------------------------------------------------------------
 def fDL(ICOP, pascop):
@@ -330,16 +811,20 @@ def fDL(ICOP, pascop):
    return ICOP * pascop
 
 # -----------------------------------------------------------------------------
-def fGp_Etot(TOTALE, ICOP, pascop, R, syme=False):
+def fGp_Etot(TOTALE, DELTAL, R, syme=False):
    """Gp(Etotale, K), deltal pris dans le context global.
-      ICOP   : numéro du copeau,
-      pascop : pas d'entaille.
-      syme   : True s'il y a symétrie.
+      ICOP      : numéro du copeau,
+      DELTAL    : liste des epaisseurs des copeaux
+      R         : rayon en axisymetrique,
+                  longueur de l'élément 1D situé sur le front d'entaille si modèle 3D.
+      syme      : True s'il y a symétrie.
    """
-   fact_axis = 1.
+   import types
+   fact_syme = 1.
    if syme:
-      fact_axis = 2.
-   return fact_axis * TOTALE / (fDL(ICOP, pascop) * R)
+      fact_syme = 2.
+   Gp_Etot = fact_syme * TOTALE / (DELTAL * R )
+   return Gp_Etot
 
 # -----------------------------------------------------------------------------
 def MaxRelatif(table, nom_para):
@@ -369,3 +854,86 @@ def moyenne(*args):
    """
    return sum(args)/len(args)
 
+def moyenne_positive(*args):
+   """Fonction moyenne
+   """
+   return sum([abs(a) for a in args])/len(args)
+
+def mysum(*args):
+   """Fonction sum.
+      La fonction sum ne peut pas etre appelee sur une liste de parametre
+      d'une table via fromfunction
+   """
+   return sum(args)
+
+def sum_and_check(*args):
+   """Fonction sum.
+      Verifie si la somme est positive.
+      Si la somme est negative, on la met egale a zero
+   """
+   somme = sum(args)
+   if somme<0:
+      somme=0
+   return somme
+
+# On recupere des infos sur le fond de fissure
+def getFondFissInfo(fondfiss):
+   # >FONFISS .FOND      .NOEU        <
+   # >FONFISS .FOND      .TYPE        < 
+   import aster
+   l_noeuds_fissure = aster.getvectjev(fondfiss.nom.ljust(8)+'.FOND      .NOEU        ')
+   type_mailles = aster.getvectjev(fondfiss.nom.ljust(8)+'.FOND      .TYPE        ')
+   if (type_mailles[0].strip() == 'SEG3' ):
+      pas = 2
+   else:
+      pas = 1
+   return l_noeuds_fissure, pas
+
+########################################################################
+# determination de la distance min entre 2 points consécutifs de la ligne de coupe
+
+def largeur_tranche(nom_maillage, l_noms_noeuds_fissure, pas, i_tranche):
+   # >MA      .COORDO    .VALE        <
+   from math import sqrt
+   import aster
+   
+   # tuple des noms des noeuds du maillage
+   t_noms_noeuds_maillage = aster.getvectjev(nom_maillage.ljust(8)+'.NOMNOE')
+   # on convertit en liste pour utiliser la methode index
+   # qui est plus optimal qu'une boucle sur les indices du tuple
+   l_noms_noeuds_maillage = list(t_noms_noeuds_maillage)
+   
+   l_numeros_noeuds_fissure = []
+   for i in range(0,len(l_noms_noeuds_fissure),pas):
+      nom = l_noms_noeuds_fissure[i]
+      index = l_noms_noeuds_maillage.index(nom)
+      l_numeros_noeuds_fissure.append(index)
+   
+   coor1=aster.getvectjev(nom_maillage.ljust(8)+'.COORDO    .VALE        ',
+                        l_numeros_noeuds_fissure[i_tranche]*3,3)
+   coor2=aster.getvectjev(nom_maillage.ljust(8)+'.COORDO    .VALE        ',
+                        l_numeros_noeuds_fissure[i_tranche+1]*3,3)
+   
+   d=sqrt( (coor1[0]-coor2[0])**2+(coor1[1]-coor2[1])**2+(coor1[2]-coor2[2])**2)
+   return d
+   
+def mergeLineInTable(multiTable, lineTable, nb_noeuds):
+   # on ajoute a la table multiTable les colonnes de lineTable
+   # pour chaque nume_ordre autant de fois qu'il y a de nb_noeuds
+   from Utilitai.Table      import Table, merge
+   
+   l_ordre = lineTable.NUME_ORDRE
+   l_para = lineTable.copy().para
+   l_para.remove('NUME_ORDRE')
+   for i, ordre in enumerate(l_ordre):
+      multiTable_i = multiTable.NUME_ORDRE==ordre
+      row_i = lineTable.rows[i]
+      for para in l_para:
+         valeur_i = row_i[para]
+         multiTable_i[para] = [valeur_i] * nb_noeuds
+      if i==0:
+         newTable=multiTable_i
+      else:
+         newTable = merge(newTable, multiTable_i)
+         
+   return newTable