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