Computing mesh quality after updating domain.geometry.x (scaled_jacobian should be negative but stays positive)

Hi all,

I am trying to compute the mesh quality (scaled Jacobian) after a Lagrangian-type displacement step, where I manually modify the mesh coordinates via domain.geometry.x. Conceptually, some elements should be inverted after the displacement, so I expect some negative values of scaled_jacobian. However, with the code below, the minimum value of scaled_jacobian is still positive.

from dolfinx import default_scalar_type
from dolfinx.fem import (
    Constant,
    dirichletbc,
    Function,
    functionspace,
    assemble_scalar,
    form,
    locate_dofs_geometrical,
    locate_dofs_topological,
)
from dolfinx.fem.petsc import LinearProblem
from dolfinx.io import XDMFFile
from dolfinx.io import gmshio
from dolfinx.mesh import create_unit_square, locate_entities
from dolfinx.plot import vtk_mesh
import matplotlib.pyplot as plt

from ufl import SpatialCoordinate, TestFunction, TrialFunction, dx, grad, inner

from mpi4py import MPI

import meshio
import gmsh
import numpy as np
import pyvista
from dolfinx import fem
import time
import pyvista as pv
from dolfinx import plot
domain, cell_tags, facet_tags = gmshio.read_from_msh(
    "rectangle_with_armature.msh",
    comm=MPI.COMM_WORLD,
    rank=0,          
    gdim=2
)


cell_markers  = cell_tags
facet_markers = facet_tags


V_linear = fem.functionspace(domain, ("Lagrange", 1))

tdim = domain.topology.dim
fdim = tdim - 1
topology, cell_types, geometry = plot.vtk_mesh(V_linear)

domain.topology.create_connectivity(tdim, tdim)   # cell -> cell
domain.topology.create_connectivity(fdim, tdim)   # facet -> cell(
domain.topology.create_connectivity(fdim, 0)  # facet -> vertex
domain.topology.create_connectivity(tdim, 0)  # cell  -> vertex

f2v = domain.topology.connectivity(fdim, 0)
c2v = domain.topology.connectivity(tdim, 0)



facets_16 = cell_tags.find(16)
verts_facets16 = np.unique(np.hstack([c2v.links(int(f)) for f in facets_16]))


x  = domain.geometry.x     
x0 = x.copy()            

gdim = domain.geometry.dim
dx = np.array((0.5, 0.5, 0.0))


x1 = x0.copy()
x1[verts_facets16, :gdim] += dx[:gdim]


from dolfinx import plot
import pyvista


grid = pyvista.UnstructuredGrid(topology, cell_types, x1)

plotter = pyvista.Plotter()
plotter.add_mesh(grid, show_edges=True)
plotter.view_xy()
plotter.show()


x = domain.geometry.x
x_backup = x.copy()


x[:] = x1

V_linear = fem.functionspace(domain, ("Lagrange", 1))

cqual = grid.compute_cell_quality("scaled_jacobian")
q = cqual["CellQuality"]

print("cell_number =", q.size)
print("scaled_jacobian: min =", float(q.min()), " max =", float(q.max()), "mean =",float(q.mean()))


plt.figure()
plt.hist(q, bins=30)
plt.xlabel("scaled_jacobian")
plt.ylabel("Number of cells")
plt.title("Mesh quality: scaled_jacobian")
plt.show()

