Version: 9.14.0
MEDCoupling Python examples

Be sure to take a look at the page A word on the Python API before proceeding.

Fields

Create

Standard build of a tensor field on cells with no time attached

fieldOnCells = MEDCouplingFieldDouble(ON_CELLS, NO_TIME)
fieldOnCells.setName("MyTensorFieldOnCellNoTime")
fieldOnCells.setMesh(mesh)
array = DataArrayDouble()
array.alloc(
fieldOnCells.getMesh().getNumberOfCells(), 9
) # Implicitly fieldOnCells will be a 9 components field.
array.fillWithValue(7.0)
fieldOnCells.setArray(array)
# fieldOnCells is now usable
# ...

Standard build of a scalar field on nodes with no time attached

fieldOnNodes = MEDCouplingFieldDouble(ON_NODES, NO_TIME)
fieldOnNodes.setName("MyScalarFieldOnNodeNoTime")
fieldOnNodes.setMesh(mesh)
array = DataArrayDouble()
array.alloc(
fieldOnNodes.getMesh().getNumberOfNodes(), 1
) # Implicitly fieldOnNodes will be a 1 component field.
array.fillWithValue(7.0)
fieldOnNodes.setArray(array)
# fieldOnNodes is now usable
# ...

Standard build of a vector field on cells with one time attached and no time interval

fieldOnCells = MEDCouplingFieldDouble(ON_CELLS, ONE_TIME)
fieldOnCells.setName("MyTensorFieldOnCellNoTime")
fieldOnCells.setTimeUnit("ms") # Time unit is ms.
fieldOnCells.setTime(
4.22, 2, -1
) # Time attached is 4.22 ms, iteration id is 2 and order id (or sub iteration id) is -1
fieldOnCells.setMesh(mesh)
array = DataArrayDouble()
array.alloc(
fieldOnCells.getMesh().getNumberOfCells(), 2
) # Implicitly fieldOnCells will be a 2 components field.
array.fillWithValue(7.0)
fieldOnCells.setArray(array)
# fieldOnCells is now usable
# ...

Standard build of a vector field on nodes defined on a time interval with a constant value during this interval

fieldOnNodes = MEDCouplingFieldDouble(ON_NODES, CONST_ON_TIME_INTERVAL)
fieldOnNodes.setName("MyVecFieldOnNodeWithConstTime")
fieldOnNodes.setTimeUnit("ms") # Time unit is ms.
fieldOnNodes.setStartTime(4.22, 2, -1)
fieldOnNodes.setEndTime(
6.44, 4, -1
) # fieldOnNodes is defined in interval [4.22 ms,6.44 ms]
fieldOnNodes.setMesh(mesh)
array = DataArrayDouble()
array.alloc(
fieldOnNodes.getMesh().getNumberOfNodes(), 3
) # Implicitly fieldOnNodes will be a 3 components field.
array.fillWithValue(7.0)
fieldOnNodes.setArray(array)
# fieldOnNodes is now usable
# ...

Getting maximal and minimal fields

In this example we

  • create two fields with two tuples per two components,
  • use MaxFields() to get a field holding maximal values of the two fields.
  • use MinFields() to get a field holding minimal values of the two fields.
vals1 = [0.0, 2.0, 4.0, 6.0] # for field 1
vals2 = [2.0, 0.0, 6.0, 4.0] # for field 2
valsMax = [2.0, 2.0, 6.0, 6.0] # expected max field
valsMin = [0.0, 0.0, 4.0, 4.0] # expected min field
# field 1
valsArr1 = DataArrayDouble(vals1, 2, 2) # 2 tuples per 2 components
field1 = MEDCouplingFieldDouble(ON_NODES)
field1.setArray(valsArr1)
# field 2
valsArr2 = DataArrayDouble(vals2, 2, 2) # 2 tuples per 2 components
field2 = MEDCouplingFieldDouble(ON_NODES)
field2.setArray(valsArr2)
# max field
fieldMax = MEDCouplingFieldDouble.MaxFields(field1, field2)
self.assertTrue(fieldMax.getArray().getValues() == valsMax)
# min field
fieldMin = MEDCouplingFieldDouble.MinFields(field1, field2)
self.assertTrue(fieldMin.getArray().getValues() == valsMin)

Concatenating fields

In this example we

  • create an 1D mesh and a field on it,
  • make a deep copy of the mesh and the field,
  • translate the mesh and the field,
  • use two variants of MergeFields() to create one field from the two by concatenating them and their meshes.
# mesh 1
coords = [0.0, 2.0, 4.0]
coordsArr = DataArrayDouble(coords, 3, 1)
mesh1 = MEDCouplingCMesh()
mesh1.setCoords(coordsArr)
# field 1
field1 = mesh1.fillFromAnalytic(ON_CELLS, 1, "x")
# mesh 2 and field 2
field2 = field1.cloneWithMesh(True)
vec = [5.0]
field2.getMesh().translate(vec) # translate mesh2
field2.applyFunc("x + 5") # "translate" field2
# concatenate field1 and field2
field3 = MEDCouplingFieldDouble.MergeFields(field1, field2)
field4 = MEDCouplingFieldDouble.MergeFields([field1, field2])

The result field is twice "longer" than field1.

Getting a field copy with different time discretization

First, we create a supporting 2D mesh and a field on it got using fillFromAnalytic(). Time discretization of this field is ONE_TIME.

coords = [0.0, 2.0, 4.0]
coordsArr = DataArrayDouble(coords, 3, 1)
mesh = MEDCouplingCMesh()
mesh.setCoords(coordsArr, coordsArr)
field1 = mesh.fillFromAnalytic(ON_NODES, 1, "x+y")
self.assertTrue(field1.getTimeDiscretization() == ONE_TIME)

Now we use buildNewTimeReprFromThis() to get a copy of field1 whose time discretization is NO_TIME.

field2 = field1.buildNewTimeReprFromThis(NO_TIME, False)
self.assertTrue(field2.getTimeDiscretization() == NO_TIME)

Creating a field using an expression

First, we create a 2D Cartesian mesh constituted by 2 cells.

coords = [0.0, 2.0, 4.0, 6.0] # 6. is not used
x = DataArrayDouble(coords[:3], 3, 1)
y = DataArrayDouble(coords[:2], 2, 1)
mesh = MEDCouplingCMesh()
mesh.setCoords(x, y)

Now we use fillFromAnalytic3() to get a MEDCouplingFieldDouble on cells filled with values computed using an expression func. This expression is applied to coordinates of each point (barycenter) for which the field value is computed. We want to get the field on cells, with 3 components computed as follows. (In func, we refer to the first component of a point using the variable "a", and to the second component, using the variable "b").

  • Component #0 = the second coordinate of the point hence "IVec * b" in func.
  • Component #1 = the first coordinate of the point hence "JVec * a".
  • Component #2 = distance between the point and SC origin (0.,0.) hence "KVec * sqrt( a*a + b*b )".

In addition we want to add 10.0 to each component computed as described above, hence "10" in func.

func = "IVec * b + JVec * a + KVec * sqrt( a*a + b*b ) + 10"
varNames = ["a", "b"] # names used to refer to X and Y coord components
field = mesh.fillFromAnalyticNamedCompo(ON_CELLS, 3, varNames, func)

Now we ascertain that the result field is as we expect. We check the second tuple of the field. We get barycenter of the cell #1 and checks that values of the second tuple are computed as we want.

vals1 = field.getArray().getTuple(1) # values of the cell #1
assert len(vals1) == 3 # 3 components in the field
#
bc = mesh.computeCellCenterOfMass() # func is applied to barycenters of cells
bc1 = bc.getTuple(1) # coordinates of the second point
#
dist = sqrt(bc1[0] * bc1[0] + bc1[1] * bc1[1]) # "sqrt( a*a + b*b )"
self.assertAlmostEqual(vals1[0], 10 + bc1[1], 13) # "10 + IVec * b"
self.assertAlmostEqual(vals1[1], 10 + bc1[0], 13) # "10 + JVec * a"
self.assertAlmostEqual(
vals1[2], 10 + dist, 13
) # "10 + KVec * sqrt( a*a + b*b )"

Creating a field using an expression

First, we create a 2D Cartesian mesh constituted by 2 cells. Note that we set names to coordinates arrays ("a" and "b" ) which will be used to refer to corresponding coordinates within a function.

coords = [0.0, 2.0, 4.0, 6.0] # 6. is not used
x = DataArrayDouble(coords[:3], 3, 1)
y = DataArrayDouble(coords[:2], 2, 1)
x.setInfoOnComponent(
0, "a"
) # name used to refer to X coordinate within a function
y.setInfoOnComponent(
0, "b"
) # name used to refer to Y coordinate within a function
mesh = MEDCouplingCMesh()
mesh.setCoords(x, y)

Now we use fillFromAnalytic2() to get a MEDCouplingFieldDouble on cells filled with values computed using an expression func. This expression is applied to coordinates of each point (barycenter) for which the field value is computed. We want to get the field on cells, with 3 components computed as follows. (In func, we refer to the first component of a point using the variable "a", and to the second component, using the variable "b").

  • Component #0 = the second coordinate of the point hence "IVec * b" in func.
  • Component #1 = the first coordinate of the point hence "JVec * a".
  • Component #2 = distance between the point and SC origin (0.,0.) hence "KVec * sqrt( a*a + b*b )".

In addition we want to add 10.0 to each component computed as described above, hence "10" in func.

func = "IVec * b + JVec * a + KVec * sqrt( a*a + b*b ) + 10"
field = mesh.fillFromAnalyticCompo(ON_CELLS, 3, func)

Now we ascertain that the result field is as we expect. We check the second tuple of the field. We get barycenter of the cell #1 and checks that values of the second tuple are computed as we want.

vals1 = field.getArray().getTuple(1) # values of the cell #1
assert len(vals1) == 3 # 3 components in the field
#
bc = mesh.computeCellCenterOfMass() # func is applied to barycenters of cells
bc1 = bc.getTuple(1) # coordinates of the second point
#
dist = sqrt(bc1[0] * bc1[0] + bc1[1] * bc1[1]) # "sqrt( a*a + b*b )"
self.assertAlmostEqual(vals1[0], 10 + bc1[1], 13) # "10 + IVec * b"
self.assertAlmostEqual(vals1[1], 10 + bc1[0], 13) # "10 + JVec * a"
self.assertAlmostEqual(
vals1[2], 10 + dist, 13
) # "10 + KVec * sqrt( a*a + b*b )"

Creating a field using an expression

First, we create a 2D Cartesian mesh constituted by 2 cells.

coords = [0.0, 2.0, 4.0, 6.0] # 6. is not used
x = DataArrayDouble(coords[:3], 3, 1)
y = DataArrayDouble(coords[:2], 2, 1)
mesh = MEDCouplingCMesh()
mesh.setCoords(x, y)

Now we use fillFromAnalytic() to get a MEDCouplingFieldDouble on cells filled with values computed using an expression func. This expression is applied to coordinates of each point (barycenter) for which the field value is computed. We want to get the field on cells, with 3 components computed as follows. (In func, we refer to the first component of a point using the variable "a", and to the second component, using the variable "b").

  • Component #0 = the second coordinate of the point hence "IVec * b" in func.
  • Component #1 = the first coordinate of the point hence "JVec * a".
  • Component #2 = distance between the point and SC origin (0.,0.) hence "KVec * sqrt( a*a + b*b )".

In addition we want to add 10.0 to each component computed as described above, hence "10" in func.

func = "IVec * b + JVec * a + KVec * sqrt( a*a + b*b ) + 10"
field = mesh.fillFromAnalytic(ON_CELLS, 3, func)

Now we ascertain that the result field is as we expect. We check the second tuple of the field. We get barycenter of the cell #1 and checks that values of the second tuple are computed as we want.

vals1 = field.getArray().getTuple(1) # values of the cell #1
assert len(vals1) == 3 # 3 components in the field
#
bc = mesh.computeCellCenterOfMass() # func is applied to barycenters of cells
bc1 = bc.getTuple(1) # coordinates of the second point
#
dist = sqrt(bc1[0] * bc1[0] + bc1[1] * bc1[1]) # "sqrt( a*a + b*b )"
self.assertAlmostEqual(vals1[0], 10 + bc1[1], 13) # "10 + IVec * b"
self.assertAlmostEqual(vals1[1], 10 + bc1[0], 13) # "10 + JVec * a"
self.assertAlmostEqual(
vals1[2], 10 + dist, 13
) # "10 + KVec * sqrt( a*a + b*b )"

Creation of a sub part of a field


Creation of a sub part of a field on cells

mesh1 = MEDCouplingDataForTest.build2DTargetMesh_1()
f1 = MEDCouplingFieldDouble(ON_CELLS, ONE_TIME)
f1.setTime(2.3, 5, 6)
f1.setMesh(mesh1)
arr1 = [3.0, 103.0, 4.0, 104.0, 5.0, 105.0, 6.0, 106.0, 7.0, 107.0]
array = DataArrayDouble(arr1, mesh1.getNumberOfCells(), 2)
f1.setArray(array)

The field on cells f1 lies on a mesh containing 5 cells and 9 nodes. So this field f1 contains 5 tuples of 2 components each (10 values). Now let's create a subfield on cells f2 from f1.

part1 = [2, 1, 4]
f2 = f1.buildSubPart(part1)

f1 is a field on cells, buildSubPart method performs an extraction on cells too.

So the array part1 lists ids on cells.

  • cell #0 of f2 is the same cell of cell #2 of f1
  • cell #1 of f2 is the same cell of cell #1 of f1
  • cell #2 of f2 is the same cell of cell #4 of f1

So f2 contains 3 tuples with 2 components.

The underlying mesh of f2 contains a newly created mesh with 3 cells (not as mesh1 in f1) and 9 nodes (as mesh1 in f1).
For fields on cells the number of tuples of the returned field is always equal to the number of ids given in input (here part1).
Only fields on cells have this particular behaviour.


Creation of a sub part of a field on nodes

f1 = MEDCouplingFieldDouble(ON_NODES, ONE_TIME)
f1.setTime(2.3, 5, 6)
f1.setMesh(mesh1)
arr2 = [
3.0,
103.0,
4.0,
104.0,
5.0,
105.0,
6.0,
106.0,
7.0,
107.0,
8.0,
108.0,
9.0,
109.0,
10.0,
110.0,
11.0,
111.0,
]
array = DataArrayDouble(arr2, mesh1.getNumberOfNodes(), 2)
f1.setArray(array)

The field on nodes f1 lies on a mesh containing 5 cells and 9 nodes. So this field f1 contains 9 tuples of 2 components each (18 values). Now let's create a subfield on nodes f2 from f1.

part2 = [1, 2]
f2 = f1.buildSubPart(part2)

f1 is a field on nodes, but buildSubPart method performs an extraction on cells.

After the call of buildSubPart on node field f1, f1 will be reduced on a submesh of mesh1 containing cells whose ids are in part2. So here the number of cells of f2 is 2 and the number of nodes is 4.
So contrary to fields on cells, it is normal for fields on nodes that number of tuples of the returned field of buildSubPart method does not match the size of the input array (here part2).

Modify

Subtracting field on different meshes

We make two meshes in 1D space with no cells and 4 nodes. Nodes #0 and #2 are swapped in the two meshes.
And we make two fields on these meshes, so that fields values to equal to node coordinates of the underlying meshes.

coords1 = [0.0, 1.0, 2.0, 3.0]
coords2 = [2.0, 1.0, 0.0, 3.0] # 0 <==> #2
# mesh 1
mesh1 = MEDCouplingUMesh()
coordsArr = DataArrayDouble(coords1, 4, 1)
mesh1.setCoords(coordsArr)
mesh1.setMeshDimension(0)
mesh1.allocateCells(0)
mesh1.finishInsertingCells()
# mesh 2
mesh2 = mesh1.deepCopy()
mesh2.getCoords().setValues(coords2, 4, 1)

We are going to subtract field2 from field1, though they are on different meshes. substractInPlaceDM() allows us doing this. We use a mesh comparison level levOfCheck = 10 that allows subtracting fields on meshes with different node arrays.

field1 = mesh1.fillFromAnalytic(ON_NODES, 1, "x") # field1 values == coords1
field2 = mesh2.fillFromAnalytic(ON_NODES, 1, "x") # field2 values == coords2
levOfCheck = 10 # nodes can be permuted
field1.substractInPlaceDM(
field2, levOfCheck, 1e-13, 0
) # values #0 and #2 must swap

After applying substractInPlaceDM() the both fields lie on mesh2. As substractInPlaceDM() permutes values of field1 before value subtraction, and thus field1 becomes equal to field2, hence their subtraction results in a zero field.

