你已经派生过 gprMax
镜像自地址
https://gitee.com/sunhf/gprMax.git
已同步 2025-08-07 23:14:03 +08:00
Add geometry object reframe tests
这个提交包含在:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -2,3 +2,5 @@ tools/Jupyter_notebooks/* linguist-vendored
|
|||||||
reframe_tests/regression_checks/TestGeometryView_5176823e/partial_volume.vtkhdf filter=lfs diff=lfs merge=lfs -text
|
reframe_tests/regression_checks/TestGeometryView_5176823e/partial_volume.vtkhdf filter=lfs diff=lfs merge=lfs -text
|
||||||
reframe_tests/regression_checks/TestGeometryView_5176823e/full_volume.vtkhdf filter=lfs diff=lfs merge=lfs -text
|
reframe_tests/regression_checks/TestGeometryView_5176823e/full_volume.vtkhdf filter=lfs diff=lfs merge=lfs -text
|
||||||
reframe_tests/regression_checks/TestGeometryView_77980202/full_volume.vtkhdf filter=lfs diff=lfs merge=lfs -text
|
reframe_tests/regression_checks/TestGeometryView_77980202/full_volume.vtkhdf filter=lfs diff=lfs merge=lfs -text
|
||||||
|
reframe_tests/regression_checks/TestGeometryObject_a6a096cb/full_volume.h5 filter=lfs diff=lfs merge=lfs -text
|
||||||
|
reframe_tests/regression_checks/TestGeometryObject_a6a096cb/partial_volume.h5 filter=lfs diff=lfs merge=lfs -text
|
||||||
|
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:ac30e1b942acb3e17bec7d2a16167429ed3b1590642d9c403ee5d0adb6be27c8
|
||||||
|
size 75462640
|
@@ -0,0 +1,9 @@
|
|||||||
|
#material: 1 inf 1 0 pec
|
||||||
|
#material: 1 0 1 0 free_space
|
||||||
|
#material: 4.9 0 1 0 myWater
|
||||||
|
#material: 3 0 2 0 boxMaterial
|
||||||
|
#material: 1.5 0 1.25 0 boxMaterial+free_space+free_space+free_space
|
||||||
|
#material: 2 0 1.5 0 boxMaterial+free_space+free_space+boxMaterial
|
||||||
|
#material: 1.975 0 1 0 myWater+free_space+free_space+free_space
|
||||||
|
#material: 2.95 0 1 0 myWater+free_space+free_space+myWater
|
||||||
|
#material: 3.925 0 1 0 myWater+myWater+free_space+myWater
|
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:224975ddea1c1a4cd3f99aaa9e7ce1fb1ec31de07b0352424f66be73a5645a4f
|
||||||
|
size 4980400
|
@@ -0,0 +1,9 @@
|
|||||||
|
#material: 1 inf 1 0 pec
|
||||||
|
#material: 1 0 1 0 free_space
|
||||||
|
#material: 4.9 0 1 0 myWater
|
||||||
|
#material: 3 0 2 0 boxMaterial
|
||||||
|
#material: 1.5 0 1.25 0 boxMaterial+free_space+free_space+free_space
|
||||||
|
#material: 2 0 1.5 0 boxMaterial+free_space+free_space+boxMaterial
|
||||||
|
#material: 1.975 0 1 0 myWater+free_space+free_space+free_space
|
||||||
|
#material: 2.95 0 1 0 myWater+free_space+free_space+myWater
|
||||||
|
#material: 3.925 0 1 0 myWater+myWater+free_space+myWater
|
@@ -9,9 +9,11 @@ from typing_extensions import TYPE_CHECKING
|
|||||||
|
|
||||||
from reframe_tests.tests.base_tests import GprMaxBaseTest
|
from reframe_tests.tests.base_tests import GprMaxBaseTest
|
||||||
from reframe_tests.tests.regression_checks import (
|
from reframe_tests.tests.regression_checks import (
|
||||||
|
GeometryObjectMaterialsRegressionCheck,
|
||||||
|
GeometryObjectRegressionCheck,
|
||||||
GeometryViewRegressionCheck,
|
GeometryViewRegressionCheck,
|
||||||
|
H5RegressionCheck,
|
||||||
ReceiverRegressionCheck,
|
ReceiverRegressionCheck,
|
||||||
RegressionCheck,
|
|
||||||
SnapshotRegressionCheck,
|
SnapshotRegressionCheck,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -38,7 +40,7 @@ class ReceiverMixin(GprMaxMixin):
|
|||||||
)
|
)
|
||||||
self.regression_checks.append(regression_check)
|
self.regression_checks.append(regression_check)
|
||||||
else:
|
else:
|
||||||
regression_check = RegressionCheck(self.output_file, reference_file)
|
regression_check = H5RegressionCheck(self.output_file, reference_file)
|
||||||
self.regression_checks.append(regression_check)
|
self.regression_checks.append(regression_check)
|
||||||
|
|
||||||
|
|
||||||
@@ -86,6 +88,61 @@ class GeometryOnlyMixin(GprMaxMixin):
|
|||||||
self.executable_opts += ["--geometry-only"]
|
self.executable_opts += ["--geometry-only"]
|
||||||
|
|
||||||
|
|
||||||
|
class GeometryObjectMixin(GprMaxMixin):
|
||||||
|
"""Add regression tests for geometry objects.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
geometry_objects (list[str]): List of geometry objects to run
|
||||||
|
regression checks on.
|
||||||
|
"""
|
||||||
|
|
||||||
|
geometry_objects = variable(typ.List[str], value=[])
|
||||||
|
|
||||||
|
def build_geometry_object_filepath(self, geometry_object: str) -> Path:
|
||||||
|
"""Build filepath to the specified geometry object.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
geometry_object: Name of the geometry object.
|
||||||
|
"""
|
||||||
|
return Path(geometry_object).with_suffix(".h5")
|
||||||
|
|
||||||
|
def build_materials_filepath(self, geometry_object: str) -> Path:
|
||||||
|
"""Build filepath to the materials output by the geometry object.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
geometry_object: Name of the geometry object.
|
||||||
|
"""
|
||||||
|
return Path(f"{geometry_object}_materials").with_suffix(".txt")
|
||||||
|
|
||||||
|
@run_after("setup")
|
||||||
|
def add_geometry_object_regression_checks(self):
|
||||||
|
"""Add a regression check for each geometry object.
|
||||||
|
|
||||||
|
The test will be skipped if no geometry objects have been specified.
|
||||||
|
"""
|
||||||
|
self.skip_if(
|
||||||
|
len(self.geometry_objects) < 0,
|
||||||
|
f"Must provide a list of geometry objects.",
|
||||||
|
)
|
||||||
|
|
||||||
|
for geometry_object in self.geometry_objects:
|
||||||
|
# Add materials regression check first as if this fails,
|
||||||
|
# checking the .h5 file will almost definitely fail.
|
||||||
|
materials_file = self.build_materials_filepath(geometry_object)
|
||||||
|
materials_reference_file = self.build_reference_filepath(
|
||||||
|
materials_file.name, suffix=materials_file.suffix
|
||||||
|
)
|
||||||
|
materials_regression_check = GeometryObjectMaterialsRegressionCheck(
|
||||||
|
materials_file, materials_reference_file
|
||||||
|
)
|
||||||
|
self.regression_checks.append(materials_regression_check)
|
||||||
|
|
||||||
|
geometry_object_file = self.build_geometry_object_filepath(geometry_object)
|
||||||
|
reference_file = self.build_reference_filepath(geometry_object)
|
||||||
|
regression_check = GeometryObjectRegressionCheck(geometry_object_file, reference_file)
|
||||||
|
self.regression_checks.append(regression_check)
|
||||||
|
|
||||||
|
|
||||||
class GeometryViewMixin(GprMaxMixin):
|
class GeometryViewMixin(GprMaxMixin):
|
||||||
"""Add regression tests for geometry views.
|
"""Add regression tests for geometry views.
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ from reframe.utility import osext
|
|||||||
|
|
||||||
|
|
||||||
class RegressionCheck:
|
class RegressionCheck:
|
||||||
"""Compare two hdf5 files using h5diff"""
|
"""Compare two files using diff"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, output_file: Union[str, PathLike], reference_file: Union[str, PathLike]
|
self, output_file: Union[str, PathLike], reference_file: Union[str, PathLike]
|
||||||
@@ -23,7 +23,8 @@ class RegressionCheck:
|
|||||||
"""
|
"""
|
||||||
self.output_file = Path(output_file)
|
self.output_file = Path(output_file)
|
||||||
self.reference_file = Path(reference_file)
|
self.reference_file = Path(reference_file)
|
||||||
self.h5diff_options: list[str] = []
|
self.cmd = "diff"
|
||||||
|
self.options: list[str] = []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def error_msg(self) -> str:
|
def error_msg(self) -> str:
|
||||||
@@ -57,26 +58,22 @@ class RegressionCheck:
|
|||||||
return sn.path_isfile(self.reference_file)
|
return sn.path_isfile(self.reference_file)
|
||||||
|
|
||||||
def run(self) -> Literal[True]:
|
def run(self) -> Literal[True]:
|
||||||
"""Run the regression check using h5diff.
|
"""Run the regression check.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
check_passed: Returns True if the output file matches the
|
check_passed: Returns True if the output file matches the
|
||||||
reference file (i.e. no output from h5diff). Otherwise,
|
reference file (i.e. no output from diff). Otherwise,
|
||||||
raises a SanityError.
|
raises a SanityError.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
reframe.core.exceptions.SanityError: If the output file does
|
reframe.core.exceptions.SanityError: If the output file does
|
||||||
not exist, or the regression check fails.
|
not exist, or the regression check fails.
|
||||||
"""
|
"""
|
||||||
if runtime().system.name == "archer2":
|
|
||||||
h5diff = "/opt/cray/pe/hdf5/default/bin/h5diff"
|
|
||||||
else:
|
|
||||||
h5diff = "h5diff"
|
|
||||||
|
|
||||||
h5diff_output = osext.run_command(
|
completed_process = osext.run_command(
|
||||||
[
|
[
|
||||||
h5diff,
|
self.cmd,
|
||||||
*self.h5diff_options,
|
*self.options,
|
||||||
str(self.output_file.absolute()),
|
str(self.output_file.absolute()),
|
||||||
str(self.reference_file),
|
str(self.reference_file),
|
||||||
]
|
]
|
||||||
@@ -86,16 +83,29 @@ class RegressionCheck:
|
|||||||
sn.path_isfile(self.output_file),
|
sn.path_isfile(self.output_file),
|
||||||
f"Expected output file '{self.output_file}' does not exist",
|
f"Expected output file '{self.output_file}' does not exist",
|
||||||
) and sn.assert_false(
|
) and sn.assert_false(
|
||||||
h5diff_output.stdout,
|
completed_process.stdout,
|
||||||
(
|
(
|
||||||
f"{self.error_msg}\n"
|
f"{self.error_msg}\n"
|
||||||
f"For more details run: '{' '.join(h5diff_output.args)}'\n"
|
f"For more details run: '{' '.join(completed_process.args)}'\n"
|
||||||
f"To re-create regression file, delete '{self.reference_file}' and rerun the test."
|
f"To re-create regression file, delete '{self.reference_file}' and rerun the test."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ReceiverRegressionCheck(RegressionCheck):
|
class H5RegressionCheck(RegressionCheck):
|
||||||
|
"""Compare two hdf5 files using h5diff"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, output_file: Union[str, PathLike], reference_file: Union[str, PathLike]
|
||||||
|
) -> None:
|
||||||
|
super().__init__(output_file, reference_file)
|
||||||
|
if runtime().system.name == "archer2":
|
||||||
|
self.cmd = "/opt/cray/pe/hdf5/default/bin/h5diff"
|
||||||
|
else:
|
||||||
|
self.cmd = "h5diff"
|
||||||
|
|
||||||
|
|
||||||
|
class ReceiverRegressionCheck(H5RegressionCheck):
|
||||||
"""Run regression check on individual reveivers in output files.
|
"""Run regression check on individual reveivers in output files.
|
||||||
|
|
||||||
This can include arbitrary receivers in each file, or two receivers
|
This can include arbitrary receivers in each file, or two receivers
|
||||||
@@ -106,7 +116,7 @@ class ReceiverRegressionCheck(RegressionCheck):
|
|||||||
self,
|
self,
|
||||||
output_file: Union[str, PathLike],
|
output_file: Union[str, PathLike],
|
||||||
reference_file: Union[str, PathLike],
|
reference_file: Union[str, PathLike],
|
||||||
output_receiver: Optional[str],
|
output_receiver: str,
|
||||||
reference_receiver: Optional[str] = None,
|
reference_receiver: Optional[str] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Create a new receiver regression check.
|
"""Create a new receiver regression check.
|
||||||
@@ -125,26 +135,42 @@ class ReceiverRegressionCheck(RegressionCheck):
|
|||||||
self.output_receiver = output_receiver
|
self.output_receiver = output_receiver
|
||||||
self.reference_receiver = reference_receiver
|
self.reference_receiver = reference_receiver
|
||||||
|
|
||||||
self.h5diff_options.append(f"rxs/{self.output_receiver}")
|
self.options.append(f"rxs/{self.output_receiver}")
|
||||||
if self.reference_receiver is not None:
|
if self.reference_receiver is not None:
|
||||||
self.h5diff_options.append(f"rxs/{self.reference_receiver}")
|
self.options.append(f"rxs/{self.reference_receiver}")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def error_msg(self) -> str:
|
def error_msg(self) -> str:
|
||||||
return f"Receiver '{self.output_receiver}' failed regression check"
|
return f"Receiver '{self.output_receiver}' failed regression check"
|
||||||
|
|
||||||
|
|
||||||
class SnapshotRegressionCheck(RegressionCheck):
|
class SnapshotRegressionCheck(H5RegressionCheck):
|
||||||
"""Run regression check on a gprMax Snapshot."""
|
"""Run regression check on a gprMax Snapshot."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def error_msg(self) -> str:
|
def error_msg(self) -> str:
|
||||||
return f"Snapshot '{self.output_file.name}' failed regression check "
|
return f"Snapshot '{self.output_file.name}' failed regression check"
|
||||||
|
|
||||||
|
|
||||||
class GeometryViewRegressionCheck(RegressionCheck):
|
class GeometryObjectRegressionCheck(H5RegressionCheck):
|
||||||
|
"""Run regression check on a GprMax GeometryObject."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def error_msg(self) -> str:
|
||||||
|
return f"GeometryObject '{self.output_file.name}' failed regression check"
|
||||||
|
|
||||||
|
|
||||||
|
class GeometryObjectMaterialsRegressionCheck(RegressionCheck):
|
||||||
|
"""Run regression check on materials output by a GeometryObject."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def error_msg(self) -> str:
|
||||||
|
return f"GeometryObject materials file '{self.output_file}' failed regression check"
|
||||||
|
|
||||||
|
|
||||||
|
class GeometryViewRegressionCheck(H5RegressionCheck):
|
||||||
"""Run regression check on a GprMax GeometryView."""
|
"""Run regression check on a GprMax GeometryView."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def error_msg(self) -> str:
|
def error_msg(self) -> str:
|
||||||
return f"GeometryView '{self.output_file.name}' failed regression check "
|
return f"GeometryView '{self.output_file.name}' failed regression check"
|
||||||
|
@@ -0,0 +1,17 @@
|
|||||||
|
#title: Hertzian dipole in free-space
|
||||||
|
#domain: 0.100 0.100 0.100
|
||||||
|
#dx_dy_dz: 0.001 0.001 0.001
|
||||||
|
#time_window: 3e-9
|
||||||
|
|
||||||
|
#waveform: gaussiandot 1 1e9 myWave
|
||||||
|
#hertzian_dipole: z 0.050 0.050 0.050 myWave
|
||||||
|
|
||||||
|
#material: 4.9 0 1 0 myWater
|
||||||
|
#material: 2 0 1.4 0 unusedMaterial
|
||||||
|
#material: 3 0 2 0 boxMaterial
|
||||||
|
|
||||||
|
#sphere: 0.05 0.05 0.05 0.03 myWater y
|
||||||
|
#box: 0.01 0.01 0.01 0.09 0.025 0.025 boxMaterial y
|
||||||
|
|
||||||
|
#geometry_objects_write: 0.02 0.02 0.02 0.06 0.06 0.06 partial_volume
|
||||||
|
#geometry_objects_write: 0 0 0 0.1 0.1 0.1 full_volume
|
@@ -1,5 +1,6 @@
|
|||||||
from reframe_tests.tests.base_tests import GprMaxBaseTest
|
from reframe_tests.tests.base_tests import GprMaxBaseTest
|
||||||
from reframe_tests.tests.mixins import (
|
from reframe_tests.tests.mixins import (
|
||||||
|
GeometryObjectMixin,
|
||||||
GeometryOnlyMixin,
|
GeometryOnlyMixin,
|
||||||
GeometryViewMixin,
|
GeometryViewMixin,
|
||||||
ReceiverMixin,
|
ReceiverMixin,
|
||||||
@@ -17,3 +18,7 @@ class GprMaxSnapshotTest(SnapshotMixin, GprMaxBaseTest):
|
|||||||
|
|
||||||
class GprMaxGeometryViewTest(GeometryViewMixin, GeometryOnlyMixin, GprMaxBaseTest):
|
class GprMaxGeometryViewTest(GeometryViewMixin, GeometryOnlyMixin, GprMaxBaseTest):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class GprMaxGeometryObjectTest(GeometryObjectMixin, GeometryOnlyMixin, GprMaxBaseTest):
|
||||||
|
pass
|
||||||
|
@@ -0,0 +1,20 @@
|
|||||||
|
import reframe as rfm
|
||||||
|
from reframe.core.builtins import parameter
|
||||||
|
|
||||||
|
from reframe_tests.tests.mixins import MpiMixin
|
||||||
|
from reframe_tests.tests.standard_tests import GprMaxGeometryObjectTest
|
||||||
|
|
||||||
|
|
||||||
|
@rfm.simple_test
|
||||||
|
class TestGeometryObject(GprMaxGeometryObjectTest):
|
||||||
|
tags = {"test", "serial", "geometry only", "geometry object"}
|
||||||
|
sourcesdir = "src/geometry_object_tests"
|
||||||
|
model = parameter(["geometry_object_write"])
|
||||||
|
geometry_objects = ["partial_volume", "full_volume"]
|
||||||
|
|
||||||
|
|
||||||
|
@rfm.simple_test
|
||||||
|
class TestGeometryObjectMPI(MpiMixin, TestGeometryObject):
|
||||||
|
tags = {"test", "mpi", "geometry only", "geometry object"}
|
||||||
|
mpi_layout = parameter([[2, 2, 2], [4, 4, 1]])
|
||||||
|
test_dependency = TestGeometryObject
|
在新工单中引用
屏蔽一个用户