$MeshFormat
4.1 0 8
$EndMeshFormat
$PhysicalNames
4
1 13 "move"
1 14 "outer"
2 15 "air"
2 16 "armature"
$EndPhysicalNames
$Entities
8 8 2 0
1 0 0 0 0 
2 10 0 0 0 
3 0 6 0 0 
4 10 6 0 0 
5 1 2 0 0 
6 3 2 0 0 
7 3 4 0 0 
8 1 4 0 0 
1 -1.000000002804313e-07 -1e-07 -1e-07 10.0000001 1e-07 1e-07 1 14 2 1 -2 
2 -1e-07 -9.999999983634211e-08 -1e-07 1e-07 6.0000001 1e-07 1 14 2 3 -1 
3 9.999999900000001 -9.999999983634211e-08 -1e-07 10.0000001 6.0000001 1e-07 1 14 2 2 -4 
4 -1.000000002804313e-07 5.9999999 -1e-07 10.0000001 6.0000001 1e-07 1 14 2 4 -3 
5 0.9999999000000002 1.9999999 -1e-07 3.0000001 2.0000001 1e-07 1 13 2 5 -6 
6 2.9999999 1.9999999 -1e-07 3.0000001 4.0000001 1e-07 1 13 2 6 -7 
7 0.9999999000000002 3.9999999 -1e-07 3.0000001 4.0000001 1e-07 1 13 2 7 -8 
8 0.9999999000000001 1.9999999 -1e-07 1.0000001 4.0000001 1e-07 1 13 2 8 -5 
2 0.9999999000000002 1.9999999 -1e-07 3.0000001 4.0000001 1e-07 1 16 4 5 6 7 8 
3 -1.000000002804313e-07 -9.999999983634211e-08 -1e-07 10.0000001 6.0000001 1e-07 1 15 8 1 3 4 2 -5 -8 -7 -6 
$EndEntities
$Nodes
18 243 1 243
0 1 0 1
1
0 0 0
0 2 0 1
2
10 0 0
0 3 0 1
3
0 6 0
0 4 0 1
4
10 6 0
0 5 0 1
5
1 2 0
0 6 0 1
6
3 2 0
0 7 0 1
7
3 4 0
0 8 0 1
8
1 4 0
1 1 0 13
9
10
11
12
13
14
15
16
17
18
19
20
21
0.6107553364652977 0 0
1.208641779473193 0 0
1.805615737618943 0 0
2.402589695764694 0 0
2.999563653918919 0 0
3.599833063667034 0 0
4.219438635192874 0 0
4.875854476694268 0 0
5.584198882724548 0 0
6.357882952380453 0 0
7.209516544615258 0 0
8.134456380794532 0 0
9.067228190397266 0 0
1 2 0 10
22
23
24
25
26
27
28
29
30
31
0 5.375510433155368 0
0 4.807411948206396 0
0 4.279043049861258 0
0 3.766932723152318 0
0 3.255644241050773 0
0 2.744355758949229 0
0 2.233067276847685 0
0 1.720956950138746 0
0 1.192588051793608 0
0 0.6244895668446366 0
1 3 0 5
32
33
34
35
36
10 1 0
10 2 0
10 3 0
10 4 0
10 5 0
1 4 0 13
37
38
39
40
41
42
43
44
45
46
47
48
49
9.067228190397266 6 0
8.134456380794532 6 0
7.209516544615253 6 0
6.357882952380458 6 0
5.584198882724541 6 0
4.875854476694268 6 0
4.219438635192875 6 0
3.599833063667035 6 0
2.999563653918921 6 0
2.402589695764695 6 0
1.805615737618945 6 0
1.208641779473195 6 0
0.6107553364652993 6 0
1 5 0 4
50
51
52
53
1.4 2 0
1.8 2 0
2.2 2 0
2.6 2 0
1 6 0 4
54
55
56
57
3 2.4 0
3 2.8 0
3 3.2 0
3 3.6 0
1 7 0 4
58
59
60
61
2.6 4 0
2.2 4 0
1.8 4 0
1.4 4 0
1 8 0 4
62
63
64
65
1 3.6 0
1 3.2 0
1 2.8 0
1 2.4 0
2 2 0 25
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
2.655477316053756 2.99673079295489 0
1.316161621245394 2.976276733901078 0
1.980664189010284 2.325510312359842 0
1.983933396055394 3.672602210072627 0
2.661405824687066 2.601496380714956 0
2.341495105276245 2.792302003558165 0
2.351068363572713 3.200417973526343 0
1.960769515458674 3 0
2.378658130739608 3.629605776988941 0
1.383202659762193 3.363840569367585 0
1.296526125417033 2.600156359210701 0
2.682063914556421 3.388989036740437 0
2.367785476671747 2.376089795890153 0
1.588685970959853 2.382519218170914 0
1.612769589714315 3.675836430402468 0
1.779669756705498 3.358780709908599 0
1.800953213671887 2.671582306488902 0
1.653589838486225 3.060904601179476 0
1.292820323027551 3.707179676972449 0
1.292820323027551 2.292820323027551 0
2.707179676972449 2.292820323027551 0
2.707179676972449 3.707179676972449 0
2.083753540756189 3.379500448429442 0
2.083753540756189 2.620499551570558 0
1.545515778994172 2.78153611292129 0
2 3 0 153
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
3.345160329830239 3.010527109848855 0
5.9710409175525 0.6417371545380819 0
5.984359529841495 5.369604587897591 0
4.551652744431619 5.505977064204581 0
4.549361516842208 0.5141990730623314 0
9.163582249739347 2.488147257974067 0
3.357931675821648 2.218334284045357 0
3.350949856170508 3.80127980147769 0
7.612224063020488 5.284966359271108 0
3.355410161513776 1.78441154273188 0
3.749102121608155 2.021858716742109 0
3.360491198633435 4.219732978799637 0
3.744610828929419 4.002670156084322 0
1.666645829896323 4.316885363595653 0
1.666645829896323 1.683114636404348 0
2.4 1.653589838486225 0
2.400000000000001 4.346410161513775 0
7.684694815614069 0.7384470018835465 0
0.4843328627257932 0.8998125581345588 0
0.484332862725795 5.100187441865446 0
3.319936403577032 5.432338375426934 0
3.320073364365236 0.5677990387560512 0
3.753228548673019 1.539534237184907 0
4.164387717144625 1.779664348410817 0
4.158238768059003 2.294048993955657 0
4.624008815275142 2.04315330542555 0
4.612908200385853 2.606091393576893 0
5.126385062639502 2.331389349321873 0
5.105509528787316 2.937331364480245 0
5.664646835105603 2.643769773884591 0
5.644070975695974 3.295072799983562 0
6.240850135014254 2.981347897940025 0
5.104118752438919 3.589024645657465 0
6.255732864498719 2.290636764275083 0
6.884185267637751 2.648750930955369 0
6.173442331675555 3.663819249718887 0
3.753382457533506 4.465675367884193 0
2.134830258883424 5.487682557500274 0
2.134830258883423 0.512317442499727 0
4.173584483452299 4.22190422087485 0
5.068676674177954 1.719535449242842 0
4.155641183433946 3.713424942152139 0
9.224062156226401 4.504411183663462 0
6.832672548511875 2.012701629878762 0
7.612211350521424 2.225443800356057 0
7.525209512088738 3.025089116192591 0
4.085956992428241 2.855162839204372 0
2.993265506185684 1.564338729663622 0
2.993485945460971 4.435841079163062 0
0.6535898384862247 3 0
4.207526358501587 1.30771311945606 0
4.222325167811828 4.713481083700964 0
4.684982476279815 4.446783549808456 0
0.6584540150429605 2.197505522861814 0
0.6452432023286079 1.785543202102719 0
0.991721359069401 1.594541136832898 0
0.6584540150429596 3.802494477138186 0
0.6452432023286088 4.214456797897283 0
0.9917213590694018 4.405458863167104 0
6.337898279836074 1.468552104899427 0
3.725814666632189 1.006161202772069 0
3.727861724836675 4.997781752172343 0
2.71823753962922 0.5089614868618111 0
2.42564871282169 0.9528077651738669 0
1.917737720641309 0.9590858204043498 0
2.953548665492042 0.9907390433338414 0
1.582311753559007 0.5232242704646306 0
1.438452989305671 0.9828474275997356 0
0.9561256081959053 0.5536231803723655 0
2.718237539629222 5.491038513138189 0
2.425648712821692 5.047192234826134 0
1.91773772064131 5.040914179595653 0
2.953548665492042 5.009260956666159 0
1.582311753559009 5.476775729535373 0
1.438452989305671 5.017152572400269 0
0.9561256081959053 5.446376819627639 0
5.237958310139073 0.5871328812536887 0
5.231161508381092 5.320884842558883 0
5.730095117657719 4.709163208192104 0
6.392679340286128 4.740264950727709 0
6.799909119346894 0.692559460780827 0
9.015759357425516 3.436770023568685 0
8.369438198798864 4.152935349006828 0
4.777079120184997 1.102529684456266 0
8.600842285595899 0.8040304733837873 0
8.146515696708807 1.451986451575071 0
4.558543212886178 3.245494084374797 0
3.724778578707128 2.475427915506771 0
5.571434342968493 4.042395785351718 0
9.131139835673602 1.517883942600189 0
8.339072751418477 2.768981474785674 0
8.509167904854674 5.110548098801203 0
3.909635849429954 0.4835223487702578 0
3.935631683965896 5.518286537373625 0
6.783699748497856 5.355007067106019 0
7.115360816054585 4.659159116016334 0
2.011107638316054 4.332323732696159 0
2.011107638316054 1.667676267303841 0
0.6605293274546211 2.599787884597093 0
0.6605293274546202 3.400212115402907 0
5.535011551393493 1.250786899229107 0
3.35293077355941 3.401967818554424 0
3.727109903141939 3.2 0
0.6374141174010743 4.657754959714784 0
0.6374141174010717 1.342245040285218 0
6.814023510170097 3.392838542686636 0
7.492726638179075 3.899495770308837 0
3.355642197322281 4.660250035126735 0
3.35533327938552 1.340316167656028 0
5.664725211275224 1.950778390142154 0
4.629594621599972 3.898374344912887 0
3.348175455783748 2.627908661415685 0
4.725392341471862 4.969802216238276 0
5.030240478039893 4.122005116001761 0
3.746700810245899 3.56756344220706 0
2.206391926625027 4.685217617601447 0
2.206391926625026 1.314782382398554 0
6.679129340275964 4.098034390413419 0
7.237007479385823 1.37039324394131 0
2.614061502217724 1.364066499724535 0
2.614098242096939 4.635963468413245 0
0.3301364731624217 4.015621601916699 0
0.3301364731624217 1.984378398083303 0
4.568335737056861 1.590519181398307 0
0.9623733488894919 4.898021228843596 0
0.962373348889491 1.101978771156408 0
0.4339428506372611 0.4379824664936298 0
0.4339428506372585 5.562017533506376 0
7.819783524181537 4.621420938680862 0
4.124448599087698 3.293922963767487 0
0.3340243820958246 2.426515806889854 0
0.3340243820958237 3.573484193110147 0
1.762260875711 4.664088404532289 0
1.762260875711 1.335911595467713 0
9.313658414826406 5.2948315419868 0
1.370242400478648 4.550267738756485 0
1.370242400478648 1.449732261243517 0
8.506249880004461 2.087388071184144 0
0.4006340049903221 2.794131890087235 0
0.3414629255044987 3.127971366433382 0
9.330146043102216 0.6897892631503182 0
4.205248828074824 0.8418669719513585 0
4.214202838423525 5.15701167442772 0
0.3225587585784213 4.394857671519284 0
0.3225587585784204 1.605142328480718 0
8.148441291582134 3.456654346772523 0
6.109356094572772 4.250735516880767 0
3.338692493968747 0.9762538631294975 0
3.338666087497807 5.033993941644791 0
3.653556691993875 2.848184417308439 0
2.705514202181899 1.708141239291102 0
2.705514202181898 4.291858760708897 0
5.161072196912267 4.633447254278279 0
$EndNodes
$Elements
10 504 1 504
1 1 1 14
1 1 9 
2 9 10 
3 10 11 
4 11 12 
5 12 13 
6 13 14 
7 14 15 
8 15 16 
9 16 17 
10 17 18 
11 18 19 
12 19 20 
13 20 21 
14 21 2 
1 2 1 11
15 3 22 
16 22 23 
17 23 24 
18 24 25 
19 25 26 
20 26 27 
21 27 28 
22 28 29 
23 29 30 
24 30 31 
25 31 1 
1 3 1 6
26 2 32 
27 32 33 
28 33 34 
29 34 35 
30 35 36 
31 36 4 
1 4 1 14
32 4 37 
33 37 38 
34 38 39 
35 39 40 
36 40 41 
37 41 42 
38 42 43 
39 43 44 
40 44 45 
41 45 46 
42 46 47 
43 47 48 
44 48 49 
45 49 3 
1 5 1 5
46 5 50 
47 50 51 
48 51 52 
49 52 53 
50 53 6 
1 6 1 5
51 6 54 
52 54 55 
53 55 56 
54 56 57 
55 57 7 
1 7 1 5
56 7 58 
57 58 59 
58 59 60 
59 60 61 
60 61 8 
1 8 1 5
61 8 62 
62 62 63 
63 63 64 
64 64 65 
65 65 5 
2 2 2 68
66 71 78 70 
67 75 83 81 
68 72 77 74 
69 75 81 80 
70 71 89 78 
71 74 88 72 
72 79 90 76 
73 82 90 79 
74 67 83 75 
75 63 75 62 
76 55 70 54 
77 56 66 55 
78 59 74 58 
79 64 67 63 
80 66 71 70 
81 66 72 71 
82 52 68 51 
83 64 76 67 
84 60 69 59 
85 67 75 63 
86 65 76 64 
87 66 70 55 
88 69 74 59 
89 72 73 71 
90 61 80 60 
91 66 77 72 
92 51 79 50 
93 53 78 52 
94 57 77 56 
95 56 77 66 
96 52 78 68 
97 60 80 69 
98 68 79 51 
99 6 86 53 
100 50 85 5 
101 8 84 61 
102 54 86 6 
103 7 87 57 
104 58 87 7 
105 62 84 8 
106 5 85 65 
107 73 83 82 
108 69 88 74 
109 68 82 79 
110 80 81 69 
111 73 89 71 
112 72 88 73 
113 83 90 82 
114 78 89 68 
115 82 89 73 
116 73 88 81 
117 53 86 78 
118 61 84 80 
119 79 85 50 
120 57 87 77 
121 75 84 62 
122 65 85 76 
123 70 86 54 
124 74 87 58 
125 76 90 67 
126 80 84 75 
127 77 87 74 
128 76 85 79 
129 78 86 70 
130 81 83 73 
131 81 88 69 
132 68 89 82 
133 67 90 83 
2 3 2 371
134 104 226 61 
135 50 227 105 
136 92 171 150 
137 61 226 149 
138 146 227 50 
139 182 219 173 
140 5 146 50 
141 61 149 8 
142 177 201 132 
143 10 159 9 
144 49 166 48 
145 171 209 150 
146 159 217 9 
147 49 218 166 
148 133 182 173 
149 172 181 96 
150 172 236 181 
151 150 209 134 
152 135 209 176 
153 23 234 194 
154 195 235 30 
155 123 201 177 
156 150 191 92 
157 179 243 204 
158 203 233 142 
159 157 159 10 
160 48 166 164 
161 112 183 151 
162 23 194 110 
163 109 195 30 
164 152 184 111 
165 174 191 131 
166 141 232 174 
167 11 157 10 
168 48 164 47 
169 166 218 110 
170 109 217 159 
171 134 209 135 
172 156 199 138 
173 139 198 163 
174 128 161 160 
175 153 154 129 
176 94 168 42 
177 16 167 95 
178 151 238 112 
179 18 171 92 
180 150 200 191 
181 111 239 152 
182 169 243 179 
183 167 191 174 
184 191 200 131 
185 143 203 142 
186 167 174 95 
187 19 171 18 
188 12 153 129 
189 128 160 46 
190 175 180 176 
191 42 168 41 
192 17 167 16 
193 138 210 156 
194 163 211 139 
195 110 215 166 
196 159 216 109 
197 117 177 137 
198 132 220 177 
199 128 162 161 
200 154 155 129 
201 112 156 153 
202 160 163 111 
203 174 232 95 
204 149 226 215 
205 216 227 146 
206 176 228 135 
207 153 156 154 
208 161 163 160 
209 229 230 27 
210 34 172 96 
211 197 208 196 
212 101 178 97 
213 129 157 11 
214 47 164 128 
215 133 173 172 
216 108 171 19 
217 112 153 13 
218 45 160 111 
219 95 183 15 
220 41 168 93 
221 92 167 17 
222 43 184 94 
223 135 228 181 
224 16 95 15 
225 43 94 42 
226 14 183 112 
227 111 184 44 
228 12 129 11 
229 47 128 46 
230 20 108 19 
231 41 93 40 
232 18 92 17 
233 45 111 44 
234 14 112 13 
235 175 176 108 
236 39 99 38 
237 185 186 99 
238 170 186 185 
239 31 109 30 
240 23 110 22 
241 124 200 150 
242 133 172 35 
243 39 185 99 
244 34 96 33 
245 119 177 117 
246 13 153 12 
247 46 160 45 
248 179 237 169 
249 123 177 119 
250 164 165 162 
251 155 158 157 
252 115 178 101 
253 168 169 93 
254 27 230 26 
255 20 175 108 
256 36 133 35 
257 93 185 40 
258 117 137 115 
259 35 172 34 
260 121 123 119 
261 137 178 115 
262 174 214 141 
263 121 179 123 
264 170 185 93 
265 180 228 176 
266 21 175 20 
267 149 215 194 
268 195 216 146 
269 173 236 172 
270 92 191 167 
271 155 157 129 
272 128 164 162 
273 33 180 32 
274 124 150 134 
275 96 180 33 
276 94 203 168 
277 99 219 182 
278 165 223 162 
279 155 224 158 
280 1 217 31 
281 22 218 3 
282 94 233 203 
283 203 243 168 
284 168 243 169 
285 40 185 39 
286 196 208 126 
287 38 182 37 
288 176 209 108 
289 165 226 223 
290 224 227 158 
291 99 182 38 
292 15 183 14 
293 44 184 43 
294 158 159 157 
295 164 166 165 
296 142 152 127 
297 126 179 121 
298 113 151 141 
299 169 170 93 
300 207 210 106 
301 107 211 206 
302 52 106 53 
303 60 104 61 
304 50 105 51 
305 58 107 59 
306 59 187 60 
307 51 188 52 
308 135 136 125 
309 9 217 1 
310 3 218 49 
311 193 220 205 
312 55 91 56 
313 62 190 63 
314 63 140 64 
315 64 189 65 
316 8 147 62 
317 65 144 5 
318 8 149 148 
319 145 146 5 
320 102 139 7 
321 6 138 100 
322 56 192 57 
323 6 97 54 
324 57 98 7 
325 178 202 97 
326 205 220 132 
327 122 126 121 
328 120 124 122 
329 197 236 173 
330 162 206 161 
331 154 207 155 
332 124 134 125 
333 215 226 165 
334 158 227 216 
335 120 121 119 
336 131 214 174 
337 136 197 196 
338 177 220 137 
339 118 119 117 
340 103 132 130 
341 4 225 36 
342 114 115 101 
343 135 181 136 
344 186 208 197 
345 116 131 118 
346 116 117 115 
347 112 238 156 
348 163 239 111 
349 134 135 125 
350 37 225 4 
351 124 125 122 
352 6 100 97 
353 98 102 7 
354 54 202 55 
355 120 122 121 
356 8 148 147 
357 144 145 5 
358 32 231 2 
359 179 204 123 
360 152 198 127 
361 95 232 183 
362 100 113 101 
363 103 127 102 
364 184 233 94 
365 113 199 151 
366 113 141 114 
367 118 120 119 
368 136 196 125 
369 130 142 127 
370 156 210 154 
371 161 211 163 
372 116 214 131 
373 123 204 201 
374 116 118 117 
375 2 231 21 
376 107 187 59 
377 52 188 106 
378 60 187 104 
379 105 188 51 
380 173 219 197 
381 114 116 115 
382 145 195 146 
383 149 194 148 
384 113 114 101 
385 136 236 197 
386 24 234 23 
387 30 235 29 
388 130 143 142 
389 100 101 97 
390 98 103 102 
391 147 190 62 
392 63 190 140 
393 65 189 144 
394 140 189 64 
395 103 130 127 
396 170 208 186 
397 91 192 56 
398 122 196 126 
399 120 200 124 
400 57 192 98 
401 103 205 132 
402 137 220 193 
403 55 202 91 
404 26 222 25 
405 28 221 27 
406 193 240 137 
407 125 196 122 
408 97 202 54 
409 7 242 58 
410 53 241 6 
411 91 193 192 
412 102 198 139 
413 138 199 100 
414 100 199 113 
415 127 198 102 
416 169 237 170 
417 131 200 118 
418 183 232 151 
419 180 231 32 
420 132 201 130 
421 152 233 184 
422 156 238 199 
423 198 239 163 
424 175 231 180 
425 197 219 186 
426 118 200 120 
427 108 209 171 
428 6 241 138 
429 139 242 7 
430 130 201 143 
431 36 225 133 
432 105 227 224 
433 223 226 104 
434 154 210 207 
435 206 211 161 
436 29 213 28 
437 25 212 24 
438 110 218 22 
439 31 217 109 
440 166 215 165 
441 158 216 159 
442 107 242 211 
443 210 241 106 
444 151 232 141 
445 142 233 152 
446 96 228 180 
447 137 240 178 
448 114 214 116 
449 186 219 99 
450 201 204 143 
451 109 216 195 
452 194 215 110 
453 107 206 187 
454 188 207 106 
455 98 205 103 
456 192 205 98 
457 193 205 192 
458 141 214 114 
459 21 231 175 
460 148 212 147 
461 144 213 145 
462 133 225 182 
463 182 225 37 
464 26 230 222 
465 221 229 27 
466 202 240 91 
467 181 228 96 
468 126 237 179 
469 162 223 206 
470 207 224 155 
471 143 243 203 
472 147 222 190 
473 189 221 144 
474 181 236 136 
475 206 223 187 
476 188 224 207 
477 187 223 104 
478 105 224 188 
479 148 234 212 
480 213 235 145 
481 211 242 139 
482 138 241 210 
483 204 243 143 
484 145 235 195 
485 194 234 148 
486 212 222 147 
487 144 221 213 
488 190 230 140 
489 140 229 189 
490 199 238 151 
491 178 240 202 
492 152 239 198 
493 106 241 53 
494 58 242 107 
495 212 234 24 
496 29 235 213 
497 222 230 190 
498 189 229 221 
499 91 240 193 
500 140 230 229 
501 208 237 126 
502 213 221 28 
503 25 222 212 
504 170 237 208 
$EndElements

