Skip to content
Snippets Groups Projects
Commit 898f6cd8 authored by wenqing's avatar wenqing Committed by Dmitri Naumov
Browse files

[ParameterLib] Added a creator for the coordinate system with implicit

bases
parent 78999c5d
No related branches found
No related tags found
No related merge requests found
......@@ -23,22 +23,33 @@ class SpatialPosition;
namespace ParameterLib
{
/**
* \brief A local coordinate system used for tensor transformations.
*
* It offers a simple way for input of anisotropic tensors w.r.t. a coordinate
* system.
* The basis vectors form a transformation matrix \f$R = (e_0, e_1, e_2)\f$.
* For a given anisotropic tensor \f$A\f$ parameter with the corresponding
* \ref ogs_file_param__prj__parameters__parameter__use_local_coordinate_system
* the tensor is rotated according to the formula: \f$A' = R\cdot A\cdot R^T\f$.
*
* For computations in transverse isotropic material models, we can create a
* coordinate system with only one base, where the last base is explicitly
* given. The other bases are set as implicit and computed from the given base
* as follows:
* - For a 2D coordinate system, the unit vector orthogonal to
* the given base is used as the first base,
* - For a 3D coordinate system, the given base vector, \c unit_direction,
* is set as the third base, \f${\vec e}_2\f$. An arbitrary unit vector
* orthogonal to \f${\vec e}_2\f$ is selected as the second base
* \f$e_1\f$, and the first base \f${\vec e}_0\f$ is calculated as
* \f${\vec e}_0 = {\vec e}_1 \times {\vec e}_2\f$.
*/
struct CoordinateSystem final
{
/**
* It is used to create a coordinate system with only one base, where the
* last base is explicitly given. The other bases are set as implicit and
* computed from the given base as follows:
* - For a 2D coordinate system, the unit vector orthogonal to
* the given base is used as the first base,
* - For a 3D coordinate system, the given base vector, \c unit_direction,
* is set as the third base, \f${\vec e}_2\f$. An arbitrary unit vector
* orthogonal to \f${\vec e}_2\f$ is selected as the second base
* \f$e_1\f$, and the first base \f${\vec e}_0\f$ is calculated as
* \f${\vec e}_0 = {\vec e}_1 \times {\vec e}_2\f$.
*
* This type of coordinate system can be used for computations in transverse
* isotropic material models.
* It is used to create a local coordinate system with only one base, where
* the last base is explicitly given as \c unit_direction.
*
* @param unit_direction The specified unit direction.
*/
......
......@@ -11,6 +11,8 @@
#include "CreateCoordinateSystem.h"
#include <string_view>
#include "BaseLib/ConfigTree.h"
#include "Parameter.h"
#include "Utils.h"
......@@ -20,6 +22,123 @@ namespace ParameterLib
struct ParameterBase;
struct CoordinateSystem;
// Note: the function is used for parsing
// 1. base1 for the case of an implicit base0.
// 2. or base2.
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)
{
auto const base_parameter_name = config.getValue<std::string>();
auto const& basis_vector = ParameterLib::findParameter<double>(
base_parameter_name, parameters, 0 /* any dimension */);
int const component_number = basis_vector.getNumberOfGlobalComponents();
if (base_tag_name == "basis_vector_1" && component_number != 2)
{
OGS_FATAL(
"The case of implicit \"basis_vector_0\" and "
"explicit \"basis_vector_1\" is for a 2D coordinate system. The "
"parameter for \"basis_vector_1\", {:s}, must have "
"two components but it has {:d}. In addition, \"basis_vector_2\" "
"should not exist in this case.",
base_parameter_name, component_number);
}
if (component_number != expected_component_number)
{
OGS_FATAL(
"The read parameter `{:s}' for tag {:s} has the wrong number of "
"components ({:d} instead of {:d}).",
base_parameter_name, base_tag_name, component_number,
expected_component_number);
}
return &basis_vector;
}
void checkThirdBaseExistanceFor2D(BaseLib::ConfigTree const& config)
{
auto const base2_config =
//! \ogs_file_param{prj__local_coordinate_system__basis_vector_2}
config.getConfigSubtreeOptional("basis_vector_2");
if (base2_config)
{
OGS_FATAL(
"The tag \"basis_vector_2\" is not needed for a 2D local "
"coordinate system.");
}
}
void confirmThirdBaseExplicit(BaseLib::ConfigTree const& config)
{
auto const implicit_base2 =
//! \ogs_file_attr{prj__local_coordinate_system__basis_vector_2__implicit}
config.getConfigAttribute<bool>("implicit", false);
if (implicit_base2)
{
OGS_FATAL("basis_vector_2 must be explicit.");
}
}
std::optional<ParameterLib::CoordinateSystem>
createCoordinateSystemWithImplicitBase(
BaseLib::ConfigTree const& config,
std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters)
{
//! \ogs_file_param{prj__local_coordinate_system__basis_vector_1}
auto const& config_base1 = config.getConfigSubtree("basis_vector_1");
// Parse the second vectors.
auto const implicit_base1 =
//! \ogs_file_attr{prj__local_coordinate_system__basis_vector_1__implicit}
config_base1.getConfigAttribute<bool>("implicit", false);
if (!implicit_base1)
{
// For 2D problem.
// Only the following case is accepted:
// <basis_vector_0 implicit = false/>
// <basis_vector_1> [two-component parameter] </basis_vector_1>.
int const expected_component_number = 2;
auto const basis_vector_1 =
parseBase1OrBase2(config_base1, parameters,
expected_component_number, "basis_vector_1");
checkThirdBaseExistanceFor2D(config);
return ParameterLib::CoordinateSystem(*basis_vector_1);
}
// For 3D problem.
// Only the following case is accepted:
// <basis_vector_0 implicit = false/>
// <basis_vector_1 implicit = false>.
// <basis_vector_2> [three-component parameter] </basis_vector_2>.
// Parse the third basis vector, e2, for the three dimensional system.
auto const config_base2 =
//! \ogs_file_param{prj__local_coordinate_system__basis_vector_2}
config.getConfigSubtreeOptional("basis_vector_2");
if (!config_base2)
{
OGS_FATAL(
"Both \"basis_vector_0\" and \"basis_vector_1\" are implicit but "
"\"basis_vector_2\" does not exist. If 2D coordinate system is "
"considered, please change \"basis_vector_1\" to explicit. If 3D "
"coordinate system is considered, please add \"basis_vector_2\".");
}
confirmThirdBaseExplicit(*config_base2);
int const expected_component_number = 3;
auto const basis_vector_2 = parseBase1OrBase2(
*config_base2, parameters, expected_component_number, "basis_vector_2");
return ParameterLib::CoordinateSystem(*basis_vector_2);
}
std::optional<ParameterLib::CoordinateSystem> createCoordinateSystem(
std::optional<BaseLib::ConfigTree> const& config,
std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters)
......@@ -29,51 +148,71 @@ std::optional<ParameterLib::CoordinateSystem> createCoordinateSystem(
return {};
}
DBUG("Reading coordinate system configuration.");
//
// Fetch the first basis vector; its length defines the dimension.
//
//! \ogs_file_param{prj__local_coordinate_system__basis_vector_0}
auto const& config_base0 = config->getConfigSubtree("basis_vector_0");
auto const implicit_base0 =
//! \ogs_file_attr{prj__local_coordinate_system__basis_vector_0__implicit}
config_base0.getConfigAttribute<bool>("implicit", false);
// base0 and base1 can be implicit. If base0 is implicit, check whether
// base1 is implicit.
// If base1 is explicit, create a 2D system if its components is 2 or quit
// if its components is not equal to 2.
// Otherwise, read base2, create a 3D system if its components is 3 or quit
// if its components is not equal to 3.
if (implicit_base0)
{
return createCoordinateSystemWithImplicitBase(*config, parameters);
}
auto const base0_name = config_base0.getValue<std::string>();
auto const& basis_vector_0 = ParameterLib::findParameter<double>(
*config,
//! \ogs_file_param_special{prj__local_coordinate_system__basis_vector_0}
"basis_vector_0", parameters, 0 /* any dimension */);
base0_name, parameters, 0 /* any dimension */);
int const dimension = basis_vector_0.getNumberOfGlobalComponents();
// check dimension
if (dimension != 2 && dimension != 3)
{
OGS_FATAL(
"Basis vector parameter '{:s}' must have two or three components, "
"but it has {:d}.",
basis_vector_0.name, dimension);
base0_name, dimension);
}
//
// Fetch the second basis vector, which must be of the same dimension as the
// first one.
//
auto const& basis_vector_1 = ParameterLib::findParameter<double>(
*config,
//! \ogs_file_param_special{prj__local_coordinate_system__basis_vector_1}
"basis_vector_1", parameters, dimension);
// Fetch the second basis vector.
//! \ogs_file_param{prj__local_coordinate_system__basis_vector_1}
auto const& config_base1 = config->getConfigSubtree("basis_vector_1");
auto const implicit_base1 =
//! \ogs_file_attr{prj__local_coordinate_system__basis_vector_1__implicit}
config_base1.getConfigAttribute<bool>("implicit", false);
if (implicit_base1)
{
OGS_FATAL(
"Since basis_vector_0 is explicitly defined, basis_vector_1"
" must be explicit as well.");
}
auto const base1_name = config_base1.getValue<std::string>();
auto const& basis_vector_1 =
ParameterLib::findParameter<double>(base1_name, parameters, dimension);
//
// For two dimensions, we are done; construct coordinate system;
//
if (dimension == 2)
{
checkThirdBaseExistanceFor2D(*config);
return ParameterLib::CoordinateSystem{basis_vector_0, basis_vector_1};
}
//
// Parse the third vector, for three dimensions.
//
auto const& basis_vector_2 = ParameterLib::findParameter<double>(
*config,
//! \ogs_file_param_special{prj__local_coordinate_system__basis_vector_2}
"basis_vector_2", parameters, dimension);
// Parse the third basis vector, e2, for the three dimensional system.
//! \ogs_file_param{prj__local_coordinate_system__basis_vector_2}
auto const& config_base2 = config->getConfigSubtree("basis_vector_2");
confirmThirdBaseExplicit(config_base2);
int const expected_component_number = 3;
auto const basis_vector_2 = parseBase1OrBase2(
config_base2, parameters, expected_component_number, "basis_vector_2");
return ParameterLib::CoordinateSystem{basis_vector_0, basis_vector_1,
basis_vector_2};
*basis_vector_2};
}
} // namespace ParameterLib
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment