Skip to content

Commit

Permalink
moreports
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilipDeegan committed Dec 11, 2023
1 parent 77301be commit a3651a5
Show file tree
Hide file tree
Showing 11 changed files with 249 additions and 16 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ tools/cmake.sh
perf.*
**/*.h5
.vscode

.phare*
REPORT_INFO.zip
18 changes: 17 additions & 1 deletion ISSUES.TXT
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@


# Having Issues

Please run:

> ./tools/report.sh # or "python3 tools/report.py" with the correct PYTHONPATH

This will build a zip archive "REPORT_INFO.zip", which you should either email to us, or
Log an issue on github via https://github.com/PHAREHUB/PHARE/issues/new
Outline the context of your issue, and upload the zip




# Known Issues

1. OMPI symbol resolution with python3.
Affects: OMPI versions < 3
Source: https://github.com/open-mpi/ompi/issues/3705
Expand All @@ -10,4 +25,5 @@
2. Python launching, with C++ MPI init, doesn't work so well with MPI4PY
Source: https://bitbucket.org/mpi4py/mpi4py/issues/154/attempting-to-use-an-mpi-routine-before
Solution:
LD_PRELOAD=/path/to/your/libmpi.so python3 $SCRIPT
LD_PRELOAD=/path/to/your/libmpi.so python3 $SCRIPT

26 changes: 26 additions & 0 deletions pyphare/pyphare/core/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#
#
#
# program help looks like
"""
usage: phare_sim.py [-h] [-d]
options:
-h, --help show this help message and exit
-d, --dry-run Validate but do not run simulations
"""


def parse_cli_args():
import argparse

parser = argparse.ArgumentParser()
parser.add_argument(
"-d",
"--dry-run",
help="Validate but do not run simulations",
action="store_true",
default=False,
)

return parser.parse_args()
5 changes: 5 additions & 0 deletions pyphare/pyphare/core/phare_utilities.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import math
import numpy as np


def debug_print(*args):
if __debug__:
print(*args)

def all_iterables(*args):
"""
return true if all arguments are either lists or tuples
Expand Down
87 changes: 87 additions & 0 deletions pyphare/pyphare/cpp/validate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import os
import sys
import json
import dataclasses
from pathlib import Path

from pyphare.core import phare_utilities
import pyphare.cpp as cpp

DOT_PHARE_DIR = Path(os.getcwd()) / ".phare"


def python_version_from(binary):
return phare_utilities.decode_bytes(
phare_utilities.run_cli_cmd(f"{binary} -V", check=True).stdout.strip()
)


def check_build_config_is_runtime_compatible(strict=True):
try:
build_config: dict = cpp.build_config()

if "PHARE_CONFIG_ERROR" in build_config:
return

build_python_version = build_config["PYTHON_VERSION"]
current_python_version = python_version_from(sys.executable)
if build_python_version != current_python_version:
print("Inconsistency detected!")
print("Python during build and now are not the same!")
print("Build python version :", build_python_version)
print("Current python version:", current_python_version)
raise ValueError("Python version mismatch!")

except RuntimeError as e:
print("Could not interrogate python versions")
print("Please see 'Having Issues' Section of ISSUES.TXT")
print("Actual error (consider adding to issue report):", e)

except ValueError as e:
print(e)
if strict:
raise e


@dataclasses.dataclass
class RuntimeSettings:
python_version: str
python_binary: str


def try_system_binary(cli, log_to):
with open(log_to, "w") as f:
try:
proc = phare_utilities.run_cli_cmd(cli, check=True)
f.write(phare_utilities.decode_bytes(proc.stdout).strip())
except Exception as e:
f.write(f"failed to run cli command {cli}\n")
f.write(f"error {e}")


def try_system_binaries(log_dir):

try_system_binary("free -g", log_dir / "free_dash_g.txt")
try_system_binary("lscpu", log_dir / "lscpu.txt")
try_system_binary("hwloc-info", log_dir / "hwloc_info.txt")


def log_runtime_config():
cpp_lib = cpp.cpp_lib()

settings = RuntimeSettings(
python_binary=sys.executable,
python_version=python_version_from(sys.executable),
)

if cpp_lib.mpi_rank() == 0:
DOT_PHARE_DIR.mkdir(exist_ok=True, parents=True)
cpp_lib.mpi_barrier()

RANK_DIR = DOT_PHARE_DIR / f"rank_{cpp_lib.mpi_rank()}"
RANK_DIR.mkdir(exist_ok=True)

with open(RANK_DIR / "runtime_config.json", "w") as f:
json.dump(dataclasses.asdict(settings), f)

try_system_binaries(RANK_DIR)
15 changes: 8 additions & 7 deletions pyphare/pyphare/pharein/maxwellian_fluid_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ def __init__(self, bx = None,
for population in self.populations:
self.add_population(population, **kwargs[population])

self.validate(global_vars.sim)
if not global_vars.sim.dry_run:
self.validate(global_vars.sim)

global_vars.sim.set_model(self)

Expand Down Expand Up @@ -142,7 +143,7 @@ def to_dict(self):
#------------------------------------------------------------------------------

def validate(self, sim, atol=1e-15):
print(f"validating dim={sim.ndim}")
phare_utilities.debug_print(f"validating dim={sim.ndim}")
if sim.ndim==1:
self.validate1d(sim, atol)
elif sim.ndim==2:
Expand Down Expand Up @@ -213,11 +214,11 @@ def getCoord(L,R, idir):
else:
return (np.zeros_like(L),L), (np.zeros_like(R),R)

print("2d periodic validation")
phare_utilities.debug_print("2d periodic validation")
for idir in np.arange(sim.ndim):
print("validating direction ...", idir)
phare_utilities.debug_print("validating direction ...", idir)
if sim.boundary_types[idir] == "periodic":
print(f"direction {idir} is periodic?")
phare_utilities.debug_print(f"direction {idir} is periodic?")
dual_left = (np.arange(-nbrDualGhosts, nbrDualGhosts)+0.5)*sim.dl[0]
dual_right = dual_left + domain[0]
primal_left = np.arange(-nbrPrimalGhosts, nbrPrimalGhosts)*sim.dl[0]
Expand Down Expand Up @@ -247,12 +248,12 @@ def getCoord(L,R, idir):
fL = f(*coordsL)
fR = f(*coordsR)
check = np.allclose(fL,fR, atol=atol, rtol=0)
print(f"checked {fn} : fL = {fL} and fR = {fR} and check = {check}")
phare_utilities.debug_print(f"checked {fn} : fL = {fL} and fR = {fR} and check = {check}")
if not check:
not_periodic += [(fn,idir)]
is_periodic &=check

if not is_periodic:
print("Warning: Simulation is periodic but some functions are not : ", not_periodic)
phare_utilities.debug_print("Warning: Simulation is periodic but some functions are not : ", not_periodic)
if sim.strict:
raise RuntimeError("Simulation is not periodic")
11 changes: 10 additions & 1 deletion pyphare/pyphare/pharein/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
from . import global_vars
from ..core import box as boxm
from ..core.box import Box
from ..core import parse_cli_args

CLI_ARGS = parse_cli_args()


# ------------------------------------------------------------------------------


def supported_dimensions():
Expand Down Expand Up @@ -498,7 +504,7 @@ def check_clustering(**kwargs):

def checker(func):
def wrapper(simulation_object, **kwargs):
accepted_keywords = ['domain_size', 'cells', 'dl', 'particle_pusher', 'final_time',
accepted_keywords = ['domain_size', 'cells', 'dl', 'particle_pusher', 'final_time', "dry_run",
'time_step', 'time_step_nbr', 'layout', 'interp_order', 'origin',
'boundary_types', 'refined_particle_nbr', 'path', 'nesting_buffer',
'diag_export_format', 'refinement_boxes', 'refinement', 'clustering',
Expand Down Expand Up @@ -566,6 +572,8 @@ def wrapper(simulation_object, **kwargs):

kwargs["hyper_resistivity"] = check_hyper_resistivity(**kwargs)

kwargs["dry_run"] = CLI_ARGS.dry_run

return func(simulation_object, **kwargs)

return wrapper
Expand Down Expand Up @@ -729,6 +737,7 @@ def __init__(self, **kwargs):
validate_restart_options(self)



def final_time(self):
return self.time_step * self.time_step_nbr

Expand Down
17 changes: 16 additions & 1 deletion pyphare/pyphare/simulator/simulator.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

#
#
#

import atexit
import time as timem
Expand All @@ -7,6 +9,7 @@

life_cycles = {}


@atexit.register
def simulator_shutdown():
from ._simulator import obj
Expand Down Expand Up @@ -57,6 +60,11 @@ def setup(self):
from pyphare.cpp import cpp_lib
import pyphare.pharein as ph
startMPI()

import pyphare.cpp.validate as validate_cpp
validate_cpp.log_runtime_config()
validate_cpp.check_build_config_is_runtime_compatible()

if self.log_to_file:
self._log_to_file()
ph.populateDict()
Expand All @@ -79,6 +87,9 @@ def initialize(self):
if self.cpp_hier is None:
self.setup()

if self.simulation.dry_run:
return

self.cpp_sim.initialize()
self._auto_dump() # first dump might be before first advance
return self
Expand All @@ -97,6 +108,8 @@ def _throw(self, e):

def advance(self, dt = None):
self._check_init()
if self.simulation.dry_run:
return
if dt is None:
dt = self.timeStep()

Expand All @@ -119,6 +132,8 @@ def times(self):
def run(self):
from pyphare.cpp import cpp_lib
self._check_init()
if self.simulation.dry_run:
return
perf = []
end_time = self.cpp_sim.endTime()
t = self.cpp_sim.currentTime()
Expand Down
9 changes: 4 additions & 5 deletions tools/config/config.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import os
import json
import subprocess
from pathlib import Path
from dataclasses import dataclass, field
import dataclasses
from pathlib import Path

FILE_DIR = Path(__file__).resolve().parent
BUILD_DIR = FILE_DIR / "build"
Expand All @@ -17,7 +16,7 @@
)


@dataclass
@dataclasses.dataclass
class SystemSettings:
cmake_binary: str
cmake_version: str
Expand Down Expand Up @@ -73,7 +72,7 @@ class SystemSettings:

def exec(cmd, on_error="error message"):
try:
proc = subprocess.run(cmd.split(" "), check=False, capture_output=True)
proc = subprocess.run(cmd.split(" "), check=True, capture_output=True)
return (proc.stdout + proc.stderr).decode().strip()
except:
return on_error
Expand Down Expand Up @@ -187,7 +186,7 @@ def gen_system_file():
python_version=get_python_version(os.environ["PYTHON_EXECUTABLE"]),
uname=exec("uname -a"),
)
with open(DOT_PHARE_DIR / ".build_config.json", "w") as f:
with open(DOT_PHARE_DIR / "build_config.json", "w") as f:
json.dump(dataclasses.asdict(settings), f)

with open(out_file, "w") as f:
Expand Down
Loading

0 comments on commit a3651a5

Please sign in to comment.