Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions doc/source/testing/testLauncher.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -191,6 +191,12 @@ In addition there is some extra keys which are dedicated to the json interpretat
* - ``multirun``
- ``{}``
- See the multi-run section below.
* - ``callPyFunctionBefore``
-
- Call a python function before executing the test (see dedicated section at the end of this file).
* - ``callPyFunctionAfter``
-
- Call a python function after executing the test (see dedicated section at the end of this file).

Looping over parameters
-----------------------
Expand DownExpand Up@@ -374,6 +380,33 @@ They are described like :
},
}

Calling a Python function
-------------------------

In some cases (example in ``test/utils/lookupTable``) you might need to call a custom
python function before running the test to prepare the data or after the test to perform
some extra check.

You can simply implement the functions you want to call in the python file in the test
directory (ideally named ``testmelib.py``) :

.. code-block:: python

def callMeAtStart():
print("This is called at test start !")

def callMeAtEnd():
print("This is called at test end !")

And add the keys in ``testme.json``:

.. code-block:: json

"default": {
"callPyFunctionBefore": "testmelib.py:callMeAtStart",
"callPyFunctionAfter": "testmelib.py:callMeAtEnd"
}

Using the idfxTest options
--------------------------

Expand Down
78 changes: 72 additions & 6 deletions pytools/idfx_test_run.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,6 +7,7 @@

import copy
import glob
import importlib
import json
import os
import sys
Expand DownExpand Up@@ -135,6 +136,58 @@ def genTests(self) -> list:
# ok
return result

def buildPyHooks(self, config: dict) -> dict:
# init
result = {}
key: str

# extract and build dict
for key, value in config.items():
if key.startswith("callPyFunction"):
when = key.replace("callPyFunction", "")
result[when] = value

# ok
return result

# https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
def importFromPath(self, moduleName: str, filePath: str):
spec = importlib.util.spec_from_file_location(moduleName, filePath)
module = importlib.util.module_from_spec(spec)
# sys.modules[moduleName] = module
spec.loader.exec_module(module)
return module

def callPyHook(self, dir: str, hooks: dict, name: str) -> None:
# nothing to do
if name not in hooks:
return

# split file:funcName
params = hooks[name].split(":", 1)
filePath = params[0]
funcName = params[1]

# complete
fileFullPath = os.path.join(dir, filePath)

# log
print("************** CALLING PY FUNCTION ****************")
print(f"Hook: {name}")
print(f"HookValue: {hooks[name]}")
print(f"Import {fileFullPath}")
print(f"Call: {funcName}")
print("***************************************************")

# import the module
module = self.importFromPath("idefix_test_py_hooks", fileFullPath)

# get function
function = getattr(module, funcName)

# call it
function()

def run(self, config: dict) -> None:
# clone before modify to not modity for caller
config = copy.deepcopy(config)
Expand All@@ -155,6 +208,7 @@ def run(self, config: dict) -> None:
nonRegressionTestIni = config.get("nonRegressionTestIni", None)
check_file_produced = config.get("check_file_produced", [])
problemDir = os.path.dirname(testfile)
pyHooks = self.buildPyHooks(config)

# cleanup some keyword not handled at the
# level of idx_test so we don't perturbate it
Expand All@@ -169,6 +223,12 @@ def run(self, config: dict) -> None:
del config["nonRegressionTest"]
if "nonRegressionTestIni" in config:
del config["nonRegressionTestIni"]
for hook in pyHooks:
del config[f"callPyFunction{hook}"]

# call hook before
with moveInDir(problemDir):
self.callPyHook(problemDir, pyHooks, "Before")

# if switch from test, rebuild the runner (a runner make for one dir)
if self.currentTestFile != testfile:
Expand All@@ -189,11 +249,16 @@ def run(self, config: dict) -> None:
)

# check produced
for file in check_file_produced:
if not os.path.exists(file) and not self.currentTestRunner.fake:
raise Exception(
f"Don't find expected file to be produced by the run : {file} !"
)
with moveInDir(problemDir):
for file in check_file_produced:
if not os.path.exists(file) and not self.currentTestRunner.fake:
raise Exception(
f"Don't find expected file to be produced by the run : {file} !"
)