This is the .msh mesh file used in the example.”

This seems like a pyvista question to me, rather than a DOLFINx question, as the function you are questioning the output of is:

which is a pyvista function.

However, I think one of the issues with computing mesh quality within pyvista is that it expects the mesh to be ordered in a anti-clock-wise fashion for all cells. This is not necessarily true when exporting data from DOLFINx (as non-simplex grids cannot be ordered).

There are several assumptions in your code that isn’t quite right when it comes to DOLFINx related things. Below I attach a way of identifying inverted cells and measuring a scaled_jacobian, based purely on DOLFINx:

# # Compute the scaled jacobian with DOLFINx
# Author: Jørgen S. Dokken

from dolfinx.io import gmsh as gmshio
import matplotlib.pyplot as plt


from mpi4py import MPI


import numpy as np
import pyvista
import dolfinx
import ufl
from dolfinx import plot
mesh_data = gmshio.read_from_msh(
    "mesh.msh",
    comm=MPI.COMM_WORLD,
    rank=0,          
    gdim=2
)


domain = mesh_data.mesh
cell_tags  = mesh_data.cell_tags
facet_tags = mesh_data.facet_tags


num_cells_local =domain.topology.index_map(domain.topology.dim).size_local
cells = np.arange(num_cells_local, dtype=np.int32)
c_e_v = ufl.geometry.CellEdgeVectors(domain)
expr_cev = dolfinx.fem.Expression(c_e_v, np.array([[0.,0.]]))
jac = ufl.JacobianDeterminant(domain)
expr_jac = dolfinx.fem.Expression(jac, np.array([[0.,0.]]))
org_jac_sign = np.sign(expr_jac.eval(domain, cells)).flatten()