field2.applyFunc(1, 0.0) # all field2 values == 0.0
self.assertTrue(field1.isEqual(field2, 1e-13, 1e-13)) # field1 == field2 == 0.0

Changing the underlying mesh

We make two meshes in 1D space with no cells and 4 nodes. Nodes #0 and #2 are swapped in the two meshes.

coords1 = [0.0, 1.0, 2.0, 3.0]
coords2 = [2.0, 1.0, 0.0, 3.0] # 0 <==> #2
# mesh 1
mesh1 = MEDCouplingUMesh()
coordsArr = DataArrayDouble(coords1, 4, 1)
mesh1.setCoords(coordsArr)
mesh1.setMeshDimension(0)
mesh1.allocateCells(0)
mesh1.finishInsertingCells()
# mesh 2
mesh2 = mesh1.deepCopy()
mesh2.getCoords().setValues(coords2, 4, 1)

We are going to use changeUnderlyingMesh() to set mesh2 instead of mesh1 as a support of a field.
We use fillFromAnalytic() to make a field on nodes of mesh1, so that its values to equal to node coordinates. Then we use changeUnderlyingMesh() to change the underlying mesh of the field. (We use a mesh comparison level levOfCheck = 10 that allows substituting meshes with different node arrays.) As a result, we expect that values of the field are also permuted same as nodes of the two meshes, and thus its values become equal to the array coords2.

field = mesh1.fillFromAnalytic(ON_NODES, 1, "x") # field values == coords1
levOfCheck = 10 # nodes can be permuted
field.changeUnderlyingMesh(
mesh2, levOfCheck, 1e-13, 0
) # values #0 and #2 must swap
self.assertTrue(field.getArray().getValues() == coords2)

Changing a field using an expression

We create a 2D vector field with 2 tuples and we want to transform this field using an expression using applyFunc(). The expression func is applied to each atomic value of the field. We want to change the field as follows. (In func, we use the variable "v" to refer to an atomic field value).

  • Component #0 = component #0 (remains the same) hence "IVec * v" in func.
  • Component #1 = component #1 ^ 2 hence "JVec * v*v".

In addition we want to add 10.0 to each component computed as described above, hence "10" in func.

v = [1.0, 2.0, 3.0, 4.0]
array = DataArrayDouble(v, 2, 2) # 2 tuples per 2 components
field = MEDCouplingFieldDouble(ON_CELLS)
field.setArray(array)
func = "IVec * v + JVec * w*w + 10"
field.applyFunc(2, func)
self.assertTrue(field.getNumberOfComponents() == 2) # 2 components remains

Now we ascertain that the result field is as we expect.

v2 = field.getArray().getValues()
self.assertAlmostEqual(v2[0], 10 + v[0], 13) # "10 + IVec * v"
self.assertAlmostEqual(v2[1], 10 + v[1] * v[1], 13) # "10 + JVec * v*v"
self.assertAlmostEqual(v2[2], 10 + v[2], 13) # "10 + IVec * v"
self.assertAlmostEqual(v2[3], 10 + v[3] * v[3], 13) # "10 + JVec * v*v"

Changing a field using an expression

We create a 2D vector field with 2 values (vectors) and then we transform this field into a 3D vector field by applying an expression to values of the 2D field using applyFunc3(). The expression func is applied to components of each vector of the field. We want the field to have 3 components computed as follows. (In func, we refer to the first component of a field value using the variable "a", and to the second component, using the variable "b", as we define it by varNamesVec).

  • Component #0 = the second vector component hence "IVec * b" in func.
  • Component #1 = the first vector component hence "JVec * a".
  • Component #2 = a vector magnitude hence "KVec * sqrt( a*a + b*b )".

In addition we want to add 10.0 to each component computed as described above, hence "10" in func.

# create a 2D vector field
values = [1.0, 1.0, 2.0, 1.0]
array = DataArrayDouble(values, 2, 2) # 2 tuples per 2 components
field = MEDCouplingFieldDouble(ON_CELLS)
field.setArray(array)
# transform the field to a 3D vector field
func = "IVec * b + JVec * a + KVec * sqrt( a*a + b*b ) + 10"
varNames = ["a", "b"] # names used to refer to X and Y components
field.applyFuncNamedCompo(3, varNames, func) # require 3 components
self.assertTrue(field.getNumberOfComponents() == 3) # 3 components as required

Now we ascertain that the result field is as we expect. We check the second vector of the field.

vec1 = field.getArray().getTuple(1) # vector #1
a, b = values[2], values[3] # initial components of the vector #1
self.assertAlmostEqual(vec1[0], 10 + b, 13) # "10 + IVec * b"
self.assertAlmostEqual(vec1[1], 10 + a, 13) # "10 + JVec * a"
self.assertAlmostEqual(
vec1[2], 10 + sqrt(a * a + b * b), 13
) # "10 + KVec * sqrt( a*a + b*b )"

Changing a field using an expression

We create a 2D vector field with 2 values (vectors) and then we transform this field into a 3D vector field by applying an expression to values of the 2D field using applyFunc2(). Note that we set component info the array ("a" and "b" ) which will be used to refer to corresponding components within a function. The expression func is applied to components of each vector of the field. We want the field to have 3 components computed as follows. (In func, we refer to the first component of a field value using the variable "a", and to the second component, using the variable "b").

  • Component #0 = the second vector component hence "IVec * b" in func.
  • Component #1 = the first vector component hence "JVec * a".
  • Component #2 = a vector magnitude hence "KVec * sqrt( a*a + b*b )".

In addition we want to add 10.0 to each component computed as described above, hence "10" in func.

# create a 2D vector field
values = [1.0, 1.0, 2.0, 1.0]
array = DataArrayDouble(values, 2, 2) # 2 tuples per 2 components
array.setInfoOnComponent(
0, "a"
) # name used to refer to X component within a function
array.setInfoOnComponent(
1, "b"
) # name used to refer to Y component within a function
field = MEDCouplingFieldDouble(ON_CELLS)
field.setArray(array)
# transform the field to a 3D vector field
func = "IVec * b + JVec * a + KVec * sqrt( a*a + b*b ) + 10"
field.applyFuncCompo(3, func) # require 3 components
self.assertTrue(field.getNumberOfComponents() == 3) # 3 components as required

Now we ascertain that the result field is as we expect. We check the second vector of the field.

vec1 = field.getArray().getTuple(1) # vector #1
a, b = values[2], values[3] # initial components of the vector #1
self.assertAlmostEqual(vec1[0], 10 + b, 13) # "10 + IVec * b"
self.assertAlmostEqual(vec1[1], 10 + a, 13) # "10 + JVec * a"
self.assertAlmostEqual(
vec1[2], 10 + sqrt(a * a + b * b), 13
) # "10 + KVec * sqrt( a*a + b*b )"

Changing a field using an expression

We create a 2D vector field with 2 values (vectors) and then we transform this field into a 3D vector field by applying an expression to values of the 2D field using applyFunc(). The expression func is applied to components of each vector of the field. We want the field to have 3 components computed as follows. (In func, we refer to the first component of a field value using the variable "a", and to the second component, using the variable "b").

  • Component #0 = the second vector component hence "IVec * b" in func.
  • Component #1 = the first vector component hence "JVec * a".
  • Component #2 = a vector magnitude hence "KVec * sqrt( a*a + b*b )".

In addition we want to add 10.0 to each component computed as described above, hence "10" in func.

# create a 2D vector field
values = [1.0, 1.0, 2.0, 1.0]
array = DataArrayDouble(values, 2, 2) # 2 tuples per 2 components
field = MEDCouplingFieldDouble(ON_CELLS)
field.setArray(array)
# transform the field to a 3D vector field
func = "IVec * b + JVec * a + KVec * sqrt( a*a + b*b ) + 10"
field.applyFunc(3, func) # require 3 components
self.assertTrue(field.getNumberOfComponents() == 3) # 3 components as required

Now we ascertain that the result field is as we expect. We check the second vector of the field.

vec1 = field.getArray().getTuple(1) # vector #1
a, b = values[2], values[3] # initial components of the vector #1
self.assertAlmostEqual(vec1[0], 10 + b, 13) # "10 + IVec * b"
self.assertAlmostEqual(vec1[1], 10 + a, 13) # "10 + JVec * a"
self.assertAlmostEqual(
vec1[2], 10 + sqrt(a * a + b * b), 13
) # "10 + KVec * sqrt( a*a + b*b )"

Filling a field with a value

We want to transform a 2D vector field to a 3D vector field so that all values to be equal to a certain value. First, we create the 2D mesh and the vector field on it.

coords = [0.0, 2.0, 4.0]
coordsArr = DataArrayDouble(coords, 3, 1)
mesh = MEDCouplingCMesh()
mesh.setCoords(coordsArr, coordsArr)
field = MEDCouplingFieldDouble(ON_CELLS)
field.setMesh(mesh)
field.fillFromAnalytic(2, "IVec * x + JVec * y") # 2 components

Finally we use applyFunc() to change the number of components and all field values.

newValue = 7.0
field.applyFunc(3, newValue) # 3 components are required
self.assertTrue(field.getIJ(1, 0) == newValue) # a value is as expected
self.assertTrue(field.getNumberOfComponents() == 3)
self.assertTrue(field.getNumberOfTuples() == mesh.getNumberOfCells())

As a result, number of tuples in the field equals to the number of cells in the mesh, and number of components becomes equal to 3 as required.

Filling a field using an expression

First, we create a 2D Cartesian mesh constituted by 2 cells.

coords = [0.0, 2.0, 4.0, 6.0] # 6. is not used
x = DataArrayDouble(coords[:3], 3, 1)
y = DataArrayDouble(coords[:2], 2, 1)
mesh = MEDCouplingCMesh()
mesh.setCoords(x, y)

Now we create a field on cells and use fillFromAnalytic2() to fill it with values computed using an expression func. This expression is applied to coordinates of each point (barycenter) for which the field value is computed. We want the field to have 3 components computed as follows. (In func, we refer to the first component of a point using the variable "a", and to the second component, using the variable "b").

  • Component #0 = the second coordinate of the point hence "IVec * b" in func.
  • Component #1 = the first coordinate of the point hence "JVec * a".
  • Component #2 = distance between the point and SC origin (0.,0.) hence "KVec * sqrt( a*a + b*b )".

In addition we want to add 10.0 to each component computed as described above, hence "10" in func.

field = MEDCouplingFieldDouble(ON_CELLS)
field.setMesh(mesh)
func = "IVec * b + JVec * a + KVec * sqrt( a*a + b*b ) + 10"
varNames = ["a", "b"] # names used to refer to X and Y coord components
field.fillFromAnalyticNamedCompo(3, varNames, func)

Now we ascertain that the result field is as we expect. We check the second tuple of the field. We get barycenter of the cell #1 and checks that values of the second tuple are computed as we want.

vals1 = field.getArray().getTuple(1) # values of the cell #1
assert len(vals1) == 3 # 3 components in the field
#
bc = mesh.computeCellCenterOfMass() # func is applied to barycenters of cells
bc1 = bc.getTuple(1) # coordinates of the second point
#
dist = sqrt(bc1[0] * bc1[0] + bc1[1] * bc1[1]) # "sqrt( a*a + b*b )"
self.assertAlmostEqual(vals1[0], 10 + bc1[1], 13) # "10 + IVec * b"
self.assertAlmostEqual(vals1[1], 10 + bc1[0], 13) # "10 + JVec * a"
self.assertAlmostEqual(
vals1[2], 10 + dist, 13
) # "10 + KVec * sqrt( a*a + b*b )"

Filling a field using an expression

First, we create a 2D Cartesian mesh constituted by 2 cells. Note that we set names to coordinates arrays ("a" and "b" ) which will be used to refer to corresponding coordinates within a function.

coords = [0.0, 2.0, 4.0]
x = DataArrayDouble(coords[:3], 3, 1)
y = DataArrayDouble(coords[:2], 2, 1)
x.setInfoOnComponent(
0, "a"
) # name used to refer to X coordinate within a function
y.setInfoOnComponent(
0, "b"
) # name used to refer to Y coordinate within a function
mesh = MEDCouplingCMesh()
mesh.setCoords(x, y)

Now we create a field on cells and use fillFromAnalytic2() to fill it with values computed using an expression func. This expression is applied to coordinates of each point (barycenter) for which the field value is computed. We want the field to have 3 components computed as follows. (In func, we refer to the first component of a point using the variable "a", and to the second component, using the variable "b").

  • Component #0 = the second coordinate of the point hence "IVec * b" in func.
  • Component #1 = the first coordinate of the point hence "JVec * a".
  • Component #2 = distance between the point and SC origin (0.,0.) hence "KVec * sqrt( a*a + b*b )".

In addition we want to add 10.0 to each component computed as described above, hence "10" in func.

field = MEDCouplingFieldDouble(ON_CELLS)
field.setMesh(mesh)
func = "IVec * b + JVec * a + KVec * sqrt( a*a + b*b ) + 10"
field.fillFromAnalyticCompo(3, func)

Now we ascertain that the result field is as we expect. We check the second tuple of the field. We get barycenter of the cell #1 and checks that values of the second tuple are computed as we want.

vals1 = field.getArray().getTuple(1) # values of the cell #1
assert len(vals1) == 3 # 3 components in the field
#
bc = mesh.computeCellCenterOfMass() # func is applied to barycenters of cells
bc1 = bc.getTuple(1) # coordinates of the second point
#
dist = sqrt(bc1[0] * bc1[0] + bc1[1] * bc1[1]) # "sqrt( a*a + b*b )"
self.assertAlmostEqual(vals1[0], 10 + bc1[1], 13) # "10 + IVec * b"
self.assertAlmostEqual(vals1[1], 10 + bc1[0], 13) # "10 + JVec * a"
self.assertAlmostEqual(
vals1[2], 10 + dist, 13
) # "10 + KVec * sqrt( a*a + b*b )"

Filling a field using an expression

First, we create a 2D Cartesian mesh constituted by 2 cells.

coords = [0.0, 2.0, 4.0]
x = DataArrayDouble(coords[:3], 3, 1)
y = DataArrayDouble(coords[:2], 2, 1)
mesh = MEDCouplingCMesh()
mesh.setCoords(x, y)

Now we create a field on cells and use fillFromAnalytic() to fill it with values computed using an expression func. This expression is applied to coordinates of each point (barycenter) for which the field value is computed. We want the field to have 3 components computed as follows. (In func, we refer to the first component of a point using the variable "a", and to the second component, using the variable "b").

  • Component #0 = the second coordinate of the point hence "IVec * b" in func.
  • Component #1 = the first coordinate of the point hence "JVec * a".
  • Component #2 = distance between the point and SC origin (0.,0.) hence "KVec * sqrt( a*a + b*b )".

In addition we want to add 10.0 to each component computed as described above, hence "10" in func.

field = MEDCouplingFieldDouble(ON_CELLS)
field.setMesh(mesh)
func = "IVec * b + JVec * a + KVec * sqrt( a*a + b*b ) + 10"
field.fillFromAnalytic(3, func)

Now we ascertain that the result field is as we expect. We check the second tuple of the field. We get barycenter of the cell #1 to check that values of the second tuple (#1) are computed as we want.

vals1 = field.getArray().getTuple(1) # values of the cell #1
assert len(vals1) == 3 # 3 components in the field
#
bc = mesh.computeCellCenterOfMass() # func is applied to barycenters of cells
bc1 = bc.getTuple(1) # coordinates of the second point
#
dist = sqrt(bc1[0] * bc1[0] + bc1[1] * bc1[1]) # "sqrt( a*a + b*b )"
self.assertAlmostEqual(vals1[0], 10 + bc1[1], 13) # "10 + IVec * b"
self.assertAlmostEqual(vals1[1], 10 + bc1[0], 13) # "10 + JVec * a"
self.assertAlmostEqual(
vals1[2], 10 + dist, 13
) # "10 + KVec * sqrt( a*a + b*b )"

Some operations that can be carried out on fields on cells

f1 = mesh.fillFromAnalytic(ON_CELLS, 1, "x*x+y*y*3+2.*x") # f1 is scalar
f2 = mesh.fillFromAnalytic(ON_CELLS, 1, "cos(x+y/x)") # f2 is scalar too
f2bis = mesh.fillFromAnalytic(
ON_CELLS, 2, "x*x*IVec+3*y*JVec"
) # f2bis is a vectors field
f3 = f1 + f2 # f3 scalar
f4 = f3 / f2 # f4 scalar
f2bis.applyFunc(1, "sqrt(x*x+y*y)") # f2bis becomes scalar
f5 = f2bis * f4 # f5 scalar
pos1 = [0.48, 0.38]
res = f4.getValueOn(pos1) # f4 is scalar so the returned value is of size 1.
# ...

