From: Gbkng Date: Mon, 17 Jun 2024 18:18:11 +0000 (+0200) Subject: remove doc/tutorial X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=5da36c290d5c7bd724a2d2259d58b0ac881b8410;p=tools%2Fmedcoupling.git remove doc/tutorial --- diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index d47643792..6771a6a9a 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -18,5 +18,4 @@ # ADD_SUBDIRECTORY(developer) -ADD_SUBDIRECTORY(tutorial) ADD_SUBDIRECTORY(user) diff --git a/doc/tutorial/CMakeLists.txt b/doc/tutorial/CMakeLists.txt deleted file mode 100644 index 00ff074c7..000000000 --- a/doc/tutorial/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (C) 2012-2024 CEA, EDF -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# - -SALOME_CONFIGURE_FILE(conf.py.in conf.py) - -SET(_cmd_options -c ${CMAKE_CURRENT_BINARY_DIR} -b html -d doctrees -D latex_paper_size=a4 ${CMAKE_CURRENT_SOURCE_DIR} html) -SALOME_GENERATE_ENVIRONMENT_SCRIPT(_cmd env_script "${SPHINX_EXECUTABLE}" "${_cmd_options}") - -ADD_CUSTOM_TARGET(tutorial_doc COMMAND ${_cmd}) -ADD_DEPENDENCIES(doxygen_documentation tutorial_doc) - -#INSTALL(CODE "EXECUTE_PROCESS(COMMAND \"${CMAKE_COMMAND}\" --build ${PROJECT_BINARY_DIR} --target tutorial_doc)") -INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/ DESTINATION ${MEDCOUPLING_INSTALL_DOC}/tutorial) -INSTALL(DIRECTORY images/ DESTINATION ${MEDCOUPLING_INSTALL_DOC}/tutorial/images) -INSTALL(DIRECTORY data/ DESTINATION ${MEDCOUPLING_INSTALL_DOC}/tutorial/data) - -SET(make_clean_files html doctrees) -SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${make_clean_files}") diff --git a/doc/tutorial/atestMEDCouplingCorba1.rst b/doc/tutorial/atestMEDCouplingCorba1.rst deleted file mode 100644 index 67aac7c62..000000000 --- a/doc/tutorial/atestMEDCouplingCorba1.rst +++ /dev/null @@ -1,37 +0,0 @@ - -.. _python_testMEDCouplingcorba1_solution: - -Visualiser une instance de MEDCoupling dans ParaViS à travers CORBA -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - from MEDCouplingCorba import MEDCouplingUMeshServant - - # Creating a mesh - arr = mc.DataArrayDouble(11) - arr.iota(0) - m = mc.MEDCouplingCMesh() - m.setCoords(arr,arr) - m = m.buildUnstructured() - - # Making it available on the CORBA bus - ref_m = MEDCouplingUMeshServant._this(m) - import CORBA - orb = CORBA.ORB_init() - ior = orb.object_to_string(ref_m) - print(ior) - - # Displaying it in ParaVis - import salome - salome.salome_init() - print("About to import module 'pvsimple' ...") - import pvsimple as pvs - print("Module 'pvsimple' was imported!") - - # From here, we use the standard ParaView API: - src1 = pvs.ParaMEDCorbaPluginSource() - src1.IORCorba = ior # This is where we need the CORBA reference of the object created - dr = pvs.Show(src1) - diff --git a/doc/tutorial/atestMEDCouplingCube.rst b/doc/tutorial/atestMEDCouplingCube.rst deleted file mode 100644 index 329fcbe56..000000000 --- a/doc/tutorial/atestMEDCouplingCube.rst +++ /dev/null @@ -1,253 +0,0 @@ - -.. _python_testMEDCouplingcube_solution: - -3D cube meshing -~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - from math import * - - # Definition of environment variables - spaceDimension = 3 - N = 4 - nbOfNodes = N*N*N - nbOfCells = (N-1)*(N-1)*(N-1) - nbOfCells2D = (N-1)*(N-1) - - print("1 ********************") - # Initialisation of coordinates - coordinates = [] - for k in range(N): - for j in range(N): - for i in range(N): - coordinates.append(float(i)) - coordinates.append(float(j)) - coordinates.append(float(k)) - - print("2 ********************") - # Creation of meshing : need following initialisations - # => Definition of the mesh dimension - # => Definition of number of cells - # => Definition of name of meshing - mesh=mc.MEDCouplingUMesh.New() - mesh.setMeshDimension(3) - mesh.allocateCells(nbOfCells+nbOfCells2D) - mesh.setName("3Dcube") - - print("3 ********************") - # One remark : only one dimension cells by meshing - # Construction of volumic meshing - # => Definition of connectivity - # => Definition of type of cells - connectivity = [] - for k in range(N-1): - for j in range(N-1): - for i in range(N-1): - inode = N*N*(k+1)+ N*(j+1)+i - connectivity.append(inode) - connectivity.append(inode-N) - connectivity.append(inode-N+1) - connectivity.append(inode+1) - connectivity.append(inode-N*N) - connectivity.append(inode-N*N-N) - connectivity.append(inode-N*N-N+1) - connectivity.append(inode-N*N+1) - print(len(connectivity)) - print(8*(nbOfCells)) - - print("4 ********************") - # Adding cells in meshing - for i in range(nbOfCells): - mesh.insertNextCell(mc.NORM_HEXA8,8,connectivity[8*i:8*(i+1)]) - pass - - print("5 ********************") - # Settings of coordinates and verify if it's OK - myCoords = mc.DataArrayDouble.New() - myCoords.setValues(coordinates,nbOfNodes,3) - mesh.setCoords(myCoords) - mesh.checkConsistencyLight() - - print("6 ********************") - # Extraction of surfacic meshing - pt=[0.,0.,0.] - vec=[0.,0.,1.] - nodes = mesh.findNodesOnPlane(pt,vec,1e-12) - mesh2D = mesh.buildFacePartOfMySelfNode(nodes,True) - #print(mesh2D) - mesh2D.setName("3Dcube") - mesh2D.checkConsistencyLight() - - print("7 ********************") - # Creation of field : with following definition - # => Definition of the mesh support - # => Definition of field name - # => Definition of field nature - field = mc.MEDCouplingFieldDouble.New(ON_CELLS) - field.setMesh(mesh) - field.setName("field") - field.setNature(ExtensiveMaximum) - - # Computing and setting field values - myCoords=mc.DataArrayDouble.New() - sampleTab=[] - bar = mesh.computeCellCenterOfMass() - print(bar.getNbOfElems()) - for i in range(nbOfCells): - x = bar.getIJ(i+1,1) - y = bar.getIJ(i+1,2) - z = bar.getIJ(i+1,3) - d = sqrt(x*x+y*y+z*z) - sinus = sin(d) - #f.setValueIJ(i+1,1,sin(d)) - sampleTab.append(sinus) - - myCoords.setValues(sampleTab,nbOfCells,1) - field.setArray(myCoords) - - fBF = mc.MEDCouplingFieldDouble.New(ON_CELLS) - fBF.setMesh(mesh2D) - fBF.setName("fieldBottomFace") - fBF.setNature(ExtensiveMaximum) - Cval = 10. - myCoords2D=mc.DataArrayDouble.New() - sampleTab=[] - for i in range(nbOfCells2D): - sampleTab.append(Cval) - myCoords2D.setValues(sampleTab,nbOfCells2D,1) - fBF.setArray(myCoords2D) - - medFileName = "mc.MEDCoupling_cube3D.med" - # For note : True / False in Write* functions - # => True : overwriting existing file - # => False : add in existing file - meshes=[mesh2D,mesh] - mc.WriteUMeshes(medFileName,meshes,True); - mc.WriteField(medFileName,field,False) - mc.WriteField(medFileName,fBF,False) - - -:: - - import medcoupling as mc - from math import * - - spaceDim3D = 3 - MeshDim2D = 2 - N = 4 - NbCell2D = (N-1)*(N-1) - NbCell3D = NbCell2D*(N-1) - NbNode2D = N*N - NbNode3D = NbNode2D*N - - # Creation of a extruded meshing - # input : a 2D meshing and a 1D meshing - # Creation of 2D meshing - coordinates = [] - for j in range(N): - for i in range(N): - coordinates.append(float(i)) - coordinates.append(float(j)) - Connectivities = [0,4,5,1, 1,5,6,2, 2,6,7,3, 4,8,9,5, 5,9,10,6, 6,10,11,7, 8,12,13,9, 9,13,14,10, 10,14,15,11] - myCoords = mc.DataArrayDouble.New() - myCoords.setValues(coordinates,NbNode2D,MeshDim2D) - - m1 = mc.MEDCouplingUMesh.New() - m1.setMeshDimension(MeshDim2D) - m1.allocateCells(NbCell2D) - m1.setCoords(myCoords) - m1.setName("2D_Support") - - for i in range(NbCell2D): - m1.insertNextCell(mc.NORM_QUAD4,4,Connectivities[4*i:4*(i+1)]) - m1.changeSpaceDimension(3) - - # Creation of 1D meshing - coords = [ 0.0, 1.0, 2.0, 3.0 ] - conn = [ 0,1, 1,2, 2,3 ] - m2 = mc.MEDCouplingUMesh.New() - m2.setMeshDimension(1) - m2.allocateCells(3) - m2.insertNextCell(mc.NORM_SEG2,2,conn[0:2]) - m2.insertNextCell(mc.NORM_SEG2,2,conn[2:4]) - m2.insertNextCell(mc.NORM_SEG2,2,conn[4:6]) - myCoords1D=mc.DataArrayDouble.New() - myCoords1D.setValues(coords,4,1) - m2.setCoords(myCoords1D) - m2.changeSpaceDimension(3) - - # Construction of extruded meshing - center = [0.,0.,0.] - vector = [0.,1.,0.] - m2.rotate(center,vector,pi/2.) - m3 = m1.buildExtrudedMesh(m2,0) - m3.setName("Extrusion") - - # Construction of group : old fashion mode - part=[1] - meshGroup=m3.buildPartOfMySelf(part,True); - meshGroup.setName("meshGroup"); - - medFileName = "MEDCoupling_Extrudedcube3D.med" - mc.WriteUMeshesPartition(medFileName,"Extrusion",[m3,meshGroup],True) - - -:: - - import medcoupling as mc - from math import * - - spaceDim3D = 3 - MeshDim2D = 2 - N = 4 - NbCell2D = (N-1)*(N-1) - NbCell3D = NbCell2D*(N-1) - NbNode2D = N*N - NbNode3D = NbNode2D*N - - # Creation of a grid => Structured mesh - # Need directions definition - mesh=mc.MEDCouplingCMesh.New() - coordsX=mc.DataArrayDouble.New() - arrX=[ 0., 1., 2., 3. ] - coordsX.setValues(arrX,4,1) - coordsY=mc.DataArrayDouble.New() - arrY=[ 0., 1., 2., 3. ] - coordsY.setValues(arrY,4,1) - coordsZ=mc.DataArrayDouble.New() - arrZ=[ 0., 1., 2., 3. ] - coordsZ.setValues(arrZ,4,1) - mesh.setCoords(coordsX,coordsY,coordsZ) - # Passing structured meshing to unstructured - # necessary to save meshing - meshU=mesh.buildUnstructured() - meshU.setName("Grid") - - # Creation of group : fashion mode - # if ids cells are known, this step is not to be made - pt=[1] - m2 = meshU.buildPartOfMySelf(pt,True); - ret,tabIdCells = meshU.areCellsIncludedIn(m2,0) - print(ret) - print(tabIdCells) - # Definition of the name group - tabIdCells.setName("meshGroup") - - # Passing mc.MEDCoupling to mc.MEDFile - fmeshU = mc.MEDFileUMesh.New() - fmeshU.setName("Grid") - fmeshU.setDescription("IHopeToConvinceLastMEDMEMUsers") - myCoords = meshU.getCoords() - print(myCoords) - fmeshU.setCoords(myCoords) - print("**************************") - fmeshU.setMeshAtLevel(0,meshU) - print("**************************") - fmeshU.setGroupsAtLevel(0,[tabIdCells],False) - print("**************************") - - medFileName = "MEDCoupling_Gridcube3D.med" - fmeshU.write(medFileName,2) - diff --git a/doc/tutorial/atestMEDCouplingDataArray1.rst b/doc/tutorial/atestMEDCouplingDataArray1.rst deleted file mode 100644 index ce0c3a1b7..000000000 --- a/doc/tutorial/atestMEDCouplingDataArray1.rst +++ /dev/null @@ -1,63 +0,0 @@ - -.. _python_testMEDCouplingdataarray1_solution: - -Playing with regular hexagons using DataArrayDouble -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - import math - # Building the coordinates of the initial hexagon, centered at 0,0 - d = mc.DataArrayDouble(6,2) - d[:,0] = 3. - d[:,1] = list(range(6)) - d[:,1] *= math.pi/3. - d = d.fromPolarToCart() - d.setInfoOnComponents(["X [m]","Y [m]"]) - print(d.getValues()) - print(d) - print("Uniform array?", d.magnitude().isUniform(3.,1e-12)) - # Translating the 7 hexagons with a translation - radius = 3. - translationToPerform = [[0.,0.],[3./2.*radius,-radius*math.sqrt(3.)/2],[3./2.*radius,radius*math.sqrt(3.)/2],[0.,radius*math.sqrt(3.)],[-3./2.*radius,radius*math.sqrt(3.)/2],[-3./2.*radius,-radius*math.sqrt(3.)/2],[0.,-radius*math.sqrt(3.)]] - ds = len(translationToPerform)*[None] - for pos,t in enumerate(translationToPerform): - 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 - pass - # Identifying duplicate tuples - d2 = mc.DataArrayDouble.Aggregate(ds) - oldNbOfTuples = d2.getNumberOfTuples() - c,cI = d2.findCommonTuples(1e-12) - tmp = c[cI[0]:cI[0+1]] - print(tmp) - a = cI.deltaShiftIndex() - b = a - 1 - myNewNbOfTuples = oldNbOfTuples - sum(b.getValues()) - o2n, newNbOfTuples = mc.DataArrayInt.ConvertIndexArrayToO2N(oldNbOfTuples,c,cI) - print("Have I got the right number of tuples?") - print("myNewNbOfTuples = %d, newNbOfTuples = %d" % (myNewNbOfTuples, newNbOfTuples)) - assert(myNewNbOfTuples == newNbOfTuples) - # Extracting the unique set of tuples - d3 = d2.renumberAndReduce(o2n, newNbOfTuples) - n2o = o2n.invertArrayO2N2N2O(newNbOfTuples) - d3_bis = d2[n2o] - print("Are d3 and d3_bis equal ? %s" % (str(d3.isEqual(d3_bis, 1e-12)))) - # Now translate everything - d3 += [3.3,4.4] - # And build an unstructured mesh representing the final pattern - m = mc.MEDCouplingUMesh("My7hexagons",2) - m.setCoords(d3) - print("Mesh dimension is", m.getMeshDimension()) - print("Spatial dimension is", m.getCoords().getNumberOfComponents()) - m.allocateCells(7) - for i in list(range(7)): - cell_connec = o2n[6*i:6*(i+1)] - m.insertNextCell(mc.NORM_POLYGON, cell_connec.getValues()) - pass - # Check that everything is coherent (will throw if not) - m.checkConsistencyLight() - # Write the result into a VTU file that can be read with ParaView - m.writeVTK("My7hexagons.vtu") - diff --git a/doc/tutorial/atestMEDCouplingFieldDouble1.rst b/doc/tutorial/atestMEDCouplingFieldDouble1.rst deleted file mode 100644 index d9fbf6dee..000000000 --- a/doc/tutorial/atestMEDCouplingFieldDouble1.rst +++ /dev/null @@ -1,74 +0,0 @@ - -.. _python_testMEDCouplingfielddouble1_solution: - -Playing with fields -~~~~~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - - # Create an unstructured mesh from a Cartesian one - xarr = mc.DataArrayDouble.New(11,1) - xarr.iota(0.) - cmesh = mc.MEDCouplingCMesh.New() - cmesh.setCoords(xarr,xarr,xarr) - mesh = cmesh.buildUnstructured() - mesh.convertToPolyTypes(mc.DataArrayInt.Range(0,mesh.getNumberOfCells(),2)) - # Create a field - f = mesh.fillFromAnalytic(mc.ON_CELLS,1,"(x-5.)*(x-5.)+(y-5.)*(y-5.)+(z-5.)*(z-5.)") # 1 means that the field should have one component - f.setName("MyField") - # A variant: - f2 = mc.MEDCouplingFieldDouble(mc.ON_CELLS, mc.ONE_TIME) - f2.setMesh(mesh) - f2.setName("MyField2") - f2.fillFromAnalytic(1,"(x-5.)*(x-5.)+(y-5.)*(y-5.)+(z-5.)*(z-5.)") # 1 means that the field should have one component - print("Are f and f2 equal?", f.isEqualWithoutConsideringStr(f2,1e-12,1e-12)) - # - da1 = f.getArray() # a DataArrayDouble, which is a direct reference (not a copy) of the field's values - ids1 = da1.findIdsInRange(0.,5.) - fPart1 = f.buildSubPart(ids1) - fPart1.writeVTK("ExoField_fPart1.vtu") - ids2 = f.getArray().findIdsInRange(50.,1.e300) - fPart2 = f.buildSubPart(ids2) - # Renumbering cells to follow MED file rules - fPart1Cpy = fPart1.deepCopy() - o2n = fPart1Cpy.getMesh().sortCellsInMEDFileFrmt() - fPart1Cpy.getArray().renumberInPlace(o2n) - # Check that fPart1Cpy and fPart1 are the same - fPart1Cpy.substractInPlaceDM(fPart1,12,1e-12) - fPart1Cpy.getArray().abs() - print("Are the fields equal?", (fPart1Cpy.getArray().accumulate()[0]<1e-12)) - # Aggregate fields - fPart12 = mc.MEDCouplingFieldDouble.MergeFields([fPart1,fPart2]) - fPart12.writeVTK("ExoField_fPart12.vtu") - # Evaluation on points - bary = fPart12.getMesh().computeCellCenterOfMass() - arr1 = fPart12.getValueOnMulti(bary) - arr2 = f.getValueOnMulti(bary) - delta = arr1-arr2 - delta.abs() - print("Is field evaluation matching?", (delta.accumulate()[0]<1e-12)) - # ExtensiveMaximum computations - integ1 = fPart12.integral(0,True) - integ1_bis = fPart12.getArray().accumulate()[0] - print("First integral matching ?", ( abs(integ1 - integ1_bis) < 1e-8 )) - fPart12.getMesh().scale([0.,0.,0.], 1.2) - integ2 = fPart12.integral(0,True) - print("Second integral matching ?", ( abs(integ2-integ1_bis*1.2*1.2*1.2) < 1e-8 )) - # Explosion of field - fVec = mesh.fillFromAnalytic(mc.ON_CELLS,3,"(x-5.)*IVec+(y-5.)*JVec+(z-5.)*KVec") - fVecPart1 = fVec.buildSubPart(ids1) - fVecPart1.setName("fVecPart1") - cells = fPart1.getMesh().getNumberOfCells() * [None] - for icell,vec in enumerate(fVecPart1.getArray()): - m = fPart1.getMesh()[[icell]] - m.zipCoords() # Not mandatory but saves memory - m.translate(vec) - cells[icell] = m - pass - meshFVecPart1Exploded = mc.MEDCouplingUMesh.MergeUMeshes(cells) - fPart1.setMesh(meshFVecPart1Exploded) - fPart1.writeVTK("ExoField_fPart1_explo.vtu") - - diff --git a/doc/tutorial/atestMEDCouplingLoaderEx1.rst b/doc/tutorial/atestMEDCouplingLoaderEx1.rst deleted file mode 100644 index c520daaef..000000000 --- a/doc/tutorial/atestMEDCouplingLoaderEx1.rst +++ /dev/null @@ -1,124 +0,0 @@ - -.. _python_testmedcouplingloaderex1_solution: - -Agitateur - Swirler -~~~~~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - import numpy as np - - # Get available time steps - data = mc.MEDFileData("agitateur.med") - ts = data.getFields()[0].getTimeSteps() - print(ts) - # Get position of the swirler - fMts = data.getFields()["DISTANCE_INTERFACE_ELEM_BODY_ELEM_DOM"] - f1ts = fMts[(2,-1)] - fMc = f1ts.getFieldAtLevel(mc.ON_CELLS,0) - arr = fMc.getArray() - arr.getMinMaxPerComponent() # just to see the field variation range per component - ids = arr.findIdsInRange(0.,1.) - f2Mc = fMc[ids] - # Extract pression field on the swirler - pressMts = data.getFields()["PRESSION_ELEM_DOM"] - press1ts = pressMts[(2,-1)] - pressMc = press1ts.getFieldAtLevel(mc.ON_CELLS,0) - pressOnAgitateurMc = pressMc[ids] - # - pressOnAgitateurMc.getMesh().zipCoords() - # Compute pressure on skin - agitateurMesh3DMc = pressOnAgitateurMc.getMesh() - m3DSurf,desc,descI,revDesc,revDescI = agitateurMesh3DMc.buildDescendingConnectivity() - nbOf3DCellSharing = revDescI.deltaShiftIndex() - ids2 = nbOf3DCellSharing.findIdsEqual(1) - agitateurSkinMc = m3DSurf[ids2] - offsetsOfTupleIdsInField = revDescI[ids2] - tupleIdsInField = revDesc[offsetsOfTupleIdsInField] - pressOnSkinAgitateurMc = pressOnAgitateurMc[tupleIdsInField] - pressOnSkinAgitateurMc.setMesh(agitateurSkinMc) - # Force field computation - pressSkin = pressOnSkinAgitateurMc.getArray() - pressSkin *= 1e5 # conversion from bar to Pa - areaSkin = agitateurSkinMc.getMeasureField(True).getArray() - forceSkin = pressSkin*areaSkin - normalSkin = agitateurSkinMc.buildOrthogonalField().getArray() - forceVectSkin = forceSkin*normalSkin - # Torque computation - singlePolyhedron = agitateurMesh3DMc.buildSpreadZonesWithPoly() - singlePolyhedron.orientCorrectlyPolyhedrons() - centerOfMass = singlePolyhedron.computeCellCenterOfMass() - - barySkin=agitateurSkinMc.computeCellCenterOfMass() - posSkin = barySkin-centerOfMass - - torquePerCellOnSkin = mc.DataArrayDouble.CrossProduct(posSkin,forceVectSkin) - - zeTorque = torquePerCellOnSkin.accumulate() - print("couple = %r N.m" % zeTorque[2]) - # Power computation - speedMts = data.getFields()["VITESSE_ELEM_DOM"] - speed1ts = speedMts[(2,-1)] - speedMc = speed1ts.getFieldAtLevel(mc.ON_CELLS,0) - speedOnSkin = speedMc.getArray()[tupleIdsInField] - powerSkin = mc.DataArrayDouble.Dot(forceVectSkin,speedOnSkin) - power = powerSkin.accumulate()[0] - print("power = %r W"%(power)) - # Eigen vector computation - x2 = posSkin[:,0]*posSkin[:,0] - x2 = x2.accumulate()[0] - y2 = posSkin[:,1]*posSkin[:,1] - y2 = y2.accumulate()[0] - xy = posSkin[:,0]*posSkin[:,1] - xy = xy.accumulate()[0] - inertiaSkin = np.matrix([[x2,xy],[xy,y2]]) - inertiaSkinValues, inertiaSkinVects = np.linalg.eig(inertiaSkin) - pos = max(enumerate(inertiaSkinValues), key=lambda x: x[1])[0] - vect0 = inertiaSkinVects[pos].tolist()[0] - print(vect0) - - def computeAngle(locAgitateur1ts): - fMc = locAgitateur1ts.getFieldAtLevel(mc.ON_CELLS,0) - arr = fMc.getArray() - ids = arr.findIdsInRange(0.,1.) - f2Mc = fMc[ids] - m3DSurf,desc,descI,revDesc,revDescI = f2Mc.getMesh().buildDescendingConnectivity() - nbOf3DCellSharing = revDescI.deltaShiftIndex() - ids2 = nbOf3DCellSharing.findIdsEqual(1) - agitateurSkinMc = m3DSurf[ids2] - # - singlePolyhedron = agitateurMesh3DMc.buildSpreadZonesWithPoly() - singlePolyhedron.orientCorrectlyPolyhedrons() - centerOfMass = singlePolyhedron.computeCellCenterOfMass() - bary = agitateurSkinMc.computeCellCenterOfMass() - posSkin = bary-centerOfMass - x2=posSkin[:,0]*posSkin[:,0] ; x2=x2.accumulate()[0] - y2=posSkin[:,1]*posSkin[:,1] ; y2=y2.accumulate()[0] - xy=posSkin[:,0]*posSkin[:,1] ; xy=xy.accumulate()[0] - inertiaSkin = np.matrix([[x2,xy],[xy,y2]]) - inertiaSkinValues,inertiaSkinVects = np.linalg.eig(inertiaSkin) - pos = max(enumerate(inertiaSkinValues), key=lambda x: x[1])[0] - vect0 = inertiaSkinVects[pos].tolist()[0] - return vect0 - - vects = len(ts)*[None] - for itts,locAgitateur1ts in zip(ts,data.getFields()["DISTANCE_INTERFACE_ELEM_BODY_ELEM_DOM"]): - angle = computeAngle(locAgitateur1ts) - vects[itts[0]] = angle - pass - - from math import acos, sqrt - angle2 = len(ts)*[0.] - for pos in list(range(2,len(vects))): - norm1 = sqrt(vects[pos-1][0]*vects[pos-1][0]+vects[pos-1][1]*vects[pos-1][1]) - norm2 = sqrt(vects[pos][0]*vects[pos][0]+vects[pos][1]*vects[pos][1]) - crs = vects[pos-1][0]*vects[pos][0]+vects[pos-1][1]*vects[pos][1] - crs /= norm1 ; crs /= norm2 ; crs = min(crs,1.) - angle2[pos] = acos(crs) #/(ts[pos][2]-ts[pos-1][2]) - pass - - omega=sum(angle2)/(ts[-1][2]-ts[0][2]) - print(sum(angle2)) - - print("At timestep (%d,%d) (physical time=%r s) the torque is: %r N.m, power/omega=%r N.m " % (ts[2][0],ts[2][1],ts[2][2],zeTorque[2],power/omega)) diff --git a/doc/tutorial/atestMEDCouplingLoaderEx2.rst b/doc/tutorial/atestMEDCouplingLoaderEx2.rst deleted file mode 100644 index dbc064fd6..000000000 --- a/doc/tutorial/atestMEDCouplingLoaderEx2.rst +++ /dev/null @@ -1,115 +0,0 @@ - -.. _python_testmedcouplingloaderex2_solution: - -Intersection géométrique de maillages -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - - def displayVTK(m,fname): - tmp = m.deepCopy() - tmp.tessellate2D(0.1) - tmp.writeVTK(fname) - return - - # Read and clean Fixe.med - fixe = mc.MEDFileMesh.New("Fixe.med") - fixm = fixe.getMeshAtLevel(0) - print("Nb of nodes in the file : %i " % (fixm.getNumberOfNodes())) - fixm.mergeNodes(1e-10) - print("Nb of non duplicated nodes : %i" % (fixm.getNumberOfNodes())) - # Read and clean Mobile.med - mobile = mc.MEDFileMesh.New("Mobile.med") - mobm = mobile.getMeshAtLevel(0) - mobm.mergeNodes(1e-10) - # Visualize fixm and mobm with PARAVIEW - fixm2 = fixm.deepCopy() # tessellate2D() modifies the current mesh - fixm2.tessellate2D(0.1) - fixm2.writeVTK("fixm2.vtu") - mobm2 = mobm.deepCopy() - mobm2.tessellate2D(0.1) - mobm2.writeVTK("mobm2.vtu") - # mobm2 is in several pieces, take the first one - zonesInMobm = mobm.partitionBySpreadZone() - print("Nb of zones in mobm : %i" % (len(zonesInMobm))) - zone1Mobm = mobm[zonesInMobm[0]] - zone1Mobm.zipCoords() - displayVTK(zone1Mobm, "zone1Mobm.vtu") - # Get cell ids from the fix part in the boudning box of zone1Mobm - ids2 = fixm.getCellsInBoundingBox(zone1Mobm.getBoundingBox(),1e-10) - partFixm = fixm[ids2] - partFixm.zipCoords() - displayVTK(partFixm,"partFixm.vtu") - # Intersect partFixm with zone1Mobm - partFixMob, iPart, iMob = mc.MEDCouplingUMesh.Intersect2DMeshes(partFixm,zone1Mobm,1e-10) - partFixMob.mergeNodes(1e-10) - # Get the part of partFixm not included in zone1Mobm using partFixMob - ids3 = iMob.findIdsEqual(-1) - partFixmWithoutZone1Mobm = partFixMob[ids3] - displayVTK(partFixmWithoutZone1Mobm,"partFixmWithoutZone1Mobm.vtu") - # Check that intersection worked properly - # Check #0 - areaPartFixm = partFixm.getMeasureField(False).getArray() # if set to True returns the absolut field value - areaPartFixm.abs() - areaPartFixMob = partFixMob.getMeasureField(False).getArray() - areaPartFixMob.abs() - val1=areaPartFixm.accumulate()[0] - val2=areaPartFixMob.accumulate()[0] - print("Check #0 %lf == %lf with precision 1e-8? %s" % (val1,val2,str(abs(val1-val2)<1e-8))) - # Check #1 - areaZone1Mobm = zone1Mobm.getMeasureField(False).getArray() - areaZone1Mobm.abs() - val3 = areaZone1Mobm.accumulate()[0] - ids4 = iMob.findIdsNotEqual(-1) - areaPartFixMob2 = areaPartFixMob[ids4] - val4 = areaPartFixMob2.accumulate()[0] - print("Check #1 %lf == %lf with precision 1e-8 ? %s" % (val3,val4,str(abs(val3-val4)<1e-8))) - # Check #2 - isCheck2OK = True - for icell in list(range(partFixm.getNumberOfCells())): - ids5 = iPart.findIdsEqual(icell) - areaOfCells = areaPartFixMob[ids5] - areaOfCells.abs() - if abs(areaOfCells.accumulate()[0] - areaPartFixm[icell]) > 1e-9: - isCheck2OK = False - pass - pass - print("Check #2? %s" % (str(isCheck2OK))) - # Indicator field creation - f = mc.MEDCouplingFieldDouble(mc.ON_CELLS,mc.ONE_TIME) - m = partFixMob.deepCopy() - m.tessellate2D(0.1) - f.setMesh(m) - arr = mc.DataArrayDouble(partFixMob.getNumberOfCells(),1) - arr[iMob.findIdsEqual(-1)] = 0. - arr[iMob.findIdsNotEqual(-1)] = 1. - f.setArray(arr) - f.checkConsistencyLight() - f.setName("Zone") - mc.MEDCouplingFieldDouble.WriteVTK("Zone.vtu",[f]) - # Other zones - zonesMobm = mc.MEDCouplingUMesh.MergeUMeshesOnSameCoords([mobm[zonesInMobm[0]], mobm[zonesInMobm[1]], mobm[zonesInMobm[5]]]) - zonesMobm.zipCoords() - partFixMob2,iPart2,iMob2 = mc.MEDCouplingUMesh.Intersect2DMeshes(partFixm,zonesMobm,1e-10) - partFixMob2.mergeNodes(1e-10) - f2 = mc.MEDCouplingFieldDouble(mc.ON_CELLS, mc.ONE_TIME) - m2 = partFixMob2.deepCopy() - m2.tessellate2D(0.1) - f2.setMesh(m2) - arr = mc.DataArrayDouble(partFixMob2.getNumberOfCells(),1) - arr[iMob2.findIdsEqual(-1)]=0. - st = 0 - end = st + len(zonesInMobm[0]) - arr[iMob2.findIdsInRange(st,end)] = 1. - st += len(zonesInMobm[0]) ; - end = st + len(zonesInMobm[1]) - arr[iMob2.findIdsInRange(st,end)] = 2. - st += len(zonesInMobm[1]) - end = st + len(zonesInMobm[2]) - arr[iMob2.findIdsInRange(st,end)] = 3. - f2.setArray(arr) - f2.checkConsistencyLight() - f2.setName("Zone2") - mc.MEDCouplingFieldDouble.WriteVTK("Zone2.vtu",[f2]) diff --git a/doc/tutorial/atestMEDCouplingNumPy.rst b/doc/tutorial/atestMEDCouplingNumPy.rst deleted file mode 100644 index 7f68da0c2..000000000 --- a/doc/tutorial/atestMEDCouplingNumPy.rst +++ /dev/null @@ -1,78 +0,0 @@ - -.. _python_testMEDCouplingNumPy_solution: - -Playing with NumPy and SciPy -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - - # - # NumPy - # - import numpy as np - - # Checking NumPy binding - assert(mc.MEDCouplingHasNumPyBindings()) - # Playing with conversion and shared data - arr = mc.DataArrayDouble(12) - arr[:] = 4. - nparr = arr.toNumPyArray() - print(nparr.__repr__()) - print(nparr.tolist()) - nparr[::2] = 7. - print(nparr.__repr__()) - print(arr.__repr__()) - del arr - import gc; gc.collect() # Make sure the object has been deleted - print(nparr.__repr__()) - arr2 = mc.DataArrayDouble(nparr) - print(arr2.__repr__()) - nparr[:] = 5. - print(nparr.__repr__()) - print(arr2.__repr__()) - # Writing to file - f = open("toto.data","w+b") - a = np.memmap(f,dtype='float64',mode='w+',offset=0,shape=nparr.shape) - a[:] = nparr[:] - f.flush() - # Re-reading file - f2 = open("toto.data","r+b") - b = np.memmap(f2,dtype='float64',mode='r',offset=0,shape=(12,)) - a[:] = 3.14 - f.flush() - b = np.memmap(f2,dtype='float64',mode='r',offset=0,shape=(12,)) - print(b.__repr__()) - # - # SciPy - # - assert(mc.MEDCouplingHasSciPyBindings()) - 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) - c1 = c1.buildUnstructured() - c2 = c2.buildUnstructured() - c2.translate([6.,0.,0.]) - c = mc.MEDCouplingUMesh.MergeUMeshes([c1,c2]) - c.mergeNodes(1e-12) - skinAndNCFaces = c.computeSkin() - skinAndNCFaces.zipCoords() - # Isolating non conform cells - from MEDCouplingRemapper import MEDCouplingRemapper - rem = MEDCouplingRemapper() - rem.setMaxDistance3DSurfIntersect(1e-12) - rem.setMinDotBtwPlane3DSurfIntersect(0.99) - rem.prepare(skinAndNCFaces,skinAndNCFaces,"P0P0") - mat = rem.getCrudeCSRMatrix() - indptr = mc.DataArrayInt(mat.indptr) - indptr2 = indptr.deltaShiftIndex() - cellIdsOfSkin = indptr2.findIdsEqual(1) - skin = skinAndNCFaces[cellIdsOfSkin] - skin.writeVTK("skin.vtu") diff --git a/doc/tutorial/atestMEDCouplingPoly.rst b/doc/tutorial/atestMEDCouplingPoly.rst deleted file mode 100644 index 57cad0e6c..000000000 --- a/doc/tutorial/atestMEDCouplingPoly.rst +++ /dev/null @@ -1,95 +0,0 @@ - -.. _python_testMEDCoupling2D_solution: - -2D polygons meshing -~~~~~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - from math import * - - numberOfNodes = 25 - numberOfCells = 12 - - print("1 ********************") - spaceDimension = 2 - - # Coordinates of central polygon - X = [1.,0.5,-0.5,-1.,-0.5,0.5] - Y = [0.,sqrt(3.)/2.,sqrt(3.)/2.,0.,-sqrt(3.)/2.,-sqrt(3.)/2.] - - coordinates = [] - # origin - coordinates.append(0.) - coordinates.append(0.) - - # central polygon - for i in range(6): - coordinates.append(X[i]) - coordinates.append(Y[i]) - - # Coordinates of second couron - xc = 1.5 - yc = - sqrt(3.)/2. - d = sqrt(xc*xc+yc*yc) - a30 = pi/6.0 - a60 = pi/3.0 - - for i in range(6): - angle = a30+a60*i - xtmp = d*cos(angle) - ytmp = d*sin(angle) - start = (i-1)%6 - coordinates.append(xtmp+X[(i-1)%6]) - coordinates.append(ytmp+Y[(i-1)%6]) - coordinates.append(xtmp+X[i%6]) - coordinates.append(ytmp+Y[i%6]) - coordinates.append(xtmp+X[(i+1)%6]) - coordinates.append(ytmp+Y[(i+1)%6]) - - print("2 ********************") - # Creation of mesh - mesh=mc.MEDCoupplingUMesh.New() - mesh.setMeshDimension(2) - mesh.allocateCells(numberOfCells) - mesh.setName("MaFleur") - - myCoords=mc.DataArrayDouble.New() - myCoords.setValues(coordinates,numberOfNodes,2) - mesh.setCoords(myCoords) - - print("3 ********************") - # Connectivity of triangular meshing - connectivity = [] - for i in range(6): - connectivity.append(0) - connectivity.append(i%6+1) - connectivity.append((i+1)%6+1) - for i in range(6): - mesh.insertNextCell(mc.NORM_TRI3,3,connectivity[3*i:3*(i+1)]) - pass - - print("4 ********************") - # Connectivity of hexagons - connectivity = [] - for i in range(6): - start = i%6+1 - connectivity.append(start) - connectivity.append(start+2*(i+3)) - connectivity.append(start+2*(i+3)+1) - connectivity.append(start+2*(i+3)+2) - if i==5: - connectivity.append(7) - else: - connectivity.append(start+2*(i+3)+3) - connectivity.append((i+1)%6+1) - for i in range(6): - mesh.insertNextCell(mc.NORM_POLYGON,6,connectivity[6*i:6*(i+1)]) - pass - - print("5 ********************") - mesh.checkConsistencyLight() - - medFileName = "MEDCouppling_Fleur.med" - mc.WriteUMesh(medFileName,mesh,True) diff --git a/doc/tutorial/atestMEDCouplingRead.rst b/doc/tutorial/atestMEDCouplingRead.rst deleted file mode 100644 index a836c9cad..000000000 --- a/doc/tutorial/atestMEDCouplingRead.rst +++ /dev/null @@ -1,45 +0,0 @@ - -.. _python_testMEDCouplingRead_solution: - -Read med File -~~~~~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - - medFileName = "MEDCoupling_cube3D.med" - MeshName = "3Dcube" - FieldName = "field" - Field2DName = "fieldBottomFace" - - # Retrieving meshes - mesh3D = mc.ReadUMeshFromFile(medFileName,MeshName,0) - mesh2D = mc.ReadUMeshFromFile(medFileName,MeshName,-1) - - # Retrieving fields - f = mc.ReadFieldCell(medFileName,mesh3D.getName(),0,FieldName,-1,-1) - f2 = mc.ReadFieldCell(medFileName,mesh2D.getName(),-1,Field2DName,-1,-1) - - # Retrieving Coords Mesh - Coords3D = mesh3D.getCoords() - Values = Coords3D.getValuesAsTuple() - - # Retrieving field value on 0 tuple - pos= Values[0] - res=f.getValueOn(pos) - - # Verify if value is OK - bar = mesh3D.computeCellCenterOfMass() - x=bar.getIJ(1,1) - y=bar.getIJ(1,2) - z=bar.getIJ(1,3) - - from math import * - d = sqrt(x*x+y*y+z*z) - sinus = sin(d) - - if abs(res[0]-sinus)<1.e-5: - print("OK") - else: - print("KO") diff --git a/doc/tutorial/atestMEDCouplingRemapper.rst b/doc/tutorial/atestMEDCouplingRemapper.rst deleted file mode 100644 index ad484fb41..000000000 --- a/doc/tutorial/atestMEDCouplingRemapper.rst +++ /dev/null @@ -1,67 +0,0 @@ - -.. _python_testMEDCouplingremapper1_solution: - -Interpoler avec MEDCouplingRemapper -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - from MEDCouplingRemapper import MEDCouplingRemapper - # Target mesh - arr = mc.DataArrayDouble(11) - arr.iota(0) - trgMesh = mc.MEDCouplingCMesh() - trgMesh.setCoords(arr,arr) - trgMesh = trgMesh.buildUnstructured() - # Source mesh - arr = mc.DataArrayDouble(21) - arr.iota(0) - arr *= 0.5 - srcMesh = mc.MEDCouplingCMesh() - srcMesh.setCoords(arr,arr) - srcMesh = srcMesh.buildUnstructured() - # Triangularize some cells in source - tmp = srcMesh[:20] # Extract a sub-part of srcMesh - tmp.simplexize(0) - srcMesh = mc.MEDCouplingUMesh.MergeUMeshes([tmp,srcMesh[20:]]) - # Interpolate cells to cells - remap = MEDCouplingRemapper() - remap.prepare(srcMesh,trgMesh,"P0P0") - # Check matrix - 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)) - # Source field construction - 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]") - # Transfer field - #remap.transferField(srcField, 1e300) - srcField.setNature(mc.IntensiveMaximum) - trgFieldCV = remap.transferField(srcField,1e300) - # IntensiveMaximum - 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)) - # ExtensiveConservation - srcField.setNature(mc.ExtensiveConservation) - trgFieldI = remap.transferField(srcField,1e300) - # - 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)) diff --git a/doc/tutorial/atestMEDCouplingUMesh1.rst b/doc/tutorial/atestMEDCouplingUMesh1.rst deleted file mode 100644 index 70ad79ba4..000000000 --- a/doc/tutorial/atestMEDCouplingUMesh1.rst +++ /dev/null @@ -1,98 +0,0 @@ - -.. _python_testMEDCouplingumesh1_solution: - -Playing with unstructured mesh -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - - # Build a 3D mesh from scratch mixing HEXA8 and POLYHED - coords=[0.,0.,0., 1.,1.,0., 1.,1.25,0., 1.,0.,0., 1.,1.5,0., 2.,0.,0., 2.,1.,0., 1.,2.,0., 0.,2.,0., 3.,1.,0., - 3.,2.,0., 0.,1.,0., 1.,3.,0., 2.,2.,0., 2.,3.,0., - 0.,0.,1., 1.,1.,1., 1.,1.25,1., 1.,0.,1., 1.,1.5,1., 2.,0.,1., 2.,1.,1., 1.,2.,1., 0.,2.,1., 3.,1.,1., - 3.,2.,1., 0.,1.,1., 1.,3.,1., 2.,2.,1., 2.,3.,1., - 0.,0.,2., 1.,1.,2., 1.,1.25,2., 1.,0.,2., 1.,1.5,2., 2.,0.,2., 2.,1.,2., 1.,2.,2., 0.,2.,2., 3.,1.,2., - 3.,2.,2., 0.,1.,2., 1.,3.,2., 2.,2.,2., 2.,3.,2., - 0.,0.,3., 1.,1.,3., 1.,1.25,3., 1.,0.,3., 1.,1.5,3., 2.,0.,3., 2.,1.,3., 1.,2.,3., 0.,2.,3., 3.,1.,3., - 3.,2.,3., 0.,1.,3., 1.,3.,3., 2.,2.,3., 2.,3.,3.] - conn=[0,11,1,3,15,26,16,18, 1,2,4,7,13,6,-1,1,16,21,6,-1,6,21,28,13,-1,13,7,22,28,-1,7,4,19,22,-1,4,2,17,19,-1,2,1,16,17,-1,16,21,28,22,19,17, - 1,6,5,3,16,21,20,18, 13,10,9,6,28,25,24,21, 11,8,7,4,2,1,-1,11,26,16,1,-1,1,16,17,2,-1,2,17,19,4,-1,4,19,22,7,-1,7,8,23,22,-1,8,11,26,23,-1,26,16,17,19,22,23, - 7,12,14,13,22,27,29,28, 15,26,16,18,30,41,31,33, 16,17,19,22,28,21,-1,16,31,36,21,-1,21,36,43,28,-1,28,22,37,43,-1,22,19,34,37,-1,19,17,32,34,-1,17,16,31,32,-1,31,36,43,37,34,32, - 16,21,20,18,31,36,35,33, 28,25,24,21,43,40,39,36, 26,23,22,19,17,16,-1,26,41,31,16,-1,16,31,32,17,-1,17,32,34,19,-1,19,34,37,22,-1,22,23,38,37,-1,23,26,41,38,-1,41,31,32,34,37,38, - 22,27,29,28,37,42,44,43, 30,41,31,33,45,56,46,48, 31,32,34,37,43,36,-1,31,46,51,36,-1,36,51,58,43,-1,43,37,52,58,-1,37,34,49,52,-1,34,32,47,49,-1,32,31,46,47,-1,46,51,58,52,49,47, - 31,36,35,33,46,51,50,48, 43,40,39,36,58,55,54,51, 41,38,37,34,32,31,-1,41,56,46,31,-1,31,46,47,32,-1,32,47,49,34,-1,34,49,52,37,-1,37,38,53,52,-1,38,41,56,53,-1,56,46,47,49,52,53, - 37,42,44,43,52,57,59,58] - mesh3D = mc.MEDCouplingUMesh("mesh3D",3); - mesh3D.allocateCells(18); - mesh3D.insertNextCell(mc.NORM_HEXA8,conn[0:8]); mesh3D.insertNextCell(mc.NORM_POLYHED,conn[8:51]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[51:59]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[59:67]); mesh3D.insertNextCell(mc.NORM_POLYHED,conn[67:110]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[110:118]); - mesh3D.insertNextCell(mc.NORM_HEXA8,conn[118:126]); mesh3D.insertNextCell(mc.NORM_POLYHED,conn[126:169]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[169:177]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[177:185]); mesh3D.insertNextCell(mc.NORM_POLYHED,conn[185:228]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[228:236]); - mesh3D.insertNextCell(mc.NORM_HEXA8,conn[236:244]); mesh3D.insertNextCell(mc.NORM_POLYHED,conn[244:287]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[287:295]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[295:303]); mesh3D.insertNextCell(mc.NORM_POLYHED,conn[303:346]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[346:354]); - myCoords = mc.DataArrayDouble(coords,60,3); - myCoords.setInfoOnComponents(["X [m]","Y [m]","Z [m]"]) - mesh3D.setCoords(myCoords); - mesh3D.orientCorrectlyPolyhedrons() - mesh3D.sortCellsInMEDFileFrmt() - mesh3D.checkConsistencyLight() - renum = mc.DataArrayInt(60) ; renum[:15]=list(range(15,30)) ; renum[15:30]=list(range(15)) ; renum[30:45]=list(range(45,60)) ; renum[45:]=list(range(30,45)) - mesh3D.renumberNodes(renum,60) - # Scale coordinates from meters to centimeters - mesh3D.getCoords()[:] *= 100. - mesh3D.getCoords().setInfoOnComponents(["X [cm]","Y [cm]","Z [cm]"]) - # Identify unique Z values - zLev = mesh3D.getCoords()[:,2] - zLev = zLev.getDifferentValues(1e-12) - zLev.sort() - # Extract cells from a given Z level - Solution 1 - tmp,cellIdsSol1 = mesh3D.buildSlice3D([0.,0.,(zLev[1]+zLev[2])/2],[0.,0.,1.],1e-12) - # Idem - Solution 2 - bary = mesh3D.computeCellCenterOfMass() - baryZ = bary[:,2] - cellIdsSol2 = baryZ.findIdsInRange(zLev[1],zLev[2]) - # Idem - Solution 3 - nodeIds = mesh3D.findNodesOnPlane([0.,0.,zLev[0]],[0.,0.,1.],1e-10) - mesh2D = mesh3D.buildFacePartOfMySelfNode(nodeIds,True) - extMesh = mc.MEDCouplingMappedExtrudedMesh(mesh3D,mesh2D,0) - n_cells = mesh2D.getNumberOfCells() - cellIdsSol3 = extMesh.getMesh3DIds()[n_cells:2*n_cells] - # Compare the 3 methods - print(cellIdsSol1.getValues()) - print(cellIdsSol2.getValues()) - print(cellIdsSol3.getValues()) - # Extract part of the mesh - mesh3DPart = mesh3D[cellIdsSol2] # equivalent to mesh3DPart = mesh3D.buildPartOfMySelf(cellIdsSol2,True) - mesh3DPart.zipCoords() - # Check geometric type ordering - #print(mesh3DPart.advancedRepr()) - print(mesh3DPart.checkConsecutiveCellTypesAndOrder([mc.NORM_HEXA8,mc.NORM_POLYHED])) - print(mesh3DPart.checkConsecutiveCellTypes()) - #print(mesh3DPart.advancedRepr()) - # Extract cells along a line - Solution 1 - baryXY = bary[:,[0,1]] - baryXY -= [250.,150.] - magn = baryXY.magnitude() - cellIds2Sol1 = magn.findIdsInRange(0.,1e-12) - # Extract cells along a line - Solution 2 - bary2 = mesh2D.computeCellCenterOfMass()[:,[0,1]] - bary2 -= [250.,150.] - magn = bary2.magnitude() - ids = magn.findIdsInRange(0.,1e-12) - idStart = int(ids) # ids is assumed to contain only one value, if not an exception is thrown - ze_range = list(range(idStart,mesh3D.getNumberOfCells(),mesh2D.getNumberOfCells())) - cellIds2Sol2 = extMesh.getMesh3DIds()[ze_range] - # Construct the final sub-part - mesh3DSlice2 = mesh3D[cellIds2Sol1] - mesh3DSlice2.zipCoords() - # Aggregate two meshes, one being the translated version of the original - mesh3DSlice2bis = mesh3DSlice2.deepCopy() - mesh3DSlice2bis.translate([0.,1000.,0.]) - mesh3DSlice2All = mc.MEDCouplingUMesh.MergeUMeshes([mesh3DSlice2,mesh3DSlice2bis]) - mesh3DSlice2All.writeVTK("mesh3DSlice2All.vtu") - # Discover descending connectivity - mesh3DSurf,desc,descIndx,revDesc,revDescIndx = mesh3D.buildDescendingConnectivity() - numberOf3DCellSharing = revDescIndx.deltaShiftIndex() - cellIds = numberOf3DCellSharing.findIdsNotEqual(1) - mesh3DSurfInside = mesh3DSurf[cellIds] - mesh3DSurfInside.writeVTK("mesh3DSurfInside.vtu") - diff --git a/doc/tutorial/atestMEDLoaderAdvancedAPI1.rst b/doc/tutorial/atestMEDLoaderAdvancedAPI1.rst deleted file mode 100644 index 16ac95887..000000000 --- a/doc/tutorial/atestMEDLoaderAdvancedAPI1.rst +++ /dev/null @@ -1,94 +0,0 @@ - -.. _python_testMEDLoaderAdvancedAPI1_solution: - -Reading, Writing a MED file using MEDLoader advanced API -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - # Mesh creation - targetCoords = [-0.3,-0.3, 0.2,-0.3, 0.7,-0.3, -0.3,0.2, 0.2,0.2, 0.7,0.2, -0.3,0.7, 0.2,0.7, 0.7,0.7 ] - targetConn = [0,3,4,1, 1,4,2, 4,5,2, 6,7,4,3, 7,8,5,4] - targetMesh = mc.MEDCouplingUMesh("MyMesh",2) - targetMesh.allocateCells(5) - targetMesh.insertNextCell(mc.NORM_TRI3,3,targetConn[4:7]) - targetMesh.insertNextCell(mc.NORM_TRI3,3,targetConn[7:10]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[0:4]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[10:14]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[14:18]) - myCoords = mc.DataArrayDouble(targetCoords,9,2) - myCoords.setInfoOnComponents(["X [km]","YY [mm]"]) - targetMesh.setCoords(myCoords) - # Build the 2D faces from the 3D volumes (descending connectivity) - targetMeshConsti, _, _, _, _ = targetMesh.buildDescendingConnectivity() - targetMesh1 = targetMeshConsti[[3,4,7,8]] - targetMesh1.setName(targetMesh.getName()) - # - # Meshes - # - meshMEDFile = mc.MEDFileUMesh() - meshMEDFile.setMeshAtLevel(0,targetMesh) - meshMEDFile.setMeshAtLevel(-1,targetMesh1) - # Some groups on cells Level 0 - grp0_0 = mc.DataArrayInt([0,1,3]) - grp0_0.setName("grp0_Lev0") - grp1_0 = mc.DataArrayInt([1,2,3,4]) - grp1_0.setName("grp1_Lev0") - meshMEDFile.setGroupsAtLevel(0, [grp0_0,grp1_0]) - # Some groups on cells Level -1 - grp0_M1 = mc.DataArrayInt([0,1]) - grp0_M1.setName("grp0_LevM1") - grp1_M1 = mc.DataArrayInt([0,1,2]) - grp1_M1.setName("grp1_LevM1") - grp2_M1 = mc.DataArrayInt([1,2,3]) - grp2_M1.setName("grp2_LevM1") - meshMEDFile.setGroupsAtLevel(-1,[grp0_M1,grp1_M1,grp2_M1]) - # Write everything - meshMEDFile.write("TargetMesh2.med",2) # 2 stands for write from scratch - # Re-read and test equality - meshMEDFileRead = mc.MEDFileMesh.New("TargetMesh2.med") # a new is needed because it returns a MEDFileUMesh (MEDFileMesh is abstract) - meshRead0 = meshMEDFileRead.getMeshAtLevel(0) - meshRead1 = meshMEDFileRead.getMeshAtLevel(-1) - print("Is level 0 in the file equal to 'targetMesh'?", meshRead0.isEqual(targetMesh,1e-12)) - print("Is level 0 in the file equal to 'targetMesh1'?", meshRead1.isEqual(targetMesh1,1e-12)) - # Read groups - print(meshMEDFileRead.getGrpNonEmptyLevels("grp0_Lev0")) - grp0_0_read = meshMEDFileRead.getGroupArr(0,"grp0_Lev0") - print("Is group 'grp0_Lev0' equal to what is read in the file?" , grp0_0_read.isEqual(grp0_0)) - # - # Fields - # - f = mc.MEDCouplingFieldDouble(mc.ON_CELLS, mc.ONE_TIME) - f.setTime(5.6,7,8) - f.setArray(targetMesh.computeCellCenterOfMass()) - f.setMesh(targetMesh) - f.setName("AFieldName") - # Prepare field for writing - fMEDFile = mc.MEDFileField1TS() - fMEDFile.setFieldNoProfileSBT(f) # No profile desired on the field, Sort By Type - # *Append* the field to an existing file - fMEDFile.write("TargetMesh2.med",0) # 0 is very important here because we want to append to TargetMesh2.med and not to scratch it - # Read the field - fMEDFileRead = mc.MEDFileField1TS("TargetMesh2.med",f.getName(),7,8) - fRead1 = fMEDFileRead.getFieldOnMeshAtLevel(mc.ON_CELLS,0,meshMEDFileRead) # Quickest way, not re-reading mesh in the file. - fRead2 = fMEDFileRead.getFieldAtLevel(mc.ON_CELLS,0) # Like above, but this time the mesh is read! - print("Does the field remain OK with the quick method?", fRead1.isEqual(f,1e-12,1e-12)) - print("Does the field remain OK with the slow method?", fRead2.isEqual(f,1e-12,1e-12)) - # - # Writing and Reading fields on profile using MEDLoader advanced API - # - pfl = mc.DataArrayInt([1,2,3]) - pfl.setName("My1stPfl") - fPart = f.buildSubPart(pfl) - fPart.setName("fPart") - # - fMEDFile2 = mc.MEDFileField1TS() - fMEDFile2.setFieldProfile(fPart,meshMEDFileRead,0,pfl) # 0 is the relative level (here 0 means 3D) - fMEDFile2.write("TargetMesh2.med",0) # 0 is paramount to indicate that we *append* (and no overwrite) to the MED file - # - fMEDFileRead2 = mc.MEDFileField1TS("TargetMesh2.med",fPart.getName(),7,8) - fPartRead, pflRead = fMEDFileRead2.getFieldWithProfile(mc.ON_CELLS,0,meshMEDFileRead) - print("Is the partial field correctly read?", fPartRead.isEqualWithoutConsideringStr(fPart.getArray(),1e-12)) - print("Is the list of cell identifiers matching?", pflRead.isEqualWithoutConsideringStr(pfl)) - diff --git a/doc/tutorial/atestMEDLoaderBasicAPI1.rst b/doc/tutorial/atestMEDLoaderBasicAPI1.rst deleted file mode 100644 index fe1adbafa..000000000 --- a/doc/tutorial/atestMEDLoaderBasicAPI1.rst +++ /dev/null @@ -1,51 +0,0 @@ - -.. _python_testMEDLoaderBasicAPI1_solution: - -Reading, Writing a MED file using MEDLoader basic API -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - # Mesh creation - targetCoords = [-0.3,-0.3, 0.2,-0.3, 0.7,-0.3, -0.3,0.2, 0.2,0.2, 0.7,0.2, -0.3,0.7, 0.2,0.7, 0.7,0.7 ] - targetConn = [0,3,4,1, 1,4,2, 4,5,2, 6,7,4,3, 7,8,5,4] - targetMesh = mc.MEDCouplingUMesh("MyMesh",2) - targetMesh.allocateCells(5) - targetMesh.insertNextCell(mc.NORM_TRI3,3,targetConn[4:7]) - targetMesh.insertNextCell(mc.NORM_TRI3,3,targetConn[7:10]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[0:4]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[10:14]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[14:18]) - myCoords = mc.DataArrayDouble(targetCoords,9,2) - myCoords.setInfoOnComponents(["X [km]","YY [mm]"]) - targetMesh.setCoords(myCoords) - # Writing mesh only - mc.WriteUMesh("TargetMesh.med",targetMesh,True) # True means 'from scratch' - # Re-read it and test equality - meshRead = mc.ReadUMeshFromFile("TargetMesh.med",targetMesh.getName(),0) - print("Is the read mesh equal to 'targetMesh' ?", meshRead.isEqual(targetMesh,1e-12)) - # Writing a field and its support mesh in one go - f = mc.MEDCouplingFieldDouble.New(mc.ON_CELLS, mc.ONE_TIME) - f.setTime(5.6,7,8) # Declare the timestep associated to the field - f.setArray(targetMesh.computeCellCenterOfMass()) - f.setMesh(targetMesh) - f.setName("AFieldName") - mc.WriteField("MyFirstField.med",f,True) - # Re-read it and test equality - f2 = mc.ReadFieldCell("MyFirstField.med", f.getMesh().getName(), 0, f.getName(), 7, 8) - print("Is the read field identical to 'f' ?", f2.isEqual(f,1e-12,1e-12)) - # Writing in several steps - mc.WriteUMesh("MySecondField.med",f.getMesh(),True) - mc.WriteFieldUsingAlreadyWrittenMesh("MySecondField.med",f) - # A second field to write - f2 = f.clone(True) # 'True' means that we need a deep copy - f2.getArray()[:] = 2.0 - f2.setTime(7.8,9,10) - mc.WriteFieldUsingAlreadyWrittenMesh("MySecondField.med",f2) - # Re-read and test this two-timestep field - f3 = mc.ReadFieldCell("MySecondField.med",f.getMesh().getName(),0,f.getName(),7,8) - print("Is the field read in file equals to 'f' ?", f.isEqual(f3,1e-12,1e-12)) - f4 = mc.ReadFieldCell("MySecondField.med",f.getMesh().getName(),0,f.getName(),9,10) - print("Is the field read in file equals to 'f2' ?", f2.isEqual(f4,1e-12,1e-12)) - diff --git a/doc/tutorial/atestMEDLoaderSplitAndMerge1.rst b/doc/tutorial/atestMEDLoaderSplitAndMerge1.rst deleted file mode 100644 index 349694fee..000000000 --- a/doc/tutorial/atestMEDLoaderSplitAndMerge1.rst +++ /dev/null @@ -1,123 +0,0 @@ - -.. _python_testMEDLoaderSplitAndMerge1_solution: - -Splitting and Merging a MED file using MEDLoader -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - import medcoupling as mc - - m0 = mc.MEDCouplingCMesh() - arr = mc.DataArrayDouble(31,1) ; arr.iota(0.) - m0.setCoords(arr,arr) - m0 = m0.buildUnstructured() - m00 = m0[::2] # Extract even cells - m00.simplexize(0) - m01 = m0[1::2] - m0 = mc.MEDCouplingUMesh.MergeUMeshes([m00,m01]) - m0.getCoords()[:] *= 1/15. - m0.setName("mesh") - # Cell field - cellField = mc.MEDCouplingFieldDouble(mc.ON_CELLS, mc.ONE_TIME) - cellField.setTime(5.6,5,6) - cellField.setMesh(m0) - cellField.setName("CellField") - cellField.fillFromAnalytic(1,"exp(-((x-1)*(x-1)+(y-1)*(y-1)))") - cellField.getArray().setInfoOnComponent(0,"powercell [W]") - # Node field - nodeField = mc.MEDCouplingFieldDouble(mc.ON_NODES,mc.ONE_TIME) - nodeField.setTime(5.6,5,6) - nodeField.setMesh(m0) - nodeField.setName("NodeField") - nodeField.fillFromAnalytic(1,"exp(-((x-1)*(x-1)+(y-1)*(y-1)))") - nodeField.getArray().setInfoOnComponent(0,"powernode [W]") - # Splitting - proc0 = m0.getCellsInBoundingBox([(0.,0.4),(0.,0.4)],1e-10) - proc1 = proc0.buildComplement(m0.getNumberOfCells()) - # - nodeField0 = nodeField[proc0] ; cellField0 = cellField[proc0] ; cellField0.setMesh(nodeField0.getMesh()) - nodeField1 = nodeField[proc1] ; cellField1 = cellField[proc1] ; cellField1.setMesh(nodeField1.getMesh()) - - proc0_fname = "proc0.med" - mc.WriteField(proc0_fname, nodeField0, True) - mc.WriteFieldUsingAlreadyWrittenMesh(proc0_fname, cellField0) - - proc1_fname = "proc1.med" - mc.WriteField(proc1_fname,nodeField1,True) - mc.WriteFieldUsingAlreadyWrittenMesh(proc1_fname,cellField1) - # - # Merging - Sub-optimal method - # - cellField0_read = mc.ReadFieldCell("proc0.med","mesh",0,"CellField",5,6) - cellField1_read = mc.ReadFieldCell("proc1.med","mesh",0,"CellField",5,6) - cellField_read = mc.MEDCouplingFieldDouble.MergeFields([cellField0_read,cellField1_read]) - cellFieldCpy = cellField.deepCopy() - cellFieldCpy.substractInPlaceDM(cellField_read,10,1e-12) - cellFieldCpy.getArray().abs() - print(cellFieldCpy.getArray().isUniform(0.,1e-12)) - # - nodeField0_read = mc.ReadFieldNode("proc0.med","mesh",0,"NodeField",5,6) - nodeField1_read = mc.ReadFieldNode("proc1.med","mesh",0,"NodeField",5,6) - nodeField_read = mc.MEDCouplingFieldDouble.MergeFields([nodeField0_read, nodeField1_read]) - nodeField_read.mergeNodes(1e-10) - nodeFieldCpy = nodeField.deepCopy() - nodeFieldCpy.mergeNodes(1e-10) - nodeFieldCpy.substractInPlaceDM(nodeField_read,10,1e-12) - print(nodeFieldCpy.getArray().isUniform(0.,1e-12)) - # - # Merging - Optimal method - # - fileNames = ["proc0.med","proc1.med"] - msML = [mc.MEDFileMesh.New(fname) for fname in fileNames] - fsML = [mc.MEDFileFields.New(fname) for fname in fileNames] - mergeMLMesh = mc.MEDFileUMesh() - mergeMLFields = mc.MEDFileFields() - for lev in msML[0].getNonEmptyLevels(): - o2nML = len(msML[0].getNonEmptyLevels())*[None] - cs = [mML.getCoords() for mML in msML] - mergeMLMesh.setCoords(mc.DataArrayDouble.Aggregate(cs)) - ms = [mML.getMeshAtLevel(lev) for mML in msML] - m = mc.MEDCouplingUMesh.MergeUMeshes(ms) ; m.setCoords(mergeMLMesh.getCoords()) - o2nML[lev] = m.sortCellsInMEDFileFrmt() - mergeMLMesh.setMeshAtLevel(lev,m) - pass - - for fieldName in fsML[0].getFieldsNames(): - fmts = [fML[fieldName] for fML in fsML] - mergeField = mc.MEDFileFieldMultiTS() - for dt,it,tim in fmts[0].getTimeSteps(): - fts = [fmt[dt,it] for fmt in fmts] - arrs = len(fts)*[None] - for typp in fts[0].getTypesOfFieldAvailable(): - arr1s = [] - if typp == mc.ON_CELLS: - for ft in fts: - for geoTyp,smth in ft.getFieldSplitedByType(): - if geoTyp != mc.NORM_ERROR: - smth1 = filter(lambda x:x[0] == mc.ON_CELLS,smth) - arr2s = [ft.getUndergroundDataArray()[elt[1][0]:elt[1][1]] for elt in smth1] - arr1s.append(mc.DataArrayDouble.Aggregate(arr2s)) - pass - pass - pass - pass - else: - for ft in fts: - smth = filter(lambda x:x[0] == mc.NORM_ERROR,ft.getFieldSplitedByType()) - arr2 = mc.DataArrayDouble.Aggregate([ft.getUndergroundDataArray()[elt[1][0][1][0]:elt[1][0][1][1]] for elt in smth]) - arr1s.append(arr2) - pass - pass - arr = mc.DataArrayDouble.Aggregate(arr1s) - if typp == mc.ON_CELLS: - arr.renumberInPlace(o2nML[lev]) - mcf = mc.MEDCouplingFieldDouble(typp,mc.ONE_TIME) ; mcf.setName(fieldName) ; mcf.setTime(tim,dt,it) ; mcf.setArray(arr) - mcf.setMesh(mergeMLMesh.getMeshAtLevel(lev)) ; mcf.checkConsistencyLight() - mergeField.appendFieldNoProfileSBT(mcf) - pass - pass - mergeMLFields.pushField(mergeField) - pass - mergeMLMesh.write("merge.med",2) - mergeMLFields.write("merge.med",0) diff --git a/doc/tutorial/conf.py.in b/doc/tutorial/conf.py.in deleted file mode 100644 index 54d02d6a2..000000000 --- a/doc/tutorial/conf.py.in +++ /dev/null @@ -1,205 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Code Coupling and Code Integration documentation build configuration file, created by -# sphinx-quickstart on Tue Apr 28 15:28:57 2009. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# The contents of this file are pickled, so don't put values in the namespace -# that aren't pickleable (module imports are okay, they're removed automatically). -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os -import sphinx - -# If your extensions are in another directory, add it here. If the directory -# is relative to the documentation root, use os.path.abspath to make it -# absolute, like shown here. -#sys.path.append(os.path.abspath('.')) - -# General configuration -# --------------------- - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.mathjax'] -try: - import sphinx_rtd_theme - extensions += ['sphinx_rtd_theme'] - use_rtd_theme = True -except: - use_rtd_theme = False - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'MEDCoupling tutorial' -copyright = u'2015-2023, Geay, Bruneton' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '@MEDCOUPLING_VERSION@' -# The full version, including alpha/beta/rc tags. -release = '@MEDCOUPLING_VERSION@' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = [] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - - -# Options for HTML output -# ----------------------- -if use_rtd_theme: - html_theme = 'sphinx_rtd_theme' -else: - html_theme = 'default' if sphinx.version_info[:2] < (1,3) else 'classic' - -themes_options = {} -themes_options['classic'] = { - 'body_max_width':'none', - 'body_min_width':0, -} -html_theme_options = themes_options.get(html_theme, {}) - -# The style sheet to use for HTML and HTML Help pages. A file of that name -# must exist either in Sphinx' static/ path, or in one of the custom paths -# given in html_static_path. -#html_style = 'default.css' - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = '' - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -#html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_use_modindex = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, the reST sources are included in the HTML build as _sources/. -#html_copy_source = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'MEDCouplingTutorial' - - -# Options for LaTeX output -# ------------------------ - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, document class [howto/manual]). -latex_documents = [ - ('index', 'MEDCouplingTutorial.tex', 'MEDCoupling tutorial', - 'A. Geay, A. Bruneton', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = '' - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_use_modindex = True diff --git a/doc/tutorial/data/Fixe.med b/doc/tutorial/data/Fixe.med deleted file mode 100644 index e8955de01..000000000 Binary files a/doc/tutorial/data/Fixe.med and /dev/null differ diff --git a/doc/tutorial/data/Mobile.med b/doc/tutorial/data/Mobile.med deleted file mode 100644 index f357d2d2e..000000000 Binary files a/doc/tutorial/data/Mobile.med and /dev/null differ diff --git a/doc/tutorial/data/agitateur.med b/doc/tutorial/data/agitateur.med deleted file mode 100644 index 10529512c..000000000 Binary files a/doc/tutorial/data/agitateur.med and /dev/null differ diff --git a/doc/tutorial/images/DataArrayDouble_1.jpg b/doc/tutorial/images/DataArrayDouble_1.jpg deleted file mode 100644 index e5f1d4754..000000000 Binary files a/doc/tutorial/images/DataArrayDouble_1.jpg and /dev/null differ diff --git a/doc/tutorial/images/FieldDouble1_1.png b/doc/tutorial/images/FieldDouble1_1.png deleted file mode 100644 index bf5f082a5..000000000 Binary files a/doc/tutorial/images/FieldDouble1_1.png and /dev/null differ diff --git a/doc/tutorial/images/FieldDouble1_1_exploded.png b/doc/tutorial/images/FieldDouble1_1_exploded.png deleted file mode 100644 index 33bf6c695..000000000 Binary files a/doc/tutorial/images/FieldDouble1_1_exploded.png and /dev/null differ diff --git a/doc/tutorial/images/FieldDouble1_2.png b/doc/tutorial/images/FieldDouble1_2.png deleted file mode 100644 index 6c5fbac59..000000000 Binary files a/doc/tutorial/images/FieldDouble1_2.png and /dev/null differ diff --git a/doc/tutorial/images/Field_Cube3D.jpg b/doc/tutorial/images/Field_Cube3D.jpg deleted file mode 100644 index 90e68015e..000000000 Binary files a/doc/tutorial/images/Field_Cube3D.jpg and /dev/null differ diff --git a/doc/tutorial/images/IndirectIndex.jpg b/doc/tutorial/images/IndirectIndex.jpg deleted file mode 100644 index 3f5ccf5d6..000000000 Binary files a/doc/tutorial/images/IndirectIndex.jpg and /dev/null differ diff --git a/doc/tutorial/images/LocationEx2.jpg b/doc/tutorial/images/LocationEx2.jpg deleted file mode 100644 index f7d109e33..000000000 Binary files a/doc/tutorial/images/LocationEx2.jpg and /dev/null differ diff --git a/doc/tutorial/images/Mesh_cube3D.jpg b/doc/tutorial/images/Mesh_cube3D.jpg deleted file mode 100644 index aaefb731d..000000000 Binary files a/doc/tutorial/images/Mesh_cube3D.jpg and /dev/null differ diff --git a/doc/tutorial/images/Mesh_polygons2D.jpg b/doc/tutorial/images/Mesh_polygons2D.jpg deleted file mode 100644 index 37330742c..000000000 Binary files a/doc/tutorial/images/Mesh_polygons2D.jpg and /dev/null differ diff --git a/doc/tutorial/images/Remapper1.png b/doc/tutorial/images/Remapper1.png deleted file mode 100644 index b410ab6e4..000000000 Binary files a/doc/tutorial/images/Remapper1.png and /dev/null differ diff --git a/doc/tutorial/images/SplitAndMerge2.jpg b/doc/tutorial/images/SplitAndMerge2.jpg deleted file mode 100644 index a67d0fa6b..000000000 Binary files a/doc/tutorial/images/SplitAndMerge2.jpg and /dev/null differ diff --git a/doc/tutorial/images/SplitAndMergeCell1.jpg b/doc/tutorial/images/SplitAndMergeCell1.jpg deleted file mode 100644 index 88a27c102..000000000 Binary files a/doc/tutorial/images/SplitAndMergeCell1.jpg and /dev/null differ diff --git a/doc/tutorial/images/SurjectionDataArray.png b/doc/tutorial/images/SurjectionDataArray.png deleted file mode 100644 index 229b02e78..000000000 Binary files a/doc/tutorial/images/SurjectionDataArray.png and /dev/null differ diff --git a/doc/tutorial/images/UMesh1.png b/doc/tutorial/images/UMesh1.png deleted file mode 100644 index 3ffb6590c..000000000 Binary files a/doc/tutorial/images/UMesh1.png and /dev/null differ diff --git a/doc/tutorial/images/agitateur.jpg b/doc/tutorial/images/agitateur.jpg deleted file mode 100644 index e4ab2eeba..000000000 Binary files a/doc/tutorial/images/agitateur.jpg and /dev/null differ diff --git a/doc/tutorial/images/blade.jpg b/doc/tutorial/images/blade.jpg deleted file mode 100644 index 72791e523..000000000 Binary files a/doc/tutorial/images/blade.jpg and /dev/null differ diff --git a/doc/tutorial/images/captureCoarseMesh.png b/doc/tutorial/images/captureCoarseMesh.png deleted file mode 100644 index a5394bec5..000000000 Binary files a/doc/tutorial/images/captureCoarseMesh.png and /dev/null differ diff --git a/doc/tutorial/images/captureFineMesh.png b/doc/tutorial/images/captureFineMesh.png deleted file mode 100644 index 0b60d1cc9..000000000 Binary files a/doc/tutorial/images/captureFineMesh.png and /dev/null differ diff --git a/doc/tutorial/images/cube.jpg b/doc/tutorial/images/cube.jpg deleted file mode 100644 index 735ecbce3..000000000 Binary files a/doc/tutorial/images/cube.jpg and /dev/null differ diff --git a/doc/tutorial/images/face.jpg b/doc/tutorial/images/face.jpg deleted file mode 100644 index 1a35b2eae..000000000 Binary files a/doc/tutorial/images/face.jpg and /dev/null differ diff --git a/doc/tutorial/images/fixm.jpg b/doc/tutorial/images/fixm.jpg deleted file mode 100644 index 475f248bb..000000000 Binary files a/doc/tutorial/images/fixm.jpg and /dev/null differ diff --git a/doc/tutorial/images/mesh3DSurfInside.jpg b/doc/tutorial/images/mesh3DSurfInside.jpg deleted file mode 100644 index 17534de80..000000000 Binary files a/doc/tutorial/images/mesh3DSurfInside.jpg and /dev/null differ diff --git a/doc/tutorial/images/mobm.jpg b/doc/tutorial/images/mobm.jpg deleted file mode 100644 index ba1e0c918..000000000 Binary files a/doc/tutorial/images/mobm.jpg and /dev/null differ diff --git a/doc/tutorial/images/partFixmAndzone1Mobm.jpg b/doc/tutorial/images/partFixmAndzone1Mobm.jpg deleted file mode 100644 index fb9ca78c9..000000000 Binary files a/doc/tutorial/images/partFixmAndzone1Mobm.jpg and /dev/null differ diff --git a/doc/tutorial/images/partFixmWithoutZone1Mobm.jpg b/doc/tutorial/images/partFixmWithoutZone1Mobm.jpg deleted file mode 100644 index b47e79d05..000000000 Binary files a/doc/tutorial/images/partFixmWithoutZone1Mobm.jpg and /dev/null differ diff --git a/doc/tutorial/images/skinandnccells_numpy.png b/doc/tutorial/images/skinandnccells_numpy.png deleted file mode 100644 index e7cb7e7c7..000000000 Binary files a/doc/tutorial/images/skinandnccells_numpy.png and /dev/null differ diff --git a/doc/tutorial/images/skinonly_numpy.png b/doc/tutorial/images/skinonly_numpy.png deleted file mode 100644 index 1b16286a6..000000000 Binary files a/doc/tutorial/images/skinonly_numpy.png and /dev/null differ diff --git a/doc/tutorial/images/zone1Mobm.jpg b/doc/tutorial/images/zone1Mobm.jpg deleted file mode 100644 index 3aa07f60c..000000000 Binary files a/doc/tutorial/images/zone1Mobm.jpg and /dev/null differ diff --git a/doc/tutorial/images/zonesMobm.jpg b/doc/tutorial/images/zonesMobm.jpg deleted file mode 100644 index 7de18b3f9..000000000 Binary files a/doc/tutorial/images/zonesMobm.jpg and /dev/null differ diff --git a/doc/tutorial/index.rst b/doc/tutorial/index.rst deleted file mode 100644 index 7cba76275..000000000 --- a/doc/tutorial/index.rst +++ /dev/null @@ -1,58 +0,0 @@ -.. 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. - -MEDCoupling/MEDLoader Tutorial -============================== - -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. -Both the French and English versions are provided, but the French version -is better maintained ... - -(Jump to the English version below :ref:`english-toc`) - -Version française ------------------ - -Table des matières: - -.. toctree:: - :maxdepth: 2 - - medcoupling_fr - medloader_fr - medcouplingremapper_fr - medcouplingnumpy_fr - medcouplingmultiproc_fr - medcouplingcorba_fr - medcouplingloaderex1_fr - medcouplingloaderex2_fr - -.. _english-toc: - -English version ---------------- - -Table of contents: - -.. toctree:: - :maxdepth: 2 - - medcoupling_en - medloader_en - medcouplingremapper_en - medcouplingnumpy_en - medcouplingcorba_en - medcouplingloaderex1_en - medcouplingloaderex2_en - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/doc/tutorial/medcoupling_2Dpolygon.rst b/doc/tutorial/medcoupling_2Dpolygon.rst deleted file mode 100644 index 44c9038e3..000000000 --- a/doc/tutorial/medcoupling_2Dpolygon.rst +++ /dev/null @@ -1,115 +0,0 @@ - -Meshing a 2D geometry with polygons ------------------------------------ - -Objective -~~~~~~~~~ - -In this example we propose to build a mesh on a 2D geometry. We first create triangles in the center of the geometry and then hexagons around them. The result will be saved in a med file, and then visualized with the SMESH module of Salome. - -.. image:: images/Mesh_polygons2D.jpg - - -Beginning of implementation -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To implement this exercice we use the python language script and import the medcoupling module. We need also mathematical functions, so we import the python math module:: - - import medcoupling as mc - from math import * - -Then we must instantiate a meshing object:: - - mesh=mc.MEDCouplingUMesh.New() - mesh.setMeshDimension(2) - mesh.allocateCells(numberOfCells) - mesh.setName("MaFleur") - - -You must define 2 variables for space dimension and total number of nodes:: - - numberOfNodes = 25 - numberOfCells = 12 - spaceDimension = 2 - - -You must define the coordinates of the nodes of the central hexagon:: - - X = [1.,0.5,-0.5,-1.,-0.5,0.5] - Y = [0.,sqrt(3.)/2.,sqrt(3.)/2.,0.,-sqrt(3.)/2.,-sqrt(3.)/2.] - -Definition of nodes coordinates -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Define the coordinates of the origin and the nodes of the 2D central polygon:: - - coordinates = [] - # origin - coordinates.append(0.) - coordinates.append(0.) - - # central polygon - for i in range(6): - coordinates.append(X[i]) - coordinates.append(Y[i]) - -Define the coordinates of the extra nodes of the hexagons around the central hexagon:: - - # second couron - xc = 1.5 - yc = - sqrt(3.)/2. - - for i in range(6): - ... - - myCoords=mc.DataArrayDouble.New() - myCoords.setValues(coordinates,numberOfNodes,2) - mesh.setCoords(myCoords) - - -Definition of triangles connectivity -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For each triangle of the mesh, you have to give its connectivity: the list of the nodes which belong to the triangles:: - - connectivity = [] - for i in range(6): - connectivity.append(0) - connectivity.append(...) - connectivity.append(...) - for i in range(6): - mesh.insertNextCell(mc.NORM_TRI3,3,connectivity[3*i:3*(i+1)]) - pass - - -Definition of hexagons connectivity -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For each hexagon of the mesh, you have to give its connectivity: the list of the nodes which belong to the hexagons:: - - connectivity = [] - for i in range(6): - start = i%6+1 - connectivity.append(...) - for i in range(6): - mesh.insertNextCell(mc.NORM_POLYGON,6,connectivity[6*i:6*(i+1)]) - pass - mesh.checkConsistencyLight() - -Saving the mesh in a med file -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You have to create a med file with the MED driver:: - - medFileName = "MEDCoupling_Fleur.med" - mc.WriteUMesh(medFileName,mesh,True) - -Visualize the mesh with SMESH module of Salome -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Launch Salome platform, then select SMESH module and import your MED file. First You can see the number of elements of your mesh. For that, select your mesh in the object browser, set select Mesh menu and "Advanced Mesh Info" option. Verify the number of triangles and the number of hexagons. To visualize your mesh: click right bottom on your mesh and select "Show" option. - -Solution -~~~~~~~~ - -:ref:`python_testMEDCoupling2D_solution` diff --git a/doc/tutorial/medcoupling_3Dcube.rst b/doc/tutorial/medcoupling_3Dcube.rst deleted file mode 100644 index 4fd0369e5..000000000 --- a/doc/tutorial/medcoupling_3Dcube.rst +++ /dev/null @@ -1,344 +0,0 @@ - -Meshing a 3D cube ------------------ - -Objective -~~~~~~~~~ - -The meshing class of the SALOME MED module allows user to create a mesh from scratch. -In this example we propose to build a mesh on a 3D cube by three methods (classical method, method by extrusion and grid method). Each cell of the mesh must be a hexaedron. -We see also how creating a group. -Then we create a field on all the 3D cube. -Each result will be saved in a med file, and then visualized with the SMESH module of Salome. - -In spite of a mesh in MEDCoupling has only one dimension, it's possible to save some meshes with different dimension in one med file. We will see this method. - -.. image:: images/Mesh_cube3D.jpg - - -Beginning of implementation -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To implement this exercice we use the python language script and import the medcoupling module. We need also mathematical functions, so we import the python math module:: - - import medcoupling as mc - from math import * - -You must define 3 variables for space dimension, number of nodes on each dimension and total number of nodes:: - - MeshDim3D = 3 - MeshDim2D = 2 - N = ... - NbCell2D = (N-1)*(N-1) - NbCell3D = NbCell2D*(N-1) - NbNode2D = N*N - NbNode3D = NbNode2D*N - - -Classical method -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -First instantiate a meshing object. Therefore, we need to define : - - * its name - * its dimension - * its number of cells - -.. note:: All this initialisation is necessary. If one is missing, you'll have a segmentation fault!. - -:: - - mesh = mc.MEDCouplingUMesh.New() - mesh.setMeshDimension(3) - mesh.allocateCells(...) - mesh.setName("3Dcube") - -Definition of nodes coordinates -``````````````````````````````` - -Define the coordinates of the nodes of the 3D cube mesh, and then use the setCoords function to set it:: - - # Initialisation of coordinates - coordinates = [] - for k in range(N): - for j in range(N): - for i in range(N): - coordinates.append(...) - - myCoords = mc.DataArrayDouble.New() - myCoords.setValues(coordinates,nbOfNodes,3) - mesh.setCoords(myCoords) - - -Definition of hexahedrons connectivity -`````````````````````````````````````` -For each hexahedron of the mesh, you have to give its connectivity: the list of the nodes which belong to the hexahedron. The order of the nodes in the connectivity array must respect the MEDCoupling format (see the following figure). - -.. image:: images/cube.jpg - -.. warning:: Connectivity elements begin to 0 from (n-1) elements - -:: - - connectivity = [] - for k in range(N-1): - for j in range(N-1): - for i in range(N-1): - inode = ... - connectivity.append(inode) - connectivity.append(...) - - # Adding cells in meshing - for i in range(nbOfCells): - mesh.insertNextCell(mc.NORM_HEXA8,8,connectivity[8*i:8*(i+1)]) - pass - - # Check mesh consistency: - mesh.checkConsistencyLight() - -Method by extrusion -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In order to create a extruded mesh, we need one 2D mesh and one 1D mesh which define the vector of extrusion and the number of steps. - -Definition of 2D mesh -`````````````````````````````````````` -:: - - coordinates = [] - for j in range(N): - for i in range(N): - coordinates.append(...) - ... - Connectivities = [...] - myCoords = mc.DataArrayDouble.New() - myCoords.setValues(coordinates,NbNode2D,MeshDim2D) - - m1 = mc.MEDCouplingUMesh.New() - m1.setMeshDimension(MeshDim2D) - m1.allocateCells(NbCell2D) - m1.setCoords(myCoords) - m1.setName("2D_Support") - - for i in range(NbCell2D): - m1.insertNextCell(mc.NORM_QUAD4,4,Connectivities[4*i:4*(i+1)]) - m1.changeSpaceDimension(3) - -Definition of 1D mesh -`````````````````````````````````````` -:: - - coords = [ ... ] - conn = [ ... ] - m2 = mc.MEDCouplingUMesh.New() - m2.setMeshDimension(1) - m2.allocateCells(3) - m2.insertNextCell(mc.NORM_SEG2,2,conn[0:2]) - m2.insertNextCell(mc.NORM_SEG2,2,conn[2:4]) - m2.insertNextCell(mc.NORM_SEG2,2,conn[4:6]) - myCoords1D=mc.DataArrayDouble.New() - myCoords1D.setValues(coords,4,1) - m2.setCoords(myCoords1D) - m2.changeSpaceDimension(3) - -Definition of extruded mesh -`````````````````````````````````````` - -Since 1D meshing isn't well oriented (along 0x vector), we need to imply a transformation on it. -Then, we can extrude 2D meshing. - -:: - - center = [...] - vector = [...] - m2.rotate(...) - m3 = m1.buildExtrudedMesh(m2,0) - m3.setName("Extrusion") - -Grid method -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -it's the easiest way to create a grid since you have no connectivity to set. They will be automatically setting. Incrementation of ids will be made first along Ox axis, then along Oy axis and finally along Oz axis. - -:: - - mesh=mc.MEDCouplingCMesh.New() - coordsX=mc.DataArrayDouble.New() - arrX=[ ... ] - coordsX.setValues(arrX,4,1) - coordsY=mc.DataArrayDouble.New() - arrY=[ ... ] - coordsY.setValues(arrY,4,1) - coordsZ=mc.DataArrayDouble.New() - arrZ=[ ... ] - coordsZ.setValues(arrZ,4,1) - mesh.setCoords(coordsX,coordsY,coordsZ) - -Really in order to save this mesh, you need to transform this structured mesh to an unstructerd mesh. -:: - - meshU=mesh.buildUnstructured() - meshU.setName("Grid") - -Creation of groups -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A group is a set of cells defining by their id. This set must the input for creating a group. -Generally ids cells using in group are known. So you just need put these ids in a DataArray. -:: - - tabIdCells = mc.DataArrayInt.New() - IdCells = [ ... ] - tabIdCells.setValues(IdCells,...) - - -.. note:: It's also possible to retrieve ids cells from a submesh of the principal mesh. - -:: - - ret,tabIdCells = mesh.areCellsIncludedIn(subMesh,0) - - -Once the DataArray is created, some initializations have to be done. -:: - - # Definition of the name group - tabIdCells.setName("meshGroup") - - -In order to add a group on a mesh, you need to transform your unstructured mesh in a file unstructured mesh. -Moreover, we need to define: - - * its name - * its description - * its coordinates - * its dimension - * its number of cells - - -:: - - # Passing MEDCoupling to MEDFile - fmeshU = mc.MEDFileUMesh.New() - fmeshU.setName("Grid") - fmeshU.setDescription("IHopeToConvinceLastMEDMEMUsers") - myCoords = meshU.getCoords() - fmeshU.setCoords(myCoords) - fmeshU.setMeshAtLevel(0,meshU) - -Then, you can -Therefore, you need to define the level (ie. the dimension) of the group. -This information is given by a number : 0,-1 or -2. - - * 0 means the same level at mesh - -:: - - fmeshU.setGroupsAtLevel(0,[tabIdCells],False) - -Create field on 3D cube -~~~~~~~~~~~~~~~~~~~~~~~ - -First you need to create a CouplingField and initialize some data: - - * its name - * its support (ie mesh) - * its nature - * its values - - -The field will be a sin function dependent of distance of the barycenter of each cell from origin. So we need to create a barycenter field on the 3D mesh:: - - # Creation of field : with following definition - # => Definition of the mesh support - # => Definition of field name - # => Definition of field nature - field = mc.MEDCouplingFieldDouble.New(ON_CELLS) - field.setMesh(mesh) - field.setName("field") - field.setNature(ExtensiveMaximum) - - # Computing and setting field values - myCoords=mc.DataArrayDouble.New() - sampleTab=[] - bar = mesh.computeCellCenterOfMass() - print(bar.getNbOfElems()) - for i in range(nbOfCells): - x = bar.getIJ(...) - y = bar.getIJ(...) - z = bar.getIJ(...) - d = sqrt(x*x+y*y+z*z) - sinus = sin(d) - . sampleTab.append(sinus) - - myCoords.setValues(sampleTab,nbOfCells,1) - field.setArray(myCoords) - - -Saving the mesh in a med file -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -General Case -```````````` -:: - - medFileName = "MEDCoupling_Extrudedcube3D.med" - mc.WriteUMesh(medFileName,meshU,True) - -.. note:: True / False in Write* functions : True for overwriting existing file and False for adding in existing file - -Multi mesh Case -```````````````` - -In spite of a MEDCoupling mesh has only one dimension, it's possible to generate a file with multi dimension. -Therefore, you need to create as meshes as necessary dimensions. - -You have to give the connectivity of the faces on the bottom face of the 3D cube: the list of the nodes which belong to the face. -The connectivity must respect following figure: - -.. image:: images/face.jpg - -:: - - # Extraction of surfacic meshing - pt=[0.,0.,0.] - vec=[0.,0.,1.] - nodes = mesh.findNodesOnPlane(pt,vec,1e-12) - mesh2D = mesh.buildFacePartOfMySelfNode(nodes,True) - #print(mesh2D) - mesh2D.setName("3Dcube") - mesh2D.checkConsistencyLight() - - medFileName = "MEDCoupling_cube3D.med" - meshes=[mesh2D,mesh] - mc.WriteUMeshes(medFileName,meshes,True) - -Group Case -```````````` -:: - - medFileName = "MEDCoupling_Gridcube3D.med" - fmeshU.write(medFileName,2) - -Saving the fields in the med file -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - mc.WriteField(medFileName,field,False) - -Visualize the mesh with the SMESH module of Salome -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Launch Salome platform, then select SMESH module and import your MED file. First You can see the number of elements of your mesh. For that, select your mesh in the object browser, set select Mesh menu and "Advanced Mesh Info" option. Verify the number of faces and the number of hexahedrons. To visualize your mesh: click right bottom on your mesh and select "Show" option. You can also visualize your groups. Select one group, click right bottom on your group and select "Show only" option. - -Visualize the fields with the VISU module of Salome -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Launch Salome platform, then select VISU module and import your MED file. You can see in the object browser the 2 fields you have created. Then you have to create a scalar map on each field to visualize them. - -.. image:: images/Field_Cube3D.jpg - -Solution -~~~~~~~~ - -:ref:`python_testMEDCouplingcube_solution` diff --git a/doc/tutorial/medcoupling_Read.rst b/doc/tutorial/medcoupling_Read.rst deleted file mode 100644 index 272936fee..000000000 --- a/doc/tutorial/medcoupling_Read.rst +++ /dev/null @@ -1,87 +0,0 @@ - -Reading a med file -------------------- - -Objective -~~~~~~~~~ - -The MEDLoader class also allows to read a med file. - -We will use the case of the 3D cube in order to retrieve all meshes and fields along with value on one node. - -Beginning of implementation -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To implement this exercice we use the python language script and import the medcoupling module. We need also mathematical functions, so we import the python math module:: - - import medcoupling as mc - from math import * - - -Then define some variables:: - - medFileName = "MEDCoupling_cube3D.med" - MeshName = "3Dcube" - FieldName = "field" - Field2DName = "fieldBottomFace" - -Retrieving 3D mesh and associated field -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You need to use MEDLoader API in order to read med file. Read functions need to give the real dimension of the mesh to max. -This information is given by a number : 0,-1 or -2. - - * 0 means the high dimension of the mesh - * -1 means the second high dimension of the mesh - -and the iteration and order of the field. In our case, since there is no iteration, it's -1 for these 2 arguments:: - - mesh3D = mc.ReadUMeshFromFile(medFileName,MeshName,0) - f = mc.ReadFieldCell(medFileName,mesh3D.getName(),0,FieldName,-1,-1) - - -Retrieving 2D mesh and associated field -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Do the same thing for the 2D mesh and the associated field:: - - mesh2D = mc.ReadUMeshFromFile(...) - f2 = mc.ReadFieldCell(...) - -Retrieving mesh coords -~~~~~~~~~~~~~~~~~~~~~~ - -:: - - # Retrieving Coords Mesh - Coords3D = mesh3D.getCoords() - Values = Coords3D.getValuesAsTuple() - -Retrieving field values -~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - # Retrieving field value on 0 tuple - pos= Values[...] - res=f.getValueOn(pos) - - # Verify if value is OK - bar = mesh3D.computeCellCenterOfMass() - x=bar.getIJ(...) - y=bar.getIJ(...) - z=bar.getIJ(...) - - from math import * - d = sqrt(x*x+y*y+z*z) - sinus = sin(d) - - if abs(res[0]-sinus)<1.e-5: - print("OK") - else: - print("KO") - -Solution -~~~~~~~~ - -:ref:`python_testMEDCouplingRead_solution` diff --git a/doc/tutorial/medcoupling_dataarray1_en.rst b/doc/tutorial/medcoupling_dataarray1_en.rst deleted file mode 100644 index 1d839c561..000000000 --- a/doc/tutorial/medcoupling_dataarray1_en.rst +++ /dev/null @@ -1,257 +0,0 @@ - -Manipulate DataArray objects ----------------------------- - -DataArrays (DataArrayInt and DataArrayDouble) are used in MEDCoupling to store contiguous arrays in memory. Each array entry is a tuple of data. -They form the base of many data processing performed by MEDCoupling. It is thus useful to be able to manipulate them with ease. - -DataArrayDouble are often used to manipulate fields in an optimized fashion, as will be shown later on. - -Objective -~~~~~~~~~ - -In this exercise the aim is to create a set of 2D Cartesian coordinates. The first component will be called X (with unit "m") and the second Y (same unit). The coordinates represent 7 regular hexagons (all inscribed in a 3cm radius circle). -The 7 hexagons are built from a centered reference hexagon (3.4; 4.4). - -Around this reference, 6 translated copies are created and each copy shares exactly one edge with the reference. -The common nodes (tuples) are then merged. This shows how to use indirections, concept widely used in unstructured meshes. - -.. image:: images/DataArrayDouble_1.jpg - -Concepts at hand: - -* Create an instance of DataArrayDouble -* Display a DataArrayDouble instance and invoke the getValue() method to convert it to a list -* Use convenient notations da[...] -* Learn about renumbering (old2new convention) -* Invoke services from findCommonTuples - -Starting the implementation -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To start with, import the whole python module medcoupling and the standard math module. :: - - from medcoupling import * - import math - -This makes the following available: - -* all MEDCoupling classes -* all enum (ON_CELLS, ON_NODES, ONE_TIME...) -* all static methods - -Create a DataArrayDouble instance containing 6 tuples -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The target here is to create one DataArrayDouble containing the complete set of coordinates for one regular hexagon. :: - - d=DataArrayDouble(6,2) - -Which is equivalent to :: - - d=DataArrayDouble() - d.alloc(6,2) - -or to :: - - d=DataArrayDouble(12) - d.rearrange(2) - -.. note:: d contains 12 values grouped in 6 tuples containing each 2 components. - The values in d are still un-initialized. - -Initialize an instance of DataArrayDouble -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Assign the value 3.0 (radius) to the first component of all tuples. :: - - d[:,0]=3. - -Initialize the 2nd component of each tuple i with the index value i. :: - - d[:,1]=list(range(6)) - -Multiply the 2nd component by pi/3. :: - - d[:,1]*=math.pi/3. - -.. note:: d now contains the polar coordinates of our regular hexagon centered at 0,0. - -Convert from polar to Cartesian by invoking fromPolarToCart(), and assign the result to d. :: - - d=d.fromPolarToCart() - -.. note:: fromPolarToCart() generates a new instance and d now points to it. - -Assign the correct component information of d.:: - - d.setInfoOnComponents(["X [m]","Y [m]"]) - -Display the values only in form of a Python list. :: - - print(d.getValues()) - -Display d. :: - - print(d) - -Verify that for each tuple of d its norm (returned by the magnitude() method) is indeed 3 (with an error less than 1.e-12): -:: - - print(d.magnitude().isUniform(3.,1e-12)) - - -Duplication and aggregation of DataArrayDouble -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -translationToPerform contains a list of vectors of size 2. This list has length 7 (7 hexagons) Cette liste de taille 7 (7 hexagones) and describes the appropriate translation for each copy of d. - -Execute directly the following lines :: - - radius=3. - translationToPerform=[[0.,0.],[3./2.*radius,-radius*math.sqrt(3.)/2],[3./2.*radius,radius*math.sqrt(3.)/2],[0.,radius*math.sqrt(3.)],[-3./2.*radius,radius*math.sqrt(3.)/2],[-3./2.*radius,-radius*math.sqrt(3.)/2],[0.,-radius*math.sqrt(3.)]] - - -Create the len(translationToPerform) copies of d and apply the corresponding translation. :: - - ds=len(translationToPerform)*[None] - for pos,t in enumerate(translationToPerform): - ds[pos]=d[:] - ds[pos]+=t - pass - -An alternative (and more compact) way to do it : :: - - ds=[d.deepCopy() for i in list(range(len(translationToPerform)))] - for (elt,t) in zip(ds,translationToPerform) : elt+=t - -Aggregating DataArrayDouble -~~~~~~~~~~~~~~~~~~~~~~~~~~~ -From the list of DataArrayDouble instances 'ds', construct the aggregation 'd2' (a new instance of DataArrayDouble). -:: - - d2=DataArrayDouble.Aggregate(ds) - -.. note:: d2 now contains the full tuple set (6*7=42 tuples of 2 components each) which was in ds with the same order. This might sound obvious but the aggregation of meshes and fields is based on the exact same principle thus facilitating data access and indexing. This is a key difference to the MED file model, as will be seen later on. - -Find identical tuples in d2 -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -d2 contains 42 tuples but some of them are duplicated. To identify those (with a 1e-12 precision) invoke DataArrayDouble.findCommonTuples(). -Use help(DataArrayDouble.findCommonTuples) to show the prototype of the method and store the result in c and cI:: - - oldNbOfTuples=d2.getNumberOfTuples() - c,cI=d2.findCommonTuples(1e-12) - -c is an array containing all the common nodes grouped sequentially. cI contains the pointers to c allowing to identify all the nodes in a group 'i' (with 'i' in [0, 12) ). Thus the tuple ids of group 'i' start at index cI[i] in the list c, and finish at index cI[i+1]. - -.. note:: DataArrayDouble.findCommonTuples() thus returns 2 values: an array containing a list of common tuples, and an index array which is used to navigate in the first list. This is a very classical return signature in MEDCoupling and often appears when manipulating unstructured meshes. - -Manipulate DataArrayInt couple representing a pair (Data,IndexData) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The number of common tuples is len(cI)-1, i.e. 12 in our case. -Get the list of tuple ids forming the first group of common nodes and store the result in tmp. :: - - tmp=c[cI[0]:cI[0+1]] - print(tmp) - -Check the result: all the tuples stored in tmp point to identical coordinates in d2.:: - - print(d2[tmp]) - -.. note:: we see the tuple (3.,0.) repeated 3 times (with an error margin below 1e-12). - -Now we will deduce from the 3 variables oldNbOfTuples, c and cI the number of truly different tuples in d2. -To this end we compute the number of repetitions in d2 and we subtract this from oldNbOfTuples. - -To get the repetition count invoke the method DataArrayInt.deltaShiftIndex(). It returns the size of each group. -Store the result in a. :: - - a=cI.deltaShiftIndex() - -The number of repetitions in d2 for each group can now be stored in b. :: - - b=a-1 - -Finally the new count of tuples can be computed as follows. :: - - myNewNbOfTuples=oldNbOfTuples-sum(b.getValues()) - -Build old to new array from c and cI -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -c and cI define a surjective function from a starting set X containing 42 tuples (oldNbOfTuples) to a set Y containing 24 tuples (myNewNbOfTuples). - -.. image:: images/SurjectionDataArray.png - -This surjective function may also be represented thanks to an "old-2-new" array. -This storage method takes the form of a DataArrayInt 'o2n' made of Card(X) tuples (in our case 42) with one component each. For each tuple (element) indexed by i in o2n, o2n[i] contains the new tuple id in Y. - -The format 'old-2-new' is systematically used for all renumbering operations (one-to-one correspondence). - -The static method DataArrayInt.ConvertIndexArrayToO2N() performs the conversion from one storage mode to the other (c, cI to o2n). -We get for free the number of elements in Y, i.e. the variable newNbOfTuples. :: - - o2n,newNbOfTuples=DataArrayInt.ConvertIndexArrayToO2N(oldNbOfTuples,c,cI) - print("Have I got the right result? %s"%(str(myNewNbOfTuples==newNbOfTuples))) - -Using o2n and newNbOfTuples invoke DataArrayDouble.renumberAndReduce() on d2. :: - - d3=d2.renumberAndReduce(o2n,newNbOfTuples) - -This method has one drawback: we don't know for each group of common tuples in d2 what id was finally retained. -For example: in the group 0 we know that tuples 0, 8 and 16 are identical (tmp.getValues()), but we don't know which of the three has been retained in d3. - -To make this choice explicit we use the new-2-old format. This storage mode is represented by a DataArrayInt n2o containing Card(Y) tuples (in our case 24) with one component each. -For each tuple (element) with id 'i' in n2o, n2o[i] contains the tuple id which was chosen in X. - -The method DataArrayInt.invertArrayO2N2N2O() allows to switch between the two representations. -Try it on the variable o2n. :: - - n2o=o2n.invertArrayO2N2N2O(newNbOfTuples) - -Using n2o we can deduce d3_bis from d2. :: - - d3_bis=d2[n2o] - print("Have I got the right result (2)? %s"%(str(d3.isEqual(d3_bis,1e-12)))) - -Translate all tuples at once -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -All tuples (or nodes) are to be translated by the vector [3.3,4.4]. :: - - d3+=[3.3,4.4] - -Build an unstructured mesh using d3 (coordinates) and o2n -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Create an unstructured mesh m with coordinates d3. m has a mesh dimension of 2 :: - - m=MEDCouplingUMesh("My7hexagons",2) - m.setCoords(d3) - -Now allocate the number of cells with an upper bound of the actual number of cells. :: - - m.allocateCells(7) - -Finally thanks to o2n we know the connectivity of all 7 hexagons using the coordinates stored in d3. :: - - for i in list(range(7)): - m.insertNextCell(NORM_POLYGON,o2n[6*i:6*(i+1)].getValues()) - pass - -Check that m is coherent. :: - - m.checkConsistencyLight() - -To visually check m, write it in a VTU file ("My7hexagons.vtu") and display it in ParaVis. :: - - m.writeVTK("My7hexagons.vtu") - -.. note:: We write the data in VTU file, not in a MED file, because MEDCoupling doesn't use the MED file pre-requisite. Also note that although we output VTK data, MEDCoupling in itself doesn't depend on the VTK libraries. - -Solution -~~~~~~~~ - -:ref:`python_testMEDCouplingdataarray1_solution` diff --git a/doc/tutorial/medcoupling_dataarray1_fr.rst b/doc/tutorial/medcoupling_dataarray1_fr.rst deleted file mode 100644 index 8aae7375d..000000000 --- a/doc/tutorial/medcoupling_dataarray1_fr.rst +++ /dev/null @@ -1,333 +0,0 @@ - -Manipuler les DataArray ------------------------ - -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 -cellules et/ou de points. - -Le but de l'exercice -~~~~~~~~~~~~~~~~~~~~ - -Le but ici est de créer les coordonnées de 7 hexagones réguliers (tous inscrits dans des cercles de rayon 3m) en dimension 2. -La première composante du tableau de coordonnées s'appelera X avec l'unité "m" (mètre) et la 2ème composante s'appelera "Y" avec la même unité. - -On pourrait directement calculer les coordonnées de l'ensemble des points requis avec un peu de trigonométrie, mais afin de travailler un peu avec l'API, on fait le choix de construire les 7 hexagones à partir d'un seul hexagone régulier centré en [3.4; 4.4]. -Autour de cet hexagone régulier central, on crée 6 copies translatées et chaque copie partagera exactement un bord (edge) avec le motif initial. Ensuite on fusionne les noeuds (tuples) communs. Ceci nous permettra de manipuler les indirections et les méthodes d'indexing très usitées dans les maillages non structurés. - -.. image:: images/DataArrayDouble_1.jpg - :scale: 50 - -Les points traités ici : - -* Créer une instance de ``DataArrayDouble`` -* Afficher une instance de ``DataArrayDouble`` et invoquer la méthode ``getValue()`` pour la convertir en liste -* Utiliser les notations pratiques ``da[:,:]`` ... -* Apprendre la renumérotation (convention "old-2-new") -* Invoquer des services tels que ``findCommonTuples()`` - -Début de l'implémentation -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Pour commencer l'exercice importer le module Python ``medcoupling`` et l'aliaser avec ``mc`` (ca nous évitera des noms trop longs). Importer aussi le module ``math``. :: - - import medcoupling as mc - import math - -On rappelle que toutes les méthodes statiques du module commencent par une majuscule. -Avec ces imports sont disponibles : - -* toutes les classes de MEDCoupling -* tous les énumérations (par exemple, les types de cellules standard: ``mc.ON_CELLS``, ``mc.ON_NODES``, ``mc.ONE_TIME``...) -* toutes les méthodes statiques - -Créer une instance de DataArrayDouble contenant 6 tuples -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Le but ici est de créer un ``DataArrayDouble`` contenant les coordonnées d'un seul hexagone régulier. :: - - d = mc.DataArrayDouble(6,2) - -Ceci est équivalent à :: - - d = mc.DataArrayDouble() - d.alloc(6,2) - -Ceci est aussi équivalent à :: - - 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 -n'a qu'une seule composante. :: - - d_example = mc.DataArrayDouble([0.0,1.0,2.5]) - print(d_example ) - -.. note:: Le tableau ``d`` contient maintenant 12 valeurs groupées en 6 tuples contenant chacun 2 composantes. - Les valeurs dans ``d`` ne sont pas encore assignées. - -Initialiser une instance de DataArrayDouble -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Assigner la valeur 3.0 (le rayon) à la première composante de chacun des tuples. La syntaxe ressemble fortement -à celle de NumPy. On peut par exemple assigner d'un coup les tuples 1 à 3 (inclus), sur la première composante avec la valeur -3.0 :: - - d[1:4,0] = 3. - -ou directement l'intégralité de la première composante :: - - d[:,0] = 3. - -Initialiser la 2ème composante de chaque tuple i avec la valeur i. :: - - d[:,1] = list(range(6)) - -Multiplier la seconde composante de chacun des tuples par pi/3. :: - - d[:,1] *= math.pi/3. - -.. note:: ``d`` contient désormais les coordonnées polaires des noeuds de notre hexagone régulier centré en 0,0 pour le moment. - -Convertir ``d`` de polaire à cartésien en invoquant la méthode ``fromPolarToCart()`` et re-mettre le résultat dans ``d``. :: - - d = d.fromPolarToCart() - -.. note:: ``fromPolarToCart()`` génère une nouvelle instance, nous avons donc perdu le ``d`` initial - -Assigner les informations textuelles correctes sur les 2 composantes de ``d`` : :: - - d.setInfoOnComponents(["X [m]","Y [m]"]) - -.. note:: Cela n'est pas indispensable pour cet exercise, mais d'autres fonctions plus avancées nécessitent cette information. - -Afficher ``d`` tel quel. :: - - print(d) - - -Afficher juste les valeurs sous forme d'une liste python. :: - - print(d.getValues()) - - -Vérifier que pour chaque tuple désormais dans ``d``, sa norme (méthode ``magnitude()``) est bien égale à 3.0, à 1.e-12 près (méthode ``isUniform()``) :: - - print("Uniform array?", d.magnitude().isUniform(3.,1e-12)) - - -Duplication et agrégation -~~~~~~~~~~~~~~~~~~~~~~~~~ - -On construit maintenant la liste ``translationToPerform``, qui contient une liste de vecteurs chacun de taille 2. Cette liste de taille 7 (7 hexagones) contient la translation à opérer pour produire chacun des hexagones. - -Faites nous confiance sur la trigonométrie, vous pouvez copier directement les deux lignes suivantes :: - - radius = 3. - translationToPerform = [[0.,0.],[3./2.*radius,-radius*math.sqrt(3.)/2],[3./2.*radius,radius*math.sqrt(3.)/2],[0.,radius*math.sqrt(3.)],[-3./2.*radius,radius*math.sqrt(3.)/2],[-3./2.*radius,-radius*math.sqrt(3.)/2],[0.,-radius*math.sqrt(3.)]] - - -Créer les 7 copies de ``d`` et opérer la "translation" correspondante. :: - - ds = len(translationToPerform)*[None] - for pos,t in enumerate(translationToPerform): - 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*) : :: - - ds = [d + translationToPerform[i] for i in list(range(len(translationToPerform)))] - -Agrégation de tableaux -~~~~~~~~~~~~~~~~~~~~~~ - -A partir de la liste d'instances de DataArrayDouble ``ds`` construire le DataArrayDouble ``d2`` résultat de l'*agrégation* des instances les unes à la suite des autres. :: - - d2 = mc.DataArrayDouble.Aggregate(ds) - -``d2`` contient désormais l'ensemble des tuples (6*7 de 2 composantes chacun) des -instances contenues dans ``ds``, en respectant l'ordre dans ``ds``. Cela parait évident, mais -l'agrégation de maillages et de champs respecte exactement le même principe pour -faciliter l'accès et le repérage des données. C'est par exemple une différence essentielle avec le -modèle MED fichier comme on le verra plus tard. - -.. note:: La méthode permettant d'agréger par composante (c'est-à-dire de concaténer des tableaux - colonne par colonne, plutôt que par tuples) s'appelle ``Meld()``. - -Trouver les tuples égaux -~~~~~~~~~~~~~~~~~~~~~~~~ - -La variable ``d2`` contient 42 tuples mais certains tuples apparaissent plusieurs fois. -Pour trouver les tuples égaux à 1e-12 près (précision absolue) invoquer ``findCommonTuples()``. -Utiliser ``help(mc.DataArrayDouble.findCommonTuples)`` pour en connaitre l'interface. Stocker le retour de la fonction dans -``c`` et ``cI`` :: - - oldNbOfTuples = d2.getNumberOfTuples() - c,cI = d2.findCommonTuples(1e-12) - -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, -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 - 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. - - -.. _indirect-index-exo: - -Manipuler le format "indirect index" -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Le nombre de tuples communs à 1e-12 près est donc égal à ``len(cI)-1``, c'est-à-dire 12 dans notre cas. -Récupérer la liste des identifiants de tuples du groupe 0 et mettre le résultat dans la variable ``tmp``. -Afficher ``tmp``. :: - - tmp = c[cI[0]:cI[0+1]] - print(tmp) - -Vérifier, en l'affichant, que pour tous les identifiants de tuples dans ``tmp``, leurs tuples sont bien égaux dans ``d2``. :: - - print(d2[tmp]) - -.. note:: On voit que le tuple (3.,0.) à 1e-12 près est répété 3 fois et ``tmp`` donne les positions respectives de - 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 connaître le nombre de doublons, invoquer ``DataArrayInt.deltaShiftIndex`` qui retourne pour chaque groupe sa taille. -Mettre le résultat dans ``a``. :: - - a = cI.deltaShiftIndex() - -Déduire de ``a`` le nombre de tuples doublons dans ``d2`` par groupe et mettre le résultat dans ``b``. :: - - b = a-1 - -Enfin on peut trouver le nouveau nombre de tuples grâce à ``b`` et à ``oldNbOfTuples``. Mettre le résultat dans ``myNewNbOfTuples``. :: - - myNewNbOfTuples = oldNbOfTuples - sum(b.getValues()) - -Construire un tableau "old-2-new" -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -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. - -.. 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. -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 -tuples uniques (non doublons) dans l'ensemble de départ. - -.. 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) -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``. :: - - o2n, newNbOfTuples = mc.DataArrayInt.ConvertIndexArrayToO2N(oldNbOfTuples,c,cI) - print("Have I got the right number of tuples?") - 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`` -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 -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 -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 -``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()``. -Effectuer ce traitement sur la variable ``o2n``. :: - - n2o = o2n.invertArrayO2N2N2O(newNbOfTuples) - -A l'aide de ``n2o`` on peut construire un ``d3_bis`` à partir de ``d2``, et qui contient la même chose que le ``d3`` précédent. :: - - d3_bis = d2[n2o] - print("Are d3 and d3_bis equal ? %s" % (str(d3.isEqual(d3_bis, 1e-12)))) - -Translater tous les tuples -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Tous les tuples (ou nodes) sont à translater du vecteur [3.3,4.4] afin de recentrer toute la figure en ce point. :: - - d3 += [3.3,4.4] - -Constuire un maillage non structuré -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -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 :: - - m = mc.MEDCouplingUMesh("My7hexagons",2) - m.setCoords(d3) - print("Mesh dimension is", m.getMeshDimension()) - print("Spatial dimension is", m.getCoords().getNumberOfComponents()) - -Maintenant, allouer le nombre de cellules avec (un majorant du) nombre attendu de cellules. :: - - m.allocateCells(7) - -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): - cell_connec = o2n[6*i:6*(i+1)] - m.insertNextCell(mc.NORM_POLYGON, cell_connec.getValues()) - pass - -Vérifier que ``m`` est correct et ne contient pas d'anomalie. :: - - 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 ... - -Pour vérifier *visuellment* que ``m`` est correct, l'écrire dans un fichier "My7hexagons.vtu" et le visualiser dans ParaViS. :: - - m.writeVTK("My7hexagons.vtu") - -.. note:: On a écrit ici dans un fichier VTU et non MED, car MEDCoupling n'inclut pas par défaut les services de MED fichier. - Bien que l'on écrive au format VTK (\*.vtu), MEDCoupling ne dépend pas de VTK. - -Solution -~~~~~~~~ - -:ref:`python_testMEDCouplingdataarray1_solution` diff --git a/doc/tutorial/medcoupling_en.rst b/doc/tutorial/medcoupling_en.rst deleted file mode 100644 index f46e42780..000000000 --- a/doc/tutorial/medcoupling_en.rst +++ /dev/null @@ -1,19 +0,0 @@ - - -Creating, Playing with DataArrays, Meshes and Fields with the MEDCoupling library -================================================================================== - -The objective of these exercises is to learn to manipulate MEDCoupling objects in Python. - - * the first exercise shows how to manipulate DataArrayDouble objects, - * the second shows how to manipulate MEDCouplingUMesh objects, - * and the third shows how to manipulate MEDCouplingFieldDouble objects. - - -.. toctree:: - :maxdepth: 2 - - medcoupling_dataarray1_en - medcoupling_umesh1_en - medcoupling_fielddouble1_en - diff --git a/doc/tutorial/medcoupling_fielddouble1_en.rst b/doc/tutorial/medcoupling_fielddouble1_en.rst deleted file mode 100644 index 4accacd2d..000000000 --- a/doc/tutorial/medcoupling_fielddouble1_en.rst +++ /dev/null @@ -1,181 +0,0 @@ - -Playing with fields -------------------- - -In MEDCoupling fields are directly supported by a mesh. That is a major difference -with the field notion in MED file. - -Fields instances are well suited: - * for high level services where an interaction with the mesh is requested as in getValueOn(), getValueOnMulti(), integral(), normL1(), normL2(), fillFromAnalytic(), changeUnderlyingMesh(), ... - * to precisely transmit information between components when coupling codes. - -For information, the MEDCouplingFieldDouble implementation is tiny since -it delegates most of its work to MEDCouplingMesh, DataArrayDouble, MEDCouplingSpatialDiscretization classes. -MEDCouplingFieldDouble insure the coherency in this model. -It is often possible and even advised to manipulate the array and mesh of a MEDCouplingFieldDouble directly. - -Objective -~~~~~~~~~ - -This exercise focuses on the relationship between a mesh and the values of a field. - -* Create a field -* Aggregate fields -* Build parts of a field -* Renumbering a field -* Compare two fields coming from 2 sources -* Evaluation of a field on a point set -* Explode a field - -Implementation start -~~~~~~~~~~~~~~~~~~~~ - -Import the medcoupling Python module. :: - - from medcoupling import * - -We are going to create a MEDCouplingUMesh from a 3D cartesian mesh. Each direction will contain 10 cells and 11 nodes. The generated MEDCouplingUMesh -will contain 1000 cells. :: - - xarr=DataArrayDouble.New(11,1) - xarr.iota(0.) - cmesh=MEDCouplingCMesh.New() - cmesh.setCoords(xarr,xarr,xarr) - mesh=cmesh.buildUnstructured() - -In order to put the focus on mixed types, cells with an even id will be converted to polyhedrons :: - - mesh.convertToPolyTypes(DataArrayInt.Range(0,mesh.getNumberOfCells(),2)) - -Creation of a field -~~~~~~~~~~~~~~~~~~~ - -Create a field called "MyField" by application of an analytic function "(x-5.)*(x-5.)+(y-5.)*(y-5.)+(z-5.)*(z-5.)". -Two possibilities : - -* Directly by calling fillFromAnalytic on a mesh :: - - f=mesh.fillFromAnalytic(ON_CELLS,1,"(x-5.)*(x-5.)+(y-5.)*(y-5.)+(z-5.)*(z-5.)") - f.setName("MyField") - -* Or by building a new instance :: - - f2=MEDCouplingFieldDouble.New(ON_CELLS,ONE_TIME) - f2.setMesh(mesh) - f2.setName("MyField2") - f2.fillFromAnalytic(1,"(x-5.)*(x-5.)+(y-5.)*(y-5.)+(z-5.)*(z-5.)") - -Compare the two fields: -Compare f and f2 with a precision of 1e-12 on coordinates and 1e-12 on values. :: - - print("f and f2 are equal: %s"%(f.isEqualWithoutConsideringStr(f2,1e-12,1e-12))) - -Builing of a subpart of a field -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Store in ids1 the list of tuple ids whose value is within [0.0,5.0] (DataArrayDouble.findIdsInRange) . From ids1 build the sub-part fPart1 of the field "f". :: - - ids1=f.getArray().findIdsInRange(0.,5.) - fPart1=f.buildSubPart(ids1) - -.. image:: images/FieldDouble1_1.png - -Select the part "fPart2" of the field "f" whose values are in [50.,infinity). :: - - ids2=f.getArray().findIdsInRange(50.,1.e300) - fPart2=f.buildSubPart(ids2) - -Renumbering cells -~~~~~~~~~~~~~~~~~ - -The generated file "fPart1" is valid for MEDCoupling, but its cells are not sorted by geometric type: it is not valid from a MED file point of view. By using MEDCouplingUMesh.sortCellsInMEDFileFrmt and DataArrayDouble.renumberInPlace -renumber manually fPart1 starting from a deep copy of fPart1. :: - - fPart1Cpy=fPart1.deepCopy() - o2n=fPart1Cpy.getMesh().sortCellsInMEDFileFrmt() - fPart1Cpy.getArray().renumberInPlace(o2n) - -"fPart1Cpy" is now normalized to be stored in a MED file (we will tackle this later). -Check that fPart1Cpy and fPart1 are the same (discarding any permutation): :: - - fPart1Cpy.substractInPlaceDM(fPart1,12,1e-12) - fPart1Cpy.getArray().abs() - print("Fields are the same? %s"%(fPart1Cpy.getArray().accumulate()[0]<1e-12)) - -.. note:: This is in fact a very special case of interpolation. Except that here - we assume that the supports of "fPart1" and "fPart1Cpy" are equal, discarding any - cell and/or node permutation. - -Aggregate Fields -~~~~~~~~~~~~~~~~ - -Aggregate fields "fPart1" and "fPart2". The result is stored in "fPart12". :: - - fPart12=MEDCouplingFieldDouble.MergeFields([fPart1,fPart2]) - -.. image:: images/FieldDouble1_2.png - -.. note:: Apologies for the name MEDCouplingFieldDouble.MergeFields instead of - AggregateFields. - -Evaluation of a MEDCouplingFieldDouble on given space points -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Evaluate the values of the computed field "fPart12" on the barycenters of its mesh. -Evaluate the field "f" on the same barycenters. The method used is MEDCouplingFieldDouble.getValueOnMulti(). :: - - bary=fPart12.getMesh().computeCellCenterOfMass() - arr1=fPart12.getValueOnMulti(bary) - arr2=f.getValueOnMulti(bary) - delta=arr1-arr2 - delta.abs() - print("Check OK: %s"%(delta.accumulate()[0]<1e-12)) - -.. note:: In this context and for example for a field on cells, "evaluate" at a point means returning the value of the cell containing the point. -.. note:: This technique can be used to quickly assess the quality of an interpolation. - -Operations on a field -~~~~~~~~~~~~~~~~~~~~~ - -Compute the integral of the field "fPart12" and compute it a second time by using -DataArrayDouble.accumulate on the underlying DataArrayDouble of this "fPart12" (remember that the cell volumes are all 1.0). -To show the link with the underlying mesh, scale the underlying mesh (fPart12.getMesh()) by 1.2 and centered at [0.,0.,0.]. -Recompute the integral. -:: - - fPart12.integral(0,True) - fPart12.getArray().accumulate() - fPart12.getMesh().scale([0.,0.,0.],1.2) - abs(fPart12.integral(0,True)-fPart12.getArray().accumulate()[0]*1.2*1.2*1.2)<1e-8 - -Exploding a field -~~~~~~~~~~~~~~~~~ - -Starting from "mesh", create a vector field on cells "fVec" with 3 components representing the displacement between each cell's barycenter and the point [5.,5.,5.]. Use MEDCouplingMesh.fillFromAnalytic(). :: - - fVec=mesh.fillFromAnalytic(ON_CELLS,3,"(x-5.)*IVec+(y-5.)*JVec+(z-5.)*KVec") - -Create the reduction of "fVec" ("fVecPart1") on cell IDs "ids1" (previously obtained). :: - - fVecPart1=fVec.buildSubPart(ids1) - fVecPart1.setName("fVecPart1") - -Build the scalar field fPart1Exploded having the same values as "fPart1" but supported by an exploded mesh (in comparison to fPart1.getMesh()). -To explode the underlying mesh fPart1.getMesh(), use the vectorial displacement field "fVecPart1" in order to apply to each cell the proper translation. :: - - cells=fPart1.getMesh().getNumberOfCells()*[None] - for icell,vec in enumerate(fVecPart1.getArray()): - m=fPart1.getMesh()[[icell]] - m.zipCoords() # pas absolument nécessaire mais permet d'être économe en mémoire - m.translate(vec) - cells[icell]=m - pass - meshFVecPart1Exploded=MEDCouplingUMesh.MergeUMeshes(cells) - fPart1.setMesh(meshFVecPart1Exploded) - -.. image:: images/FieldDouble1_1_exploded.png - -Solution -~~~~~~~~ - -:ref:`python_testMEDCouplingfielddouble1_solution` diff --git a/doc/tutorial/medcoupling_fielddouble1_fr.rst b/doc/tutorial/medcoupling_fielddouble1_fr.rst deleted file mode 100644 index e838c8cda..000000000 --- a/doc/tutorial/medcoupling_fielddouble1_fr.rst +++ /dev/null @@ -1,246 +0,0 @@ - -Manipuler des champs de double ------------------------------- - -Les champs dans MEDCoupling ont comme support un unique maillage, de dimension fixée, et bien défini. -Cela semble trivial mais c'est en fait une différence majeure avec la notion de champ dans MED fichier, qui elle est beaucoup -plus permissive. - -Les champs sont utiles pour : - -* stocker des valeurs d'une grandeur physique relative au problème traité, mais aussi -* des services de haut niveau où l'interaction avec les maillages - est requise comme par exemple ``getValueOn()``, ``getValueOnMulti()``, ``integral()``, ``getMeasureField`` - ``normL1()``, ``normL2()``, ``fillFromAnalytic()``, ... qui calculent toutes des valeurs en lien avec le maillage - (par exemple le *volume* des cellules) -* expliciter précisément les informations échangées entre les différents codes - lors de couplage. - -Pour information, l'implémentation de ``MEDCouplingFieldDouble`` est relativement petite car cette classe -délègue la très large majorité de ses traitements à des instances de classes aggrégées -comme ``MEDCouplingMesh``, ``DataArrayDouble``, et ``MEDCouplingSpatialDiscretization``. -La classe ``MEDCouplingFieldDouble`` permet d'assurer la cohérence entre tous ces éléments. - - -Il est souvent possible et même parfois recommandé de manipuler les tableaux (un ``DataArrayDouble``) -et/ou le maillage d'une instance de ``MEDCouplingFieldDouble`` directement. - -Objectifs -~~~~~~~~~ - -Cet exercice met l'accent sur la relation entre le maillage et les valeurs d'un champ. - -* Créer un champ -* Agréger des champs -* Construire une sous-partie d'un champ -* Renuméroter les entités d'un champ -* Comparer 2 champs venant de 2 sources différentes -* Evaluation d'un champ sur un ensemble de points -* Exploser un champ - -Début de l'implementation -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Importer le module Python ``medcoupling``. :: - - import medcoupling as mc - -Créer un ``MEDCouplingUMesh`` à partir d'un maillage 3D cartésien. Chaque direction contiendra 10 cells -et 11 nodes. Le ``MEDCouplingUMesh`` résultant contiendra ainsi 1000 cells. :: - - xarr = mc.DataArrayDouble.New(11,1) - xarr.iota(0.) # Generate s, s+1, s+2, ... with a given start value s - cmesh = mc.MEDCouplingCMesh.New() - cmesh.setCoords(xarr,xarr,xarr) - mesh = cmesh.buildUnstructured() - -.. note:: La méthode ``MEDCouplingMesh.buildUnstructured()`` est très utile pour construire rapidement un maillage - non structuré afin de tester quelque chose. - -Afin de mettre en évidence le problème des types géométriques multiples, convertir en polyhèdres -les cellules d'identifiant pair :: - - mesh.convertToPolyTypes(mc.DataArrayInt.Range(0,mesh.getNumberOfCells(),2)) - - -Création d'un champ -~~~~~~~~~~~~~~~~~~~ - -Créer un champ scalaire (une seule composante) aux cellules (P0) appelé "MyField" en appliquant la fonction analytique -suivante ``(x-5.)*(x-5.)+(y-5.)*(y-5.)+(z-5.)*(z-5.)``, où ``(x, y, z)`` représente implicitement les coordonnées du barycentre -d'une cellule. -Pour cela, deux possiblités : - -* Directement en appelant ``fillFromAnalytic()`` sur un maillage :: - - f = mesh.fillFromAnalytic(mc.ON_CELLS,1,"(x-5.)*(x-5.)+(y-5.)*(y-5.)+(z-5.)*(z-5.)") # 1 means that the field should have one component - f.setName("MyField") - -* Ou en créant au préalable un champ non initialisé, et en appliquant ``fillFromAnalytic()`` sur cette - instance de ``MEDCouplingFieldDouble`` :: - - f2 = mc.MEDCouplingFieldDouble(mc.ON_CELLS, mc.ONE_TIME) - f2.setMesh(mesh) - f2.setName("MyField2") - f2.fillFromAnalytic(1,"(x-5.)*(x-5.)+(y-5.)*(y-5.)+(z-5.)*(z-5.)") # 1 means that the field should have one component - -Comparer les deux champs : comparer ``f`` et ``f2`` avec une précision de 1e-12 sur les coordonnées et -de 1e-13 sur les valeurs. :: - - print("Are f and f2 equal?", f.isEqualWithoutConsideringStr(f2,1e-12,1e-13)) - - -.. note:: Le ``WithoutConsideringStr`` dans le nom de la méthode précédente indique que les noms des champs ne seront - pas comparés. On retrouve ce suffixe dans d'autres méthodes MEDCoupling. - - -Construire une sous-partie d'un champ -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Récupérer dans une variable ``ids1`` la liste des identifiants de cellules pour lesquelles la valeur du champ est dans le -range [0.0,5.0]. Utiliser pour cela la méthode ``DataArrayDouble.findIdsInRange()``. Avec ce résultat, construire la -sous-partie ``fPart1`` du champ ``f``. :: - - da1 = f.getArray() # a DataArrayDouble, which is a direct reference (not a copy) of the field's values - ids1 = da1.findIdsInRange(0., 5.) - fPart1 = f.buildSubPart(ids1) - fPart1.writeVTK("ExoField_fPart1.vtu") - -.. image:: images/FieldDouble1_1.png - -Sélectionner la partie ``fPart2`` du champ ``f`` dont toutes les valeurs de tuples -sont dans ``[50.,+infinity)``. :: - - ids2 = f.getArray().findIdsInRange(50., 1.e300) - fPart2 = f.buildSubPart(ids2) - -Ce genre de technique permet d'extraire facilement les parties d'un champ relatives à un groupe de mailles par exemple. - -Renuméroter les entités d'un champ -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -La partie ``fPart1`` générée est valide d'un point de vue de MEDCoupling. Mais elle -n'est pas valide d'un point de vue de MED *fichier*. -Une renumérotation s'impose dans l'hypothèse de stocker ce champs dans un fichier MED afin d'ordonner les cellules -par type géométrique. - -L'idée est d'utiliser les deux méthodes ``MEDCouplingUMesh.sortCellsInMEDFileFrmt()`` et -``DataArrayDouble.renumberInPlace()`` pour renuméroter manuellement une *copie* de ``fPart1``: :: - - fPart1Cpy = fPart1.deepCopy() - o2n = fPart1Cpy.getMesh().sortCellsInMEDFileFrmt() - fPart1Cpy.getArray().renumberInPlace(o2n) - -``fPart1Cpy`` est désormais normalisé pour être stocké dans un fichier MED (ce que nous verrons plus loin) - -Vérifier que ``fPart1Cpy`` et ``fPart1`` sont les mêmes à une permutation près (``MEDCouplingFieldDouble.substractInPlaceDM()``) :: - - fPart1Cpy.substractInPlaceDM(fPart1,12,1e-12) - fPart1Cpy.getArray().abs() - print("Equal field ? %s" % (fPart1Cpy.getArray().accumulate()[0]<1e-12)) - -.. note:: La renumérotation effectuée ici représente en fait d'un cas très particulier - d'interpolation. Effectivement l'hypothèse est faite que les supports - de ``fPart1`` et ``fPart1Cpy`` sont égaux à une permutation de cellule - et/ou noeuds. - -Agréger des champs -~~~~~~~~~~~~~~~~~~ - -Agréger ``fPart1`` et ``fPart2`` (utiliser ``MEDCouplingFieldDouble.MergeFields()``). Et mettre le résultat de l'agrégation -dans ``fPart12``. :: - - fPart12 = mc.MEDCouplingFieldDouble.MergeFields([fPart1,fPart2]) - fPart12.writeVTK("ExoField_fPart12.vtu") - -.. note:: La méthode ``MEDCouplingFieldDouble.MergeFields()`` devrait vraiment se - nommer ``MEDCouplingFieldDouble.AggregateFields()`` ... - -.. image:: images/FieldDouble1_2.png - -Evaluation d'un champ en des points donnés de l'espace -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Evaluer la valeur du champ ``fPart12`` calculé précédemment sur les barycentres des cellules de son -maillage (variable ``bary``) et mettre le résultat dans ``arr1``. -Utiliser pour cela les méthodes ``MEDCouplingFieldDouble.getValueOnMulti()`` et ``MEDCouplingMesh.computeCellCenterOfMass()``. - -De manière similaire, évaluer ensuite directement le champ ``f`` en utilisant la même liste de points -que précédemment (``bary``) et mettre le résultat dans ``arr2``. - -Vérifier ensuite que ``arr1`` et ``arr2`` sont bien égaux: :: - - bary = fPart12.getMesh().computeCellCenterOfMass() - arr1 = fPart12.getValueOnMulti(bary) - arr2 = f.getValueOnMulti(bary) - delta = arr1-arr2 - delta.abs() - print("Is field evaluation matching?", (delta.accumulate()[0]<1e-12)) - -.. note:: Dans ce contexte, et pour un champ aux cellules (P0) par exemple, "évaluer" en un point signifie retourner la valeur - de la cellule contenant le point donné. - Pour les champs aux noeuds (P1), les cellules doivent être de types simples (triangles, tétraèdres) et une interpolation - linéaire est alors utilisée. - -.. note:: Cette technique peut être utilisée pour juger rapidement de la qualité d'une interpolation. - -Opérations sur les champs -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Calculer l'intégrale du champ ``fPart12`` sur le maillage, et la retrouver d'une autre manière en utilisant -la méthode ``DataArrayDouble.accumulate()`` sur le tableau de valeurs de ce champ. -On rappelle que, vu le maillage simplifié en jeu, les cellules ont toutes un volume unité. :: - - integ1 = fPart12.integral(0,True) - integ1_bis = fPart12.getArray().accumulate()[0] - print("First integral matching ?", ( abs(integ1 - integ1_bis) < 1e-8 )) - -Ensuite appliquer une homotétie de facteur 1.2 centrée en [0.,0.,0.] sur le support de ``fPart12`` (c'est-à-dire son maillage). -Quelle est alors la nouvelle valeur de l'intégrale ? :: - - fPart12.getMesh().scale([0.,0.,0.], 1.2) - integ2 = fPart12.integral(0,True) - print("Second integral matching ?", ( abs(integ2-integ1_bis*1.2*1.2*1.2) < 1e-8 )) - -Exploser un champ - Vecteurs de déplacement -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Nous allons maintenant créer un nouveau maillage représentant l'*éclaté* du maillage initial. - -Partant du maillage ``mesh`` créer un champ vectoriel aux cellules ``fVec`` ayant 3 composantes représentant -le vecteur déplacement entre le point [5.,5.,5.] et le barycentre de chaque cellule du maillage. -Utiliser la méthode ``MEDCouplingMesh.fillFromAnalytic()`` : :: - - fVec = mesh.fillFromAnalytic(mc.ON_CELLS,3,"(x-5.)*IVec+(y-5.)*JVec+(z-5.)*KVec") - -.. note:: Les identifiants spéciaux ``IVec``, ``JVec`` et ``KVec`` représentent les vecteurs unitaires du repère. - -Créer ensuite une réduction de ``fVec`` (nommée ``fVecPart1``) sur les cellules ``ids1`` précédemment obtenues : :: - - fVecPart1 = fVec.buildSubPart(ids1) - fVecPart1.setName("fVecPart1") - -Construire le champ scalaire ``fPart1Exploded`` ayant les mêmes valeurs que ``fPart1`` mais reposant sur un maillage *eclaté* -par rapport à celui de ``fPart1.getMesh()``. Pour exploser ``fPart1.getMesh()`` utiliser le champ de déplacement vectoriel -``fVecPart1`` afin d'appliquer à chaque cellule la translation associée. :: - - cells = fPart1.getMesh().getNumberOfCells() * [None] - for icell,vec in enumerate(fVecPart1.getArray()): - m = fPart1.getMesh()[[icell]] - m.zipCoords() # Not mandatory but saves memory - m.translate(vec) - cells[icell] = m - pass - meshFVecPart1Exploded = mc.MEDCouplingUMesh.MergeUMeshes(cells) - fPart1.setMesh(meshFVecPart1Exploded) - fPart1.writeVTK("ExoField_fPart1_explo.vtu") - -Et voilà ce que vous devriez obtenir: - -.. image:: images/FieldDouble1_1_exploded.png - :scale: 120 - -Solution -~~~~~~~~ - -:ref:`python_testMEDCouplingfielddouble1_solution` diff --git a/doc/tutorial/medcoupling_fr.rst b/doc/tutorial/medcoupling_fr.rst deleted file mode 100644 index 6b2f89b83..000000000 --- a/doc/tutorial/medcoupling_fr.rst +++ /dev/null @@ -1,19 +0,0 @@ - - -MEDCoupling : créer et manipuler des DataArrays, des Meshes et des Fields -========================================================================= - -L'objectif de ces exercices est d'apprendre à manipuler les objets MEDCoupling en Python. - - * La première série d'exercices montre comment manipuler des tableaux ``DataArrayDouble`` et ``DataArrayInt``. - * La deuxième série d'exercices montre comment manipuler des maillages ``MEDCouplingUMesh``. - * La troisième série d'exercices montre comment manipuler des champs ``MEDCouplingFieldDouble``. - - -.. toctree:: - :maxdepth: 2 - - medcoupling_dataarray1_fr - medcoupling_umesh1_fr - medcoupling_fielddouble1_fr - diff --git a/doc/tutorial/medcoupling_umesh1_en.rst b/doc/tutorial/medcoupling_umesh1_en.rst deleted file mode 100644 index bde6d6bec..000000000 --- a/doc/tutorial/medcoupling_umesh1_en.rst +++ /dev/null @@ -1,219 +0,0 @@ - -Playing with unstructured mesh ------------------------------- - -Unstructured meshes are the most used mesh type. MEDCouplingUMesh is the name of the class representing unstuctured meshes in MEDCoupling. MEDCouplingUMesh inherits from the MEDCouplingPointSet class that deals with all methods handling coordinates only. -MEDCouplingUMesh adds two more attributes : -* nodal connectivity -* nodal connectivity index - -Objective -~~~~~~~~~ - -The aim here is to manipulate unstructured mesh instances to extract part of an unstructured mesh. -Several points will be covered in this exercise : - -* coordinates modification of an unstructured mesh -* extraction of a slice -* build a part of a mesh given cell ids -* playing with data, index arrays - -.. image:: images/UMesh1.png - -Implementation start -~~~~~~~~~~~~~~~~~~~~ - -Import the medcoupling Python module. :: - - from medcoupling import * - -We now build a mesh containing artificially two types of cell (NORM_HEXA8 and NORM_POLYHED) to highlight the possibility to work with non-homogeneous cell types. -mesh3D is an extruded mesh containing 18 cells composed into 3 levels along Z of 6 cells. -Copy paste the following lines. :: - - coords=[0.,0.,0., 1.,1.,0., 1.,1.25,0., 1.,0.,0., 1.,1.5,0., 2.,0.,0., 2.,1.,0., 1.,2.,0., 0.,2.,0., 3.,1.,0., - 3.,2.,0., 0.,1.,0., 1.,3.,0., 2.,2.,0., 2.,3.,0., - 0.,0.,1., 1.,1.,1., 1.,1.25,1., 1.,0.,1., 1.,1.5,1., 2.,0.,1., 2.,1.,1., 1.,2.,1., 0.,2.,1., 3.,1.,1., - 3.,2.,1., 0.,1.,1., 1.,3.,1., 2.,2.,1., 2.,3.,1., - 0.,0.,2., 1.,1.,2., 1.,1.25,2., 1.,0.,2., 1.,1.5,2., 2.,0.,2., 2.,1.,2., 1.,2.,2., 0.,2.,2., 3.,1.,2., - 3.,2.,2., 0.,1.,2., 1.,3.,2., 2.,2.,2., 2.,3.,2., - 0.,0.,3., 1.,1.,3., 1.,1.25,3., 1.,0.,3., 1.,1.5,3., 2.,0.,3., 2.,1.,3., 1.,2.,3., 0.,2.,3., 3.,1.,3., - 3.,2.,3., 0.,1.,3., 1.,3.,3., 2.,2.,3., 2.,3.,3.] - conn=[0,11,1,3,15,26,16,18, 1,2,4,7,13,6,-1,1,16,21,6,-1,6,21,28,13,-1,13,7,22,28,-1,7,4,19,22,-1,4,2,17,19,-1,2,1,16,17,-1,16,21,28,22,19,17, - 1,6,5,3,16,21,20,18, 13,10,9,6,28,25,24,21, 11,8,7,4,2,1,-1,11,26,16,1,-1,1,16,17,2,-1,2,17,19,4,-1,4,19,22,7,-1,7,8,23,22,-1,8,11,26,23,-1,26,16,17,19,22,23, - 7,12,14,13,22,27,29,28, 15,26,16,18,30,41,31,33, 16,17,19,22,28,21,-1,16,31,36,21,-1,21,36,43,28,-1,28,22,37,43,-1,22,19,34,37,-1,19,17,32,34,-1,17,16,31,32,-1,31,36,43,37,34,32, - 16,21,20,18,31,36,35,33, 28,25,24,21,43,40,39,36, 26,23,22,19,17,16,-1,26,41,31,16,-1,16,31,32,17,-1,17,32,34,19,-1,19,34,37,22,-1,22,23,38,37,-1,23,26,41,38,-1,41,31,32,34,37,38, - 22,27,29,28,37,42,44,43, 30,41,31,33,45,56,46,48, 31,32,34,37,43,36,-1,31,46,51,36,-1,36,51,58,43,-1,43,37,52,58,-1,37,34,49,52,-1,34,32,47,49,-1,32,31,46,47,-1,46,51,58,52,49,47, - 31,36,35,33,46,51,50,48, 43,40,39,36,58,55,54,51, 41,38,37,34,32,31,-1,41,56,46,31,-1,31,46,47,32,-1,32,47,49,34,-1,34,49,52,37,-1,37,38,53,52,-1,38,41,56,53,-1,56,46,47,49,52,53, - 37,42,44,43,52,57,59,58] - mesh3D=MEDCouplingUMesh.New("mesh3D",3) - mesh3D.allocateCells(18) - mesh3D.insertNextCell(NORM_HEXA8,conn[0:8]); mesh3D.insertNextCell(NORM_POLYHED,conn[8:51]); mesh3D.insertNextCell(NORM_HEXA8,conn[51:59]); mesh3D.insertNextCell(NORM_HEXA8,conn[59:67]); mesh3D.insertNextCell(NORM_POLYHED,conn[67:110]); mesh3D.insertNextCell(NORM_HEXA8,conn[110:118]); - mesh3D.insertNextCell(NORM_HEXA8,conn[118:126]); mesh3D.insertNextCell(NORM_POLYHED,conn[126:169]); mesh3D.insertNextCell(NORM_HEXA8,conn[169:177]); mesh3D.insertNextCell(NORM_HEXA8,conn[177:185]); mesh3D.insertNextCell(NORM_POLYHED,conn[185:228]); mesh3D.insertNextCell(NORM_HEXA8,conn[228:236]); - mesh3D.insertNextCell(NORM_HEXA8,conn[236:244]); mesh3D.insertNextCell(NORM_POLYHED,conn[244:287]); mesh3D.insertNextCell(NORM_HEXA8,conn[287:295]); mesh3D.insertNextCell(NORM_HEXA8,conn[295:303]); mesh3D.insertNextCell(NORM_POLYHED,conn[303:346]); mesh3D.insertNextCell(NORM_HEXA8,conn[346:354]); - myCoords=DataArrayDouble.New(coords,60,3) - myCoords.setInfoOnComponents(["X [m]","Y [m]","Z [m]"]) - mesh3D.setCoords(myCoords) - mesh3D.orientCorrectlyPolyhedrons() - mesh3D.sortCellsInMEDFileFrmt() - mesh3D.checkConsistencyLight() - renum=DataArrayInt.New(60) - renum[:15] = list(range(15,30)) - renum[15:30] = list(range(15)) - renum[30:45] = list(range(45,60)) - renum[45:] = list(range(30,45)) - mesh3D.renumberNodes(renum,60) - -Convert coordinate unit from meters to centimeters -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -It might seem stupid, but this comes up regularly when coupling... :: - - mesh3D.getCoords()[:]*=100. - mesh3D.getCoords().setInfoOnComponents(["X [cm]","Y [cm]","Z [cm]"]) - -.. note:: It is important to keep the DataArrayDouble instance up-to-date about the physical units to avoid ambiguity. The INTERP_KERNEL library includes a physical unit processor. - -Find the different Z levels in mesh3D and sort in increasing order -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -DataArrayDouble.getDifferentValues and DataArrayDouble.sort can help you! :: - - zLev=mesh3D.getCoords()[:,2] - zLev=zLev.getDifferentValues(1e-12) - zLev.sort() - -Extract the 6 cells of the second row along Oz -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There are 3 possibilities to do that. We will see them from the simplest to the most complicated. - -* Using buildSlice3D: - -Simple method but a little costly. To do that simply define a plane having direction vector equal to [0.,0.,1.] and -going through point [0.,0.,(zLev[1]+zLev[2])/2]. This method retrieves 2 things : the slicemesh containing the result slicing mesh3D -and foreach 2D cell in slicemesh, the corresponding cell id into mesh3D. :: - - tmp,cellIdsSol1=mesh3D.buildSlice3D([0.,0.,(zLev[1]+zLev[2])/2],[0.,0.,1.],1e-12) - -* Using Barycenter of cells of mesh3D : - -Firstly, compute the barycenters of the 3D cells. Then select the 2nd component of the barycenter of the cells. -Finally select the tuple ids (corresponding to cell ids) falling in the range [zLev[1],zLev[2]]. :: - - bary=mesh3D.computeCellCenterOfMass() - baryZ=bary[:,2] - cellIdsSol2=baryZ.findIdsInRange(zLev[1],zLev[2]) - -* Using MEDCouplingMappedExtrudedMesh : - -This is the safest method since it only uses the nodal connectivity to compute the extrusion. The coordinates are ignored. -Two things are needed to build a MEDCouplingMappedExtrudedMesh. The 3D mesh you expect to be an extruded mesh, and a 2D mesh -lying on the same coordinates, from which the extrusion will be computed. -Let's begin with the build of the 2D mesh. We build it from all the nodes on a plane going through point [0.,0.,zLev[0]] and with normal vector [0.,0.,1.] (MEDCouplingUMesh.findNodesOnPlane()). -Then invoke MEDCouplingUMesh.buildFacePartOfMySelfNode to build mesh2D (read the documentation of buildFacePartOfMySelfNode()). :: - - nodeIds=mesh3D.findNodesOnPlane([0.,0.,zLev[0]],[0.,0.,1.],1e-10) - mesh2D=mesh3D.buildFacePartOfMySelfNode(nodeIds,True) - -Then it is possible to compute an extrusion from mesh3D and mesh2D. :: - - extMesh=MEDCouplingMappedExtrudedMesh.New(mesh3D,mesh2D,0) - -Then simply request the 2nd row. :: - - cellIdsSol3=extMesh.getMesh3DIds()[mesh2D.getNumberOfCells():2*mesh2D.getNumberOfCells()] - -It is now possible to check that the 3 solutions are the same : :: - - for i in list(range(3)): - exec("print(cellIdsSol%s.getValues())"%(i+1)) - -Extract a sub-part of mesh3D -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use the previously retrieved cell ids in cellIdsSol2 to compute a sub-part of mesh3D. :: - - mesh3DPart=mesh3D[cellIdsSol2] # equivalent to mesh3DPart=mesh3D.buildPartOfMySelf(cellIdsSol2,True) - -.. note:: The geometrical type doesn't play any role here. "mesh3DPart" now contains len(cellIdsSol2) cells. The cell #0 in "mesh3DPart" corresponds to the cell #cellIdsSol2[0] in "mesh3D" and so on ... "cellIdsSol2" can thus be seen as an array "new-to-old". - -At this point, "mesh3DPart" lies on the same coordinates, so mesh3DPart has 60 nodes whereas only 30 are necessary. To zip the orphan nodes in "mesh3DPart", simply invoke zipCoords(): :: - - mesh3DPart.zipCoords() - -At this point mesh3DPart only contains 30 nodes and 6 cells. To prepare to MED file I/O we have to check if mesh3DPart is ready to be written safely into a MED file (i.e. if the cells are indeed ordered by type). :: - - print(mesh3DPart.checkConsecutiveCellTypesAndOrder([NORM_HEXA8,NORM_POLYHED])) - -Or: :: - - print(mesh3DPart.checkConsecutiveCellTypes()) - -You can also print the content of the mesh "mesh3Dpart": :: - - print(mesh3DPart.advancedRepr()) - -We see that mesh3DPart contains 6 cells, 4 HEXA8 then 2 POLYHED. Everything's OK: the cells are grouped by geometrical type. - -Extract the 3 cells in mesh3D whose barycenters are along the line (pt=[250.,150.,0.],v=[0.,0.,1.]) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There are 2 solutions to do that. - -* using the barycenters of mesh3D again: same principle than above. :: - - baryXY=bary[:,[0,1]] - baryXY-=[250.,150.] - magn=baryXY.magnitude() - cellIds2Sol1=magn.findIdsInRange(0.,1e-12) - -* using extrusion extMesh: starting from the unique cell in mesh2D whose center is at [250.,150.,0.] MEDCouplingMappedExtrudedMesh.getMesh3DIds retrieves the cell IDs sorted by slice. :: - - bary2=mesh2D.computeCellCenterOfMass()[:,[0,1]] - bary2-=[250.,150.] - magn=bary2.magnitude() - ids=magn.findIdsInRange(0.,1e-12) - idStart=int(ids) # ids is assumed to contain only one value, if not an exception is thrown - cellIds2Sol2=extMesh.getMesh3DIds()[list(range(idStart,mesh3D.getNumberOfCells(),mesh2D.getNumberOfCells()))] - -Now, build the sub-part of mesh3D using cell IDs in cellIds2Sol1. :: - - mesh3DSlice2=mesh3D[cellIds2Sol1] - mesh3DSlice2.zipCoords() - -Duplicate "mesh3DSlice2" and translate it -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This part of the exercise shows how to perform copy and aggregation. This can be useful to build complex meshes, or to get in a single object several mesh parts coming from several processors. - -Perform a deep copy of mesh3DSlice2. On this copy perform a translation v=[0.,1000.,0.]. -Then aggregate mesh3DSlice2 with its translated copy, using MEDCouplingUMesh.MergeUMeshes. :: - - mesh3DSlice2bis=mesh3DSlice2.deepCopy() - mesh3DSlice2bis.translate([0.,1000.,0.]) - mesh3DSlice2All=MEDCouplingUMesh.MergeUMeshes([mesh3DSlice2,mesh3DSlice2bis]) - -.. note:: My apologies for the name of the method MEDCouplingUMesh.MergeUMeshes. In future version it will be called AggregateUMeshes. For information, to merge two (or more) unstructured meshes, one has to invoke MergeUMeshes(), then mergeNodes() on the result, and finally zipConnectivityTraducer(). - - -Descending connectivity -~~~~~~~~~~~~~~~~~~~~~~~ - -The aim here is to retrieve the internal faces of mesh3D. -To this purpose, we build the "descending" mesh from "mesh3D" ("mesh3Dsurf"), i.e. the mesh with mesh dimension (mesh3D.getMeshDimension()-1) made of the faces of each cell in "mesh3D". -The method MEDCoupling.buildDescendingConnectivity builds this mesh and also returns the correspondences "mesh3D" <-> "mesh3DSurf". - -A face from "mesh3DSurf" is said to be internal if and only if it is shared by more than one 3D cell in "mesh3D" (see reverse descending connectivity (out parameter 3 et 4)). :: - - mesh3DSurf,desc,descIndx,revDesc,revDescIndx=mesh3D.buildDescendingConnectivity() - numberOf3DCellSharing=revDescIndx.deltaShiftIndex() - cellIds=numberOf3DCellSharing.findIdsNotEqual(1) - mesh3DSurfInside=mesh3DSurf[cellIds] - mesh3DSurfInside.writeVTK("mesh3DSurfInside.vtu") - -.. image:: images/mesh3DSurfInside.jpg - -Solution -~~~~~~~~ - -:ref:`python_testMEDCouplingumesh1_solution` diff --git a/doc/tutorial/medcoupling_umesh1_fr.rst b/doc/tutorial/medcoupling_umesh1_fr.rst deleted file mode 100644 index 3429eefa7..000000000 --- a/doc/tutorial/medcoupling_umesh1_fr.rst +++ /dev/null @@ -1,294 +0,0 @@ - -Manipuler les maillages non structurés --------------------------------------- - -Les meshes non-structurées sont le type de maillage le plus utilisé. ``MEDCouplingUMesh`` est le nom de la classe en charge -de représenter ces maillages dans MEDCoupling. ``MEDCouplingUMesh`` hérite de la classe ``MEDCouplingPointSet``. -``MEDCouplingPointSet`` gère toutes les méthodes relatives au coordonnées. ``MEDCouplingUMesh`` a deux attributs en plus de -ceux de ``MEDCouplingPointSet`` permettant de décrire la liste des noeuds contribuants à une cellule (i.e. la *connectivité*). - -Objectifs -~~~~~~~~~ - -Le but ici est de manipuler des maillages non structurés (en extraire une partie, etc...). -Plusieurs points seront traités dans cet exercice : - -* modification des coordonnées d'un maillage -* extraction d'une coupe d'un maillage -* extraire une partie de maillage à partir d'identifiants de cellules -* manipuler les indices, etc ... -* manipulation de la connectivité descendante - -.. image:: images/UMesh1.png - :scale: 80 - -Début de l'implémentation -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Importer le module Python ``medcoupling``. :: - - import medcoupling as mc - -Construire un maillage. Ce maillage ``mesh3D`` contient artificiellement 2 types de cellules (``mc.NORM_HEXA8`` et ``mc.NORM_POLYHED``) -pour appréhender le mélange de types geometriques. -``mesh3D`` est un *maillage extrudé* contenant 18 cellules composées de 3 niveaux selon Z, chaque niveau ayant 6 cellules. -Faire un bon gros copier-coller des lignes suivantes pour construire la mesh (l'intérêt de l'exercise vient après) : :: - - coords=[0.,0.,0., 1.,1.,0., 1.,1.25,0., 1.,0.,0., 1.,1.5,0., 2.,0.,0., 2.,1.,0., 1.,2.,0., 0.,2.,0., 3.,1.,0., - 3.,2.,0., 0.,1.,0., 1.,3.,0., 2.,2.,0., 2.,3.,0., - 0.,0.,1., 1.,1.,1., 1.,1.25,1., 1.,0.,1., 1.,1.5,1., 2.,0.,1., 2.,1.,1., 1.,2.,1., 0.,2.,1., 3.,1.,1., - 3.,2.,1., 0.,1.,1., 1.,3.,1., 2.,2.,1., 2.,3.,1., - 0.,0.,2., 1.,1.,2., 1.,1.25,2., 1.,0.,2., 1.,1.5,2., 2.,0.,2., 2.,1.,2., 1.,2.,2., 0.,2.,2., 3.,1.,2., - 3.,2.,2., 0.,1.,2., 1.,3.,2., 2.,2.,2., 2.,3.,2., - 0.,0.,3., 1.,1.,3., 1.,1.25,3., 1.,0.,3., 1.,1.5,3., 2.,0.,3., 2.,1.,3., 1.,2.,3., 0.,2.,3., 3.,1.,3., - 3.,2.,3., 0.,1.,3., 1.,3.,3., 2.,2.,3., 2.,3.,3.] - conn=[0,11,1,3,15,26,16,18, 1,2,4,7,13,6,-1,1,16,21,6,-1,6,21,28,13,-1,13,7,22,28,-1,7,4,19,22,-1,4,2,17,19,-1,2,1,16,17,-1,16,21,28,22,19,17, - 1,6,5,3,16,21,20,18, 13,10,9,6,28,25,24,21, 11,8,7,4,2,1,-1,11,26,16,1,-1,1,16,17,2,-1,2,17,19,4,-1,4,19,22,7,-1,7,8,23,22,-1,8,11,26,23,-1,26,16,17,19,22,23, - 7,12,14,13,22,27,29,28, 15,26,16,18,30,41,31,33, 16,17,19,22,28,21,-1,16,31,36,21,-1,21,36,43,28,-1,28,22,37,43,-1,22,19,34,37,-1,19,17,32,34,-1,17,16,31,32,-1,31,36,43,37,34,32, - 16,21,20,18,31,36,35,33, 28,25,24,21,43,40,39,36, 26,23,22,19,17,16,-1,26,41,31,16,-1,16,31,32,17,-1,17,32,34,19,-1,19,34,37,22,-1,22,23,38,37,-1,23,26,41,38,-1,41,31,32,34,37,38, - 22,27,29,28,37,42,44,43, 30,41,31,33,45,56,46,48, 31,32,34,37,43,36,-1,31,46,51,36,-1,36,51,58,43,-1,43,37,52,58,-1,37,34,49,52,-1,34,32,47,49,-1,32,31,46,47,-1,46,51,58,52,49,47, - 31,36,35,33,46,51,50,48, 43,40,39,36,58,55,54,51, 41,38,37,34,32,31,-1,41,56,46,31,-1,31,46,47,32,-1,32,47,49,34,-1,34,49,52,37,-1,37,38,53,52,-1,38,41,56,53,-1,56,46,47,49,52,53, - 37,42,44,43,52,57,59,58] - mesh3D = mc.MEDCouplingUMesh("mesh3D",3) - mesh3D.allocateCells(18) - mesh3D.insertNextCell(mc.NORM_HEXA8,conn[0:8]); mesh3D.insertNextCell(mc.NORM_POLYHED,conn[8:51]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[51:59]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[59:67]); mesh3D.insertNextCell(mc.NORM_POLYHED,conn[67:110]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[110:118]); - mesh3D.insertNextCell(mc.NORM_HEXA8,conn[118:126]); mesh3D.insertNextCell(mc.NORM_POLYHED,conn[126:169]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[169:177]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[177:185]); mesh3D.insertNextCell(mc.NORM_POLYHED,conn[185:228]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[228:236]); - mesh3D.insertNextCell(mc.NORM_HEXA8,conn[236:244]); mesh3D.insertNextCell(mc.NORM_POLYHED,conn[244:287]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[287:295]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[295:303]); mesh3D.insertNextCell(mc.NORM_POLYHED,conn[303:346]); mesh3D.insertNextCell(mc.NORM_HEXA8,conn[346:354]); - myCoords = mc.DataArrayDouble(coords,60,3) - myCoords.setInfoOnComponents(["X [m]","Y [m]","Z [m]"]) - mesh3D.setCoords(myCoords) - mesh3D.orientCorrectlyPolyhedrons() - mesh3D.sortCellsInMEDFileFrmt() - mesh3D.checkConsistencyLight() - renum = mc.DataArrayInt(60) - renum[:15]=list(range(15,30)) - renum[15:30]=list(range(15)) - renum[30:45]=list(range(45,60)) - renum[45:]=list(range(30,45)) - mesh3D.renumberNodes(renum,60) - -Convertir les unités -~~~~~~~~~~~~~~~~~~~~ - -On convertit ici les coordonnées de mètres en centimètres. -Cela paraît idiot mais c'est un très grand classique du couplage ... :: - - mesh3D.getCoords()[:] *= 100. - mesh3D.getCoords().setInfoOnComponents(["X [cm]","Y [cm]","Z [cm]"]) - -.. note:: Il est important de mettre à jour les informations sur les composantes des coordonnées (les unités) pour éviter toute ambiguïté. - INTERP_KERNEL library inclut un évaluateur d'unité. - -.. note:: Noter l'astuce sur la première ligne ``[:]`` afin de récupérer la version inscriptible des coordonnées - (et non une copie temporaire) - -Trouver les différents niveaux -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Le maillage est extrudé, il est donc très régulier, et aligné sur les axes Ox, Oy et Oz (cf figure). -On veut connaître quelles -sont les côtes Z des différentes couches de cubes. -Extraire les différents niveaux en Z dans ``mesh3D``, rangés de manière croissante. -Utiliser la méthode ``DataArrayDouble.getDifferentValues()`` and ``DataArrayDouble.sort()``. :: - - zLev = mesh3D.getCoords()[:,2] - zLev = zLev.getDifferentValues(1e-12) - zLev.sort() # In-place sort - -Extraire des identifiants de cellules -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Extraire les 6 identifiants des cellules de la seconde rangée suivant Oz. -Il y a 3 possibilités pour faire cela. Nous allons les voir du plus simple au plus complexe. - -* En utilisant ``buildSlice3D()`` : - Méthode très simple mais gourmande en CPU. Pour trouver la solution il suffit de définir un plan dont le vecteur normal est ``[0.,0.,1.]`` - et passant par le point ``[0., 0., (zLev[1]+zLev[2])/2]``. - La méthode retourne deux choses : le maillage de coupe ``tmp`` (un maillage de mesh-dimension 2, mais de dimension spatiale - 3) et pour chaque cellule 3D surfacique de ``tmp``, l'identifiant de la cellule 3D (=un volume) coupée dans le - maillage de départ :: - - tmp, cellIdsSol1 = mesh3D.buildSlice3D([0.,0.,(zLev[1]+zLev[2])/2], [0.,0.,1.], 1e-12) - -* En utilisant les barycentres des cellules de ``mesh3D`` : - L'utilisation des barycentres est une technique classique pour identifier un ensemble de cellules répondant à certains - critères géométriques. - Il s'agit d'abord de calculer les barycentres des cellules 3D de ``mesh3D`` (méthode - ``MEDCouplingUMesh.computeCellCenterOfMass()``). - - Ensuite sélectionner la composante #2 des barycentres des cellules et mettre le résultat dans ``baryZ``. - Ensuite il suffit de selectionner dans ``baryZ`` les tuples qui sont dans l'intervalle ``[zLev[1], zLev[2]]``. - Les identifiants de ces tuples (i.e. leur index dans ``baryZ``) est directement un identifiant de cellule - car ``computeCellCenterOfMass()`` retourne un tableau indéxé par les numéros de cellule.:: - - bary = mesh3D.computeCellCenterOfMass() - baryZ = bary[:,2] - cellIdsSol2 = baryZ.findIdsInRange(zLev[1], zLev[2]) - -* En utilisant ``MEDCouplingMappedExtrudedMesh`` : - C'est la méthode exclusivement basée sur la connectivité nodale pour déduire l'extrusion. Les coordonnées sont ici ignorées. - Pour construire un ``MEDCouplingMappedExtrudedMesh`` deux objets sont requis. Le maillage non-structuré 3D - représentant en fait un maillage *extrudé*, et un maillage non structuré 3D surfacique (mesh-dim 2) - reposant sur les mêmes coordonnéees, à partir duquel l'extrusion sera calculée. - Commencer par construire le maillage 3D surfacique. Pour ce faire il suffit de repérer les noeuds appartenant - à 1e-10 près de plan de vecteur normal ``[0.,0.,1.]`` et passant - par ``[0.,0.,zLev[0]]`` (``MEDCouplingUMesh.findNodesOnPlane()``). Ensuite appeler ``MEDCouplingUMesh.buildFacePartOfMySelfNode()`` - pour construire ``mesh2D`` (lire la doc de la fonction). :: - - nodeIds = mesh3D.findNodesOnPlane([0., 0., zLev[0]], [0.,0.,1.], 1e-10) - mesh2D = mesh3D.buildFacePartOfMySelfNode(nodeIds, True) - - - Il est alors possible de construire un maillage extrudé ``extMesh`` à partir de ``mesh3D`` et de ``mesh2D``. - Un maillage extrudé se construit en *reconnaissant* un maillage non structuré comme étant l'extrusion d'un maillage - de dimension ``n-1`` (avec ``n`` la dimension initiale de ``mesh3D``, ici 3). Si cela n'est pas le cas, la construction - plante. Le maillage 2D est forcément en haut ou en bas du 3D volumique, et le dernier entier spécifie la cellule à partir - de laquelle le fil de fer 1D guidant l'extrusion sera construit : :: - - extMesh = mc.MEDCouplingMappedExtrudedMesh(mesh3D, mesh2D, 0) - - On a alors la garantie que, dans ``extMesh``, les cellules sont ordonnées par niveau Z croissant. - Il suffit de récupérer le 2ème niveau (``MEDCouplingMappedExtrudedMesh.getMesh3DIds()``). :: - - n_cells = mesh2D.getNumberOfCells() - cellIdsSol3 = extMesh.getMesh3DIds()[n_cells:2*n_cells] - -On vérifie alors que les 3 solutions sont les mêmes : :: - - print(cellIdsSol1.getValues()) - print(cellIdsSol2.getValues()) - print(cellIdsSol3.getValues()) - - -Extraire une sous partie d'un maillage 3D -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Utiliser les identifiants de cellules ``cellIdsSol2`` obtenus précédemment pour extraire une sous-partie de ``mesh3D``, -c'est-à-dire un maillage avec un sous-ensemble des cellules de ``mesh3D``. :: - - mesh3DPart = mesh3D[cellIdsSol2] - -.. note:: En C++ la méthode sous-jacente invoquée (et par ailleurs aussi disponible en Python) s'appelle - ``mesh3DPart = mesh3D.buildPartOfMySelf(cellIdsSol2,True)`` - -.. note:: Le type géométrique ne rentre pas du tout en compte ici. L'instruction précédente prend les cellules - dans l'ordre où elles sont disponibles dans le maillage initial. - -L'objet ``mesh3DPart`` contient ``len(cellIdsSol2)`` cellules désormais. La cellule #0 de ``mesh3DPart`` correspond à la cellule avec l'identifiant ``cellIdsSol2[0]`` de ``mesh3D``, et ainsi de suite. Ainsi ``cellIdsSol2`` peut être vu comme un -tableau new-2-old. - -A ce point, ``mesh3DPart`` repose sur une copie du tableau de coordonnées de ``mesh3D``, c'est-à-dire 60 nodes. -Seuls 30 sont effectivement utilisés. -Pour retirer les noeuds orphelins de ``mesh3DPart`` invoquer simplement ``MEDCouplingUMesh.zipCoords()``. :: - - mesh3DPart.zipCoords() - -Maintenant, ``mesh3DPart`` repose sur 30 nodes et possède 6 cellules. Pour être prêt aux I/O MED-fichier, il est -alors important de voir si ``mesh3DPart`` est bien ordonné, c'est-à-dire si ses cellules sont bien rangées par type géométrique. -On commence par inspecter l'état actuel : :: - - print(mesh3DPart.advancedRepr()) - -La fonction suivante fait le même travail : :: - - print(mesh3DPart.checkConsecutiveCellTypesAndOrder([mc.NORM_HEXA8, mc.NORM_POLYHED])) - -Ou bien : :: - - print(mesh3DPart.checkConsecutiveCellTypes()) - -On voit que ``mesh3DPart`` contient 6 cellules, quatre HEXA8 puis deux POLYHED. Les cellules sont bien -groupées par type géométrique. Si ce n'était pas le cas, on aurait pu invoquer ``MEDCouplingUMesh.sortCellsInMEDFileFrmt()``. - - -Extraire des cellules alignées sur une ligne 3D -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -On souhaite extraire de ``mesh3D`` les 3 cellules dont les barycentres sont le long de la ligne portée par -``v = [0.,0.,1.]`` et passant par ``pt = [250.,150.,0.]``. -Il y a deux solutions. - -* les barycentres de ``mesh3D`` : même principe qu'au-dessus. :: - - baryXY = bary[:,[0,1]] - baryXY -= [250.,150.] - magn = baryXY.magnitude() - cellIds2Sol1 = magn.findIdsInRange(0.,1e-12) - -* utiliser le maillage extrudé ``extMesh`` : partant de l'unique cellule dans ``mesh2D`` dont le centre est - en ``[250.,150.,0.]``, la méthdode ``MEDCouplingMappedExtrudedMesh.getMesh3DIds()`` retourne les identifiants de - cellules rangée par rangée. :: - - bary2 = mesh2D.computeCellCenterOfMass()[:,[0,1]] - bary2 -= [250.,150.] - magn = bary2.magnitude() - ids = magn.findIdsInRange(0.,1e-12) - idStart = int(ids) # ids is assumed to contain only one value, if not an exception is thrown - ze_range = list(range(idStart,mesh3D.getNumberOfCells(),mesh2D.getNumberOfCells())) - cellIds2Sol2 = extMesh.getMesh3DIds()[ze_range] - -Maintenant on construit cette sous partie de ``mesh3D`` en utilisant ``cellIds2Sol1`` ou ``cellIds2Sol2``: :: - - mesh3DSlice2 = mesh3D[cellIds2Sol1] - mesh3DSlice2.zipCoords() - -Duplication, translation et aggrégation de maillages -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Cette partie de l'exercice est intéressante pour construire des maillages complexes, ou pour aggréger des parties -de maillages venant de différents processeurs. - -On cherche ici à dupliquer ``mesh3DSlice2``, le translater et l'aggréger avec l'original. - -Effectuer une copie complète de ``mesh3DSlice2`` (aussi appelée *deep copy*) sous le nom ``mesh3DSlice2bis``. -Sur cette copie effectuer une translation de ``v=[0.,1000.,0.]``. -Puis aggréger ``mesh3DSlice2`` avec sa copie translatée ``mesh3DSlice2bis``, en utilisant ``MEDCouplingUMesh.MergeUMeshes()``. :: - - mesh3DSlice2bis = mesh3DSlice2.deepCopy() - mesh3DSlice2bis.translate([0.,1000.,0.]) - mesh3DSlice2All = mc.MEDCouplingUMesh.MergeUMeshes([mesh3DSlice2,mesh3DSlice2bis]) - mesh3DSlice2All.writeVTK("mesh3DSlice2All.vtu") - -.. note:: Pour information pour merger deux (ou plus) maillages non structurés, il faut invoquer ``MEDCouplingUMesh.MergeUMeshes()`` - puis ``MEDCouplingUMesh.mergeNodes()`` sur le résultat, et enfin ``MEDCouplingUMesh.zipConnectivityTraducer()``. - -.. _exo-umesh-desc-connec: - -Connectivité descendante -~~~~~~~~~~~~~~~~~~~~~~~~ - -Le but ici est de présenter la notion de *connectivité descendante* (*descending connectivity*). - -La connectivité descendante représente les éléments de dimension ``n-1`` -constituant chacune des cellules de dimension ``n`` (avec donc ``n`` la dimension du maillage, *mesh-dim*). Par exemple, pour un -maillage de dimension 3 (les cellules sont des *volumes* 3D), cela donne l'ensemble des faces (des *surfaces* 2D) bordant -ces volumes. - -A titre d'exemple, on se propose dans notre cas de récupérer les faces *internes* du maillage ``mesh3D``. -Pour cela il est nécessaire de construire le maillage -descendant de ``mesh3D`` (stocké dans ``mesh3DSurf``) c'est-à-dire -le maillage de mesh-dimension 2 (soit ``mesh3D.getMeshDimension()-1``) constitué -des *faces* bordant chacune des cellules (ici des *volumes* 3D) de ``mesh3D``. -La méthode ``MEDCoupling.buildDescendingConnectivity()`` calcule ce maillage, et retourne en même temps des tableaux -de correspondance. Ces tableaux font le lien entre les identifiants des cellules de ``mesh3D`` -vers les identifiants de cellules de ``mesh3DSurf``, et vice-et-versa. - -Une face de ``mesh3DSurf`` est dite interne, si et seulement si, elle est partagée par plus d'une cellule 3D de ``mesh3D``. -Les 3ème et 4ème paramètres de sortie de la fonction donnent le lien -entre une face et ses cellules *parentes* (i.e. le ou les volumes qu'elle délimite). -Ce lien est exprimé au format *indirect index* vu dans le premier exercice :ref:`indirect-index-exo`. :: - - mesh3DSurf, desc, descIndx, revDesc, revDescIndx = mesh3D.buildDescendingConnectivity() - numberOf3DCellSharing = revDescIndx.deltaShiftIndex() - cellIds = numberOf3DCellSharing.findIdsNotEqual(1) - mesh3DSurfInside = mesh3DSurf[cellIds] - mesh3DSurfInside.writeVTK("mesh3DSurfInside.vtu") - -Ce genre de manipulation est très utile pour accéder au voisinage d'une ou plusieurs cellules d'un maillage non-structuré. - -.. image:: images/mesh3DSurfInside.jpg - -Solution -~~~~~~~~ - -:ref:`python_testMEDCouplingumesh1_solution` diff --git a/doc/tutorial/medcouplingcorba_en.rst b/doc/tutorial/medcouplingcorba_en.rst deleted file mode 100644 index 1c1dc72da..000000000 --- a/doc/tutorial/medcouplingcorba_en.rst +++ /dev/null @@ -1,94 +0,0 @@ - -Visualize a MEDCoupling instance in ParaViS through CORBA ---------------------------------------------------------- - -ParaViS can be used to directly visualize a mesh or a field stored in memory in a Python -process. For information, this technique will become the preferred choice for the MED -Calculator in a future Salome release. -The following use cases can also be mentioned: - -* YACS, to create visualization nodes -* create a Python mock-up script and use the standard Python interpreter whilst benefiting - from the ParaViS graphical interface - -Implementation start -~~~~~~~~~~~~~~~~~~~~ - -Import the whole Python module MEDCouplingCorba. :: - - from MEDCouplingCorba import * - - -Create a 2D MEDCouplingUMesh instance -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Create a trivial unstructured mesh "m" which will be sent through CORBA to ParaViS. -:: - - arr=DataArrayDouble(11) - arr.iota(0) - m=MEDCouplingCMesh() - m.setCoords(arr,arr) - m=m.buildUnstructured() - -.. note:: "m" is unstructured but a Cartesian mesh would also work perfectly fine. - -Create a CORBA servant from "m", and turn the Python process into a CORBA server -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Invoke MEDCouplingUMeshServant._this() on "m" to turn it into a CORBA reference ("ref_m"). -:: - - ref_m=MEDCouplingUMeshServant._this(m) - -.. note:: This command doesn't only create a CORBA servant but also makes the current - Python process a full CORBA server. - -Read the identifiers that are passed to ParaViS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -What follows holds for any omniORBpy code. Display the IOR "ior" of "ref_m". -This character string is given to the ParaViS plugin (ParaMEDCorbaPlugin) to create -a new ParaViS source. -:: - - import CORBA - orb=CORBA.ORB_init() - ior=orb.object_to_string(ref_m) - print(ior) - -A simple copy/paste in the ParaViS GUI allows to create the source and to have our -mesh rendered on screen. - -Use ParaViS interactively -~~~~~~~~~~~~~~~~~~~~~~~~~ - -This section simply highlights what can be done in principle. It should be regarded -as a starting point towards the creation of more advanced scripts. -With ParaViS still up, retrieve a remote handle on ParaViS: -:: - - import PARAVIS_Gen_idl - import salome - salome.salome_init() - paravis=salome.lcc.FindOrLoadComponent("FactoryServer","PARAVIS") - -Then send a script to ParaViS so that it displays "m": -:: - - script=""" - src1 = ParaMEDCorbaPluginSource() - src1.IORCorba = '%s' - asc=GetAnimationScene() - rw=GetRenderView() - dr=Show()\ndr.Visibility = 1 - Render() - """ - content=script%(ior) - paravis.ExecuteScript(content) - - -Solution -~~~~~~~~ - -:ref:`python_testMEDCouplingcorba1_solution` diff --git a/doc/tutorial/medcouplingcorba_fr.rst b/doc/tutorial/medcouplingcorba_fr.rst deleted file mode 100644 index 6f2f7a0cf..000000000 --- a/doc/tutorial/medcouplingcorba_fr.rst +++ /dev/null @@ -1,100 +0,0 @@ - -Visualiser une instance de MEDCoupling dans ParaViS à travers CORBA -------------------------------------------------------------------- - -Il peut être intéressant de visualiser directement un maillage ou un champ en mémoire dans -un process Python avec une session de ParaViS. Cela évite d'avoir à écrire le maillage (ou le champ) sur disque. -Cette technique peut également être utilisée pour : - -* faire des noeuds de visualisation dans le module YACS -* maquetter un script Python, et profiter de l'interpreteur interactif Python tout en - bénéficiant de l'interface graphique de ParaViS. - -Nous allons pour ce faire bénéficier des mécanismes de distribution mis en oeuvre dans SALOME sur -la base du standard `CORBA `_. -SALOME utilise l'implémentation `omniORB `_ et -`omniORBPy `_ du standard. - -Début de l'implémentation -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Pour commencer l'exercice importer le module ``medcoupling`` -et la classe ``MEDCouplingUMeshServant`` du module Python ``MEDCouplingCorba``. :: - - import medcoupling as mc - from MEDCouplingCorba import MEDCouplingUMeshServant - -Créer un maillage -~~~~~~~~~~~~~~~~~ - -Le but ici est de créer un maillage ``m`` non structuré trivial qui sera envoyé par CORBA à ParaViS. :: - - arr = mc.DataArrayDouble(11) - arr.iota(0) - m = mc.MEDCouplingCMesh() - m.setCoords(arr,arr) - m = m.buildUnstructured() - -.. note:: Le maillage ``m`` est non struturé, mais s'il est cartésien ça marche aussi ! - -Créer un servant CORBA -~~~~~~~~~~~~~~~~~~~~~~ - -Nous allons maintenant créer un *servant* CORBA à partir de ``m``, et faire du process Python courant -un *serveur* CORBA. L'objet ``m`` devient ainsi disponible sur le bus CORBA et pourra être interrogé pour -la visualisation par un service distant, typiquement dans notre cas, le module ParaVis. - -Invoquer ``MEDCouplingUMeshServant._this()`` sur ``m`` pour en faire une reférence CORBA (``ref_m``).:: - - ref_m = MEDCouplingUMeshServant._this(m) - -.. note:: Cette ligne ne se contente pas de faire un servant CORBA mais fait du processus courant Python un serveur CORBA. - -Récupérer les identifiants pour ParaViS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Ce qui suit est général à tout code omniORBpy. Afficher l'IOR ``ior`` de ``ref_m`` (c'est à dire l'identifiant -unique de l'objet sur le bus CORBA) pour pouvoir passer cette chaîne de caractères au plugin ParaMEDCorbaPlugin -de ParaViS, et ainsi créer une nouvelle source dans ParaViS. :: - - import CORBA - orb = CORBA.ORB_init() - ior = orb.object_to_string(ref_m) - print(ior) - -Puis, via un copier/coller dans l'IHM ParaViS (Menu "Source -> Para MED Corba Plugin Source"), passer l'IOR. -On voit s'afficher notre maillage. - -Utiliser ParaViS en interactif -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Le but ici est juste de voir le principe. Il s'agit d'un point d'entrée pour réaliser des scripts ParaViS plus évolués. -*Tout en laissant actif ParaViS*, importer le module ``pvsimple`` qui fournit l'interface haut niveau de visualisation : :: - - import salome - salome.salome_init() - import pvsimple as pvs - -.. note:: Le module ``pvsimple`` est, à peu de choses prêt, identique au module ``paraview.simple``. - Il est juste adapté à une utilisation au sein de SALOME. Voir la formation PARAVIS à ce sujet. - -Une fois cet import réalisé, le script est automatiquement connecté au même serveur de visualisation que -l'interface graphique de SALOME (si le module PARAVIS est bien actif !). Nous pouvons donc envoyer des commandes -au serveur de visualisation pour demander l'affichage de notre objet CORBA. :: - - # We now talk to the PVServer directly - import pvsimple as pvs - pvs.Connect(url) - src1 = pvs.ParaMEDCorbaPluginSource() - src1.IORCorba = ior # This is where we need the CORBA reference of the object created - dr = pvs.Show(src1) - -.. note:: Cela correspond exactement à la manipulation précédente faite via l'interface graphique (ajout d'une nouvelle - source, saisie de l'IOR, etc ...). - -Solution -~~~~~~~~ - -Le script complet doit être exécuté avec le module PARAVIS (ou une fenêtre ParaView) actif dans l'IHM SALOME! - -:ref:`python_testMEDCouplingcorba1_solution` diff --git a/doc/tutorial/medcouplingloaderex1_en.rst b/doc/tutorial/medcouplingloaderex1_en.rst deleted file mode 100644 index 30d8097de..000000000 --- a/doc/tutorial/medcouplingloaderex1_en.rst +++ /dev/null @@ -1,161 +0,0 @@ - - -Full example 1 - Agitator -------------------------- - -The MED file :download:`agitateur.med ` is used and has the following content:ant : - -.. image:: images/agitateur.jpg - -This is the result of a simple 2-phase computation. -The agitator in green (represented by a cell field) turn on itself from one time-step -to the other. -The purpose of the exercise is to compute the torque applied on this piece.agitateur. - -Objective -~~~~~~~~~ - -The aim of this exercise is to give a full example of non-trivial post-treatment -from a MED file. - -Implementation start -~~~~~~~~~~~~~~~~~~~~ - -Import the whole Python module medcoupling. -Also import NumPy. :: - - import medcoupling as mc - import numpy as np - -Mesh and field extraction using advanced API -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Using the advanced API read the whole file "agitateur.med" and display all time-steps of -the first field. :: - - data=mc.MEDFileData("agitateur.med") - ts=data.getFields()[0].getTimeSteps() - print(ts) - -Get the agitator's mesh (in green) at the time-step (2,-1) (see ts). -To this end use the cell field "DISTANCE_INTERFACE_ELEM_BODY_ELEM_DOM" and select -only the field part having a value within [0.0, 1.0] (variable "ids"). :: - - fMts=data.getFields()["DISTANCE_INTERFACE_ELEM_BODY_ELEM_DOM"] - f1ts=fMts[(2,-1)] - fMc=f1ts.getFieldAtLevel(mc.ON_CELLS,0) - arr=fMc.getArray() - arr.getMinMaxPerComponent() # just to see the variation range of the field per component - ids=arr.findIdsInRange(0.,1.) - f2Mc=fMc[ids] - -Using the field "PRESSION_ELEM_DOM" find the 3D pression field applied on the agitator. -Store the result in pressOnAgitateur. :: - - pressMts=data.getFields()["PRESSION_ELEM_DOM"] - press1ts=pressMts[(2,-1)] - pressMc=press1ts.getFieldAtLevel(mc.ON_CELLS,0) - pressOnAgitateurMc=pressMc[ids] - -Delete unused nodes in pressOnAgitateurMc.getMesh(). :: - - pressOnAgitateurMc.getMesh().zipCoords() - -Create a 3D surface field from the 3D cell field -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Deduce the 3D field on the skin of the agitator. -To achieve this use the constituting mesh MEDCouplingUMesh.buildDescendingConnectivity(). -::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: - - agitateurMesh3DMc=pressOnAgitateurMc.getMesh() - m3DSurf,desc,descI,revDesc,revDescI=agitateurMesh3DMc.buildDescendingConnectivity() - nbOf3DCellSharing=revDescI.deltaShiftIndex() - ids2=nbOf3DCellSharing.findIdsEqual(1) - agitateurSkinMc=m3DSurf[ids2] - OffsetsOfTupleIdsInField=revDescI[ids2] - tupleIdsInField=revDesc[OffsetsOfTupleIdsInField] - pressOnSkinAgitateurMc=pressOnAgitateurMc[tupleIdsInField] - pressOnSkinAgitateurMc.setMesh(agitateurSkinMc) - -Manipulate fields -~~~~~~~~~~~~~~~~~ - -Compute the force vector field on the agitator's skin by multiplying at each cell -the pressure by the surface, and then the normal vector. -Pression is expressed in bar, convert it first to Pa. :: - - pressSkin=pressOnSkinAgitateurMc.getArray() - pressSkin*=1e5 - areaSkin=agitateurSkinMc.getMeasureField(True).getArray() - forceSkin=pressSkin*areaSkin - normalSkin=agitateurSkinMc.buildOrthogonalField().getArray() - forceVectSkin=forceSkin*normalSkin - -First computation of the torque at the center of mass of the agitator: - -Let's compute first the position of the center of mass. -Compute the polyhedron representing the 3D mesh hull of the agitator "agitateurMesh3DMc" -(use MEDCouplingUMesh.buildSpreadZonesWithPoly()). :: - - singlePolyhedron=agitateurMesh3DMc.buildSpreadZonesWithPoly() - singlePolyhedron.orientCorrectlyPolyhedrons() - centerOfMass=singlePolyhedron.computeCellCenterOfMass() - -.. note:: The call to MEDCouplingUMesh.orientCorrectlyPolyhedrons() is not mandatory - but is recommended: if the polyhedron happens to be mis-oriented, its center of mass will - be incorrect! - -Compute for each skin cell the torque with respect to the center of mass "centerOfMass". -To this end compute "posSkin", a DataArrayDouble giving for each skin cell the vector -centerOfMass -> G, where G represents the center of mass of the current cell. :: - - barySkin=agitateurSkinMc.computeCellCenterOfMass() - posSkin=barySkin-centerOfMass - -Compute the cross product for each cell of "posSkin" using "forceVectSkin" -(method DataArrayDouble.CrossProduct()). :: - - torquePerCellOnSkin=mc.DataArrayDouble.CrossProduct(posSkin,forceVectSkin) - -Sum "torqueOnSkin" using DataArrayDouble.accumulate(). :: - - zeTorque=torquePerCellOnSkin.accumulate() - print("couple = %r N.m"%(zeTorque[2])) - -Check the previously computed torque by dividing the power by the angular speed. -Compute the power per skin cell and sum it. :: - - speedMts=data.getFields()["VITESSE_ELEM_DOM"] - speed1ts=speedMts[(2,-1)] - speedMc=speed1ts.getFieldAtLevel(mc.ON_CELLS,0) - speedOnSkin=speedMc.getArray()[tupleIdsInField] - powerSkin=mc.DataArrayDouble.Dot(forceVectSkin,speedOnSkin) - power=powerSkin.accumulate()[0] - print("power = %r W"%(power)) - -Compute the angular speed: compute the sum of x^2, y^2 and xz of "posSkin" and build -with NumPy the 2x2 matrix -inertiaSkin=[[x2,xy], [xy,z2]] -Retrieve the eigen vector associated to the maximal eigen value with linalg.eig(inertiaSkin). :: - - x2=posSkin[:,0]*posSkin[:,0] ; x2=x2.accumulate()[0] - y2=posSkin[:,1]*posSkin[:,1] ; y2=y2.accumulate()[0] - xy=posSkin[:,0]*posSkin[:,1] ; xy=xy.accumulate()[0] - inertiaSkin=matrix([[x2,xy],[xy,y2]]) - inertiaSkinValues,inertiaSkinVects=linalg.eig(inertiaSkin) - pos=max(enumerate(inertiaSkinValues),key=lambda x: x[1])[0] - vect0=inertiaSkinVects[pos].tolist()[0] - print(vect0) - -Thanks to the previous computation we can see that the agitator had a rotation of -1.1183827931 radian (see solution). -Compute and compare the torque on the agitator. :: - - omega=1.1183827931/(ts[-1][2]-ts[0][2]) - print("At time-step (%d,%d) at %r s the torque is: %r N.m, power/omega=%r N.m"%(ts[2][0],ts[2][1],ts[2][2],zeTorque[2],power/omega)) - -Solution -~~~~~~~~ - -:ref:`python_testmedcouplingloaderex1_solution` diff --git a/doc/tutorial/medcouplingloaderex1_fr.rst b/doc/tutorial/medcouplingloaderex1_fr.rst deleted file mode 100644 index 9a8b01b33..000000000 --- a/doc/tutorial/medcouplingloaderex1_fr.rst +++ /dev/null @@ -1,168 +0,0 @@ - -MEDCoupling / MEDLoader - Exemple complet 1 - Agitateur -------------------------------------------------------- - -Nous partons ici d'un fichier :download:`agitateur.med ` ayant le contenu suivant : - -.. image:: images/agitateur.jpg - -Il s'agit du résultat d'un petit calcul diphasique : l'agitateur magnétique en vert (repéré seulement par un champ -aux cellules, et n'ayant *pas* de maillage propre) tourne d'un pas de temps à l'autre au -sein d'une phase liquide. Deux gouttes de liquide chutent pendant ce temps vers l'interface air/eau (en gris). - -Le but de l'exercice est de calculer le couple appliqué sur cet agitateur, qui est la pièce mécanique entraînant la -partie basse du fluide. - -Objectif -~~~~~~~~ - -L'objectif est de donner un exemple complet de post-traitement non trivial à partir d'un fichier MED. - -Début de l'implémentation -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Pour commencer l'exercice importer le module python ``medcoupling``. -Importer aussi ``numpy``. :: - - import medcoupling as mc - import numpy as np - -Extraction des maillages et champs avec l'API avancée -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Avec l'API avancée lire tout le fichier "agitateur.med" et afficher tous les pas de temps du 1er champ. :: - - data = mc.MEDFileData("agitateur.med") - ts = data.getFields()[0].getTimeSteps() - print(ts) - -Récupérer le maillage de l'agitateur (en vert) au pas de temps (2,-1) (cf. ts). -La position de l'agitateur est définie par un champ sur le maillage global du système et n'a pas de maillage propre. -Il faut donc utiliser le champ aux cellules "DISTANCE_INTERFACE_ELEM_BODY_ELEM_DOM" -et ne sélectionner que la partie du champ ayant une valeur entre dans ``[0.,1.]``. Mettre les identifiants -de cellules correspondant dans ``ids`` : :: - - fMts = data.getFields()["DISTANCE_INTERFACE_ELEM_BODY_ELEM_DOM"] - f1ts = fMts[(2,-1)] - fMc = f1ts.getFieldAtLevel(mc.ON_CELLS,0) - arr = fMc.getArray() - arr.getMinMaxPerComponent() # just to see the field variation range per component - ids = arr.findIdsInRange(0.,1.) - f2Mc = fMc[ids] - -A l'aide du champ "PRESSION_ELEM_DOM" trouver le champ de pression 3D qu'applique l'agitateur. Mettre le résultat dans -``pressOnAgitateur``. :: - - pressMts = data.getFields()["PRESSION_ELEM_DOM"] - press1ts = pressMts[(2,-1)] - pressMc = press1ts.getFieldAtLevel(mc.ON_CELLS,0) - pressOnAgitateurMc = pressMc[ids] - -Supprimer les noeuds inutiles de ``pressOnAgitateurMc.getMesh()`` : :: - - pressOnAgitateurMc.getMesh().zipCoords() - -Passer d'un champ aux cellules 3D à un champ surfacique 3D -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Deduire le champ 3D de pression sur la *peau* de l'agitateur. -Pour ce faire passer par le maillage descendant ``MEDCouplingUMesh.buildDescendingConnectivity()``. :: - - agitateurMesh3DMc = pressOnAgitateurMc.getMesh() - m3DSurf,desc,descI,revDesc,revDescI = agitateurMesh3DMc.buildDescendingConnectivity() - nbOf3DCellSharing = revDescI.deltaShiftIndex() - ids2 = nbOf3DCellSharing.findIdsEqual(1) # Cells with only one neighbor are on the boundary, i.e. on the skin - agitateurSkinMc = m3DSurf[ids2] - offsetsOfTupleIdsInField = revDescI[ids2] - tupleIdsInField = revDesc[offsetsOfTupleIdsInField] - pressOnSkinAgitateurMc = pressOnAgitateurMc[tupleIdsInField] - pressOnSkinAgitateurMc.setMesh(agitateurSkinMc) - -Manipuler les champs -~~~~~~~~~~~~~~~~~~~~ - -Calculer le champ vectoriel de force sur la peau de l'agitateur en multipliant pour chaque cellule -la pression par la surface et ensuite par le vecteur normal. -La pression est en bar, la convertir au préalable en pascal (Pa). :: - - pressSkin = pressOnSkinAgitateurMc.getArray() - pressSkin *= 1e5 # conversion from bar to Pa - areaSkin = agitateurSkinMc.getMeasureField(True).getArray() - forceSkin = pressSkin*areaSkin - normalSkin = agitateurSkinMc.buildOrthogonalField().getArray() - forceVectSkin = forceSkin*normalSkin - -Voici maintenant le premier calcul du moment au centre de masse de l'agitateur : - -Pour faire ce 1er calcul de couple exercé sur l'agitateur, calculons la position du centre de masse de l'agitateur. -Calculer le polyèdre représentant l'enveloppe du maillage 3D de l'agitateur ``agitateurMesh3DMc`` -(utiliser ``MEDCouplingUMesh.buildSpreadZonesWithPoly()``). :: - - singlePolyhedron = agitateurMesh3DMc.buildSpreadZonesWithPoly() - singlePolyhedron.orientCorrectlyPolyhedrons() - centerOfMass = singlePolyhedron.computeCellCenterOfMass() - -.. note:: L'appel à ``MEDCouplingUMesh.orientCorrectlyPolyhedrons()`` n'est pas obligatoire mais conseillé car - si par malheur le polyhèdre est mal orienté, son barycentre sera incorrect ! - -Calculer pour chaque cellule de la peau de l'agitateur le moment par rapport au centre de masse ``centerOfMass`` -de l'agitateur. -Pour ce faire calculer ``posSkin`` le ``DataArrayDouble`` donnant pour chaque cellule de la peau de l'agitateur -le vecteur ``centerOfMass`` -> ``G``, avec ``G`` le barycentre de la cellule courante. :: - - barySkin=agitateurSkinMc.computeCellCenterOfMass() - posSkin = barySkin-centerOfMass - -Appliquer maintenant la formule classique de calcul du moment : calculer le produit -vectoriel par cellule de ``posSkin`` avec ``forceVectSkin`` (méthode ``DataArrayDouble.CrossProduct()``). :: - - torquePerCellOnSkin = mc.DataArrayDouble.CrossProduct(posSkin,forceVectSkin) - -Sommer ``torqueOnSkin`` en utilisant la méthode ``DataArrayDouble.accumulate()``. :: - - zeTorque = torquePerCellOnSkin.accumulate() - print("couple = %r N.m" % zeTorque[2]) - -Vérifions le couple calculé précédemment en divisant la puissance par la vitesse *angulaire*. -La vitesse *linéaire* est stockée dans le champ "VITESSE_ELEM_DOM". - -Calculer la puissance par cellule de la peau de l'agitateur et la sommer. :: - - speedMts = data.getFields()["VITESSE_ELEM_DOM"] - speed1ts = speedMts[(2,-1)] - speedMc = speed1ts.getFieldAtLevel(mc.ON_CELLS,0) - speedOnSkin = speedMc.getArray()[tupleIdsInField] - powerSkin = mc.DataArrayDouble.Dot(forceVectSkin,speedOnSkin) - power = powerSkin.accumulate()[0] - print("power = %r W"%(power)) - -Calculer la vitesse *angulaire*. Pour ce faire, calculer la somme de ``x^2``, ``y^2`` et ``xz`` de ``posSkin`` et -construire (avec NumPy) la matrice 2x2 d'inertie ``inertiaSkin=[[x2,xy], [xy,z2]]``. - -Récupérer le vecteur propre associé à la valeur propre maximale -avec ``linalg.eig(inertiaSkin)``. :: - - x2 = posSkin[:,0]*posSkin[:,0] - x2 = x2.accumulate()[0] - y2 = posSkin[:,1]*posSkin[:,1] - y2 = y2.accumulate()[0] - xy = posSkin[:,0]*posSkin[:,1] - xy = xy.accumulate()[0] - inertiaSkin = np.matrix([[x2,xy],[xy,y2]]) - inertiaSkinValues, inertiaSkinVects = np.linalg.eig(inertiaSkin) - pos = max(enumerate(inertiaSkinValues), key=lambda x: x[1])[0] - vect0 = inertiaSkinVects[pos].tolist()[0] - print(vect0) - -Grâce au calcul précédent on peut déduire que l'agitateur a tourné de 1.1183827931 radian (cf. solution complète pour le -détail - on remet les étapes précédentes dans une fonction que l'on applique sur plusieurs pas de temps). - -Calculer et comparer le couple sur l'agitateur. :: - - omega = 1.1183827931 / (ts[-1][2]-ts[0][2]) - print("At timestep (%d,%d) (physical time=%r s) the torque is: %r N.m, power/omega=%r N.m " % (ts[2][0],ts[2][1],ts[2][2],zeTorque[2],power/omega)) - -Solution -~~~~~~~~ - -:ref:`python_testmedcouplingloaderex1_solution` diff --git a/doc/tutorial/medcouplingloaderex2_en.rst b/doc/tutorial/medcouplingloaderex2_en.rst deleted file mode 100644 index 7fde3d538..000000000 --- a/doc/tutorial/medcouplingloaderex2_en.rst +++ /dev/null @@ -1,240 +0,0 @@ - -Full example 2 - RJH --------------------- - -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. - -.. image:: images/fixm.jpg - -The 2nd file "Mobile.med" represent the mobile part. - -.. image:: images/mobm.jpg - - -Objective -~~~~~~~~~ - -The aim of this exercise is to use MEDCoupling to intersect those two meshes, assign a field to it and thus localize the zones. - - -Implementation start -~~~~~~~~~~~~~~~~~~~~ - -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 -representing the static mesh. :: - - fixe = mc.MEDFileMesh.New("Fixe.med") - fixm = fixe.getMeshAtLevel(0) - -In what follows, it is required that any two cells touching each other share the same edges. -As we are in nodal connectivity mode it means that common nodes have to merged. This is not the case here. -Merge the nodes closer than 1e-10 and assess the impact on the node count of "fixm". :: - - print("nb of nodes in file : %i"%(fixm.getNumberOfNodes())) - fixm.mergeNodes(1e-10) - print("nb of non duplicated nodes : %i"%(fixm.getNumberOfNodes())) - -Same thing for "Mobile.med" (called "mobm"). Repair it by deleting duplicated nodes. :: - - mobile = mc.MEDFileMesh.New("Mobile.med") - mobm=mobile.getMeshAtLevel(0) - mobm.mergeNodes(1e-10) - - -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 -(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). -The trick for now is to store QPOLYG in standard linear polygons and to convert them after reading. -Only "mobm" is concerned. Convert all polygonal cells in "mobm" into QPOLYG. :: - - ids = mobm.giveCellsWithType(NORM_POLYGON) - 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 -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 -neither "fixm" nor "mobm"! :: - - fixm2 = fixm.deepCopy() # tessellate2D is non const - a mesh copy is required - fixm2.tessellate2D(0.1) - fixm2.writeVTK("fixm2.vtu") - mobm2 = mobm.deepCopy() - mobm2.tessellate2D(0.1) - mobm2.writeVTK("mobm2.vtu") - -Define a small method displayVTK() which we will use later on. :: - - def displayVTK(m,fname): - tmp = m.deepCopy() - tmp.tessellate2D(0.1) - tmp.writeVTK(fname) - return - -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 -extract the first zone. -Name this new instance "zone1Mobm", remove all orphan nodes and display. :: - - zonesInMobm = mobm.partitionBySpreadZone() - print("number of zones in mobm : %i"%(len(zonesInMobm))) - zone1Mobm = mobm[zonesInMobm[0]] - zone1Mobm.zipCoords() - displayVTK(zone1Mobm,"zone1Mobm.vtu") - -.. image:: images/zone1Mobm.jpg - -From now on we work on "zone1Mobm". We will reduce the working area of "fixm" around "zone1Mobm". -To achieve this: reduce "fixm" taking only "fixm" cells located in the bounding box of "zone1Mobm" (MEDCouplingUMesh.getBoundingBox() and MEDCouplingUMesh.getCellsInBoundingBox()). -Name this object "partFixm", remove its orphan nodes and display it. :: - - ids2 = fixm.getCellsInBoundingBox(zone1Mobm.getBoundingBox(),1e-10) - partFixm = fixm[ids2] - partFixm.zipCoords() - displayVTK(partFixm,"partFixm.vtu") - -.. image:: images/partFixmAndzone1Mobm.jpg - -Geometrical intersection of the two meshes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -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 -MEDCouplingUMesh.Intersect2DMeshes(), with "partFixm" and "zone1Mobm", and use a precision -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. :: - - partFixMob,iPart,iMob = mc.MEDCouplingUMesh.Intersect2DMeshes(partFixm,zone1Mobm,1e-10) - partFixMob.mergeNodes(1e-10) - -Get and display partFixm part which is not in zone1Mobm. Call this mesh partFixmWithoutZone1Mobm. :: - - ids3 = iMob.findIdsEqual(-1) - partFixmWithoutZone1Mobm = partFixMob[ids3] - displayVTK(partFixmWithoutZone1Mobm,"partFixmWithoutZone1Mobm.vtu") - -.. image:: images/partFixmWithoutZone1Mobm.jpg - - -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 - * (check#1) the cell area sum in zone1Mobm equals the same sum on the cells in partFixMob whose cell ID different of -1 - * (check#2) for each cell in partFixm, its area equals the cell area sum in partFixMob - -Area is a algebraic value. The check can be performed only if all cells are correctly oriented or at least -all oriented consistently. -To check this let's inspect the areas of the 38 cells of partFixm (variable name "areaPartFixm"). :: - - areaPartFixm = partFixm.getMeasureField(isAbs=False).getArray() - print(areaPartFixm.getValues()) - -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. -Check then that the first test check#0 is successful :: - - areaPartFixm = partFixm.getMeasureField(isAbs=False).getArray() - areaPartFixm.abs() - areaPartFixMob = partFixMob.getMeasureField(isAbs=False).getArray() - areaPartFixMob.abs() - val1 = areaPartFixm.accumulate()[0] - val2 = areaPartFixMob.accumulate()[0] - print("Check #0 %lf == %lf a 1e-8 ? %s"%(val1,val2,str(abs(val1-val2)<1e-8))) - -Now check#1. Same spirit as in check#0. :: - - areaZone1Mobm = zone1Mobm.getMeasureField(isAbs=False).getArray() - areaZone1Mobm.abs() - val3 = areaZone1Mobm.accumulate()[0] - ids4 = iMob.findIdsNotEqual(-1) - areaPartFixMob2=areaPartFixMob[ids4] - val4 = areaPartFixMob2.accumulate()[0] - print("Check #1 %lf == %lf a 1e-8 ? %s"%(val3,val4,str(abs(val3-val4)<1e-8))) - -Finally check#2. :: - - isCheck2OK = True - for icell in list(range(partFixm.getNumberOfCells())): - ids5 = iPart.findIdsEqual(icell) - areaOfCells = areaPartFixMob[ids5] - areaOfCells.abs() - if abs(areaOfCells.accumulate()[0]-areaPartFixm[icell])>1e-9: - isCheck2OK = False - pass - pass - print("Check #2? %s"%(str(isCheck2OK))) - -Use intersection information to create fields -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -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. :: - - f = mc.MEDCouplingFieldDouble(ON_CELLS,ONE_TIME) - m = partFixMob.deepCopy() ; m.tessellate2D(0.1) - f.setMesh(m) - arr = mc.DataArrayDouble(partFixMob.getNumberOfCells(),1) - arr[iMob.findIdsEqual(-1)]=0. - arr[iMob.findIdsNotEqual(-1)]=1. - f.setArray(arr) - f.checkConsistencyLight() - f.setName("Zone") - mc.MEDCouplingFieldDouble.WriteVTK("Zone.vtu",[f]) - -.. image:: images/LocationEx2.jpg - -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. :: - - zonesMobm = mc.MEDCouplingUMesh.MergeUMeshesOnSameCoords([mobm[zonesInMobm[0]], mobm[zonesInMobm[1]], mobm[zonesInMobm[5]]]) - zonesMobm.zipCoords() - partFixMob2,iPart2,iMob2 = mc.MEDCouplingUMesh.Intersect2DMeshes(partFixm,zonesMobm,1e-10) - partFixMob2.mergeNodes(1e-10) - f2 = mc.MEDCouplingFieldDouble(ON_CELLS,ONE_TIME) - m2 = partFixMob2.deepCopy() ; m2.tessellate2D(0.1) - f2.setMesh(m2) - arr = mc.DataArrayDouble(partFixMob2.getNumberOfCells(),1) - arr[iMob2.findIdsEqual(-1)]=0. - st=0 ; end = st+len(zonesInMobm[0]) - arr[iMob2.findIdsInRange(st,end)]=1. - st += len(zonesInMobm[0]) ; end=st+len(zonesInMobm[1]) - arr[iMob2.findIdsInRange(st,end)]=2. - st += len(zonesInMobm[1]) ; end=st+len(zonesInMobm[2]) - arr[iMob2.findIdsInRange(st,end)]=3. - f2.setArray(arr) - f2.checkConsistencyLight() - f2.setName("Zone2") - mc.MEDCouplingFieldDouble.WriteVTK("Zone2.vtu",[f2]) - -.. image:: images/zonesMobm.jpg - -Solution -~~~~~~~~ - -:ref:`python_testmedcouplingloaderex2_solution` diff --git a/doc/tutorial/medcouplingloaderex2_fr.rst b/doc/tutorial/medcouplingloaderex2_fr.rst deleted file mode 100644 index d30ab343c..000000000 --- a/doc/tutorial/medcouplingloaderex2_fr.rst +++ /dev/null @@ -1,254 +0,0 @@ - -MEDCoupling / MEDLoader - Exemple complet 2 - RJH -------------------------------------------------- - -Ici nous partons de deux fichiers MED très librement inspirés du réacteur expérimental -RJH (Réacteur Jules Horowitz). - -Le premier, :download:`Fixe.med `, représente la partie statique du réacteur -sans dispositif expérimental. - -.. image:: images/fixm.jpg - :scale: 70 - -Le deuxième, :download:`Mobile.med `, représente la partie mobile. - -.. image:: images/mobm.jpg - :scale: 70 - - -Objectif -~~~~~~~~ - -Le but ici est d'utiliser MEDCoupling pour: - -* intersecter ces deux maillages, -* y mettre un champ, -* et ainsi localiser les zones de recouvrement - - -Début de l'implémentation -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Cet exercice repose comme tous les autres sur le language de script Python. On charge -le module Python ``medcoupling``.:: - - import medcoupling as mc - -Lire et réparer le maillage statique "Fixe.med" -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Avec l'API avancée lire tout le fichier "Fixe.med" et appeler ``fixm`` -l'objet de type ``MEDCouplingUMesh`` représentant le maillage statique. :: - - fixe = mc.MEDFileMesh.New("Fixe.med") - fixm = fixe.getMeshAtLevel(0) - -Pour ce qui suit il faut absolument que deux cellules se touchant partagent les mêmes edges. Pour ce faire, comme on est -en connectivité nodale, il faut absolument que les noeuds soient les mêmes. Il s'avère que cela n'est pas le cas ici. -Fusionner le noeuds distants de moins de 1e-10 et regarder l'impact sur le nombre de noeuds de ``fixm``. :: - - print("Nb of nodes in the file : %i " % (fixm.getNumberOfNodes())) - fixm.mergeNodes(1e-10) - print("Nb of non duplicated nodes : %i" % (fixm.getNumberOfNodes())) - -Même traitement pour ``Mobile.med``, le lire avec l'API avancée de MEDLoader (appeler ``mobm`` l'instance du maillage) -et le réparer en supprimant les noeuds dupliqués. :: - - mobile = mc.MEDFileMesh.New("Mobile.med") - mobm = mobile.getMeshAtLevel(0) - mobm.mergeNodes(1e-10) - -Le maillage du RJH étant plus général que des ``TRI6`` et des ``QUAD8``, on a besoin -de stocker ces cellules avec un type géométrique à ``QPOLYG`` (Quadratic Polygon) qui représente un polygone *quadratique* -(le terme n'est pas très heureux, encore des raisons historiques, ...), c'est-à-dire un polygone avec un nombre arbitraire -de côtés, et potentiellement des côtés en forme d'arcs de cercles plutôt que de segments de droites. -Ce type géométrique ``NORM_QPOLYG`` est dans MEDCoupling/MEDLoader et aussi dans MED fichier. - -Nous voudrions visualiser ces deux maillages dans PARAVIS/ParaView, mais nous rencontrons ici deux soucis: - -* les polygones non-convexes sont, par défaut, mal représentés par VTK en mode *Surface*. - Il faut sélectionner l'option avancée "Triangulate" dans le panneau Display de PARAVIS/ParaView pour avoir un rendu correct. -* les arcs de cercles ne sont pas correctement supportés par ParaView. Il faut les *tesséliser*, c'est-à-dire les transformer - en plusieurs petits segments de droite. La méthode ``MEDCouplingUMesh.tessellate2D()`` fait ce travail, mais modifie - le maillage. Nous faisons donc une copie préalable. Nous passons en paramètre la finesse de découpage (0.1 est suffisant - -- angle en radian). Attention donc à ne pas modifer ni ``fixm`` ni ``mobm`` ! :: - - fixm2 = fixm.deepCopy() # tessellate2D() modifies the current mesh - fixm2.tessellate2D(0.1) - fixm2.writeVTK("fixm2.vtu") - mobm2 = mobm.deepCopy() - mobm2.tessellate2D(0.1) - mobm2.writeVTK("mobm2.vtu") - -Faire une petite méthode ``displayVTK()``, faisant le travail qui nous servira souvent après. :: - - def displayVTK(m,fname): - tmp = m.deepCopy() - tmp.tessellate2D(0.1) - tmp.writeVTK(fname) - return - -Faire des réductions et des repérages de zones -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Le maillage ``mobm`` est en 6 parties distinctes (voir l'image au dessus). On ne veut récupérer que la première partie. -Utiliser ``MEDCouplingUMesh.partitionBySpreadZone()`` pour partitionner en zones ``mobm`` et ne prendre que la première zone. -Appeler cette nouvelle instance ``zone1Mobm`` et lui retirer tous les noeuds orphelins (``MEDCouplingUMesh.zipCoords()``) -Enfin l'afficher : :: - - zonesInMobm = mobm.partitionBySpreadZone() - print("Nb of zones in mobm : %i" % (len(zonesInMobm))) - zone1Mobm = mobm[zonesInMobm[0]] - zone1Mobm.zipCoords() - displayVTK(zone1Mobm, "zone1Mobm.vtu") - -.. image:: images/zone1Mobm.jpg - :scale: 70 - -Nous allons désormais travailler autour de ``zone1Mobm``. Nous allons réduire la zone de travail de ``fixm`` autour de ``zone1Mobm``. -Pour ce faire, réduire ``fixm`` en ne prenant que les cellules dans la boîte englobante -de ``zone1Mobm`` (``MEDCouplingUMesh.getBoundingBox()`` et ``MEDCouplingUMesh.getCellsInBoundingBox()``). -Appeler ce nouvel objet ``partFixm``, lui retirer ses noeuds orphelins et l'afficher. :: - - ids2 = fixm.getCellsInBoundingBox(zone1Mobm.getBoundingBox(),1e-10) - partFixm = fixm[ids2] - partFixm.zipCoords() - displayVTK(partFixm,"partFixm.vtu") - -.. image:: images/partFixmAndzone1Mobm.jpg - -Intersecter géométriquement deux maillages -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -C'est le coeur de l'exercice. Nous allons intersecter géométriquement ``partFixm`` et ``zone1Mobm``. Cela revient à -partitionner à minima ``partFixm`` en cellules appartenant -soit complètement à ``partFixm`` soit à ``partFixm`` et ``zone1Mobm``. Invoquer la méthode statique -``MEDCouplingUMesh.Intersect2DMeshes()``, avec ``partFixm`` et ``zone1Mobm`` et mettre une précision -de 1e-10 (seuil de détection de fusion). Cette méthode retourne 3 paramètres (voir API dans la doc) que l'on appellera -ici ``partFixMob``, ``iPart`` et ``iMob`` dans cet ordre. - -Sur ``partFixMob`` merger les noeuds à 1e-10 près. :: - - partFixMob, iPart, iMob = mc.MEDCouplingUMesh.Intersect2DMeshes(partFixm,zone1Mobm,1e-10) - partFixMob.mergeNodes(1e-10) - -Récupérer et afficher la partie de ``partFixm`` qui n'est pas dans ``zone1Mobm``. Appeler ce maillage ``partFixmWithoutZone1Mobm``. :: - - ids3 = iMob.findIdsEqual(-1) - partFixmWithoutZone1Mobm = partFixMob[ids3] - displayVTK(partFixmWithoutZone1Mobm,"partFixmWithoutZone1Mobm.vtu") - -.. image:: images/partFixmWithoutZone1Mobm.jpg - :scale: 70 - -Maintenant, on va vérifier la qualité du résultat retourné par ``MEDCouplingUMesh.Intersect2DMeshes()``. -Pour ce faire on va passer 3 tests: - - * **Check #0** la somme des aires des cellules de ``partFixm`` et égale à celle de ``partFixMob`` - * **Check #1** la somme des aires des cellules de ``zone1Mobm`` et égale à la somme des cells de ``partFixMob`` - dont l'id dans ``iMob`` est different de -1 - * **Check #2** pour chaque cellule de ``partFixm``, son aire est égale à la somme des aires des cellules de ``partFixMob`` - -L'aire est une valeur algébrique. Donc attention cette verification ne peut se faire que si les cellules -sont toutes bien orientées ou à minima toutes orientées de la même manière. -Pour ce faire, regardons les aires des 38 cellules de ``partFixm`` (nom de variable : ``areaPartFixm``). :: - - areaPartFixm = partFixm.getMeasureField(True).getArray() - print(areaPartFixm.getValues()) - -On voit que toutes les valeurs sont négatives. *Bilan*: ce fichier MED ne respecte pas la convention MED fichier ! -``partFixm`` étant mal orienté, et ``MEDCouplingUMesh.Intersect2DMeshes()`` conservant l'orientation, -``partFixMob`` est lui aussi mal orienté. -Bref, on va faire les comparaisons sur des tableaux de valeurs absolues. Vérifier alors **Check #0**. :: - - areaPartFixm = partFixm.getMeasureField(isAbs=False).getArray() # prise en compte de l'orientation des mailles - areaPartFixm.abs() - areaPartFixMob = partFixMob.getMeasureField(isAbs=False).getArray() - areaPartFixMob.abs() - val1=areaPartFixm.accumulate()[0] - val2=areaPartFixMob.accumulate()[0] - print("Check #0 %lf == %lf with precision 1e-8? %s" % (val1,val2,str(abs(val1-val2)<1e-8))) - -On peut passer au **Check #1**. L'esprit est le même que le **Check #0**. :: - - areaZone1Mobm = zone1Mobm.getMeasureField(isAbs=False).getArray() - areaZone1Mobm.abs() - val3 = areaZone1Mobm.accumulate()[0] - ids4 = iMob.findIdsNotEqual(-1) - areaPartFixMob2 = areaPartFixMob[ids4] - val4 = areaPartFixMob2.accumulate()[0] - print("Check #1 %lf == %lf with precision 1e-8 ? %s" % (val3,val4,str(abs(val3-val4)<1e-8))) - -Puis le **Check #2**. :: - - isCheck2OK = True - for icell in list(range(partFixm.getNumberOfCells())): - ids5 = iPart.findIdsEqual(icell) - areaOfCells = areaPartFixMob[ids5] - areaOfCells.abs() - if abs(areaOfCells.accumulate()[0] - areaPartFixm[icell]) > 1e-9: - isCheck2OK = False - pass - pass - print("Check #2? %s" % (str(isCheck2OK))) - -Utiliser les informations de l'intersection pour en faire des champs -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -OK pour ``partFixMob``. Nous souhaitons maintenant créer un champ représentant une fonction indicatrice de la zone - -Maintenant créer un champ aux cellules sur ``partFixMob`` en mettant 0 sur la partie -exclusive ``partFixm`` et 1 sur la partie couverte. Nous créons donc un champ représentant une fonction indicatrice. -Le visualiser en utilisant un fichier VTK (ne pas oublier l'option *Triangulate* de ParaView). :: - - f = mc.MEDCouplingFieldDouble(mc.ON_CELLS,mc.ONE_TIME) - m = partFixMob.deepCopy() - m.tessellate2D(0.1) - f.setMesh(m) - arr = mc.DataArrayDouble(partFixMob.getNumberOfCells(),1) - arr[iMob.findIdsEqual(-1)] = 0. - arr[iMob.findIdsNotEqual(-1)] = 1. - f.setArray(arr) - f.checkConsistencyLight() - f.setName("Zone") - mc.MEDCouplingFieldDouble.WriteVTK("Zone.vtu",[f]) - -.. image:: images/LocationEx2.jpg - :scale: 100 - -Plus généralement prendre les zones 0, 1 et 5. Faire un champ aux cellules qui vaut 0 dans la zone exclusivement de ``fixm``, -1 dans zone #0, 2 dans la zone #1 et finalement 3 dans la zone #5. :: - - zonesMobm = mc.MEDCouplingUMesh.MergeUMeshesOnSameCoords([mobm[zonesInMobm[0]], mobm[zonesInMobm[1]], mobm[zonesInMobm[5]]]) - zonesMobm.zipCoords() - partFixMob2,iPart2,iMob2 = mc.MEDCouplingUMesh.Intersect2DMeshes(partFixm,zonesMobm,1e-10) - partFixMob2.mergeNodes(1e-10) - f2 = mc.MEDCouplingFieldDouble(mc.ON_CELLS, mc.ONE_TIME) - m2 = partFixMob2.deepCopy() - m2.tessellate2D(0.1) - f2.setMesh(m2) - arr = mc.DataArrayDouble(partFixMob2.getNumberOfCells(),1) - arr[iMob2.findIdsEqual(-1)]=0. - st = 0 - end = st + len(zonesInMobm[0]) - arr[iMob2.findIdsInRange(st,end)] = 1. - st += len(zonesInMobm[0]) ; - end = st + len(zonesInMobm[1]) - arr[iMob2.findIdsInRange(st,end)] = 2. - st += len(zonesInMobm[1]) - end = st + len(zonesInMobm[2]) - arr[iMob2.findIdsInRange(st,end)] = 3. - f2.setArray(arr) - f2.checkConsistencyLight() - f2.setName("Zone2") - mc.MEDCouplingFieldDouble.WriteVTK("Zone2.vtu",[f2]) - -Ne pas oublier l'option *Triangulate* de ParaView dans le panneau Display pour bien voir les champs: - -.. image:: images/zonesMobm.jpg - -Solution -~~~~~~~~ - -:ref:`python_testmedcouplingloaderex2_solution` diff --git a/doc/tutorial/medcouplingmultiproc_fr.rst b/doc/tutorial/medcouplingmultiproc_fr.rst deleted file mode 100644 index 91550150f..000000000 --- a/doc/tutorial/medcouplingmultiproc_fr.rst +++ /dev/null @@ -1,116 +0,0 @@ - -MEDCoupling, multiprocessing ----------------------------- - -Cet exercice fait la supposition de Numpy Scipy sont correctement maîtrisés, sinon voir :ref:`medcouplingnumpyptr`. -On va faire simuler un traitement un peu long (ici l'interpolation d'un maillage de 64000 cells avec un autre de 64000 cells). -On va faire le traitement d'abord en séquentiel puis en parallèle pour exploiter les coeurs de notre CPU. -Nous allons utiliser le module ``multiprocessing`` pour cela. - -Début de l'implémentation -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Pour commencer l'exercice importer le module Python ``medcoupling``, ``MEDCouplingRemapper``, ``numpy``, ``scipy``, ``multiprocessing`` -et ``datetime`` pour chronométrer : :: - - import medcoupling as mc - import MEDCouplingRemapper as mr - import multiprocessing as mp - from datetime import datetime - from scipy.sparse import csr_matrix - -Créer un maillage cartésien régulier 3D avec 40 cells en X, Y et Z -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Créons un maillage cartésien 3D m de pas régulier entre 0. et 1. en X, Y et Z : :: - - nbCells=40 - arr=mc.DataArrayDouble(nbCells+1) ; arr.iota() ; arr/=nbCells - m=mc.MEDCouplingCMesh() ; m.setCoords(arr,arr,arr) - -Traduisons m en non structuré pour que le calcul soit plus long : :: - - m=m.buildUnstructured() - -Créer une copie m2 de m translatée de la moitié du pas en X, Y et Z :: - - m2=m.deepCopy() - t=mc.DataArrayDouble(3) - t[:]=1/(2*float(nbCells)) - m2.translate(t.getValues()) - -Calculer séquentiellement la matrice d'interpolation M de la projection entre m et m2 en P0P0 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -m sera considéré comme le maillage source et m2 sera considéré comme le maillage cible. -Profitons en pour chronométrer le temps necessaire pour le traitement séquentiel. -Utilisons ``MEDCouplingRemapper`` pour cela. :: - - remap=mr.MEDCouplingRemapper() - strt=datetime.now() - assert(remap.prepare(m,m2,"P0P0")==1) - print("time in sequential : %s"%(str(datetime.now()-strt))) - -Stockons la sparse matrix scipy dans ``matSeq``. :: - - matSeq=remap.getCrudeCSRMatrix() - -Calculer cette même matrice M en parallèle avec multiprocessing. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Commencons par récupérer le nombre de coeur de notre machine. :: - - nbProc=mp.cpu_count() - -L'idée est de faire une méthode ``work`` prenant un tuple de longueur 2. -Le premier élément du tuple est la partie du maillage ``m2`` considérée. Le 2eme élément donne la correspondance entre les cells id de ``m2Part`` les cells id de ``m2``. - -L'idée est d'interpoler ``m`` avec ``m2Part``. - -On récupèrera ensuite la matrice sparse ``myMat`` issue de ``m`` avec ``m2Part``. -Ensuite l'idée est de générer une matrice sparse ``mat2`` à partir de ``myMat`` avec les ids globaux de ``m2``. :: - - def work(inp): - m2Part,partToGlob=inp - myRemap=mr.MEDCouplingRemapper() - assert(myRemap.prepare(m,m2Part,"P0P0")==1) - myMat=myRemap.getCrudeCSRMatrix() - indptrnew=mc.DataArrayInt(m2.getNumberOfCells()) - indptrnew.fillWithZero() - d=mc.DataArrayInt(myMat.indptr).deltaShiftIndex() - indptrnew[partToGlob]=d - indptrnew.computeOffsetsFull() - mat2=csr_matrix( (myMat.data,myMat.indices,indptrnew.toNumPyArray()), shape=(m2.getNumberOfCells(),m.getNumberOfCells())) - return mat2 - -Il s'agit désormais de faire la liste des inputs à donner aux ``nbProc`` instances de ``work`` qui seront exécutés en parallèle. -Appelons cette liste python ``workToDo`` qui sera de longueur ``nbProc``. -On peut se faire aider de ``mc.DataArray.GetSlice``. :: - - workToDo=[] - for i in list(range(nbProc)): - s=mc.DataArray.GetSlice(slice(0,m2.getNumberOfCells(),1),i,nbProc) - part=m2[s] - partToGlob=mc.DataArrayInt.Range(s.start,s.stop,s.step) - workToDo.append((part,partToGlob)) - pass - -On est maintenant prêt pour faire travailler chacun des coeurs indépendamment. Pour ce faire, on crée un ``mp.Pool`` et on assigne à chaque worker le travail ``work`` avec autant de worker que de coeurs. Et chronométrons le tout ! :: - - - strt=datetime.now() - pool = mp.Pool() - asyncResult = pool.map_async(work,workToDo) - subMatrices = asyncResult.get() - print("time in parallel (x%d) : %s"%(nbProc,str(datetime.now()-strt))) - -.. note:: A noter la magie ! On a transféré entre le process maitre et les process esclave sans même s'en rendre compte les maillages et les DataArrayInt contenus dans ``workToDo`` ! - Merci à la pickelisation des objets MEDCoupling :) - -Vérfication -~~~~~~~~~~~ - -Vérifions que les matrices sont les mêmes ! Sommons ``subMatrices`` (``matPar``) et regardons le nombre de non zéros de la différence entre la ``matPar`` et ``matSeq``. :: - - matPar = sum(subMatrices) - matDelta=matSeq-matPar - assert(matDelta.nnz==0) diff --git a/doc/tutorial/medcouplingnumpy_en.rst b/doc/tutorial/medcouplingnumpy_en.rst deleted file mode 100644 index 3b1b37f32..000000000 --- a/doc/tutorial/medcouplingnumpy_en.rst +++ /dev/null @@ -1,190 +0,0 @@ - -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 `_ - -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 `_ - -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.findIdsEqual(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` - diff --git a/doc/tutorial/medcouplingnumpy_fr.rst b/doc/tutorial/medcouplingnumpy_fr.rst deleted file mode 100644 index e731af764..000000000 --- a/doc/tutorial/medcouplingnumpy_fr.rst +++ /dev/null @@ -1,191 +0,0 @@ -.. _medcouplingnumpyptr: - -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 `_ - -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 `_ - -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.findIdsEqual(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` - diff --git a/doc/tutorial/medcouplingremapper_en.rst b/doc/tutorial/medcouplingremapper_en.rst deleted file mode 100644 index 04bf1f49b..000000000 --- a/doc/tutorial/medcouplingremapper_en.rst +++ /dev/null @@ -1,125 +0,0 @@ - -Interpolate with MEDCouplingRemapper ------------------------------------- - -The purpose of this exercise is to interpolate between two meshes "srcMesh" and "trgMesh". -To make the reader aware of some subtleties about interpolation, a special case -is considered: "srcMesh" is a refinement of "trgMesh". - - -Implementation start -~~~~~~~~~~~~~~~~~~~~ - -To start the exercise import the whole Python module MEDCouplingRemapper. :: - - from MEDCouplingRemapper import * - - -Create a MEDCouplingUMesh 2D instance, built from a Cartesian mesh -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Build the unstructured mesh "trgMesh" from a 2D Cartesian mesh with 10x10 cells, -starting at point [0.,0.] and having a step of 1.0 along the X and Y directions. -:: - - arr=DataArrayDouble(11) ; arr.iota(0) - trgMesh=MEDCouplingCMesh() ; trgMesh.setCoords(arr,arr) ; trgMesh=trgMesh.buildUnstructured() - -Create the source mesh "srcMesh" -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Create a mesh "srcMesh" from a 2D Cartesian mesh having 20x20 cells and starting -at point [0.,0.] with a step of 0.5 along the X and Y directions. -:: - - arr=DataArrayDouble(21) ; arr.iota(0) ; arr*=0.5 - srcMesh=MEDCouplingCMesh() ; srcMesh.setCoords(arr,arr) ; srcMesh=srcMesh.buildUnstructured() - -Triangulate the 20 first cells of source mesh (using MEDCouplingUMesh.simplexize()). -Store the result in "srcMesh". -:: - - tmp=srcMesh[:20] ; tmp.simplexize(0) - srcMesh=MEDCouplingUMesh.MergeUMeshes([tmp,srcMesh[20:]]) - -Interpolate using MEDCouplingRemapper -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Compute the first part of the interpolation matrix with the following considerations: -"srcMesh" is regarded as a discretization at cell points, and so is "trgMesh". -To this end invoke prepare() on an instance of the MEDCouplingRemapper class ("remap"). -:: - - remap=MEDCouplingRemapper() - remap.prepare(srcMesh,trgMesh,"P0P0") - -Check that the computed matrix is correct in this trivial case: get the internal -interpolation matrix by calling MEDCouplingRemapper.getCrudeMatrix() and save it in -"myMatrix". This matrix gives for each cell in "trgMesh" the cell IDs of "srcMesh" -which are intersecting the target and the area of intersection. Check that for each -cell in "trgMesh" the sum of the areas is always equal to 1.0. -:: - - myMatrix=remap.getCrudeMatrix() - print(myMatrix) # to see what it looks like - sumByRows=DataArrayDouble(len(myMatrix)) - for i,wIt in enumerate(sumByRows): - su=0. - for it in myMatrix[i]: - su+=myMatrix[i][it] - wIt[0]=su - print("Does interpolation look OK? %s"%(str(sumByRows.isUniform(1.,1e-12)))) - -.. note:: Some triangles were added into "srcMesh" to make "myMatrix" less boring. "myMatrix". - -Create a field at cell points "srcField" built from the following analytical formula: -"7-sqrt((x-5.)*(x-5.)+(y-5.)*(y-5.))" where x and y represent the usual space coordinates. -:: - - srcField=MEDCouplingFieldDouble(ON_CELLS,ONE_TIME) ; srcField.setMesh(srcMesh) - srcField.fillFromAnalytic(1,"7-sqrt((x-5.)*(x-5.)+(y-5.)*(y-5.))") ; srcField.getArray().setInfoOnComponent(0,"powercell [W]") - -.. image:: images/Remapper1.png - -Apply the interpolation using MEDCouplingRemapper.transferField(): :: - - remap.transferField(srcField,1e300) - -.. note:: 1e300 is a default value. It will be systematically assigned to all cells - in "trgField" which do not intersect any cell in "srcMesh". The common usage is to assign - a huge value to identify what is often considered as a bug. But some other use cases - indicate using 0 here, e.g. when considering a parallel interpolation merged ultimately - with an addition. - -.. note:: An exception is raised since "srcField" hasn't got an explicitly defined nature. - In what follows the impact of this attribute on the final result will be explained. - -Set the nature of "srcField" to IntensiveMaximum (intensive field, e.g. a temperature). :: - - srcField.setNature(IntensiveMaximum) - trgFieldCV=remap.transferField(srcField,1e300) - -Check that with this nature the field integral is conserved. On the other side -the sum on cells (accumulation) is NOT conserved. :: - - print("IntensiveMaximum %lf == %lf"%(srcField.integral(True)[0],trgFieldCV.integral(True)[0])) - print("IntensiveMaximum %lf != %lf"%(srcField.getArray().accumulate()[0],trgFieldCV.getArray().accumulate()[0])) - -Set the nature of "srcField" to ExtensiveConservation (extensive field, e.g. a power). :: - - srcField.setNature(ExtensiveConservation) - trgFieldI=remap.transferField(srcField,1e300) - -Check that given this nature the field integral is NOT conserved. On the other side the -cumulative sum on cells is conserved. :: -:: - - print("ExtensiveConservation %lf != %lf"%(srcField.integral(True)[0],trgFieldI.integral(True)[0])) - print("ExtensiveConservation %lf == %lf"%(srcField.getArray().accumulate()[0],trgFieldI.getArray().accumulate()[0])) - -Visualize the fields using ParaViS. - -Solution -~~~~~~~~ - -:ref:`python_testMEDCouplingremapper1_solution` diff --git a/doc/tutorial/medcouplingremapper_fr.rst b/doc/tutorial/medcouplingremapper_fr.rst deleted file mode 100644 index f9ae92862..000000000 --- a/doc/tutorial/medcouplingremapper_fr.rst +++ /dev/null @@ -1,150 +0,0 @@ - -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` diff --git a/doc/tutorial/medloader_SplitAndMerge1_en.rst b/doc/tutorial/medloader_SplitAndMerge1_en.rst deleted file mode 100644 index dc01c2a89..000000000 --- a/doc/tutorial/medloader_SplitAndMerge1_en.rst +++ /dev/null @@ -1,196 +0,0 @@ - -Splitting and merging a MED file using MEDLoader's advanced API ---------------------------------------------------------------- - -Objective -~~~~~~~~~ - -The aim of this exercise is to create a mesh with mixed geometrical type from scratch, and to associate two fields to it: - -* a field on cells "CellField" -* a field on nodes "NodeField" - - -Implementation start -~~~~~~~~~~~~~~~~~~~~ - -Create an unstructured mesh "m0" built from a 30x30 structured mesh (meshDim=2, spaceDim=2). -Each of the even cell of "m0" is "simplexized" (cut in triangles - method MEDCouplingUMesh.simplexize(0)) :: - - import medcoupling as mc - - m0 = mc.MEDCouplingCMesh() - arr = mc.DataArrayDouble(31,1) ; arr.iota(0.) - m0.setCoords(arr,arr) - m0 = m0.buildUnstructured() - m00 = m0[::2] # Extract even cells - m00.simplexize(0) - m01 = m0[1::2] - m0 = mc.MEDCouplingUMesh.MergeUMeshes([m00,m01]) - m0.getCoords()[:] *= 1/15. # Illustrate how to quickly rescale a mesh - m0.setName("mesh") - -.. note:: The call to setName() on "m0" is mandatory. Don't forget that the correct naming of the meshes is paramount in the MED file context. - -Create the fields "CellField" and "NodeField" at the time-stamp (5,6) corresponding to 5.6s. -:: - - # Cell field - cellField = mc.MEDCouplingFieldDouble(mc.ON_CELLS, mc.ONE_TIME) - cellField.setTime(5.6,5,6) - cellField.setMesh(m0) - cellField.setName("CellField") - cellField.fillFromAnalytic(1,"exp(-((x-1)*(x-1)+(y-1)*(y-1)))") - cellField.getArray().setInfoOnComponent(0,"powercell [W]") - # Node field - nodeField = mc.MEDCouplingFieldDouble(mc.ON_NODES,mc.ONE_TIME) - nodeField.setTime(5.6,5,6) - nodeField.setMesh(m0) - nodeField.setName("NodeField") - nodeField.fillFromAnalytic(1,"exp(-((x-1)*(x-1)+(y-1)*(y-1)))") - nodeField.getArray().setInfoOnComponent(0,"powernode [W]") - -"CellField" looks like this: - -.. image:: images/SplitAndMergeCell1.jpg - - -Mesh partitionning -~~~~~~~~~~~~~~~~~~ - -Cut "m0" into two distinct parts called "proc0" and "proc1". "proc0" will be contained in the bounding box [(0.,0.4),(0.,0.4)] (with a precision of 1e-10). Use the method MEDCouplingUMesh.getCellsInBoundingBox(). "proc1" is simply the complementary part of "proc0" (method DataArrayInt.buildComplement()). -:: - - proc0 = m0.getCellsInBoundingBox([(0.,0.4),(0.,0.4)],1e-10) - proc1 = proc0.buildComplement(m0.getNumberOfCells()) - -.. image:: images/SplitAndMerge2.jpg - -Writing into two different MED files -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Starting with the partition above ("proc0" and "proc1") create two MED files called "proc0.med" et "proc1.med". :: - - nodeField0 = nodeField[proc0] ; cellField0 = cellField[proc0] ; cellField0.setMesh(nodeField0.getMesh()) - nodeField1 = nodeField[proc1] ; cellField1 = cellField[proc1] ; cellField1.setMesh(nodeField1.getMesh()) - - proc0_fname = "proc0.med" - mc.WriteField(proc0_fname, nodeField0, True) - mc.WriteFieldUsingAlreadyWrittenMesh(proc0_fname, cellField0) - - proc1_fname = "proc1.med" - mc.WriteField(proc1_fname,nodeField1,True) - mc.WriteFieldUsingAlreadyWrittenMesh(proc1_fname,cellField1) - -Reading and merging 2 MED files - Easy (but non optimal) version -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In the two files "proc0.med" and "proc1.med" read the respective "CellField" with the basic API. Aggregate the two and store the result in "CellField_read". :: - - cellField0_read = mc.ReadFieldCell("proc0.med","mesh",0,"CellField",5,6) - cellField1_read = mc.ReadFieldCell("proc1.med","mesh",0,"CellField",5,6) - cellField_read = mc.MEDCouplingFieldDouble.MergeFields([cellField0_read,cellField1_read]) - -.. note:: It might seem to the reader that the cell type information is repeated uselessly, but don't forget that the MED file norm doesn't forbid a field to be defined simultaneously on nodes and on Gauss points for example ... - -Compare "CellField_read" and "CellField0". Problem: because of the constraint on the MED file numbering, the initial numbering has been lost. Or more exactly there is no standard way to retrieve it. This means that a call to MEDCouplingFieldDouble.isEqual() won't succeed. Let's use the method MEDCouplingFieldDouble.substractInPlaceDM() which operates a renumbering based on a given policy (see HTML doc). -To this end, create a deep copy of "CellField" into "CellFieldCpy" and invoke substractInPlaceDM() on it (DM stands for "Different Meshes", contrarily to substract() which only succeeds if the fields share the same mesh). :: - - cellFieldCpy = cellField.deepCopy() - cellFieldCpy.substractInPlaceDM(cellField_read,10,1e-12) - cellFieldCpy.getArray().abs() - print(cellFieldCpy.getArray().isUniform(0.,1e-12)) - -Let's do the same on "NodeField". The main difference here is that redundant information is created at the boundary. :: - - nodeField0_read = mc.ReadFieldNode("proc0.med","mesh",0,"NodeField",5,6) - nodeField1_read = mc.ReadFieldNode("proc1.med","mesh",0,"NodeField",5,6) - nodeField_read = mc.MEDCouplingFieldDouble.MergeFields([nodeField0_read, nodeField1_read]) - -.. note:: The mesh is read a second time here, which can be damaging in terms of performance. - -Invoke MEDCouplingUMesh.mergeNodes() on "NodeField_read" to remove duplicate nodes. -Make a deep copy called "NodeFieldCpy" from "NodeField" and call MEDCouplingUMesh.mergeNodes(). :: - - nodeField_read.mergeNodes(1e-10) - nodeFieldCpy = nodeField.deepCopy() - nodeFieldCpy.mergeNodes(1e-10) - -.. note:: mergeNodes() takes two epsilons: the first classical one on the absolute distance between nodes, and the second expressing a tolerance on the values. If the field value of two nodes to be merged is bigger than this an exception is raised. - -Compare "NodeFieldCpy" and "NodeField_read" still using MEDCouplingFieldDouble.substractInPlaceDM(). :: - - nodeFieldCpy.substractInPlaceDM(nodeField_read,10,1e-12) - print(nodeFieldCpy.getArray().isUniform(0.,1e-12)) - - -Read/write of two separated MED files - More complex but more efficient version -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -We show a more systematic and more general method to merge files. -This is the preferred route when dealing with big files . -This method adds performance but also allows to add extra information. - -Using the advanced API read the meshes of two files "proc0.med" and "proc1.med" and aggregate the result in an MEDFileUMesh instance "mergeMLMesh". -Handle all the levels (even if there is only one in the present case) using the method -MEDFileUMesh.getNonEmptyLevels() on the instance coming from "proc0.med". :: - - fileNames = ["proc0.med","proc1.med"] - msML = [mc.MEDFileMesh.New(fname) for fname in fileNames] - fsML = [mc.MEDFileFields.New(fname) for fname in fileNames] - mergeMLMesh = mc.MEDFileUMesh() - mergeMLFields = mc.MEDFileFields() - for lev in msML[0].getNonEmptyLevels(): - o2nML = len(msML[0].getNonEmptyLevels())*[None] - cs = [mML.getCoords() for mML in msML] - mergeMLMesh.setCoords(mc.DataArrayDouble.Aggregate(cs)) - ms = [mML.getMeshAtLevel(lev) for mML in msML] - m = mc.MEDCouplingUMesh.MergeUMeshes(ms) ; m.setCoords(mergeMLMesh.getCoords()) - o2nML[lev] = m.sortCellsInMEDFileFrmt() - mergeMLMesh.setMeshAtLevel(lev,m) - pass - - for fieldName in fsML[0].getFieldsNames(): - fmts = [fML[fieldName] for fML in fsML] - mergeField = mc.MEDFileFieldMultiTS() - for dt,it,tim in fmts[0].getTimeSteps(): - fts = [fmt[dt,it] for fmt in fmts] - arrs = len(fts)*[None] - for typp in fts[0].getTypesOfFieldAvailable(): - arr1s = [] - if typp == mc.ON_CELLS: - for ft in fts: - for geoTyp,smth in ft.getFieldSplitedByType(): - if geoTyp != mc.NORM_ERROR: - smth1 = filter(lambda x:x[0] == mc.ON_CELLS,smth) - arr2s = [ft.getUndergroundDataArray()[elt[1][0]:elt[1][1]] for elt in smth1] - arr1s.append(mc.DataArrayDouble.Aggregate(arr2s)) - pass - pass - pass - pass - else: - for ft in fts: - smth = filter(lambda x:x[0] == mc.NORM_ERROR,ft.getFieldSplitedByType()) - arr2 = mc.DataArrayDouble.Aggregate([ft.getUndergroundDataArray()[elt[1][0][1][0]:elt[1][0][1][1]] for elt in smth]) - arr1s.append(arr2) - pass - pass - arr = mc.DataArrayDouble.Aggregate(arr1s) - if typp == mc.ON_CELLS: - arr.renumberInPlace(o2nML[lev]) - mcf = mc.MEDCouplingFieldDouble(typp,mc.ONE_TIME) ; mcf.setName(fieldName) ; mcf.setTime(tim,dt,it) ; mcf.setArray(arr) - mcf.setMesh(mergeMLMesh.getMeshAtLevel(lev)) ; mcf.checkConsistencyLight() - mergeField.appendFieldNoProfileSBT(mcf) - pass - pass - mergeMLFields.pushField(mergeField) - pass - mergeMLMesh.write("merge.med",2) - mergeMLFields.write("merge.med",0) - - -Solution -~~~~~~~~ - -:ref:`python_testMEDLoaderSplitAndMerge1_solution` diff --git a/doc/tutorial/medloader_SplitAndMerge1_fr.rst b/doc/tutorial/medloader_SplitAndMerge1_fr.rst deleted file mode 100644 index f72ce174f..000000000 --- a/doc/tutorial/medloader_SplitAndMerge1_fr.rst +++ /dev/null @@ -1,219 +0,0 @@ - -Spliter et fusionner un fichier MED grâce à l'API avancée de MEDLoader ----------------------------------------------------------------------- - -Objectif -~~~~~~~~ - -Cet exercise présente un cas complet et avancé d'utilisation de l'API avancée de MEDLoader. -Le but est de créer un maillage multi-type à partir de rien avec 2 champs : - -* un champ aux cellules "CellField" -* un champ aux noeuds "NodeField" - -Nous allons ensuite couper ces champs en deux parties (dans le but d'un traitement en parallèle par un code par exemple) -et aussi montrer comment re-fusionner deux champs à partir de morceaux disjoints. - -Début de l'implémentation -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Créer un unstructured mesh ``m0`` issu d'un maillage structuré (meshDim=2, spaceDim=2) de 30*30. -Chacune des cellules paires du maillage sera *simplexisée* (i.e. coupée en triangle - méthode ``MEDCouplingUMesh.simplexize(0)``) :: - - import medcoupling as mc - - m0 = mc.MEDCouplingCMesh() - arr = mc.DataArrayDouble(31,1) ; arr.iota(0.) - m0.setCoords(arr,arr) - m0 = m0.buildUnstructured() - m00 = m0[::2] # Extract even cells - m00.simplexize(0) - m01 = m0[1::2] - m0 = mc.MEDCouplingUMesh.MergeUMeshes([m00,m01]) - m0.getCoords()[:] *= 1/15. # Illustrate how to quickly rescale a mesh - m0.setName("mesh") - -.. note:: Le ``setName()`` sur "m0" est obligatoire. Ne pas oublier que dans le contexte MED fichier - le nommage correct des maillages est fondamental. - -Créer les champs ``cellField`` et ``nodeField`` au pas de temps identifié à (5,6) et au pas de temps 5.6 s. :: - - # Cell field - cellField = mc.MEDCouplingFieldDouble(mc.ON_CELLS, mc.ONE_TIME) - cellField.setTime(5.6,5,6) - cellField.setMesh(m0) - cellField.setName("CellField") - cellField.fillFromAnalytic(1,"exp(-((x-1)*(x-1)+(y-1)*(y-1)))") - cellField.getArray().setInfoOnComponent(0,"powercell [W]") - # Node field - nodeField = mc.MEDCouplingFieldDouble(mc.ON_NODES,mc.ONE_TIME) - nodeField.setTime(5.6,5,6) - nodeField.setMesh(m0) - nodeField.setName("NodeField") - nodeField.fillFromAnalytic(1,"exp(-((x-1)*(x-1)+(y-1)*(y-1)))") - nodeField.getArray().setInfoOnComponent(0,"powernode [W]") - -On obtient par exemple pour "CellField" ceci : - -.. image:: images/SplitAndMergeCell1.jpg - - -Partitionnement de maillage -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Couper ``m0`` en deux parties distinctes. Les deux parties seront nommées ``proc0`` et ``proc1``. -``proc0`` sera la partie dans la boîte englobante (``MEDCouplingUMesh.getCellsInBoundingBox()``) ``[(0.,0.4),(0.,0.4)]`` -à 1e-10 près. ``proc1`` sera le complémentaire (``DataArrayInt.buildComplement()``). :: - - proc0 = m0.getCellsInBoundingBox([(0.,0.4),(0.,0.4)],1e-10) - proc1 = proc0.buildComplement(m0.getNumberOfCells()) - -.. image:: images/SplitAndMerge2.jpg - -Ecriture dans 2 fichiers MED séparés -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -En partant du partitionnement ``proc0`` et ``proc1`` créer 2 fichiers MED appelés "proc0.med" et "proc1.med" : :: - - nodeField0 = nodeField[proc0] ; cellField0 = cellField[proc0] ; cellField0.setMesh(nodeField0.getMesh()) - nodeField1 = nodeField[proc1] ; cellField1 = cellField[proc1] ; cellField1.setMesh(nodeField1.getMesh()) - - proc0_fname = "proc0.med" - mc.WriteField(proc0_fname, nodeField0, True) - mc.WriteFieldUsingAlreadyWrittenMesh(proc0_fname, cellField0) - - proc1_fname = "proc1.med" - mc.WriteField(proc1_fname,nodeField1,True) - mc.WriteFieldUsingAlreadyWrittenMesh(proc1_fname,cellField1) - -Lecture et fusion des 2 fichiers MED séparés (non optimal) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Partant de "proc0.med" et de "proc1.med" lire leur "CellField" respectif avec l'API basique, -agréger les deux et mettre le résultat dans ``cellField_read`` : :: - - cellField0_read = mc.ReadFieldCell("proc0.med","mesh",0,"CellField",5,6) - cellField1_read = mc.ReadFieldCell("proc1.med","mesh",0,"CellField",5,6) - cellField_read = mc.MEDCouplingFieldDouble.MergeFields([cellField0_read,cellField1_read]) - -.. note:: On peut avoir l'impression que l'information Cell (méthode ``ReadFieldCell``) est répétée de manière abusive - (effectivement le champ "CellField" a été créé aux cellules), - mais ne pas oublier que dans la norme MED fichier rien n'interdit qu'un champ repose sur des cellules mais - aussi simultanément sur des noeuds, ou des points de Gauss ... - -Comparer ``cellField_read`` et ``cellField0``. Problème, à cause de la contrainte sur la numérotation MED fichier, -on a perdu la numérotation initiale. Ou plus exactement il n'y a pas -de moyen standard de retrouver la numérotation originale. Donc un ``MEDCouplingFieldDouble.isEqual()`` -n'est pas suffisant. Utilisons un ``MEDCouplingFieldDouble.substractInPlaceDM()`` -qui opère pour nous une renumérotation suivant une politique particulière (*policy*, voir doc html). -Pour ce faire une copie profonde (*deep copy*) de ``cellField`` vers ``cellFieldCpy`` et opérer sur cette copie -un ``substractInPlaceDM`` (DM pour "Different Meshes", contrairement à ``substract`` qui ne marche que -s'ils partagent le même maillage): :: - - cellFieldCpy = cellField.deepCopy() - cellFieldCpy.substractInPlaceDM(cellField_read,10,1e-12) - cellFieldCpy.getArray().abs() - print(cellFieldCpy.getArray().isUniform(0.,1e-12)) - -Opérons le même travail sur "NodeField" que celui réalisé plus haut sur "CellField". -La différence ici c'est qu'il va y avoir duplication de l'information à la frontière, car les noeuds limites sont partagés -des deux côtés : :: - - nodeField0_read = mc.ReadFieldNode("proc0.med","mesh",0,"NodeField",5,6) - nodeField1_read = mc.ReadFieldNode("proc1.med","mesh",0,"NodeField",5,6) - nodeField_read = mc.MEDCouplingFieldDouble.MergeFields([nodeField0_read, nodeField1_read]) - -.. note:: Dans cette partie, on a donc relu le maillage une deuxième fois ce qui peut être pénalisant ... - -Invoquer ``MEDCouplingUMesh.mergeNodes()`` sur ``nodeField_read`` pour lui retirer les noeuds dupliqués. -Faire une deep copy appelée ``nodeFieldCpy`` de ``nodeField`` -et supprimer encore les doublons : :: - - nodeField_read.mergeNodes(1e-10) - nodeFieldCpy = nodeField.deepCopy() - nodeFieldCpy.mergeNodes(1e-10) - -.. note:: A noter que ``mergeNodes()`` possède deux paramètres de précisions (*epsilons*), le premier, - classique, sur la distance absolue entre les noeuds, et l'autre sur la tolérance acceptée sur les valeurs du champ. - Si la valeur du champ de deux noeuds à fusionner dépasse ce deuxième epsilon, une exception est levée. - -Comparer ``nodeFieldCpy`` et ``nodeField_read`` toujours en utilisant ``MEDCouplingFieldDouble.substractInPlaceDM()`` : :: - - nodeFieldCpy.substractInPlaceDM(nodeField_read,10,1e-12) - print(nodeFieldCpy.getArray().isUniform(0.,1e-12)) - - -Lecture et merge des 2 fichiers MED séparés (moins facile, mais plus optimal) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Il s'agit ici de faire une méthode plus systématique et potentiellement plus générale de fusion de fichiers. -Pour de gros fichiers cette approche est à préférer. -Outre la performance, cette approche a l'avantage de pouvoir rajouter des infos. - -Avec l'API avancée lire les maillages des deux fichiers "proc0.med" et "proc1.med" et agréger le résultat -dans une instance ``mergeMLMesh`` de ``MEDFileUMesh``. -Traiter tous les niveaux de dimension (même si ici il n'y en a qu'un seul) en utilisant la méthode ``MEDFileUMesh.getNonEmptyLevels()`` -sur l'instance venant de "proc0.med". - -La solution donnée ci-dessous est la plus générique possible, car elle traite aussi les différents pas de temps et les -différents types géométriques : :: - - fileNames = ["proc0.med","proc1.med"] - msML = [mc.MEDFileMesh.New(fname) for fname in fileNames] - fsML = [mc.MEDFileFields.New(fname) for fname in fileNames] - mergeMLMesh = mc.MEDFileUMesh() - mergeMLFields = mc.MEDFileFields() - for lev in msML[0].getNonEmptyLevels(): - o2nML = len(msML[0].getNonEmptyLevels())*[None] - cs = [mML.getCoords() for mML in msML] - mergeMLMesh.setCoords(mc.DataArrayDouble.Aggregate(cs)) - ms = [mML.getMeshAtLevel(lev) for mML in msML] - m = mc.MEDCouplingUMesh.MergeUMeshes(ms) ; m.setCoords(mergeMLMesh.getCoords()) - o2nML[lev] = m.sortCellsInMEDFileFrmt() - mergeMLMesh.setMeshAtLevel(lev,m) - pass - - for fieldName in fsML[0].getFieldsNames(): - fmts = [fML[fieldName] for fML in fsML] - mergeField = mc.MEDFileFieldMultiTS() - for dt,it,tim in fmts[0].getTimeSteps(): - fts = [fmt[dt,it] for fmt in fmts] - arrs = len(fts)*[None] - for typp in fts[0].getTypesOfFieldAvailable(): - arr1s = [] - if typp == mc.ON_CELLS: - for ft in fts: - for geoTyp,smth in ft.getFieldSplitedByType(): - if geoTyp != mc.NORM_ERROR: - smth1 = filter(lambda x:x[0] == mc.ON_CELLS,smth) - arr2s = [ft.getUndergroundDataArray()[elt[1][0]:elt[1][1]] for elt in smth1] - arr1s.append(mc.DataArrayDouble.Aggregate(arr2s)) - pass - pass - pass - pass - else: - for ft in fts: - smth = filter(lambda x:x[0] == mc.NORM_ERROR,ft.getFieldSplitedByType()) - arr2 = mc.DataArrayDouble.Aggregate([ft.getUndergroundDataArray()[elt[1][0][1][0]:elt[1][0][1][1]] for elt in smth]) - arr1s.append(arr2) - pass - pass - arr = mc.DataArrayDouble.Aggregate(arr1s) - if typp == mc.ON_CELLS: - arr.renumberInPlace(o2nML[lev]) - mcf = mc.MEDCouplingFieldDouble(typp,mc.ONE_TIME) ; mcf.setName(fieldName) ; mcf.setTime(tim,dt,it) ; mcf.setArray(arr) - mcf.setMesh(mergeMLMesh.getMeshAtLevel(lev)) ; mcf.checkConsistencyLight() - mergeField.appendFieldNoProfileSBT(mcf) - pass - pass - mergeMLFields.pushField(mergeField) - pass - mergeMLMesh.write("merge.med",2) - mergeMLFields.write("merge.med",0) - - -Solution -~~~~~~~~ - -:ref:`python_testMEDLoaderSplitAndMerge1_solution` diff --git a/doc/tutorial/medloader_advancedAPI1_en.rst b/doc/tutorial/medloader_advancedAPI1_en.rst deleted file mode 100644 index 4abc69a0c..000000000 --- a/doc/tutorial/medloader_advancedAPI1_en.rst +++ /dev/null @@ -1,151 +0,0 @@ - -Reading, Writing a MED file using MEDLoader's advanced API ----------------------------------------------------------- - -The advanced API is incarnated by the MEDFile* classes in the MEDLoader library. - -* MEDFileMesh, MEDFileUMesh, MEDFileCMesh -* MEDFileMeshes, MEDFileMeshMultiTS -* MEDFileField1TS, MEDFileFieldMultiTS -* MEDFileFields, MEDFileFieldGlobs -* MEDFileData - -Objective -~~~~~~~~~ - -Write a mesh and a field from scratch, re-read them and compare the result. - -Topics covered: - -* Read/Write Mesh using MEDLoader's advanced API -* Read/Write Field using MEDLoader's advanced API - -Implementation start -~~~~~~~~~~~~~~~~~~~~ - -To implement this exercise we use the Python scripting language and import the `medcoupling` Python module. :: - - import medcoupling as mc - - -Writing and Reading meshes using MEDLoader's advanced API -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -First of all, creation of a mesh "targetMesh". :: - - targetCoords=[-0.3,-0.3, 0.2,-0.3, 0.7,-0.3, -0.3,0.2, 0.2,0.2, 0.7,0.2, -0.3,0.7, 0.2,0.7, 0.7,0.7 ] - targetConn=[0,3,4,1, 1,4,2, 4,5,2, 6,7,4,3, 7,8,5,4] - targetMesh=mc.MEDCouplingUMesh.New("MyMesh",2) - targetMesh.allocateCells(5) - targetMesh.insertNextCell(mc.NORM_TRI3,3,targetConn[4:7]) - targetMesh.insertNextCell(mc.NORM_TRI3,3,targetConn[7:10]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[0:4]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[10:14]) - 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]. -:: - - targetMeshConsti=targetMesh.buildDescendingConnectivity()[0] - targetMesh1=targetMeshConsti[[3,4,7,8]] - targetMesh1.setName(targetMesh.getName()) - -.. note:: "targetMesh1" will be recorded as a part of the same global mesh in the MED file, so it must have the same name! - -Then we are ready to write targetMesh and targetMesh1 into TargetMesh2.med. :: - - meshMEDFile=mc.MEDFileUMesh.New() - meshMEDFile.setMeshAtLevel(0,targetMesh) - meshMEDFile.setMeshAtLevel(-1,targetMesh1) - meshMEDFile.write("TargetMesh2.med",2) # 2 stands for write from scratch - -Create 2 groups on level 0. The first called "grp0_Lev0" on cells [0,1,3] and the second called "grp1_Lev0" on cells [1,2,3,4] :: - - grp0_0=mc.DataArrayInt.New([0,1,3]) ; grp0_0.setName("grp0_Lev0") - grp1_0=mc.DataArrayInt.New([1,2,3,4]) ; grp1_0.setName("grp1_Lev0") - meshMEDFile.setGroupsAtLevel(0,[grp0_0,grp1_0]) - -Create 3 groups on level -1. The 1st called "grp0_LevM1" on cells [0,1], the 2nd called "grp1_LevM1" on cells [0,1,2], and the 3rd called "grp2_LevM1" on cells [1,2,3] :: - - grp0_M1=mc.DataArrayInt.New([0,1]) ; grp0_M1.setName("grp0_LevM1") - 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. :: - - meshMEDFileRead=mc.MEDFileMesh.New("TargetMesh2.med") - meshRead0=meshMEDFileRead.getMeshAtLevel(0) - meshRead1=meshMEDFileRead.getMeshAtLevel(-1) - print("Is the mesh at level 0 read in file equals targetMesh ? %s"%(meshRead0.isEqual(targetMesh,1e-12))) - print("Is the mesh at level -1 read in file equals targetMesh ? %s"%(meshRead1.isEqual(targetMesh1,1e-12))) - -Print available levels for group "grp0_Lev0" :: - - print(meshMEDFileRead.getGrpNonEmptyLevels("grp0_Lev0")) - -Request for cell ids of group "grp0_Lev0" :: - - grp0_0_read=meshMEDFileRead.getGroupArr(0,"grp0_Lev0") - print("Is group \"grp0_Lev0\" are the same ? %s"%(grp0_0_read.isEqual(grp0_0))) - -Writing and Reading fields -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Creation of a simple vector field on cells called f. :: - - f=mc.MEDCouplingFieldDouble.New(mc.ON_CELLS,mc.ONE_TIME) - f.setTime(5.6,7,8) - f.setArray(targetMesh.computeCellCenterOfMass()) - f.setMesh(targetMesh) - f.setName("AFieldName") - -Put f into a MEDFileField1TS for preparation of MED writing :: - - fMEDFile=mc.MEDFileField1TS.New() - fMEDFile.setFieldNoProfileSBT(f) - -Append field to "TargetMesh2.med" :: - - fMEDFile.write("TargetMesh2.med",0) # 0 is very important here because we want to append to TargetMesh2.med and not to overwrite it - -Read it : :: - - fMEDFileRead=mc.MEDFileField1TS.New("TargetMesh2.med",f.getName(),7,8) - fRead1=fMEDFileRead.getFieldOnMeshAtLevel(mc.ON_CELLS,0,meshMEDFileRead) # fastest method. No reading of the supporting mesh. - 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" -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Build a reduction on cells [1,2,3] of f and call it fPart. :: - - pfl=mc.DataArrayInt.New([1,2,3]) ; pfl.setName("My1stPfl") - fPart=f.buildSubPart(pfl) - fPart.setName("fPart") - -Put it into MEDFileField1TS data structure. :: - - fMEDFile2=mc.MEDFileField1TS.New() - fMEDFile2.setFieldProfile(fPart,meshMEDFileRead,0,pfl) - fMEDFile2.write("TargetMesh2.med",0) # 0 is very important here because we want to append to TargetMesh2.med and not to scratch it - -Read "fPart" field from File "TargetMesh2.med". :: - - fMEDFileRead2=mc.MEDFileField1TS.New("TargetMesh2.med",fPart.getName(),7,8) - fPartRead,pflRead=fMEDFileRead2.getFieldWithProfile(mc.ON_CELLS,0,meshMEDFileRead) - print(fPartRead.isEqualWithoutConsideringStr(fPart.getArray(),1e-12)) - print(pflRead.isEqualWithoutConsideringStr(pfl)) - -Solution -~~~~~~~~ - -:ref:`python_testMEDLoaderAdvancedAPI1_solution` diff --git a/doc/tutorial/medloader_advancedAPI1_fr.rst b/doc/tutorial/medloader_advancedAPI1_fr.rst deleted file mode 100644 index d41647a68..000000000 --- a/doc/tutorial/medloader_advancedAPI1_fr.rst +++ /dev/null @@ -1,187 +0,0 @@ - -Lecture, écriture d'un fichier MED grâce à l'API avancée de MEDLoader ---------------------------------------------------------------------- - -L'API avancée de MEDLoader est représentée par les classes ``MEDFile*`` de la bibliothèque MEDLoader. - -* Au plus haut niveau, pour l'ensemble du fichier: ``MEDFileData``, -* Pour l'ensemble des maillages du fichier : ``MEDFileMeshes``, -* Pour chacun des maillages : ``MEDFileMeshMultiTS``, ``MEDFileMesh``, ``MEDFileUMesh``, ``MEDFileCMesh``, -* Pour l'ensemble des champs du fichier : ``MEDFileFields``, ``MEDFileFieldGlobs``, -* Et enfin pour chacun des champs : ``MEDFileField1TS``, ``MEDFileFieldMultiTS`` - - -Objectif -~~~~~~~~ - -Ecrire un maillage et un champ à partir de rien, les relire et comparer les résultats. - -Points abordés : en utilisant l'API avancée de MEDLoader, - -* Ecrire un fichier -* Lire un fichier - -Début d'implémentation -~~~~~~~~~~~~~~~~~~~~~~ - -Cet exercice repose comme tous les autres sur le language de script Python. On charge -le module Python ``medcoupling``.:: - - import medcoupling as mc - -Lecture, écriture d'un maillage -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Nous créons tout d'abord le même maillage ``targetMesh`` que pour l'API simple. :: - - targetCoords = [-0.3,-0.3, 0.2,-0.3, 0.7,-0.3, -0.3,0.2, 0.2,0.2, 0.7,0.2, -0.3,0.7, 0.2,0.7, 0.7,0.7 ] - targetConn = [0,3,4,1, 1,4,2, 4,5,2, 6,7,4,3, 7,8,5,4] - targetMesh = mc.MEDCouplingUMesh("MyMesh",2) - targetMesh.allocateCells(5) - targetMesh.insertNextCell(mc.NORM_TRI3,3,targetConn[4:7]) - targetMesh.insertNextCell(mc.NORM_TRI3,3,targetConn[7:10]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[0:4]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[10:14]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[14:18]) - myCoords = mc.DataArrayDouble(targetCoords,9,2) - myCoords.setInfoOnComponents(["X [km]","YY [mm]"]) - targetMesh.setCoords(myCoords) - -.. note:: Le maillage ``targetMesh`` est ordonné par type géométrique. - -Nous construisons ensuite ``targetMesh1`` représentant les sous-constituants (*faces*) du maillage -``targetMesh``, et nous en extrayons seulement les cellules (donc ici des surfaces) [3,4,7,8]. -Pour plus de détails sur la connectivité descendante, -consulter la section :ref:`exo-umesh-desc-connec` du deuxième exercise. -Cet ensemble peut par exemple représenter un ensemble d'intérêt pour un calcul : :: - - targetMeshConsti, _, _, _, _ = targetMesh.buildDescendingConnectivity() - targetMesh1 = targetMeshConsti[[3,4,7,8]] - targetMesh1.setName(targetMesh.getName()) - -.. note:: En Python, le underscore ``_`` signifie que l'on attend une valeur de retour, mais qu'on n'en aura pas l'usage - (on ne la *bind* pas). -.. note:: ``targetMesh1`` sera sauvé comme étant une partie du même maillage global dans le fichier MED. - Il doit donc avoir le même nom. C'est là qu'on voit qu'un maillage au sens MED fichier peut mélanger les dimensions. - -On peut alors écrire les deux maillages dans le fichier "TargetMesh2.med". :: - - meshMEDFile = mc.MEDFileUMesh() - meshMEDFile.setMeshAtLevel(0,targetMesh) - meshMEDFile.setMeshAtLevel(-1,targetMesh1) - meshMEDFile.write("TargetMesh2.med",2) # 2 stands for 'write from scratch' - -Lecture, écriture de groupes de mailles -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Créons deux groupes de cellules sur le maillage 2D, c'est à dire au niveau relatif 0 (ici, le niveau relatif 0 correspond -à la 2D, le niveau -1 -correspond à la 1D, etc ...). Le premier groupe ``grp0_Lev0`` contient les cellules [0,1,3] -le second ``grp1_Lev0`` les cellules [1,2,3,4] : :: - - grp0_0 = mc.DataArrayInt([0,1,3]) - grp0_0.setName("grp0_Lev0") - grp1_0 = mc.DataArrayInt([1,2,3,4]) - grp1_0.setName("grp1_Lev0") - meshMEDFile.setGroupsAtLevel(0, [grp0_0,grp1_0]) - -.. note:: On voit évidemment ici l'importance de nommer les tableaux : c'est le nom qui sera utilisé pour le groupe. - -Créons trois groupes de niveau -1, c'est à dire des groupes de faces. Le premier appelé -``grp0_LevM1`` aux cellules [0,1], le second appelé ``grp1_LevM1`` aux cellules [0,1,2], et le 3ème ``grp2_LevM1`` -aux cellules [1,2,3] : :: - - grp0_M1 = mc.DataArrayInt([0,1]) - grp0_M1.setName("grp0_LevM1") - grp1_M1 = mc.DataArrayInt([0,1,2]) - grp1_M1.setName("grp1_LevM1") - grp2_M1 = mc.DataArrayInt([1,2,3]) - grp2_M1.setName("grp2_LevM1") - meshMEDFile.setGroupsAtLevel(-1,[grp0_M1,grp1_M1,grp2_M1]) - -Ecrivons le tout : :: - - meshMEDFile.write("TargetMesh2.med",2) # 2 stands for 'write from scratch' - -Nous pouvons ensuite re-lire le fichier MED : :: - - meshMEDFileRead = mc.MEDFileMesh.New("TargetMesh2.med") # a new is needed because it returns a MEDFileUMesh (MEDFileMesh is abstract) - meshRead0 = meshMEDFileRead.getMeshAtLevel(0) - meshRead1 = meshMEDFileRead.getMeshAtLevel(-1) - print("Is level 0 in the file equal to 'targetMesh'?", meshRead0.isEqual(targetMesh,1e-12)) - print("Is level 0 in the file equal to 'targetMesh1'?", meshRead1.isEqual(targetMesh1,1e-12)) - -Affichons les niveaux disponibles pour le groupe ``grp0_Lev0`` : :: - - print(meshMEDFileRead.getGrpNonEmptyLevels("grp0_Lev0")) - -Et récupérons enfin les identifiants de cellules contenus dans le groupe ``grp0_Lev0`` : :: - - grp0_0_read = meshMEDFileRead.getGroupArr(0,"grp0_Lev0") - print("Is group 'grp0_Lev0' equal to what is read in the file?" , grp0_0_read.isEqual(grp0_0)) - -Lire/écrire des champs avec l'API avancée -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Créons un champ de vecteurs simple, aux cellules (P0), avec un seul pas de temps, appelé ``f``. :: - - f = mc.MEDCouplingFieldDouble(mc.ON_CELLS, mc.ONE_TIME) - f.setTime(5.6,7,8) - f.setArray(targetMesh.computeCellCenterOfMass()) - f.setMesh(targetMesh) - f.setName("AFieldName") - -Stocker ``f`` dans un object ``MEDFileField1TS`` (un champ avec un seul pas de temps -- *one time-step, 1TS*) -pour préparer l'écriture MED :: - - fMEDFile = mc.MEDFileField1TS() - fMEDFile.setFieldNoProfileSBT(f) # No profile desired on the field, Sort By Type - -Ajouter le champ au fichier "TargetMesh2.med" :: - - fMEDFile.write("TargetMesh2.med",0) # 0 is paramount to indicate that we *append* (and no overwrite) to the MED file - -.. note:: Noter l'utilisation du 0 pour indiquer que nous désirons ajouter au fichier existant. - -Lire le champ : :: - - fMEDFileRead = mc.MEDFileField1TS("TargetMesh2.med",f.getName(),7,8) - fRead1 = fMEDFileRead.getFieldOnMeshAtLevel(mc.ON_CELLS,0,meshMEDFileRead) # Quickest way, not re-reading mesh in the file. - fRead2 = fMEDFileRead.getFieldAtLevel(mc.ON_CELLS,0) # Like above, but this time the mesh is read! - print("Does the field remain OK with the quick method?", fRead1.isEqual(f,1e-12,1e-12)) - print("Does the field remain OK with the slow method?", fRead2.isEqual(f,1e-12,1e-12)) - -Lire/écrire un champ sur un "profil" -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Nous allons maintenant voir un concept avancé des fichiers MED, à savoir la possibilité d'écrire un champ sur seulement -une *partie* du maillage. La technique habituellement utilisée est plutôt de mettre des valeurs particulières (e.g. +infinity -soit 1e+300) sur les zones où le champ n'a pas de sens, permettant ainsi de repérer en plus des bugs éventuels lors du calcul. - -Le mode de fonctionnement avec les profils reste donc peu courant. - -Construisons une réduction aux cellules [1,2,3] de ``f`` et appelons la ``fPart`` : :: - - pfl = mc.DataArrayInt([1,2,3]) - pfl.setName("My1stPfl") - fPart = f.buildSubPart(pfl) - fPart.setName("fPart") - -La stocker dans la structure ``MEDFileField1TS`` et invoquer ``setFieldProfile()``. :: - - fMEDFile2 = mc.MEDFileField1TS() - fMEDFile2.setFieldProfile(fPart,meshMEDFileRead,0,pfl) # 0 is the relative level (here 0 means 2D) - fMEDFile2.write("TargetMesh2.med",0) # 0 is paramount to indicate that we *append* (and no overwrite) to the MED file - -Lire le champ ``fPart`` du fichier "TargetMesh2.med" et les identifiants de cellules correspondant. :: - - fMEDFileRead2 = mc.MEDFileField1TS("TargetMesh2.med",fPart.getName(),7,8) - fPartRead, pflRead = fMEDFileRead2.getFieldWithProfile(mc.ON_CELLS,0,meshMEDFileRead) - print("Is the partial field correctly read?", fPartRead.isEqualWithoutConsideringStr(fPart.getArray(),1e-12)) - print("Is the list of cell identifiers matching?", pflRead.isEqualWithoutConsideringStr(pfl)) - -Solution -~~~~~~~~ - -:ref:`python_testMEDLoaderAdvancedAPI1_solution` - diff --git a/doc/tutorial/medloader_basicAPI1_en.rst b/doc/tutorial/medloader_basicAPI1_en.rst deleted file mode 100644 index 11947a299..000000000 --- a/doc/tutorial/medloader_basicAPI1_en.rst +++ /dev/null @@ -1,96 +0,0 @@ - -Reading, Writing a MED file using MEDLoader's basic API -------------------------------------------------------- - -The basic API is incarnated by the MEDLoader class. -All methods in that class are static. -The sessions of read/write are done on each call of a method. - -Objective -~~~~~~~~~ - -Write a mesh and a field from scratch, re-read them and compare the result. - -Topics covered: -* Write using MEDLoader's basic API -* Read using MEDLoader's basic API - -Implementation start -~~~~~~~~~~~~~~~~~~~~ - -To implement this exercise we use the Python scripting language and import the `medcoupling` Python module. :: - - import medcoupling as mc - -Writing/Reading a mesh -~~~~~~~~~~~~~~~~~~~~~~ - -First of all, creation of a mesh "targetMesh". :: - - targetCoords=[-0.3,-0.3, 0.2,-0.3, 0.7,-0.3, -0.3,0.2, 0.2,0.2, 0.7,0.2, -0.3,0.7, 0.2,0.7, 0.7,0.7 ] - targetConn=[0,3,4,1, 1,4,2, 4,5,2, 6,7,4,3, 7,8,5,4] - targetMesh=mc.MEDCouplingUMesh.New("MyMesh",2) - targetMesh.allocateCells(5) - targetMesh.insertNextCell(NORM_TRI3,3,targetConn[4:7]) - targetMesh.insertNextCell(NORM_TRI3,3,targetConn[7:10]) - targetMesh.insertNextCell(NORM_QUAD4,4,targetConn[0:4]) - targetMesh.insertNextCell(NORM_QUAD4,4,targetConn[10:14]) - targetMesh.insertNextCell(NORM_QUAD4,4,targetConn[14:18]) - 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. :: - - mc.WriteUMesh("TargetMesh.med",targetMesh,True) - -Then trying to read it. :: - - meshRead=mc.ReadUMeshFromFile("TargetMesh.med",targetMesh.getName(),0) - print("Is the mesh read in file equals targetMesh? %s"%(meshRead.isEqual(targetMesh,1e-12))) - -Writing/Reading a field on one time step at once -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Creation of a vector field "f" on cell supported by "targetMesh". :: - - f=mc.MEDCouplingFieldDouble.New(ON_CELLS,ONE_TIME) - f.setTime(5.6,7,8) - f.setArray(targetMesh.computeCellCenterOfMass()) - f.setMesh(targetMesh) - f.setName("AFieldName") - mc.WriteField("MyFirstField.med",f,True) - -.. note:: Mesh AND Field is written at once into MyFirstField. - -Reading into MyFirstField.med :: - - f2=mc.ReadFieldCell("MyFirstField.med",f.getMesh().getName(),0,f.getName(),7,8) - print("Is the field read in file equals f ? %s"%(f2.isEqual(f,1e-12,1e-12))) - -Writing/Reading a field on one or many times steps in "multi-session mode" -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Here contrary to the previous steps, we are going to write in a multi-session mode on the same MED file. -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) - f2.getArray()[:]=2.0 - f2.setTime(7.8,9,10) - mc.WriteFieldUsingAlreadyWrittenMesh("MySecondField.med",f2) - -Now "MySecondField.med" file contains 2 time steps. - -Solution -~~~~~~~~ - -:ref:`python_testMEDLoaderBasicAPI1_solution` diff --git a/doc/tutorial/medloader_basicAPI1_fr.rst b/doc/tutorial/medloader_basicAPI1_fr.rst deleted file mode 100644 index 4847ef4e0..000000000 --- a/doc/tutorial/medloader_basicAPI1_fr.rst +++ /dev/null @@ -1,124 +0,0 @@ - -Lecture, écriture d'un fichier MED grâce à l'API basique de MEDLoader ---------------------------------------------------------------------- - -L'API basique de MEDLoader est contenue dans la classe ``MEDLoader``. -Toutes les méthodes de cette classe sont *statiques* (elles ne dépendent pas d'une instance particulière de la -classe), leurs noms commencent par une majuscule. -L'ensemble des lectures/écritures sont exécutées à chaque appel de méthode et aucun état interne à la classe n'est -enregistré. - -Objectif -~~~~~~~~ - -Ecrire un maillage et un champ à partir de rien, les relire et comparer les résultats. - -Points abordés: en utilisant l'API basique de ``MEDLoader`` - -* Ecrire un fichier -* Lire un fichier - -Début d'implémentation -~~~~~~~~~~~~~~~~~~~~~~ - -Cet exercice repose comme tous les autres sur le language de script Python. On charge -le module Python ``medcoupling``.:: - - import medcoupling as mc - -Lecture, écriture d'un maillage -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Tout d'abord créons un maillage ``targetMesh`` composé de plusieurs types géométriques. :: - - targetCoords = [-0.3,-0.3, 0.2,-0.3, 0.7,-0.3, -0.3,0.2, 0.2,0.2, 0.7,0.2, -0.3,0.7, 0.2,0.7, 0.7,0.7 ] - targetConn = [0,3,4,1, 1,4,2, 4,5,2, 6,7,4,3, 7,8,5,4] - targetMesh = mc.MEDCouplingUMesh("MyMesh",2) - targetMesh.allocateCells(5) - targetMesh.insertNextCell(mc.NORM_TRI3,3,targetConn[4:7]) - targetMesh.insertNextCell(mc.NORM_TRI3,3,targetConn[7:10]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[0:4]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[10:14]) - targetMesh.insertNextCell(mc.NORM_QUAD4,4,targetConn[14:18]) - myCoords = mc.DataArrayDouble(targetCoords,9,2) - myCoords.setInfoOnComponents(["X [km]","YY [mm]"]) - targetMesh.setCoords(myCoords) - -.. note:: Le maillage ``targetMesh`` est ordonné par type géométrique. - -Le maillage peut alors directement être écrit ... :: - - mc.WriteUMesh("TargetMesh.med",targetMesh,True) # True means 'from scratch' - -... et relu. :: - - meshRead = mc.ReadUMeshFromFile("TargetMesh.med",targetMesh.getName(),0) - print("Is the read mesh equal to 'targetMesh' ?", meshRead.isEqual(targetMesh,1e-12)) - -Lire/Ecrire un champ sur un pas de temps -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Nous créons maintenant un champ de vecteurs ``f`` aux cellules (P0) avec ``targetMesh`` comme support. -Ce champ correspond par exemple au temps physique 5.6, repéré par l'itération 7 et la sous-itération 8. -Nous en profitons pour rappeler -que dans les champs MEDCoupling, le temps physique est donné pour information seulement, le stockage et la plupart des -fonctions de l'API se basent sur les deux derniers entiers. :: - - f = mc.MEDCouplingFieldDouble.New(mc.ON_CELLS, mc.ONE_TIME) - f.setTime(5.6,7,8) # Declare the timestep associated to the field - f.setArray(targetMesh.computeCellCenterOfMass()) - f.setMesh(targetMesh) - f.setName("AFieldName") - mc.WriteField("MyFirstField.med",f,True) - -Question subsidiaire : à quoi correspond le champ ainsi créé ? - -.. note:: Le maillage **et** le champ sont écrits d'un seul coup dans le fichier "MyFirstField.med". - -Nous relisons ensuite MyFirstField.med : :: - - f2 = mc.ReadFieldCell("MyFirstField.med", f.getMesh().getName(), 0, f.getName(), 7, 8) - print("Is the read field identical to 'f' ?", f2.isEqual(f,1e-12,1e-12)) - -.. note:: Lors de la lecture du champ, on doit donc connaître: son nom, le nom de sa mesh de support - et le pas de temps voulu. Des fonctions du type ``MEDFileFields.getFieldsNames()`` ou encore - ``MEDFileMeshes.getMeshesNames()`` aident à cela. - -.. note:: Le nom ``ReadFieldCell()`` rappelle que le champ doit être lu aux cellules. Souvenez-vous que suivant la - norme MED fichier, un même champ peut avoir une partie de ses données stockées aux cellules, mais aussi - simultanément aux noeuds, aux points de Gauss, etc ... même si ce genre de mélange exotique n'est généralement - pas conseillé. - -Lire/Ecrire un champ sur plusieurs pas de temps -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Ici contrairement au cas précédent, nous écrivons en plusieurs fois dans le *même* fichier MED. -Ecrivons tout d'abord le maillage. :: - - mc.WriteUMesh("MySecondField.med",f.getMesh(),True) - -Ensuite, nous écrivons seulement les informations relatives au champ (principalement son tableau de valeurs en fait -). :: - - mc.WriteFieldUsingAlreadyWrittenMesh("MySecondField.med",f) # mesh is not re-written - -Nous rajoutons ensuite un second pas de temps sur le *même* maillage. :: - - f2 = f.clone(True) # 'True' means that we need a deep copy - f2.getArray()[:] = 2.0 - f2.setTime(7.8,9,10) - mc.WriteFieldUsingAlreadyWrittenMesh("MySecondField.med",f2) - -Maintenant le fichier "MySecondField.med" contient le maillage et un champ à deux pas de temps porté par ce maillage. - -Nous pouvons relire tout cela avec des méthodes similaires à ce qui a été vu précédemment : :: - - f3 = mc.ReadFieldCell("MySecondField.med",f.getMesh().getName(),0,f.getName(),7,8) - print("Is the field read in file equals to 'f' ?", f.isEqual(f3,1e-12,1e-12)) - f4 = mc.ReadFieldCell("MySecondField.med",f.getMesh().getName(),0,f.getName(),9,10) - print("Is the field read in file equals to 'f2' ?", f2.isEqual(f4,1e-12,1e-12)) - -Solution -~~~~~~~~ - -:ref:`python_testMEDLoaderBasicAPI1_solution` diff --git a/doc/tutorial/medloader_en.rst b/doc/tutorial/medloader_en.rst deleted file mode 100644 index 19c328ba2..000000000 --- a/doc/tutorial/medloader_en.rst +++ /dev/null @@ -1,23 +0,0 @@ - -Reading, Writing a MED file using the MEDLoader library -======================================================= - -The objective of these exercises is to see how to read and write a MED file. - * Usage of MEDLoader's basic API - - * Meshes - * Fields - - * Usage of MEDLoader's advanced API - - * Meshes - * Fields - - * An Example of classical manipulation of MED files: splitting a MED file / merge a MED file - -.. toctree:: - :maxdepth: 2 - - medloader_basicAPI1_en - medloader_advancedAPI1_en - medloader_SplitAndMerge1_en diff --git a/doc/tutorial/medloader_fr.rst b/doc/tutorial/medloader_fr.rst deleted file mode 100644 index af19266d1..000000000 --- a/doc/tutorial/medloader_fr.rst +++ /dev/null @@ -1,23 +0,0 @@ - -MEDLoader : lecture, écriture d'un fichier MED -============================================== - -L'objectif de ces exercices est de comprendre comment lire et écrire un fichier MED. - * Utilisation basique de l'API MEDLoader - - * Maillages - * Champs - - * Utilisation avancée de l'API MEDLoader - - * Maillages - * Champs - - * Exemple de manipulation classique de fichiers MED : splitter / fusionner un fichier MED suivant plusieurs sous-domaines - -.. toctree:: - :maxdepth: 2 - - medloader_basicAPI1_fr - medloader_advancedAPI1_fr - medloader_SplitAndMerge1_fr