Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions models/dynamics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,6 @@ add_cml_tests(
dynamics

SOURCES
integration/accumulated_absolute_deltas/test/accumulated_absolute_deltas_test.cc
mass_derivative_dynamics/tests/test_mass_derivative_dynamics.cpp
)
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ PROGRAMMERS:

#include "cml/models/utilities/subscriptions/include/subscriptions.hh"

#include <cstddef>

class AccumulatedAbsoluteDeltas : public SubscriptionBase
{
protected:
Expand All @@ -48,6 +50,9 @@ class AccumulatedAbsoluteDeltas : public SubscriptionBase
and old_variable values */
AccumulatedAbsoluteDeltas( const double * variable_,
const unsigned int size_);
template <std::size_t size_>
explicit AccumulatedAbsoluteDeltas(const double (&variable_)[size_])
: AccumulatedAbsoluteDeltas(variable_, size_) {}
~AccumulatedAbsoluteDeltas() override;
AccumulatedAbsoluteDeltas ( const AccumulatedAbsoluteDeltas &) = delete;
AccumulatedAbsoluteDeltas & operator= ( const AccumulatedAbsoluteDeltas &) = delete;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ LIBRARY DEPENDENCIES:
(((Gary Turner) (OSR) (Apr 2017) (Antares) (new)))
**********************************************************************/

#include <algorithm>
#include <cmath>
#include <new>

#include "../include/accumulated_absolute_deltas.hh"
#include "cml/models/utilities/cml_message/include/cml_message.hh"
Expand All @@ -33,7 +33,7 @@ AccumulatedAbsoluteDeltas::AccumulatedAbsoluteDeltas(
if (variable == nullptr) {
CMLMessage::fail(
__FILE__,__LINE__,"Invalid construction\n",
"The variable being accumulated in NULL.\n");
"The variable being accumulated is NULL.\n");
}
if (size == 0) {
CMLMessage::fail(
Expand All @@ -44,6 +44,8 @@ AccumulatedAbsoluteDeltas::AccumulatedAbsoluteDeltas(

accumulated_deltas = new double[size];
old_variable = new double[size];

std::fill_n(accumulated_deltas, size, 0.0);
}

/*****************************************************************************
Expand Down Expand Up @@ -90,10 +92,8 @@ Purpose:(resets the accumulated value and the starting values)
void
AccumulatedAbsoluteDeltas::reset()
{
for (unsigned int ii = 0; ii < size; ++ii) {
old_variable[ii] = variable[ii];
accumulated_deltas[ii] = 0.0;
}
std::copy_n(variable, size, old_variable);
std::fill_n(accumulated_deltas, size, 0.0);
}

/*****************************************************************************
Expand All @@ -110,4 +110,4 @@ AccumulatedAbsoluteDeltas::update()
accumulated_deltas[ii] += std::abs( variable[ii] - old_variable[ii]);
old_variable[ii] = variable[ii];
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include "../include/accumulated_absolute_deltas.hh"
#include "cml/models/utilities/cml_message/include/cml_message.hh"
#include "mocks/cml/cml_message_mock.hh"

#include <gmock/gmock.h>
#include <gtest/gtest.h>

namespace {

inline constexpr double tolerance = 1e-12; // Float comparison tolerance

TEST(AccumulatedAbsoluteDeltas, Construction) {
using testing::_;
using testing::HasSubstr;

const double variable[3] {};
CMLMessage::Mock cml_message_mock;

// Test attempting to construct with a null pointer.
EXPECT_CALL(
cml_message_mock,
publish(CMLMessage::Fail, _, _, HasSubstr("The variable being accumulated is NULL")));
const AccumulatedAbsoluteDeltas null_test(nullptr, 3);

// Test attempting to construct with an array of size 0.
EXPECT_CALL(
cml_message_mock,
publish(CMLMessage::Fail, _, _, HasSubstr("The size of the array must be positive")));
const AccumulatedAbsoluteDeltas zero_test(variable, 0);

// Test normal construction.
const AccumulatedAbsoluteDeltas valid1(variable, std::size(variable));
const AccumulatedAbsoluteDeltas valid2(variable);
EXPECT_NE(valid1.accumulated_deltas, nullptr);
EXPECT_NE(valid2.accumulated_deltas, nullptr);
}

TEST(AccumulatedAbsoluteDeltas, Disabled) {
double data = 0.0;
AccumulatedAbsoluteDeltas article(&data, 1);
article.disable();

// Attempt to initialize the model while it's disabled.
article.initialize();
EXPECT_FALSE(article.is_initialized());

// The data changes but since the model is disabled, it will not accumulate
// the deltas.
data = 1.0;
article.update();
EXPECT_EQ(article.accumulated_deltas[0], 0.0);
}

TEST(AccumulatedAbsoluteDeltas, Update) {
double data[2] {1.0, -1.0};
AccumulatedAbsoluteDeltas article(data);
article.subscribe();
article.initialize();

// Test a few updates.
// Update 1:
// Element 0 changes to 0.1: net change = 0.1
// Element 1 stays the same: net change = 0
data[0] = 1.1;
data[1] = -1.0;
article.update();
EXPECT_NEAR(article.accumulated_deltas[0], 0.1, tolerance);
EXPECT_NEAR(article.accumulated_deltas[1], 0.0, tolerance);

// Update 2:
// Element 0 changes to 0: net change = 0.1 + (1.1 - 0) = 1.2
// Element 1 changes to 0: net change = 1
data[0] = 0.0;
data[1] = 0.0;
article.update();
EXPECT_NEAR(article.accumulated_deltas[0], 1.2, tolerance);
EXPECT_NEAR(article.accumulated_deltas[1], 1.0, tolerance);

// Update 3:
// Element 0 changes to -5: net change = 1.2 + 5 = 6.2
// Element 1 changes to 10: net change = 1 + 10 = 11
data[0] = -5.0;
data[1] = 10.0;
article.update();
EXPECT_NEAR(article.accumulated_deltas[0], 6.2, tolerance);
EXPECT_NEAR(article.accumulated_deltas[1], 11.0, tolerance);

// The model is deactivated. The data it's accumulating changes but the
// accumulated deltas remain the same.
article.unsubscribe();
data[0] = 0.0;
data[1] = 0.0;
article.update();
EXPECT_NEAR(article.accumulated_deltas[0], 6.2, tolerance);
EXPECT_NEAR(article.accumulated_deltas[1], 11.0, tolerance);
}

} // namespace
Loading