Permuting a field on nodes

First, we create a supporting 2D mesh constituted by 4 cells. We create a 2x2 Cartesian mesh and then convert it to an unstructured one, since the Cartesian mesh is not suitable for renumberNodes() as its nature does not imply node renumbering.

coords = [0.0, 2.0, 4.0]
coordsArr = DataArrayDouble(coords, 3, 1)
mesh = MEDCouplingCMesh()
mesh.setCoords(coordsArr, coordsArr)
mesh = mesh.buildUnstructured()

Then we create a field on nodes using fillFromAnalytic(), such that its values to coincide with coordinates of field location points that are nodes in our case (as our field is ON_NODES). At last we ascertain that field values are equal to node coordinates.

field = mesh.fillFromAnalytic(ON_NODES, 2, "IVec*x+JVec*y")
values = field.getArray()
nodeCoords = mesh.getCoords()
self.assertTrue(values.isEqualWithoutConsideringStr(nodeCoords, 1e-13))

Now, we are going to reverse order of nodes using renumberNodes().

renumber = [8, 7, 6, 5, 4, 3, 2, 1, 0]
field.renumberNodes(renumber, False)
mesh2 = field.getMesh() # field now refers to another mesh
values = field.getArray()
nodeCoords = mesh2.getCoords()
self.assertTrue(values.isEqualWithoutConsideringStr(nodeCoords, 1e-13))

As a result, the underlying mesh of field is changed and its nodes are also renumbered. And the field values are still equal to node coordinates of the renumbered mesh2.

Permuting a field on cells

First, we create a supporting 2D mesh constituted by 4 cells. We create a 2x2 Cartesian mesh and then convert it to an unstructured one, since the Cartesian mesh is not suitable for renumberCells() as its nature does not imply cell renumbering.

coords = [0.0, 2.0, 4.0]
coordsArr = DataArrayDouble(coords, 3, 1)
mesh = MEDCouplingCMesh()
mesh.setCoords(coordsArr, coordsArr)
mesh = mesh.buildUnstructured()

Then we create a field on cells using fillFromAnalytic(), such that its values to coincide with coordinates of field location points that are cell barycenters in our case (as our field is ON_CELLS). At last we ascertain that field values are equal to cell barycenters.

field = mesh.fillFromAnalytic(ON_CELLS, 2, "IVec*x+JVec*y")
values = field.getArray()
bc = mesh.computeCellCenterOfMass()
self.assertTrue(values.isEqualWithoutConsideringStr(bc, 1e-13))

Now, we are going to reverse order of cells using renumberCells().

renumber = [3, 2, 1, 0]
field.renumberCells(renumber, False)
mesh2 = field.getMesh() # field now refers to another mesh
values = field.getArray()
bc = mesh2.computeCellCenterOfMass()
self.assertTrue(values.isEqualWithoutConsideringStr(bc, 1e-13))

As a result, the underlying mesh of field is changed and its cells are also renumbered. And the field values are still equal to cell barycenters of the renumbered mesh2.

Access

Getting a field value at some point at certain time

First, we create a supporting structured mesh. We create a 2x2 Cartesian mesh constituted by 4 cells.

coords = [0.0, 2.0, 4.0]
coordsArr = DataArrayDouble(coords, 3, 1)
mesh = MEDCouplingCMesh()
mesh.setCoords(coordsArr, coordsArr)

Then we create a scalar field on cells, whose values vary linearly in time. We set all field values at a start time to be equal 10.0 using fillFromAnalytic(). And we set all field values at an end time to be equal 20.0 by doubling the start time array.

field = MEDCouplingFieldDouble(ON_CELLS, LINEAR_TIME)
field.setMesh(mesh)
field.fillFromAnalytic(1, "10") # all values == 10.
field.setEndArray(field.getArray() + field.getArray()) # all values == 20.
time1, time2 = 1.1, 22.0
field.setStartTime(time1, 0, 0)
field.setEndTime(time2, 0, 0)

Now, we want to get a field value at a point [0,0] at a middle time between the start and end times. We expect the returned value to be equal to an average of 10. and 20.

pos = [1.0, 1.0] # we are in 2D space
value = field.getValueOn(pos, 0.5 * (time1 + time2))
self.assertTrue(value[0] == 0.5 * (10.0 + 20.0))

Getting field values at some points

First, we create a supporting structured mesh. We create a 2x2 Cartesian mesh constituted by 4 cells. Then we create a scalar field on cells using fillFromAnalytic().

coords = [0.0, 2.0, 4.0]
coordsArr = DataArrayDouble(coords, 3, 1)
mesh = MEDCouplingCMesh()
mesh.setCoords(coordsArr, coordsArr)
field = mesh.fillFromAnalytic(ON_CELLS, 1, "x+y")

Now, we want to retrieve all field values using getValueOnMulti(). The field values relate to cells, hence we will use cell barycenters as a parameter of getValueOnMulti(). We expect that the double array returned getValueOnMulti() is equal to that stored by field.

bc = (
mesh.computeCellCenterOfMass()
) # field values are located at cell barycenters
valArray = field.getValueOnMulti(bc)
self.assertTrue(valArray.isEqual(field.getArray(), 1e-13))

Getting a field value at a point

First, we create a supporting structured mesh. We create a 2x2 Cartesian mesh constituted by 4 cells. Then we create a scalar field on cells using fillFromAnalytic().

coords = [0.0, 2.0, 4.0]
coordsArr = DataArrayDouble(coords, 3, 1)
mesh = MEDCouplingCMesh()
mesh.setCoords(coordsArr, coordsArr)
field = mesh.fillFromAnalytic(ON_CELLS, 1, "x+y")

Now, we want to retrieve all field values using getValueOn(). The field values relate to cells, hence we will use cell barycenters to get a field value at each cell.

bc = (
mesh.computeCellCenterOfMass()
) # field values are located at cell barycenters
vals = [] # array to collect values returned by getValueOn()
for i, tupl in enumerate(bc):
vals.extend(field.getValueOn(tupl))
self.assertTrue(vals == field.getArray().getValues())

We collected all values returned by getValueOn() in an array, so that we can ascertain that the array of returned values is same as that stored by field.

Getting a value of field lying on a structured mesh

First, we create a supporting structured mesh. We create a 2x2 Cartesian mesh constituted by 4 cells. Then we create a scalar field on cells using fillFromAnalytic().

coords = [0.0, 2.0, 4.0]
coordsArr = DataArrayDouble(coords, 3, 1)
mesh = MEDCouplingCMesh()
mesh.setCoords(coordsArr, coordsArr)
field = mesh.fillFromAnalytic(ON_CELLS, 1, "x+y")

Now, we retrieve a field value relating to the cell #3 (this cell has a structured indexed (1,1)). For that we use getValueOnPos() where we pass the structured indexed of the cell: 1,1,-1 (the last index is meaningless as the mesh is 2D).

val11 = field.getValueOnPos(1, 1, -1)
bc = (
mesh.computeCellCenterOfMass()
) # field values are located at cell barycenters
self.assertTrue(val11[0] == bc[3, 0] + bc[3, 1])

After all we ascertain that the returned value corresponds to the expression used for the field creation. Namely that the value equals to the sum of components of barycenter of cell #3.

Meshes

Create

Standard build of an unstructured mesh from scratch

Firstly retrieve basic data in full interlace mode for coordinates, and nodal connectivity cell per cell.

coords = [
-0.3,
-0.3,
0.0,
0.2,
-0.3,
0.0,
0.7,
-0.3,
0.0,
-0.3,
0.2,
0.0,
0.2,
0.2,
0.0,
0.7,
0.2,
0.0,
-0.3,
0.7,
0.0,
0.2,
0.7,
0.0,
0.7,
0.7,
0.0,
]
nodalConnPerCell = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]

Then create MEDCoupling::MEDCouplingUMesh instance giving its mesh dimension (2 here) and a name.

mesh = MEDCouplingUMesh("My2DMesh", 2)

Gives an upper bound of the number of cells to be inserted into the unstructured mesh.
Then enter nodal connectivity of all cells, cell per cell using MEDCoupling::MEDCouplingUMesh::insertNextCell method.
When the nodal connectivity cell per cell has been finished, call MEDCoupling::MEDCouplingUMesh::finishInsertingCells method in order to restore mesh instance.

mesh.allocateCells(5) # You can put more than 5 if you want but not less.
# adding cells
mesh.insertNextCell(NORM_QUAD4, nodalConnPerCell[:4])
mesh.insertNextCell(NORM_TRI3, nodalConnPerCell[4:7])
mesh.insertNextCell(NORM_TRI3, nodalConnPerCell[7:10])
mesh.insertNextCell(NORM_QUAD4, nodalConnPerCell[10:14])
mesh.insertNextCell(NORM_QUAD4, nodalConnPerCell[14:])
# compacting
mesh.finishInsertingCells()

At this level the connectivity part of the mesh mesh as been defined. Now let's set the coordinates using array coords defined above.

coordsArr = DataArrayDouble(
coords, 9, 3
) # here coordsArr are declared to have 3 components, mesh will deduce that its spaceDim==3.
mesh.setCoords(
coordsArr
) # coordsArr contains 9 tuples, that is to say mesh contains 9 nodes.

At this level mesh is usable. When this mesh is no more needed simply call decrRef to decrement its reference counter.

mesh.checkConsistencyLight()

Advanced build of an unstructured mesh from scratch

Firstly retrieve basic data in full interlace mode for coordinates, and nodal connectivity cell per cell, cell type included (3 for INTERP_KERNEL::NORM_TRI3 and 4 for INTERP_KERNEL::QUAD4).

coords = [
-0.3,
-0.3,
0.0,
0.2,
-0.3,
0.0,
0.7,
-0.3,
0.0,
-0.3,
0.2,
0.0,
0.2,
0.2,
0.0,
0.7,
0.2,
0.0,
-0.3,
0.7,
0.0,
0.2,
0.7,
0.0,
0.7,
0.7,
0.0,
]
nodalConnPerCell = [
4,
0,
3,
4,
1,
3,
1,
4,
2,
3,
4,
5,
2,
4,
6,
7,
4,
3,
4,
7,
8,
5,
4,
]
nodalConnPerCellIndex = [0, 5, 9, 13, 18, 23]

Then create MEDCoupling::MEDCouplingUMesh instance giving its mesh dimension (2 here) and a name.

mesh = MEDCouplingUMesh("My2DMesh", 2)

Then enter nodal connectivity at once.

nodalConn = DataArrayInt(nodalConnPerCell, 23, 1)
nodalConnI = DataArrayInt(nodalConnPerCellIndex, 6, 1)
mesh.setConnectivity(nodalConn, nodalConnI, True)

At this level the connectivity part of the mesh mesh as been defined. Now let's set the coordinates using array coords defined above.

coordsArr = DataArrayDouble(
coords, 9, 3
) # here coordsArr are declared to have 3 components, mesh will deduce that its spaceDim==3.
mesh.setCoords(
coordsArr
) # coordsArr contains 9 tuples, that is to say mesh contains 9 nodes.

At this level mesh is usable. When this mesh is no more needed simply call decrRef() to decrement its reference counter.

Standard build of an cartesian mesh from scratch

We are going to build a 2D cartesian mesh, constituted from 9 nodes along X axis, and 7 nodes along Y axis.

Firstly retrieve for each direction the discretization and build a DataArrayDouble instance on the corresponding direction.

XCoords = [-0.3, 0.0, 0.1, 0.3, 0.45, 0.47, 0.49, 1.0, 1.22] # 9 values along X
YCoords = [0.0, 0.1, 0.37, 0.45, 0.47, 0.49, 1.007] # 7 values along Y
arrX = DataArrayDouble(XCoords)
arrX.setInfoOnComponent(0, "X [m]")
arrY = DataArrayDouble(YCoords)
arrY.setInfoOnComponent(0, "Y [m]")

Then create MEDCoupling::MEDCouplingCMesh instance giving the 2 instances of DataArrayDouble obtained above.

There are 2 techniques to get it.

Either :

mesh = MEDCouplingCMesh("My2D_CMesh")
mesh.setCoords(arrX, arrY)

Or :

mesh.setCoordsAt(0, arrX)
mesh.setCoordsAt(1, arrY)

mesh is now available for use :

self.assertEqual(8 * 6, mesh.getNumberOfCells())
self.assertEqual(9 * 7, mesh.getNumberOfNodes())
self.assertEqual(2, mesh.getSpaceDimension())
self.assertEqual(2, mesh.getMeshDimension())

When this mesh is no more needed simply call decrRef to decrement its reference counter (nothing to be done in Python).

Getting a bounding mesh

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4])
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7])
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10])
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14])
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18])
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Now we use buildBoundaryMesh() to get a mesh of lower dimension bounding mesh.

mesh1 = mesh.buildBoundaryMesh(True)
mesh2 = mesh.buildBoundaryMesh(False)
assert coordsArr.isEqual(mesh1.getCoords(), 1e-13) # same nodes
assert not coordsArr.isEqual(mesh2.getCoords(), 1e-13) # different nodes

Depending on the value of a parameter, buildBoundaryMesh() creates the mesh sharing the node coordinates array with mesh or not.

Retrieving a lower dimension mesh based on given nodes

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

In the following code we retrieve nodes of the cell #0 an then we call buildFacePartOfMySelfNode() twice with these nodes and with varying last parameter allNodes as input.

nodeIds = mesh.getNodeIdsOfCell(0)
allNodes = True
mesh1 = mesh.buildFacePartOfMySelfNode(nodeIds, allNodes)
assert mesh1.getNumberOfCells() == 4 # 4 segments bounding QUAD4 #0 only
mesh2 = mesh.buildFacePartOfMySelfNode(nodeIds, not allNodes)
assert mesh2.getNumberOfCells() > 4 # more segments added


If the last parameter is true buildFacePartOfMySelfNode() looks for segments whose all nodes are given to it, hence it finds segments bounding the cell #0 only.
If the last parameter is false buildFacePartOfMySelfNode() looks for any segment whose nodes are given to it, hence it adds more segments to mesh2.

Copying cells selected by nodes

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

In the following code we retrieve nodes of the cell #0 an then we call buildPartOfMySelfNode() twice with these nodes and with varying last parameter allNodes as input.

nodeIds = mesh.getNodeIdsOfCell(0)
allNodes = True
mesh1 = mesh.buildPartOfMySelfNode(nodeIds, allNodes)
mesh2 = mesh.buildPartOfMySelfNode(nodeIds, not allNodes)
assert mesh1.getNumberOfCells() == 1 # cell #0 is found only
assert (
mesh2.getNumberOfCells() == mesh.getNumberOfCells()
) # all cells are found


If the last parameter is true buildPartOfMySelfNode() looks for cells whose all nodes are given to it, hence it finds the cell #0 only.
If the last parameter is false buildPartOfMySelfNode() looks for any cell whose nodes are given to it, hence it finds all cells of mesh because all cells share the node #4.

Getting a part of mesh

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Now we use buildPartOfMySelf() to get a mesh containing only two cells of mesh.

cellIds = [1, 2]
mesh2 = mesh.buildPartOfMySelf(cellIds, True)
mesh3 = mesh.buildPartOfMySelf(cellIds, False)
coordsArr2 = mesh2.getCoords()
assert coordsArr.isEqual(coordsArr2, 1e-13) # same nodes
coordsArr3 = mesh3.getCoords()
assert not coordsArr.isEqual(coordsArr3, 1e-13) # different nodes
assert mesh2.getNodeIdsOfCell(0) == mesh.getNodeIdsOfCell(
cellIds[0]
) # cell #1 was copied
assert mesh2.getNodeIdsOfCell(1) == mesh.getNodeIdsOfCell(
cellIds[1]
) # cell #2 was copied

Modify

Fixing orientation of "extruded" volumes

First, we create a mesh with 2 incorrectly oriented "extruded" volumes.

# 2D coordinates of 5 base nodes
coords = [-0.3, -0.3, 0.2, -0.3, 0.7, -0.3, -0.3, 0.2, 0.2, 0.2]
coordsArr = DataArrayDouble(coords, 5, 2)
# coordinates of 5 top nodes
coordsArr2 = coordsArr.deepCopy()
# 3D coordinates of base + top nodes
coordsArr = coordsArr.changeNbOfComponents(3, 0)
coordsArr2 = coordsArr2.changeNbOfComponents(3, 1)
coordsArr = DataArrayDouble.Aggregate([coordsArr, coordsArr2])
# mesh
mesh = MEDCouplingUMesh()
mesh.setCoords(coordsArr)
mesh.setMeshDimension(3)
mesh.allocateCells(2)
# connectivity of reversed HEXA8 and PENTA6
conn = [0, 1, 4, 3, 5, 6, 9, 8, 1, 2, 4, 6, 7, 9]
mesh.insertNextCell(NORM_HEXA8, 8, conn[0 : 0 + 8])
mesh.insertNextCell(NORM_PENTA6, 6, conn[8 : 8 + 6])
mesh.finishInsertingCells()

