2Correctness tests for CFV.FiniteVolume through the Python bindings.
4Tests the FiniteVolume construction pipeline and verifies geometric
5quantities (volumes, areas, barycenters, normals) against known values
6for the Uniform_3x3_wall mesh (a 3x3 quad grid on [-1,2]^2).
8These tests use pytest assertions and are intended for automated CI.
11from __future__
import annotations
18from DNDSR
import DNDS, Geom, CFV
22@pytest.fixture(scope="module")
30 """Return absolute path to a mesh file under data/mesh/."""
32 os.path.dirname(__file__),
"..",
"..",
"data",
"mesh", name
37 """Construct a FiniteVolume with default settings on a given mesh."""
38 fv = CFV.FiniteVolume(mpi, mesh)
39 settings = fv.GetSettings()
40 settings[
"intOrder"] = 3
41 settings[
"maxOrder"] = 1
42 fv.ParseSettings(settings)
45 fv.ConstructCellVolume()
46 fv.ConstructCellBary()
47 fv.ConstructCellCent()
48 fv.ConstructCellIntJacobiDet()
49 fv.ConstructCellIntPPhysics()
50 fv.ConstructCellAlignedHBox()
51 fv.ConstructCellMajorHBoxCoordInertia()
54 fv.ConstructFaceCent()
55 fv.ConstructFaceArea()
56 fv.ConstructFaceIntJacobiDet()
57 fv.ConstructFaceIntPPhysics()
58 fv.ConstructFaceUnitNorm()
59 fv.ConstructFaceMeanNorm()
61 fv.ConstructCellSmoothScale()
65@pytest.fixture(scope="module")
67 """Build FiniteVolume on the Uniform_3x3_wall mesh (9 quads, [-1,2]^2)."""
69 mesh, reader, name2Id = create_mesh_from_CGNS(mesh_file, mpi, 2)
71 return mesh, fv, name2Id
74@pytest.fixture(scope="module")
76 """Build FiniteVolume on Uniform_3x3 with periodic BCs (9 quads, [0,3]^2)."""
78 mesh, reader, name2Id = create_mesh_from_CGNS(
83 "translation1": [3, 0, 0],
84 "translation2": [0, 3, 0],
88 return mesh, fv, name2Id
97 """Verify cell volumes for uniform quad meshes."""
100 """Each cell in Uniform_3x3_wall has volume 1.0 (unit squares on [-1,2]^2)."""
101 mesh, fv, _ = wall_mesh_fv
102 for iCell
in range(mesh.NumCell()):
103 vol = fv.GetCellVol(iCell)
104 assert vol == pytest.approx(1.0, abs=1e-12), (
105 f
"Cell {iCell} volume = {vol}, expected 1.0"
109 """Each cell in Uniform_3x3 has volume 1.0 (unit squares on [0,3]^2)."""
110 mesh, fv, _ = periodic_mesh_fv
111 for iCell
in range(mesh.NumCell()):
112 vol = fv.GetCellVol(iCell)
113 assert vol == pytest.approx(1.0, abs=1e-12), (
114 f
"Cell {iCell} volume = {vol}, expected 1.0"
124 """Verify global (summed) volume equals the domain area."""
127 """Domain [-1,2]^2 has area 9.0."""
128 _, fv, _ = wall_mesh_fv
129 assert fv.GetGlobalVol() == pytest.approx(9.0, abs=1e-10)
132 """Domain [0,3]^2 has area 9.0."""
133 _, fv, _ = periodic_mesh_fv
134 assert fv.GetGlobalVol() == pytest.approx(9.0, abs=1e-10)
143 """Verify face areas on uniform quad meshes are 1.0 (unit edge length)."""
146 mesh, fv, _ = wall_mesh_fv
147 for iFace
in range(mesh.NumFaceProc()):
148 area = fv.GetFaceArea(iFace)
149 assert area == pytest.approx(1.0, abs=1e-12), (
150 f
"Face {iFace} area = {area}, expected 1.0"
154 mesh, fv, _ = periodic_mesh_fv
155 for iFace
in range(mesh.NumFaceProc()):
156 area = fv.GetFaceArea(iFace)
157 assert area == pytest.approx(1.0, abs=1e-12), (
158 f
"Face {iFace} area = {area}, expected 1.0"
168 """Verify cell barycenters are at cell centers."""
171 """All barycenters should be within [-1,2]^2."""
172 mesh, fv, _ = wall_mesh_fv
173 for iCell
in range(mesh.NumCell()):
174 bary = fv.GetCellBary(iCell)
175 assert -1.0 - 1e-10 <= bary[0] <= 2.0 + 1e-10, (
176 f
"Cell {iCell} bary x = {bary[0]} out of range"
178 assert -1.0 - 1e-10 <= bary[1] <= 2.0 + 1e-10, (
179 f
"Cell {iCell} bary y = {bary[1]} out of range"
183 """Barycenters of unit-square cells are at half-integer offsets from -1."""
184 mesh, fv, _ = wall_mesh_fv
185 expected_coords = {-0.5, 0.5, 1.5}
188 for iCell
in range(mesh.NumCell()):
189 bary = fv.GetCellBary(iCell)
190 bary_xs.add(round(bary[0], 8))
191 bary_ys.add(round(bary[1], 8))
192 assert bary_xs == expected_coords, f
"Got x coords: {bary_xs}"
193 assert bary_ys == expected_coords, f
"Got y coords: {bary_ys}"
202 """Verify DOF arrays can be built and have correct sizes."""
205 mesh, fv, _ = wall_mesh_fv
208 assert u.Size() >= mesh.NumCell()
209 assert u.father.Size() == mesh.NumCell()
212 mesh, fv, _ = wall_mesh_fv
215 assert u.Size() >= mesh.NumCell()
218 mesh, fv, _ = wall_mesh_fv
219 grad = CFV.tUGrad_3xD()
220 fv.BuildUGrad_3xD(grad, 1)
221 assert grad.Size() >= mesh.NumCell()
224 """Writing and reading back DOF values through numpy views."""
225 mesh, fv, _ = wall_mesh_fv
228 for iCell
in range(mesh.NumCell()):
229 u_i = np.array(u[iCell], copy=
False)
230 u_i[0] = float(iCell) + 0.5
231 for iCell
in range(mesh.NumCell()):
232 u_i = np.array(u[iCell], copy=
False)
233 assert u_i[0] == pytest.approx(float(iCell) + 0.5, abs=1e-14)
242 """Verify getArrayBytes returns a positive value."""
245 _, fv, _ = wall_mesh_fv
246 nbytes = fv.getArrayBytes()
256 """Verify smooth scale ratio is finite and positive for all cells."""
259 mesh, fv, _ = wall_mesh_fv
260 for iCell
in range(mesh.NumCell()):
261 ratio = fv.GetCellSmoothScaleRatio(iCell)
262 assert np.isfinite(ratio), f
"Cell {iCell} smooth scale ratio not finite"
263 assert ratio > 0, f
"Cell {iCell} smooth scale ratio = {ratio}"
272 """Verify Jacobian determinants at quadrature points are positive."""
275 mesh, fv, _ = wall_mesh_fv
276 for iCell
in range(mesh.NumCell()):
278 jdet = fv.GetCellJacobiDet(iCell, 0)
279 assert jdet > 0, f
"Cell {iCell} Jacobi det = {jdet}"
282 mesh, fv, _ = wall_mesh_fv
283 for iFace
in range(mesh.NumFaceProc()):
284 jdet = fv.GetFaceJacobiDet(iFace, 0)
285 assert jdet > 0, f
"Face {iFace} Jacobi det = {jdet}"
288if __name__ ==
"__main__":
289 pytest.main([__file__,
"-v"])
test_array_bytes_positive(self, wall_mesh_fv)
test_wall_mesh_barycenters_are_half_integers(self, wall_mesh_fv)
test_wall_mesh_barycenters_in_domain(self, wall_mesh_fv)
test_wall_mesh_cell_volumes(self, wall_mesh_fv)
test_periodic_mesh_cell_volumes(self, periodic_mesh_fv)
test_build_udof_dynamic(self, wall_mesh_fv)
test_build_udof_fixed_5(self, wall_mesh_fv)
test_build_ugrad_3xD(self, wall_mesh_fv)
test_udof_write_read(self, wall_mesh_fv)
test_wall_mesh_face_areas(self, wall_mesh_fv)
test_periodic_mesh_face_areas(self, periodic_mesh_fv)
test_wall_mesh_global_volume(self, wall_mesh_fv)
test_periodic_mesh_global_volume(self, periodic_mesh_fv)
test_cell_jacobi_det_positive(self, wall_mesh_fv)
test_face_jacobi_det_positive(self, wall_mesh_fv)
test_smooth_scale_ratio(self, wall_mesh_fv)
str _data_mesh_path(str name)
CFV.FiniteVolume _build_fv(mpi, mesh)
set(LIBNAME cfv) set(LINKS) set(LINKS_SHARED geom_shared dnds_shared $
Lightweight bundle of an MPI communicator and the calling rank's coordinates.