MEDCouplingRemapper : interpolation de champs --------------------------------------------- Nous allons ici effectuer une interpolation entre deux maillages ``srcMesh`` et ``trgMesh``. Pour mettre l'accent sur certaines petites subtilitÊs de l'interpolation, nous prenons un cas particulier oÚ ``srcMesh`` est un maillage raffinÊ de ``trgMesh`` (avec certaines cellules dÊcoupÊes plus finement). DÊbut de l'implÊmentation ~~~~~~~~~~~~~~~~~~~~~~~~~ Pour commencer l'exercice importer le module Python ``MEDCoupling`` et la classe ``MEDCouplingRemapper`` du module ``MEDCouplingRemapper``. :: import MEDCoupling as mc from MEDCouplingRemapper import MEDCouplingRemapper CrÊer le maillage target ~~~~~~~~~~~~~~~~~~~~~~~~ Construire le maillage non structurÊ ``trgMesh`` issu d'un maillage cartÊsien 2D 10x10 commençant au point ``[0.,0.]`` et ayant un pas de 1. selon X et selon Y : :: arr = mc.DataArrayDouble(11) arr.iota(0) trgMesh = mc.MEDCouplingCMesh() trgMesh.setCoords(arr,arr) trgMesh = trgMesh.buildUnstructured() CrÊer le maillage source ~~~~~~~~~~~~~~~~~~~~~~~~ CrÊer un maillage ``srcMesh`` issu d'un maillage cartÊsien 2D 20x20 cellules commençant aussi au point ``[0.,0.]`` et ayant un pas de 0.5 selon X et selon Y : :: arr = mc.DataArrayDouble(21) arr.iota(0) arr *= 0.5 srcMesh = mc.MEDCouplingCMesh() srcMesh.setCoords(arr,arr) srcMesh = srcMesh.buildUnstructured() Afin de rendre l'exercise plus intÊressant, triangulariser à l'aide de ``MEDCouplingUMesh.simplexize()`` les 20 premières cellules de ``srcMesh`` (les simplexes 2D sont les triangles). Mettre le rÊsultat dans ``srcMesh``. :: tmp = srcMesh[:20] # Extract a sub-part of srcMesh tmp.simplexize(0) srcMesh = mc.MEDCouplingUMesh.MergeUMeshes([tmp,srcMesh[20:]]) Interpoler avec MEDCouplingRemapper ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Nous rappelons que pour projeter un champ d'un maillage vers un autre, il faut d'abord prÊparer la matrice d'interpolation qui contient les ratios de projection. Calculer la première partie de la matrice d'interpolation de ``srcMesh`` (discrÊtisÊe aux cellules - *P0*) vers ``trgMesh`` (discrÊtisÊe aux cellules Êgalement). Pour ce faire, invoquer ``MEDCouplingRemapper.prepare()`` sur une instance (``remap``) de ``MEDCouplingRemapper``. :: remap = MEDCouplingRemapper() remap.prepare(srcMesh,trgMesh,"P0P0") VÊrifier que la matrice calculÊe par la mÊthode est correcte dans notre cas trivial. Pour ce faire, rÊcupÊrer dans ``myMatrix`` la matrice interne retournÊe par ``MEDCouplingRemapper.getCrudeMatrix()``. Celle-ci donne pour chaque cellule de ``trgMesh`` les identifiants de cellules de ``srcMesh`` avec lesquelles elle s'intersecte, et l'aire d'intersection correspondante. VÊrifier notamment que pour chaque cellule de ``trgMesh`` la somme des aires fait toujours 1. :: myMatrix = remap.getCrudeMatrix() print myMatrix sumByRows = mc.DataArrayDouble(len(myMatrix)) for i,wIt in enumerate(sumByRows): su = 0. for it in myMatrix[i]: su += myMatrix[i][it] wIt[0] = su print "Is interpolation well prepared?", sumByRows.isUniform(1.,1e-12) .. note:: Les triangles dans ``srcMesh`` ont ÊtÊ rajoutÊs pour casser la monotonie de la matrice ``myMatrix``. .. note:: Comme on le voit, la prÊparation ne nÊcessite que les deux maillages, et rien d'autre. Construire un champ aux cellules "srcField" construit à partir de la formule analytique suivante ``7-sqrt((x-5.)*(x-5.)+(y-5.)*(y-5.))`` : :: srcField = mc.MEDCouplingFieldDouble(mc.ON_CELLS, mc.ONE_TIME) srcField.setMesh(srcMesh) srcField.fillFromAnalytic(1,"7-sqrt((x-5.)*(x-5.)+(y-5.)*(y-5.))") srcField.getArray().setInfoOnComponent(0, "powercell [W]") Voici à quoi ressemble ce champ : .. image:: images/Remapper1.png Appliquer l'interpolation avec ``MEDCouplingRemapper.transferField()`` : :: remap.transferField(srcField, 1e300) .. note:: 1e300 est une valeur par dÊfaut. Cette valeur sera systÊmatiquement assignÊe à toute cellule de ``trgField`` n'interceptant aucune cellule de ``srcMesh``. En gÊnÊral, les utilisateurs mettent une valeur Ênorme pour repÊrer ce qui est souvent un bug. Mais d'autres utilisateurs, dans la perspective d'une interpolation parallèle par exemple, mettent 0. .. note:: Une exception est envoyÊe car ``srcField`` n'a pas de *nature* dÊfinie. Nous allons voir dans la suite l'impact de cet attribut sur le rÊsultat final. Mettre la nature de ``srcField`` à ``IntensiveMaximum``. Cela signifie que le champ doit être interprÊtÊ commÊ Êtant intensif (une tempÊrature par exemple). :: srcField.setNature(mc.IntensiveMaximum) trgFieldCV = remap.transferField(srcField,1e300) VÊrifier qu'avec la nature ``IntensiveMaximum``, l'intÊgrale du champ est conservÊe. Par contre, la somme sur les cellules (accumulation) n'est **pas** conservÊe ! :: integSource = srcField.integral(True)[0] integTarget = trgFieldCV.integral(True)[0] print "IntensiveMaximum -- integrals: %lf == %lf" % (integSource, integTarget) accSource = srcField.getArray().accumulate()[0] accTarget = trgFieldCV.getArray().accumulate()[0] print "IntensiveMaximum -- sums: %lf != %lf" % (accSource, accTarget) Maintenant mettre la nature de ``srcField`` à ``ExtensiveConservation``. Le champ doit être interprÊtÊ commÊ Êtant extensif (par exemple une puissance ou un volume). :: srcField.setNature(mc.ExtensiveConservation) trgFieldI = remap.transferField(srcField,1e300) VÊrifier qu'avec la nature ``ExtensiveConservation``, l'intÊgrale du champ n'est **pas** conservÊe. Par contre, la somme sur les cellules est conservÊe. :: integSource = srcField.integral(True)[0] integTarget = trgFieldI.integral(True)[0] print "ExtensiveConservation -- integrals: %lf != %lf" % (integSource, integTarget) accSource = srcField.getArray().accumulate()[0] accTarget = trgFieldI.getArray().accumulate()[0] print "ExtensiveConservation -- sums: %lf == %lf" % (accSource, accTarget) Visualiser les champs avec ParaViS, ou en les Êcrivant dans un fichier. Solution ~~~~~~~~ :ref:`python_testMEDCouplingremapper1_solution`