Now we check that findAndCorrectBadOriented3DExtrudedCells() finds and fixes the reversed cells.

fixedCells = mesh.findAndCorrectBadOriented3DExtrudedCells()
assert len(fixedCells) == 2 # 2 cells fixed
fixedCells = mesh.findAndCorrectBadOriented3DExtrudedCells()
assert len(fixedCells) == 0 # no bad cells

Fixing orientation of polyhedra

First, we create a mesh with 2 polyhedra, one of which is incorrectly oriented. We create two "extruded" polyhedra and then convert them to correctly defined polyhedra.

# 2D coordinates of 5 base nodes
coords = [-0.3, -0.3, 0.2, -0.3, 0.7, -0.3, -0.3, 0.2, 0.2, 0.2]
coordsArr = DataArrayDouble(coords, 5, 2)
# coordinates of 5 top nodes
coordsArr2 = coordsArr.deepCopy()
# 3D coordinates of base + top nodes
coordsArr = coordsArr.changeNbOfComponents(3, 0)
coordsArr2 = coordsArr2.changeNbOfComponents(3, 1)
coordsArr = DataArrayDouble.Aggregate([coordsArr, coordsArr2])
# mesh
mesh = MEDCouplingUMesh()
mesh.setCoords(coordsArr)
mesh.setMeshDimension(3)
mesh.allocateCells(2)
# connectivity of a HEXA8 + a reversed PENTA6
conn = [0, 3, 4, 1, 5, 8, 9, 6, 1, 2, 4, 6, 7, 9]
mesh.insertNextCell(NORM_POLYHED, 8, conn[0 : 0 + 8]) # "extruded" polyhedron
mesh.insertNextCell(NORM_POLYHED, 6, conn[8 : 8 + 6])
mesh.finishInsertingCells()
# fix connectivity of NORM_POLYHED's
mesh.convertExtrudedPolyhedra()

Now we check that arePolyhedronsNotCorrectlyOriented() finds one reversed cell. After that we fix it using orientCorrectlyPolyhedrons() and re-check the orientation of polyhedra.

badCells = mesh.arePolyhedronsNotCorrectlyOriented()
assert len(badCells) == 1 # one polyhedron is KO
# fix invalid rolyherdons
mesh.orientCorrectlyPolyhedrons()
# re-check the orientation
badCells = mesh.arePolyhedronsNotCorrectlyOriented()
assert len(badCells) == 0 # connectivity is OK

Fixing orientation of faces

First, we create a 2D mesh in 3D space with 3 QUAD4 and 2 TRI3 cells. Orientation of the cell #1 is reversed comparing with others.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 2, 4, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)
mesh.changeSpaceDimension(3)

Now we check that are2DCellsNotCorrectlyOriented() finds one reversed face. After that we fix the incorrectly oriented cell using orientCorrectly2DCells() and re-check the orientation of cells.

vec = [0.0, 0.0, -1.0]
badCellIds = mesh.are2DCellsNotCorrectlyOriented(vec, False)
assert len(badCellIds) == 1 # one cell is reversed
# fix orientation
mesh.orientCorrectly2DCells(vec, False)
# re-check orientation
badCellIds = mesh.are2DCellsNotCorrectlyOriented(vec, False)
assert len(badCellIds) == 0 # the orientation is OK

Alternatively you can orient all 2D cells equally using the first cell as a reference:

mesh.orientCorrectly2DCells(None)

Also it is possible to orient some selected 2D cells by using another group of cells as the reference:

refCells = [0, 2]
objCells = [1, 3]
refGroup = mesh.buildPartOfMySelf(refCells)
objGroup = mesh.buildPartOfMySelf(objCells)
objGroup.orientCorrectly2DCells(refGroup)
mesh.setPartOfMySelf(objCells, objGroup)

Renumbering nodes in the connectivity array

First, we create a 2D mesh with 1 QUAD4 cell and with undefined coordinates of nodes.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(1)
conn = [4, 3, 2, 1]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4])
mesh.finishInsertingCells()

Now we use renumberNodesInConn() to get the following nodal connectivity of a sole cell: 0,1,2,3.

old2newIds = [-1, 3, 2, 1, 0]
mesh.renumberNodesInConn(old2newIds)
nodes0 = mesh.getNodeIdsOfCell(0)
assert nodes0 == [0, 1, 2, 3]

old2newIds array defines how node ids are changed:

  • new id of node #0 is -1,
  • new id of node #1 is 3,
  • new id of node #2 is 4,
  • new id of node #3 is 1,
  • new id of node #4 is 0.

Renumbering nodes

First, we create a 2D mesh with 4 nodes and no cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
coords = [-0.3, -0.3, 0.2, -0.3, 0.7, -0.3, -0.3, 0.3]
coordsArr = DataArrayDouble(coords, 4, 2)
mesh.setCoords(coordsArr)
mesh.allocateCells(0)
mesh.finishInsertingCells()

Next, we use renumberNodes() to permute nodes so that

  • old node #0 becomes #2,
  • old node #1 remains #1,
  • old node #2 becomes #0,
  • old node #3 is removed.

Number of nodes becomes 3.

mesh.renumberNodes([2, 1, 0, -1], 3)
coordsArr = mesh.getCoords() # get a shorten array
assert coordsArr.getValues() == [0.7, -0.3, 0.2, -0.3, -0.3, -0.3]

Next we compare behavior of renumberNodes() and that of renumberNodes2() which, in contrast to renumberNodes(), moves merged nodes to their barycenter.
We set #2 as new id of old node #3 and expect that renumberNodes2() moves old nodes #0 and #3 to their barycenter (-0.3,0.0) which becomes position of node #2.

coordsArr.setValues(coords, 4, 2) # restore old nodes
mesh.renumberNodesCenter([2, 1, 0, 2], 3)
coordsArr = mesh.getCoords() # get a shorten array
assert coordsArr.getValues() == [0.7, -0.3, 0.2, -0.3, -0.3, 0.0]

Merging equal nodes

First, we create a 2D mesh with 1 QUAD4 and 2 TRI3 cells. The cells are based on 6 nodes of which 2 nodes fully coincide (#3 and #4) and 3 nodes are equal with precision 0.003.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4])
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7])
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10])
mesh.finishInsertingCells()
coords = [
0.3,
-0.301, # 0
0.2,
-0.3, # 1
0.3,
-0.302, # 2 ~~ 0
1.1,
0.0, # 3
1.1,
0.0, # 4 == 3
0.3,
-0.303,
] # 5 ~~ 0
coordsArr = DataArrayDouble(coords, 6, 2)
mesh.setCoords(coordsArr)

Now we merge node duplicates using mergeNodes() and check values it returns.

arr, areNodesMerged, newNbOfNodes = mesh.mergeNodes(0.004)
assert arr.getValues() == [0, 1, 0, 2, 2, 0]
assert areNodesMerged
assert newNbOfNodes == 3

Contents of arr shows ids of old nodes after the merging. The nodes considered equal one to the other have the same id in arr.

Next we compare behavior of mergeNodes() and that of mergeNodes2() which, in contrast to mergeNodes(), moves merged nodes to their barycenter.
We expect that mergeNodes2() moves old nodes #0, #2 and #5 to their barycenter equal to position of node #2.
First we check that mergeNodes() does not move nodes coincident with the node #2 to the position of node #2, and then we check that mergeNodes2() does move. (We check only the second (Y) component of node coordinates since the first component of these nodes is exactly same.)

baryCoords2 = coords[2 * 2 :] # initial coordinates of node #2
coordsArr = mesh.getCoords() # retrieve a new shorten coord array
self.assertNotAlmostEqual(
baryCoords2[1], coordsArr.getIJ(0, 1), 13
) # Y of node #0 differs from that of baryCoords2
# restore coordinates
coordsArr = DataArrayDouble(coords, 6, 2)
mesh.setCoords(coordsArr)
# call mergeNodesCenter()
mesh.mergeNodesCenter(0.004)
coordsArr = mesh.getCoords() # retrieve a new shorten coord array
self.assertAlmostEqual(
baryCoords2[1], coordsArr.getIJ(0, 1), 13
) # Y of node #0 equals to that of baryCoords2

Removing cell duplicates

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells, so that

  • the cell #2 has the same nodal connectivity as the cell #1 does,
  • the cell #3 has the same nodal connectivity as the cell #0 does,
  • the cell #4 is based on the same nodes as the cell #0 but nodes order is different.
mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 2 == 1
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 3 == 0
mesh.insertNextCell(NORM_QUAD4, 4, conn[2:4] + conn[0:2]) # 4 ~~ 0
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Now we use zipConnectivityTraducer() to remove duplicate cells. Then we check that two cells, having exactly same nodal connectivity with other cells, have been removed.

oldNbCells = mesh.getNumberOfCells()
arr = mesh.zipConnectivityTraducer(0)
assert mesh.getNumberOfCells() == oldNbCells - 2
assert arr.getValues() == [0, 1, 1, 0, 2]

Contents of arr shows ids of cells after duplicates removal. If a value (cell id) equals to its index in arr, this means that the cell is not a duplicate of any cell with lower id. Else, the value gives a cell id to which this cell is equal.
Thus, the cells #0 and #1 have no preceding equal cell since arr[i] == i.
The cell #2 equals to the cell #1 (== arr[2] ).
The cell #3 equals to the cell #0 (== arr[3] ).
The cell #4 has no equal cell. This is because the cell comparison technique specified when we called zipConnectivityTraducer() was 0 ("exact"), if we had used the technique 2 ("nodal"), arr[4] would be 0.

Removing unused nodes

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4])
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7])
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10])
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14])
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18])
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Now we create mesh2 including all nodes but only two cells of mesh, and we use zipCoordsTraducer() to remove unused nodes from mesh2. zipCoordsTraducer() returns an array with -1 for unused nodes and new ids for used ones.

cellIds = [1, 2]
mesh2 = mesh.buildPartOfMySelf(cellIds, True)
arr = mesh2.zipCoordsTraducer()
assert mesh2.getNumberOfNodes() == 4 # nb of nodes decreased
assert arr.getValues() == [
-1,
0,
1,
-1,
2,
3,
-1,
-1,
-1,
] # -1 for unused nodes

Retrieving unused nodes

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4])
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7])
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10])
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14])
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18])
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Now we create mesh2 including all nodes but only two cells of mesh, and we use getNodeIdsInUse() to get nodes of mesh2 used in its two cells. getNodeIdsInUse() returns an array with -1 for unused nodes and new ids for used ones.

cellIds = [1, 2]
mesh2 = mesh.buildPartOfMySelf(cellIds, True)
arr, newNbOfNodes = mesh2.getNodeIdsInUse()
assert arr.getValues() == [-1, 0, 1, -1, 2, 3, -1, -1, -1]

Now we use newNbOfNodes returned by getNodeIdsInUse() to convert arr to "New to Old" mode.

arr2 = arr.invertArrayO2N2N2O(newNbOfNodes)
assert arr2.getValues() == [1, 2, 4, 5]

Conversion of cells to "poly" types

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Now we convert cells #1 and #3 to type POLYGON and check the result

cells = [1, 3]
mesh.convertToPolyTypes(cells)
assert mesh.getTypeOfCell(0) == NORM_QUAD4
assert mesh.getTypeOfCell(1) == NORM_POLYGON, mesh.getTypeOfCell(1)
assert mesh.getTypeOfCell(2) == NORM_TRI3
assert mesh.getTypeOfCell(3) == NORM_POLYGON

Scaling the mesh

First, we create a 2D mesh with 4 nodes and no cells.

coords = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0] # 2D coordinates of 4 nodes
coordsArr = DataArrayDouble(coords, 4, 2)
mesh = MEDCouplingUMesh()
mesh.setCoords(coordsArr)
initCoords = coordsArr.deepCopy()

Then we scale it by a factor of 2 with a center (0.,0.).

center = [0.0, 0.0]
factor = 2.0
mesh.scale(center, factor)

Finally we check that all node coordinates have changed by more than 0.9.

coords2 = mesh.getCoords()
assert coords2.isEqualWithoutConsideringStr(initCoords, 1.0)
assert not coords2.isEqualWithoutConsideringStr(initCoords, 0.9)

Translating the mesh

First, we create a 2D mesh with 4 nodes and no cells.

coords = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0] # 2D coordinates of 4 nodes
coordsArr = DataArrayDouble(coords, 4, 2)
mesh = MEDCouplingUMesh()
mesh.setCoords(coordsArr)
initCoords = coordsArr.deepCopy()

Then we translate it by a vector (1.,1.).

vector = [1.0, 1.0]
mesh.translate(vector)

Finally we check that all node coordinates have changed by more than 0.9.

coords2 = mesh.getCoords()
assert coords2.isEqualWithoutConsideringStr(initCoords, 1)
assert not coords2.isEqualWithoutConsideringStr(initCoords, 0.9)

Rotating the mesh

First, we create a 2D mesh with 4 nodes and no cells.

coords = [0.0, 0.0, 0.1, 0.0, 0.1, 0.1, 0.0, 0.1] # 2D coordinates of 4 nodes
coordsArr = DataArrayDouble(coords, 4, 2)
mesh = MEDCouplingUMesh()
mesh.setCoords(coordsArr)

Then we rotate it around a point (0.,0.) by 90 degrees clockwise.

center = [0.0, 0.0]
mesh.rotate(center, -pi / 2)

Next, we make a 3D mesh from the 2D one and rotate it around the Z axis by 90 degrees counter-clockwise.

mesh.changeSpaceDimension(3)
center = [0.0, 0.0, 0.0]
vector = [0.0, 0.0, 1.0]
mesh.rotate(center, vector, pi / 2)

Finally we transform the mesh back to 2D space and check that all nodes get back to the initial location.

mesh.changeSpaceDimension(2)
coords2 = mesh.getCoords()
for i, c in enumerate(coords):
self.assertAlmostEqual(c, coords2.getIJ(0, i), 13)

Access

Getting node coordinates along an axis

We create an 1D Cartesian mesh and retrieves node coordinates using getCoordsAt().

coords = [1.0, 2.0, 4.0]
x = DataArrayDouble(coords, 3, 1)
mesh = MEDCouplingCMesh()
mesh.setCoordsAt(0, x)
x2 = mesh.getCoordsAt(0)
assert coords == x2.getValues()

Getting coordinates of a node

The following code creates a 2D MEDCouplingUMesh with 3 nodes and no cells.

coords = [-0.3, -0.3, 0.2, -0.3, 0.7, -0.3]
coordsArr = DataArrayDouble(coords, 3, 2)
mesh = MEDCouplingUMesh()
mesh.setCoords(coordsArr)

Here we get coordinates of the second node and check its two coordinates.

nodeCoords = mesh.getCoordinatesOfNode(1)
self.assertAlmostEqual(0.2, nodeCoords[0], 13)
self.assertAlmostEqual(-0.3, nodeCoords[1], 13)

Cells correspondence in two meshes

First, we create a 2D mesh1 with 3 QUAD4 and 2 TRI3 cells.

