Skip to content

Commit

Permalink
Write converted object and CSG metadata for debugging (celeritas-proj…
Browse files Browse the repository at this point in the history
…ect#1259)

* Add serialization code for unit proto
* Rename input builder to proto builder
* Add output of proto-universes
* Add callback for writing proto intermediate data
* Add CSG tree debug output
* Discard when proto isn't available
* Write CSG output for unit proto test
* Save unit label and remapped universe IDs to CSG output
  • Loading branch information
sethrj committed Jun 8, 2024
1 parent 98d6ce3 commit 21a801a
Show file tree
Hide file tree
Showing 25 changed files with 723 additions and 124 deletions.
54 changes: 36 additions & 18 deletions scripts/user/orange-csg-to-dot.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""
Convert an ORANGE CSG JSON representation to a GraphViz input.
"""
from itertools import count, repeat
import json

class DoxygenGenerator:
Expand All @@ -22,35 +23,50 @@ def __enter__(self):
def __exit__(self, type, value, traceback):
self.write("}\n")

def write_literal(self, i, value):
def write_node(self, i, value):
self.write(f"{i:02d} [label=\"{value}\"];\n")

def write_node(self, i, value, edges):
self.write_literal(i, f"{i}: {value}")
for e in edges:
self.write(f"{i:02d} -> {e:02d};\n")
def write_edge(self, i, e):
self.write(f"{i:02d} -> {e:02d};\n")

def process(gen, tree):
for (i, node) in enumerate(tree):
def process(gen, tree, labels):
for (i, node, labs) in zip(count(), tree, labels or repeat(None)):
if isinstance(node, str):
# True (or false??)
gen.write_literal(i, node)
gen.write_node(i, node)
continue
label = "\\n".join(labs) if labs else ""

(nodetype, value) = node
if nodetype == "S":
# Surface
gen.write_literal(i, f"S{value}")
elif nodetype in ("~", "="):
# Negated
gen.write_node(i, nodetype, [value])
else:
# Surface (literal)
gen.write_node(i, label or f"S{value}")
continue

if label:
label += "\\n"
label += nodetype
gen.write_node(i, label)

if isinstance(value, list):
# Joined
gen.write_node(i, nodetype, value)
for v in value:
gen.write_edge(i, v)
else:
# Aliased/negated
gen.write_edge(i, value)

def run(infile, outfile):
def run(infile, outfile, universe):
tree = json.load(infile)
metadata = None
if universe is not None:
# Load from a 'proto' debug file
csg_unit = tree[universe]
tree = csg_unit["tree"]
metadata = csg_unit["metadata"]

with DoxygenGenerator(outfile) as gen:
process(gen, tree)
process(gen, tree, metadata)

def main():
import argparse
Expand All @@ -60,6 +76,8 @@ def main():
parser.add_argument(
"input",
help="Input filename (- for stdin)")
parser.add_argument('-u', '--universe', type=int, default=None,
help="Universe ID if a 'proto' debug file")
parser.add_argument(
"-o", "--output",
default=None,
Expand All @@ -76,7 +94,7 @@ def main():
else:
outfile = open(args.output, 'w')

run(infile, outfile)
run(infile, outfile, args.universe)

if __name__ == "__main__":
main()
10 changes: 10 additions & 0 deletions src/corecel/io/JsonPimpl.hh
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,15 @@ void to_json_pimpl(JsonPimpl* jp, T const& self)
#endif
}

#if CELERITAS_USE_JSON
template<class T>
nlohmann::json json_pimpl_output(T const& self)
{
JsonPimpl jp;
self.output(&jp);
return std::move(jp.obj);
}
#endif

//---------------------------------------------------------------------------//
} // namespace celeritas
13 changes: 13 additions & 0 deletions src/corecel/io/StreamableVariant.hh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#pragma once

#include <ostream>
#include <sstream>
#include <variant>

#include "corecel/Assert.hh"
Expand Down Expand Up @@ -65,5 +66,17 @@ std::ostream& operator<<(std::ostream& os, StreamableVariant<T> const& svar)
return os;
}

//---------------------------------------------------------------------------//
/*!
* Save a variant object's value to a string.
*/
template<class T>
std::string to_string(StreamableVariant<T> const& svar)
{
std::ostringstream os;
os << svar;
return os.str();
}

//---------------------------------------------------------------------------//
} // namespace celeritas
3 changes: 2 additions & 1 deletion src/orange/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ list(APPEND SOURCES
orangeinp/CsgTree.cc
orangeinp/CsgTypes.cc
orangeinp/CsgTreeUtils.cc
orangeinp/InputBuilder.cc
orangeinp/IntersectRegion.cc
orangeinp/IntersectSurfaceBuilder.cc
orangeinp/PolySolid.cc
Expand All @@ -40,12 +41,12 @@ list(APPEND SOURCES
orangeinp/detail/BoundingZone.cc
orangeinp/detail/BuildIntersectRegion.cc
orangeinp/detail/CsgUnitBuilder.cc
orangeinp/detail/InputBuilder.cc
orangeinp/detail/InternalSurfaceFlagger.cc
orangeinp/detail/IntersectSurfaceState.cc
orangeinp/detail/LocalSurfaceInserter.cc
orangeinp/detail/NodeSimplifier.cc
orangeinp/detail/PostfixLogicBuilder.cc
orangeinp/detail/ProtoBuilder.cc
orangeinp/detail/ProtoMap.cc
orangeinp/detail/SenseEvaluator.cc
orangeinp/detail/TransformInserter.cc
Expand Down
8 changes: 8 additions & 0 deletions src/orange/OrangeParams.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include "corecel/io/Logger.hh"
#include "corecel/io/ScopedTimeLog.hh"
#include "corecel/io/StringUtils.hh"
#include "corecel/sys/ScopedMem.hh"
#include "corecel/sys/ScopedProfiling.hh"
#include "geocel/BoundingBox.hh"
#include "geocel/GeantGeoUtils.hh"

Expand Down Expand Up @@ -144,6 +146,12 @@ OrangeParams::OrangeParams(OrangeInput&& input)
{
CELER_VALIDATE(input, << "input geometry is incomplete");

ScopedProfiling profile_this{"finalize-orange-runtime"};
ScopedMem record_mem("orange.finalize_runtime");
CELER_LOG(debug) << "Merging runtime data"
<< (celeritas::device() ? " and copying to GPU" : "");
ScopedTimeLog scoped_time;

// Save global bounding box
bbox_ = [&input] {
auto& global = input.universes[orange_global_universe.unchecked_get()];
Expand Down
2 changes: 1 addition & 1 deletion src/orange/OrangeParams.hh
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class OrangeParams final : public GeoParamsSurfaceInterface,
// Construct from a JSON or GDML file (if JSON or Geant4 are enabled)
explicit OrangeParams(std::string const& filename);

// Construct in-memory from Geant4 (not implemented)
// Construct in-memory from Geant4
explicit OrangeParams(G4VPhysicalVolume const*);

// ADVANCED usage: construct from explicit host data
Expand Down
14 changes: 10 additions & 4 deletions src/orange/g4org/Converter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "corecel/io/Logger.hh"
#include "geocel/detail/LengthUnits.hh"
#include "orange/orangeinp/InputBuilder.hh"

#include "PhysicalVolumeConverter.hh"
#include "ProtoConstructor.hh"
Expand Down Expand Up @@ -47,7 +48,7 @@ auto Converter::operator()(arg_type g4world) -> result_type
{
CELER_EXPECT(g4world);

CELER_LOG(debug) << "Converting Geant4 geometry elements";
using orangeinp::InputBuilder;

// Convert solids, logical volumes, physical volumes
PhysicalVolumeConverter::Options options;
Expand All @@ -57,14 +58,19 @@ auto Converter::operator()(arg_type g4world) -> result_type
CELER_VALIDATE(std::holds_alternative<NoTransformation>(world.transform),
<< "world volume should not have a transformation");

CELER_LOG(debug) << "Building protos";
// Convert logical volumes into protos
auto global_proto = ProtoConstructor{opts_.verbose}(*world.lv);

CELER_LOG(debug) << "Building universes";
// Build universes from protos
result_type result;
result.input = build_input(opts_.tol, *global_proto);
InputBuilder build_input([&opts = opts_] {
InputBuilder::Options ibo;
ibo.tol = opts.tol;
ibo.proto_output_file = opts.proto_output_file;
ibo.debug_output_file = opts.debug_output_file;
return ibo;
}());
result.input = build_input(*global_proto);
return result;
}

Expand Down
11 changes: 11 additions & 0 deletions src/orange/g4org/Converter.hh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//---------------------------------------------------------------------------//
#pragma once

#include <functional>
#include <memory>
#include <unordered_map>

Expand All @@ -23,6 +24,12 @@ class G4VPhysicalVolume;

namespace celeritas
{
struct OrangeInput;
namespace orangeinp
{
class ProtoInterface;
}

namespace g4org
{
//---------------------------------------------------------------------------//
Expand Down Expand Up @@ -55,6 +62,10 @@ class Converter
bool verbose{false};
//! Manually specify a tracking/construction tolerance
Tolerance<> tol;
//! Write interpreted geometry to a JSON file
std::string proto_output_file;
//! Write intermediate debug ouput (CSG construction) to a JSON file
std::string debug_output_file;
};

struct result_type
Expand Down
4 changes: 3 additions & 1 deletion src/orange/g4org/PhysicalVolumeConverter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ auto PhysicalVolumeConverter::operator()(arg_type g4world) -> result_type
CELER_EXPECT(g4world.GetTranslation() == G4ThreeVector(0, 0, 0));

ScopedProfiling profile_this{"import-geant-geo"};
ScopedMem record_mem("PhysicalVolumeConverter.convert");
ScopedMem record_mem("orange.convert-geant");

CELER_LOG(status) << "Converting Geant4 geometry elements to ORANGE input";
ScopedTimeLog scoped_time;

// Construct world volume
Expand Down
Loading

0 comments on commit 21a801a

Please sign in to comment.