Salome HOME
Documentation reorganization
[tools/medcoupling.git] / doc / tutorial / medcouplingnumpy_fr.rst
diff --git a/doc/tutorial/medcouplingnumpy_fr.rst b/doc/tutorial/medcouplingnumpy_fr.rst
new file mode 100644 (file)
index 0000000..a6dc90e
--- /dev/null
@@ -0,0 +1,190 @@
+
+MEDCoupling,  NumPy et SciPy
+----------------------------
+
+NumPy est un package additionnel de python qui permet de manipuler des tableaux de manière optimisée. 
+Il s'agit d'un prérequis optionnel de MEDCoupling.
+
+NumPy est une passerelle vers le HPC Python (multiprocessing, pyCUDA, SciPy...) et offre de puissantes 
+fonctions de calcul vectoriel. C'est pourquoi MEDCoupling offre des liens avec NumPy. 
+Un bon point de départ pour la découverte de NumPy est le `Tutorial NumPy <http://wiki.scipy.org/Tentative_NumPy_Tutorial>`_
+
+SciPy est aussi un package de python nécessitant NumPy. Il s'agit également d'un prérequis optionnel de MEDCoupling.
+SciPy offre des services d'algèbre linéaire, Fast Fourrier Transform, etc ...
+
+Nous allons ici faire quelques petites manipulations pour voir ce lien entre MEDCoupling et NumPy / SciPy.
+
+Début de l'implémentation
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Pour commencer l'exercice importer le module Python ``MEDCoupling``: ::
+
+       import MEDCoupling as mc
+
+NumPy est un prérequis optionnel, vérifions que nous en bénéficions bien : ::
+
+       assert(mc.MEDCouplingHasNumPyBindings())
+
+Nous pouvons alors importer NumPy sans problème: ::
+
+       import numpy as np
+
+Convertir un DataArray en tableau NumPy et vice versa
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Créer une instance de ``DataArrayDouble`` ayant une composante et 12 tuples.
+Et assigner 4. à tous les tuples. ::
+
+       arr = mc.DataArrayDouble(12)
+       arr[:] = 4.
+
+Créons maintenant un tableau NumPy reposant sur les mêmes données que ``arr``. ::
+
+       nparr = arr.toNumPyArray()
+
+Et afficher ``nparr``. ::
+
+       print nparr.__repr__()
+       print nparr.tolist()
+
+Mais est ce qu'on ne nous a pas mystifié ? ``arr`` et ``nparr`` partagent-ils le même bloc mémoire ?
+Pour le vérifier assignons 7.0 un tuple sur 2 avec ``nparr`` et vérifions que ``arr`` et ``nparr`` sont simultanément modifiés. ::
+
+       nparr[::2] = 7.
+       print nparr.__repr__()
+       print arr.__repr__()
+
+C'est rigolo ! Mais si je détruis ``arr`` (le premier à avoir alloué la mémoire) est-ce que ``nparr`` est tué aussi ? 
+Ne risque-t-on pas le SIGSEGV ?
+Testons : ::
+
+       del arr
+       import gc; gc.collect()     # Make sure the object has been deleted
+       print nparr.__repr__()
+
+OK super. Mais inversement puis je faire une instance de ``DataArrayDouble`` avec ``nparr`` ? Oui, en utilisant le constructeur
+qui prend un ``nparray`` en entrée.
+Et afficher le contenu.::
+
+       arr2 = mc.DataArrayDouble(nparr)
+       print arr2.__repr__()
+
+Modifions ``nparr`` en assignant 5.0 pour tous les tuples et vérifier que les 2 représentations ont bien été modifiées simultanément.::
+
+       nparr[:] = 5.
+       print nparr.__repr__()
+       print arr2.__repr__()
+
+Nous en profitons pour montrer un petit service pratique avec NumPy, à savoir, l'écriture optimisée. 
+Ecrivons le contenu binaire de ``nparr`` dans un fichier. ::
+
+       f = open("toto.data","w+b")
+       a = np.memmap(f, dtype='float64', mode='w+', offset=0, shape=nparr.shape)
+       a[:] = nparr[:]
+       f.flush()
+
+Relisons "toto.data". ::
+
+       f2 = open("toto.data","r+b")
+       b = np.memmap(f2,dtype='float64',mode='r',offset=0,shape=(12,))
+
+Pour rigoler, assignons 3.14 à ``a``, flushons et relisons. ::
+
+       a[:] = 3.14
+       f.flush()
+       b = np.memmap(f2,dtype='float64',mode='r',offset=0,shape=(12,))
+       print b.__repr__()
+
+On voit donc que le passage de MEDCoupling à NumPy se fait directement et de manière optimisée. Donc ca peut valoir le coup !
+Tout ce qui vient d'être montré marche aussi avec des ``DataArrayInt``.
+Regardons la suite.
+
+Jouons avec SciPy
+~~~~~~~~~~~~~~~~~
+
+Nous allons créer un maillage non conforme. Le but sera de trouver la peau de ce maillage *sans* les surfaces non conformes.
+
+Nous allons faire cela en jouant avec les matrices creuses de SciPy (*sparse matrix*). Nous interpolons ce maillage non conforme
+sur lui même, ce qui devrait donner une matrice diagonale si le maillage était conforme.
+
+Avant nous vérifions que l'on peut jouer avec SciPy ! ::
+
+       assert(mc.MEDCouplingHasSciPyBindings())
+
+Pour le moment créons un maillage non conforme. Nous collons simplement deux maillages structurés avec des 
+discrétisations spatiales différentes.::
+
+       c1 = mc.MEDCouplingCMesh()
+       arr1 = mc.DataArrayDouble(7) 
+       arr1.iota() 
+       c1.setCoords(arr1,arr1,arr1)
+       c2 = mc.MEDCouplingCMesh()
+       arr2 = mc.DataArrayDouble(9)
+       arr2.iota() 
+       arr2 *= 6./8.
+       c2.setCoords(arr2,arr2,arr2)
+
+Dégénérons ``c1`` et ``c2`` en non-structuré, une translation de ``[6.,0.,0.]`` de ``c2``,  et en faisant 
+l'agrégation des deux, c'est dans la poche. ::
+
+       c1 = c1.buildUnstructured()
+       c2 = c2.buildUnstructured()
+       c2.translate([6.,0.,0.])
+       c = mc.MEDCouplingUMesh.MergeUMeshes([c1,c2])
+
+Attention des noeuds sont dupliqués, il faut invoquer ``mergeNodes()``. ::
+
+       c.mergeNodes(1e-12)
+
+Récupérons la peau et les faces non conformes. Ca nous savons faire, car nous avons fait les exercices avant :-) ::
+
+       skinAndNCFaces = c.computeSkin()
+
+Retirons les noeuds non utilisés. Cette étape n'est pas obligatoire. ::
+
+       skinAndNCFaces.zipCoords()
+
+Voici à quoi cela ressemble:
+
+.. image:: images/skinandnccells_numpy.png
+
+OK maintenant on va séparer les cellules de bord des cellules non conformes grâce au ``MEDCouplingRemapper``.
+Interpolons ``skinAndNCFaces`` sur lui-même. On acceptera un écart entre face de 1e-12 et un warping max de 0.01. ::
+
+       from MEDCouplingRemapper import MEDCouplingRemapper
+       rem = MEDCouplingRemapper()
+       rem.setMaxDistance3DSurfIntersect(1e-12)
+       rem.setMinDotBtwPlane3DSurfIntersect(0.99)
+       rem.prepare(skinAndNCFaces,skinAndNCFaces,"P0P0")
+
+Récupérer la matrice creuse au format CSR du remapper. ::
+
+       mat = rem.getCrudeCSRMatrix()
+       
+.. note:: Le format CSR est un format de stockage efficace des matrices 
+       creuses : `Sparse matrix CSR <http://en.wikipedia.org/wiki/Sparse_matrix>`_
+
+Comme nous avons bien suivi les exos sur NumPy, grâce au NumPy array ``mat.indptr`` on peut récupérer 
+l'ensemble des lignes de la matrice ``mat`` ayant exactement un élément non nul. ::
+
+       indptr = mc.DataArrayInt(mat.indptr)
+       indptr2 = indptr.deltaShiftIndex()
+       cellIdsOfSkin = indptr2.getIdsEqual(1)
+
+C'est presque fini. Créer le sous maillage contenant uniquement la peau et l'écrire dans 
+un fichier VTK ou MED pour le visualiser avec ParaView. ::
+
+       skin = skinAndNCFaces[cellIdsOfSkin]
+       skin.writeVTK("skin.vtu")
+
+.. note:: ``skin`` contient des noeuds orphelins, on peut les retirer avec ``skin.zipCoords()``.
+
+Et voilà ce que cela donne :
+
+.. image:: images/skinonly_numpy.png
+
+Script complet
+~~~~~~~~~~~~~~
+
+:ref:`python_testMEDCouplingNumPy_solution`
+