# call hook after
with moveInDir(problemDir):
self.callPyHook(problemDir, pyHooks, "After")

def _runNonRegression(
self,
Expand DownExpand Up@@ -365,7 +430,7 @@ def main(self, all: bool = False):
os.environ["IDEFIX_TEST_FILTER_SUBDIR"] = idefixTest.filterSubdir

if idefixTest.all:
pytest.main(
status = pytest.main(
[
"-v",
"--no-header",
Expand All@@ -375,6 +440,7 @@ def main(self, all: bool = False):
+ idefixTest.remainingArgs
+ [self.parentScritFile]
)
sys.exit(status)
else:
raise NotImplementedError("Not yet supported !")
# elif self.check:
Expand Down
4 changes: 2 additions & 2 deletions src/fluid/RiemannSolver/MHDsolvers/storeFlux.hpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -55,8 +55,8 @@ KOKKOS_FORCEINLINE_FUNCTION void K_StoreHLL( const int i, const int j, const int
const IdefixArray3D<real> &dL,
const IdefixArray3D<real> &dR) {
EXPAND( ,
constexpr int Xt = (DIR == IDIR ? MX2 : MX1); ,
constexpr int Xb = (DIR == KDIR ? MX2 : MX3); )
[[maybe_unused]] constexpr int Xt = (DIR == IDIR ? MX2 : MX1); ,
[[maybe_unused]] constexpr int Xb = (DIR == KDIR ? MX2 : MX3); )

real ar = std::fmax(ZERO_F, sr);
real al = std::fmin(ZERO_F, sl);
Expand Down
11 changes: 6 additions & 5 deletions src/fluid/boundary/axis.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -392,7 +392,8 @@ void Axis::ExchangeMPI(int side) {
idfx::pushRegion("Axis::ExchangeMPI");
#ifdef WITH_MPI
// Load the buffers with data
int ibeg,iend,jbeg,jend,kbeg,kend,offset;
[[maybe_unused]] int ibeg,iend,jbeg,jend,kbeg,kend;
int offset;
int ny;
Buffer bufferSend = this->bufferSend;
IdefixArray1D<int> map = this->mapVars;
Expand DownExpand Up@@ -491,12 +492,12 @@ void Axis::ExchangeMPI(int side) {
//unpack Vs face-centered
BoundingBox recvBoxVsIdir = baseBox;
recvBoxVsIdir[IDIR][1] += 1;
bufferRecv.UnpackJDirSymetric(Vs, IDIR, sVs(IDIR), recvBoxVsIdir);
bufferRecv.UnpackJDirSymetric(Vs, IDIR, sVs, recvBoxVsIdir);

//unpack Vs face-centered
BoundingBox recvBoxVsKdir = baseBox;
recvBoxVsKdir[KDIR][1] += 1;
bufferRecv.UnpackJDirSymetric(Vs, KDIR, sVs(KDIR), recvBoxVsKdir);
bufferRecv.UnpackJDirSymetric(Vs, KDIR, sVs, recvBoxVsKdir);
}
} else if(side==right) {
//unpack Vc on right part
Expand All@@ -514,14 +515,14 @@ void Axis::ExchangeMPI(int side) {
recvBoxVsIdir[IDIR][1] += 1;
recvBoxVsIdir[JDIR][0] += offset;
recvBoxVsIdir[JDIR][1] += offset;
bufferRecv.UnpackJDirSymetric(Vs, IDIR, sVs(IDIR), recvBoxVsIdir);
bufferRecv.UnpackJDirSymetric(Vs, IDIR, sVs, recvBoxVsIdir);

//unpack Vs face-centered on right part
BoundingBox recvBoxVsKdir = baseBox;
recvBoxVsKdir[KDIR][1] += 1;
recvBoxVsKdir[JDIR][0] += offset;
recvBoxVsKdir[JDIR][1] += offset;
bufferRecv.UnpackJDirSymetric(Vs, KDIR, sVs(KDIR), recvBoxVsKdir);
bufferRecv.UnpackJDirSymetric(Vs, KDIR, sVs, recvBoxVsKdir);
} // MHD
}

Expand Down
12 changes: 6 additions & 6 deletions src/fluid/constrainedTransport/EMFexchange.hpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,7 +75,7 @@ void ConstrainedTransport<Phys>::ExchangeX1(IdefixArray3D<real> ey, IdefixArray3
sendBoxEy[KDIR][1] += 1;
sendBoxEy[IDIR][0] = iright;
sendBoxEy[IDIR][1] = iright + 1;
BufferRight.Pack(ez, sendBoxEy);
BufferRight.Pack(ey, sendBoxEy);
#endif

// Wait for completion before sending out everything
Expand DownExpand Up@@ -239,11 +239,11 @@ void ConstrainedTransport<Phys>::ExchangeX3(IdefixArray3D<real> ex, IdefixArray3
baseBox[KDIR][1] = data->end[KDIR];

//extend by one the end on jdir && take the ghost on k
BoundingBox sendBoxEz = baseBox;
sendBoxEz[JDIR][1] += 1;
sendBoxEz[KDIR][0] = kright;
sendBoxEz[KDIR][1] = kright + 1;
BufferRight.Pack(ez, sendBoxEz);
BoundingBox sendBoxEx = baseBox;
sendBoxEx[JDIR][1] += 1;
sendBoxEx[KDIR][0] = kright;
sendBoxEx[KDIR][1] = kright + 1;
BufferRight.Pack(ex, sendBoxEx);

//extend by one the end on idir && take the ghost on k
BoundingBox sendBoxEy = baseBox;
Expand Down
3 changes: 2 additions & 1 deletion src/mpi/buffer.hpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -165,7 +165,7 @@ class Buffer {

void UnpackJDirSymetric(IdefixArray4D<real>& out,
const int var,
const int symMultiplier,
IdefixArray1D<int>& SymMap,
BoundingBox box) {
const int ni = box[IDIR][1]-box[IDIR][0];
const int ninj = (box[JDIR][1]-box[JDIR][0])*ni;
Expand All@@ -183,6 +183,7 @@ class Buffer {
KOKKOS_LAMBDA (int k, int j, int i) {
const int jinverted = jend-(j-jbeg)-1;
const int arrIndex = i-ibeg + (j-jbeg)*ni + (k-kbeg)*ninj + offset;
const int symMultiplier = SymMap(var);
out(var,k,jinverted,i) = symMultiplier * arr(arrIndex);
});

Expand Down
3 changes: 2 additions & 1 deletion test/utils/lookupTable/testme.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,7 @@
"ini": "idefix.ini",
"nonRegressionTest": false,
"standardTest": false,
"tolerance": 0
"tolerance": 0,
"callPyFunctionBefore": "testmelib.py:MakeNumpyFile"
}
}
25 changes: 3 additions & 22 deletions test/utils/lookupTable/testme.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,32 +9,13 @@
import sys

sys.path.append(os.getenv("IDEFIX_DIR"))
import numpy as np

# from scipy.interpolate import RegularGridInterpolator
import pytools.idfx_test as tst


def MakeNumpyFile():
x = np.arange(1, 10, 1.0)
y = np.arange(5, 10, 1.0)
z = np.arange(2, 5, 1.0)

xp, yp, zp = np.meshgrid(x, y, z, indexing="ij")

data = xp + 2 * yp - zp

np.save("x.npy", x)
np.save("y.npy", y)
np.save("z.npy", z)
np.save("data.npy", data)
# show the expected result
# f=RegularGridInterpolator((x, y, z), data)
# print(f([2.7,7.4,3.9]))
import testmelib

import pytools.idfx_test as tst

test = tst.idfxTest(__file__)
MakeNumpyFile()
testmelib.MakeNumpyFile()

test.configure()
test.compile()
Expand Down
19 changes: 19 additions & 0 deletions test/utils/lookupTable/testmelib.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
import numpy as np


def MakeNumpyFile():
x = np.arange(1, 10, 1.0)
y = np.arange(5, 10, 1.0)
z = np.arange(2, 5, 1.0)

xp, yp, zp = np.meshgrid(x, y, z, indexing="ij")

data = xp + 2 * yp - zp

np.save("x.npy", x)
np.save("y.npy", y)
np.save("z.npy", z)
np.save("data.npy", data)
# show the expected result
# f=RegularGridInterpolator((x, y, z), data)
# print(f([2.7,7.4,3.9]))
Loading