47 std::vector<std::string> required_keys = {
"anchor_stiffness",
48 "anchor_cross_sectional_area"};
49 std::vector<std::string> optional_keys = {
50 "maximum_anchor_stress",
"initial_anchor_stress",
51 "residual_anchor_stress",
"free_fraction"};
52 if (number_of_anchors == 0)
54 OGS_FATAL(
"No anchors found in the json.");
56 for (
const auto& key : required_keys)
58 if (!data.contains(key))
60 OGS_FATAL(
"JSON file does not contain required key '{:s}'", key);
62 if (number_of_anchors != data[key].size())
65 "Number of anchor start points does not match the number of {} "
69 for (
size_t i = 0; i < number_of_anchors; ++i)
71 if (!data[key][i].is_number())
73 OGS_FATAL(
"Non-numeric element in JSON array for key {}!", key);
77 for (
const auto& key : optional_keys)
79 if (data.contains(key))
81 if (number_of_anchors != data[key].size())
84 "Number of anchor start points does not match the number "
89 for (
size_t i = 0; i < number_of_anchors; ++i)
91 if (!data[key][i].is_number())
93 OGS_FATAL(
"Non-numeric element in JSON array for key {}!",
96 if (key ==
"free_fraction")
98 double const free_fraction_number =
99 data[
"free_fraction"][i].get<
double>();
100 if (free_fraction_number < 0.0 ||
101 free_fraction_number > 1.0)
104 "Free fraction must be in the range [0, 1] but is "
105 "{} for anchor #{}.",
106 free_fraction_number, i);
117std::tuple<AU::ComputeNaturalCoordsResult, Eigen::VectorXd>
readJSON(
118 TCLAP::ValueArg<std::string>
const& input_filename)
120 using json = nlohmann::json;
121 std::ifstream f(input_filename.getValue());
124 OGS_FATAL(
"Could not open file '{:s}'", input_filename.getValue());
126 json
const data = json::parse(f);
128 auto const number_of_anchors = data[
"anchor_start_points"].size();
129 if (number_of_anchors != data[
"anchor_end_points"].size())
132 "Number of anchor start points does not match the number of "
133 "anchor end points.");
137 Eigen::MatrixX3d realcoords(2 * number_of_anchors, 3);
139 auto get_coordinates = [&data](
const char* key, std::size_t
const i)
141 const auto& v = data[key][i].get_ref<json::array_t
const&>();
145 "Expected a vector of length three for {:s} {}. Got vector of "
149 return Eigen::RowVector3d{v[0].get<
double>(), v[1].get<double>(),
153 for (std::size_t i = 0; i < number_of_anchors; i++)
155 realcoords.row(2 * i).noalias() =
156 get_coordinates(
"anchor_start_points", i);
157 realcoords.row(2 * i + 1).noalias() =
158 get_coordinates(
"anchor_end_points", i);
160 Eigen::VectorXd initial_anchor_stress(number_of_anchors);
161 Eigen::VectorXd maximum_anchor_stress(number_of_anchors);
162 Eigen::VectorXd residual_anchor_stress(number_of_anchors);
163 Eigen::VectorXd anchor_cross_sectional_area(number_of_anchors);
164 Eigen::VectorXd anchor_stiffness(number_of_anchors);
165 Eigen::VectorXd free_fraction(number_of_anchors);
166 if (!data.contains(
"initial_anchor_stress"))
168 initial_anchor_stress.setZero();
172 for (
size_t i = 0; i < number_of_anchors; ++i)
174 initial_anchor_stress(i) =
175 data[
"initial_anchor_stress"][i].get<
double>();
178 if (!data.contains(
"maximum_anchor_stress"))
180 maximum_anchor_stress = Eigen::VectorXd::Constant(
181 number_of_anchors, std::numeric_limits<double>::max());
185 for (
size_t i = 0; i < number_of_anchors; ++i)
187 maximum_anchor_stress(i) =
188 data[
"maximum_anchor_stress"][i].get<
double>();
191 if (!data.contains(
"residual_anchor_stress"))
193 residual_anchor_stress = Eigen::VectorXd::Constant(
194 number_of_anchors, std::numeric_limits<double>::max());
198 for (
size_t i = 0; i < number_of_anchors; ++i)
200 residual_anchor_stress(i) =
201 data[
"residual_anchor_stress"][i].get<
double>();
204 if (!data.contains(
"free_fraction"))
206 free_fraction = Eigen::VectorXd::Constant(number_of_anchors, 1.0);
210 for (
size_t i = 0; i < number_of_anchors; ++i)
212 free_fraction(i) = data[
"free_fraction"][i].get<
double>();
216 for (
size_t i = 0; i < number_of_anchors; ++i)
218 anchor_cross_sectional_area(i) =
219 data[
"anchor_cross_sectional_area"][i].get<
double>();
220 anchor_stiffness(i) = data[
"anchor_stiffness"][i].get<
double>();
230 return {json_data, free_fraction};
238 "Computes natual coordinates from given real coordinates\n\n"
240 "OpenGeoSys-6 software, version " +
243 "Copyright (c) 2012-2026, OpenGeoSys Community "
244 "(http://www.opengeosys.org)",
248 cmd.add(log_level_arg);
250 TCLAP::ValueArg<std::string> input_filename_arg(
251 "i",
"input",
"Input (.vtu) bulk mesh file",
true,
"",
"INPUT_FILE",
254 TCLAP::ValueArg<std::string> output_filename_arg(
255 "o",
"output",
"Output (.vtu). Anchor mesh file",
true,
"",
258 TCLAP::ValueArg<std::string> json_filename_arg(
260 "Input (.json) JSON file containing anchor start and end points",
true,
261 "",
"INPUT_FILE", cmd);
263 TCLAP::ValueArg<double> tolerance_arg(
264 "",
"tolerance",
"Tolerance/Search length",
false,
265 std::numeric_limits<double>::epsilon(),
"float", cmd);
267 TCLAP::ValueArg<unsigned> max_iter_arg(
269 "maximum number of iterations of the internal root-finding "
270 "algorithm, (min = 0)",
271 false, 5,
"MAX_ITER", cmd);
273 cmd.parse(argc, argv);
278 auto const& [json_data, free_fraction] =
readJSON(json_filename_arg);
279 auto const bulk_mesh =
readGrid(input_filename_arg.getValue());
281 auto split_anchor_coords =
283 tolerance_arg.getValue());
292 bulk_mesh, anchor_data, tolerance_arg.getValue(),
293 max_iter_arg.getValue());
296 writeGrid(output_mesh, output_filename_arg.getValue());
300 OGS_FATAL(
"Failed to compute natural coordinates.");
std::vector< std::vector< IntersectionResult > > getOrderedAnchorCoords(vtkUnstructuredGrid *grid, Eigen::MatrixX3d const &realcoords, Eigen::VectorXd const &free_fraction, double const tol)
Finds intersection points of a line segment with the cells of a vtkUnstructuredGrid....
AU::ComputeNaturalCoordsResult setPhysicalPropertiesForIntersectionPoints(std::vector< std::vector< IntersectionResult > > const &anchor_coords, AU::ComputeNaturalCoordsResult const &original_anchor_data)
fills the physical properties of the intersection points based on the original anchor data.