# Node numbering of a refined mesh (truncated with split = 2) for P2 elements post-processing

**URL:** https://community.freefem.org/t/node-numbering-of-a-refined-mesh-truncated-with-split-2-for-p2-elements-post-processing/4132
**Category:** General Discussion
**Created:** [November 12, 2025, 2:23pm UTC](https://community.freefem.org/t/node-numbering-of-a-refined-mesh-truncated-with-split-2-for-p2-elements-post-processing/4132 "2025-11-12T14:23:55Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![MatrixVector](https://avatars.discourse-cdn.com/v4/letter/m/b5e925/32.png) [@MatrixVector](https://community.freefem.org/u/MatrixVector)
#### Post date: [November 12, 2025, 2:23pm UTC](https://community.freefem.org/t/node-numbering-of-a-refined-mesh-truncated-with-split-2-for-p2-elements-post-processing/4132/1 "2025-11-12T14:23:55Z")

</div>

I’m doing a post-processing work which outputs the node values of a 2D P2 element using VTK. Since Freefem++ currently doesn’t support outputing the P2 elements (VTK order = 2) directly, one possible way is to first refine the mesh (truncated with split = 2), then output the refined mesh with P1 elements (VTK order = 1).

The mesh refinement is easy to implement. Assuming we have an original 2D mesh called `Th`, and a refined mesh `ThR` is established by using the command:

```cpp
mesh ThR = Th;
ThR = trunc(ThR, true, split=2);

```

But, it is a bit difficult to establish the node numbering mapping between the original `Th` with P2 elements and the refined `ThR` with P1 elements.

The node numbering for the original P2 elements can be accessed as follows:

```cpp
mesh Th = square(2, 2);

fespace Wh(Th, P2);

for (int k = 0; k < Th.nt; k++) {
    for (int i = 0; i < 6; i++) {
        cout << Wh(k, i) << " ";
    }
    cout << endl;
}

```

However, the node numbering rule for the refined mesh `ThR` with P1 elements is not very clear. The node numbering for the common nodes of `Th` & `ThR` are the same, but the rule for the newly added nodes is not clear.

Here is an example.

Fig. 1 gives the P1 node numbering of the mesh `Th`.

 ![1](https://canada1.discourse-cdn.com/flex030/uploads/freefem/original/2X/8/87750185c0bde5f2f2395b012fde1f92ef7f31bb.png)

Fig. 2 gives the P1 node numbering of the refined mesh `ThR`.

 ![2](https://canada1.discourse-cdn.com/flex030/uploads/freefem/original/2X/2/27c8569eb392fbd0208dbedc33fc42d0c84137af.png)

Fig. 3 gives the P2 node numbering of the mesh `Th`.

 ![3](https://canada1.discourse-cdn.com/flex030/uploads/freefem/original/2X/6/63b9412c927389a8d6449a1e44e947271b4c8464.png)

Of course, we can find the mapping relation by comparing each nodes’ coordinates, and determine whether they’re the same one by Euclidean distance like

`sqrt((xi - xj)^2 + (yi - yj)^2 + (zi - zj)^2) < epsilon`

Is there any more efficient way to address this problem, since the above method maybe time cost expensive when there are millions of nodes?

---

<div class="post-metadata">

### Author: ![fb77](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.freefem.org/fb77/32/3796_2.png) [@fb77](https://community.freefem.org/u/fb77)
#### Post date: [November 12, 2025, 8:48pm UTC](https://community.freefem.org/t/node-numbering-of-a-refined-mesh-truncated-with-split-2-for-p2-elements-post-processing/4132/2 "2025-11-12T20:48:04Z")

</div>

I don’t have a simple method to solve your problem, but some search trough the neighbouring vertices of a vertex i of ThR (which is not a vertex of Th) should give the two that belong to Th (then the vertex i is the middle of these two) . Note that a vertex of ThR of index i is a vertex of Th if and only if i\<Th.nv.  
By the way, how do you produce these nice images including vertex indices ?

---

<div class="post-metadata">

### Author: ![MatrixVector](https://avatars.discourse-cdn.com/v4/letter/m/b5e925/32.png) [@MatrixVector](https://community.freefem.org/u/MatrixVector)
#### Post date: [November 13, 2025, 1:30am UTC](https://community.freefem.org/t/node-numbering-of-a-refined-mesh-truncated-with-split-2-for-p2-elements-post-processing/4132/3 "2025-11-13T01:30:56Z")

</div>

Thanks for your reply.

I guess an interpolation operator `=` maybe can solve the problem indirectly. Using the interpolation, the nodes with same coordinates maybe have same values.

```cpp
// Original P2 solution
fespace Vh(Th, P2);
Vh u;

// Refined P1 solution
fespace Rh(ThR, P1);
Rh uR = u;

```

In this way, we don’t focus on the mapping between the P2 node indices and the refined P1 node indices, but just transferring nodal values of the P2 nodes to the refined P1 nodes.

Regarding the figures with vertex indices, Fig.1 & Fig. 2 are produced directly by Paraview, and Fig. 3 is produced by hand.

---

<div class="post-metadata">

### Author: ![fb77](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.freefem.org/fb77/32/3796_2.png) [@fb77](https://community.freefem.org/u/fb77)
#### Post date: [November 13, 2025, 12:59pm UTC](https://community.freefem.org/t/node-numbering-of-a-refined-mesh-truncated-with-split-2-for-p2-elements-post-processing/4132/4 "2025-11-13T12:59:23Z")

</div>

Your idea can indeed be converted to a real mapping:

```auto
mesh Th = square(2, 2);
mesh ThR = trunc(Th, true, split=2);

fespace Vh(Th,P2);
fespace Rh(ThR,P1);

matrix convert=interpolate(Vh,Rh);
cout << convert;

```

Then convert(i,j) is 1 (0 otherwise)  
if (i,j) is a couple with i the Vh label and j the Rh label, of the same vertex.

About Fig 1 & 2, do you save the meshes as .vtu ? How do you plot the label numbers in paraview?

---

<div class="post-metadata">

### Author: ![MatrixVector](https://avatars.discourse-cdn.com/v4/letter/m/b5e925/32.png) [@MatrixVector](https://community.freefem.org/u/MatrixVector)
#### Post date: [November 14, 2025, 2:21am UTC](https://community.freefem.org/t/node-numbering-of-a-refined-mesh-truncated-with-split-2-for-p2-elements-post-processing/4132/5 "2025-11-14T02:21:43Z")

</div>

Thanks for your reply, Dr Bouchut. The interpolation matrix really solves the nodal indices mapping problem, and it can be converted into a mapping array for further applications.

Regarding Figs. 1 & 2, the meshes are generated in FreeFem++ as follows

```cpp
mesh Th = square(2, 2);
mesh ThR = trunc(Th, true, split=2);

load “iovtk”
savevtk(“Th.vtu”, Th);
savevtk(“ThR.vtu”, ThR);

```

Then, the vtu files are imported into Paraview, where we can use the “Find data matching various criteria …” function to find all the points and show their labels.

 ![find_data](https://canada1.discourse-cdn.com/flex030/uploads/freefem/original/2X/b/b03084e9454abf8730170fc00cd690ee22cc97eb.png)

---

<div class="post-metadata">

### Author: ![fb77](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.freefem.org/fb77/32/3796_2.png) [@fb77](https://community.freefem.org/u/fb77)
#### Post date: [November 14, 2025, 10:12am UTC](https://community.freefem.org/t/node-numbering-of-a-refined-mesh-truncated-with-split-2-for-p2-elements-post-processing/4132/6 "2025-11-14T10:12:15Z")

</div>

Thanks a lot, I succeeded in plotting the labels!  
I didn’t know this feature, which is very useful.  
Francois.
