feat: add solver core skeleton
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
file(GLOB FESA_UNIT_TEST_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*_test.cpp")
|
||||
|
||||
foreach(test_source IN LISTS FESA_UNIT_TEST_SOURCES)
|
||||
get_filename_component(test_name "${test_source}" NAME_WE)
|
||||
add_executable("${test_name}" "${test_source}")
|
||||
target_link_libraries("${test_name}" PRIVATE fesa_core)
|
||||
add_test(NAME "${test_name}" COMMAND "${test_name}")
|
||||
endforeach()
|
||||
@@ -0,0 +1,37 @@
|
||||
#include <fesa/analysis/linear_static_analysis.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
fesa::model::Domain make_domain()
|
||||
{
|
||||
fesa::model::Domain domain;
|
||||
domain.add_node({fesa::core::NodeId{1}, {0.0, 0.0, 0.0}});
|
||||
domain.add_node({fesa::core::NodeId{2}, {1.0, 0.0, 0.0}});
|
||||
domain.add_material({fesa::core::MaterialId{3}, "steel"});
|
||||
domain.add_property({fesa::core::PropertyId{4}, "bar", fesa::core::MaterialId{3}});
|
||||
domain.add_element({
|
||||
fesa::core::ElementId{5},
|
||||
fesa::model::ElementTopology::truss2,
|
||||
{fesa::core::NodeId{1}, fesa::core::NodeId{2}},
|
||||
fesa::core::PropertyId{4}
|
||||
});
|
||||
fesa::model::AnalysisStep step{fesa::core::StepId{6}, "static"};
|
||||
step.add_boundary_condition({fesa::core::NodeId{1}, fesa::model::DofComponent::ux, 0.0});
|
||||
step.add_load({fesa::core::NodeId{2}, fesa::model::DofComponent::ux, 10.0});
|
||||
domain.add_step(step);
|
||||
return domain;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
const auto domain = make_domain();
|
||||
fesa::analysis::LinearStaticAnalysis analysis{domain, fesa::core::StepId{6}};
|
||||
analysis.run();
|
||||
|
||||
if (analysis.analysis_model() == nullptr || analysis.state() == nullptr) {
|
||||
return 1;
|
||||
}
|
||||
return analysis.state()->displacement().size() == 6 ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#include <fesa/analysis/analysis.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class RecordingAnalysis : public fesa::analysis::Analysis {
|
||||
public:
|
||||
const std::vector<std::string>& calls() const
|
||||
{
|
||||
return calls_;
|
||||
}
|
||||
|
||||
protected:
|
||||
void initialize() override { calls_.push_back("initialize"); }
|
||||
void build_analysis_model() override { calls_.push_back("build_analysis_model"); }
|
||||
void build_dof_map() override { calls_.push_back("build_dof_map"); }
|
||||
void build_sparse_pattern() override { calls_.push_back("build_sparse_pattern"); }
|
||||
void assemble() override { calls_.push_back("assemble"); }
|
||||
void apply_boundary_conditions() override { calls_.push_back("apply_boundary_conditions"); }
|
||||
void solve() override { calls_.push_back("solve"); }
|
||||
void update_state() override { calls_.push_back("update_state"); }
|
||||
void write_results() override { calls_.push_back("write_results"); }
|
||||
|
||||
private:
|
||||
std::vector<std::string> calls_;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
RecordingAnalysis analysis;
|
||||
analysis.run();
|
||||
const std::vector<std::string> expected{
|
||||
"initialize",
|
||||
"build_analysis_model",
|
||||
"build_dof_map",
|
||||
"build_sparse_pattern",
|
||||
"assemble",
|
||||
"apply_boundary_conditions",
|
||||
"solve",
|
||||
"update_state",
|
||||
"write_results"
|
||||
};
|
||||
return analysis.calls() == expected ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
#include <fesa/analysis/analysis_model.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace {
|
||||
|
||||
fesa::model::Domain make_domain()
|
||||
{
|
||||
fesa::model::Domain domain;
|
||||
domain.add_node({fesa::core::NodeId{1}, {0.0, 0.0, 0.0}});
|
||||
domain.add_node({fesa::core::NodeId{2}, {1.0, 0.0, 0.0}});
|
||||
domain.add_material({fesa::core::MaterialId{3}, "steel"});
|
||||
domain.add_property({fesa::core::PropertyId{4}, "bar", fesa::core::MaterialId{3}});
|
||||
domain.add_element({
|
||||
fesa::core::ElementId{5},
|
||||
fesa::model::ElementTopology::truss2,
|
||||
{fesa::core::NodeId{1}, fesa::core::NodeId{2}},
|
||||
fesa::core::PropertyId{4}
|
||||
});
|
||||
|
||||
fesa::model::AnalysisStep step{fesa::core::StepId{6}, "static"};
|
||||
step.add_boundary_condition({fesa::core::NodeId{1}, fesa::model::DofComponent::ux, 0.0});
|
||||
step.add_load({fesa::core::NodeId{2}, fesa::model::DofComponent::ux, 10.0});
|
||||
domain.add_step(step);
|
||||
return domain;
|
||||
}
|
||||
|
||||
int fail()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
const auto domain = make_domain();
|
||||
const fesa::analysis::AnalysisModel model{domain, fesa::core::StepId{6}};
|
||||
|
||||
if (&model.domain() != &domain) {
|
||||
return fail();
|
||||
}
|
||||
if (&model.step() != domain.find_step(fesa::core::StepId{6})) {
|
||||
return fail();
|
||||
}
|
||||
if (model.active_elements().size() != 1 ||
|
||||
model.active_elements()[0] != domain.find_element(fesa::core::ElementId{5})) {
|
||||
return fail();
|
||||
}
|
||||
if (model.active_boundary_conditions().size() != 1 ||
|
||||
model.active_loads().size() != 1) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
const auto* property = model.property_for(*model.active_elements()[0]);
|
||||
if (property == nullptr || property != domain.find_property(fesa::core::PropertyId{4})) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
const auto* material = model.material_for(*property);
|
||||
if (material == nullptr || material != domain.find_material(fesa::core::MaterialId{3})) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
try {
|
||||
const fesa::analysis::AnalysisModel missing{domain, fesa::core::StepId{99}};
|
||||
(void)missing;
|
||||
return fail();
|
||||
} catch (const std::invalid_argument&) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#include <fesa/analysis/analysis_state.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
int fail()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool all_zero(const std::vector<double>& values)
|
||||
{
|
||||
for (const double value : values) {
|
||||
if (value != 0.0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
fesa::analysis::AnalysisState state{3};
|
||||
if (state.displacement().size() != 3 ||
|
||||
state.velocity().size() != 3 ||
|
||||
state.acceleration().size() != 3 ||
|
||||
state.temperature().size() != 3 ||
|
||||
state.external_force().size() != 3 ||
|
||||
state.internal_force().size() != 3 ||
|
||||
state.residual().size() != 3) {
|
||||
return fail();
|
||||
}
|
||||
if (!all_zero(state.displacement()) || !all_zero(state.residual())) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
state.set_displacement({1.0, 2.0, 3.0});
|
||||
if (state.displacement()[2] != 3.0) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
state.set_external_force({10.0, 20.0, 30.0});
|
||||
state.set_internal_force({1.0, 2.0, 3.0});
|
||||
state.update_residual();
|
||||
if (state.residual()[0] != 9.0 ||
|
||||
state.residual()[1] != 18.0 ||
|
||||
state.residual()[2] != 27.0) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
try {
|
||||
state.set_displacement({1.0});
|
||||
return fail();
|
||||
} catch (const std::invalid_argument&) {
|
||||
}
|
||||
|
||||
state.iteration_state().time = 1.25;
|
||||
state.iteration_state().increment = 2;
|
||||
state.iteration_state().iteration = 3;
|
||||
if (state.iteration_state().time != 1.25 ||
|
||||
state.iteration_state().increment != 2 ||
|
||||
state.iteration_state().iteration != 3) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
state.set_element_state(fesa::core::ElementId{7}, {4.0, 5.0});
|
||||
const auto* element_state = state.element_state(fesa::core::ElementId{7});
|
||||
if (element_state == nullptr || element_state->size() != 2 || (*element_state)[1] != 5.0) {
|
||||
return fail();
|
||||
}
|
||||
if (state.element_state(fesa::core::ElementId{8}) != nullptr) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <fesa/core/diagnostic.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
const fesa::core::Diagnostic diagnostic{
|
||||
fesa::core::Severity::info,
|
||||
"core.info",
|
||||
"diagnostic"
|
||||
};
|
||||
return diagnostic.code == "core.info" ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <fesa/core/ids.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
int main()
|
||||
{
|
||||
static_assert(!std::is_same_v<fesa::core::NodeId, fesa::core::ElementId>);
|
||||
return fesa::core::NodeId{7}.value == 7 ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#include <fesa/core/diagnostic.hpp>
|
||||
#include <fesa/core/ids.hpp>
|
||||
#include <fesa/core/status.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace {
|
||||
|
||||
int fail()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
static_assert(!std::is_same_v<fesa::core::NodeId, fesa::core::ElementId>);
|
||||
|
||||
const auto ok = fesa::core::Status::ok();
|
||||
if (!ok.is_ok() || !ok.diagnostics().empty()) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
fesa::core::Diagnostic error{
|
||||
fesa::core::Severity::error,
|
||||
"core.error",
|
||||
"core failure"
|
||||
};
|
||||
auto failed = fesa::core::Status::failure(error);
|
||||
if (failed.is_ok() || failed.diagnostics().size() != 1) {
|
||||
return fail();
|
||||
}
|
||||
if (failed.diagnostics()[0].code != "core.error" ||
|
||||
failed.diagnostics()[0].message != "core failure") {
|
||||
return fail();
|
||||
}
|
||||
|
||||
failed.add({fesa::core::Severity::warning, "core.warning", "check warning"});
|
||||
if (failed.diagnostics().size() != 2) {
|
||||
return fail();
|
||||
}
|
||||
if (failed.diagnostics()[0].code != "core.error" ||
|
||||
failed.diagnostics()[1].code != "core.warning") {
|
||||
return fail();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <fesa/core/status.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
const auto status = fesa::core::Status::ok();
|
||||
return status.is_ok() ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#include <fesa/fem/dof_key.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
const fesa::fem::DofKey lhs{fesa::core::NodeId{1}, fesa::model::DofComponent::ux};
|
||||
const fesa::fem::DofKey rhs{fesa::core::NodeId{1}, fesa::model::DofComponent::ux};
|
||||
return lhs == rhs ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#include <fesa/fem/dof_manager.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
int fail()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
fesa::fem::DofManager dofs;
|
||||
dofs.define_node_dofs(fesa::core::NodeId{2}, {
|
||||
fesa::model::DofComponent::ux,
|
||||
fesa::model::DofComponent::uy
|
||||
});
|
||||
dofs.define_node_dofs(fesa::core::NodeId{1}, {
|
||||
fesa::model::DofComponent::uy,
|
||||
fesa::model::DofComponent::ux
|
||||
});
|
||||
dofs.apply_boundary_condition({
|
||||
fesa::core::NodeId{1},
|
||||
fesa::model::DofComponent::ux,
|
||||
0.0
|
||||
});
|
||||
dofs.number_equations();
|
||||
|
||||
const fesa::fem::DofKey n1ux{fesa::core::NodeId{1}, fesa::model::DofComponent::ux};
|
||||
const fesa::fem::DofKey n1uy{fesa::core::NodeId{1}, fesa::model::DofComponent::uy};
|
||||
const fesa::fem::DofKey n2ux{fesa::core::NodeId{2}, fesa::model::DofComponent::ux};
|
||||
const fesa::fem::DofKey n2uy{fesa::core::NodeId{2}, fesa::model::DofComponent::uy};
|
||||
|
||||
if (dofs.total_dof_count() != 4 ||
|
||||
dofs.constrained_dof_count() != 1 ||
|
||||
dofs.free_dof_count() != 3) {
|
||||
return fail();
|
||||
}
|
||||
if (dofs.equation_id(n1ux) != 0 ||
|
||||
dofs.equation_id(n1uy) != 1 ||
|
||||
dofs.equation_id(n2ux) != 2 ||
|
||||
dofs.equation_id(n2uy) != 3) {
|
||||
return fail();
|
||||
}
|
||||
if (!dofs.is_constrained(n1ux) ||
|
||||
dofs.free_equation_id(n1ux).has_value()) {
|
||||
return fail();
|
||||
}
|
||||
if (!dofs.free_equation_id(n1uy).has_value() ||
|
||||
*dofs.free_equation_id(n1uy) != 0 ||
|
||||
*dofs.free_equation_id(n2ux) != 1 ||
|
||||
*dofs.free_equation_id(n2uy) != 2) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
const auto full = dofs.expand_free_vector({11.0, 22.0, 33.0});
|
||||
if (full.size() != 4 ||
|
||||
full[0] != 0.0 ||
|
||||
full[1] != 11.0 ||
|
||||
full[2] != 22.0 ||
|
||||
full[3] != 33.0) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
const auto& pattern = dofs.sparse_pattern();
|
||||
if (pattern.size() != 9 ||
|
||||
pattern.front() != std::pair<int, int>{0, 0} ||
|
||||
pattern.back() != std::pair<int, int>{2, 2}) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
try {
|
||||
(void)dofs.equation_id({fesa::core::NodeId{99}, fesa::model::DofComponent::ux});
|
||||
return fail();
|
||||
} catch (const std::invalid_argument&) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <string>
|
||||
|
||||
int main()
|
||||
{
|
||||
const std::string project = "fesa";
|
||||
return project.size() == 4 ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <fesa/model/analysis_step.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
const fesa::model::AnalysisStep step{fesa::core::StepId{1}, "static"};
|
||||
return step.name() == "static" ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <fesa/model/boundary_condition.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
const fesa::model::BoundaryCondition bc{
|
||||
fesa::core::NodeId{1},
|
||||
fesa::model::DofComponent::ux,
|
||||
0.0
|
||||
};
|
||||
return bc.node_id().value == 1 ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#include <fesa/model/domain.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
int fail()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
fesa::model::Domain domain;
|
||||
|
||||
domain.add_node(fesa::model::Node{fesa::core::NodeId{1}, {1.0, 2.0, 3.0}});
|
||||
domain.add_element(fesa::model::Element{
|
||||
fesa::core::ElementId{10},
|
||||
fesa::model::ElementTopology::truss2,
|
||||
{fesa::core::NodeId{1}, fesa::core::NodeId{2}},
|
||||
fesa::core::PropertyId{20}
|
||||
});
|
||||
domain.add_material(fesa::model::Material{fesa::core::MaterialId{30}, "steel"});
|
||||
domain.add_property(fesa::model::Property{
|
||||
fesa::core::PropertyId{20},
|
||||
"bar",
|
||||
fesa::core::MaterialId{30}
|
||||
});
|
||||
|
||||
fesa::model::AnalysisStep step{fesa::core::StepId{40}, "load"};
|
||||
step.add_boundary_condition({fesa::core::NodeId{1}, fesa::model::DofComponent::ux, 0.0});
|
||||
step.add_load({fesa::core::NodeId{2}, fesa::model::DofComponent::ux, 10.0});
|
||||
domain.add_step(step);
|
||||
|
||||
const auto* node = domain.find_node(fesa::core::NodeId{1});
|
||||
if (node == nullptr || node->coordinates()[2] != 3.0) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
const auto* element = domain.find_element(fesa::core::ElementId{10});
|
||||
if (element == nullptr ||
|
||||
element->topology() != fesa::model::ElementTopology::truss2 ||
|
||||
element->node_ids().size() != 2 ||
|
||||
element->property_id().value != 20) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
const auto* material = domain.find_material(fesa::core::MaterialId{30});
|
||||
if (material == nullptr || material->name() != "steel") {
|
||||
return fail();
|
||||
}
|
||||
|
||||
const auto* property = domain.find_property(fesa::core::PropertyId{20});
|
||||
if (property == nullptr ||
|
||||
property->name() != "bar" ||
|
||||
property->material_id().value != 30) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
const auto* analysis_step = domain.find_step(fesa::core::StepId{40});
|
||||
if (analysis_step == nullptr ||
|
||||
analysis_step->boundary_conditions().size() != 1 ||
|
||||
analysis_step->loads().size() != 1) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
if (domain.find_node(fesa::core::NodeId{999}) != nullptr ||
|
||||
domain.find_element(fesa::core::ElementId{999}) != nullptr ||
|
||||
domain.find_material(fesa::core::MaterialId{999}) != nullptr ||
|
||||
domain.find_property(fesa::core::PropertyId{999}) != nullptr ||
|
||||
domain.find_step(fesa::core::StepId{999}) != nullptr) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <fesa/model/element.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
const fesa::model::Element element{
|
||||
fesa::core::ElementId{1},
|
||||
fesa::model::ElementTopology::bar2,
|
||||
{fesa::core::NodeId{1}, fesa::core::NodeId{2}},
|
||||
fesa::core::PropertyId{3}
|
||||
};
|
||||
return element.node_ids().size() == 2 ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <fesa/model/load.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
const fesa::model::Load load{
|
||||
fesa::core::NodeId{2},
|
||||
fesa::model::DofComponent::ux,
|
||||
5.0
|
||||
};
|
||||
return load.value() == 5.0 ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <fesa/model/material.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
const fesa::model::Material material{fesa::core::MaterialId{1}, "steel"};
|
||||
return material.name() == "steel" ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <fesa/model/node.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
const fesa::model::Node node{fesa::core::NodeId{1}, {0.0, 1.0, 2.0}};
|
||||
return node.coordinates()[1] == 1.0 ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <fesa/model/property.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
const fesa::model::Property property{
|
||||
fesa::core::PropertyId{2},
|
||||
"section",
|
||||
fesa::core::MaterialId{3}
|
||||
};
|
||||
return property.material_id().value == 3 ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
#include <fesa/results/results.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace {
|
||||
|
||||
int fail()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
fesa::results::ResultStep step{"static"};
|
||||
auto& frame = step.add_frame(1, 0.0);
|
||||
if (step.name() != "static" ||
|
||||
step.frames().size() != 1 ||
|
||||
frame.frame_id() != 1 ||
|
||||
frame.time() != 0.0) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
frame.add_field_output({
|
||||
"U",
|
||||
fesa::results::FieldLocation::nodal,
|
||||
{"ux", "uy"},
|
||||
{1, 2},
|
||||
{0.0, 0.1, 1.0, 1.1}
|
||||
});
|
||||
if (frame.field_outputs().size() != 1 ||
|
||||
frame.field_outputs()[0].entity_ids[1] != 2 ||
|
||||
frame.field_outputs()[0].values[3] != 1.1) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
frame.add_history_output({"load-factor", {0.0, 1.0}, {0.0, 10.0}});
|
||||
if (frame.history_outputs().size() != 1 ||
|
||||
frame.history_outputs()[0].values[1] != 10.0) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
try {
|
||||
frame.add_field_output({
|
||||
"bad",
|
||||
fesa::results::FieldLocation::nodal,
|
||||
{},
|
||||
{1},
|
||||
{0.0}
|
||||
});
|
||||
return fail();
|
||||
} catch (const std::invalid_argument&) {
|
||||
}
|
||||
|
||||
try {
|
||||
frame.add_field_output({
|
||||
"bad-shape",
|
||||
fesa::results::FieldLocation::nodal,
|
||||
{"ux", "uy"},
|
||||
{1},
|
||||
{0.0}
|
||||
});
|
||||
return fail();
|
||||
} catch (const std::invalid_argument&) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user