feat(cpp-object-oriented-modular-refactoring): step 3 - foundation-google-style

This commit is contained in:
KOKO\Mimi
2026-08-16 04:26:14 +09:00
parent 2628ed3488
commit 042edadffb
93 changed files with 3144 additions and 3175 deletions
+44 -44
View File
@@ -50,10 +50,10 @@ EulerBeam3D requireBeam(const Node& firstNode,
const GeneralBeamSection& section,
const LinearElasticMaterial& material) {
auto result = EulerBeam3D::create(firstNode, secondNode, section, material);
if (!result.hasValue()) {
if (!result.HasValue()) {
throw std::runtime_error{"Expected a valid EulerBeam3D fixture."};
}
return std::move(result.value());
return std::move(result.Value());
}
EulerBeam3D alignedBeam(double length,
@@ -68,8 +68,8 @@ EulerBeam3D alignedBeam(double length,
double maximumAbsoluteEntry(const Matrix& matrix) {
double maximum = 0.0;
for (std::size_t row = 0; row < matrix.rows(); ++row) {
for (std::size_t column = 0; column < matrix.columns(); ++column) {
for (std::size_t row = 0; row < matrix.Rows(); ++row) {
for (std::size_t column = 0; column < matrix.Columns(); ++column) {
maximum = (std::max)(maximum, std::abs(matrix(row, column)));
}
}
@@ -77,8 +77,8 @@ double maximumAbsoluteEntry(const Matrix& matrix) {
}
bool matrixIsFinite(const Matrix& matrix) {
for (std::size_t row = 0; row < matrix.rows(); ++row) {
for (std::size_t column = 0; column < matrix.columns(); ++column) {
for (std::size_t row = 0; row < matrix.Rows(); ++row) {
for (std::size_t column = 0; column < matrix.Columns(); ++column) {
if (!std::isfinite(matrix(row, column))) {
return false;
}
@@ -88,13 +88,13 @@ bool matrixIsFinite(const Matrix& matrix) {
}
double normalizedMatrixError(const Matrix& actual, const Matrix& expected) {
if (actual.rows() != expected.rows() || actual.columns() != expected.columns()) {
if (actual.Rows() != expected.Rows() || actual.Columns() != expected.Columns()) {
throw std::invalid_argument{"Matrix comparison requires equal shapes."};
}
double maximumDifference = 0.0;
for (std::size_t row = 0; row < actual.rows(); ++row) {
for (std::size_t column = 0; column < actual.columns(); ++column) {
for (std::size_t row = 0; row < actual.Rows(); ++row) {
for (std::size_t column = 0; column < actual.Columns(); ++column) {
maximumDifference = (std::max)(
maximumDifference,
std::abs(actual(row, column) - expected(row, column)));
@@ -109,16 +109,16 @@ double normalizedMatrixError(const Matrix& actual, const Matrix& expected) {
double vectorNorm(const Vector& vector) {
double sum = 0.0;
for (std::size_t index = 0; index < vector.size(); ++index) {
for (std::size_t index = 0; index < vector.Size(); ++index) {
sum += vector[index] * vector[index];
}
return std::sqrt(sum);
}
double quadraticEnergy(const Matrix& matrix, const Vector& vector) {
const Vector product = matrix.multiply(vector);
const Vector product = matrix.Multiply(vector);
double value = 0.0;
for (std::size_t index = 0; index < vector.size(); ++index) {
for (std::size_t index = 0; index < vector.Size(); ++index) {
value += vector[index] * product[index];
}
return value;
@@ -328,14 +328,14 @@ Vector solveFixedFirstNode(const Matrix& stiffness,
}
Vector solveDenseSystem(Matrix matrix, Vector rightHandSide) {
if (matrix.rows() != matrix.columns() ||
matrix.rows() != rightHandSide.size()) {
if (matrix.Rows() != matrix.Columns() ||
matrix.Rows() != rightHandSide.Size()) {
throw std::invalid_argument{"Dense test solve requires a square system."};
}
for (std::size_t pivot = 0; pivot < matrix.rows(); ++pivot) {
for (std::size_t pivot = 0; pivot < matrix.Rows(); ++pivot) {
std::size_t pivotRow = pivot;
for (std::size_t row = pivot + 1U; row < matrix.rows(); ++row) {
for (std::size_t row = pivot + 1U; row < matrix.Rows(); ++row) {
if (std::abs(matrix(row, pivot)) >
std::abs(matrix(pivotRow, pivot))) {
pivotRow = row;
@@ -345,22 +345,22 @@ Vector solveDenseSystem(Matrix matrix, Vector rightHandSide) {
!std::isfinite(matrix(pivotRow, pivot))) {
throw std::runtime_error{"Uniform-load test fixture is singular."};
}
for (std::size_t column = pivot; column < matrix.columns(); ++column) {
for (std::size_t column = pivot; column < matrix.Columns(); ++column) {
std::swap(matrix(pivot, column), matrix(pivotRow, column));
}
std::swap(rightHandSide[pivot], rightHandSide[pivotRow]);
const double pivotValue = matrix(pivot, pivot);
for (std::size_t column = pivot; column < matrix.columns(); ++column) {
for (std::size_t column = pivot; column < matrix.Columns(); ++column) {
matrix(pivot, column) /= pivotValue;
}
rightHandSide[pivot] /= pivotValue;
for (std::size_t row = 0; row < matrix.rows(); ++row) {
for (std::size_t row = 0; row < matrix.Rows(); ++row) {
if (row == pivot) {
continue;
}
const double factor = matrix(row, pivot);
for (std::size_t column = pivot; column < matrix.columns(); ++column) {
for (std::size_t column = pivot; column < matrix.Columns(); ++column) {
matrix(row, column) -= factor * matrix(pivot, column);
}
rightHandSide[row] -= factor * rightHandSide[pivot];
@@ -489,12 +489,12 @@ Matrix transformationFromKnownRows(
}
Vector transposeMultiply(const Matrix& matrix, const Vector& vector) {
if (matrix.rows() != vector.size()) {
if (matrix.Rows() != vector.Size()) {
throw std::invalid_argument{"Transpose multiply dimension mismatch."};
}
Vector result{matrix.columns()};
for (std::size_t column = 0; column < matrix.columns(); ++column) {
for (std::size_t row = 0; row < matrix.rows(); ++row) {
Vector result{matrix.Columns()};
for (std::size_t column = 0; column < matrix.Columns(); ++column) {
for (std::size_t row = 0; row < matrix.Rows(); ++row) {
result[column] += matrix(row, column) * vector[row];
}
}
@@ -595,9 +595,9 @@ TEST(EulerBeam3D, TwoPointGaussMatchesClosedStiffness) {
const Matrix closed = expectedClosedStiffness(length, section, material);
EXPECT_LE(normalizedMatrixError(actual, closed), kMatrixTolerance);
Matrix transpose{actual.rows(), actual.columns()};
for (std::size_t row = 0; row < actual.rows(); ++row) {
for (std::size_t column = 0; column < actual.columns(); ++column) {
Matrix transpose{actual.Rows(), actual.Columns()};
for (std::size_t row = 0; row < actual.Rows(); ++row) {
for (std::size_t column = 0; column < actual.Columns(); ++column) {
transpose(row, column) = actual(column, row);
}
}
@@ -629,7 +629,7 @@ TEST(EulerBeam3D, HasSixRigidModesRankSixAndPositiveDeformationEnergy) {
const double stiffnessScale = (std::max)(1.0, maximumAbsoluteEntry(stiffness));
for (const Vector& mode : rigidModes) {
const double normalizedResidual =
vectorNorm(stiffness.multiply(mode)) /
vectorNorm(stiffness.Multiply(mode)) /
(stiffnessScale * (std::max)(1.0, vectorNorm(mode)));
EXPECT_LE(normalizedResidual, kRigidTolerance);
}
@@ -695,7 +695,7 @@ TEST(EulerBeam3D, RotatedTransformPreservesWorkAndEnergy) {
const Matrix global = beam.globalStiffness();
Matrix expectedGlobal{kElementDofCount, kElementDofCount};
const Matrix localTimesTransform = local.multiply(transformation);
const Matrix localTimesTransform = local.Multiply(transformation);
for (std::size_t row = 0; row < kElementDofCount; ++row) {
for (std::size_t column = 0; column < kElementDofCount; ++column) {
for (std::size_t inner = 0; inner < kElementDofCount; ++inner) {
@@ -707,12 +707,12 @@ TEST(EulerBeam3D, RotatedTransformPreservesWorkAndEnergy) {
EXPECT_LE(normalizedMatrixError(global, expectedGlobal), kMatrixTolerance);
Vector localDisplacement{kElementDofCount};
for (std::size_t index = 0; index < localDisplacement.size(); ++index) {
for (std::size_t index = 0; index < localDisplacement.Size(); ++index) {
localDisplacement[index] = 0.01 * static_cast<double>(index + 1U) - 0.04;
}
const Vector globalDisplacement = transposeMultiply(transformation, localDisplacement);
const Vector localForce = local.multiply(localDisplacement);
const Vector globalForce = global.multiply(globalDisplacement);
const Vector localForce = local.Multiply(localDisplacement);
const Vector globalForce = global.Multiply(globalDisplacement);
const Vector expectedGlobalForce = transposeMultiply(transformation, localForce);
for (std::size_t index = 0; index < kElementDofCount; ++index) {
expectScaledNear(globalForce[index], expectedGlobalForce[index], kMatrixTolerance);
@@ -723,13 +723,13 @@ TEST(EulerBeam3D, RotatedTransformPreservesWorkAndEnergy) {
kMatrixTolerance);
Vector globalVariation{kElementDofCount};
for (std::size_t index = 0; index < globalVariation.size(); ++index) {
for (std::size_t index = 0; index < globalVariation.Size(); ++index) {
globalVariation[index] = 0.03 - 0.002 * static_cast<double>(index);
}
const Vector localVariation = transformation.multiply(globalVariation);
const Vector localVariation = transformation.Multiply(globalVariation);
expectScaledNear(
globalVariation.dot(globalForce),
localVariation.dot(localForce),
globalVariation.Dot(globalForce),
localVariation.Dot(localForce),
kMatrixTolerance);
const BeamRecovery recovery = beam.recover(globalDisplacement);
@@ -746,7 +746,7 @@ TEST(EulerBeam3D, ConstantLineLoadMatchesAllSignedComponents) {
const std::array<double, kElementDofCount> expected = {
5.0, -6.0, 11.0, -14.0, -22.0 / 3.0, -4.0,
5.0, -6.0, 11.0, -14.0, 22.0 / 3.0, 4.0};
ASSERT_EQ(equivalent.size(), expected.size());
ASSERT_EQ(equivalent.Size(), expected.size());
for (std::size_t index = 0; index < expected.size(); ++index) {
expectScaledNear(equivalent[index], expected[index], kMatrixTolerance);
}
@@ -931,17 +931,17 @@ TEST(EulerBeam3D, RejectsInvalidGeometryAndProperties) {
const auto expectFailure = [](const Result<EulerBeam3D>& result,
const std::string& code) {
if (result.hasValue()) {
const Matrix stiffness = result.value().localStiffness();
if (result.HasValue()) {
const Matrix stiffness = result.Value().localStiffness();
ADD_FAILURE()
<< "Invalid fixture was accepted; local stiffness finite="
<< matrixIsFinite(stiffness)
<< ", maximum absolute entry=" << maximumAbsoluteEntry(stiffness);
return;
}
EXPECT_EQ(result.status().failureCategory(), FailureCategory::model);
ASSERT_EQ(result.status().diagnostics().size(), 1U);
EXPECT_EQ(result.status().diagnostics()[0U].code, code);
EXPECT_EQ(result.GetStatus().Category(), FailureCategory::kModel);
ASSERT_EQ(result.GetStatus().Diagnostics().size(), 1U);
EXPECT_EQ(result.GetStatus().Diagnostics()[0U].code, code);
};
expectFailure(
@@ -964,7 +964,7 @@ TEST(EulerBeam3D, RejectsInvalidGeometryAndProperties) {
"invalid-beam-length");
EXPECT_TRUE(EulerBeam3D::create(
scaledFirst, aboveThreshold, validSection, validMaterial)
.hasValue());
.HasValue());
auto parallelGuide = validSection;
parallelGuide.firstAxis = {1.0, 0.0, 0.0};
@@ -978,7 +978,7 @@ TEST(EulerBeam3D, RejectsInvalidGeometryAndProperties) {
"invalid-beam-guide-vector");
auto guideAboveThreshold = validSection;
guideAboveThreshold.firstAxis = {1.0, 2.0e-12, 0.0};
EXPECT_TRUE(EulerBeam3D::create(origin, unitX, guideAboveThreshold, validMaterial).hasValue());
EXPECT_TRUE(EulerBeam3D::create(origin, unitX, guideAboveThreshold, validMaterial).HasValue());
auto invalidMaterial = validMaterial;
invalidMaterial.youngsModulus = 0.0;
+113 -113
View File
@@ -84,10 +84,10 @@ void expectMatrixNear(
const fesa::Matrix& actual,
const fesa::Matrix& expected,
double tolerance = 1.0e-12) {
ASSERT_EQ(actual.rows(), expected.rows());
ASSERT_EQ(actual.columns(), expected.columns());
for (std::size_t row = 0U; row < actual.rows(); ++row) {
for (std::size_t column = 0U; column < actual.columns(); ++column) {
ASSERT_EQ(actual.Rows(), expected.Rows());
ASSERT_EQ(actual.Columns(), expected.Columns());
for (std::size_t row = 0U; row < actual.Rows(); ++row) {
for (std::size_t column = 0U; column < actual.Columns(); ++column) {
EXPECT_NEAR(actual(row, column), expected(row, column), tolerance)
<< "at (" << row << ", " << column << ")";
}
@@ -95,20 +95,20 @@ void expectMatrixNear(
}
void expectSymmetric(const fesa::Matrix& matrix) {
ASSERT_EQ(matrix.rows(), matrix.columns());
for (std::size_t row = 0U; row < matrix.rows(); ++row) {
for (std::size_t column = 0U; column < matrix.columns(); ++column) {
ASSERT_EQ(matrix.Rows(), matrix.Columns());
for (std::size_t row = 0U; row < matrix.Rows(); ++row) {
for (std::size_t column = 0U; column < matrix.Columns(); ++column) {
EXPECT_NEAR(matrix(row, column), matrix(column, row), 1.0e-12);
}
}
}
bool hasPositiveCholeskyPivots(const fesa::Matrix& matrix) {
if (matrix.rows() != matrix.columns()) {
if (matrix.Rows() != matrix.Columns()) {
return false;
}
fesa::Matrix lower{matrix.rows(), matrix.columns()};
for (std::size_t row = 0U; row < matrix.rows(); ++row) {
fesa::Matrix lower{matrix.Rows(), matrix.Columns()};
for (std::size_t row = 0U; row < matrix.Rows(); ++row) {
for (std::size_t column = 0U; column <= row; ++column) {
double value = matrix(row, column);
for (std::size_t inner = 0U; inner < column; ++inner) {
@@ -129,8 +129,8 @@ bool hasPositiveCholeskyPivots(const fesa::Matrix& matrix) {
double frobeniusNorm(const fesa::Matrix& matrix) {
double squaredNorm = 0.0;
for (std::size_t row = 0U; row < matrix.rows(); ++row) {
for (std::size_t column = 0U; column < matrix.columns(); ++column) {
for (std::size_t row = 0U; row < matrix.Rows(); ++row) {
for (std::size_t column = 0U; column < matrix.Columns(); ++column) {
squaredNorm += matrix(row, column) * matrix(row, column);
}
}
@@ -141,11 +141,11 @@ double scaledSymmetryError(
const fesa::Matrix& matrix,
std::size_t dofsPerNode,
double elementLength) {
fesa::Matrix difference{matrix.rows(), matrix.columns()};
fesa::Matrix scaled{matrix.rows(), matrix.columns()};
for (std::size_t row = 0U; row < matrix.rows(); ++row) {
fesa::Matrix difference{matrix.Rows(), matrix.Columns()};
fesa::Matrix scaled{matrix.Rows(), matrix.Columns()};
for (std::size_t row = 0U; row < matrix.Rows(); ++row) {
const double rowScale = row % dofsPerNode < 3U ? elementLength : 1.0;
for (std::size_t column = 0U; column < matrix.columns(); ++column) {
for (std::size_t column = 0U; column < matrix.Columns(); ++column) {
const double columnScale =
column % dofsPerNode < 3U ? elementLength : 1.0;
scaled(row, column) =
@@ -161,10 +161,10 @@ fesa::Matrix scaledStiffness(
const fesa::Matrix& matrix,
std::size_t dofsPerNode,
double elementLength) {
fesa::Matrix scaled{matrix.rows(), matrix.columns()};
for (std::size_t row = 0U; row < matrix.rows(); ++row) {
fesa::Matrix scaled{matrix.Rows(), matrix.Columns()};
for (std::size_t row = 0U; row < matrix.Rows(); ++row) {
const double rowScale = row % dofsPerNode < 3U ? elementLength : 1.0;
for (std::size_t column = 0U; column < matrix.columns(); ++column) {
for (std::size_t column = 0U; column < matrix.Columns(); ++column) {
const double columnScale =
column % dofsPerNode < 3U ? elementLength : 1.0;
scaled(row, column) =
@@ -175,10 +175,10 @@ fesa::Matrix scaledStiffness(
}
std::vector<double> symmetricEigenvalues(fesa::Matrix matrix) {
if (matrix.rows() != matrix.columns()) {
if (matrix.Rows() != matrix.Columns()) {
throw std::invalid_argument{"Symmetric eigensolve requires a square matrix."};
}
const std::size_t size = matrix.rows();
const std::size_t size = matrix.Rows();
double matrixScale = 0.0;
for (std::size_t row = 0U; row < size; ++row) {
for (std::size_t column = 0U; column < size; ++column) {
@@ -266,7 +266,7 @@ double symmetricOperatorNorm(const fesa::Matrix& matrix) {
}
double quadraticEnergy(const fesa::Matrix& stiffness, const fesa::Vector& vector) {
return 0.5 * vector.dot(stiffness.multiply(vector));
return 0.5 * vector.Dot(stiffness.Multiply(vector));
}
fesa::Vector physicalField(const std::array<std::array<double, 5>, 4>& values) {
@@ -286,7 +286,7 @@ void expectStrain(
double eta,
double zeta,
const std::array<double, 5>& expected) {
const auto actual = shell.strainDisplacement20(xi, eta, zeta).multiply(field);
const auto actual = shell.strainDisplacement20(xi, eta, zeta).Multiply(field);
for (std::size_t component = 0U; component < expected.size(); ++component) {
EXPECT_NEAR(actual[component], expected[component], 1.0e-12)
<< "component " << component;
@@ -367,8 +367,8 @@ TEST(Mitc4ShellKinematics, BuildsRightHandedFramesAndSeparatePhysicalDrillingMap
node(4, {0.0, -1.0, 1.0})};
const auto candidate = fesa::Mitc4Shell::create(
nodePointers(nodes), directors({1.0, 0.0, 0.0}), section(), material());
ASSERT_TRUE(candidate.hasValue());
const auto& shell = candidate.value();
ASSERT_TRUE(candidate.HasValue());
const auto& shell = candidate.Value();
const auto frame = shell.localFrame(0.0, 0.0);
expectVectorNear(frame.e1, {0.0, 1.0, 0.0});
@@ -378,10 +378,10 @@ TEST(Mitc4ShellKinematics, BuildsRightHandedFramesAndSeparatePhysicalDrillingMap
const auto physical = shell.physicalTransformation20();
const auto drilling = shell.drillingTransformation4();
ASSERT_EQ(physical.rows(), 20U);
ASSERT_EQ(physical.columns(), 24U);
ASSERT_EQ(drilling.rows(), 4U);
ASSERT_EQ(drilling.columns(), 24U);
ASSERT_EQ(physical.Rows(), 20U);
ASSERT_EQ(physical.Columns(), 24U);
ASSERT_EQ(drilling.Rows(), 4U);
ASSERT_EQ(drilling.Columns(), 24U);
for (std::size_t nodeIndex = 0U; nodeIndex < 4U; ++nodeIndex) {
const std::size_t physicalOffset = 5U * nodeIndex;
const std::size_t globalOffset = 6U * nodeIndex;
@@ -411,7 +411,7 @@ TEST(Mitc4ShellKinematics, BuildsRightHandedFramesAndSeparatePhysicalDrillingMap
invalidDirectors[2] = {0.0, 0.0, 0.0};
EXPECT_FALSE(fesa::Mitc4Shell::create(
nodePointers(nodes), invalidDirectors, section(), material())
.hasValue());
.HasValue());
}
// MITC4-KIN-003
@@ -419,12 +419,12 @@ TEST(Mitc4ShellKinematics, FormsDirectColumnsAndAllCovariantTyingSamples) {
const auto nodes = planarNodes();
const auto candidate = fesa::Mitc4Shell::create(
nodePointers(nodes), directors(), section(), material());
ASSERT_TRUE(candidate.hasValue());
const auto& shell = candidate.value();
ASSERT_TRUE(candidate.HasValue());
const auto& shell = candidate.Value();
const auto direct = shell.directStrainDisplacement20(0.0, 0.0, 0.5);
ASSERT_EQ(direct.rows(), 5U);
ASSERT_EQ(direct.columns(), 20U);
ASSERT_EQ(direct.Rows(), 5U);
ASSERT_EQ(direct.Columns(), 20U);
EXPECT_DOUBLE_EQ(direct(0U, 0U), -0.25);
EXPECT_DOUBLE_EQ(direct(0U, 4U), -0.125);
EXPECT_DOUBLE_EQ(direct(1U, 1U), -0.25);
@@ -439,8 +439,8 @@ TEST(Mitc4ShellKinematics, FormsDirectColumnsAndAllCovariantTyingSamples) {
EXPECT_DOUBLE_EQ(direct(4U, 3U), -0.25);
const auto samples = shell.covariantTyingShearSamples20();
ASSERT_EQ(samples.rows(), 4U);
ASSERT_EQ(samples.columns(), 20U);
ASSERT_EQ(samples.Rows(), 4U);
ASSERT_EQ(samples.Columns(), 20U);
EXPECT_DOUBLE_EQ(samples(0U, 2U), -0.25);
EXPECT_DOUBLE_EQ(samples(0U, 4U), 0.25);
EXPECT_DOUBLE_EQ(samples(0U, 7U), 0.25);
@@ -476,21 +476,21 @@ TEST(Mitc4ShellConstitutive, BuildsExactPositiveDefiniteSectionMatricesAndRescal
const auto nodes = planarNodes();
const auto candidate = fesa::Mitc4Shell::create(
nodePointers(nodes), directors(), section(), material());
ASSERT_TRUE(candidate.hasValue());
const auto& shell = candidate.value();
ASSERT_TRUE(candidate.HasValue());
const auto& shell = candidate.Value();
const auto cps = shell.planeStressConstitutive();
const auto c5 = shell.materialConstitutive5();
const auto a = shell.membraneSectionMatrix();
const auto d = shell.bendingSectionMatrix();
const auto as = shell.transverseShearSectionMatrix();
EXPECT_EQ(cps.rows(), 3U);
EXPECT_EQ(cps.columns(), 3U);
EXPECT_EQ(c5.rows(), 5U);
EXPECT_EQ(c5.columns(), 5U);
EXPECT_EQ(a.rows(), 3U);
EXPECT_EQ(d.rows(), 3U);
EXPECT_EQ(as.rows(), 2U);
EXPECT_EQ(cps.Rows(), 3U);
EXPECT_EQ(cps.Columns(), 3U);
EXPECT_EQ(c5.Rows(), 5U);
EXPECT_EQ(c5.Columns(), 5U);
EXPECT_EQ(a.Rows(), 3U);
EXPECT_EQ(d.Rows(), 3U);
EXPECT_EQ(as.Rows(), 2U);
EXPECT_DOUBLE_EQ(cps(0U, 0U), 128.0);
EXPECT_DOUBLE_EQ(cps(0U, 1U), 32.0);
EXPECT_DOUBLE_EQ(cps(2U, 2U), 48.0);
@@ -514,8 +514,8 @@ TEST(Mitc4ShellConstitutive, BuildsExactPositiveDefiniteSectionMatricesAndRescal
directors(),
section(2.0 * lengthScale),
material(120.0 * forceScale / (lengthScale * lengthScale), 0.25));
ASSERT_TRUE(scaledCandidate.hasValue());
const auto& scaled = scaledCandidate.value();
ASSERT_TRUE(scaledCandidate.HasValue());
const auto& scaled = scaledCandidate.Value();
fesa::Matrix expectedCps{3U, 3U};
fesa::Matrix expectedC5{5U, 5U};
fesa::Matrix expectedA{3U, 3U};
@@ -548,13 +548,13 @@ TEST(Mitc4ShellConstitutive, BuildsExactPositiveDefiniteSectionMatricesAndRescal
EXPECT_FALSE(fesa::Mitc4Shell::create(
nodePointers(nodes), directors(), section(0.0), material())
.hasValue());
.HasValue());
EXPECT_FALSE(fesa::Mitc4Shell::create(
nodePointers(nodes), directors(), section(), material(0.0, 0.25))
.hasValue());
.HasValue());
EXPECT_FALSE(fesa::Mitc4Shell::create(
nodePointers(nodes), directors(), section(), material(120.0, 0.5))
.hasValue());
.HasValue());
}
// MITC4-KIN-005
@@ -578,23 +578,23 @@ TEST(Mitc4ShellKernel, FormsFiniteScaledSymmetricPhysicalAndStabilizedStiffness)
const auto nodes = planarNodes();
const auto shellCandidate = fesa::Mitc4Shell::create(
nodePointers(nodes), directors(), section(), material());
ASSERT_TRUE(shellCandidate.hasValue());
ASSERT_TRUE(shellCandidate.HasValue());
const auto stiffnessCandidate = shellCandidate.value().stiffness();
ASSERT_TRUE(stiffnessCandidate.hasValue());
const auto& stiffness = stiffnessCandidate.value();
EXPECT_EQ(stiffness.physicalLocal20.rows(), 20U);
EXPECT_EQ(stiffness.physicalLocal20.columns(), 20U);
EXPECT_EQ(stiffness.physicalGlobal24.rows(), 24U);
EXPECT_EQ(stiffness.drillingGlobal24.rows(), 24U);
EXPECT_EQ(stiffness.stabilizedGlobal24.rows(), 24U);
const auto stiffnessCandidate = shellCandidate.Value().stiffness();
ASSERT_TRUE(stiffnessCandidate.HasValue());
const auto& stiffness = stiffnessCandidate.Value();
EXPECT_EQ(stiffness.physicalLocal20.Rows(), 20U);
EXPECT_EQ(stiffness.physicalLocal20.Columns(), 20U);
EXPECT_EQ(stiffness.physicalGlobal24.Rows(), 24U);
EXPECT_EQ(stiffness.drillingGlobal24.Rows(), 24U);
EXPECT_EQ(stiffness.stabilizedGlobal24.Rows(), 24U);
for (const fesa::Matrix* matrix : {
&stiffness.physicalLocal20,
&stiffness.physicalGlobal24,
&stiffness.drillingGlobal24,
&stiffness.stabilizedGlobal24}) {
for (std::size_t row = 0U; row < matrix->rows(); ++row) {
for (std::size_t column = 0U; column < matrix->columns(); ++column) {
for (std::size_t row = 0U; row < matrix->Rows(); ++row) {
for (std::size_t column = 0U; column < matrix->Columns(); ++column) {
EXPECT_TRUE(std::isfinite((*matrix)(row, column)));
}
}
@@ -604,9 +604,9 @@ TEST(Mitc4ShellKernel, FormsFiniteScaledSymmetricPhysicalAndStabilizedStiffness)
EXPECT_LE(scaledSymmetryError(stiffness.drillingGlobal24, 6U, 2.0), 1.0e-12);
EXPECT_LE(scaledSymmetryError(stiffness.stabilizedGlobal24, 6U, 2.0), 1.0e-12);
const auto repeatedCandidate = shellCandidate.value().stiffness();
ASSERT_TRUE(repeatedCandidate.hasValue());
const auto& repeated = repeatedCandidate.value();
const auto repeatedCandidate = shellCandidate.Value().stiffness();
ASSERT_TRUE(repeatedCandidate.HasValue());
const auto& repeated = repeatedCandidate.Value();
expectMatrixNear(repeated.physicalLocal20, stiffness.physicalLocal20, 0.0);
expectMatrixNear(repeated.physicalGlobal24, stiffness.physicalGlobal24, 0.0);
expectMatrixNear(repeated.drillingGlobal24, stiffness.drillingGlobal24, 0.0);
@@ -619,18 +619,18 @@ TEST(Mitc4ShellKernel, PreservesPhysicalEnergyUnderTwentyToTwentyFourCongruence)
const auto nodes = planarNodes();
const auto shellCandidate = fesa::Mitc4Shell::create(
nodePointers(nodes), directors(), section(), material());
ASSERT_TRUE(shellCandidate.hasValue());
const auto stiffnessCandidate = shellCandidate.value().stiffness();
ASSERT_TRUE(stiffnessCandidate.hasValue());
const auto& stiffness = stiffnessCandidate.value();
ASSERT_TRUE(shellCandidate.HasValue());
const auto stiffnessCandidate = shellCandidate.Value().stiffness();
ASSERT_TRUE(stiffnessCandidate.HasValue());
const auto& stiffness = stiffnessCandidate.Value();
fesa::Vector globalField{24U};
for (std::size_t index = 0U; index < globalField.size(); ++index) {
for (std::size_t index = 0U; index < globalField.Size(); ++index) {
globalField[index] = 0.125 * static_cast<double>(
static_cast<int>(index % 7U) - 3);
}
const auto physicalField20 =
shellCandidate.value().physicalTransformation20().multiply(globalField);
shellCandidate.Value().physicalTransformation20().Multiply(globalField);
const double localEnergy = quadraticEnergy(
stiffness.physicalLocal20, physicalField20);
const double globalEnergy = quadraticEnergy(
@@ -648,10 +648,10 @@ TEST(Mitc4ShellKernel, RetainsSixRigidModesAndHasExpectedPhysicalAndStabilizedRa
const auto nodes = planarNodes();
const auto shellCandidate = fesa::Mitc4Shell::create(
nodePointers(nodes), directors(), section(), material());
ASSERT_TRUE(shellCandidate.hasValue());
const auto stiffnessCandidate = shellCandidate.value().stiffness();
ASSERT_TRUE(stiffnessCandidate.hasValue());
const auto& stiffness = stiffnessCandidate.value();
ASSERT_TRUE(shellCandidate.HasValue());
const auto stiffnessCandidate = shellCandidate.Value().stiffness();
ASSERT_TRUE(stiffnessCandidate.HasValue());
const auto& stiffness = stiffnessCandidate.Value();
const auto scaledPhysical20 =
scaledStiffness(stiffness.physicalLocal20, 5U, 2.0);
@@ -680,14 +680,14 @@ TEST(Mitc4ShellKernel, RetainsSixRigidModesAndHasExpectedPhysicalAndStabilizedRa
scaledMode[6U * nodeIndex + component] /= 2.0;
}
}
const double modeNorm = scaledMode.norm();
const double modeNorm = scaledMode.Norm();
ASSERT_GT(modeNorm, 0.0);
EXPECT_LE(
scaledPhysical24.multiply(scaledMode).norm() /
scaledPhysical24.Multiply(scaledMode).Norm() /
(physicalNorm * modeNorm),
1.0e-10);
EXPECT_LE(
scaledStabilized24.multiply(scaledMode).norm() /
scaledStabilized24.Multiply(scaledMode).Norm() /
(stabilizedNorm * modeNorm),
1.0e-10);
}
@@ -698,11 +698,11 @@ TEST(Mitc4ShellPatch, ReproducesIndependentMembraneBendingShearAndTwistFields) {
const auto nodes = planarNodes();
const auto shellCandidate = fesa::Mitc4Shell::create(
nodePointers(nodes), directors(), section(), material());
ASSERT_TRUE(shellCandidate.hasValue());
const auto& shell = shellCandidate.value();
ASSERT_TRUE(shellCandidate.HasValue());
const auto& shell = shellCandidate.Value();
const auto stiffnessCandidate = shell.stiffness();
ASSERT_TRUE(stiffnessCandidate.hasValue());
const auto& stiffness = stiffnessCandidate.value().physicalLocal20;
ASSERT_TRUE(stiffnessCandidate.HasValue());
const auto& stiffness = stiffnessCandidate.Value().physicalLocal20;
constexpr double magnitude = 0.2;
const double gauss = 1.0 / std::sqrt(3.0);
@@ -755,10 +755,10 @@ TEST(Mitc4ShellDrilling, UsesOnlyEightPositivePhysicalRotationDiagonalsAndFixedF
node(3, {50.0, 50.0, 0.0}), node(4, {-50.0, 50.0, 0.0})};
const auto shellCandidate = fesa::Mitc4Shell::create(
nodePointers(nodes), directors(), section(0.1), material());
ASSERT_TRUE(shellCandidate.hasValue());
const auto stiffnessCandidate = shellCandidate.value().stiffness();
ASSERT_TRUE(stiffnessCandidate.hasValue());
const auto& stiffness = stiffnessCandidate.value();
ASSERT_TRUE(shellCandidate.HasValue());
const auto stiffnessCandidate = shellCandidate.Value().stiffness();
ASSERT_TRUE(stiffnessCandidate.HasValue());
const auto& stiffness = stiffnessCandidate.Value();
double expectedReference = (std::numeric_limits<double>::max)();
double allDiagonalMinimum = (std::numeric_limits<double>::max)();
@@ -788,17 +788,17 @@ TEST(Mitc4ShellDrilling, FailsNonfiniteReferenceAndStabilizesEachPureDrillCoordi
const auto nodes = planarNodes();
const auto shellCandidate = fesa::Mitc4Shell::create(
nodePointers(nodes), directors(), section(), material());
ASSERT_TRUE(shellCandidate.hasValue());
const auto stiffnessCandidate = shellCandidate.value().stiffness();
ASSERT_TRUE(stiffnessCandidate.hasValue());
const auto& stiffness = stiffnessCandidate.value();
ASSERT_TRUE(shellCandidate.HasValue());
const auto stiffnessCandidate = shellCandidate.Value().stiffness();
ASSERT_TRUE(stiffnessCandidate.HasValue());
const auto& stiffness = stiffnessCandidate.Value();
for (std::size_t nodeIndex = 0U; nodeIndex < 4U; ++nodeIndex) {
fesa::Vector pureDrill{24U};
pureDrill[6U * nodeIndex + 5U] = 1.0;
EXPECT_DOUBLE_EQ(
stiffness.physicalGlobal24.multiply(pureDrill).norm(), 0.0);
const auto drillAction = stiffness.drillingGlobal24.multiply(pureDrill);
stiffness.physicalGlobal24.Multiply(pureDrill).Norm(), 0.0);
const auto drillAction = stiffness.drillingGlobal24.Multiply(pureDrill);
EXPECT_DOUBLE_EQ(drillAction[6U * nodeIndex + 5U], stiffness.drillingStiffness);
EXPECT_GT(quadraticEnergy(stiffness.drillingGlobal24, pureDrill), 0.0);
}
@@ -808,20 +808,20 @@ TEST(Mitc4ShellDrilling, FailsNonfiniteReferenceAndStabilizesEachPureDrillCoordi
node(3, {5.0e9, 5.0e9, 0.0}), node(4, {-5.0e9, 5.0e9, 0.0})};
const auto extremeShell = fesa::Mitc4Shell::create(
nodePointers(extremeNodes), directors(), section(1.0), material(1.0e300));
ASSERT_TRUE(extremeShell.hasValue());
const auto failure = extremeShell.value().stiffness();
ASSERT_FALSE(failure.hasValue());
ASSERT_EQ(failure.status().diagnostics().size(), 1U);
EXPECT_EQ(failure.status().diagnostics()[0].code, "invalid-shell-stiffness");
const auto repeatedFailure = extremeShell.value().stiffness();
ASSERT_FALSE(repeatedFailure.hasValue());
ASSERT_EQ(repeatedFailure.status().diagnostics().size(), 1U);
ASSERT_TRUE(extremeShell.HasValue());
const auto failure = extremeShell.Value().stiffness();
ASSERT_FALSE(failure.HasValue());
ASSERT_EQ(failure.GetStatus().Diagnostics().size(), 1U);
EXPECT_EQ(failure.GetStatus().Diagnostics()[0].code, "invalid-shell-stiffness");
const auto repeatedFailure = extremeShell.Value().stiffness();
ASSERT_FALSE(repeatedFailure.HasValue());
ASSERT_EQ(repeatedFailure.GetStatus().Diagnostics().size(), 1U);
EXPECT_EQ(
repeatedFailure.status().diagnostics()[0].code,
failure.status().diagnostics()[0].code);
repeatedFailure.GetStatus().Diagnostics()[0].code,
failure.GetStatus().Diagnostics()[0].code);
EXPECT_EQ(
repeatedFailure.status().diagnostics()[0].message,
failure.status().diagnostics()[0].message);
repeatedFailure.GetStatus().Diagnostics()[0].message,
failure.GetStatus().Diagnostics()[0].message);
}
// MITC4-KERNEL-007
@@ -829,21 +829,21 @@ TEST(Mitc4ShellDrilling, ExcludesPureDrillFromPhysicalRecoveryAndEnergy) {
const auto nodes = planarNodes();
const auto shellCandidate = fesa::Mitc4Shell::create(
nodePointers(nodes), directors(), section(), material());
ASSERT_TRUE(shellCandidate.hasValue());
const auto& shell = shellCandidate.value();
ASSERT_TRUE(shellCandidate.HasValue());
const auto& shell = shellCandidate.Value();
const auto stiffnessCandidate = shell.stiffness();
ASSERT_TRUE(stiffnessCandidate.hasValue());
ASSERT_TRUE(stiffnessCandidate.HasValue());
for (std::size_t nodeIndex = 0U; nodeIndex < nodes.size(); ++nodeIndex) {
fesa::Vector pureDrill{24U};
pureDrill[6U * nodeIndex + 5U] = 1.0;
EXPECT_GT(
stiffnessCandidate.value().stabilizedGlobal24.multiply(pureDrill).norm(),
stiffnessCandidate.Value().stabilizedGlobal24.Multiply(pureDrill).Norm(),
0.0);
const auto recoveryCandidate = shell.recoverPhysical(pureDrill);
ASSERT_TRUE(recoveryCandidate.hasValue());
const auto& recovery = recoveryCandidate.value();
ASSERT_TRUE(recoveryCandidate.HasValue());
const auto& recovery = recoveryCandidate.Value();
EXPECT_DOUBLE_EQ(recovery.strainEnergy, 0.0);
for (const auto& point : recovery.points) {
for (double value : point.generalizedStrain) {
@@ -866,8 +866,8 @@ TEST(Mitc4ShellPhysicalRecovery, RecoversHandFieldAtFixedLocationsAndSectionPosi
const auto nodes = planarNodes();
const auto shellCandidate = fesa::Mitc4Shell::create(
nodePointers(nodes), directors(), section(), material());
ASSERT_TRUE(shellCandidate.hasValue());
const auto& shell = shellCandidate.value();
ASSERT_TRUE(shellCandidate.HasValue());
const auto& shell = shellCandidate.Value();
constexpr std::array<double, 8> generalized{
0.1, -0.05, 0.2, 0.3, -0.15, 0.25, 0.4, -0.3};
@@ -889,8 +889,8 @@ TEST(Mitc4ShellPhysicalRecovery, RecoversHandFieldAtFixedLocationsAndSectionPosi
}
const auto recoveryCandidate = shell.recoverPhysical(globalField);
ASSERT_TRUE(recoveryCandidate.hasValue());
const auto& recovery = recoveryCandidate.value();
ASSERT_TRUE(recoveryCandidate.HasValue());
const auto& recovery = recoveryCandidate.Value();
const double gauss = 1.0 / std::sqrt(3.0);
const std::array<std::array<double, 2>, 4> expectedCoordinates{
std::array<double, 2>{-gauss, -gauss},