tdim = domain.topology.dim
fdim = tdim - 1
V_lin = dolfinx.fem.functionspace(domain, ("Lagrange", 1))
_, cell_types, _ = plot.vtk_mesh(V_lin)
topology, _, geometry2 = plot.vtk_mesh(domain)

domain.topology.create_connectivity(0, domain.topology.dim)
domain.topology.create_connectivity(domain.topology.dim, 0)
vertices16 = dolfinx.mesh.compute_incident_entities(domain.topology, cell_tags.find(16), domain.topology.dim, 0)
nodes16 = dolfinx.mesh.entities_to_geometry(domain, 0, vertices16).flatten()

x  = domain.geometry.x     
x0 = x.copy()            

gdim = domain.geometry.dim
dx = np.array((0.5, 0.5, 0.0))


x1 = x0.copy()
x1[nodes16, :gdim] += dx[:gdim]


from dolfinx import plot
import pyvista


grid = pyvista.UnstructuredGrid(topology.flatten(), cell_types, x1)

plotter = pyvista.Plotter()
plotter.add_mesh(grid, show_edges=True)
plotter.view_xy()
plotter.show()


x = domain.geometry.x
x_backup = x.copy()

x[:] = x1

cqual = grid.cell_quality("scaled_jacobian", progress_bar = True)
q = cqual.active_scalars


