53 std::vector<std::string> required_keys = {
"anchor_stiffness",
54 "anchor_cross_sectional_area"};
55 std::vector<std::string> optional_keys = {
56 "maximum_anchor_stress",
"initial_anchor_stress",
57 "residual_anchor_stress",
"free_fraction"};
58 if (number_of_anchors == 0)
60 OGS_FATAL(
"No anchors found in the json.");
62 for (
const auto& key : required_keys)
64 if (!data.contains(key))
66 OGS_FATAL(
"JSON file does not contain required key '{:s}'", key);
68 if (number_of_anchors != data[key].size())
71 "Number of anchor start points does not match the number of {} "
75 for (
size_t i = 0; i < number_of_anchors; ++i)
77 if (!data[key][i].is_number())
79 OGS_FATAL(
"Non-numeric element in JSON array for key {}!", key);
83 for (
const auto& key : optional_keys)
85 if (data.contains(key))
87 if (number_of_anchors != data[key].size())
90 "Number of anchor start points does not match the number "
95 for (
size_t i = 0; i < number_of_anchors; ++i)
97 if (!data[key][i].is_number())
99 OGS_FATAL(
"Non-numeric element in JSON array for key {}!",
102 if (key ==
"free_fraction")
104 double const free_fraction_number =
105 data[
"free_fraction"][i].get<
double>();
106 if (free_fraction_number < 0.0 ||
107 free_fraction_number > 1.0)
110 "Free fraction must be in the range [0, 1] but is "
111 "{} for anchor #{}.",
112 free_fraction_number, i);
123std::tuple<AU::ComputeNaturalCoordsResult, Eigen::VectorXd>
readJSON(
124 TCLAP::ValueArg<std::string>
const& input_filename)
126 using json = nlohmann::json;
127 std::ifstream f(input_filename.getValue());
130 OGS_FATAL(
"Could not open file '{:s}'", input_filename.getValue());
132 json
const data = json::parse(f);
134 auto const number_of_anchors = data[
"anchor_start_points"].size();
135 if (number_of_anchors != data[
"anchor_end_points"].size())
138 "Number of anchor start points does not match the number of "
139 "anchor end points.");
143 Eigen::MatrixX3d realcoords(2 * number_of_anchors, 3);
145 auto get_coordinates = [&data](
const char* key, std::size_t
const i)
147 const auto& v = data[key][i].get_ref<json::array_t
const&>();
151 "Expected a vector of length three for {:s} {}. Got vector of "
155 return Eigen::RowVector3d{v[0].get<
double>(), v[1].get<double>(),
159 for (std::size_t i = 0; i < number_of_anchors; i++)
161 realcoords.row(2 * i).noalias() =
162 get_coordinates(
"anchor_start_points", i);
163 realcoords.row(2 * i + 1).noalias() =
164 get_coordinates(
"anchor_end_points", i);
166 Eigen::VectorXd initial_anchor_stress(number_of_anchors);
167 Eigen::VectorXd maximum_anchor_stress(number_of_anchors);
168 Eigen::VectorXd residual_anchor_stress(number_of_anchors);
169 Eigen::VectorXd anchor_cross_sectional_area(number_of_anchors);
170 Eigen::VectorXd anchor_stiffness(number_of_anchors);
171 Eigen::VectorXd free_fraction(number_of_anchors);
172 if (!data.contains(
"initial_anchor_stress"))
174 initial_anchor_stress.setZero();
178 for (
size_t i = 0; i < number_of_anchors; ++i)
180 initial_anchor_stress(i) =
181 data[
"initial_anchor_stress"][i].get<
double>();
184 if (!data.contains(
"maximum_anchor_stress"))
186 maximum_anchor_stress = Eigen::VectorXd::Constant(
187 number_of_anchors, std::numeric_limits<double>::max());
191 for (
size_t i = 0; i < number_of_anchors; ++i)
193 maximum_anchor_stress(i) =
194 data[
"maximum_anchor_stress"][i].get<
double>();
197 if (!data.contains(
"residual_anchor_stress"))
199 residual_anchor_stress = Eigen::VectorXd::Constant(
200 number_of_anchors, std::numeric_limits<double>::max());
204 for (
size_t i = 0; i < number_of_anchors; ++i)
206 residual_anchor_stress(i) =
207 data[
"residual_anchor_stress"][i].get<
double>();
210 if (!data.contains(
"free_fraction"))
212 free_fraction = Eigen::VectorXd::Constant(number_of_anchors, 1.0);
216 for (
size_t i = 0; i < number_of_anchors; ++i)
218 free_fraction(i) = data[
"free_fraction"][i].get<
double>();
222 for (
size_t i = 0; i < number_of_anchors; ++i)
224 anchor_cross_sectional_area(i) =
225 data[
"anchor_cross_sectional_area"][i].get<
double>();
226 anchor_stiffness(i) = data[
"anchor_stiffness"][i].get<
double>();
236 return {json_data, free_fraction};
244 "Computes natual coordinates from given real coordinates\n\n"
246 "OpenGeoSys-6 software, version " +
249 "Copyright (c) 2012-2025, OpenGeoSys Community "
250 "(http://www.opengeosys.org)",
254 cmd.add(log_level_arg);
256 TCLAP::ValueArg<std::string> input_filename_arg(
257 "i",
"input",
"Input (.vtu) bulk mesh file",
true,
"",
"INPUT_FILE",
260 TCLAP::ValueArg<std::string> output_filename_arg(
261 "o",
"output",
"Output (.vtu). Anchor mesh file",
true,
"",
264 TCLAP::ValueArg<std::string> json_filename_arg(
266 "Input (.json) JSON file containing anchor start and end points",
true,
267 "",
"INPUT_FILE", cmd);
269 TCLAP::ValueArg<double> tolerance_arg(
270 "",
"tolerance",
"Tolerance/Search length",
false,
271 std::numeric_limits<double>::epsilon(),
"float", cmd);
273 TCLAP::ValueArg<unsigned> max_iter_arg(
275 "maximum number of iterations of the internal root-finding "
276 "algorithm, (min = 0)",
277 false, 5,
"MAX_ITER", cmd);
279 cmd.parse(argc, argv);
284 auto const& [json_data, free_fraction] =
readJSON(json_filename_arg);
285 auto const bulk_mesh =
readGrid(input_filename_arg.getValue());
287 auto split_anchor_coords =
289 tolerance_arg.getValue());
298 bulk_mesh, anchor_data, tolerance_arg.getValue(),
299 max_iter_arg.getValue());
302 writeGrid(output_mesh, output_filename_arg.getValue());
306 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.