mesh1 = MEDCouplingUMesh()
mesh1.setMeshDimension(2)
mesh1.allocateCells(5)
conn = [0, 3, 4, 1, 1, 2, 4, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh1.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh1.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh1.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh1.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh1.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh1.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh1.setCoords(coordsArr)

Then we create a mesh2 which includes cells #4, #2 and #0 of mesh1. The two meshes share the same node coordinates array.

cells2 = [4, 2, 0]
mesh2 = mesh1.buildPartOfMySelf(cells2, True) # even cells selected

Now we ascertain that

  • areCellsIncludedIn() detects that all cells of mesh2 are present in mesh1,
  • the correspondence array corr2to1, which gives cell ids of mesh2 within mesh1, is equal to the array cells2 which selected cells from mesh1 for creation of mesh2.
compType = 0 # the strongest policy
isOk, corr2to1 = mesh1.areCellsIncludedIn(mesh2, compType)
assert isOk # a larger mesh1 includes a smaller mesh2
assert corr2to1.getValues() == cells2

Now we apply areCellsIncludedIn() in a reverse direction and ascertain that it returns false.

isOk, corr1to2 = mesh2.areCellsIncludedIn(mesh1, compType)
assert not isOk # the smaller mesh2 does NOT include the larger mesh1
assert corr1to2.getValues() == [2, 3, 1, 4, 0]

The contents of the correspondence array corr1to2 [2, 3, 1, 4, 0] means the following.

  • The cell #0 of mesh1 is equal to the cell #2 (== corr1to2[ 0 ]) of mesh2.
  • The cell #1 of mesh1 is missing from mesh2 (as corr1to2[ 1 ] >= mesh2->getNumberOfCells()).
  • The cell #2 of mesh1 is equal to the cell #1 (== corr1to2[ 2 ]) of mesh2.
  • The cell #3 of mesh1 is missing from mesh2 (as corr1to2[ 3 ] >= mesh2->getNumberOfCells()).
  • The cell #4 of mesh1 is equal to the cell #0 (== corr1to2[ 4 ]) of mesh2.

Deep comparison of meshes

First, we create two 2D meshes with two triangles, so that

  • their nodes are almost same but permuted,
  • the first triangle is based exactly on the same nodes (taking the permutation into account),
  • an order of nodes in the second triangle is changed.
# mesh 1
mesh1 = MEDCouplingUMesh()
mesh1.setMeshDimension(2)
coords = [
0.0,
0.0, # 0
1.0,
0.0, # 1
1.0,
1.0, # 2
0.0,
1.0,
] # 3
coordsArr = DataArrayDouble(coords, 4, 2)
mesh1.setCoords(coordsArr)
mesh1.allocateCells(2)
mesh1.insertNextCell(NORM_TRI3, 3, [0, 1, 2]) # 0
mesh1.insertNextCell(NORM_TRI3, 3, [1, 2, 3]) # 1
mesh1.finishInsertingCells()
# mesh 2
mesh2 = MEDCouplingUMesh()
mesh2.setMeshDimension(2)
coords = [
0.0,
1.0, # 0 = #3
0.0,
0.0, # 1 = #0
1.0,
0.0, # 2 = #1
1.0,
1.001,
] # 3 ~ #2
coordsArr2 = DataArrayDouble(coords, 4, 2)
mesh2.setCoords(coordsArr2)
mesh2.allocateCells(2)
mesh2.insertNextCell(NORM_TRI3, 3, [2, 3, 0]) # 0 = #1
mesh2.insertNextCell(NORM_TRI3, 3, [3, 1, 2]) # 1 ~ #0
mesh2.finishInsertingCells()

Then we check that

  • checkDeepEquivalWith() considers the meshes equal (i.e. it does not throw any exception) if it is called with a cell comparison policy cellCompPol == 1
  • mapping from mesh1 to mesh2 for both nodes and cells is as expected.
cellCompPol = 1 # "permuted same orientation" - policy of medium severity
cOld2New, nOld2New = mesh1.checkDeepEquivalWith(mesh2, cellCompPol, 0.002)
assert nOld2New.getValues() == [3, 0, 1, 2]
assert cOld2New.getValues() == [1, 0]

Next we ascertain that checkDeepEquivalOnSameNodesWith() consider mesh1 and mesh2 different as they do not share the same nodal connectivity array.
After that we make the meshes share the node coordinates array and insert new triangles based on the same nodes but in different order. This is to ascertain that checkDeepEquivalOnSameNodesWith() called with the weakest cell comparison policy considers the meshes equal.

self.assertRaises(
InterpKernelException,
mesh1.checkDeepEquivalOnSameNodesWith,
mesh2,
cellCompPol,
0.002,
)
mesh2.setCoords(coordsArr) # make meshes share the same coordinates array
mesh2.allocateCells(2)
mesh2.insertNextCell(NORM_TRI3, 3, [1, 2, 3]) # 0 = #1
mesh2.insertNextCell(NORM_TRI3, 3, [1, 0, 2]) # 1 ~ #0
mesh2.finishInsertingCells()
cellCompPol = 2 # the weakest policy
mesh1.checkDeepEquivalOnSameNodesWith(mesh2, cellCompPol, 0)

Getting barycenters of cells

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 2, 4, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Now we use getPartBarycenterAndOwner() to get barycenters of all but the first cell.

part = DataArrayInt([1, 2, 3, 4], 4, 1) # cell #0 is omitted
baryCenters = mesh.getPartBarycenterAndOwner(part)
assert len(baryCenters) == len(part)
assert baryCenters.getNumberOfComponents() == mesh.getSpaceDimension()

The returned array contains 4 tuples per 2 components.

Finding cells containing a point (multi-point case)

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 2, 4, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Then we use getCellsContainingPoints() to get cells in contact with tree points. Two of them are in contact with some cells and one is not.

pos = [
10.0,
10, # point out of the mesh
0.3,
0.3, # point located somewhere inside the mesh
coords[2],
coords[3],
] # point at the node #1
eps = 1e-4 # ball radius
cells, cellsIndex = mesh.getCellsContainingPoints(pos, 3, eps)
assert cells.getValues() == [4, 0, 1]
assert cellsIndex.getValues() == [0, 0, 1, 3]

The contents of the result arrays cells ([4, 0, 1]) and cellsIndex ([0, 0, 1, 3]) mean the following.

  • Point #0 is in contact with none (== cellsIndx[1] - cellsIndx[0]) cell.
  • Point #1 is in contact with 1 (== cellsIndx[2] - cellsIndx[1]) cell whose id is #4 (== cells[ cellsIndx[ 1 ]]).
  • Point #2 is in contact with 2 (== cellsIndx[3] - cellsIndx[2]) cells whose ids are #0 (== cells[ cellsIndx[ 2 ]]) and #1 (== cells[ cellsIndx[ 2 ] + 1 ]).

Finding cells containing a point

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 2, 4, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4])
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7])
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10])
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14])
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18])
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Then we use getCellsContainingPoint() to get cells in contact with a small ball (point with precision) located near the node #4 and shifted from this node by its radius eps.

pos4 = coords[4 * 2 :] # coordinates of the node #4
eps = 1e-4 # ball radius
pos = [pos4[0] + eps, pos4[1] - eps] # ball center
cellIds = mesh.getCellsContainingPoint(pos, eps)
assert len(cellIds) == mesh.getNumberOfCells()

Since the node #4 is shared by all cells, size of the vector cellIds must be equal to the number of cells in mesh.

Getting normals of cells

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells. Orientation of the cell #1 is reversed.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 2, 4, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Now we use buildPartOrthogonalField() to get normal vectors to the cells.

part = DataArrayInt([1, 2, 3, 4], 4, 1) # cell #0 is omitted
vecField = mesh.buildPartOrthogonalField(part)
vecArr = vecField.getArray()
assert len(vecArr) == len(part)
assert vecArr.getNumberOfComponents() == 3

Getting volumes of cells

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells. Orientation of the cell #1 is reversed.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 2, 4, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Now we use getPartMeasureField() to get volumes of all but the first cell. If we call getPartMeasureField() with isAbs == true, the area of the cell #1 is returned positive, else, negative that reflects its inverse orientation.

isAbs = True
part = DataArrayInt([1, 2, 3, 4], 4, 1) # cell #0 is omitted
areaArr = mesh.getPartMeasureField(isAbs, part)
assert areaArr[0] > 0 # orientation ignored
areaArr = mesh.getPartMeasureField(not isAbs, part)
assert areaArr[0] < 0 # orientation considered
assert len(areaArr) == len(part)

Getting cells using the bounding box

First, we create a 2D mesh with 1 TRI3 cell. Bounding box of this cell is [0.,0., 1.,1].

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
coords = [0.0, 0.0, 0.0, 1.0, 1.0, 1]
coordsArr = DataArrayDouble(coords, 3, 2)
mesh.setCoords(coordsArr)
mesh.allocateCells(1)
conn = [0, 1, 2]
mesh.insertNextCell(NORM_TRI3, 3, conn)
mesh.finishInsertingCells()

Now we check how getCellsInBoundingBox() searches for cells using the bounding box. We use a bounding box touching the bounding box of the sole cell at one point (1.,1.).

bbox = [1.0, 1.0, 1.001, 1.001] # xMin, xMax, yMin, yMax
cellsInBox = mesh.getCellsInBoundingBox(bbox, 0.0)
assert cellsInBox.getValues() == []
cellsInBox = mesh.getCellsInBoundingBox(bbox, 0.1)
assert cellsInBox.getValues() == [0]

If getCellsInBoundingBox() is called with parameter eps == 0.0, the cell is not found because the two bounding boxes (one of the cell and the one passed as parameter) do not overlap.
If getCellsInBoundingBox() is called with parameter eps == 0.1, the cell is found because eps is used to increase the bounding box of the cell and thus the two bounding boxes intersect each other.

Getting boundary nodes

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4])
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7])
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10])
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14])
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18])
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Now we use findBoundaryNodes() to get ids of boundary nodes.

nodeIdsArr = mesh.findBoundaryNodes()
assert nodeIdsArr.getNumberOfTuples() == mesh.getNumberOfNodes() - 1

findBoundaryNodes() returns all node ids except the node #4 which is in the middle of mesh.

Getting cells by nodes

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

In the following code we retrieve nodes of the cell #0 an then we call getCellIdsLyingOnNodes() twice with these nodes and with varying last parameter allNodes as input.

nodeIds = mesh.getNodeIdsOfCell(0)
allNodes = True
cellIdsArr1 = mesh.getCellIdsLyingOnNodes(nodeIds, allNodes)
cellIdsArr2 = mesh.getCellIdsLyingOnNodes(nodeIds, not allNodes)
assert cellIdsArr1.getNumberOfTuples() == 1 # cell #0 is found only
assert (
cellIdsArr2.getNumberOfTuples() == mesh.getNumberOfCells()
) # all cells are found


If the last parameter is true getCellIdsLyingOnNodes() looks for cells whose all nodes are given to it, hence it finds the cell #0 only.
If the last parameter is false getCellIdsLyingOnNodes() looks for any cell whose nodes are given to it, hence it finds all cells of mesh because all cells share the node #4.

Getting cells by nodes

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4])
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7])
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10])
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14])
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18])
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

In the following code we retrieve nodes of two cells an then we use getCellIdsFullyIncludedInNodeIds() to find these cells by their nodes.

cellIds = [1, 2]
nodeIds = mesh.getNodeIdsOfCell(cellIds[0])
nodeIds += mesh.getNodeIdsOfCell(cellIds[1])
cellIdsArr = mesh.getCellIdsFullyIncludedInNodeIds(nodeIds)
assert cellIdsArr.getValues() == cellIds

Retrieving the descending connectivity with orientation

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Now we get and check the descending connectivity.

mesh2, desc, descIndx, revDesc, revDescIndx = (
mesh.buildDescendingConnectivity2()
)
assert desc.getValues() == [
1,
2,
3,
4,
-3,
5,
6,
7,
8,
-5,
9,
10,
-2,
11,
12,
13,
-7,
-10,
]
assert descIndx.getValues() == [0, 4, 7, 10, 14, 18]
assert revDesc.getValues() == [
0,
0,
3,
0,
1,
0,
1,
2,
1,
2,
4,
2,
3,
3,
4,
3,
4,
4,
]
assert revDescIndx.getValues() == [
0,
1,
3,
5,
6,
8,
9,
11,
12,
13,
15,
16,
17,
18,
]

Here we get connectivity of the cell #2 (#3 in FORTRAN mode) of mesh2 to see how mutual orientation of cells in mesh and mesh2 is defined.

assert mesh2.getNodeIdsOfCell(3 - 1) == [4, 1] # cell #3 in FORTRAN mode

The contents of the result arrays desc and descIndx mean the following.

  • The cell #0 of mesh (QUAD4) is bound by 4 (== descIndx[1] - descIndx[0]) segments (SEG2) of mesh2 whose ids in FORTRAN mode are
    • #1 (== desc[ descIndx[ 0 ]]),
    • #2 (== desc[ descIndx[ 0 ] + 1 ]),
    • #3 (== desc[ descIndx[ 0 ] + 2 ]) and
    • #4 (== desc[ descIndx[ 0 ] + 3 ]).
      Ids are positive since order of nodes in the corresponding cells of mesh and mesh2 are same. For example nodes of SEG2 #3 are [4,1] and nodes of QUAD4 #0 are [0,3,4,1].
  • The cell #1 of mesh (TRI3) is bound by 3 (== descIndx[2] - descIndx[1]) segments of mesh2 whose ids in FORTRAN mode are:
    • #-3 (== desc[ descIndx[ 1 ]]),
    • #5 (== desc[ descIndx[ 1 ] + 1 ]) and
    • #6 (== desc[ descIndx[ 1 ] + 2 ]).
      The id -3 means that order of nodes in SEG2 #3 ([4,1]) is different from the order of these nodes in TRI3 #1: [1,4,2].
  • etc.

The contents of the result arrays revDesc and revDescIndx mean the following.

  • The cell #0 of mesh2 (SEG2) bounds 1 (== revDescIndx[1] - revDescIndx[0]) cell of mesh whose id is:
    • # 0 (== revDesc[ revDescIndx[ 0 ]]).
  • The cell #1 of mesh2 bounds 2 (== revDescIndx[2] - revDescIndx[1]) cells of mesh whose ids are:
    • # 0 (== revDesc[ revDescIndx[ 1 ]]) and
    • # 1 (== revDesc[ revDescIndx[ 1 ] + 1 ]).
  • etc.

Retrieving the descending connectivity

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Now we get and check the descending connectivity.

mesh2, desc, descIndx, revDesc, revDescIndx = mesh.buildDescendingConnectivity()
assert desc.getValues() == [
0,
1,
2,
3,
2,
4,
5,
6,
7,
4,
8,
9,
1,
10,
11,
12,
6,
9,
]
assert descIndx.getValues() == [0, 4, 7, 10, 14, 18]
assert revDesc.getValues() == [
0,
0,
3,
0,
1,
0,
1,
2,
1,
2,
4,
2,
3,
3,
4,
3,
4,
4,
]
assert revDescIndx.getValues() == [
0,
1,
3,
5,
6,
8,
9,
11,
12,
13,
15,
16,
17,
18,
]

The contents of the result arrays desc and descIndx mean the following.

  • The cell #0 of mesh (QUAD4) is bound by 4 (== descIndx[1] - descIndx[0]) segments (SEG2) of mesh2 whose ids are
    • #0 (== desc[ descIndx[ 0 ]]),
    • #1 (== desc[ descIndx[ 0 ] + 1 ]),
    • #2 (== desc[ descIndx[ 0 ] + 2 ]) and
    • #3 (== desc[ descIndx[ 0 ] + 3 ]).
  • The cell #1 of mesh (TRI3) is bound by 3 (== descIndx[2] - descIndx[1]) segments of mesh2 whose ids are:
    • #2 (== desc[ descIndx[ 1 ]]),
    • #4 (== desc[ descIndx[ 1 ] + 1 ]) and
    • #5 (== desc[ descIndx[ 1 ] + 2 ]).
  • etc.

The contents of the result arrays revDesc and revDescIndx mean the following.

  • The cell #0 of mesh2 (SEG2) bounds 1 (== revDescIndx[1] - revDescIndx[0]) cell of mesh whose id is:
    • # 0 (== revDesc[ revDescIndx[ 0 ]]).
  • The cell #1 of mesh2 bounds 2 (== revDescIndx[2] - revDescIndx[1]) cells of mesh whose ids are:
    • # 0 (== revDesc[ revDescIndx[ 1 ]]) and
    • # 1 (== revDesc[ revDescIndx[ 1 ] + 1 ]).
  • etc.

Getting the reverse nodal connectivity

First, we create a 2D mesh with 3 QUAD4 and 2 TRI3 cells.

mesh = MEDCouplingUMesh()
mesh.setMeshDimension(2)
mesh.allocateCells(5)
conn = [0, 3, 4, 1, 1, 4, 2, 4, 5, 2, 6, 7, 4, 3, 7, 8, 5, 4]
mesh.insertNextCell(NORM_QUAD4, 4, conn[0:4]) # 0
mesh.insertNextCell(NORM_TRI3, 3, conn[4:7]) # 1
mesh.insertNextCell(NORM_TRI3, 3, conn[7:10]) # 2
mesh.insertNextCell(NORM_QUAD4, 4, conn[10:14]) # 3
mesh.insertNextCell(NORM_QUAD4, 4, conn[14:18]) # 4
mesh.finishInsertingCells()
coords = [
-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,
]
coordsArr = DataArrayDouble(coords, 9, 2)
mesh.setCoords(coordsArr)

Now we get and check its reverse nodal connectivity.

revNodal, revNodalIndx = mesh.getReverseNodalConnectivity()
assert revNodal.getValues() == [
0,
0,
1,
1,
2,
0,
3,
0,
1,
2,
3,
4,
2,
4,
3,
3,
4,
4,
]
assert revNodalIndx.getValues() == [0, 1, 3, 5, 7, 12, 14, 15, 17, 18]