import ufl
import dolfinx

jac = ufl.geometry.JacobianDeterminant(domain)
expr_jac = dolfinx.fem.Expression(jac, np.array([[0.,0.]]))

cev_vals = expr_cev.eval(domain, cells).reshape(num_cells_local, 3, 2)
jac_vals = expr_jac.eval(domain, cells).reshape(-1)
edge_lengths = np.linalg.norm(cev_vals, axis=2)
sorted_lengths = np.sort(edge_lengths, axis=1)
_max_pos = sorted_lengths[:,-2:]
_max_prod =  np.prod(_max_pos, axis=1)

denominator = _max_prod
vals = jac_vals/denominator*org_jac_sign

flipped_cells = vals < 0
grid.cell_data["flipped"] = flipped_cells
grid.set_active_scalars("flipped")
plotter2 = pyvista.Plotter()
plotter2.add_mesh(grid, show_edges=True, scalars="flipped", opacity=0.5)
plotter2.add_mesh(grid, style="wireframe")
plotter2.view_xy()
plotter2.show()

print("cell_number =", q.size)
print("scaled_jacobian: min =", float(q.min()), " max =", float(q.max()), "mean =",float(q.mean()))
print("fenics scaled jacobian: min= ", float(vals.min()), " max = ",float(vals.max()), "mean = ", vals.mean())

plt.figure()
plt.hist(q, bins=30, label="pyvista")
plt.hist(vals, bins=30, label="fenics")

plt.xlabel("scaled_jacobian")
plt.ylabel("Number of cells")
plt.title("Mesh quality: scaled_jacobian")
plt.legend()
plt.show()

which yields:


and

2 Likes

Hello. PyVista uses the VTK implementation of mesh quality measures, you can find the implementation for scaled Jacobian over triangles here. If you inspect the code, you can find that the returned value will always be positive due to taking jacobian = cross.length(), so you will never receive negative values.

An implementation of the measure using vectorized numpy should be efficient enough and probably give you the values you expect.

Hope this is helpful.

2 Likes

Hi, thank you very much for your detailed reply and for sharing the complete DOLFINx-based implementation.
I appreciate the clear code example — it works well on my side and has resolved my issue.

Thank you for the explanation — it was very helpful. I checked the link you provided and confirmed that PyVista’s scaled Jacobian for triangles is always non-negative. This really cleared up my confusion. I appreciate your support!