Skip to content

Commit

Permalink
Add application tetwild_msh_converter.
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-zint committed Jan 10, 2025
1 parent d81dd26 commit 55263cc
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 4 deletions.
1 change: 1 addition & 0 deletions applications/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ add_application(marching ON)
add_application(procedural ON)
add_application(multimesh OFF)
add_application(isotropic_remeshing OFF)
add_application(tetwild_msh_converter ON)
add_application(tetwild_simplification ON)
add_application(triwild ON)
add_application(tetwild ON)
Expand Down
7 changes: 7 additions & 0 deletions applications/tetwild_msh_converter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
wmtk_add_application(tetwild_msh_converter_app
tetwild_msh_converter_main.cpp
tetwild_msh_converter_spec.hpp
)

target_link_libraries(tetwild_msh_converter_app PRIVATE
wmtk::input)
31 changes: 31 additions & 0 deletions applications/tetwild_msh_converter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Tetwild MSH Converter

This application converts an MSH file produced by [Tetwild](https://github.com/daniel-zint/TetWild) into a VTU file.
If the MSH has an `in_out` attribute, it will convert it to a `winding_number` attribute.

#### Parameters

As this application is extremely simple, it does not require the standard JSON input. Instead, it just requires an input file name and optionally an output file name.

```
-i Input MSH file
-j Output VTU file (optional, by default the same as the input)
```

#### Examples of usage

```
./tetwild_msh_converter -i sphere.msh
```

This will create a `sphere_tets.vtu`.

```
./tetwild_msh_converter -i sphere.msh -o sphere_converted.vtu
```

This will create a `sphere_converted_tets.vtu`.

#### JSON parameter file

While a JSON parameter file is not necessary, it is still possible to be used with that, too. For details, look at `tetwild_msh_converter_spec.json`.
130 changes: 130 additions & 0 deletions applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#include <jse/jse.h>
#include <CLI/CLI.hpp>
#include <filesystem>
#include <nlohmann/json.hpp>

#include <wmtk/io/ParaviewWriter.hpp>
#include <wmtk/utils/Logger.hpp>

#include <wmtk/components/input/input.hpp>
#include <wmtk/components/utils/json_utils.hpp>
#include <wmtk/components/utils/resolve_path.hpp>

#include "tetwild_msh_converter_spec.hpp"

using namespace wmtk;
using namespace wmtk::components;
namespace fs = std::filesystem;

int main(int argc, char* argv[])

Check warning on line 19 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L19

Added line #L19 was not covered by tests
{
opt_logger().set_level(spdlog::level::off);
CLI::App app{argv[0]};

Check warning on line 22 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L21-L22

Added lines #L21 - L22 were not covered by tests

app.ignore_case();

Check warning on line 24 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L24

Added line #L24 was not covered by tests

fs::path json_input_file;
fs::path input_file = "";
fs::path output_file;

Check warning on line 28 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L26-L28

Added lines #L26 - L28 were not covered by tests

auto cli_group = app.add_option_group("subgroup");

Check warning on line 30 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L30

Added line #L30 was not covered by tests

CLI::Option* cli_json_spec_file_option =

Check warning on line 32 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L32

Added line #L32 was not covered by tests
cli_group->add_option("-j, --json", json_input_file, "json specification file")
->check(CLI::ExistingFile);
CLI::Option* cli_input_file_option =

Check warning on line 35 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L34-L35

Added lines #L34 - L35 were not covered by tests
cli_group->add_option("-i, --input", input_file, "input MSH file")
->check(CLI::ExistingFile);

Check warning on line 37 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L37

Added line #L37 was not covered by tests

cli_group->require_option(1); // --j xor --i

Check warning on line 39 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L39

Added line #L39 was not covered by tests

CLI::Option* cli_output_file_option =

Check warning on line 41 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L41

Added line #L41 was not covered by tests
app.add_option("-o, --output", output_file, "output VTU file")
->needs(cli_input_file_option);

Check warning on line 43 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L43

Added line #L43 was not covered by tests

CLI11_PARSE(app, argc, argv);

Check warning on line 45 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L45

Added line #L45 was not covered by tests

// json spec file
nlohmann::json j;

Check warning on line 48 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L48

Added line #L48 was not covered by tests
if (!json_input_file.empty()) {
using wmtk::components::utils::resolve_paths;

Check warning on line 50 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L50

Added line #L50 was not covered by tests

std::ifstream ifs(json_input_file);
j = nlohmann::json::parse(ifs);

Check warning on line 53 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L52-L53

Added lines #L52 - L53 were not covered by tests

jse::JSE spec_engine;
bool r = spec_engine.verify_json(j, tetwild_msh_converter_spec);

Check warning on line 56 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L55-L56

Added lines #L55 - L56 were not covered by tests
if (!r) {
wmtk::logger().error("{}", spec_engine.log2str());
return 1;

Check warning on line 59 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L58-L59

Added lines #L58 - L59 were not covered by tests
} else {
j = spec_engine.inject_defaults(j, tetwild_msh_converter_spec);

Check warning on line 61 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L61

Added line #L61 was not covered by tests
}

input_file = resolve_paths(json_input_file, {j["input_path"], j["input"]});
output_file = std::string(j["output"]);

Check warning on line 65 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L64-L65

Added lines #L64 - L65 were not covered by tests
}

if (output_file.empty()) {
output_file = input_file;

Check warning on line 69 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L69

Added line #L69 was not covered by tests
}
output_file.replace_extension();

Check warning on line 71 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L71

Added line #L71 was not covered by tests


std::shared_ptr<Mesh> mesh;
try {
mesh = wmtk::components::input::input(input_file, false, {"in_out"});
} catch (const std::exception&) {

Check warning on line 77 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L74-L77

Added lines #L74 - L77 were not covered by tests
// try again but without in_out attribute
mesh = wmtk::components::input::input(input_file);

Check warning on line 79 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L79

Added line #L79 was not covered by tests
}
Mesh& m = *mesh;
wmtk::logger().info("mesh has {} vertices", m.get_all(PrimitiveType::Vertex).size());

Check warning on line 82 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L81-L82

Added lines #L81 - L82 were not covered by tests

// add winding_number attribute
if (m.has_attribute<double>("in_out", m.top_simplex_type())) {
auto wn_handle = m.register_attribute<double>("winding_number", m.top_simplex_type(), 1);
auto wn_acc = m.create_accessor<double>(wn_handle);

Check warning on line 87 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L86-L87

Added lines #L86 - L87 were not covered by tests

auto in_out_handle = m.get_attribute_handle<double>("in_out", PrimitiveType::Tetrahedron);
auto in_out_acc = m.create_accessor<double>(in_out_handle);

Check warning on line 90 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L89-L90

Added lines #L89 - L90 were not covered by tests

for (const Tuple& t : m.get_all(m.top_simplex_type())) {
wn_acc.scalar_attribute(t) = in_out_acc.scalar_attribute(t);

Check warning on line 93 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L93

Added line #L93 was not covered by tests
}

auto pos_handle = m.get_attribute_handle<double>("vertices", PrimitiveType::Vertex);
m.clear_attributes({pos_handle, wn_handle});

Check warning on line 97 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L96-L97

Added lines #L96 - L97 were not covered by tests
}

// output
{
logger().info("Write mesh '{}'", output_file.string());

Check warning on line 102 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L101-L102

Added lines #L101 - L102 were not covered by tests

const bool edge = m.top_simplex_type() == PrimitiveType::Edge;
const bool tri = m.top_simplex_type() == PrimitiveType::Triangle;
const bool tet = m.top_simplex_type() == PrimitiveType::Tetrahedron;

Check warning on line 106 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L104-L106

Added lines #L104 - L106 were not covered by tests

wmtk::io::ParaviewWriter writer(output_file, "vertices", m, false, edge, tri, tet);
m.serialize(writer);

Check warning on line 109 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L108-L109

Added lines #L108 - L109 were not covered by tests
}

if (!json_input_file.empty()) {
const std::string report = j["report"];

Check warning on line 113 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L113

Added line #L113 was not covered by tests
if (!report.empty()) {
nlohmann::json out_json;
out_json["stats"]["vertices"] = m.get_all(PrimitiveType::Vertex).size();
out_json["stats"]["edges"] = m.get_all(PrimitiveType::Edge).size();
out_json["stats"]["triangles"] = m.get_all(PrimitiveType::Triangle).size();
out_json["stats"]["tets"] = m.get_all(PrimitiveType::Tetrahedron).size();

Check warning on line 119 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L115-L119

Added lines #L115 - L119 were not covered by tests

out_json["input"] = j;

Check warning on line 121 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L121

Added line #L121 was not covered by tests

std::ofstream ofs(report);
ofs << std::setw(4) << out_json;

Check warning on line 124 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L123-L124

Added lines #L123 - L124 were not covered by tests
}
}


return 0;

Check warning on line 129 in applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp

View check run for this annotation

Codecov / codecov/patch

applications/tetwild_msh_converter/tetwild_msh_converter_main.cpp#L129

Added line #L129 was not covered by tests
}
38 changes: 38 additions & 0 deletions applications/tetwild_msh_converter/tetwild_msh_converter_spec.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once
#include <nlohmann/json.hpp>
namespace {

nlohmann::json tetwild_msh_converter_spec = R"(
[
{
"pointer": "/",
"type": "object",
"required": ["input"],
"optional": ["output", "report", "input_path"]
},
{
"pointer": "/input",
"type": "string",
"doc": "Input MSH file"
},
{
"pointer": "/output",
"type": "string",
"default": "",
"doc": "Output VTU file. By default, the same as the input file name but with .vtu extension."
},
{
"pointer": "/report",
"type": "string",
"default": ""
},
{
"pointer": "/input_path",
"type": "string",
"default": "",
"doc": " The folder in which the input file is located. By default, this path will be set to the folder of the JSON spec file."
}
]
)"_json;

}
30 changes: 30 additions & 0 deletions applications/tetwild_msh_converter/tetwild_msh_converter_spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[
{
"pointer": "/",
"type": "object",
"required": ["input"],
"optional": ["output", "report", "input_path"]
},
{
"pointer": "/input",
"type": "string",
"doc": "Input MSH file"
},
{
"pointer": "/output",
"type": "string",
"default": "",
"doc": "Output VTU file. By default, the same as the input file name but with .vtu extension."
},
{
"pointer": "/report",
"type": "string",
"default": ""
},
{
"pointer": "/input_path",
"type": "string",
"default": "",
"doc": " The folder in which the input file is located. By default, this path will be set to the folder of the JSON spec file."
}
]
7 changes: 3 additions & 4 deletions src/wmtk/io/MshReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,8 @@ void MshReader::extract_element_attribute(
}
}

auto MshReader::generate(
const std::optional<std::vector<std::vector<std::string>>>& extra_attributes_opt)
-> std::shared_ptr<Mesh>
auto MshReader::generate(const std::optional<std::vector<std::vector<std::string>>>&
extra_attributes_opt) -> std::shared_ptr<Mesh>
{
std::shared_ptr<Mesh> res;
switch (get_mesh_dimension()) {
Expand Down Expand Up @@ -384,7 +383,7 @@ void MshReader::validate<3>()
// swap col 0 and 1 of S
S.col(0).swap(S.col(1));
wmtk::logger().info(
"Input tet orientation is inverted, swapping col 0 and 1 of TV matirx.");
"Input tet orientation is inverted, swapping col 0 and 1 of TV matrix.");
}
}

Expand Down

0 comments on commit 55263cc

Please sign in to comment.