Difference between revisions of "Contrib:KeesWouters/Homard/lshape/loop"

From CAELinuxWiki
Jump to: navigation, search
m
m (Remarks on Python language)
 
(77 intermediate revisions by 6 users not shown)
Line 3: Line 3:
 
['''under construction - just started 2010-02-22 ... ''']
 
['''under construction - just started 2010-02-22 ... ''']
  
This contribution is based on the mesh refinement described [http://www.caelinux.org/wiki/index.php/Contrib:KeesWouters/Homard/lshape here]
+
This contribution is based on the mesh refinement described [http://www.caelinux.org/wiki/index.php/Contrib:KeesWouters/Homard/lshape here]. Two mesh refinements based on three calculations are given there. Since the three calculations are basically the same, it is convenient to use the Python looping facility. So now we will perform four calculations and three mesh refinements. The iteration is controlled by the a Python for loop.
  
 
=='''The geometry'''==
 
=='''The geometry'''==
 
==='''The geometry and the mesh of the construction'''===
 
==='''The geometry and the mesh of the construction'''===
 
The mesh refinement is based on [http://www.code-aster.org/outils/homard Homard].
 
The mesh refinement is based on [http://www.code-aster.org/outils/homard Homard].
As usual the geometry is quite simple in order not to disturb the issue we would like to show with other difficulties. We try to refine the mesh of an L shape with a few holes in it. The thickness of the two 'legs' are 0.8 mm and 1.2 mm. The diameters of the holes vary between 0.9 and 1.0 mm. Overall dimensions of the shape are 5 * 6 * 7 mm3.
+
As usual the geometry is quite simple and is defined in the link given above.  
 
+
The geometry is defined in a python script (for download see end of this contribution)  and can be loaded into Salome Geometry module by ''File --> Load script (or ctrl T in the object browser window)''. Right click ''Refresh'' or push ''F5'' after loading if necessary.  
+
  
 
: [[image:kw_lshape.jpg]] <br>
 
: [[image:kw_lshape.jpg]] <br>
  
: overall dimension: [x,y,z] = [5.0, 6.0, 7.0] mm
+
Again, the mesh consists of coarse, tetrehedral elements to start with.
: width of the legs: 1.2 mm vertical and 0.8 mm horizontal
+
: diameters of the circles: in vertical plate: 0.9 mm - in horizontal plate: 0.8 mm
+
: radii of the fillets: innerfillet 0.5 mm - outerfillet 1.2 mm
+
  
The mesh consists of coarse, tetrehedral elements to start with.
+
==='''The load of the construction'''===
 +
The L shape is fixed in all directions at the bottom area Afix. The area at opposite end of L is denoted Apres. For simplicity, on this area a displacement of 0.1 mm is given in the y direction.
  
==='''The load of the construction'''===
+
=='''The refinement process'''==
The L shape is fixed in all directions at the bottom area Afix. On area at opposite end of L is denoted Apres. For simplicity, on this area a displacement of 0.1 mm is given in the y direction.
+
The general idea of the Homard refinement is to start with a rather course mesh and update the mesh according to a criterium. In this case we use the stress error estimate ''ERRE_ELEM_SIGM'' and its component ''ERREST''. For more details on this error estimation see [[http://www.code-aster.org/V2/doc/default/man_u/u7/u7.03.01.pdf U7.03.01.pdf] Homard]. To start a standard load case will be calculated and an error estimation on all the elements will be carried out. In this example a percentage of the elements with the highest error estimates will be refined.
 +
A new calculation with the adapted mesh will then follow. For this calculation all the models, loads and parameters need to be rebuild. So it is most suitable to define geometrical entities ''(GROUP_MA)'' in the mesh in stead of nodes.  
  
=='''The general idea of the refinement'''==
+
Notes:
The general idea of the Homard refinement is to start with a rather course mesh and update the mesh according to a criterium. In this case we use the stress error estimate ''ERRE_ELEM_SIGM'' and its component ''ERREST''. For more details on this error estimation see [....]. So to start with, a standard load case will be calculated and an error estimation on all the elements will be carried out. Again depending on a criterium the mesh will be adapted. In this example a certain percentage of the elements with the highest error estimates will be refined.
+
When using Homard it is:
A new calculation with the adapted mesh can take place. For this calculation all the models, loads and parameters need to be rebuild. So it is most suitable to define geometrical entities ''(GROUP_MA)'' in the mesh in stead of nodes.
+
* quite impractical to use group of nodes (because they will be renumbered or reallocated)
 +
* not possible to use ''poursuite''
  
 
To summarise:  
 
To summarise:  
Line 33: Line 31:
 
* define material properties
 
* define material properties
 
* define number of refinement iterations (whether or not fixed)
 
* define number of refinement iterations (whether or not fixed)
 
+
* for counter in range:
* loop through:
+
**  define model
...define model
+
**  apply material to model
...apply material to model
+
**  apply load to model
...apply load to model
+
**  perform calculation
...perform calculation
+
**  determine element and node parameters
...determine element and node parameters
+
**  (write output data)
...(write output data)
+
**  refinement of mesh MACR_ADAP_MAIL [no need for  refinement in the last iteration]
...refinement of mesh MACR_ADAP_MAIL
+
  
 
The error estimation is determined in the CALC_ELEM command, by the option 'ERRE_ELEM_SIGM':
 
The error estimation is determined in the CALC_ELEM command, by the option 'ERRE_ELEM_SIGM':
Line 48: Line 45:
 
The refinement command itself is as follows:
 
The refinement command itself is as follows:
  
......
+
  ......
refmesh = CO('refmesh')
+
  print mesh
MACR_ADAP_MAIL(MAILLAGE_N=curmesh,
+
  print model
              MAILLAGE_NP1=refmesh,
+
              ADAPTATION='RAFFINEMENT',
+
              RESULTAT_N=result...,
+
              INDICATEUR='ERRE_ELEM_SIGM',
+
              NOM_CMP_INDICA='ERREST',
+
              CRIT_RAFF_PE=0.30,
+
              QUALITE='OUI',
+
              CONNEXITE='OUI',
+
              TAILLE='OUI',);
+
  
The command takes the current mesh ''curmesh'' as input '''MAILLAGE_N=curmesh''' and the output mesh is '''MAILLAGE_NP1=refmesh'''. Since the ''parameter refmesh'' is not yet defined (in the Python sense), we need to apply the operator '''CO('refmesh')''' to define it. [If an unknown parameter is needed in the right hand side of a command, we always need to apply this operator.] Further keywords are the ADAPTATION='RAFFINEMENT' together with CRIT_RAFF_PE=0.30. In this case the 0.30 or 30 % of the elements with the largest error estimate (based on stress error indicator INDICATEUR='ERRE_ELEM_SIGM', NOM_CMP_INDICA='ERREST') are refined. The other elements remain untouched. Note that 30 % refinement of volume elements yields a significant amount of new elements. See table at the ''result'' part.
+
  counterp1 = counter+1;
 +
  meshcp1=CO('mesh_%d' %counterp1)
 +
  MACR_ADAP_MAIL(MAILLAGE_N=mesh[counter],
 +
              MAILLAGE_NP1=meshcp1,
 +
              ADAPTATION='RAFFINEMENT',
 +
              RESULTAT_N=result[counter],
 +
              INDICATEUR='ERRE_ELEM_SIGM',
 +
              NOM_CMP_INDICA='ERREST',
 +
              CRIT_RAFF_PE=0.20,
 +
              QUALITE='OUI',
 +
              CONNEXITE='OUI',
 +
              TAILLE='OUI',
 +
              LANGUE ='ANGLAIS');
 +
  mesh[counter+1] = meshcp1;
  
==='''The detailed command of the refinement'''===
 
In this case we perform two refinements of the mesh, ie. three standard calculations are performed. Each refinement of the mesh is based on a parameter of the previous calculation.
 
  
==='''The standard calculation'''===
+
The command takes the current mesh ''mesh[counter]'' as input '''MAILLAGE_N=curmesh''' and the output mesh is '''MAILLAGE_NP1=meshcp1'''. Again, the meshcp1 is not defined (in the Python sense) so we need to use the CO('..') operator on forehand:
This set of commands is a standard calculation. The only command that should be added for a complete calculation is ''FIN()'':
+
  counterp1 = counter+1;
 +
  meshcp1=CO('mesh_%d' %counterp1)
 +
 
 +
Further keywords are the ADAPTATION='RAFFINEMENT' together with CRIT_RAFF_PE=0.10. In this case the 0.10 or 10 % of the elements with the largest error estimate (based on stress error indicator INDICATEUR='ERRE_ELEM_SIGM', NOM_CMP_INDICA='ERREST') are refined. The other elements remain untouched.
 +
At the end we need to assign the next element of array mesh to the newly defined meshcp1: mesh[counter+1] = meshcp1.
 +
In the last iteration no refinement is required, hence the if statement.
 +
 
 +
Note:
 +
I mainly based this command file on the astest example zzzz121a.comm (see links below). In that case the statement immediately after macro command MACR_ADAP_MAIL mesh[counter+1] = meshcp1 is not included. For my examples it doesnot work without this.
 +
 
 +
 
 +
 
 +
 
 +
==='''The initialisation of the calculation'''===
 +
Here the initialisation commands that can be left out the for loop are described:
  
 
  DEBUT();
 
  DEBUT();
  
  #Read MED mesh file
+
  # initialise counters
  mesh0=LIRE_MAILLAGE(UNITE=20,FORMAT='MED',NOM_MED='mesh0',INFO_MED=2,INFO=1,);
+
  count = [0,1,2,3];
 +
count0 = count[0];
  
  #Assign to the Model
+
  # initialise model parameters
  model0=AFFE_MODELE(MAILLAGE=mesh0,AFFE=_F(TOUT='OUI',
+
  mesh=[None]*4
                    PHENOMENE='MECANIQUE',MODELISATION='3D',),);
+
model=[None]*4
 +
Amat=[None]*4
 +
result=[None]*4
 +
Load=[None]*4
  
 
  #Define material properties
 
  #Define material properties
 
  steel=DEFI_MATERIAU(ELAS=_F(E=2.1e5,NU=.28,),);
 
  steel=DEFI_MATERIAU(ELAS=_F(E=2.1e5,NU=.28,),);
  
  #Assign material to mesh
+
  #Read MED mesh file
  Amat0=AFFE_MATERIAU(MAILLAGE=mesh0,AFFE=_F(TOUT='OUI',MATER=steel,),);
+
  mesh[count0]=LIRE_MAILLAGE(UNITE=20,FORMAT='MED',NOM_MED='mesh0',);
  
  # define boundary conditions and loads
+
 
Load0=AFFE_CHAR_MECA(MODELE=model0,
+
In the array count all the loop numbers 0 to 3 are defined. This is used to control the for loop. The array parameters mesh, model, Amat, result and Load are initialised with maximum size according to the ''count'' array.
 +
Furthermore teh material properties are defined and the initial mesh is read.
 +
 
 +
==='''The for loop construction'''===
 +
 
 +
 
 +
  # start counter
 +
for counter in count:
 +
  model[counter]=AFFE_MODELE(MAILLAGE=mesh[counter],AFFE=_F(TOUT='OUI',
 +
                          PHENOMENE='MECANIQUE',MODELISATION='3D',),);
 +
 
 +
 
 +
  #Assign material to mesh
 +
  Amat[counter]=AFFE_MATERIAU(MAILLAGE=mesh[counter],
 +
                              AFFE=_F(TOUT='OUI',MATER=steel,),);
 +
 
 +
  #define boundary conditions and loads
 +
  Load[counter]=AFFE_CHAR_MECA(MODELE=model[counter],
 
                     DDL_IMPO=(_F(GROUP_MA='Afix',DX=0.0,DY=0.0,DZ=0.0,),
 
                     DDL_IMPO=(_F(GROUP_MA='Afix',DX=0.0,DY=0.0,DZ=0.0,),
 
                               _F(GROUP_MA='Apres',DX=0.0,DY=0.1,DZ=0.0,),),);
 
                               _F(GROUP_MA='Apres',DX=0.0,DY=0.1,DZ=0.0,),),);
  
result0=MECA_STATIQUE(MODELE=model0,CHAM_MATER=Amat0,
+
  result[counter]=MECA_STATIQUE(MODELE=model[counter],
                        EXCIT=_F(CHARGE=Load0,),),);
+
                    CHAM_MATER=Amat[counter],
 
+
                    EXCIT=(_F(CHARGE=Load[counter],),),);
  
result0=CALC_ELEM(reuse =result0,MODELE=model0,RESULTAT=result0,
+
  result[counter]=CALC_ELEM(reuse =result[counter],
                 TOUT='OUI',TYPE_OPTION='TOUTES',
+
                MODELE=model[counter],
 +
                RESULTAT=result[counter],
 +
                 TOUT='OUI',
 +
                TYPE_OPTION='TOUTES',
 
                 OPTION=('EQUI_ELNO_SIGM','SIEF_ELNO_ELGA','ERRE_ELEM_SIGM',),);
 
                 OPTION=('EQUI_ELNO_SIGM','SIEF_ELNO_ELGA','ERRE_ELEM_SIGM',),);
  
result0=CALC_NO(reuse =result0,RESULTAT=result0,OPTION=('EQUI_NOEU_SIGM',),);
+
  result[counter]=CALC_NO(reuse =result[counter],
 +
              RESULTAT=result[counter],
 +
              OPTION=('EQUI_NOEU_SIGM',),);
  
  
IMPR_RESU(FORMAT='MED',UNITE=80,RESU=_F(MAILLAGE=mesh0,RESULTAT=result0,
+
  unitnumber = 80
                  NOM_CHAM=('EQUI_ELNO_SIGM','EQUI_NOEU_SIGM','ERRE_ELEM_SIGM','DEPL',),),);
+
  IMPR_RESU(FORMAT='MED',
 +
          UNITE=unitnumber,
 +
          RESU=_F(MAILLAGE=mesh[counter],RESULTAT=result[counter],NOM_CHAM=('DEPL',),),);
  
==='''The first refinement - on mesh0'''===
 
The mesh0 is refined. The refined mesh is available under the name ''mesh1''. Now exactly the same, standard calculation is being performed. The models, loads and material properties first need to be based on mesh1. So also the assingments for this new mesh need to be carried out. The results are now written to unit 81 in stead of unit 80.
 
  
MACR_ADAP_MAIL(MAILLAGE_N=mesh0,
+
  ##========================##
               MAILLAGE_NP1=CO('mesh1'),
+
  ## define mesh refinement ##
 +
  ##========================##
 +
  if (counter<count[len(count)-1]):
 +
      print count, len(count), count[len(count)-1], counter
 +
      print mesh
 +
      print model
 +
     
 +
      counterp1 = counter+1;
 +
      meshcp1=CO('mesh_%d' %counterp1)
 +
      MACR_ADAP_MAIL(MAILLAGE_N=mesh[counter],
 +
               LANGUE='ENGLISH',
 +
              MAILLAGE_NP1=meshcp1,
 
               ADAPTATION='RAFFINEMENT',
 
               ADAPTATION='RAFFINEMENT',
               RESULTAT_N=result0,
+
               RESULTAT_N=result[counter],
 
               INDICATEUR='ERRE_ELEM_SIGM',
 
               INDICATEUR='ERRE_ELEM_SIGM',
 
               NOM_CMP_INDICA='ERREST',
 
               NOM_CMP_INDICA='ERREST',
               CRIT_RAFF_PE=0.30,
+
               CRIT_RAFF_PE=0.10,
 
               QUALITE='OUI',
 
               QUALITE='OUI',
 
               CONNEXITE='OUI',
 
               CONNEXITE='OUI',
 
               TAILLE='OUI',);
 
               TAILLE='OUI',);
  
model1=AFFE_MODELE(MAILLAGE=mesh1,AFFE=_F(TOUT='OUI',
+
      mesh[counter+1] = meshcp1;
                    PHENOMENE='MECANIQUE',MODELISATION='3D',),);
+
      #endif
 +
  #end for loop
  
  Load1=AFFE_CHAR_MECA(MODELE=model1,
+
And close the calculations:
                    DDL_IMPO=(_F(GROUP_MA='Afix',DX=0.0,DY=0.0,DZ=0.0,),
+
  FIN(FORMAT_HDF='OUI',);
                              _F(GROUP_MA='Apres',DX=0.0,DY=0.1,DZ=0.0,),),);
+
  
  
 +
All the results are now written to a single file on unit 80. In Salome's object browser the results are available after 'file' --> 'import'--> '<resultfile>.med' under mesh_0, mesh_1, mesh_2 and mesh_2. Each mesh contains a ''DEPL'' under ''fields''. By adding the LANGUE='ENGLISH' Homard's output will be in English!  One small portion of text output that will be easier to understand for non-Fr users.
  
#Assign material to mesh
+
===''Remarks on Python language''===
Amat1=AFFE_MATERIAU(MAILLAGE=mesh1,AFFE=_F(TOUT='OUI',MATER=steel,),);
+
First note that 'test_%d',%3 will evaluate to 'test_3' in Python.
 +
Now suppose counter=1, counterp1=2 then meshcp1 evaluates to '' 'mesh_2' = CO('mesh_2')''. The new name 'mesh_2' is defined. This corresponds to mesh[2].
 +
* Note that the name 'mesh_2' has maximum length of 8 characters, due to (Fortran?) filename limitations.
  
result1=MECA_STATIQUE(MODELE=model1,CHAM_MATER=Amat1,
 
                      EXCIT=(_F(CHARGE=Load1,),),);
 
  
result1=CALC_ELEM(reuse =result1,MODELE=model1,RESULTAT=result1,
+
To check this the print commands ''print model'' and ''print mesh'' have been added at the start of this block. The output of these commands are e.g:
                TOUT='OUI',TYPE_OPTION='TOUTES',
+
                OPTION=('EQUI_ELNO_SIGM','SIEF_ELNO_ELGA','ERRE_ELEM_SIGM',),);
+
  
result1=CALC_NO(reuse =result1,RESULTAT=result1,OPTION=('EQUI_NOEU_SIGM',),);
 
  
IMPR_RESU(FORMAT='MED',UNITE=81,
+
''print mesh'',''print model'',.....:<br>
          RESU=_F(MAILLAGE=mesh1,RESULTAT=result1,
+
                  NOM_CHAM=('EQUI_ELNO_SIGM','SIGM_NOEU_DEPL','DEPL','SIEF_ELNO_ELGA','ERRE_ELEM_SIGM',),),);
+
  
==='''The second refinement - on mesh1'''===
+
[<maillage_sdaster(72a5fd0,'mesh_0          ')>, <maillage_sdaster(56ed650,'mesh_1          ')>, None , None]
Same procedure as before but now carried out on mesh1 and the output is the refined mesh2. Of course, the models, loads and material properties need to be based on mesh2 now. The results are now written to unit 82.
+
[<modele_sdaster(72becd0,'model_0            ')>, <modele_sdaster(56ed750,'model_1            ')>, None , None]
 +
[<char_meca(5af3110,'Load_0                  ')>, <char_meca(56fa6d0,'Load_1                  ')>, None , None]
 +
[<cham_mater(5661fd0,'Amat_0                ')>, <cham_mater(56eb290,'Amat_1                ')>, None , None]
 +
[<evol_elas(56e49d0,'result_0                ')>, <evol_elas(56ff690,'result_1                ')>, None , None]<br>
  
MACR_ADAP_MAIL(MAILLAGE_N=mesh1,
+
'''Command control'''<br>
              MAILLAGE_NP1=CO('mesh2'),
+
The Python for loop is controlled by indenting the commands by a fixed number of characters:
              ADAPTATION='RAFFINEMENT',
+
              RESULTAT_N=result1,
+
              INDICATEUR='ERRE_ELEM_SIGM',
+
              NOM_CMP_INDICA='ERREST',
+
              CRIT_RAFF_PE=0.30,
+
              QUALITE='OUI',
+
              CONNEXITE='OUI',
+
              TAILLE='OUI',);
+
  
  model2=AFFE_MODELE(MAILLAGE=mesh2,AFFE=_F(TOUT='OUI',
+
  maxcount = 4;
                          PHENOMENE='MECANIQUE',MODELISATION='3D',),);
+
  for counter in range(0,maxcount):
   
+
    do_something();
Load2=AFFE_CHAR_MECA(MODELE=model2,
+
    if (counter<maxcount-1):
                    DDL_IMPO=(_F(GROUP_MA='Afix',DX=0.0,DY=0.0,DZ=0.0,),
+
      refine();
                              _F(GROUP_MA='Apres',DX=0.0,DY=0.1,DZ=0.0,),),);
+
    else:
 +
      donotrefine_or_donothing();
 +
    #endif
 +
#endfor
  
  #Assign material to mesh
+
The range command yields:
  Amat2=AFFE_MATERIAU(MAILLAGE=mesh2,AFFE=_F(TOUT='OUI',MATER=steel,),);
+
  maxcount=4;
 +
  xx = range(0,maxcount);xx
 +
--> xx=[0,1,2,3]
  
result2=MECA_STATIQUE(MODELE=model2,CHAM_MATER=Amat2,
+
=='''The results of the refinement'''==
                    EXCIT=(_F(CHARGE=Load2,),),);
+
===''Some numerical results''===
 +
The numbers of nodes and quadratic elements (tetrahedrons) of the meshes:
  
  result2=CALC_ELEM(reuse =result2,MODELE=model2,RESULTAT=result2,
+
                        10%          90%        new    change
                TOUT='OUI',TYPE_OPTION='TOUTES',
+
  nodes elements    changed unchanged  elements factor
                OPTION=('EQUI_ELNO_SIGM','SIEF_ELNO_ELGA','ERRE_ELEM_SIGM',),);
+
4224     2064 206     1858
 +
8796     4958 496     4462 3100 15 (= 3100/ 206)
 +
20043   12029 1203     10826 7567 15 (= 7567/ 496)
 +
45066   28347 2835     25512      17521 15 (=17521/1203)
  
result2=CALC_NO(reuse =result2,RESULTAT=result2,OPTION=('EQUI_NOEU_SIGM',),);
+
So, from a single tetrahedron that is refined, 15 tetrahedrons are generated for this mesh.
  
IMPR_RESU(FORMAT='MED',UNITE=82,
+
In an extended calculation, where the number of refinements are increased to five, the following information is reported in the mess file:
          RESU=_F(MAILLAGE=mesh2,RESULTAT=result2,
+
                  NOM_CHAM=('EQUI_ELNO_SIGM','SIGM_NOEU_DEPL','DEPL','SIEF_ELNO_ELGA','ERRE_ELEM_SIGM',),),);
+
  
  FIN(FORMAT_HDF='OUI',);
+
                  elements    niveau-----------------------------------level
 +
          nodes    total          0      1      2      3        4      5
 +
  mesh_0    4224      2064      2064      -      -      -        -      -
 +
mesh_1    8796      4958      1290    3668      -      -        -      -
 +
mesh_2    20043    12029        496    8757  2776      -        -      -
 +
mesh_3    45066    28347        69  11727  12259    4292        -      -
 +
mesh_4  112313    72762        21    6940  50452    8241    7108      -
 +
mesh_5  272204    180412          0    2132  93176  55159    14843  15066
  
==='''The results of the refinement'''===
+
Hence after 6 iterations, all the elements have been refined, number of level 0 elements is 0.
The numbers of nodes and quadratic elements (tetrahedrons) of the meshes:
+
 
+
                      30%          70%    30%-->new  factor   
+
nodes  elements changed    unchanged    elements  change 
+
  4224      2064      620        1444
+
16346      9636    2890        6746        8192    13 (=8192 / 620)
+
65845    42537    12760        29777      35791    12 (=35791/2890)
+
 
+
So, from a single tetrahedron that is refined, 12 to 13 tetrahedrons are generated for this mesh.
+
  
 +
===''Some graphical results''===
 
In the graph below, the original mesh (top left) and the two successive refinements based on the discussed criteria are depicted (bottom right last iteration).
 
In the graph below, the original mesh (top left) and the two successive refinements based on the discussed criteria are depicted (bottom right last iteration).
  
 
: [[image:kw_refinement_4.jpg]] <br>
 
: [[image:kw_refinement_4.jpg]] <br>
  
The picture below shows the stress error estimation 'ERREST'. The first refinement is based on this field: mesh0 --> mesh1.
+
The picture below shows the stress error estimation 'ERREST'. The first refinement from mesh0 to mesh1 is based on this ERREST field.
 
+
: [[image:kw_errorest3.jpg]] <br>
+
 
+
The error estimation field 'ERROR-ELEM_SIGMA' containes 10 components:
+
ERREST, NUEST,
+
SIGCAL,
+
TERMRE,TERMR2,TERMRENO,TERMN2,TERMSA,TERMS2,
+
TAILLE.
+
+
Any of these components can be used in the component indicator, eg. NOM_CMP_INDICA='ERREST'
+
  
 
=='''The ASTK input files'''==
 
=='''The ASTK input files'''==
 
The picture below shows the input and output files defined in ASTK.
 
The picture below shows the input and output files defined in ASTK.
  
: [[image:kw_astk_meshrefine.png]] <br>
+
: [[image:kw_astk_loop4.png]] <br>
  
 
=='''Download files'''==
 
=='''Download files'''==
  
: [[Media:kw_mesh_refinement012.zip]]<br/>
+
: [[Media:kw_meshrefine_loop.zip]]<br/>
 
This zip contains the following files
 
This zip contains the following files
 
* python geometry and mesh files (load in Salome by ''File --> Load script'' (cntrl T)) and right select ''refresh'' (F5) in the object browser). Export the med file in the mesh module under ''mesh0.med'' for further processing by Code-Aster, controlled by ASTK.
 
* python geometry and mesh files (load in Salome by ''File --> Load script'' (cntrl T)) and right select ''refresh'' (F5) in the object browser). Export the med file in the mesh module under ''mesh0.med'' for further processing by Code-Aster, controlled by ASTK.
Line 222: Line 259:
 
* export file, generated by ASTK.
 
* export file, generated by ASTK.
  
The result files ''resi0.med'', ''resi1.med'' and ''resi2.med'', can be viewed in the post processor module of Salome by ''File --> Import --> resix.med'' or cntrl I in the object browser.
+
The result file ''resx0.med'' can be viewed in the post processor module of Salome by ''File --> Import --> resix.med'' or cntrl I in the object browser. Importing it into the mesh module can be useful to check e.g. the number of elements. All the results of the meshes are stored in separate fields ''mesh_0, mesh_1, mesh_2 and mesh_3''.
 
+
  
 
=='''Links'''==
 
=='''Links'''==
Line 229: Line 265:
 
pdf file: http://www.code-aster.org/V2/doc/default/man_u/u7/u7.03.01.pdf<br>
 
pdf file: http://www.code-aster.org/V2/doc/default/man_u/u7/u7.03.01.pdf<br>
 
Homard website: http://www.code-aster.org/outils/homard
 
Homard website: http://www.code-aster.org/outils/homard
 +
 +
*It seems I have to update all pdf links; for now check u7.03.01.pdf by hand on the Code Aster site.
 +
 +
Not really links, but nice to study are the examples<br>
 +
* zzzz121a.comm,
 +
* zzzz121b.comm,
 +
* zzzz121c.comm,
 +
* zzzz121d.comm and
 +
* zzzz121e.comm.
 +
in the astest directory [$ASTER_ROOT]/STA[$VERSION]/astest/.....,<br>
 +
e.g in my case: /cae/aster101/STA10.1/astest/zzzz121a.comm
  
 
That's it for now.<br>
 
That's it for now.<br>
 
Kees
 
Kees

Latest revision as of 19:43, 7 January 2018

Mesh refinement using Python loop facility

[under construction - just started 2010-02-22 ... ]

This contribution is based on the mesh refinement described here. Two mesh refinements based on three calculations are given there. Since the three calculations are basically the same, it is convenient to use the Python looping facility. So now we will perform four calculations and three mesh refinements. The iteration is controlled by the a Python for loop.

The geometry

The geometry and the mesh of the construction

The mesh refinement is based on Homard. As usual the geometry is quite simple and is defined in the link given above.

Kw lshape.jpg

Again, the mesh consists of coarse, tetrehedral elements to start with.

The load of the construction

The L shape is fixed in all directions at the bottom area Afix. The area at opposite end of L is denoted Apres. For simplicity, on this area a displacement of 0.1 mm is given in the y direction.

The refinement process

The general idea of the Homard refinement is to start with a rather course mesh and update the mesh according to a criterium. In this case we use the stress error estimate ERRE_ELEM_SIGM and its component ERREST. For more details on this error estimation see [U7.03.01.pdf Homard]. To start a standard load case will be calculated and an error estimation on all the elements will be carried out. In this example a percentage of the elements with the highest error estimates will be refined. A new calculation with the adapted mesh will then follow. For this calculation all the models, loads and parameters need to be rebuild. So it is most suitable to define geometrical entities (GROUP_MA) in the mesh in stead of nodes.

Notes: When using Homard it is:

  • quite impractical to use group of nodes (because they will be renumbered or reallocated)
  • not possible to use poursuite

To summarise:

  • initial some parameters
  • read initial mesh
  • define material properties
  • define number of refinement iterations (whether or not fixed)
  • for counter in range:
    • define model
    • apply material to model
    • apply load to model
    • perform calculation
    • determine element and node parameters
    • (write output data)
    • refinement of mesh MACR_ADAP_MAIL [no need for refinement in the last iteration]

The error estimation is determined in the CALC_ELEM command, by the option 'ERRE_ELEM_SIGM':

result...=CALC_ELEM(....,OPTION=(....,'ERRE_ELEM_SIGM',),);

The refinement command itself is as follows:

  ......
  print mesh
  print model
  counterp1 = counter+1;
  meshcp1=CO('mesh_%d' %counterp1)
  MACR_ADAP_MAIL(MAILLAGE_N=mesh[counter],
              MAILLAGE_NP1=meshcp1,
              ADAPTATION='RAFFINEMENT',
              RESULTAT_N=result[counter],
              INDICATEUR='ERRE_ELEM_SIGM',
              NOM_CMP_INDICA='ERREST',
              CRIT_RAFF_PE=0.20,
              QUALITE='OUI',
              CONNEXITE='OUI',
              TAILLE='OUI',
              LANGUE ='ANGLAIS');
  mesh[counter+1] = meshcp1;


The command takes the current mesh mesh[counter] as input MAILLAGE_N=curmesh and the output mesh is MAILLAGE_NP1=meshcp1. Again, the meshcp1 is not defined (in the Python sense) so we need to use the CO('..') operator on forehand:

  counterp1 = counter+1;
  meshcp1=CO('mesh_%d' %counterp1)

Further keywords are the ADAPTATION='RAFFINEMENT' together with CRIT_RAFF_PE=0.10. In this case the 0.10 or 10 % of the elements with the largest error estimate (based on stress error indicator INDICATEUR='ERRE_ELEM_SIGM', NOM_CMP_INDICA='ERREST') are refined. The other elements remain untouched. At the end we need to assign the next element of array mesh to the newly defined meshcp1: mesh[counter+1] = meshcp1. In the last iteration no refinement is required, hence the if statement.

Note: I mainly based this command file on the astest example zzzz121a.comm (see links below). In that case the statement immediately after macro command MACR_ADAP_MAIL mesh[counter+1] = meshcp1 is not included. For my examples it doesnot work without this.



The initialisation of the calculation

Here the initialisation commands that can be left out the for loop are described:

DEBUT();
# initialise counters
count = [0,1,2,3];
count0 = count[0];
# initialise model parameters
mesh=[None]*4
model=[None]*4
Amat=[None]*4
result=[None]*4
Load=[None]*4
#Define material properties
steel=DEFI_MATERIAU(ELAS=_F(E=2.1e5,NU=.28,),);
#Read MED mesh file
mesh[count0]=LIRE_MAILLAGE(UNITE=20,FORMAT='MED',NOM_MED='mesh0',);


In the array count all the loop numbers 0 to 3 are defined. This is used to control the for loop. The array parameters mesh, model, Amat, result and Load are initialised with maximum size according to the count array. Furthermore teh material properties are defined and the initial mesh is read.

The for loop construction

# start counter
for counter in count:
  model[counter]=AFFE_MODELE(MAILLAGE=mesh[counter],AFFE=_F(TOUT='OUI',
                         PHENOMENE='MECANIQUE',MODELISATION='3D',),);


  #Assign material to mesh
  Amat[counter]=AFFE_MATERIAU(MAILLAGE=mesh[counter],
                              AFFE=_F(TOUT='OUI',MATER=steel,),);
  #define boundary conditions and loads
  Load[counter]=AFFE_CHAR_MECA(MODELE=model[counter],
                    DDL_IMPO=(_F(GROUP_MA='Afix',DX=0.0,DY=0.0,DZ=0.0,),
                              _F(GROUP_MA='Apres',DX=0.0,DY=0.1,DZ=0.0,),),);
  result[counter]=MECA_STATIQUE(MODELE=model[counter],
                    CHAM_MATER=Amat[counter],
                    EXCIT=(_F(CHARGE=Load[counter],),),);
  result[counter]=CALC_ELEM(reuse =result[counter],
                MODELE=model[counter],
                RESULTAT=result[counter],
                TOUT='OUI',
                TYPE_OPTION='TOUTES',
                OPTION=('EQUI_ELNO_SIGM','SIEF_ELNO_ELGA','ERRE_ELEM_SIGM',),);
  result[counter]=CALC_NO(reuse =result[counter],
              RESULTAT=result[counter],
              OPTION=('EQUI_NOEU_SIGM',),);


  unitnumber = 80
  IMPR_RESU(FORMAT='MED',
         UNITE=unitnumber,
         RESU=_F(MAILLAGE=mesh[counter],RESULTAT=result[counter],NOM_CHAM=('DEPL',),),);


  ##========================##
  ## define mesh refinement ##
  ##========================##
  if (counter<count[len(count)-1]):
     print count, len(count), count[len(count)-1], counter
     print mesh
     print model
     
     counterp1 = counter+1;
     meshcp1=CO('mesh_%d' %counterp1)
     MACR_ADAP_MAIL(MAILLAGE_N=mesh[counter],
              LANGUE='ENGLISH',
              MAILLAGE_NP1=meshcp1,
              ADAPTATION='RAFFINEMENT',
              RESULTAT_N=result[counter],
              INDICATEUR='ERRE_ELEM_SIGM',
              NOM_CMP_INDICA='ERREST',
              CRIT_RAFF_PE=0.10,
              QUALITE='OUI',
              CONNEXITE='OUI',
              TAILLE='OUI',);
     mesh[counter+1] = meshcp1;
     #endif
  #end for loop

And close the calculations:

FIN(FORMAT_HDF='OUI',);


All the results are now written to a single file on unit 80. In Salome's object browser the results are available after 'file' --> 'import'--> '<resultfile>.med' under mesh_0, mesh_1, mesh_2 and mesh_2. Each mesh contains a DEPL under fields. By adding the LANGUE='ENGLISH' Homard's output will be in English! One small portion of text output that will be easier to understand for non-Fr users.

Remarks on Python language

First note that 'test_%d',%3 will evaluate to 'test_3' in Python. Now suppose counter=1, counterp1=2 then meshcp1 evaluates to 'mesh_2' = CO('mesh_2'). The new name 'mesh_2' is defined. This corresponds to mesh[2].

  • Note that the name 'mesh_2' has maximum length of 8 characters, due to (Fortran?) filename limitations.


To check this the print commands print model and print mesh have been added at the start of this block. The output of these commands are e.g:


print mesh,print model,.....:

[<maillage_sdaster(72a5fd0,'mesh_0           ')>, <maillage_sdaster(56ed650,'mesh_1           ')>, None , None]
[<modele_sdaster(72becd0,'model_0            ')>, <modele_sdaster(56ed750,'model_1            ')>, None , None]
[<char_meca(5af3110,'Load_0                  ')>, <char_meca(56fa6d0,'Load_1                  ')>, None , None]
[<cham_mater(5661fd0,'Amat_0                 ')>, <cham_mater(56eb290,'Amat_1                 ')>, None , None]
[<evol_elas(56e49d0,'result_0                ')>, <evol_elas(56ff690,'result_1                ')>, None , None]

Command control
The Python for loop is controlled by indenting the commands by a fixed number of characters:

maxcount = 4;
for counter in range(0,maxcount):
   do_something();
   if (counter<maxcount-1):
      refine();
   else:
      donotrefine_or_donothing();
   #endif
#endfor

The range command yields:

maxcount=4;
xx = range(0,maxcount);xx

--> xx=[0,1,2,3]

The results of the refinement

Some numerical results

The numbers of nodes and quadratic elements (tetrahedrons) of the meshes:

                        10%          90%        new    change
nodes	elements     changed	unchanged   elements	factor
4224	    2064	 206	     1858		
8796	    4958	 496	     4462	3100	15 (= 3100/ 206)
20043	   12029	1203	    10826	7567	15 (= 7567/ 496)
45066	   28347	2835	    25512      17521	15 (=17521/1203)

So, from a single tetrahedron that is refined, 15 tetrahedrons are generated for this mesh.

In an extended calculation, where the number of refinements are increased to five, the following information is reported in the mess file:

                 elements     niveau-----------------------------------level
          nodes     total          0       1      2       3        4       5
mesh_0     4224      2064       2064       -      -       -        -       -
mesh_1     8796      4958       1290    3668      -       -        -       -
mesh_2    20043     12029        496    8757   2776       -        -       -
mesh_3    45066     28347         69   11727  12259    4292        -       -
mesh_4   112313     72762         21    6940  50452    8241     7108       -
mesh_5   272204    180412          0    2132  93176   55159    14843   15066

Hence after 6 iterations, all the elements have been refined, number of level 0 elements is 0.

Some graphical results

In the graph below, the original mesh (top left) and the two successive refinements based on the discussed criteria are depicted (bottom right last iteration).

Kw refinement 4.jpg

The picture below shows the stress error estimation 'ERREST'. The first refinement from mesh0 to mesh1 is based on this ERREST field.

The ASTK input files

The picture below shows the input and output files defined in ASTK.

Kw astk loop4.png

Download files

Media:kw_meshrefine_loop.zip

This zip contains the following files

  • python geometry and mesh files (load in Salome by File --> Load script (cntrl T)) and right select refresh (F5) in the object browser). Export the med file in the mesh module under mesh0.med for further processing by Code-Aster, controlled by ASTK.
  • command files for Code-Aster
  • astk file for file control by ASTK
  • export file, generated by ASTK.

The result file resx0.med can be viewed in the post processor module of Salome by File --> Import --> resix.med or cntrl I in the object browser. Importing it into the mesh module can be useful to check e.g. the number of elements. All the results of the meshes are stored in separate fields mesh_0, mesh_1, mesh_2 and mesh_3.

Links

More information about the mesh refinement by Homard can be find here:
pdf file: http://www.code-aster.org/V2/doc/default/man_u/u7/u7.03.01.pdf
Homard website: http://www.code-aster.org/outils/homard

  • It seems I have to update all pdf links; for now check u7.03.01.pdf by hand on the Code Aster site.

Not really links, but nice to study are the examples

  • zzzz121a.comm,
  • zzzz121b.comm,
  • zzzz121c.comm,
  • zzzz121d.comm and
  • zzzz121e.comm.

in the astest directory [$ASTER_ROOT]/STA[$VERSION]/astest/.....,
e.g in my case: /cae/aster101/STA10.1/astest/zzzz121a.comm

That's it for now.
Kees