The contents of the result arrays mean the following.

  • Node #0 is shared by 1 (== revNodalIndx[1] - revNodalIndx[0]) cell whose id is #0 (== revNodal[ revNodalIndx[ 0 ]]).
  • Node #1 is shared by 2 (== revNodalIndx[2] - revNodalIndx[1]) cells whose ids are #0 (== revNodal[ revNodalIndx[ 1 ]]) and #1 (== revNodal[ revNodalIndx[ 1 ] + 1 ]).
  • etc.

Getting a minimum box bounding nodes

First, we create a 3D mesh with 2 nodes, so that the first one has minimal coordinates and the second one has maximal coordinates.

cc = [
0.0,
0.1,
0.2, # 3D coordinates of 2 nodes
2.0,
2.1,
2.2,
]
coordsArr = DataArrayDouble(cc, 2, 3)
mesh = MEDCouplingUMesh()
mesh.setCoords(coordsArr)

Now we get a bounding box enclosing these nodes. This bounding box should contain coordinates of our two nodes (but in "no interlace" mode), as the nodes coincide with points returned by the bounding box.

bbox = mesh.getBoundingBox()
assert bbox == [
(cc[0], cc[3]), # NOTE: list of 3 tuples is retirned!
(cc[1], cc[4]),
(cc[2], cc[5]),
]

Getting nodes close to a point

The following code creates a 2D MEDCouplingUMesh with 5 nodes and no cells.

# 2D coordinates of 5 nodes
coords = [
0.3,
-0.301, # 0
0.2,
-0.3, # 1
0.3,
-0.302, # 2
1.1,
0.0, # 3
0.3,
-0.30299999999999,
] # 4
coordsArr = DataArrayDouble(coords, 5, 2)
mesh = MEDCouplingUMesh()
mesh.setCoords(coordsArr)

Now we define an array of coordinates of a point close to nodes #0, #2 and #4.

Thus we expect that getNodeIdsNearPoint() that we are going to use, if called with eps = 0.003, would return ids of nodes #0, #2 and #4.

point = [0.3, -0.3] # point close to nodes #0, #2 and #4
ids = mesh.getNodeIdsNearPoint(point, 0.003)
assert ids.getValues() == [0, 2, 4]

Getting nodes close to some points

The following code creates a 2D MEDCouplingUMesh with 7 nodes and no cells.

# 2D coordinates of 7 nodes
coords = [
0.3,
-0.301, # 0
0.2,
-0.3, # 1
0.3,
-0.302, # 2
1.1,
0.0, # 3
1.1,
0.0, # 4
1.1,
0.002, # 5
0.3,
-0.303,
] # 6
coordsArr = DataArrayDouble(coords, 7, 2)
mesh = MEDCouplingUMesh()
mesh.setCoords(coordsArr)

Now we define an array of coordinates of 3 points near which we want to find nodes of the mesh.

  • Point #0 is at distance 0.001 from the node #1.
  • Point #1 is rather far from all nodes.
  • Point #2 is close to nodes #3, #4 and #5.

Thus we expect that getNodeIdsNearPoints() that we are going to use, if called with eps = 0.003, would return ids of close nodes #1, #3, #4 and #5.

points = [
0.2,
-0.301, # ~ node #1
0.0,
0.0,
1.1,
0.002,
] # ~ nodes #3, #4 and #5
ids, idsIndex = mesh.getNodeIdsNearPoints(points, 3, 0.003)
assert ids.getValues() == [1, 3, 4, 5]
assert idsIndex.getValues() == [0, 1, 1, 4]

idsIndex returns [0, 1, 1, 4] which means that:

  • Point #0 is close to 1 (== idsIndex[1] - idsIndex[0]) node whose id is ids[ idsIndex[ 0 ]].
  • Point #1 is close to 0 (== idsIndex[2] - idsIndex[1]) nodes.
  • Point #2 is close to 3 (== idsIndex[3] - idsIndex[2]) nodes whose ids are ids[ idsIndex[ 2 ]], ids[ idsIndex[ 2 ] + 1 ] and ids[ idsIndex[ 2 ] + 2 ].

Finding coincident nodes

