.. Code Integration and Code Coupling documentation master file, created by sphinx-quickstart on Tue Apr 28 14:31:38 2009.
You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
+ contain the root ``toctree`` directive.
MEDCoupling/MEDLoader Tutorial
==============================
-MEDCoupling is a powerful library to manipulate meshes and fields.
+MEDCoupling is a powerful library to manipulate meshes and fields.
This tutorial presents the most wanted functionalities of the MEDCoupling/MEDLoader
-library through a series of small exercises in Python.
+library through a series of small exercises in Python.
Both the French and English versions are provided, but the French version
-is better maintained ...
+is better maintained ...
(Jump to the English version below :ref:`english-toc`)
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
-
Manipuler les DataArray
-----------------------
-Les DataArrays (``DataArrayInt`` et ``DataArrayDouble``) sont utilisés dans MEDCoupling pour stocker des valeurs sous
+Les DataArrays (``DataArrayInt`` et ``DataArrayDouble``) sont utilisés dans MEDCoupling pour stocker des valeurs sous
forme de tableaux contigus en mémoire. Les valeurs sont groupées par tuples, et chaque tuple a le même nombre de composantes.
Ils sont à la base de beaucoup de traitements réalisés dans MEDCoupling. Il est ainsi important de bien savoir les manipuler.
Les ``DataArrayDouble`` sont souvent utilisés pour la manipulation directe des valeurs d'un champ comme on le verra plus tard.
-Les ``DataArrayInt`` eux sont utilisés pour toutes les fonctionnalités travaillant avec des identifiants de
+Les ``DataArrayInt`` eux sont utilisés pour toutes les fonctionnalités travaillant avec des identifiants de
cellules et/ou de points.
Le but de l'exercice
import medcoupling as mc
import math
-On rappelle que toutes les méthodes statiques du module commencent par une majuscule.
+On rappelle que toutes les méthodes statiques du module commencent par une majuscule.
Avec ces imports sont disponibles :
* toutes les classes de MEDCoupling
d = mc.DataArrayDouble(12)
d.rearrange(2)
-Notons enfin que l'on peut aussi directement construire un ``DataArray`` à partir d'une liste Python. Par défaut le tableau
+Notons enfin que l'on peut aussi directement construire un ``DataArray`` à partir d'une liste Python. Par défaut le tableau
n'a qu'une seule composante. ::
d_example = mc.DataArrayDouble([0.0,1.0,2.5])
ds[pos] = d[:] # Perform a deep copy of d and place it at position 'pos' in ds
ds[pos] += t # Adding a vector to a set of coordinates does a translation. t could have been a DataArrayDouble too.
pass
-
+
.. note:: Le ``pass`` à la fin de la boucle ``for`` n'est pas indispensable mais aide certains éditeurs à indenter le code.
Une autre façon de faire un peu plus compacte (pour les amoureux des *one-liner*) : ::
On a ainsi récupéré dans ``c`` l'ensemble des m=12 groupes de noeuds communs accollés. ``cI`` contient les index pour repérer les identifiants de points dans ``c`` pour tout groupe
``i`` dans [0,12). Ainsi les identifiants de tuples du groupe ``i`` commencent à l'index ``cI[i]`` et finissent à l'index ``cI[i+1]``.
-La méthode ``findCommonTuples()`` retourne ainsi 2 paramètres: un tableau contenant la liste des tuples communs
-et un tableau d'index qui permet de naviguer dans le premier tableau.
-Il s'agit d'une forme de retour très classique dans MEDCoupling, appelée *indirect indexing*. Cela apparaît souvent dans la manipulation des
-maillages non structurés. Cette représentation est rappelée sur l'image ci-dessous, où le premier tableau est en haut,
+La méthode ``findCommonTuples()`` retourne ainsi 2 paramètres: un tableau contenant la liste des tuples communs
+et un tableau d'index qui permet de naviguer dans le premier tableau.
+Il s'agit d'une forme de retour très classique dans MEDCoupling, appelée *indirect indexing*. Cela apparaît souvent dans la manipulation des
+maillages non structurés. Cette représentation est rappelée sur l'image ci-dessous, où le premier tableau est en haut,
et le deuxième tableau permettant de la parcourir en bas:
.. image:: images/IndirectIndex.jpg
:scale: 50
-.. note:: Le dernier élément de ``cI`` pointe en dehors du tableau ``c``. Ce dernier index est toujours présent
+.. note:: Le dernier élément de ``cI`` pointe en dehors du tableau ``c``. Ce dernier index est toujours présent
et permet de s'assurer que des traitements tels que les *slices* présentés juste après, sont toujours valables,
- sans avoir besoin de particulariser le dernier groupe.
+ sans avoir besoin de particulariser le dernier groupe.
.. _indirect-index-exo:
ces 3 répétitions.
Maintenant on va déduire des variables ``oldNbOfTuples``, ``c`` et ``cI`` le nombre de tuples effectivement différents dans d2.
-Pour ce faire, nous allons trouver le nombre de tuples doublons dans ``d2`` et soustraire le résultat de ``oldNbOfTuples``.
+Pour ce faire, nous allons trouver le nombre de tuples doublons dans ``d2`` et soustraire le résultat de ``oldNbOfTuples``.
Pour connaître le nombre de doublons, invoquer ``DataArrayInt.deltaShiftIndex`` qui retourne pour chaque groupe sa taille.
Mettre le résultat dans ``a``. ::
Nous allons maintenant exploiter cette information pour extraire un seul
représentant dans chaque groupe de points dupliqués.
-Les deux tableaux ``c`` et ``cI`` définissent une surjection d'un espace de départ à 42 (``oldNbOfTuples``) tuples X
-vers un espace à 24 (``myNewNbOfTuples``) tuples Y.
+Les deux tableaux ``c`` et ``cI`` définissent une surjection d'un espace de départ à 42 (``oldNbOfTuples``) tuples X
+vers un espace à 24 (``myNewNbOfTuples``) tuples Y.
.. image:: images/SurjectionDataArray.png
L'autre manière de définir cette surjection (sans perte d'information) est de la représenter par un tableau "old-2-new".
-Ce mode de stockage prend la forme d'un DataArrayInt ``o2n`` composé de Card(X) tuples (i.e. 42) à une composante.
+Ce mode de stockage prend la forme d'un DataArrayInt ``o2n`` composé de Card(X) tuples (i.e. 42) à une composante.
Pour chaque tuple (élément) d'index ``i`` de ``o2n``, la case ``o2n[i]`` contient le nouvel identifiant de tuple dans Y.
On va donc d'un ancien identifiant (old) vers un nouveau (new).
-Nous allons construire ce tableau pour extraire un sous-ensemble des coordonnées de départ, et ne garder que les
+Nous allons construire ce tableau pour extraire un sous-ensemble des coordonnées de départ, et ne garder que les
tuples uniques (non doublons) dans l'ensemble de départ.
-.. note:: Pour toutes les opérations de renumérotation en MEDCoupling (bijection),
+.. note:: Pour toutes les opérations de renumérotation en MEDCoupling (bijection),
le format "old-2-new" est systématiquement utilisé.
-La méthode statique ``DataArrayInt.ConvertIndexArrayToO2N()`` (nom un peu barbare, on vous l'accorde)
+La méthode statique ``DataArrayInt.ConvertIndexArrayToO2N()`` (nom un peu barbare, on vous l'accorde)
permet de passer du mode de stockage de cette surjection ``c``, ``cI`` au format ``o2n``.
On récupère au passage card(Y) c'est-à-dire le ``newNbOfTuples``. ::
print("myNewNbOfTuples = %d, newNbOfTuples = %d" % (myNewNbOfTuples, newNbOfTuples))
assert(myNewNbOfTuples == newNbOfTuples)
-Nous pouvons maintenant constuire le tableau de points uniques ``d3``. A l'aide de ``o2n``
+Nous pouvons maintenant constuire le tableau de points uniques ``d3``. A l'aide de ``o2n``
et ``newNbOfTuples``, invoquer ``DataArrayDouble.renumberAndReduce()`` sur ``d2``. ::
d3 = d2.renumberAndReduce(o2n, newNbOfTuples)
-L'inconvénient de cette méthode c'est que finalement on ne connait pas pour chaque groupe de tuple communs dans
+L'inconvénient de cette méthode c'est que finalement on ne connait pas pour chaque groupe de tuple communs dans
d2 quel identifiant a été utilisé.
-Par exemple pour le groupe 0 on sait que les tuples 0, 8 et 16 (tmp.getValues()) sont tous égaux, et on ne sait
+Par exemple pour le groupe 0 on sait que les tuples 0, 8 et 16 (tmp.getValues()) sont tous égaux, et on ne sait
pas si 0, 8 ou 16 a été utilisé pour remplir ``d3``.
-Si l'on souhaite expliciter ce choix, on peut passer en format "new-2-old". Ce mode de stockage prend la forme d'un
+Si l'on souhaite expliciter ce choix, on peut passer en format "new-2-old". Ce mode de stockage prend la forme d'un
``DataArrayInt`` ``n2o`` composé de Card(Y)
tuples (24) à 1 composante. Pour chaque tuple (élément) d'index i de ``n2o``, la case ``n2o[i]`` contient l'index du tuple qui a été choisi dans X.
-Pour passer d'une description "old-2-new" vers "new-2-old", la méthode est ``DataArrayInt.invertArrayO2N2N2O()``.
+Pour passer d'une description "old-2-new" vers "new-2-old", la méthode est ``DataArrayInt.invertArrayO2N2N2O()``.
Effectuer ce traitement sur la variable ``o2n``. ::
n2o = o2n.invertArrayO2N2N2O(newNbOfTuples)
On chercher maintenant à créer le maillage final montré dans la figure. Nous avons déjà construit le tableau
de coordonnées, il nous reste les cellules à créer.
-Créer un maillage non structuré ``m`` avec les coordonnées ``d3``. Le maillage``m`` a une mesh-dimension 2 ::
+Créer un maillage non structuré ``m`` avec les coordonnées ``d3``. Le maillage ``m`` a une mesh-dimension 2 ::
m = mc.MEDCouplingUMesh("My7hexagons",2)
m.setCoords(d3)
m.allocateCells(7)
-Enfin grâce à ``o2n`` on a la *connectivité* (i.e. la liste des points formant un hexagone)
+Enfin grâce à ``o2n`` on a la *connectivité* (i.e. la liste des points formant un hexagone)
des 7 hexagones utilisant les coordonnées ``d3``. ::
for i in range(7):
m.checkConsistencyLight()
.. note:: Il est toujours une bonne idée d'appeler cette méthode après la construction "from scratch" d'un maillage.
- Cela assure qu'il n'y a pas de gros "couacs" dans la connectivité, etc ...
+ Cela assure qu'il n'y a pas de gros "couacs" dans la connectivité, etc ...
Pour vérifier *visuellment* que ``m`` est correct, l'écrire dans un fichier "My7hexagons.vtu" et le visualiser dans ParaViS. ::
Full example 2 - RJH
--------------------
-Two MED files are used in this case, which are (very freely) inspired by the RJH experimental reactor.
+Two MED files are used in this case, which are (very freely) inspired by the RJH experimental reactor.
The first file "Fixe.med" represents the 2D geometry of the static RJH without the installations.
Implementation start
~~~~~~~~~~~~~~~~~~~~
-To implement this exercise we use the Python scripting language and import the `medcoupling` Python module. ::
+To implement this exercise we use the Python scripting language and import the ``medcoupling`` Python module. ::
import medcoupling as mc
Read and repare the static mesh "Fixe.med"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-With the advanced API read the whole file "Fixe.med" and call "fixm" the MEDCouplingUMEsh instance
+With the advanced API read the whole file "Fixe.med" and call "fixm" the MEDCouplingUMEsh instance
representing the static mesh. ::
fixe = mc.MEDFileMesh.New("Fixe.med")
Repair the "mobm" mesh converting from POLYGON to QPOLYG (temporary solution)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-This section will disappear in the future.
-The RJH mesh being more generic than TRI6 and QUAD8 we need to store cells with an intermediate type QPOLYG
+This section will disappear in the future.
+The RJH mesh being more generic than TRI6 and QUAD8 we need to store cells with an intermediate type QPOLYG
(Quadratic Polygon) which is the polygonal extension to the 2D cells with a dynamic edge count.
For now this geometrical type QPOLYG is in MEDCoupling but there is no equivalent yet in MED file (work in progress
at EDF).
mobm.getNodalConnectivity()[mobm.getNodalConnectivityIndex()[ids]]=NORM_QPOLYG
mobm.computeTypes()
-Visualize "fixm" and "mobm" using ParaView. Tesselation is needed: OpenGL doesn't handle properly circle arcs
+Visualize "fixm" and "mobm" using ParaView. Tesselation is needed: OpenGL doesn't handle properly circle arcs
and those have to be split into smaller linear segments to be able to represent them. The method MEDCouplingUMesh.tessellate2D() achieves this but modifies the mesh (non const method in C++).
-It only take a cut fineness parameter (0.1 will suffice (angle expressed in rd)). Remember not to modify
+It only take a cut fineness parameter (0.1 will suffice (angle expressed in rd)). Remember not to modify
neither "fixm" nor "mobm"! ::
fixm2 = fixm.deepCopy() # tessellate2D is non const - a mesh copy is required
Perform reductions and identifying zones
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"mobm" is made of 6 distinct parts (see image above). We only want the first part.
-Use MEDCouplingUMesh.partitionBySpreadZone() to partition "mobm" in zones and only
+"mobm" is made of 6 distinct parts (see image above). We only want the first part.
+Use MEDCouplingUMesh.partitionBySpreadZone() to partition "mobm" in zones and only
extract the first zone.
Name this new instance "zone1Mobm", remove all orphan nodes and display. ::
Geometrical intersection of the two meshes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-This is the core of the exercise.
+This is the core of the exercise.
-We intersect geometrically "partFixm" and "zone1Mobm".
-This boils down to partition in a minimal fashion "partFixm" into cells belonging either fully to
-"partFixm", or to "partFixm" and "zone1Mobm". Invoke the static method
+We intersect geometrically "partFixm" and "zone1Mobm".
+This boils down to partition in a minimal fashion "partFixm" into cells belonging either fully to
+"partFixm", or to "partFixm" and "zone1Mobm". Invoke the static method
MEDCouplingUMesh.Intersect2DMeshes(), with "partFixm" and "zone1Mobm", and use a precision
-of 1e-10 (merge detection threshold).
+of 1e-10 (merge detection threshold).
This method returns 3 parameters (see API documentation) which will be called partFixMob, iPart and iMob.
In partFixMob merge common nodes with a threshold of 1e-10. ::
.. image:: images/partFixmWithoutZone1Mobm.jpg
-Let's now check the result quality given by MEDCouplingUMesh.Intersect2DMeshes.
+Let's now check the result quality given by MEDCouplingUMesh.Intersect2DMeshes.
Three tests will be passed:
* (check#0) the cell area sum in partFixm equals the one in partFixMob
All values are negative: this MED file doesn't respect the MED file convention.
"partFixm" being mis-oriented and the method MEDCouplingUMesh.Intersect2DMeshes() conserving the orientation, "partFixMob" is also mis-oriented.
-To cut long story short, we perform comparison on absolute arrays.
+To cut long story short, we perform comparison on absolute arrays.
Check then that the first test check#0 is successful ::
areaPartFixm = partFixm.getMeasureField(isAbs=False).getArray()
Use intersection information to create fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We are done with partFixMob.
+We are done with partFixMob.
Now create a cell field on partFixMob by setting it to 0 on the part covering only partFixm and 1 on the overlapped
part. Visualize it in a VTK file. ::
.. image:: images/LocationEx2.jpg
-More generally take zones 0, 1 and 5.
+More generally take zones 0, 1 and 5.
Create a cell field whose value is 0 in the zone being exclusively part of fixm,
1 in the zone #0, 2 in the zone #1 and 3 in the zone #5. ::
Implementation start
~~~~~~~~~~~~~~~~~~~~
-To implement this exercise we use the Python scripting language and import the `medcoupling` Python module. ::
+To implement this exercise we use the Python scripting language and import the ``medcoupling`` Python module. ::
import medcoupling as mc
targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[14:18])
myCoords=mc.DataArrayDouble.New(targetCoords,9,2)
targetMesh.setCoords(myCoords)
-
+
.. note:: targetMesh is grouped by geometric type.
-Build "targetMesh1" representing the sub-constituents (faces) of "targetMesh" reduced to cell ids [3,4,7,8].
+Build "targetMesh1" representing the sub-constituents (faces) of "targetMesh" reduced to cell ids [3,4,7,8].
::
targetMeshConsti=targetMesh.buildDescendingConnectivity()[0]
grp1_M1=mc.DataArrayInt.New([0,1,2]) ; grp1_M1.setName("grp1_LevM1")
grp2_M1=mc.DataArrayInt.New([1,2,3]) ; grp2_M1.setName("grp2_LevM1")
meshMEDFile.setGroupsAtLevel(-1,[grp0_M1,grp1_M1,grp2_M1])
-
+
Then trying to read it. ::
fRead2=fMEDFileRead.getFieldAtLevel(mc.ON_CELLS,0) # like above but mesh is re-read from file...
print("Does the field f remain the same using fast method ? %s"%(fRead1.isEqual(f,1e-12,1e-12)))
print("Does the field f remain the same using slow method ? %s"%(fRead2.isEqual(f,1e-12,1e-12)))
-
+
Writing and Reading fields on a "profile"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Implementation start
~~~~~~~~~~~~~~~~~~~~
-To implement this exercise we use the Python scripting language and import the `medcoupling` Python module. ::
+To implement this exercise we use the Python scripting language and import the ``medcoupling`` Python module. ::
import medcoupling as mc
myCoords=mc.DataArrayDouble.New(targetCoords,9,2)
myCoords.setInfoOnComponents(["X [km]","YY [mm]"])
targetMesh.setCoords(myCoords)
-
+
.. note:: targetMesh is ordered by geometric type.
We are then ready to write it. ::
First dealing with the mesh. ::
mc.WriteUMesh("MySecondField.med",f.getMesh(),True)
-
+
Then writing only array part of field. ::
mc.WriteFieldUsingAlreadyWrittenMesh("MySecondField.med",f)
-
+
Then put a another time step. ::
f2=f.clone(True)
.. Code Integration and Code Coupling documentation master file, created by sphinx-quickstart on Tue Apr 28 14:31:38 2009.
You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
+ contain the root ``toctree`` directive.
medcoupling user's manual
=========================
data_analysis
data_conversion
data_optimization
-