OGS
CreateCoordinateSystem.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
5
6#include <string_view>
7
9#include "Parameter.h"
10#include "Utils.h"
11
12namespace ParameterLib
13{
14struct ParameterBase;
15struct CoordinateSystem;
16
17// Note: the function is used for parsing
18// 1. base1 for the case of an implicit base0.
19// 2. or base2.
21 BaseLib::ConfigTree const& config,
22 std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
23 int const expected_component_number,
24 std::string_view const base_tag_name)
25{
26 auto const base_parameter_name = config.getValue<std::string>();
27 auto const& basis_vector = ParameterLib::findParameter<double>(
28 base_parameter_name, parameters, 0 /* any dimension */);
29
30 int const component_number = basis_vector.getNumberOfGlobalComponents();
31 if (base_tag_name == "basis_vector_1" && component_number != 2)
32 {
34 "The case of implicit \"basis_vector_0\" and "
35 "explicit \"basis_vector_1\" is for a 2D coordinate system. The "
36 "parameter for \"basis_vector_1\", {:s}, must have "
37 "two components but it has {:d}. In addition, \"basis_vector_2\" "
38 "should not exist in this case.",
39 base_parameter_name, component_number);
40 }
41
42 if (component_number != expected_component_number)
43 {
45 "The read parameter `{:s}' for tag {:s} has the wrong number of "
46 "components ({:d} instead of {:d}).",
47 base_parameter_name, base_tag_name, component_number,
48 expected_component_number);
49 }
50
51 return &basis_vector;
52}
53
55{
56 auto const base2_config =
58 config.getConfigSubtreeOptional("basis_vector_2");
59 if (base2_config)
60 {
62 "The tag \"basis_vector_2\" is not needed for a 2D local "
63 "coordinate system.");
64 }
65}
66
68{
69 auto const implicit_base2 =
71 config.getConfigAttribute<bool>("implicit", false);
72 if (implicit_base2)
73 {
74 OGS_FATAL("basis_vector_2 must be explicit.");
75 }
76}
77
78std::optional<ParameterLib::CoordinateSystem>
80 BaseLib::ConfigTree const& config,
81 std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters)
82{
84 auto const& config_base1 = config.getConfigSubtree("basis_vector_1");
85
86 // Parse the second vectors.
87 auto const implicit_base1 =
89 config_base1.getConfigAttribute<bool>("implicit", false);
90
91 if (!implicit_base1)
92 {
93 // For 2D problem.
94 // Only the following case is accepted:
95 // <basis_vector_0 implicit = false/>
96 // <basis_vector_1> [two-component parameter] </basis_vector_1>.
97 int const expected_component_number = 2;
98 auto const basis_vector_1 =
99 parseBase1OrBase2(config_base1, parameters,
100 expected_component_number, "basis_vector_1");
101
103
104 return ParameterLib::CoordinateSystem(*basis_vector_1);
105 }
106
107 // For 3D problem.
108 // Only the following case is accepted:
109 // <basis_vector_0 implicit = false/>
110 // <basis_vector_1 implicit = false>.
111 // <basis_vector_2> [three-component parameter] </basis_vector_2>.
112
113 // Parse the third basis vector, e2, for the three dimensional system.
114 auto const config_base2 =
116 config.getConfigSubtreeOptional("basis_vector_2");
117 if (!config_base2)
118 {
119 OGS_FATAL(
120 "Both \"basis_vector_0\" and \"basis_vector_1\" are implicit but "
121 "\"basis_vector_2\" does not exist. If 2D coordinate system is "
122 "considered, please change \"basis_vector_1\" to explicit. If 3D "
123 "coordinate system is considered, please add \"basis_vector_2\".");
124 }
125
126 confirmThirdBaseExplicit(*config_base2);
127
128 int const expected_component_number = 3;
129 auto const basis_vector_2 = parseBase1OrBase2(
130 *config_base2, parameters, expected_component_number, "basis_vector_2");
131 return ParameterLib::CoordinateSystem(*basis_vector_2);
132}
133
134std::optional<ParameterLib::CoordinateSystem> createCoordinateSystem(
135 std::optional<BaseLib::ConfigTree> const& config,
136 std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters)
137{
138 if (!config)
139 {
140 return {};
141 }
142
143 //
144 // Fetch the first basis vector; its length defines the dimension.
145 //
147 auto const& config_base0 = config->getConfigSubtree("basis_vector_0");
148 auto const implicit_base0 =
150 config_base0.getConfigAttribute<bool>("implicit", false);
151
152 // base0 and base1 can be implicit. If base0 is implicit, check whether
153 // base1 is implicit.
154 // If base1 is explicit, create a 2D system if its components is 2 or quit
155 // if its components is not equal to 2.
156 // Otherwise, read base2, create a 3D system if its components is 3 or quit
157 // if its components is not equal to 3.
158 if (implicit_base0)
159 {
160 return createCoordinateSystemWithImplicitBase(*config, parameters);
161 }
162
163 auto const base0_name = config_base0.getValue<std::string>();
164 auto const& basis_vector_0 = ParameterLib::findParameter<double>(
165 base0_name, parameters, 0 /* any dimension */);
166 int const dimension = basis_vector_0.getNumberOfGlobalComponents();
167 // check dimension
168 if (dimension != 2 && dimension != 3)
169 {
170 OGS_FATAL(
171 "Basis vector parameter '{:s}' must have two or three components, "
172 "but it has {:d}.",
173 base0_name, dimension);
174 }
175
176 // Fetch the second basis vector.
178 auto const& config_base1 = config->getConfigSubtree("basis_vector_1");
179 auto const implicit_base1 =
181 config_base1.getConfigAttribute<bool>("implicit", false);
182 if (implicit_base1)
183 {
184 OGS_FATAL(
185 "Since basis_vector_0 is explicitly defined, basis_vector_1"
186 " must be explicit as well.");
187 }
188 auto const base1_name = config_base1.getValue<std::string>();
189 auto const& basis_vector_1 =
190 ParameterLib::findParameter<double>(base1_name, parameters, dimension);
191
192 if (dimension == 2)
193 {
195 return ParameterLib::CoordinateSystem{basis_vector_0, basis_vector_1};
196 }
197
198 // Parse the third basis vector, e2, for the three dimensional system.
200 auto const& config_base2 = config->getConfigSubtree("basis_vector_2");
201 confirmThirdBaseExplicit(config_base2);
202
203 int const expected_component_number = 3;
204 auto const basis_vector_2 = parseBase1OrBase2(
205 config_base2, parameters, expected_component_number, "basis_vector_2");
206
207 return ParameterLib::CoordinateSystem{basis_vector_0, basis_vector_1,
208 *basis_vector_2};
209}
210} // namespace ParameterLib
#define OGS_FATAL(...)
Definition Error.h:19
std::optional< ConfigTree > getConfigSubtreeOptional(std::string const &root) const
T getConfigAttribute(std::string const &attr) const
ConfigTree getConfigSubtree(std::string const &root) const
std::optional< ParameterLib::CoordinateSystem > createCoordinateSystem(std::optional< BaseLib::ConfigTree > const &config, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters)
Parameter< double > const * parseBase1OrBase2(BaseLib::ConfigTree const &config, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters, int const expected_component_number, std::string_view const base_tag_name)
OGS_NO_DANGLING Parameter< ParameterDataType > & findParameter(std::string const &parameter_name, std::vector< std::unique_ptr< ParameterBase > > const &parameters, int const num_components, MeshLib::Mesh const *const mesh=nullptr)
std::optional< ParameterLib::CoordinateSystem > createCoordinateSystemWithImplicitBase(BaseLib::ConfigTree const &config, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters)
void checkThirdBaseExistanceFor2D(BaseLib::ConfigTree const &config)
void confirmThirdBaseExplicit(BaseLib::ConfigTree const &config)
A local coordinate system used for tensor transformations.