First, we create a mesh with 6 nodes, of which two nodes (#3 and #4) are fully coincident and 3 nodes (#0, #2 and #5) have distance less than 0.004 between them.

coords = [
0.3,
-0.301, # 0
0.2,
-0.3, # 1
0.3,
-0.302, # 2
1.1,
0.0, # 3
1.1,
0.0, # 4
0.3,
-0.303,
] # 5
coordsArr = DataArrayDouble(coords, 6, 2)
mesh = MEDCouplingUMesh()
mesh.setCoords(coordsArr)

Then, we use findCommonNodes() to find coincident nodes, and check that (1) calling findCommonNodes() with prec == 1e-13 finds the two fully coincident nodes only and (2) findCommonNodes(0.004) finds 5 equal nodes.

comm, commI = mesh.findCommonNodes(1e-13)
assert comm.getValues() == [3, 4]
comm, commI = mesh.findCommonNodes(0.004)
assert comm.getValues() == [0, 2, 5, 3, 4]

Arrays

Create

Building an array from scratch in Python

Building a double array from scratch in Python

Let's consider a list of floats dataDouble.

dataDouble = [
0.0,
10.0,
20.0,
1.0,
11.0,
21.0,
2.0,
12.0,
22.0,
3.0,
13.0,
23.0,
4.0,
14.0,
24.0,
]

The easiest way to build the DataArrayDouble instance called arrayDouble simply call :

arrayDouble = DataArrayDouble(dataDouble, 5, 3)

An another way is to do that :

arrayDouble = DataArrayDouble()
arrayDouble.setValues(dataDouble, 5, 3) # 5 tuples containing each 3 components

Building an int array from scratch in Python

Let's consider a list of ints dataInt.

dataInt = [0, 10, 20, 1, 11, 21, 2, 12, 22, 3, 13, 23, 4, 14, 24]

The easiest way to build the DataArrayInt instance called arrayInt simply call :

arrayInt = DataArrayInt(dataInt, 5, 3)

An another way is to do that :

arrayInt = DataArrayInt()
arrayInt.setValues(dataInt, 5, 3) # 5 tuples containing each 3 components

Building a permutation array

Here we create two arrays containing same values but in different order and then we use DataArrayInt::buildPermutationArr() to get an array showing in what places the values of b array are located in a array.

a = DataArrayInt()
a.setValues([4, 5, 6, 7, 8], 5, 1)
b = DataArrayInt()
b.setValues([5, 4, 8, 6, 7], 5, 1)
c = a.buildPermutationArr(b)

The result array c contains [1,0,4,2,3].

Modify

Inverting renumbering maps

invertArrayO2N2N2O()

In this example we create a DataArrayInt containing a renumbering map in "Old to New" mode, convert it into the renumbering map in "New to Old" mode and check the result.

arr1 = [2, 0, 4, 1, 5, 3]
da = DataArrayInt()
da.setValues(arr1, 6, 1)
da2 = da.invertArrayO2N2N2O(6)
expected1 = [1, 3, 0, 5, 2, 4]
for i in range(6):
self.assertEqual(expected1[i], da2.getIJ(i, 0))
pass


invertArrayN2O2O2N()

In this example we create a DataArrayInt containing a renumbering map in "New to Old" mode, convert it into the renumbering map in "Old to New" mode and check the result.

arr1 = [2, 0, 4, 1, 5, 3]
da = DataArrayInt()
da.setValues(arr1, 6, 1)
da2 = da.invertArrayN2O2O2N(7)
expected1 = [1, 3, 0, 5, 2, 4, -1]
for i in range(6):
self.assertEqual(expected1[i], da2.getIJ(i, 0))
pass

Set part of values of DataArrayDouble

setSelectedComponents()

First, we create a 'source' array.

array1 = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
da = DataArrayDouble(array1, 3, 2)
da.setInfoOnComponents(["a1", "a2"])

Now we create a larger zero array and assign the array da into it.

dv = DataArrayDouble()
dv.alloc(4, 4)
dv.fillWithZero()
dv.setInfoOnComponents(["v1", "v2", "v3", "v4"])
dv2 = dv.deepCopy()
dv.setSelectedComponents(da, [1, 0])

As result contents of the array dv are as follows.

Info of components : "a2"   "a1"   "v3"   "v4"
    Tuple #0 : 2 1 0 0
    Tuple #1 : 4 3 0 0
    Tuple #2 : 6 5 0 0
    Tuple #3 : 0 0 0 0

The same result can be achieved other way (except that component info is not copied):

dv2[:3, [1, 0]] = da
self.assertTrue(dv.isEqualWithoutConsideringStr(dv2, 1e-20))


setPartOfValues1()

We create two arrays:

  • a "large" (4x4) zero array da to assign to and
  • a smaller (2x2) array dv filled with values [7.,8.,9.,10].
da = DataArrayDouble()
da.alloc(4, 4)
da.setInfoOnComponents(["v1", "v2", "v3", "v4"])
#
dv = DataArrayDouble()
dv.alloc(4, 1)
dv.iota(7)
dv.rearrange(2)
dv.setInfoOnComponents(["a1", "a2"])

Now we copy dv to the middle of da.

da.fillWithZero()
da.setPartOfValues1(dv, 1, 3, 1, 1, 3, 1, True)

As result contents of the array da are as follows.

    Info of components :"v1"   "v2"   "v3"   "v4"
    Tuple #0 : 0 0 0 0
    Tuple #1 : 0 7 8 0
    Tuple #2 : 0 9 10 0
    Tuple #3 : 0 0 0 0

Here we re-fill da with zeros and copy dv into a component of da.

Note that the last parameter strictCompoCompare should be False in this case, else MEDCoupling::DataArrayDouble::setPartOfValues1() throws an exception because da has 2 components but only one target component is specified.

da.fillWithZero()
da.setPartOfValues1(dv, 0, 4, 1, 1, 2, 1, False)
    Tuple #0 : 0 7 0 0
    Tuple #1 : 0 8 0 0
    Tuple #2 : 0 9 0 0
    Tuple #3 : 0 10 0 0

Below more two variants of location of target values are shown.

da.fillWithZero()
da.setPartOfValues1(dv, 1, 2, 1, 0, 4, 1, False)
    Tuple #0 : 0 0 0 0
    Tuple #1 : 7 8 9 10
    Tuple #2 : 0 0 0 0
    Tuple #3 : 0 0 0 0
da.fillWithZero()
da.setPartOfValues1(dv, 0, 3, 2, 1, 4, 2, True)
    Tuple #0 : 0 7 0 8
    Tuple #1 : 0 0 0 0
    Tuple #2 : 0 9 0 10
    Tuple #3 : 0 0 0 0

The same result can be achieved other way:

da2 = da.deepCopy()
da2.fillWithZero()
da2[0:3:2, 1:4:2] = dv
self.assertTrue(da.isEqual(da2, 1e-20))


setPartOfValuesSimple1()

We create an array (4x4) da to assign to and define a value dv to assign.

da = DataArrayDouble()
da.alloc(4, 4)
dv = 7

Now we assign dv to the middle of da.

da.fillWithZero()
da.setPartOfValuesSimple1(dv, 1, 3, 1, 1, 3, 1)

As result contents of the array da are as follows.

    Tuple #0 : 0 0 0 0
    Tuple #1 : 0 7 7 0
    Tuple #2 : 0 7 7 0
    Tuple #3 : 0 0 0 0

Here we re-fill da with zeros and assign dv to a component of da.

da.fillWithZero()
da.setPartOfValuesSimple1(dv, 0, 4, 1, 1, 2, 1)
    Tuple #0 : 0 7 0 0
    Tuple #1 : 0 7 0 0
    Tuple #2 : 0 7 0 0
    Tuple #3 : 0 7 0 0

Below more two variants of location of target values are shown.

da.fillWithZero()
da.setPartOfValuesSimple1(dv, 1, 2, 1, 0, 4, 1)
    Tuple #0 : 0 0 0 0
    Tuple #1 : 7 7 7 7
    Tuple #2 : 0 0 0 0
    Tuple #3 : 0 0 0 0
da.fillWithZero()
da.setPartOfValuesSimple1(dv, 0, 3, 2, 1, 4, 2)
    Tuple #0 : 0 7 0 7
    Tuple #1 : 0 0 0 0
    Tuple #2 : 0 7 0 7
    Tuple #3 : 0 0 0 0

The same result can be achieved other way:

da2 = da.deepCopy()
da2.fillWithZero()
da2[0:3:2, 1:4:2] = dv
self.assertTrue(da.isEqual(da2, 1e-20))


setPartOfValuesSimple2()

We create an array (4x4) da to assign to and define a value dv to assign.

da = DataArrayDouble()
da.alloc(4, 4)
dv = 7

Now we assign dv to the middle of da. We explicitly specify tuples and component to assign to by a list [1,2].

da.fillWithZero()
da[[1, 2], [1, 2]] = dv

As result contents of the array da are as follows.

    Tuple #0 : 0 0 0 0
    Tuple #1 : 0 7 7 0
    Tuple #2 : 0 7 7 0
    Tuple #3 : 0 0 0 0

Here we re-fill da with zeros and assign dv to a component of da.

da.fillWithZero()
da[[0, 1, 2, 3], [1]] = dv
    Tuple #0 : 0 7 0 0
    Tuple #1 : 0 7 0 0
    Tuple #2 : 0 7 0 0
    Tuple #3 : 0 7 0 0

Below more two variants of location of target values are shown.

da.fillWithZero()
da[[1], [0, 1, 2, 3]] = dv
    Tuple #0 : 0 0 0 0
    Tuple #1 : 7 7 7 7
    Tuple #2 : 0 0 0 0
    Tuple #3 : 0 0 0 0
da.fillWithZero()
da[[0, 2], [1, 3]] = dv
    Tuple #0 : 0 7 0 7
    Tuple #1 : 0 0 0 0
    Tuple #2 : 0 7 0 7
    Tuple #3 : 0 0 0 0
Note
MEDCoupling::DataArrayDouble::setPartOfValuesSimple2() can't be explicitly called in Python.


setPartOfValuesSimple3()

We create an array (4x4) da to assign to and define a value dv to assign.

da = DataArrayDouble()
da.alloc(4, 4)
dv = 7

Now we assign dv to the middle of da. We explicitly specify tuples to assign to by a list [1,2]. And we specify components to assign to using slicing: 1:3.

da.fillWithZero()
da[[1, 2], 1:3] = dv

As result contents of the array da are as follows.

    Tuple #0 : 0 0 0 0
    Tuple #1 : 0 7 7 0
    Tuple #2 : 0 7 7 0
    Tuple #3 : 0 0 0 0

Here we re-fill da with zeros and assign dv to a component of da.

da.fillWithZero()
da[[0, 1, 2, 3], 1:2] = dv
    Tuple #0 : 0 7 0 0
    Tuple #1 : 0 7 0 0
    Tuple #2 : 0 7 0 0
    Tuple #3 : 0 7 0 0

Below more two variants of location of target values are shown.

da.fillWithZero()
da[[1], 0:4] = dv
    Tuple #0 : 0 0 0 0
    Tuple #1 : 7 7 7 7
    Tuple #2 : 0 0 0 0
    Tuple #3 : 0 0 0 0
da.fillWithZero()
da[[0, 2], 1:4:2] = dv
    Tuple #0 : 0 7 0 7
    Tuple #1 : 0 0 0 0
    Tuple #2 : 0 7 0 7
    Tuple #3 : 0 0 0 0
Note
MEDCoupling::DataArrayDouble::setPartOfValuesSimple3() can't be explicitly called in Python.


setPartOfValues2()

We create two arrays:

  • a "large" (4x7) zero array da to assign to,
  • a smaller (3x2) array dv filled with values [7.,8.,9.,10.,11.,12.].
da = DataArrayDouble()
da.alloc(4, 7)
#
dv = DataArrayDouble()
dv.alloc(6, 1)
dv.iota(7)
dv.rearrange(2)

Now we assign the two components of dv to the components of da with indices [1,3], and the 3 tuples of dv to the 3 tuples of da with indices [0,1,2]. This is the first mode of usage.

da.fillWithZero()
da[[0, 1, 2], [1, 3]] = dv

As result contents of the array da are as follows.

    Tuple #0 : 0  7  0  8  0  0  0
    Tuple #1 : 0  9  0 10  0  0  0
    Tuple #2 : 0 11  0 12  0  0  0
    Tuple #3 : 0  0  0  0  0  0  0

Every value of dv has been assigned to its own location within da.

Now we re-fill da with zeros and rearrange dv to have 6 components. And we assign dv to the tuples of da with indices [0,2,3] . This is the second mode of usage.

da.fillWithZero()
dv.rearrange(6)
da[[0, 2, 3], [0, 2, 3, 4, 5, 6]] = dv

The contents of dv have been assigned to each of specified tuples of da. Every value of dv is repeated in the 3 specified tuples within da.

    Tuple #0 : 7  0  8  9 10 11 12
    Tuple #1 : 0  0  0  0  0  0  0
    Tuple #2 : 7  0  8  9 10 11 12
    Tuple #3 : 7  0  8  9 10 11 12
Note
MEDCoupling::DataArrayDouble::setPartOfValues2() can't be explicitly called in Python.


setPartOfValues3()

We create two arrays:

  • a "large" (4x7) zero array da to assign to,
  • a smaller (3x2) array dv filled with values [7.,8.,9.,10.,11.,12.].
da = DataArrayDouble()
da.alloc(4, 7)
#
dv = DataArrayDouble()
dv.alloc(6, 1)
dv.iota(7)
dv.rearrange(2)

Now we assign the two components of dv to the components of da with indices [1,3], and the 3 tuples of dv to the 3 tuples of da with indices [0,1,2] which are specified using slicing: "0:3". This is the first mode of usage.

da.fillWithZero()
da[0:3, [1, 3]] = dv

As result contents of the array da are as follows.

    Tuple #0 : 0  7  0  8  0  0  0
    Tuple #1 : 0  9  0 10  0  0  0
    Tuple #2 : 0 11  0 12  0  0  0
    Tuple #3 : 0  0  0  0  0  0  0

Every value of dv has been assigned to its own location within da.

Now we re-fill da with zeros and rearrange dv to have 6 components. And we assign dv to the tuples of da with indices [0,2] using slice notation "0:4:2". This is the second mode of usage.

da.fillWithZero()
dv.rearrange(6)
da[0:4:2, [0, 2, 3, 4, 5, 6]] = dv

The contents of dv have been assigned to each of specified tuples of da. Every value of dv is repeated in the 3 specified tuples within da.

    Tuple #0 : 7  0  8  9 10 11 12
    Tuple #1 : 0  0  0  0  0  0  0
    Tuple #2 : 7  0  8  9 10 11 12
    Tuple #3 : 0  0  0  0  0  0  0
Note
MEDCoupling::DataArrayDouble::setPartOfValues3() can't be explicitly called in Python.

Set part of values of DataArrayInt

setSelectedComponents()

First, we create a 'source' array.

da = DataArrayInt()
array1 = [1, 2, 3, 4, 5, 6]
da.setValues(array1, 3, 2)
da.setInfoOnComponents(["a1", "a2"])

Now we create a larger zero array and assign the array da to it.

dv = DataArrayInt()
dv.alloc(4, 4)
dv.fillWithZero()
dv.setInfoOnComponents(["v1", "v2", "v3", "v4"])
dv2 = dv.deepCopy()
dv.setSelectedComponents(da, [1, 0])

As result contents of the array dv are as follows.

Info of components : "a2"   "a1"   "v3"   "v4"
    Tuple #0 : 2 1 0 0
    Tuple #1 : 4 3 0 0
    Tuple #2 : 6 5 0 0
    Tuple #3 : 0 0 0 0

The same result can be achieved other way (except that component info is not copied):

dv2[:3, [1, 0]] = da
self.assertTrue(dv.isEqualWithoutConsideringStr(dv2))


setPartOfValues1()

We create two arrays:

  • a "large" (4x4) zero array da to assign to, and
  • a smaller (2x2) array dv filled with values [7,8,9,10].
da = DataArrayInt()
da.alloc(4, 4)
da.setInfoOnComponents(["v1", "v2", "v3", "v4"])
#
dv = DataArrayInt()
dv.alloc(4, 1)
dv.iota(7)
dv.rearrange(2)
dv.setInfoOnComponents(["a1", "a2"])

Now we copy dv to the middle of da.

da.fillWithZero()
da.setPartOfValues1(dv, 1, 3, 1, 1, 3, 1, True)

As result contents of the array da are as follows.

    Info of components :"v1"   "v2"   "v3"   "v4"
    Tuple #0 : 0 0 0 0
    Tuple #1 : 0 7 8 0
    Tuple #2 : 0 9 10 0
    Tuple #3 : 0 0 0 0

Here we re-fill da with zeros and copy dv into a component of da.

Note that the last parameter strictCompoCompare should be False in this case, else MEDCoupling::DataArrayInt::setPartOfValues1() throws an exception because da has 2 components but only one target component is specified.

da.fillWithZero()
da.setPartOfValues1(dv, 0, 4, 1, 1, 2, 1, False)
    Tuple #0 : 0 7 0 0
    Tuple #1 : 0 8 0 0
    Tuple #2 : 0 9 0 0
    Tuple #3 : 0 10 0 0

Below more two variants of location of target values are shown.

da.fillWithZero()
da.setPartOfValues1(dv, 1, 2, 1, 0, 4, 1, False)
    Tuple #0 : 0 0 0 0
    Tuple #1 : 7 8 9 10
    Tuple #2 : 0 0 0 0
    Tuple #3 : 0 0 0 0
da.fillWithZero()
da.setPartOfValues1(dv, 0, 3, 2, 1, 4, 2, True)
    Tuple #0 : 0 7 0 8
    Tuple #1 : 0 0 0 0
    Tuple #2 : 0 9 0 10
    Tuple #3 : 0 0 0 0

The same result can be achieved other way:

da2 = da.deepCopy()
da2.fillWithZero()
da2[0:3:2, 1:4:2] = dv
self.assertTrue(da.isEqual(da2))


setPartOfValuesSimple1()

We create an array (4x4) da to assign to and define a value dv to assign.

da = DataArrayInt()
da.alloc(4, 4)
dv = 7

Now we assign dv to the middle of da.

da.fillWithZero()
da.setPartOfValuesSimple1(dv, 1, 3, 1, 1, 3, 1)

As result contents of the array da are as follows.

    Tuple #0 : 0 0 0 0
    Tuple #1 : 0 7 7 0
    Tuple #2 : 0 7 7 0
    Tuple #3 : 0 0 0 0

Here we re-fill da with zeros and assign dv to a component of da.

da.fillWithZero()
da.setPartOfValuesSimple1(dv, 0, 4, 1, 1, 2, 1)
    Tuple #0 : 0 7 0 0
    Tuple #1 : 0 7 0 0
    Tuple #2 : 0 7 0 0
    Tuple #3 : 0 7 0 0

Below more two variants of location of target values are shown.

da.fillWithZero()
da.setPartOfValuesSimple1(dv, 1, 2, 1, 0, 4, 1)
    Tuple #0 : 0 0 0 0
    Tuple #1 : 7 7 7 7
    Tuple #2 : 0 0 0 0
    Tuple #3 : 0 0 0 0
da.fillWithZero()
da.setPartOfValuesSimple1(dv, 0, 3, 2, 1, 4, 2)
    Tuple #0 : 0 7 0 7
    Tuple #1 : 0 0 0 0
    Tuple #2 : 0 7 0 7
    Tuple #3 : 0 0 0 0

The same result can be achieved other way:

da2 = da.deepCopy()
da2.fillWithZero()
da2[0:3:2, 1:4:2] = dv
self.assertTrue(da.isEqual(da2))


setPartOfValuesSimple2()

We create an array (4x4) da to assign to and define a value dv to assign.

da = DataArrayInt()
da.alloc(4, 4)
dv = 7

Now we assign dv to the middle of da. We explicitly specify tuples and component to assign to by a list [1,2].

da.fillWithZero()
da[[1, 2], [1, 2]] = dv

As result contents of the array da are as follows.

    Tuple #0 : 0 0 0 0
    Tuple #1 : 0 7 7 0
    Tuple #2 : 0 7 7 0
    Tuple #3 : 0 0 0 0

Here we re-fill da with zeros and assign dv to a component of da.

da.fillWithZero()
da[[0, 1, 2, 3], [1]] = dv
    Tuple #0 : 0 7 0 0
    Tuple #1 : 0 7 0 0
    Tuple #2 : 0 7 0 0
    Tuple #3 : 0 7 0 0

Below more two variants of location of target values are shown.

da.fillWithZero()
da[[1], [0, 1, 2, 3]] = dv
    Tuple #0 : 0 0 0 0
    Tuple #1 : 7 7 7 7
    Tuple #2 : 0 0 0 0
    Tuple #3 : 0 0 0 0
da.fillWithZero()
da[[0, 2], [1, 3]] = dv
    Tuple #0 : 0 7 0 7
    Tuple #1 : 0 0 0 0
    Tuple #2 : 0 7 0 7
    Tuple #3 : 0 0 0 0
Note
MEDCoupling::DataArrayInt::setPartOfValuesSimple2() can't be explicitly called in Python.


setPartOfValuesSimple3()

We create an array (4x4) da to assign to and define a value dv to assign.

da = DataArrayInt()
da.alloc(4, 4)
dv = 7

Now we assign dv to the middle of da. We explicitly specify tuples to assign to by a list [1,2]. And we specify components to assign to using slicing: 1:3.

da.fillWithZero()
da[[1, 2], 1:3] = dv

As result contents of the array da are as follows.

    Tuple #0 : 0 0 0 0
    Tuple #1 : 0 7 7 0
    Tuple #2 : 0 7 7 0
    Tuple #3 : 0 0 0 0

Here we re-fill da with zeros and assign dv to a component of da.

da.fillWithZero()
da[[0, 1, 2, 3], 1:2] = dv
    Tuple #0 : 0 7 0 0
    Tuple #1 : 0 7 0 0
    Tuple #2 : 0 7 0 0
    Tuple #3 : 0 7 0 0

Below more two variants of location of target values are shown.

da.fillWithZero()
da[[1], 0:4] = dv
    Tuple #0 : 0 0 0 0
    Tuple #1 : 7 7 7 7
    Tuple #2 : 0 0 0 0
    Tuple #3 : 0 0 0 0
da.fillWithZero()
da[[0, 2], 1:4:2] = dv
    Tuple #0 : 0 7 0 7
    Tuple #1 : 0 0 0 0
    Tuple #2 : 0 7 0 7
    Tuple #3 : 0 0 0 0
Note
MEDCoupling::DataArrayInt::setPartOfValuesSimple3() can't be explicitly called in Python.


setPartOfValues2()

We create two arrays:

  • a "large" (4x7) zero array da to assign to,
  • a smaller (3x2) array dv filled with values [7,8,9,10,11,12].
da = DataArrayInt()
da.alloc(4, 7)
#
dv = DataArrayInt()
dv.alloc(6, 1)
dv.iota(7)
dv.rearrange(2)

Now we assign the two components of dv to the components of da with indices [1,3], and the 3 tuples of dv to the 3 tuples of da with indices [0,1,2]. This is the first mode of usage.

da.fillWithZero()
da[[0, 1, 2], [1, 3]] = dv

As result contents of the array da are as follows.

    Tuple #0 : 0  7  0  8  0  0  0
    Tuple #1 : 0  9  0 10  0  0  0
    Tuple #2 : 0 11  0 12  0  0  0
    Tuple #3 : 0  0  0  0  0  0  0

Every value of dv has been assigned to its own location within da.

Now we re-fill da with zeros and rearrange dv to have 6 components. And we assign dv to the tuples of da with indices [0,2,3] . This is the second mode of usage.

da.fillWithZero()
dv.rearrange(6)
da[[0, 2, 3], [0, 2, 3, 4, 5, 6]] = dv

The contents of dv have been assigned to each of specified tuples of da. Every value of dv is repeated in the 3 specified tuples within da.

    Tuple #0 : 7  0  8  9 10 11 12
    Tuple #1 : 0  0  0  0  0  0  0
    Tuple #2 : 7  0  8  9 10 11 12
    Tuple #3 : 7  0  8  9 10 11 12
Note
MEDCoupling::DataArrayInt::setPartOfValues2() can't be explicitly called in Python.


setPartOfValues3()

We create two arrays:

  • a "large" (4x7) zero array da to assign to,
  • a smaller (3x2) array dv filled with values [7,8,9,10,11,12].
da = DataArrayInt()
da.alloc(4, 7)
#
dv = DataArrayInt()
dv.alloc(6, 1)
dv.iota(7)
dv.rearrange(2)

Now we assign the two components of dv to the components of da with indices [1,3], and the 3 tuples of dv to the 3 tuples of da with indices [0,1,2] which are specified using slicing: "0:3". This is the first mode of usage.

da.fillWithZero()
da[0:3, [1, 3]] = dv

As result contents of the array da are as follows.

    Tuple #0 : 0  7  0  8  0  0  0
    Tuple #1 : 0  9  0 10  0  0  0
    Tuple #2 : 0 11  0 12  0  0  0
    Tuple #3 : 0  0  0  0  0  0  0

Every value of dv has been assigned to its own location within da.

Now we re-fill da with zeros and rearrange dv to have 6 components. And we assign dv to the tuples of da with indices [0,2] using slice notation "0:4:2". This is the second mode of usage.

da.fillWithZero()
dv.rearrange(6)
da[0:4:2, [0, 2, 3, 4, 5, 6]] = dv

The contents of dv have been assigned to each of specified tuples of da. Every value of dv is repeated in the 3 specified tuples within da.

    Tuple #0 : 7  0  8  9 10 11 12
    Tuple #1 : 0  0  0  0  0  0  0
    Tuple #2 : 7  0  8  9 10 11 12
    Tuple #3 : 0  0  0  0  0  0  0
Note
MEDCoupling::DataArrayInt::setPartOfValues3() can't be explicitly called in Python.

Excluding coincident tuples from DataArrayDouble

The code below creates an array of real values and than an array of unique values, not closer one to another than 0.2, is retrieved from it.

array1 = [2.3, 1.2, 1.3, 2.3, 2.301, 0.8]
da = DataArrayDouble(array1, 6, 1)
#
dv = da.getDifferentValues(2e-1)
expected2 = [2.301, 1.3, 0.8]
self.assertEqual(3, dv.getNbOfElems())
for i in range(3):
self.assertAlmostEqual(expected2[i], dv.getIJ(i, 0), 14)
pass

Concatenating DataArrayDouble's by appending components

In this example we create two data arrays including same number of tuples and then we concatenate them using meldWith().

da1 = DataArrayDouble()
da1.alloc(7, 2)
da2 = DataArrayDouble()
da2.alloc(7, 1)
#
da1.fillWithValue(7.0)
da2.iota(0.0)
da3 = da2.applyFunc(3, "10*x*IVec+100*x*JVec+1000*x*KVec")
#
da1.setInfoOnComponent(0, "c0da1")
da1.setInfoOnComponent(1, "c1da1")
da3.setInfoOnComponent(0, "c0da3")
da3.setInfoOnComponent(1, "c1da3")
da3.setInfoOnComponent(2, "c2da3")
#
da1C = da1.deepCopy()
da1.meldWith(da3)

Now the array da1 includes 7 tuples (as before) of 3 components each. Its components are: "c0da1","c1da1","c0da2".

Concatenating DataArrayInt's by appending components

In this example we create two data arrays including same number of tuples and then we concatenate them using meldWith().

da1 = DataArrayInt()
da1.alloc(7, 2)
da2 = DataArrayInt()
da2.alloc(7, 1)
#
da1.fillWithValue(7)
da2.iota(0)
#
da1.setInfoOnComponent(0, "c0da1")
da1.setInfoOnComponent(1, "c1da1")
da2.setInfoOnComponent(0, "c0da2")
#
da1.meldWith(da2)

Now the array da1 includes 7 tuples (as before) of 3 components each. Its components are: "c0da1","c1da1","c0da2".

Access

Getting a tuple of DataArrayInt

In this simple example we create an array of integers arranged into 3 tuples per 2 components, and finally print the second tuple.

dv = DataArrayInt()
dv.alloc(6, 1)
dv.iota(7)
dv.rearrange(2)
assert dv.getTuple(1) == [9, 10]

The output is

 [9, 10] 

Note that we can traverse all tuples in the array by simply iterating over it as the code below does.

for tpl in dv:
print(tpl)

Its output follows.

(7, 8)
(9, 10)
(11, 12)

Finding values in range in DataArrayDouble

In this example we create an array da containing same values as ones returned by range( 10 ). Then we get an array of indices of values of da being in range [ 2.5, 6 ].

da = DataArrayDouble()
da.alloc(10, 1)
da[:, :] = list(range(10))
da2 = da.findIdsInRange(2.5, 6)

As result contents of the array da2 are as follows.

    Tuple #0 : 3
    Tuple #1 : 4
    Tuple #2 : 5
    Tuple #3 : 6

Finding coincident tuples in DataArrayDouble

Let's create an array of 6 tuples and 2 components that can be considered as coordinates of 6 points in 2D space.

array2 = [2.3, 2.3, 1.2, 1.2, 1.3, 1.3, 2.3, 2.3, 2.301, 2.301, 0.8, 0.8]
da = DataArrayDouble(array2, 6, 2)

Now we find points that are not far each from other than 1e-1.

c, cI = da.findCommonTuples(1.01e-1)
expected3 = [0, 3, 4, 1, 2]
expected4 = [0, 3, 5]
self.assertEqual(expected3, c.getValues())
self.assertEqual(expected4, cI.getValues())

As we can realize from the above code, a hardcoded array expected3 is equal to the raw data of a DataArrayInt c and a hardcoded array expected4 is equal to the raw data of the DataArrayInt cI.

The array c contains indices of 5 coincident points. The array cI shows us boundaries of (cI->getNumberOfTuples()-1) = 2 groups of coincident points:

  • The first group starts at index 0 and includes (3 - 0) = 3 points: 0,3,4.
  • The second group starts at index 3 and includes (5 - 3) = 2 points: 1,2.

Creation of a sub-part of the DataArrayDouble by selecting components

arr1 = [
1.0,
2.0,
3.0,
4.0, # tuple 0
11.0,
12.0,
13.0,
14.0, # tuple 1
21.0,
22.0,
23.0,
24.0, # ...
31.0,
32.0,
33.0,
34.0,
41.0,
42.0,
43.0,
44.0,
]
a1 = DataArrayDouble(arr1, 5, 4)
a1.setInfoOnComponent(0, "a")
a1.setInfoOnComponent(1, "b")
a1.setInfoOnComponent(2, "c")
a1.setInfoOnComponent(3, "d")

We created an array a1 containing 5 tuples of 4 components each (20 values). Now we are going to create an array a2 containing some components of a1.

arr2V = [1, 2, 1, 2, 0, 0]
a2 = a1.keepSelectedComponents(arr2V)

Now each tuple of a2 includes components named "b","c","b","c","a","a". Thus the result array a2 includes 30 elements (5 tuples per 6 components).

Creation of a sub-part of the DataArrayInt by selecting components

arr1 = [
1,
2,
3,
4, # tuple 0
11,
12,
13,
14, # tuple 1
21,
22,
23,
24, #
31,
32,
33,
34,
41,
42,
43,
44,
]
a1 = DataArrayInt()
a1.setValues(arr1, 5, 4)
a1.setInfoOnComponent(0, "a")
a1.setInfoOnComponent(1, "b")
a1.setInfoOnComponent(2, "c")
a1.setInfoOnComponent(3, "d")

We created an array a1 containing 5 tuples of 4 components each (20 values). Now we are going to create an array a2 containing some components of a1.

arr2V = [1, 2, 1, 2, 0, 0]
a2 = a1.keepSelectedComponents(arr2V)

Now each tuple of a2 includes components named "b","c","b","c","a","a". Thus the result array a2 includes 30 elements (5 tuples per 6 components).

Note that DataArrayInt::keepSelectedComponents() is called, providing the same result, by the following python code:

a3 = a1[:, arr2V]

Other

Input/Output

Writing fields in a VTK file

In this example we

  • create an 2D mesh and 3 fields on it,
  • use WriteVTK() to write all the fields and the mesh to a VTK file.
# mesh
coords = [0.0, 2.0, 4.0]
coordsArr = DataArrayDouble(coords, 3, 1)
mesh = MEDCouplingCMesh()
mesh.setCoords(coordsArr, coordsArr) # mesh becomes a 2D one
# 3 fields (lying on the same mesh!)
field1 = mesh.getMeasureField(True)
field2 = mesh.buildOrthogonalField()
field3 = mesh.fillFromAnalytic(ON_CELLS, 2, "IVec * x + JVec * y")
field2.setName("Normal") # name is necessary!
field3.setName("Barycenter") # name is necessary!
# WriteVTK
fileName = "testExample_MEDCouplingFieldDouble_WriteVTK"
fs = [field1, field2, field3] # field series
writtenFileName = MEDCouplingFieldDouble.WriteVTK(fileName, fs)
print("The file name with correct extension is : %s" % (writtenFileName))

Loading a mesh using basic API

Consider a mesh called "Example2" in file "file2.med" containing MED_POLYHEDRA, MED_TETRA4, MED_QUAD8, MED_TRI6, MED_SEG2 and MED_POINT1. In this case you will have :

self.assertEqual(3, ReadUMeshDimFromFile("file2.med", "Example2"))
int ReadUMeshDimFromFile(const std::string &fileName, const std::string &meshName)
Definition: MEDLoader.cxx:1385

To get 3D cells (MED_POLYHEDRA and MED_TETRA4) you should type :

m2D = ReadUMeshFromFile("file2.med", "Example2", 0)
MEDCoupling::MEDCouplingUMesh * ReadUMeshFromFile(const std::string &fileName, const std::string &meshName, int meshDimRelToMax=0)
Definition: MEDLoader.cxx:1351

To get 2D cells (MED_TRI6 and MED_QUAD8) you should type :

m2D = ReadUMeshFromFile("file2.med", "Example2", -1)

To get 1D cells (MED_SEG2) you should type :

m1D = ReadUMeshFromFile("file2.med", "Example2", -2)

And finally for 0D cells (MED_POINT1) you will write :

m0D = ReadUMeshFromFile("file2.med", "Example2", -3)

Writing one mesh using basic API

To write one mesh myMesh with name "myMeshName" in a MED file "wfile1.med" the following code should be typed :

self.assertTrue(isinstance(myMesh, MEDCouplingUMesh))
myMesh.setName(meshName)
WriteUMesh("wFile1.med", myMesh, True)
void WriteUMesh(const std::string &fileName, const MEDCoupling::MEDCouplingUMesh *mesh, bool writeFromScratch)
Definition: MEDLoader.cxx:1929

With the previous code, if "wFile1.med" file exists the file is crashed and will contain after the call only the contents of myMesh instance.

If you want to append a mesh in "wFile1.med" you should type :

self.assertTrue(isinstance(myMesh, MEDCouplingUMesh))
myMesh.setName(meshName)
WriteUMesh("wFile1.med", myMesh, False)

With the previous code, if the "wFile1.med" has already a mesh called "myMeshName" an INTERP_KERNEL::Exception will be thrown.

Reading a field at one time step using basic API

So to retrieve a field on 3D cell called "F1Cell" in example file "file2.med" on a mesh "Example2" (as defined here) on time step defined by iteration number 2 and iteration 3 the request will be :

f1Cell_3D = ReadFieldCell("file2.med", "Example2", 0, "F1Cell", 2, 3)
MEDCoupling::MEDCouplingField * ReadFieldCell(const std::string &fileName, const std::string &meshName, int meshDimRelToMax, const std::string &fieldName, int iteration, int order)
Definition: MEDLoader.cxx:1789

To retrieve the same field (same iteration) on 2D cells only the call will be :

f1Cell_2D = ReadFieldCell("file2.med", "Example2", -1, "F1Cell", 2, 3)

Reading a field at all time steps using basic API

It is typically recommended to use the following code when you want to load all time steps of a field on cell "myField" lying on same mesh "mesh1" in one shot :

timeStepsIds = GetCellFieldIterations("file3.med", "Example2", "myField")
self.assertEqual([(1, 0), (2, 0)], timeStepsIds)
ON_CELLS, "file3.med", "Example2", 0, "myField", timeStepsIds
)
std::vector< MEDCoupling::MEDCouplingFieldDouble * > ReadFieldsOnSameMesh(MEDCoupling::TypeOfField type, const std::string &fileName, const std::string &meshName, int meshDimRelToMax, const std::string &fieldName, const std::vector< std::pair< int, int >> &its)
Definition: MEDLoader.cxx:1558
std::vector< std::pair< int, int > > GetCellFieldIterations(const std::string &fileName, const std::string &meshName, const std::string &fieldName)
Definition: MEDLoader.cxx:1116

