Connect MITC4 drilling evidence across analysis procedures
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
#include "assembly/ordered_contribution_internal.h"
|
||||
#include "math/finite_values.h"
|
||||
#include "elements/shell_kernel_values.h"
|
||||
#include "results/mitc4_drilling_evidence.h"
|
||||
|
||||
namespace fesa {
|
||||
namespace {
|
||||
@@ -57,6 +58,7 @@ struct InternalAssembly {
|
||||
SparseMatrix tangent;
|
||||
std::vector<ShellResultRow> shell_rows;
|
||||
double physical_strain_energy;
|
||||
Mitc4DrillingEvidence mitc4_drilling;
|
||||
};
|
||||
|
||||
Status ProcedureFailure(const FailureCategory category, const std::string& code,
|
||||
@@ -175,6 +177,10 @@ Result<NonlinearStateBaselineInput> BuildBaseline(const Domain& domain) {
|
||||
Result<std::vector<RuntimeShell>> BuildRuntimeShells(const Domain& domain,
|
||||
const DofManager& dofs) {
|
||||
std::vector<RuntimeShell> shells;
|
||||
if (domain.Elements().Empty())
|
||||
return Result<std::vector<RuntimeShell>>::Failure(ProcedureFailure(
|
||||
FailureCategory::kModel, "unsupported-nonlinear-element", {}, "ELEMENT",
|
||||
{}, "The nonlinear static procedure requires a MITC4 shell element."));
|
||||
shells.reserve(domain.Elements().Size());
|
||||
for (std::size_t index = 0U; index < domain.Elements().Size(); ++index) {
|
||||
const auto* definition =
|
||||
@@ -320,7 +326,7 @@ NonlinearMitc4TrialDofs ExtractElementTrial(
|
||||
|
||||
Result<InternalAssembly> AssembleInternal(
|
||||
const std::vector<RuntimeShell>& shells, const DofManager& dofs,
|
||||
const Vector& coordinates, const ParallelFor& parallel_for) {
|
||||
const Domain& domain, const Vector& coordinates, const ParallelFor& parallel_for) {
|
||||
std::vector<std::optional<NonlinearMitc4InternalEquilibrium>> local(
|
||||
shells.size());
|
||||
std::vector<std::optional<Status>> failures(shells.size());
|
||||
@@ -341,6 +347,7 @@ Result<InternalAssembly> AssembleInternal(
|
||||
std::vector<ShellResultRow> rows;
|
||||
rows.reserve(shells.size() * 4U);
|
||||
double energy = 0.0;
|
||||
Mitc4DrillingEvidence drilling{shells.front().kernel->DrillingMode()};
|
||||
for (std::size_t index = 0U; index < shells.size(); ++index) {
|
||||
if (failures[index].has_value()) {
|
||||
return Result<InternalAssembly>::Failure(*failures[index]);
|
||||
@@ -354,6 +361,28 @@ Result<InternalAssembly> AssembleInternal(
|
||||
"NONLINEAR_STATIC_PROCEDURE", std::to_string(index),
|
||||
"A nonlinear shell internal residual or tangent is nonfinite."));
|
||||
}
|
||||
if (shells[index].kernel->DrillingMode() != drilling.mode ||
|
||||
local[index]->drilling_force.Size() != kShellDofCount ||
|
||||
!IsFinite(local[index]->drilling_force))
|
||||
return Result<InternalAssembly>::Failure(ProcedureFailure(
|
||||
FailureCategory::kSolver, "invalid-shell-drilling-evidence", {},
|
||||
"NONLINEAR_STATIC_PROCEDURE", {}, "Drilling mode or force is invalid."));
|
||||
const auto element_trial = ExtractElementTrial(shells[index], coordinates);
|
||||
for (std::size_t node = 0U; node < 4U; ++node) {
|
||||
const auto first = 6U * node;
|
||||
const auto global_node = shells[index].scatter[first] / 6U;
|
||||
const auto& values = local[index]->drilling_force;
|
||||
const Vector3 drilling_force{values[first], values[first + 1U], values[first + 2U]};
|
||||
const auto spatial = SpatialMomentSO3(element_trial.rotation_vector[node],
|
||||
{values[first + 3U], values[first + 4U], values[first + 5U]});
|
||||
if (!spatial.HasValue())
|
||||
return Result<InternalAssembly>::Failure(spatial.GetStatus());
|
||||
const Vector3 position = Vector3(domain.Nodes()[global_node].coordinates) +
|
||||
element_trial.displacement[node];
|
||||
const Vector3 moment = position.Cross(drilling_force) + spatial.Value();
|
||||
for (std::size_t c = 0U; c < 3U; ++c)
|
||||
drilling.drilling_moment[c] += moment[c];
|
||||
}
|
||||
for (std::size_t row = 0U; row < kShellDofCount; ++row) {
|
||||
force[shells[index].scatter[row]] += local[index]->internal_residual[row];
|
||||
assembly_internal::AppendLocalMatrixRow(
|
||||
@@ -373,7 +402,8 @@ Result<InternalAssembly> AssembleInternal(
|
||||
}
|
||||
energy += local[index]->physical_strain_energy;
|
||||
}
|
||||
if (!IsFinite(force) || !std::isfinite(energy)) {
|
||||
if (!IsFinite(force) || !std::isfinite(energy) ||
|
||||
!IsFinite(drilling.drilling_moment)) {
|
||||
return Result<InternalAssembly>::Failure(ProcedureFailure(
|
||||
FailureCategory::kSolver, "nonfinite-newton-data", {},
|
||||
"NONLINEAR_STATIC_PROCEDURE", {},
|
||||
@@ -387,7 +417,7 @@ Result<InternalAssembly> AssembleInternal(
|
||||
return Result<InternalAssembly>::Failure(tangent.GetStatus());
|
||||
}
|
||||
return Result<InternalAssembly>::Success(
|
||||
{std::move(force), std::move(tangent.Value()), std::move(rows), energy});
|
||||
{std::move(force), std::move(tangent.Value()), std::move(rows), energy, drilling});
|
||||
}
|
||||
|
||||
Result<Vector> Difference(const Vector& left, const Vector& right) {
|
||||
@@ -699,7 +729,7 @@ AcceptedFrameState AcceptedFrame(const std::uint32_t frame_index,
|
||||
trial.reaction,
|
||||
trial.shell_results,
|
||||
trial.physical_strain_energy,
|
||||
trial.global_equilibrium};
|
||||
trial.global_equilibrium, trial.mitc4_drilling};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -807,7 +837,7 @@ Result<NonlinearStaticExecutionResult> ExecuteNonlinearStaticCore(
|
||||
NewtonIterationStage::kKinematicsEvaluated;
|
||||
|
||||
Result<InternalAssembly> internal = AssembleInternal(
|
||||
shells.Value(), dofs.Value(),
|
||||
shells.Value(), dofs.Value(), domain,
|
||||
trial.Value().generalized_coordinates, parallel_for);
|
||||
if (!internal.HasValue()) {
|
||||
return Result<std::optional<ShellStepCandidate>>::Failure(
|
||||
@@ -879,6 +909,9 @@ Result<NonlinearStaticExecutionResult> ExecuteNonlinearStaticCore(
|
||||
NewtonIterationStage::kExternalAssembled));
|
||||
}
|
||||
trial.Value().global_equilibrium = global_equilibrium.Value();
|
||||
trial.Value().mitc4_drilling = internal.Value().mitc4_drilling;
|
||||
results_internal::CompleteDrillingEvidence(
|
||||
trial.Value().global_equilibrium, &*trial.Value().mitc4_drilling);
|
||||
|
||||
Result<PartitionedStiffness> partition =
|
||||
constraints.Partition(tangent.Value(), dofs.Value());
|
||||
|
||||
Reference in New Issue
Block a user