Reading a field on all entities using advanced API

Let's read a field on all entity called fieldName lying on a mesh called meshName in a MED file called fname at a iteration defined on time step defined by iteration and order.

fname = "PyExamples1.med"
meshName = "mesh"
fieldName = "FieldOnAll"
iteration = 3
order = 4

To read it there are 3 main approaches :

medfileField1TS = MEDFileField1TS.New(fname, fieldName, iteration, order)
mm = MEDFileMesh.New(fname)
fread = medfileField1TS.getFieldOnMeshAtLevel(ON_CELLS, 0, mm)
fread2 = medfileField1TS.getFieldAtLevel(ON_CELLS, 0)
self.assertTrue(fread.isEqual(f, 1e-12, 1e-12))
self.assertTrue(fread2.isEqual(f, 1e-12, 1e-12))
medfileFieldMTS = MEDFileFieldMultiTS.New(fname, fieldName)
mm = MEDFileMesh.New(fname)
fread = medfileFieldMTS.getFieldOnMeshAtLevel(ON_CELLS, iteration, order, 0, mm)
fread2 = medfileFieldMTS.getFieldAtLevel(ON_CELLS, iteration, order, 0)
self.assertTrue(fread.isEqual(f, 1e-12, 1e-12))
self.assertTrue(fread2.isEqual(f, 1e-12, 1e-12))
medfileFieldMTS = MEDFileFieldMultiTS.New(fname, fieldName)
for medfileField1TS in medfileFieldMTS:
if medfileField1TS.getTime()[:2] == [iteration, order]:
fread = medfileField1TS.getFieldOnMeshAtLevel(ON_CELLS, 0, mm)
fread2 = medfileField1TS.getFieldAtLevel(ON_CELLS, 0)
self.assertTrue(fread.isEqual(f, 1e-12, 1e-12))
self.assertTrue(fread2.isEqual(f, 1e-12, 1e-12))
pass
pass

Reading a partial field using advanced API

Let's read a partial field called fieldName lying on a mesh called meshName in a MED file called fname at a iteration defined on time step defined by iteration and order.

fname = "PyExamples2.med"
meshName = "mesh"
fieldName = "FieldPartial"
iteration = 3
order = 4

Fields defined partially on a meshes can been read using 2 main approaches :

  • Either the user wants to retrieve it's field in MEDCoupling sense, that is to say for interpolation, to evaluate such field on different points...
    In this mode the link with the whole mesh is not useful for the user
mm = MEDFileMesh.New(fname)
medfileField1TS = MEDFileField1TS.New(fname, fieldName, iteration, order)
fread = medfileField1TS.getFieldOnMeshAtLevel(ON_CELLS, 0, mm)
fread2 = medfileField1TS.getFieldAtLevel(ON_CELLS, 0)
self.assertTrue(fread.isEqual(f, 1e-12, 1e-12))
self.assertTrue(fread2.isEqual(f, 1e-12, 1e-12))
  • Or the user wants to retrieve the binding (cell ids or node ids) with the whole mesh on which the partial field lies partially on.
medfileField1TS = MEDFileField1TS.New(fname, fieldName, iteration, order)
mm = MEDFileMesh.New(fname)
valsRead, pflRead = medfileField1TS.getFieldWithProfile(ON_CELLS, 0, mm)
self.assertEqual(valsRead.getName(), f.getName())
valsRead.setName("")
self.assertTrue(valsRead.isEqual(f.getArray(), 1e-12))
pflRead.setName(pfl.getName())
self.assertTrue(pflRead.isEqual(pfl))

MEDCoupling allows to make bridges between the approaches. For example pfl DataArrayInt instance retrieved directly from the file in the second approach can be retrieved starting from first approach.

Starting from mesh firstApproachMesh of read field in first approach fread, with the whole mesh wholeMesh the profile pflComputed can be computed :

firstApproachMesh = fread.getMesh()
mm = MEDFileMesh.New(fname)
wholeMesh = mm.getMeshAtLevel(0)
wholeMesh.tryToShareSameCoords(firstApproachMesh, 1e-12)
isIncluded, pflComputed = wholeMesh.areCellsIncludedIn(firstApproachMesh, 2)
self.assertTrue(isIncluded)
self.assertEqual(pflComputed.getName(), mm.getName())
pflComputed.setName(pflRead.getName())
self.assertTrue(pflComputed.isEqual(pflRead))

Inversely, it is possible to rebuild field obtained in first approach starting from second approach :

mm = MEDFileMesh.New(fname)
wholeMesh = mm.getMeshAtLevel(0)
computedMesh = wholeMesh[pflRead]
computedMesh.setName(mm.getName())
self.assertTrue(computedMesh.isEqual(fread.getMesh(), 1e-12))
fieldFromSecondApproach = MEDCouplingFieldDouble.New(ON_CELLS, ONE_TIME)
fieldFromSecondApproach.setName(medfileField1TS.getName())
fieldFromSecondApproach.setMesh(computedMesh)
fieldFromSecondApproach.setArray(valsRead)
fieldFromSecondApproach.setTime(
medfileField1TS.getTime()[2],
medfileField1TS.getTime()[0],
medfileField1TS.getTime()[1],
)
self.assertTrue(fieldFromSecondApproach.isEqual(fread, 1e-12, 1e-12))

Writing several time steps of a field using basic API

To write a serie of time steps in a "file3.med" file lying on the same unstructured mesh the typical code to write is the following :

WriteUMesh("file3.med", f.getMesh(), True)
f.setTime(1.2, 1, 0)
fileNameMultiTimeStep = "file3.med"
WriteFieldUsingAlreadyWrittenMesh(fileNameMultiTimeStep, f)
f.setTime(1.3, 2, 0)
f.applyFunc("sqrt(x)")
# Writing second time step with iteration==2 and order==0
void WriteFieldUsingAlreadyWrittenMesh(const std::string &fileName, const MEDCoupling::MEDCouplingField *f)
Definition: MEDLoader.cxx:2241

In the above code, it is important to note that the values of pairs (iteration,order) should be different between two calls to avoid that a call to MEDLoader::WriteFieldUsingAlreadyWrittenMesh overwrites a previous call. Another important thing is the fact that f.getMesh() is not modified. This write method presents the big advantage to be fast, because neither check nor read is performed. That's why the parameter of writeFromScratch is not needed here, contrary to other MEDLoader::Write* methods.

Writing a field defined on all entities using advanced API

Let's write a cell field on all entities called fieldName lying on a mesh called meshName in a MED file called fname at a iteration defined on time step defined by iteration and order.

m = MEDLoaderDataForTest.build2DMesh_3()
m = m[:10]
m.setName(meshName)
f = m.getMeasureField(False)
f = f.buildNewTimeReprFromThis(ONE_TIME, False)
f.setTime(5.5, iteration, order)
f.setName(fieldName)
# MEDCoupling finished, MEDLoader advanced API specific part starting from here
mm = MEDFileUMesh.New()
mm.setMeshAtLevel(0, m)
ff = MEDFileField1TS.New()
ff.setFieldNoProfileSBT(f)
mm.write(fname, 2)
ff.write(fname, 0)

We can see here that the necessity to deal with both mesh and field to write a field is exposed by the API. The mesh write mode is 2 to tell to MED file that is file already exists to scratch it. The mode of write is 0 to simply add to the file the field specific part.

Writing a partial field using advanced API

m = MEDLoaderDataForTest.build2DMesh_1()
m.sortCellsInMEDFileFrmt()
m.setName(meshName)
# end of generation of a mesh -> let's create a field on that mesh
f = m.getMeasureField(False)
f = f.buildNewTimeReprFromThis(ONE_TIME, False)
f.setTime(5.5, iteration, order)
f.setName(fieldName)
# The MEDCoupling part is finished -> let's perform advanced API
mm = MEDFileUMesh.New()
mm.setMeshAtLevel(
0, m
) # the MED file data structure is ready for writing. Of course mm could have been more complicated with groups, families, multilevel
# Let's building a sub field
pfl = DataArrayInt.New([1, 3, 4, 5])
pfl.setName(
"myPfl"
) # here it is necessary to give a name to be compliant with MED file
f = f[pfl]
f.getMesh().setName(
m.getName()
) # of course f should be in coherence with pfl -> f[pfl]
#
ff = MEDFileField1TS.New()
tmp = f.getMesh() # useless line, only to show that mesh into f is not considered by MEDFileField1TS.setFieldProfile
f.setMesh(
None
) # useless line, only to show that mesh into f is not considered by MEDFileField1TS.setFieldProfile
ff.setFieldProfile(f, mm, 0, pfl)
f.setMesh(
tmp
) # useless line, only to show that mesh into f is not considered by MEDFileField1TS.setFieldProfile
mm.write(fname, 2)
ff.write(fname, 0)

To write a partial field f can have a null mesh, because the link with mesh is made given the entry of mm MEDFileField1TS::setFieldProfile method.