diff --git a/build/codeblocks/otlsmodels_sagtension.cbp b/build/codeblocks/otlsmodels_sagtension.cbp
index f66b338..1d40fc6 100644
--- a/build/codeblocks/otlsmodels_sagtension.cbp
+++ b/build/codeblocks/otlsmodels_sagtension.cbp
@@ -65,12 +65,18 @@
+
+
+
+
+
+
@@ -92,12 +98,18 @@
+
+
+
+
+
+
diff --git a/build/codeblocks/otlsmodels_transmissionline.cbp b/build/codeblocks/otlsmodels_transmissionline.cbp
index b7ea8d6..25f08a5 100644
--- a/build/codeblocks/otlsmodels_transmissionline.cbp
+++ b/build/codeblocks/otlsmodels_transmissionline.cbp
@@ -60,7 +60,7 @@
-
+
@@ -102,7 +102,7 @@
-
+
diff --git a/build/msvc/otlsmodels_sagtension.vcxproj b/build/msvc/otlsmodels_sagtension.vcxproj
index 27c8784..d4aebdc 100644
--- a/build/msvc/otlsmodels_sagtension.vcxproj
+++ b/build/msvc/otlsmodels_sagtension.vcxproj
@@ -61,8 +61,10 @@
+
+
@@ -72,8 +74,10 @@
+
+
diff --git a/build/msvc/otlsmodels_sagtension.vcxproj.filters b/build/msvc/otlsmodels_sagtension.vcxproj.filters
index f6b6cf6..455f0cd 100644
--- a/build/msvc/otlsmodels_sagtension.vcxproj.filters
+++ b/build/msvc/otlsmodels_sagtension.vcxproj.filters
@@ -38,6 +38,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
@@ -67,5 +73,11 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
\ No newline at end of file
diff --git a/build/msvc/otlsmodels_transmissionline.vcxproj b/build/msvc/otlsmodels_transmissionline.vcxproj
index 5b6c100..aa8436b 100644
--- a/build/msvc/otlsmodels_transmissionline.vcxproj
+++ b/build/msvc/otlsmodels_transmissionline.vcxproj
@@ -60,7 +60,7 @@
-
+
@@ -76,7 +76,7 @@
-
+
diff --git a/build/msvc/otlsmodels_transmissionline.vcxproj.filters b/build/msvc/otlsmodels_transmissionline.vcxproj.filters
index 7fa2cf4..5a4504e 100644
--- a/build/msvc/otlsmodels_transmissionline.vcxproj.filters
+++ b/build/msvc/otlsmodels_transmissionline.vcxproj.filters
@@ -17,9 +17,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -53,6 +50,9 @@
Header Files
+
+ Header Files
+
@@ -61,9 +61,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -97,5 +94,8 @@
Source Files
+
+ Source Files
+
\ No newline at end of file
diff --git a/docs/doxygen_config b/docs/doxygen_config
index e057230..9e29adf 100644
--- a/docs/doxygen_config
+++ b/docs/doxygen_config
@@ -745,9 +745,11 @@ WARN_LOGFILE = "./doxygen.log"
INPUT = ../include/models/base \
../include/models/sagtension \
+ ../include/models/thermalrating \
../include/models/transmissionline \
../src/base \
../src/sagtension \
+ ../src/thermalrating \
../src/transmissionline
# This tag can be used to specify the character encoding of the source files
diff --git a/include/models/sagtension/cable_component_elongation_model.h b/include/models/sagtension/cable_component_elongation_model.h
index 8d3a78c..197fc4a 100644
--- a/include/models/sagtension/cable_component_elongation_model.h
+++ b/include/models/sagtension/cable_component_elongation_model.h
@@ -427,6 +427,14 @@ class CableComponentElongationModel {
/// The polynomial that describes the cable component elongation.
Polynomial polynomial_loadstrain_;
+ /// \var state_
+ /// The state of the component.
+ const CableState* state_;
+
+ /// \var state_stretch_
+ /// The state used to stretch the component.
+ const CableStretchState* state_stretch_;
+
/// \var strain_thermal_state_
/// The amount of strain due to shifting from reference temperature to the
/// state temperature.
@@ -437,14 +445,6 @@ class CableComponentElongationModel {
/// stretch temperature.
mutable double strain_thermal_stretch_;
- /// \var state_
- /// The state of the component.
- const CableState* state_;
-
- /// \var state_stretch_
- /// The state used to stretch the component.
- const CableStretchState* state_stretch_;
-
/// \var temperature_reference_
/// The base reference temperature for the cable component. The polynomial
/// is defined at this temperature.
diff --git a/include/models/sagtension/line_cable_loader_base.h b/include/models/sagtension/line_cable_loader_base.h
new file mode 100644
index 0000000..f34f076
--- /dev/null
+++ b/include/models/sagtension/line_cable_loader_base.h
@@ -0,0 +1,149 @@
+// This is free and unencumbered software released into the public domain.
+// For more information, please refer to
+
+#ifndef OTLS_MODELS_SAGTENSION_LINECABLELOADERBASE_H_
+#define OTLS_MODELS_SAGTENSION_LINECABLELOADERBASE_H_
+
+#include
+
+#include "models/base/error_message.h"
+#include "models/sagtension/cable_elongation_model.h"
+#include "models/sagtension/sag_tension_cable.h"
+#include "models/transmissionline/catenary.h"
+#include "models/transmissionline/line_cable.h"
+
+/// \par OVERVIEW
+///
+/// This class sets up a LineCable for a sag-tension analysis. The process is
+/// as follows:
+/// - solve for a catenary based on the line cable constraint
+/// - solve cable model for the constraint
+/// - solve cable models for the stretch conditions
+/// - determine the stretch load for each condition
+///
+/// \par STRETCH
+///
+/// This class supports multiple forms of stretch, including:
+/// - short term, heavy load stretch
+/// - long term, creep stretch
+///
+/// \par LINE CABLE GEOMETRY
+///
+/// This class uses the ruling span geometry defined in the line cable.
+class LineCableLoaderBase {
+ public:
+ /// \brief Default constructor.
+ LineCableLoaderBase();
+
+ /// \brief Destructor.
+ ~LineCableLoaderBase();
+
+ /// \brief Gets the stretch state for the creep condition.
+ /// \return The stretch state for the creep condition.
+ CableStretchState StretchStateCreep() const;
+
+ /// \brief Gets the stretch state for the load condition.
+ /// \return The stretch state for the load condition.
+ CableStretchState StretchStateLoad() const;
+
+ /// \brief Validates member variables.
+ /// \param[in] is_included_warnings
+ /// A flag that tightens the acceptable value range.
+ /// \param[in,out] messages
+ /// A list of detailed error messages. If this is provided, any validation
+ /// errors will be appended to the list.
+ /// \return A boolean value indicating status of member variables.
+ bool Validate(const bool& is_included_warnings = true,
+ std::list* messages = nullptr) const;
+
+ /// \brief Gets the line cable.
+ /// \return The line cable.
+ const LineCable* line_cable() const;
+
+ /// \brief Sets the line cable.
+ /// \param[in] line_cable
+ /// The line cable.
+ void set_line_cable(const LineCable* line_cable);
+
+ protected:
+ /// \brief Initializes the models defined in the line cable.
+ /// \return The success status of the update.
+ /// This function initializes the cable models with the correct temperature
+ /// and polynomial, but does not solve for any stretch.
+ bool InitializeLineCableModels() const;
+
+ /// \brief Determines if class is updated.
+ /// \return A boolean indicating if class is updated.
+ virtual bool IsUpdated() const;
+
+ /// \brief Calculates the unit load of the catenary.
+ /// \param[in] weathercase
+ /// The weather case.
+ /// \return The unit loading of the cable.
+ Vector3d UnitLoad(const WeatherLoadCase& weathercase) const;
+
+ /// \brief Updates cached member variables and modifies control variables if
+ /// update is required.
+ /// \return A boolean indicating if class updates completed successfully.
+ virtual bool Update() const;
+
+ /// \brief Updates the constraint cable model.
+ /// \return The success status of the update.
+ /// This function further updates the constraint cable model to include any
+ /// stretch.
+ bool UpdateConstraintCableModel() const;
+
+ /// \brief Updates the constraint catenary.
+ /// \return The success status of the update.
+ bool UpdateConstraintCatenary() const;
+
+ /// \brief Updates the stretch due to load and creep.
+ /// \return The success status of the update.
+ bool UpdateLoadStretch() const;
+
+ /// \var cable_sagtension_
+ /// The cable, which is referenced for sag-tension methods.
+ SagTensionCable cable_sagtension_;
+
+ /// \var catenary_constraint_
+ /// The catenary for the line cable constraint.
+ mutable Catenary3d catenary_constraint_;
+
+ /// \var is_updated_catenary_constraint_
+ /// An indicator that tells if the constraint catenary cable is updated.
+ mutable bool is_updated_catenary_constraint_;
+
+ /// \var is_updated_stretch_
+ /// An indicator that tells if the stretch load is updated.
+ mutable bool is_updated_stretch_;
+
+ /// \var line_cable_
+ /// The line cable that is being reloaded.
+ const LineCable* line_cable_;
+
+ /// \var model_constraint_
+ /// The cable model for the constraint weathercase. This model may contain
+ /// stretch, depending on the constraint condition.
+ mutable CableElongationModel model_constraint_;
+
+ /// \var model_creep_
+ /// The cable model used for solving creep stretch. This model will always
+ /// contain zero stretch to ensure that only the polynomial is referenced.
+ mutable CableElongationModel model_creep_;
+
+ /// \var model_load_
+ /// The cable model used for solving heavy load stretch. This model will
+ /// always contain zero stretch to ensure that only the polynomial is
+ /// referenced.
+ mutable CableElongationModel model_load_;
+
+ /// \var state_stretch_creep_
+ /// The stretch state for the creep condition.
+ mutable CableStretchState state_stretch_creep_;
+
+ /// \var state_stretch_load_;
+ /// The stretch state for the load condition.
+ mutable CableStretchState state_stretch_load_;
+};
+
+#endif // OTLS_MODELS_SAGTENSION_LINECABLELOADERBASE_H_
diff --git a/include/models/sagtension/line_cable_reloader.h b/include/models/sagtension/line_cable_reloader.h
index d48e248..deb25b9 100644
--- a/include/models/sagtension/line_cable_reloader.h
+++ b/include/models/sagtension/line_cable_reloader.h
@@ -7,32 +7,18 @@
#include
#include "models/base/error_message.h"
-#include "models/sagtension/cable_elongation_model.h"
-#include "models/sagtension/sag_tension_cable.h"
+#include "models/sagtension/line_cable_loader_base.h"
#include "models/transmissionline/catenary.h"
-#include "models/transmissionline/line_cable.h"
/// \par OVERVIEW
///
/// This class reloads a line cable to a specified weather case and condition.
/// The process is as follows:
-/// - solve for a catenary based on the line cable constraint
-/// - build cable models for the constraint, creep-stretch, load-stretch, and
-/// reloaded weathercases
-/// - determine the stretch load for creep and load conditions
-/// - reload the catenary (based on the line cable constraint) at the reloaded
-/// weathercase
-///
-/// \par STRETCH
-///
-/// This class supports multiple forms of stretch, including:
-/// - short term, heavy load stretch
-/// - long term, creep stretch
-///
-/// \par LINE CABLE GEOMETRY
-///
-/// This class uses the ruling span geometry defined in the line cable.
-class LineCableReloader {
+/// - set up the line cable for sag-tension analysis (see LineCableLoaderBase)
+/// - build a cable model for the reloaded state
+/// - reload the constraint catenary to the reloaded state
+/// (see CatenaryCableReloader)
+class LineCableReloader : public LineCableLoaderBase {
public:
/// \brief Default constructor.
LineCableReloader();
@@ -44,26 +30,10 @@ class LineCableReloader {
/// \return A catenary at the reloaded load case.
Catenary3d CatenaryReloaded() const;
- /// \brief Gets the unloaded length of the constraint catenary.
- /// \return The unloaded length of the constraint catenary.
- double LengthUnloadedConstraint() const;
-
- /// \brief Gets the unloaded length of the reloaded catenary.
- /// \return The unloaded length of the reloaded catenary.
- double LengthUnloadedReloaded() const;
-
/// \brief Gets the reloaded cable state.
/// \return The reloaded cable state.
CableState StateReloaded() const;
- /// \brief Gets the stretch state for the creep condition.
- /// \return The stretch state for the creep condition.
- CableStretchState StretchStateCreep() const;
-
- /// \brief Gets the stretch state for the load condition.
- /// \return The stretch state for the load condition.
- CableStretchState StretchStateLoad() const;
-
/// \brief Gets the average load of the cable component.
/// \param[in] type_component
/// The model component type.
@@ -96,20 +66,11 @@ class LineCableReloader {
/// \return The reloaded cable condition.
CableConditionType condition_reloaded() const;
- /// \brief Gets the line cable.
- /// \return The line cable.
- const LineCable* line_cable() const;
-
/// \brief Sets the reloaded cable condition.
/// \param[in] condition_reloaded
/// The reloaded cable condition.
void set_condition_reloaded(const CableConditionType& condition_reloaded);
- /// \brief Sets the line cable.
- /// \param[in] line_cable
- /// The line cable.
- void set_line_cable(const LineCable* line_cable);
-
/// \brief Sets the reloaded load case.
/// \param[in] weathercase_reloaded
/// The reloaded weathercase.
@@ -120,40 +81,14 @@ class LineCableReloader {
const WeatherLoadCase* weathercase_reloaded() const;
private:
- /// \brief Initializes the models defined in the line cable.
- /// \return The success status of the update.
- /// This function initializes the cable models with the correct temperature
- /// and polynomial, but does not solve for any stretch.
- bool InitializeLineCableModels() const;
-
/// \brief Determines if class is updated.
/// \return A boolean indicating if class is updated.
- bool IsUpdated() const;
-
- /// \brief Calculates the unit load of the catenary.
- /// \param[in] weathercase
- /// The weather case.
- /// \return The unit loading of the cable.
- Vector3d UnitLoad(const WeatherLoadCase& weathercase) const;
+ virtual bool IsUpdated() const;
/// \brief Updates cached member variables and modifies control variables if
/// update is required.
/// \return A boolean indicating if class updates completed successfully.
- bool Update() const;
-
- /// \brief Updates the constraint cable model.
- /// \return The success status of the update.
- /// This function further updates the constraint cable model to include any
- /// stretch.
- bool UpdateConstraintCableModel() const;
-
- /// \brief Updates the constraint catenary.
- /// \return The success status of the update.
- bool UpdateConstraintCatenary() const;
-
- /// \brief Updates the stretch due to load and creep.
- /// \return The success status of the update.
- bool UpdateLoadStretch() const;
+ virtual bool Update() const;
/// \brief Updates the reloaded cable model.
/// \return The success status of the update.
@@ -163,14 +98,6 @@ class LineCableReloader {
/// \return The success status of the update.
bool UpdateReloadedCatenary() const;
- /// \var cable_sagtension_
- /// The cable, which is referenced for sag-tension methods.
- SagTensionCable cable_sagtension_;
-
- /// \var catenary_constraint_
- /// The catenary for the line cable constraint.
- mutable Catenary3d catenary_constraint_;
-
/// \var catenary_reloaded_
/// The catenary that is reloaded.
mutable Catenary3d catenary_reloaded_;
@@ -179,51 +106,19 @@ class LineCableReloader {
/// The condition of the cable when loaded at the query load case.
CableConditionType condition_reloaded_;
- /// \var is_updated_catenary_constraint_
- /// An indicator that tells if the constraint catenary cable is updated.
- mutable bool is_updated_catenary_constraint_;
-
/// \var is_updated_catenary_reloaded_
- /// An indicator that tells if the query catenary cable is updated.
+ /// An indicator that tells if the reloaded catenary is updated.
mutable bool is_updated_catenary_reloaded_;
- /// \var is_updated_stretch_
- /// An indicator that tells if the stretch load is updated.
- mutable bool is_updated_stretch_;
-
- /// \var line_cable_
- /// The line cable that is being reloaded.
- const LineCable* line_cable_;
-
- /// \var model_constraint_
- /// The cable model for the constraint weathercase. This model may contain
- /// stretch, depending on the constraint condition.
- mutable CableElongationModel model_constraint_;
-
- /// \var model_creep_
- /// The cable model used for solving creep stretch. This model will always
- /// contain zero stretch to ensure that only the polynomial is referenced.
- mutable CableElongationModel model_creep_;
-
- /// \var model_load_
- /// The cable model used for solving heavy load stretch. This model will
- /// always contain zero stretch to ensure that only the polynomial is
- /// referenced.
- mutable CableElongationModel model_load_;
+ /// \var is_updated_model_reloaded_
+ /// An indicator that tells if the reloaded cable model is updated.
+ mutable bool is_updated_model_reloaded_;
/// \var model_reloaded_
/// The cable model for the reloaded weathercase. This model may contain
/// stretch, depending on the reloaded condition.
mutable CableElongationModel model_reloaded_;
- /// \var state_stretch_creep_
- /// The stretch state for the creep condition.
- mutable CableStretchState state_stretch_creep_;
-
- /// \var state_stretch_load_;
- /// The stretch state for the load condition.
- mutable CableStretchState state_stretch_load_;
-
/// \var weathercase_reloaded_
/// The load case that the cable is being reloaded to.
const WeatherLoadCase* weathercase_reloaded_;
diff --git a/include/models/sagtension/line_cable_unloader.h b/include/models/sagtension/line_cable_unloader.h
new file mode 100644
index 0000000..767c6fb
--- /dev/null
+++ b/include/models/sagtension/line_cable_unloader.h
@@ -0,0 +1,118 @@
+// This is free and unencumbered software released into the public domain.
+// For more information, please refer to
+
+#ifndef OTLS_MODELS_SAGTENSION_LINECABLEUNLOADER_H_
+#define OTLS_MODELS_SAGTENSION_LINECABLEUNLOADER_H_
+
+#include
+
+#include "models/base/error_message.h"
+#include "models/sagtension/line_cable_loader_base.h"
+
+/// \par OVERVIEW
+///
+/// This class unloads a line cable at a specific condition and temperature.
+/// The process is as follows:
+/// - set up the line cable for sag-tension analysis (see LineCableLoaderBase)
+/// - build a cable model for the unloaded state
+/// - unload the constraint catenary to the unloaded state
+/// (see CatenaryCableUnloader)
+class LineCableUnloader : public LineCableLoaderBase {
+ public:
+ /// \brief Default constructor.
+ LineCableUnloader();
+
+ /// \brief Destructor.
+ ~LineCableUnloader();
+
+ /// \brief Gets the unloaded length.
+ /// \return The unloaded length.
+ double LengthUnloaded() const;
+
+ /// \brief Validates member variables.
+ /// \param[in] is_included_warnings
+ /// A flag that tightens the acceptable value range.
+ /// \param[in,out] messages
+ /// A list of detailed error messages. If this is provided, any validation
+ /// errors will be appended to the list.
+ /// \return A boolean value indicating status of member variables.
+ bool Validate(const bool& is_included_warnings = true,
+ std::list* messages = nullptr) const;
+
+ /// \brief Gets the unloaded cable condition.
+ /// \return The unloaded cable condition.
+ CableConditionType condition_unloaded() const;
+
+ /// \brief Sets the unloaded cable condition.
+ /// \param[in] condition_unloaded
+ /// The unloaded cable condition.
+ void set_condition_unloaded(const CableConditionType& condition_unloaded);
+
+ /// \brief Sets the attachment spacing.
+ /// \param[in] spacing_attachments
+ /// The attachment spacing
+ void set_spacing_attachments(const Vector3d& spacing_attachments);
+
+ /// \brief Sets the unloaded temperature.
+ /// \param[in] temperature_unloaded
+ /// The unloaded temperature.
+ void set_temperature_unloaded(const double& temperature_unloaded);
+
+ /// \brief Gets the attachment spacing.
+ /// \return The attachment spacing.
+ Vector3d spacing_attachments() const;
+
+ /// \brief Gets the unloaded temperature.
+ /// \return The unloaded temperature.
+ double temperature_unloaded() const;
+
+ private:
+ /// \brief Determines if class is updated.
+ /// \return A boolean indicating if class is updated.
+ virtual bool IsUpdated() const;
+
+ /// \brief Updates cached member variables and modifies control variables if
+ /// update is required.
+ /// \return A boolean indicating if class updates completed successfully.
+ virtual bool Update() const;
+
+ /// \brief Updates the unloaded cable model.
+ /// \return The success status of the update.
+ bool UpdateUnloadedCableModel() const;
+
+ /// \brief Updates the unloaded length.
+ /// \return The success status of the update.
+ bool UpdateUnloadedLength() const;
+
+ /// \var condition_unloaded_
+ /// The condition of the cable when unloaded.
+ CableConditionType condition_unloaded_;
+
+ /// \var is_updated_length_unloaded_
+ /// An indicator that tells if the unloaded cable length is updated.
+ mutable bool is_updated_length_unloaded_;
+
+ /// \var is_updated_model_unloaded_
+ /// An indicator that tells if the unloaded cable model is updated.
+ mutable bool is_updated_model_unloaded_;
+
+ /// \var length_unloaded_
+ /// The unloaded cable length.
+ mutable double length_unloaded_;
+
+ /// \var model_unloaded_
+ /// The cable model for the unloaded state. This model may contain stretch,
+ /// depending on the unloaded condition.
+ mutable CableElongationModel model_unloaded_;
+
+ /// \var spacing_attachments_
+ /// The spacing of the span attachments. The coordinates follows the
+ /// Catenary3d coordinate system.
+ Vector3d spacing_attachments_;
+
+ /// \var temperature_unloaded_
+ /// The temperature that the cable is being unloaded to.
+ double temperature_unloaded_;
+};
+
+#endif // OTLS_MODELS_SAGTENSION_LINECABLEUNLOADER_H_
diff --git a/include/models/thermalrating/cable_heat_transfer_state.h b/include/models/thermalrating/cable_heat_transfer_state.h
index 6f4e4b3..9b7939a 100644
--- a/include/models/thermalrating/cable_heat_transfer_state.h
+++ b/include/models/thermalrating/cable_heat_transfer_state.h
@@ -51,7 +51,7 @@ struct CableHeatTransferState {
/// The heat transfer due to solar. This should always be positive.
double heat_solar;
- /// \var heat_stored
+ /// \var heat_storage
/// The heat transfer rate to/from the cable material (thermal storage).
/// This can either be positive or negative.
double heat_storage;
diff --git a/include/models/thermalrating/solar_radiation_solver.h b/include/models/thermalrating/solar_radiation_solver.h
index 4490622..a401c6c 100644
--- a/include/models/thermalrating/solar_radiation_solver.h
+++ b/include/models/thermalrating/solar_radiation_solver.h
@@ -217,7 +217,7 @@ class SolarRadiationSolver {
/// x = solar altitude, y = solar radiation
mutable std::vector coefficients_atmosphere_;
- /// \var coefficients_altitude_
+ /// \var coefficients_elevation_
/// The polynomial coefficients used to correct radiation based on
/// elevation.
/// x = elevation, y = solar radiation correction factor
diff --git a/include/models/thermalrating/transient_cable_temperature_solver.h b/include/models/thermalrating/transient_cable_temperature_solver.h
index 575b818..162ae5a 100644
--- a/include/models/thermalrating/transient_cable_temperature_solver.h
+++ b/include/models/thermalrating/transient_cable_temperature_solver.h
@@ -102,13 +102,13 @@ class TransientCableTemperatureSolver {
void set_cable(const ThermalRatingCable* cable);
/// \brief Sets the steady-state current.
- /// \param[in] current
- /// The electrical current.
+ /// \param[in] current_steady
+ /// The steady-state electrical current.
void set_current_steady(const double& current_steady);
/// \brief Sets the step current.
- /// \param[in] current
- /// The electrical current.
+ /// \param[in] current_step
+ /// The electrical current to step to.
void set_current_step(const double& current_step);
/// \brief Sets the time duration.
@@ -187,7 +187,7 @@ class TransientCableTemperatureSolver {
/// The current to step to.
double current_step_;
- /// \var duration
+ /// \var duration_
/// The time duration.
int duration_;
@@ -199,7 +199,7 @@ class TransientCableTemperatureSolver {
/// The calculated temperature points.
mutable std::list points_temperature_;
- /// \var solver_heat_
+ /// \var solver_
/// The heat transfer solver.
mutable CableHeatTransferSolver solver_;
diff --git a/include/models/transmissionline/cable_unit_load_calculator.h b/include/models/transmissionline/cable_unit_load_solver.h
similarity index 89%
rename from include/models/transmissionline/cable_unit_load_calculator.h
rename to include/models/transmissionline/cable_unit_load_solver.h
index c3098ea..424d5e6 100644
--- a/include/models/transmissionline/cable_unit_load_calculator.h
+++ b/include/models/transmissionline/cable_unit_load_solver.h
@@ -1,8 +1,8 @@
// This is free and unencumbered software released into the public domain.
// For more information, please refer to
-#ifndef OTLS_MODELS_TRANSMISSIONLINE_CABLEUNITLOADCALCULATOR_H_
-#define OTLS_MODELS_TRANSMISSIONLINE_CABLEUNITLOADCALCULATOR_H_
+#ifndef OTLS_MODELS_TRANSMISSIONLINE_CABLEUNITLOADSOLVER_H_
+#define OTLS_MODELS_TRANSMISSIONLINE_CABLEUNITLOADSOLVER_H_
#include
@@ -22,13 +22,13 @@
///
/// - uniform loading (constat wind speed, equal ice accumulation)
/// - drag coefficient is 1.0 (no aerodynamic effects)
-class CableUnitLoadCalculator {
+class CableUnitLoadSolver {
public:
/// \brief Default constructor.
- CableUnitLoadCalculator();
+ CableUnitLoadSolver();
/// \brief Destructor.
- ~CableUnitLoadCalculator();
+ ~CableUnitLoadSolver();
/// \brief Gets the load per unit length of cable.
/// \param[in] case_load_weather
@@ -77,4 +77,4 @@ class CableUnitLoadCalculator {
const double* weight_unit_cable_;
};
-#endif // OTLS_MODELS_TRANSMISSIONLINE_CABLEUNITLOADCALCULATOR_H_
+#endif // OTLS_MODELS_TRANSMISSIONLINE_CABLEUNITLOADSOLVER_H_
diff --git a/include/models/transmissionline/catenary.h b/include/models/transmissionline/catenary.h
index f0cdeda..d19c727 100644
--- a/include/models/transmissionline/catenary.h
+++ b/include/models/transmissionline/catenary.h
@@ -98,6 +98,14 @@ class Catenary2d {
/// the sag point.
double Sag() const;
+ /// \brief Gets the sag at a specific point.
+ /// \param[in] position_fraction
+ /// A decimal ranging from 0 and 1 that describes position on the curve by
+ /// the fraction of curve length from the left end point.
+ /// \return The vertical distance between the straight line and the catenary
+ /// the position.
+ double Sag(const double& position_fraction) const;
+
/// \brief Gets a tangent angle from the horizontal axis to the curve tangent
/// line.
/// \param[in] position_fraction
@@ -347,6 +355,14 @@ class Catenary3d {
/// the sag point.
double Sag() const;
+ /// \brief Gets the sag at a specific point.
+ /// \param[in] position_fraction
+ /// A decimal ranging from 0 and 1 that describes position on the curve by
+ /// the fraction of curve length from the left end point.
+ /// \return The distance between the straight line and the catenary the
+ /// position.
+ double Sag(const double& position_fraction) const;
+
/// \brief Gets the swing angle of the catenary due to transverse loading.
/// \return The swing angle, which is referenced from the vertical plane.
double SwingAngle() const;
diff --git a/include/models/transmissionline/catenary_solver.h b/include/models/transmissionline/catenary_solver.h
index c5b2039..0b24241 100644
--- a/include/models/transmissionline/catenary_solver.h
+++ b/include/models/transmissionline/catenary_solver.h
@@ -14,8 +14,26 @@
/// \par OVERVIEW
///
/// This class solves for a catenary.
+///
+/// \par HORIZONTAL TENSION
+///
+/// This is the typical value that is solved for. The remaining catenary parameters
+/// must be known, as well as a specific target type.
+///
+/// The horizontal tension is often solved numerically.
class CatenarySolver {
public:
+ /// \par OVERVIEW
+ ///
+ /// This enum contains types of CatenarySolver targets.
+ enum class TargetType {
+ kConstant,
+ kLength,
+ kNull,
+ kSag,
+ kTension
+ };
+
/// \brief Default constructor.
CatenarySolver();
@@ -23,8 +41,13 @@ class CatenarySolver {
~CatenarySolver();
/// \brief Gets the catenary.
+ /// \return The catenary.
Catenary3d Catenary() const;
+ /// \brief Gets the catenary horizontal tension.
+ /// \return The catenary horizontal tension.
+ double TensionHorizontal() const;
+
/// \brief Validates member variables.
/// \param[in] is_included_warnings
/// A flag that tightens the acceptable value range.
@@ -35,42 +58,57 @@ class CatenarySolver {
bool Validate(const bool& is_included_warnings = true,
std::list* messages = nullptr) const;
- /// \brief Gets the cable.
- /// \return The cable.
- const Cable* cable() const;
+ /// \brief Gets the target position.
+ /// \return The target position.
+ double position_target() const;
+
+ /// \brief Sets the target position.
+ /// \param[in] position
+ /// The catenary position. If the target type applies to the entire curve,
+ /// and not just a specific point, leave this to the default value.
+ void set_position_target(const double& position = -1);
- /// \brief Gets the constraint.
- /// \return The constraint.
- const CableConstraint* constraint() const;
+ /// \brief Sets the end point spacing.
+ /// \param[in] spacing_endpoints
+ /// The endpoint spacing.
+ void set_spacing_endpoints(const Vector3d& spacing_endpoints);
- /// \brief Sets the cable.
- /// \param[in] cable
- /// The cable.
- void set_cable(const Cable* cable);
+ /// \brief Sets the target type.
+ /// \param[in] type
+ /// The target type.
+ void set_type_target(const TargetType& type);
- /// \brief Gets the constraint.
- /// \param[in] constraint
- /// The constraint.
- void set_constraint(const CableConstraint* constraint);
+ /// \brief Sets the target value.
+ /// \param[in] value
+ /// The target value.
+ void set_value_target(const double& value);
- /// \brief Sets the attachment spacing.
- /// \param[in] spacing_attachments
- void set_spacing_attachments(const Vector3d* spacing_attachments);
+ /// \brief Sets the unit weight.
+ /// \param[in] weight_unit
+ /// The unit weight.
+ void set_weight_unit(const Vector3d& weight_unit);
- /// \brief Gets the attachment spacing.
- /// \return The attachment spacing.
- const Vector3d* spacing_attachments() const;
+ /// \brief Gets the end point spacing.
+ /// \return The end point spacing.
+ const Vector3d spacing_endpoints() const;
+
+ /// \brief Gets the target type.
+ /// \return The target type.
+ TargetType type_target() const;
+
+ /// \brief Gets the target value.
+ /// \return The target value.
+ double value_target() const;
+
+ /// \brief Gets the unit weight.
+ /// \return The unit weight.
+ const Vector3d weight_unit() const;
private:
/// \brief Determines if class is updated.
/// \return A boolean indicating if class is updated.
bool IsUpdated() const;
- /// \brief Updates cached member variables and modifies control variables if
- /// update is required.
- /// \return A boolean indicating if class updates completed successfully.
- bool Update() const;
-
/// \brief Solves and updates catenary horizontal tension by converting from
/// the catenary constant.
/// \return A boolean indicating the success status of the update.
@@ -82,18 +120,19 @@ class CatenarySolver {
bool SolveHorizontalTensionFromLength() const;
/// \brief Solves and updates catenary horizontal tension by converting from
- /// sag.
+ /// sag at a specific position on the catenary.
/// \return A boolean indicating the success status of the update.
bool SolveHorizontalTensionFromSag() const;
/// \brief Solves and updates catenary horizontal tension by converting from
- /// support tension.
+ /// a tension at a specific position on the catenary.
/// \return A boolean indicating the success status of the update.
- bool SolveHorizontalTensionFromSupportTension() const;
+ bool SolveHorizontalTensionFromTension() const;
- /// \brief Solves and updates the catenary unit weight.
- /// \return A boolean indicating the success status of the update.
- bool SolveWeightUnit() const;
+ /// \brief Updates cached member variables and modifies control variables if
+ /// update is required.
+ /// \return A boolean indicating if class updates completed successfully.
+ bool Update() const;
/// \brief Updates catenary horizontal tension and calculates new length.
/// \param[in] tension_horizontal
@@ -102,38 +141,47 @@ class CatenarySolver {
/// catenary.
double UpdateCatenaryLength(const double& tension_horizontal) const;
- /// \brief Updates catenary tension and calculates new support tension.
+ /// \brief Updates catenary horizontal tension and calculates new sag at the
+ /// specified position.
/// \param[in] tension_horizontal
/// The new horizontal tension for the catenary.
- /// \return The support tension correlating to the new horizontal tension of
- /// the catenary.
- double UpdateCatenaryMaxTension(const double& tension_horizontal) const;
+ /// \param[in] position_fraction
+ /// The position fraction to calculate the catenary tension at.
+ /// \return The sag correlating to the new horizontal tension of the catenary.
+ double UpdateCatenarySag(const double& tension_horizontal,
+ const double& position_fraction) const;
- /// \brief Updates catenary horizontal tension and calculates new sag.
+ /// \brief Updates catenary horizontal tension and calculates new tension at
+ /// the specified position.
/// \param[in] tension_horizontal
/// The new horizontal tension for the catenary.
- /// \return The sag correlating to the new horizontal tension of the catenary.
- double UpdateCatenarySag(const double& tension_horizontal) const;
-
- /// \var cable_
- /// The cable.
- const Cable* cable_;
+ /// \param[in] position_fraction
+ /// The position fraction to calculate the catenary tension at.
+ /// \return The tension correlating to the new horizontal tension of the
+ /// catenary.
+ double UpdateCatenaryTension(const double& tension_horizontal,
+ const double& position_fraction) const;
/// \var catenary_
/// The catenary being solved for.
mutable Catenary3d catenary_;
- /// \var constraint_
- /// The constraint.
- const CableConstraint* constraint_;
+ /// \var is_updated_
+ /// An indicator that tells if the class is updated.
+ mutable bool is_updated_;
+
+ /// \var position_target_
+ /// The target position fraction along the catenary curve. If the position
+ /// isn't needed, set to -1.
+ double position_target_;
- /// \var is_updated_catenary_
- /// An indicator that tells if the catenary is updated.
- mutable bool is_updated_catenary_;
+ /// \var type_target_
+ /// The target type.
+ TargetType type_target_;
- /// \var spacing_attachments_
- /// The attachment spacing for the catenary.
- const Vector3d* spacing_attachments_;
+ /// \var value_target_
+ /// The target value.
+ double value_target_;
};
#endif // OTLS_MODELS_TRANSMISSIONLINE_CATENARYSOLVER_H_
diff --git a/include/models/transmissionline/line_cable.h b/include/models/transmissionline/line_cable.h
index 0f72c6d..af9e308 100644
--- a/include/models/transmissionline/line_cable.h
+++ b/include/models/transmissionline/line_cable.h
@@ -10,6 +10,7 @@
#include "models/base/vector.h"
#include "models/transmissionline/cable.h"
#include "models/transmissionline/cable_constraint.h"
+#include "models/transmissionline/catenary.h"
class LineStructure;
@@ -54,6 +55,10 @@ class LineCable {
/// connection to the line cable fails, -1 will be returned.
int AddConnection(const LineCableConnection& connection);
+ /// \brief Gets a catenary based on the constraint and ruling span geometry.
+ /// \return A catenary based on the constraint and ruling span geometry.
+ Catenary3d CatenaryRulingSpan() const;
+
/// \brief Clears all connections.
void ClearConnections();
diff --git a/src/base/geometric_shapes.cc b/src/base/geometric_shapes.cc
index 8d2c687..d16474e 100644
--- a/src/base/geometric_shapes.cc
+++ b/src/base/geometric_shapes.cc
@@ -15,7 +15,7 @@ Cylinder::Cylinder() {
Cylinder::~Cylinder() {}
double Cylinder::AreaCrossSection() const {
- return (units::kPi / 4) * pow(diameter_, 2);
+ return (units::kPi / 4) * std::pow(diameter_, 2);
}
bool Cylinder::Validate(const bool& is_included_warnings,
diff --git a/src/base/helper.cc b/src/base/helper.cc
index c292567..b04a461 100644
--- a/src/base/helper.cc
+++ b/src/base/helper.cc
@@ -68,7 +68,7 @@ std::list Parse(const std::string& str,
}
double Round(const double& number, const int& precision) {
- return std::round(number * pow(10, precision)) / pow(10, precision);
+ return std::round(number * std::pow(10, precision)) / std::pow(10, precision);
}
} // namespace helper
diff --git a/src/base/polynomial.cc b/src/base/polynomial.cc
index 4d5b400..2ddb9c3 100644
--- a/src/base/polynomial.cc
+++ b/src/base/polynomial.cc
@@ -94,7 +94,7 @@ double Polynomial::X(const double& y, const int& decimal_precision_y,
}
// converts to decimal precision
- const double precision_y = 1 / pow(10, decimal_precision_y);
+ const double precision_y = 1 / std::pow(10, decimal_precision_y);
// gets a shifted polynomial so that y value is on x-axis
std::vector coefficients = *coefficients_;
@@ -135,7 +135,7 @@ double Polynomial::Y(const double& x) const {
for (int order = 0; order <= order_max; order++) {
const double& coefficient = coefficients_->at(order);
- y = y + (coefficient * pow(x, order));
+ y = y + (coefficient * std::pow(x, order));
}
return y;
diff --git a/src/base/units.cc b/src/base/units.cc
index ded928d..177b458 100644
--- a/src/base/units.cc
+++ b/src/base/units.cc
@@ -59,7 +59,7 @@ double Convert(const double& value,
const double& exponent,
const bool& is_numerator) {
// adjusts the factor based on the exponent
- double factor_adj = pow(factor, exponent);
+ double factor_adj = std::pow(factor, exponent);
// inverts factor if unit value is not in the numerator
if (is_numerator == false) {
diff --git a/src/base/vector.cc b/src/base/vector.cc
index d722ab7..7f31e5d 100644
--- a/src/base/vector.cc
+++ b/src/base/vector.cc
@@ -60,21 +60,21 @@ double Vector2d::Angle(const bool& is_enabled_negative_angles) const {
if (0 <= x_) { // quadrant I
angle = units::ConvertAngle(
- atan(y_ / x_),
+ std::atan(y_ / x_),
units::AngleConversionType::kRadiansToDegrees);
} else { // quadrant II
angle = 180 - units::ConvertAngle(
- std::abs(atan(y_ / x_)),
+ std::abs(std::atan(y_ / x_)),
units::AngleConversionType::kRadiansToDegrees);
}
} else {
if (x_ <= 0) { // quadrant III
angle = 180 + units::ConvertAngle(
- std::abs(atan(y_ / x_)),
+ std::abs(std::atan(y_ / x_)),
units::AngleConversionType::kRadiansToDegrees);
} else { // quadrant IV
angle = 360 - units::ConvertAngle(
- std::abs(atan(y_ / x_)),
+ std::abs(std::atan(y_ / x_)),
units::AngleConversionType::kRadiansToDegrees);
}
}
@@ -89,7 +89,7 @@ double Vector2d::Angle(const bool& is_enabled_negative_angles) const {
}
double Vector2d::Magnitude() const {
- return sqrt( pow(x_, 2) + pow(y_, 2) );
+ return sqrt(std::pow(x_, 2) + std::pow(y_, 2));
}
/// Converts the vector into the radial coordinate system (magnitude and angle)
@@ -111,8 +111,8 @@ void Vector2d::Rotate(const double& angle_rotation) {
const double angle_radians =
units::ConvertAngle(angle_new,
units::AngleConversionType::kDegreesToRadians);
- x_ = magnitude * cos(angle_radians);
- y_ = magnitude * sin(angle_radians);
+ x_ = magnitude * std::cos(angle_radians);
+ y_ = magnitude * std::sin(angle_radians);
}
void Vector2d::Scale(const double& factor_scale) {
@@ -185,7 +185,7 @@ double Vector3d::Angle(const Plane2dType& plane,
}
double Vector3d::Magnitude() const {
- return sqrt( pow(x_, 2) + pow(y_, 2) + pow(z_, 2) );
+ return sqrt(std::pow(x_, 2) + std::pow(y_, 2) + std::pow(z_, 2));
}
/// The planar vector components are assigned to a 2D vector. The rotation is
diff --git a/src/sagtension/cable_elongation_model.cc b/src/sagtension/cable_elongation_model.cc
index c35b6a3..e41c724 100644
--- a/src/sagtension/cable_elongation_model.cc
+++ b/src/sagtension/cable_elongation_model.cc
@@ -351,7 +351,7 @@ double CableElongationModel::StrainCombined(
// declares iteration variables
// iterates until current point load matches target load
int iter = 1;
- double precision = 1 / pow(10, precision_decimal_load);
+ double precision = 1 / std::pow(10, precision_decimal_load);
double slope_line =-999999;
while ((precision < std::abs(point_current.y - load)) && (iter < 100)) {
diff --git a/src/sagtension/line_cable_loader_base.cc b/src/sagtension/line_cable_loader_base.cc
new file mode 100644
index 0000000..788c734
--- /dev/null
+++ b/src/sagtension/line_cable_loader_base.cc
@@ -0,0 +1,418 @@
+// This is free and unencumbered software released into the public domain.
+// For more information, please refer to
+
+#include "models/sagtension/line_cable_loader_base.h"
+
+#include
+
+#include "models/sagtension/catenary_cable_reloader.h"
+#include "models/transmissionline/cable_unit_load_solver.h"
+
+LineCableLoaderBase::LineCableLoaderBase() {
+ line_cable_ = nullptr;
+
+ is_updated_catenary_constraint_ = false;
+ is_updated_stretch_ = false;
+}
+
+LineCableLoaderBase::~LineCableLoaderBase() {
+}
+
+CableStretchState LineCableLoaderBase::StretchStateCreep() const {
+ // updates class if necessary
+ if (IsUpdated() == false) {
+ if (Update() == false) {
+ return CableStretchState();
+ }
+ }
+
+ return state_stretch_creep_;
+}
+
+CableStretchState LineCableLoaderBase::StretchStateLoad() const {
+ // updates class if necessary
+ if (IsUpdated() == false) {
+ if (Update() == false) {
+ return CableStretchState();
+ }
+ }
+
+ return state_stretch_load_;
+}
+
+bool LineCableLoaderBase::Validate(
+ const bool& is_included_warnings,
+ std::list* messages) const {
+ // initializes
+ bool is_valid = true;
+ ErrorMessage message;
+ message.title = "LINE CABLE LOADER BASE";
+
+ // validates cable-sagtension
+ if (cable_sagtension_.Validate(is_included_warnings, messages) == false) {
+ is_valid = false;
+ if (messages != nullptr) {
+ message.description = "Invalid sag-tension cable";
+ messages->push_back(message);
+ }
+ }
+
+ // validates line cable
+ if (line_cable_ == nullptr) {
+ is_valid = false;
+ if (messages != nullptr) {
+ message.description = "Invalid line cable";
+ messages->push_back(message);
+ }
+ } else {
+ if (line_cable_->Validate(is_included_warnings, messages) == false) {
+ is_valid = false;
+ }
+ }
+
+ // returns if errors are present
+ if (is_valid == false) {
+ return is_valid;
+ }
+
+ // validates update process
+ if (Update() == false) {
+ is_valid = false;
+ if (messages != nullptr) {
+ message.description = "";
+ if (is_updated_catenary_constraint_ == false) {
+ message.description = "Error updating class. Could not solve for "
+ "constraint catenary.";
+ } else if (is_updated_stretch_ == false) {
+ message.description = "Error updating class. Could not solve for "
+ "creep or load based stretch.";
+ }
+ messages->push_back(message);
+ }
+ }
+
+ return is_valid;
+}
+
+const LineCable* LineCableLoaderBase::line_cable() const {
+ return line_cable_;
+}
+
+void LineCableLoaderBase::set_line_cable(const LineCable* line_cable) {
+ line_cable_ = line_cable;
+
+ // updates sag-tension cable
+ if (line_cable == nullptr) {
+ cable_sagtension_.set_cable_base(nullptr);
+ } else {
+ cable_sagtension_.set_cable_base(line_cable_->cable());
+ }
+
+ is_updated_catenary_constraint_ = false;
+ is_updated_stretch_ = false;
+}
+
+bool LineCableLoaderBase::InitializeLineCableModels() const {
+ // declares working variable
+ // all models are initialized with zero stretch
+ CableState state;
+
+ CableStretchState state_stretch;
+ state_stretch.load = 0;
+
+ // initializes the constraint cable model
+ CableConstraint constraint = line_cable_->constraint();
+ state.temperature = constraint.case_weather->temperature_cable;
+ state.type_polynomial = SagTensionCableComponent::PolynomialType::kLoadStrain;
+
+ if (constraint.condition == CableConditionType::kInitial) {
+ state_stretch.temperature = 0; // doesn't matter, model is never stretched
+ state_stretch.type_polynomial =
+ SagTensionCableComponent::PolynomialType::kLoadStrain;
+ } else if (constraint.condition == CableConditionType::kCreep) {
+ state_stretch.temperature =
+ line_cable_->weathercase_stretch_creep()->temperature_cable;
+ state_stretch.type_polynomial =
+ SagTensionCableComponent::PolynomialType::kCreep;
+ } else if (constraint.condition == CableConditionType::kLoad) {
+ state_stretch.temperature =
+ line_cable_->weathercase_stretch_load()->temperature_cable;
+ state_stretch.type_polynomial =
+ SagTensionCableComponent::PolynomialType::kLoadStrain;
+ } else {
+ return false;
+ }
+
+ model_constraint_.set_cable(&cable_sagtension_);
+ model_constraint_.set_state(state);
+ model_constraint_.set_state_stretch(state_stretch);
+
+ // updates the creep stretch model
+ state.temperature =
+ line_cable_->weathercase_stretch_creep()->temperature_cable;
+ state.type_polynomial = SagTensionCableComponent::PolynomialType::kCreep;
+
+ state_stretch.temperature = state.temperature;
+ state_stretch.type_polynomial =
+ SagTensionCableComponent::PolynomialType::kCreep;
+
+ model_creep_.set_cable(&cable_sagtension_);
+ model_creep_.set_state(state);
+ model_creep_.set_state_stretch(state_stretch);
+
+ // updates the load stretch model
+ state.temperature =
+ line_cable_->weathercase_stretch_load()->temperature_cable;
+ state.type_polynomial = SagTensionCableComponent::PolynomialType::kLoadStrain;
+
+ state_stretch.temperature = state.temperature;
+ state_stretch.type_polynomial =
+ SagTensionCableComponent::PolynomialType::kLoadStrain;
+
+ model_load_.set_cable(&cable_sagtension_);
+ model_load_.set_state(state);
+ model_load_.set_state_stretch(state_stretch);
+
+ return true;
+}
+
+bool LineCableLoaderBase::IsUpdated() const {
+ if ((is_updated_catenary_constraint_ == true)
+ && (is_updated_stretch_ == true)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Vector3d LineCableLoaderBase::UnitLoad(
+ const WeatherLoadCase& weathercase) const {
+ CableUnitLoadSolver solver;
+ solver.set_diameter_cable(&line_cable_->cable()->diameter);
+ solver.set_weight_unit_cable(&line_cable_->cable()->weight_unit);
+
+ return solver.UnitCableLoad(weathercase);
+}
+
+bool LineCableLoaderBase::Update() const {
+ // updates constraint catenary
+ is_updated_catenary_constraint_ = UpdateConstraintCatenary();
+ if (is_updated_catenary_constraint_ == false) {
+ return false;
+ }
+
+ InitializeLineCableModels();
+
+ is_updated_catenary_constraint_ = UpdateConstraintCableModel();
+ if (is_updated_catenary_constraint_ == false) {
+ return false;
+ }
+
+ // updates load-stretch
+ is_updated_stretch_ = UpdateLoadStretch();
+ if (is_updated_stretch_ == false) {
+ return false;
+ }
+
+ // if it reaches this point, update was successful
+ return true;
+}
+
+/// This function checks the condition of the line cable constraint, and
+/// determines if stretch is necessary to solve for. Solving for the stretch
+/// requires an iterative approach. The line cable is reloaded from the
+/// constraint cable model to the stretch cable model and loading. The solution
+/// is found when the stretch load in the constraint cable model matches the
+/// reloaded catenary average tension (which is reloaded at the stretch cable
+/// model).
+bool LineCableLoaderBase::UpdateConstraintCableModel() const {
+ // checks if no stretch is defined (initial modulus)
+ // constraint cable model was already initialized with zero stretch
+ if (line_cable_->constraint().condition == CableConditionType::kInitial) {
+ return true;
+ }
+
+ // x = stretch load
+ // y = stretch load difference
+ // i.e.(reloaded catenary avg tension - constraint model stretch load)
+
+ // iterative routine to determine solution
+ // solution reached when y = 0
+ const double target_solution = 0;
+
+ // initializes the stretch state
+ CableStretchState state_stretch = model_constraint_.state_stretch();
+
+ // initializes the reloader
+ Vector3d weight_unit_reloaded;
+ CatenaryCableReloader reloader;
+ reloader.set_catenary(&catenary_constraint_);
+ reloader.set_model_reference(&model_constraint_);
+
+ if (line_cable_->constraint().condition == CableConditionType::kCreep) {
+ weight_unit_reloaded = UnitLoad(*line_cable_->weathercase_stretch_creep());
+
+ reloader.set_model_reloaded(&model_creep_);
+ reloader.set_weight_unit_reloaded(&weight_unit_reloaded);
+ } else if (line_cable_->constraint().condition == CableConditionType::kLoad) {
+ weight_unit_reloaded = UnitLoad(*line_cable_->weathercase_stretch_load());
+
+ reloader.set_model_reloaded(&model_load_);
+ reloader.set_weight_unit_reloaded(&weight_unit_reloaded);
+ } else {
+ // condition isn't recognized
+ return false;
+ }
+
+ // initializes left point
+ Point2d point_left;
+ point_left.x = 0;
+ point_left.y = reloader.CatenaryReloaded().TensionAverage()
+ - state_stretch.load;
+
+ // initializes right point
+ Point2d point_right;
+ point_right.x = *cable_sagtension_.strength_rated();
+
+ state_stretch.load = point_right.x;
+ model_constraint_.set_state_stretch(state_stretch);
+ reloader.set_model_reference(&model_constraint_);
+
+ point_right.y = reloader.CatenaryReloaded().TensionAverage()
+ - state_stretch.load;
+
+ // initializes current point
+ Point2d point_current;
+
+ // iterates until target solution is reached
+ unsigned int iter = 1;
+ const int iter_max = 100;
+ const double precision = 0.01;
+ double slope_line = -999999;
+
+ while ((precision < std::abs(point_current.y - target_solution))
+ && (iter < iter_max)) {
+
+ // solves for new stretch value is calculated for current point
+ slope_line = (point_right.y - point_left.y)
+ / (point_right.x - point_left.x);
+ point_current.x = point_left.x
+ + ((target_solution - point_left.y) / slope_line);
+
+ // updates constraint model and reloader
+ state_stretch.load = point_current.x;
+ model_constraint_.set_state_stretch(state_stretch);
+ reloader.set_model_reference(&model_constraint_);
+
+ // solves for new horizontal tension value for current point
+ point_current.y = reloader.CatenaryReloaded().TensionAverage()
+ - state_stretch.load;
+
+ // current point is left of left/right points
+ if (point_current.x < point_left.x) {
+
+ point_right.x = point_left.x;
+ point_right.y = point_left.y;
+ point_left.x = point_current.x;
+ point_left.y = point_current.y;
+
+ // current point is between left/right points
+ } else if ((point_left.x <= point_current.x)
+ && (point_current.x <= point_right.x)) {
+
+ if (point_current.y < target_solution) {
+ point_right.x = point_current.x;
+ point_right.y = point_current.y;
+ } else if (target_solution < point_current.y) {
+ point_left.x = point_current.x;
+ point_left.y = point_current.y;
+ }
+
+ // current point is right of left/right points
+ } else if (point_right.x < point_current.x) {
+
+ point_left.x = point_right.x;
+ point_left.y = point_right.y;
+ point_right.x = point_current.x;
+ point_right.y = point_current.y;
+ }
+
+ iter++;
+ }
+
+ // returns success status
+ if (iter < iter_max) {
+ return true;
+ } else {
+ // re-initializes constraint model stretch
+ state_stretch.load = 0;
+ model_constraint_.set_state_stretch(state_stretch);
+ return false;
+ }
+}
+
+bool LineCableLoaderBase::UpdateConstraintCatenary() const {
+ Catenary3d catenary = line_cable_->CatenaryRulingSpan();
+ if (catenary.Validate() == true) {
+ catenary_constraint_ = catenary;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool LineCableLoaderBase::UpdateLoadStretch() const {
+ // initializes working variables
+ CatenaryCableReloader reloader;
+ reloader.set_catenary(&catenary_constraint_);
+ reloader.set_model_reference(&model_constraint_);
+
+ Vector3d weight_unit_stretch;
+ const WeatherLoadCase* weathercase_stretch = nullptr;
+
+ // solves the stretch due to creep
+ if (line_cable_->constraint().condition == CableConditionType::kCreep) {
+ // stretch has already been solved for during constraint model update
+ state_stretch_creep_ = model_constraint_.state_stretch();
+ } else {
+ // solves for the unit load at the creep stretch case
+ weathercase_stretch = line_cable_->weathercase_stretch_creep();
+ weight_unit_stretch = UnitLoad(*weathercase_stretch);
+
+ // reloads the constraint catenary to the creep stretch case
+ reloader.set_model_reloaded(&model_creep_);
+ reloader.set_weight_unit_reloaded(&weight_unit_stretch);
+
+ if (reloader.Validate(false, nullptr) == false) {
+ return false;
+ } else {
+ state_stretch_creep_.load = reloader.CatenaryReloaded().TensionAverage();
+ state_stretch_creep_.temperature = model_creep_.state().temperature;
+ state_stretch_creep_.type_polynomial = model_creep_.state().type_polynomial;
+ }
+ }
+
+ // solves the stretch due to load
+ if (line_cable_->constraint().condition == CableConditionType::kLoad) {
+ // stretch has already been solved for during constraint model update
+ state_stretch_load_ = model_constraint_.state_stretch();
+ } else {
+ // solves for the unit load at the load stretch case
+ weathercase_stretch = line_cable_->weathercase_stretch_load();
+ weight_unit_stretch = UnitLoad(*weathercase_stretch);
+
+ // reloads the constraint catenary to the load stretch case
+ reloader.set_model_reloaded(&model_load_);
+ reloader.set_weight_unit_reloaded(&weight_unit_stretch);
+
+ if (reloader.Validate(false, nullptr) == false) {
+ return false;
+ } else {
+ state_stretch_load_.load = reloader.CatenaryReloaded().TensionAverage();
+ state_stretch_load_.temperature = model_load_.state().temperature;
+ state_stretch_load_.type_polynomial = model_load_.state().type_polynomial;
+ }
+ }
+
+ return true;
+}
diff --git a/src/sagtension/line_cable_reloader.cc b/src/sagtension/line_cable_reloader.cc
index feacb8f..54e14c9 100644
--- a/src/sagtension/line_cable_reloader.cc
+++ b/src/sagtension/line_cable_reloader.cc
@@ -3,21 +3,14 @@
#include "models/sagtension/line_cable_reloader.h"
-#include
-
#include "models/sagtension/catenary_cable_reloader.h"
-#include "models/sagtension/catenary_cable_unloader.h"
-#include "models/transmissionline/catenary_solver.h"
-#include "models/transmissionline/cable_unit_load_calculator.h"
LineCableReloader::LineCableReloader() {
condition_reloaded_ = CableConditionType::kNull;
- line_cable_ = nullptr;
weathercase_reloaded_ = nullptr;
- is_updated_catenary_constraint_ = false;
- is_updated_stretch_ = false;
is_updated_catenary_reloaded_ = false;
+ is_updated_model_reloaded_ = false;
}
LineCableReloader::~LineCableReloader() {
@@ -34,40 +27,6 @@ Catenary3d LineCableReloader::CatenaryReloaded() const {
return catenary_reloaded_;
}
-double LineCableReloader::LengthUnloadedConstraint() const {
- // updates class if necessary
- if (IsUpdated() == false) {
- if (Update() == false) {
- return -999999;
- }
- }
-
- // creates a catenary cable unloader to solve for length
- CatenaryCableUnloader unloader;
- unloader.set_catenary(&catenary_constraint_);
- unloader.set_model_reference(&model_constraint_);
- unloader.set_model_unloaded(&model_constraint_);
-
- return unloader.LengthUnloaded();
-}
-
-double LineCableReloader::LengthUnloadedReloaded() const {
- // updates class if necessary
- if (IsUpdated() == false) {
- if (Update() == false) {
- return -999999;
- }
- }
-
- // creates a catenary cable unloader to solve for length
- CatenaryCableUnloader unloader;
- unloader.set_catenary(&catenary_reloaded_);
- unloader.set_model_reference(&model_reloaded_);
- unloader.set_model_unloaded(&model_reloaded_);
-
- return unloader.LengthUnloaded();
-}
-
CableState LineCableReloader::StateReloaded() const {
// updates class if necessary
if (IsUpdated() == false) {
@@ -79,28 +38,6 @@ CableState LineCableReloader::StateReloaded() const {
return model_reloaded_.state();
}
-CableStretchState LineCableReloader::StretchStateCreep() const {
- // updates class if necessary
- if (IsUpdated() == false) {
- if (Update() == false) {
- return CableStretchState();
- }
- }
-
- return state_stretch_creep_;
-}
-
-CableStretchState LineCableReloader::StretchStateLoad() const {
- // updates class if necessary
- if (IsUpdated() == false) {
- if (Update() == false) {
- return CableStretchState();
- }
- }
-
- return state_stretch_load_;
-}
-
double LineCableReloader::TensionAverageComponent(
const CableElongationModel::ComponentType& type_component) const {
// updates class if necessary
@@ -159,13 +96,9 @@ bool LineCableReloader::Validate(
ErrorMessage message;
message.title = "LINE CABLE RELOADER";
- // validates cable-sagtension
- if (cable_sagtension_.Validate(is_included_warnings, messages) == false) {
+ // validates base class
+ if (LineCableLoaderBase::Validate(is_included_warnings, messages) == false) {
is_valid = false;
- if (messages != nullptr) {
- message.description = "Invalid sag-tension cable";
- messages->push_back(message);
- }
}
// validates condition-reloaded
@@ -177,19 +110,6 @@ bool LineCableReloader::Validate(
}
}
- // validates line cable
- if (line_cable_ == nullptr) {
- is_valid = false;
- if (messages != nullptr) {
- message.description = "Invalid line cable";
- messages->push_back(message);
- }
- } else {
- if (line_cable_->Validate(is_included_warnings, messages) == false) {
- is_valid = false;
- }
- }
-
// validates weathercase-reloaded
if (weathercase_reloaded_ == nullptr) {
is_valid = false;
@@ -214,15 +134,12 @@ bool LineCableReloader::Validate(
is_valid = false;
if (messages != nullptr) {
message.description = "";
- if (is_updated_catenary_constraint_ == false) {
- message.description = "Error updating class. Could not solve for "
- "constraint catenary.";
- } else if (is_updated_stretch_ == false) {
- message.description = "Error updating class. Could not solve for "
- "creep or load based stretch.";
- } else if (is_updated_catenary_reloaded_ == false) {
+ if (is_updated_catenary_reloaded_ == false) {
message.description = "Error updating class. Could not solve for "
"reloaded catenary.";
+ } else if (is_updated_model_reloaded_ == false) {
+ message.description = "Error updating class. Could not solve for "
+ "reloaded cable model.";
}
messages->push_back(message);
}
@@ -235,36 +152,19 @@ CableConditionType LineCableReloader::condition_reloaded() const {
return condition_reloaded_;
}
-const LineCable* LineCableReloader::line_cable() const {
- return line_cable_;
-}
-
-void LineCableReloader::set_weathercase_reloaded(
- const WeatherLoadCase* case_reloaded) {
- weathercase_reloaded_ = case_reloaded;
-
- is_updated_catenary_reloaded_ = false;
-}
-
void LineCableReloader::set_condition_reloaded(
const CableConditionType& condition_reloaded) {
condition_reloaded_ = condition_reloaded;
+ is_updated_model_reloaded_ = false;
is_updated_catenary_reloaded_ = false;
}
-void LineCableReloader::set_line_cable(const LineCable* line_cable) {
- line_cable_ = line_cable;
-
- // updates sag-tension cable
- if (line_cable == nullptr) {
- cable_sagtension_.set_cable_base(nullptr);
- } else {
- cable_sagtension_.set_cable_base(line_cable_->cable());
- }
+void LineCableReloader::set_weathercase_reloaded(
+ const WeatherLoadCase* case_reloaded) {
+ weathercase_reloaded_ = case_reloaded;
- is_updated_catenary_constraint_ = false;
- is_updated_stretch_ = false;
+ is_updated_model_reloaded_ = false;
is_updated_catenary_reloaded_ = false;
}
@@ -272,73 +172,9 @@ const WeatherLoadCase* LineCableReloader::weathercase_reloaded() const {
return weathercase_reloaded_;
}
-bool LineCableReloader::InitializeLineCableModels() const {
- // declare working variable
- // all models are initialized with zero stretch
- CableState state;
-
- CableStretchState state_stretch;
- state_stretch.load = 0;
-
- // initializes the constraint cable model
- CableConstraint constraint = line_cable_->constraint();
- state.temperature = constraint.case_weather->temperature_cable;
- state.type_polynomial = SagTensionCableComponent::PolynomialType::kLoadStrain;
-
- if (constraint.condition == CableConditionType::kInitial) {
- state_stretch.temperature = 0; // doesn't matter, model is never stretched
- state_stretch.type_polynomial =
- SagTensionCableComponent::PolynomialType::kLoadStrain;
- } else if (constraint.condition == CableConditionType::kCreep) {
- state_stretch.temperature =
- line_cable_->weathercase_stretch_creep()->temperature_cable;
- state_stretch.type_polynomial =
- SagTensionCableComponent::PolynomialType::kCreep;
- } else if (constraint.condition == CableConditionType::kLoad) {
- state_stretch.temperature =
- line_cable_->weathercase_stretch_load()->temperature_cable;
- state_stretch.type_polynomial =
- SagTensionCableComponent::PolynomialType::kLoadStrain;
- } else {
- return false;
- }
-
- model_constraint_.set_cable(&cable_sagtension_);
- model_constraint_.set_state(state);
- model_constraint_.set_state_stretch(state_stretch);
-
- // updates the creep stretch model
- state.temperature =
- line_cable_->weathercase_stretch_creep()->temperature_cable;
- state.type_polynomial = SagTensionCableComponent::PolynomialType::kCreep;
-
- state_stretch.temperature = state.temperature;
- state_stretch.type_polynomial =
- SagTensionCableComponent::PolynomialType::kCreep;
-
- model_creep_.set_cable(&cable_sagtension_);
- model_creep_.set_state(state);
- model_creep_.set_state_stretch(state_stretch);
-
- // updates the load stretch model
- state.temperature =
- line_cable_->weathercase_stretch_load()->temperature_cable;
- state.type_polynomial = SagTensionCableComponent::PolynomialType::kLoadStrain;
-
- state_stretch.temperature = state.temperature;
- state_stretch.type_polynomial =
- SagTensionCableComponent::PolynomialType::kLoadStrain;
-
- model_load_.set_cable(&cable_sagtension_);
- model_load_.set_state(state);
- model_load_.set_state_stretch(state_stretch);
-
- return true;
-}
-
bool LineCableReloader::IsUpdated() const {
- if ((is_updated_catenary_constraint_ == true)
- && (is_updated_stretch_ == true)
+ if ((LineCableLoaderBase::IsUpdated() == true)
+ && (is_updated_model_reloaded_ == true)
&& (is_updated_catenary_reloaded_ == true)) {
return true;
} else {
@@ -346,46 +182,28 @@ bool LineCableReloader::IsUpdated() const {
}
}
-Vector3d LineCableReloader::UnitLoad(
- const WeatherLoadCase& weathercase) const {
- CableUnitLoadCalculator calculator;
- calculator.set_diameter_cable(&line_cable_->cable()->diameter);
- calculator.set_weight_unit_cable(&line_cable_->cable()->weight_unit);
-
- return calculator.UnitCableLoad(weathercase);
-}
-
bool LineCableReloader::Update() const {
- // updates constraint catenary
- if (is_updated_catenary_constraint_ == false) {
- is_updated_catenary_constraint_ = UpdateConstraintCatenary();
- if (is_updated_catenary_constraint_ == false) {
- return false;
- }
+ // updates base class
+ if (LineCableLoaderBase::IsUpdated() == false) {
+ // resets downstream update indicators
+ is_updated_model_reloaded_ = false;
+ is_updated_catenary_reloaded_ = false;
- InitializeLineCableModels();
-
- is_updated_catenary_constraint_ = UpdateConstraintCableModel();
- if (is_updated_catenary_constraint_ == false) {
+ if (LineCableLoaderBase::Update() == false) {
return false;
}
}
- // updates load-stretch
- if (is_updated_stretch_ == false) {
- is_updated_stretch_ = UpdateLoadStretch();
- if (is_updated_stretch_ == false) {
+ // updates reloaded cable model
+ if (is_updated_model_reloaded_ == false) {
+ is_updated_model_reloaded_ = UpdateReloadedCableModel();
+ if (is_updated_model_reloaded_ == false) {
return false;
}
}
// updates reloaded catenary
if (is_updated_catenary_reloaded_ == false) {
- is_updated_catenary_reloaded_ = UpdateReloadedCableModel();
- if (is_updated_catenary_reloaded_ == false) {
- return false;
- }
-
is_updated_catenary_reloaded_ = UpdateReloadedCatenary();
if (is_updated_catenary_reloaded_ == false) {
return false;
@@ -396,215 +214,8 @@ bool LineCableReloader::Update() const {
return true;
}
-/// This function checks the condition of the line cable constraint, and
-/// determines if stretch is necessary to solve for. Solving for the stretch
-/// requires an iterative approach. The line cable is reloaded from the
-/// constraint cable model to the stretch cable model and loading. The solution
-/// is found when the stretch load in the constraint cable model matches the
-/// reloaded catenary average tension (which is reloaded at the stretch cable
-/// model).
-bool LineCableReloader::UpdateConstraintCableModel() const {
- // checks if no stretch is defined (initial modulus)
- // constraint cable model was already initialized with zero stretch
- if (line_cable_->constraint().condition == CableConditionType::kInitial) {
- return true;
- }
-
- // x = stretch load
- // y = stretch load difference
- // i.e.(reloaded catenary avg tension - constraint model stretch load)
-
- // iterative routine to determine solution
- // solution reached when y = 0
- const double target_solution = 0;
-
- // initializes the stretch state
- CableStretchState state_stretch = model_constraint_.state_stretch();
-
- // initializes the reloader
- Vector3d weight_unit_reloaded;
- CatenaryCableReloader reloader;
- reloader.set_catenary(&catenary_constraint_);
- reloader.set_model_reference(&model_constraint_);
-
- if (line_cable_->constraint().condition == CableConditionType::kCreep) {
- weight_unit_reloaded = UnitLoad(*line_cable_->weathercase_stretch_creep());
-
- reloader.set_model_reloaded(&model_creep_);
- reloader.set_weight_unit_reloaded(&weight_unit_reloaded);
- } else if (line_cable_->constraint().condition == CableConditionType::kLoad) {
- weight_unit_reloaded = UnitLoad(*line_cable_->weathercase_stretch_load());
-
- reloader.set_model_reloaded(&model_load_);
- reloader.set_weight_unit_reloaded(&weight_unit_reloaded);
- } else {
- // condition isn't recognized
- return false;
- }
-
- // initializes left point
- Point2d point_left;
- point_left.x = 0;
- point_left.y = reloader.CatenaryReloaded().TensionAverage()
- - state_stretch.load;
-
- // initializes right point
- Point2d point_right;
- point_right.x = *cable_sagtension_.strength_rated();
-
- state_stretch.load = point_right.x;
- model_constraint_.set_state_stretch(state_stretch);
- reloader.set_model_reference(&model_constraint_);
-
- point_right.y = reloader.CatenaryReloaded().TensionAverage()
- - state_stretch.load;
-
- // initializes current point
- Point2d point_current;
-
- // iterates until target solution is reached
- unsigned int iter = 1;
- const int iter_max = 100;
- const double precision = 0.01;
- double slope_line = -999999;
-
- while ((precision < std::abs(point_current.y - target_solution))
- && (iter < iter_max)) {
-
- // solves for new stretch value is calculated for current point
- slope_line = (point_right.y - point_left.y)
- / (point_right.x - point_left.x);
- point_current.x = point_left.x
- + ((target_solution - point_left.y) / slope_line);
-
- // updates constraint model and reloader
- state_stretch.load = point_current.x;
- model_constraint_.set_state_stretch(state_stretch);
- reloader.set_model_reference(&model_constraint_);
-
- // solves for new horizontal tension value for current point
- point_current.y = reloader.CatenaryReloaded().TensionAverage()
- - state_stretch.load;
-
- // current point is left of left/right points
- if (point_current.x < point_left.x) {
-
- point_right.x = point_left.x;
- point_right.y = point_left.y;
- point_left.x = point_current.x;
- point_left.y = point_current.y;
-
- // current point is between left/right points
- } else if ((point_left.x <= point_current.x)
- && (point_current.x <= point_right.x)) {
-
- if (point_current.y < target_solution) {
- point_right.x = point_current.x;
- point_right.y = point_current.y;
- } else if (target_solution < point_current.y) {
- point_left.x = point_current.x;
- point_left.y = point_current.y;
- }
-
- // current point is right of left/right points
- } else if (point_right.x < point_current.x) {
-
- point_left.x = point_right.x;
- point_left.y = point_right.y;
- point_right.x = point_current.x;
- point_right.y = point_current.y;
- }
-
- iter++;
- }
-
- // returns success status
- if (iter < iter_max) {
- return true;
- } else {
- // re-initializes constraint model stretch
- state_stretch.load = 0;
- model_constraint_.set_state_stretch(state_stretch);
- return false;
- }
-}
-
-bool LineCableReloader::UpdateConstraintCatenary() const {
- CableConstraint constraint = line_cable_->constraint();
- Vector3d spacing = line_cable_->spacing_attachments_ruling_span();
-
- // builds a catenary solver
- CatenarySolver solver;
- solver.set_cable(cable_sagtension_.cable_base());
- solver.set_constraint(&constraint);
- solver.set_spacing_attachments(&spacing);
-
- if (solver.Validate() == false) {
- return false;
- } else {
- catenary_constraint_ = solver.Catenary();
- return true;
- }
-}
-
-bool LineCableReloader::UpdateLoadStretch() const {
- // initializes working variables
- CatenaryCableReloader reloader;
- reloader.set_catenary(&catenary_constraint_);
- reloader.set_model_reference(&model_constraint_);
-
- Vector3d weight_unit_stretch;
- const WeatherLoadCase* weathercase_stretch = nullptr;
-
- // solves the stretch due to creep
- if (line_cable_->constraint().condition == CableConditionType::kCreep) {
- // stretch has already been solved for during constraint model update
- state_stretch_creep_ = model_constraint_.state_stretch();
- } else {
- // solves for the unit load at the creep stretch case
- weathercase_stretch = line_cable_->weathercase_stretch_creep();
- weight_unit_stretch = UnitLoad(*weathercase_stretch);
-
- // reloads the constraint catenary to the creep stretch case
- reloader.set_model_reloaded(&model_creep_);
- reloader.set_weight_unit_reloaded(&weight_unit_stretch);
-
- if (reloader.Validate(false, nullptr) == false) {
- return false;
- } else {
- state_stretch_creep_.load = reloader.CatenaryReloaded().TensionAverage();
- state_stretch_creep_.temperature = model_creep_.state().temperature;
- state_stretch_creep_.type_polynomial = model_creep_.state().type_polynomial;
- }
- }
-
- // solves the stretch due to load
- if (line_cable_->constraint().condition == CableConditionType::kLoad) {
- // stretch has already been solved for during constraint model update
- state_stretch_load_ = model_constraint_.state_stretch();
- } else {
- // solves for the unit load at the load stretch case
- weathercase_stretch = line_cable_->weathercase_stretch_load();
- weight_unit_stretch = UnitLoad(*weathercase_stretch);
-
- // reloads the constraint catenary to the load stretch case
- reloader.set_model_reloaded(&model_load_);
- reloader.set_weight_unit_reloaded(&weight_unit_stretch);
-
- if (reloader.Validate(false, nullptr) == false) {
- return false;
- } else {
- state_stretch_load_.load = reloader.CatenaryReloaded().TensionAverage();
- state_stretch_load_.temperature = model_load_.state().temperature;
- state_stretch_load_.type_polynomial = model_load_.state().type_polynomial;
- }
- }
-
- return true;
-}
-
bool LineCableReloader::UpdateReloadedCableModel() const {
- // builds cable state based on reloaded weathercase and stretch
+ // builds cable states based on reloaded weathercase and stretch
CableState state;
state.temperature = weathercase_reloaded_->temperature_cable;
state.type_polynomial = SagTensionCableComponent::PolynomialType::kLoadStrain;
@@ -620,6 +231,8 @@ bool LineCableReloader::UpdateReloadedCableModel() const {
state_stretch = state_stretch_creep_;
} else if (condition_reloaded_ == CableConditionType::kLoad) {
state_stretch = state_stretch_load_;
+ } else {
+ return false;
}
// updates model
@@ -634,17 +247,17 @@ bool LineCableReloader::UpdateReloadedCatenary() const {
// calculates reloaded unit weight
Vector3d weight_unit_reloaded = UnitLoad(*weathercase_reloaded_);
- // builds reloader and gets the calculates the reloaded catenary
+ // builds reloader and gets the reloaded catenary
CatenaryCableReloader reloader;
reloader.set_catenary(&catenary_constraint_);
reloader.set_model_reference(&model_constraint_);
reloader.set_model_reloaded(&model_reloaded_);
reloader.set_weight_unit_reloaded(&weight_unit_reloaded);
- if (reloader.Validate(false, nullptr) == false) {
- return false;
- } else {
+ if (reloader.Validate(false, nullptr) == true) {
catenary_reloaded_ = reloader.CatenaryReloaded();
return true;
+ } else {
+ return false;
}
}
diff --git a/src/sagtension/line_cable_unloader.cc b/src/sagtension/line_cable_unloader.cc
new file mode 100644
index 0000000..264826d
--- /dev/null
+++ b/src/sagtension/line_cable_unloader.cc
@@ -0,0 +1,238 @@
+// This is free and unencumbered software released into the public domain.
+// For more information, please refer to
+
+#include "models/sagtension/line_cable_unloader.h"
+
+#include
+
+#include "models/sagtension/catenary_cable_unloader.h"
+
+LineCableUnloader::LineCableUnloader() {
+ condition_unloaded_ = CableConditionType::kNull;
+ spacing_attachments_ = Vector3d();
+ temperature_unloaded_ = -999999;
+
+ length_unloaded_ = -999999;
+
+ is_updated_length_unloaded_ = false;
+ is_updated_model_unloaded_ = false;
+}
+
+LineCableUnloader::~LineCableUnloader() {
+}
+
+double LineCableUnloader::LengthUnloaded() const {
+ // updates class if necessary
+ if (IsUpdated() == false) {
+ if (Update() == false) {
+ return -999999;
+ }
+ }
+
+ return length_unloaded_;
+}
+
+bool LineCableUnloader::Validate(
+ const bool& is_included_warnings,
+ std::list* messages) const {
+ // initializes
+ bool is_valid = true;
+ ErrorMessage message;
+ message.title = "LINE CABLE UNLOADER";
+
+ // validates base class
+ if (LineCableLoaderBase::Validate(is_included_warnings, messages) == false) {
+ is_valid = false;
+ }
+
+ // validates condition-unloaded
+ if (condition_unloaded_ == CableConditionType::kNull) {
+ is_valid = false;
+ if (messages != nullptr) {
+ message.description = "Invalid unloaded condition";
+ messages->push_back(message);
+ }
+ }
+
+ // validates spacing-attachments
+ if (spacing_attachments_.x() <= 0) {
+ is_valid = false;
+ if (messages != nullptr) {
+ message.description = "Invalid horizontal attachment spacing";
+ messages->push_back(message);
+ }
+ }
+
+ if (spacing_attachments_.y() != 0) {
+ is_valid = false;
+ if (messages != nullptr) {
+ message.description = "Invalid transverse attachment spacing";
+ messages->push_back(message);
+ }
+ }
+
+ if (2000 < std::abs(spacing_attachments_.z())) {
+ is_valid = false;
+ if (messages != nullptr) {
+ message.description = "Invalid vertical attachment spacing";
+ messages->push_back(message);
+ }
+ }
+
+ // validates temperature-unloaded
+ if (temperature_unloaded_ < -50) {
+ is_valid = false;
+ if (messages != nullptr) {
+ message.description = "Invalid unloaded temperature";
+ messages->push_back(message);
+ }
+ }
+
+ // returns if errors are present
+ if (is_valid == false) {
+ return is_valid;
+ }
+
+ // validates update process
+ if (Update() == false) {
+ is_valid = false;
+ if (messages != nullptr) {
+ message.description = "";
+ if (is_updated_length_unloaded_ == false) {
+ message.description = "Error updating class. Could not solve for "
+ "unloaded cable length.";
+ } else if (is_updated_model_unloaded_ == false) {
+ message.description = "Error updating class. Could not solve for "
+ "unloaded cable model.";
+ }
+ messages->push_back(message);
+ }
+ }
+
+ return is_valid;
+}
+
+CableConditionType LineCableUnloader::condition_unloaded() const {
+ return condition_unloaded_;
+}
+
+void LineCableUnloader::set_condition_unloaded(
+ const CableConditionType& condition_unloaded) {
+ condition_unloaded_ = condition_unloaded;
+
+ is_updated_model_unloaded_ = false;
+ is_updated_length_unloaded_ = false;
+}
+
+void LineCableUnloader::set_spacing_attachments(
+ const Vector3d& spacing_attachments) {
+ spacing_attachments_ = spacing_attachments;
+
+ is_updated_length_unloaded_ = false;
+}
+
+void LineCableUnloader::set_temperature_unloaded(
+ const double& temperature_unloaded) {
+ temperature_unloaded_ = temperature_unloaded;
+
+ is_updated_model_unloaded_ = false;
+ is_updated_length_unloaded_ = false;
+}
+
+Vector3d LineCableUnloader::spacing_attachments() const {
+ return spacing_attachments_;
+}
+
+double LineCableUnloader::temperature_unloaded() const {
+ return temperature_unloaded_;
+}
+
+bool LineCableUnloader::IsUpdated() const {
+ if ((LineCableLoaderBase::IsUpdated() == true)
+ && (is_updated_model_unloaded_ == true)
+ && (is_updated_length_unloaded_ == true)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool LineCableUnloader::Update() const {
+ // updates base class
+ if (LineCableLoaderBase::IsUpdated() == false) {
+ // resets downstream update indicators
+ is_updated_model_unloaded_ = false;
+ is_updated_length_unloaded_ = false;
+
+ if (LineCableLoaderBase::Update() == false) {
+ return false;
+ }
+ }
+
+ // updates unloaded cable model
+ if (is_updated_model_unloaded_ == false) {
+ is_updated_model_unloaded_ = UpdateUnloadedCableModel();
+ if (is_updated_model_unloaded_ == false) {
+ return false;
+ }
+ }
+
+ // updates unloaded length
+ if (is_updated_length_unloaded_ == false) {
+ is_updated_length_unloaded_ = UpdateUnloadedLength();
+ if (is_updated_length_unloaded_ == false) {
+ return false;
+ }
+ }
+
+ // if it reaches this point, update was successful
+ return true;
+}
+
+bool LineCableUnloader::UpdateUnloadedCableModel() const {
+ // builds cable states based on unloaded condition and temperature
+ CableState state;
+ state.temperature = temperature_unloaded_;
+ state.type_polynomial = SagTensionCableComponent::PolynomialType::kLoadStrain;
+
+ CableStretchState state_stretch;
+ if (condition_unloaded_ == CableConditionType::kInitial) {
+ // stretch parameters don't matter, model isn't stretched
+ state_stretch.load = 0;
+ state_stretch.temperature = 0;
+ state_stretch.type_polynomial =
+ SagTensionCableComponent::PolynomialType::kLoadStrain;
+ } else if (condition_unloaded_ == CableConditionType::kCreep) {
+ state_stretch = state_stretch_creep_;
+ } else if (condition_unloaded_ == CableConditionType::kLoad) {
+ state_stretch = state_stretch_load_;
+ } else {
+ return false;
+ }
+
+ // updates model
+ model_unloaded_.set_cable(&cable_sagtension_);
+ model_unloaded_.set_state(state);
+ model_unloaded_.set_state_stretch(state_stretch);
+
+ return true;
+}
+
+bool LineCableUnloader::UpdateUnloadedLength() const {
+ // builds catenary to unload
+ Catenary3d catenary = catenary_constraint_;
+ catenary.set_spacing_endpoints(spacing_attachments_);
+
+ // builds unloader and gets the unloaded length
+ CatenaryCableUnloader unloader;
+ unloader.set_catenary(&catenary);
+ unloader.set_model_reference(&model_constraint_);
+ unloader.set_model_unloaded(&model_unloaded_);
+
+ if (unloader.Validate(false, nullptr) == true) {
+ length_unloaded_ = unloader.LengthUnloaded();
+ return true;
+ } else {
+ return false;
+ }
+}
diff --git a/src/transmissionline/cable_unit_load_calculator.cc b/src/transmissionline/cable_unit_load_solver.cc
similarity index 80%
rename from src/transmissionline/cable_unit_load_calculator.cc
rename to src/transmissionline/cable_unit_load_solver.cc
index 53eefda..ddf3883 100644
--- a/src/transmissionline/cable_unit_load_calculator.cc
+++ b/src/transmissionline/cable_unit_load_solver.cc
@@ -1,19 +1,19 @@
// This is free and unencumbered software released into the public domain.
// For more information, please refer to
-#include "models/transmissionline/cable_unit_load_calculator.h"
+#include "models/transmissionline/cable_unit_load_solver.h"
#include "models/base/geometric_shapes.h"
-CableUnitLoadCalculator::CableUnitLoadCalculator() {
+CableUnitLoadSolver::CableUnitLoadSolver() {
diameter_cable_ = nullptr;
weight_unit_cable_ = nullptr;
}
-CableUnitLoadCalculator::~CableUnitLoadCalculator() {
+CableUnitLoadSolver::~CableUnitLoadSolver() {
}
-bool CableUnitLoadCalculator::Validate(
+bool CableUnitLoadSolver::Validate(
const bool& is_included_warnings,
std::list* messages) const {
// initializes
@@ -47,7 +47,7 @@ bool CableUnitLoadCalculator::Validate(
///
/// The transverse load on the cable is solved using the following formula:
/// \f[ T = AP \f]
-Vector3d CableUnitLoadCalculator::UnitCableLoad(
+Vector3d CableUnitLoadSolver::UnitCableLoad(
const WeatherLoadCase& case_load_weather) const {
// creates bare and iced cylinders
Cylinder cylinder_bare;
@@ -73,19 +73,19 @@ Vector3d CableUnitLoadCalculator::UnitCableLoad(
return load_unit_cable;
}
-const double* CableUnitLoadCalculator::diameter_cable() const {
+const double* CableUnitLoadSolver::diameter_cable() const {
return diameter_cable_;
}
-const double* CableUnitLoadCalculator::weight_unit_cable() const {
+const double* CableUnitLoadSolver::weight_unit_cable() const {
return weight_unit_cable_;
}
-void CableUnitLoadCalculator::set_diameter_cable(const double* diameter_cable) {
+void CableUnitLoadSolver::set_diameter_cable(const double* diameter_cable) {
diameter_cable_ = diameter_cable;
}
-void CableUnitLoadCalculator::set_weight_unit_cable(
+void CableUnitLoadSolver::set_weight_unit_cable(
const double* weight_unit_cable) {
weight_unit_cable_ = weight_unit_cable;
}
diff --git a/src/transmissionline/catenary.cc b/src/transmissionline/catenary.cc
index d33ee1d..4a4b009 100644
--- a/src/transmissionline/catenary.cc
+++ b/src/transmissionline/catenary.cc
@@ -51,35 +51,30 @@ Point2d Catenary2d::Coordinate(const double& position_fraction,
// select how to calculate length and position from origin based on
// endpoint coordinates
- // both endpoints are left from origin
if (point_end_left_.x < 0 && point_end_right_.x < 0) {
+ // both endpoints are left from origin
length_origin_to_position = length_origin_to_left -
length_left_to_position;
- direction_origin_to_position = AxisDirectionType::kPositive;
- }
- // one endpoint left from origin, one endpoint right from origin
- else if (point_end_left_.x < 0 && 0 < point_end_right_.x) {
-
- // left from origin
+ direction_origin_to_position = AxisDirectionType::kNegative;
+ } else if (point_end_left_.x < 0 && 0 < point_end_right_.x) {
+ // one endpoint left from origin, one endpoint right from origin
if (length_left_to_position < length_origin_to_left) {
+ // left from origin
length_origin_to_position = length_origin_to_left -
length_left_to_position;
direction_origin_to_position = AxisDirectionType::kNegative;
- }
- // at origin
- else if (length_left_to_position == length_origin_to_left) {
+ } else if (length_left_to_position == length_origin_to_left) {
+ // at origin
length_origin_to_position = 0;
direction_origin_to_position = AxisDirectionType::kPositive;
- }
- // right from origin
- else if (length_origin_to_left < length_left_to_position) {
+ } else if (length_origin_to_left < length_left_to_position) {
+ // right from origin
length_origin_to_position = length_left_to_position -
length_origin_to_left;
direction_origin_to_position = AxisDirectionType::kPositive;
}
- }
- // both endpoints are AOL of origin
- else if (0 < point_end_left_.x && 0 < point_end_right_.x) {
+ } else if (0 < point_end_left_.x && 0 < point_end_right_.x) {
+ // both endpoints are AOL of origin
length_origin_to_position = length_origin_to_left +
length_left_to_position;
direction_origin_to_position = AxisDirectionType::kPositive;
@@ -207,13 +202,16 @@ double Catenary2d::Sag() const {
// gets sag position
const double position_fraction_sagpoint = PositionFractionSagPoint();
- // gets catenary coordinate at sag position
- const Point2d coordinate_catenary =
- Coordinate(position_fraction_sagpoint);
+ // calculates and returns
+ return Sag(position_fraction_sagpoint);
+}
+
+double Catenary2d::Sag(const double& position_fraction) const {
+ // gets catenary coordinate at the position
+ const Point2d coordinate_catenary = Coordinate(position_fraction);
- // gets a chord coordinate at sag position
- const Point2d coordinate_chord =
- CoordinateChord(position_fraction_sagpoint);
+ // gets a chord coordinate at the position
+ const Point2d coordinate_chord = CoordinateChord(position_fraction);
// gets height difference between chord and catenary
return coordinate_chord.y - coordinate_catenary.y;
@@ -231,11 +229,12 @@ double Catenary2d::TangentAngle(const double& position_fraction,
const Point2d coordinate = Coordinate(position_fraction);
// calculates slope at position
- const double slope = sinh(coordinate.x / (tension_horizontal_/weight_unit_));
+ const double slope = std::sinh(coordinate.x
+ / (tension_horizontal_/weight_unit_));
// converts to degrees
double tangent_angle = units::ConvertAngle(
- atan(slope),
+ std::atan(slope),
units::AngleConversionType::kRadiansToDegrees);
// adjusts if direction is negative
@@ -268,11 +267,11 @@ Vector2d Catenary2d::TangentVector(const double& position_fraction,
angle_tangent,
units::AngleConversionType::kDegreesToRadians);
if (direction == AxisDirectionType::kNegative) {
- tangent_vector.set_x( -(1 * cos(angle_radians)) );
- tangent_vector.set_y( sin(angle_radians) );
+ tangent_vector.set_x(-(1 * std::cos(angle_radians)));
+ tangent_vector.set_y(std::sin(angle_radians));
} else if (direction == AxisDirectionType::kPositive) {
- tangent_vector.set_x( cos(angle_radians) );
- tangent_vector.set_y( sin(angle_radians) );
+ tangent_vector.set_x(std::cos(angle_radians));
+ tangent_vector.set_y(std::sin(angle_radians));
}
return tangent_vector;
@@ -289,7 +288,7 @@ double Catenary2d::Tension(const double& position_fraction) const {
Point2d coordinate = Coordinate(position_fraction);
return tension_horizontal_
- * cosh( coordinate.x / (tension_horizontal_/weight_unit_));
+ * std::cosh(coordinate.x / (tension_horizontal_ / weight_unit_));
}
/// A tangent unit vector is calculated and then multiplied by the tension magnitude.
@@ -330,15 +329,14 @@ double Catenary2d::TensionAverage(const int& num_points) const {
const double w = weight_unit_;
const double l = Length();
- const double term_1 = (pow(h, 2) / (2 * w * l));
- const double term_2 = sinh(point_end_right_.x / (h / w))
- * cosh(point_end_right_.x / (h / w));
- const double term_3 = sinh(point_end_left_.x / (h / w))
- * cosh(point_end_left_.x / (h / w));
- const double term_4 = (point_end_right_.x - point_end_left_.x)
- / (h / w);
+ const double k1 = (std::pow(h, 2) / (2 * w * l));
+ const double k2 = std::sinh(point_end_right_.x / (h / w))
+ * std::cosh(point_end_right_.x / (h / w));
+ const double k3 = std::sinh(point_end_left_.x / (h / w))
+ * std::cosh(point_end_left_.x / (h / w));
+ const double k4 = (point_end_right_.x - point_end_left_.x) / (h / w);
- tension_average = term_1 * (term_2 - term_3 + term_4);
+ tension_average = k1 * (k2 - k3 + k4);
} else if (0 < num_points) {
@@ -478,11 +476,11 @@ double Catenary2d::CoordinateX(
// BOL from origin - negative x coordinate
if (direction_origin_to_position == AxisDirectionType::kNegative) {
- coordinate_x = -(h/w) * (asinh(l / (h/w)));
+ coordinate_x = -(h / w) * (std::asinh(l / (h / w)));
}
// AOL from origin - positive x coordinate
else if (direction_origin_to_position == AxisDirectionType::kPositive) {
- coordinate_x = (h/w) * (asinh(l / (h/w)));
+ coordinate_x = (h / w) * (std::asinh(l / (h / w)));
}
return coordinate_x;
@@ -497,7 +495,7 @@ double Catenary2d::CoordinateY(
const double h = tension_horizontal_;
const double w = weight_unit_;
- return (h/w) * (cosh(x / (h/w)) - 1);
+ return (h / w) * (std::cosh(x / (h / w)) - 1);
}
bool Catenary2d::IsUpdated() const {
@@ -515,7 +513,7 @@ double Catenary2d::LengthFromOrigin(const Point2d& coordinate) const {
const double h = tension_horizontal_;
const double w = weight_unit_;
- return std::abs((h/w) * sinh(x / (h/w)));
+ return std::abs((h / w) * std::sinh(x / (h / w)));
}
double Catenary2d::PositionFraction(const double& tangent_angle) const {
@@ -575,9 +573,6 @@ bool Catenary2d::Update() const {
return true;
}
-/// Hyperbolic identity equations are used to solve for the endpoint coordinates:
-/// \f[ xBOL = \frac{A}{2} - \frac{H}{w} sinh^{-1} \left( \frac{\frac{B}{2}}{ \frac{H}{w} sinh \left( \frac{\frac{A}{2}}{\frac{H}{w}} \right)} \right) \f]
-/// \f[ xAOL = \frac{A}{2} + \frac{H}{w} sinh^{-1} \left( \frac{\frac{B}{2}}{ \frac{H}{w} sinh \left( \frac{\frac{A}{2}}{\frac{H}{w}} \right)} \right) \f]
bool Catenary2d::UpdateEndPoints() const {
const double h = tension_horizontal_;
const double w = weight_unit_;
@@ -585,13 +580,13 @@ bool Catenary2d::UpdateEndPoints() const {
const double b = spacing_endpoints_.y();
const double z = (a/2) / (h/w);
- // solves for left endpoint coordinate
- point_end_left_.x = (h/w) * (asinh((b * z) / (a * sinh(z))) - z);
+ // solves for left endpoint coordinate (Ehrenburg)
+ point_end_left_.x = (h / w) * (std::asinh((b * z) / (a * std::sinh(z))) - z);
point_end_left_.y = CoordinateY(LengthFromOrigin(point_end_left_),
AxisDirectionType::kNegative);
- // solves for right endpoint coordinate
- point_end_right_.x = (h/w) * (asinh((b * z) / (a * sinh(z))) + z);
+ // solves for right endpoint coordinate (Ehrenburg)
+ point_end_right_.x = (h / w) * (std::asinh((b * z) / (a * std::sinh(z))) + z);
point_end_right_.y = CoordinateY(LengthFromOrigin(point_end_right_),
AxisDirectionType::kPositive);
@@ -786,6 +781,16 @@ double Catenary3d::Sag() const {
return catenary_2d_.Sag();
}
+double Catenary3d::Sag(const double& position_fraction) const {
+ if (IsUpdated() == false) {
+ if (Update() == false) {
+ return -999999;
+ }
+ }
+
+ return catenary_2d_.Sag(position_fraction);
+}
+
double Catenary3d::SwingAngle() const {
double angle_swing = -999999;
@@ -814,8 +819,8 @@ double Catenary3d::TangentAngleTransverse(
Vector3d tangent_vector = TangentVector(position_fraction, direction);
// adjusts components to use only positive values in unit circle
- tangent_vector.set_y( std::abs(tangent_vector.y()) );
- tangent_vector.set_z( std::abs(tangent_vector.z()) );
+ tangent_vector.set_y(std::abs(tangent_vector.y()));
+ tangent_vector.set_z(std::abs(tangent_vector.z()));
// returns transverse angle
return tangent_vector.Angle(Plane2dType::kZy, true);
@@ -834,7 +839,7 @@ double Catenary3d::TangentAngleVertical(
Vector3d tangent_vector = TangentVector(position_fraction, direction);
// adjusts x component to use only positive values in unit circle
- tangent_vector.set_x( std::abs(tangent_vector.x()) );
+ tangent_vector.set_x(std::abs(tangent_vector.x()));
// returns vertical angle
return tangent_vector.Angle(Plane2dType::kXz, true);
@@ -866,7 +871,8 @@ Vector3d Catenary3d::TangentVector(const double& position_fraction,
Vector2d spacing_endpoints_2d = catenary_2d_.spacing_endpoints();
double angle_endpoints_2d = spacing_endpoints_2d.Angle(true);
- double angle_endpoints_3d = spacing_endpoints_.Angle(Plane2dType::kXz, true);
+ double angle_endpoints_3d = spacing_endpoints_.Angle(Plane2dType::kXz,
+ true);
tangent_vector.Rotate(Plane2dType::kXz,
angle_endpoints_3d - angle_endpoints_2d);
@@ -1089,8 +1095,9 @@ bool Catenary3d::UpdateCatenary2d() const {
// solves for 2D catenary endpoint spacing
Vector2d spacing_endpoints_2d;
- spacing_endpoints_2d.set_y(b * (v/w));
- spacing_endpoints_2d.set_x(sqrt( pow(c,2)-pow(spacing_endpoints_2d.y(), 2)));
+ spacing_endpoints_2d.set_y(b * (v / w));
+ spacing_endpoints_2d.set_x(
+ std::sqrt(std::pow(c,2) - std::pow(spacing_endpoints_2d.y(), 2)));
// sets catenary spacing and unit weight
catenary_2d_.set_spacing_endpoints(spacing_endpoints_2d);
diff --git a/src/transmissionline/catenary_solver.cc b/src/transmissionline/catenary_solver.cc
index b0a4645..33a724c 100644
--- a/src/transmissionline/catenary_solver.cc
+++ b/src/transmissionline/catenary_solver.cc
@@ -5,14 +5,13 @@
#include
-#include "models/transmissionline/cable_unit_load_calculator.h"
-
CatenarySolver::CatenarySolver() {
- cable_ = nullptr;
- constraint_ = nullptr;
- spacing_attachments_ = nullptr;
+ catenary_ = Catenary3d();
+ position_target_ = -1;
+ type_target_ = TargetType::kNull;
+ value_target_ = -999999;
- is_updated_catenary_ = false;
+ is_updated_ = false;
}
CatenarySolver::~CatenarySolver() {
@@ -29,6 +28,17 @@ Catenary3d CatenarySolver::Catenary() const {
return catenary_;
}
+double CatenarySolver::TensionHorizontal() const {
+ // updates class if necessary
+ if (IsUpdated() == false) {
+ if (Update() == false) {
+ return -999999;
+ }
+ }
+
+ return catenary_.tension_horizontal();
+}
+
bool CatenarySolver::Validate(
const bool& is_included_warnings,
std::list* messages) const {
@@ -37,53 +47,84 @@ bool CatenarySolver::Validate(
ErrorMessage message;
message.title = "CATENARY SOLVER";
- // validates cable
- if (cable_ == nullptr) {
+ // validates position-target
+ if ((position_target_ < 0) || (1 < position_target_)) {
is_valid = false;
if (messages != nullptr) {
- message.description = "Invalid cable";
+ message.description = "Invalid target position";
messages->push_back(message);
}
- } else {
- if (cable_->Validate(is_included_warnings, messages) == false) {
- is_valid = false;
+ }
+
+ // validates spacing-endpoints
+ Vector3d spacing_endpoints = catenary_.spacing_endpoints();
+ if (spacing_endpoints.x() <= 0) {
+ is_valid = false;
+ if (messages != nullptr) {
+ message.description = "Invalid horizontal end point spacing";
+ messages->push_back(message);
}
}
- // validates constraint
- if (constraint_ == nullptr) {
+ if (spacing_endpoints.y() != 0) {
is_valid = false;
if (messages != nullptr) {
- message.description = "Invalid constraint";
+ message.description = "Invalid end point spacing";
messages->push_back(message);
}
- } else {
- if (constraint_->Validate(is_included_warnings, messages) == false) {
- is_valid = false;
+ }
+
+ if (2000 < std::abs(spacing_endpoints.z())) {
+ is_valid = false;
+ if (messages != nullptr) {
+ message.description = "Invalid vertical end point spacing";
+ messages->push_back(message);
+ }
+ }
+
+ // validates type-target
+ if (type_target_ == CatenarySolver::TargetType::kNull) {
+ is_valid = false;
+ if (messages != nullptr) {
+ message.description = "Invalid target type";
+ messages->push_back(message);
}
}
- // validates spacing-attachments
- if (spacing_attachments_->x() <= 0) {
+ // validates value-target
+ if (value_target_ <= 0) {
is_valid = false;
if (messages != nullptr) {
- message.description = "Invalid horizontal attachment spacing";
+ message.description = "Invalid target value";
messages->push_back(message);
}
}
- if (spacing_attachments_->y() != 0) {
+ // validates weight-unit-horizontal
+ Vector3d weight_unit = catenary_.weight_unit();
+ if (weight_unit.x() != 0) {
is_valid = false;
if (messages != nullptr) {
- message.description = "Invalid attachment spacing";
+ message.description = "Invalid horizontal unit weight. It must "
+ "equal zero";
messages->push_back(message);
}
}
- if (2000 < std::abs(spacing_attachments_->z())) {
+ // validates weight-unit-transverse
+ if (weight_unit.y() < 0) {
is_valid = false;
if (messages != nullptr) {
- message.description = "Invalid vertical attachment spacing";
+ message.description = "Invalid transverse unit weight";
+ messages->push_back(message);
+ }
+ }
+
+ // validates weight-unit-vertical
+ if (weight_unit.z() <= 0) {
+ is_valid = false;
+ if (messages != nullptr) {
+ message.description = "Invalid vertical unit weight";
messages->push_back(message);
}
}
@@ -107,36 +148,53 @@ bool CatenarySolver::Validate(
return is_valid;
}
-const Cable* CatenarySolver::cable() const {
- return cable_;
+double CatenarySolver::position_target() const {
+ return position_target_;
+}
+
+void CatenarySolver::set_position_target(const double& position) {
+ position_target_ = position;
+ is_updated_ = false;
+}
+
+void CatenarySolver::set_spacing_endpoints(const Vector3d& spacing_endpoints) {
+ catenary_.set_spacing_endpoints(spacing_endpoints);
+ is_updated_ = false;
+}
+
+void CatenarySolver::set_type_target(const TargetType& type) {
+ type_target_ = type;
+ is_updated_ = false;
}
-const CableConstraint* CatenarySolver::constraint() const {
- return constraint_;
+void CatenarySolver::set_value_target(const double& value) {
+ value_target_ = value;
+ is_updated_ = false;
}
-void CatenarySolver::set_cable(const Cable* cable) {
- cable_ = cable;
- is_updated_catenary_ = false;
+void CatenarySolver::set_weight_unit(const Vector3d& weight_unit) {
+ catenary_.set_weight_unit(weight_unit);
+ is_updated_ = false;
}
-void CatenarySolver::set_constraint(const CableConstraint* constraint) {
- constraint_ = constraint;
- is_updated_catenary_ = false;
+const Vector3d CatenarySolver::spacing_endpoints() const {
+ return catenary_.spacing_endpoints();
}
-void CatenarySolver::set_spacing_attachments(
- const Vector3d* spacing_attachments) {
- spacing_attachments_ = spacing_attachments;
- is_updated_catenary_ = false;
+CatenarySolver::TargetType CatenarySolver::type_target() const {
+ return type_target_;
}
-const Vector3d* CatenarySolver::spacing_attachments() const {
- return spacing_attachments_;
+double CatenarySolver::value_target() const {
+ return value_target_;
+}
+
+const Vector3d CatenarySolver::weight_unit() const {
+ return catenary_.weight_unit();
}
bool CatenarySolver::IsUpdated() const {
- if (is_updated_catenary_ == true) {
+ if (is_updated_ == true) {
return true;
} else {
return false;
@@ -146,8 +204,8 @@ bool CatenarySolver::IsUpdated() const {
bool CatenarySolver::SolveHorizontalTensionFromConstant() const {
// the catenary unit weight should already be updated, so this multiplies
// catenary constant by w to get horizontal tension
- catenary_.set_tension_horizontal(constraint_->limit
- * catenary_.weight_unit().Magnitude());
+ catenary_.set_tension_horizontal(
+ value_target_ * catenary_.weight_unit().Magnitude());
return true;
}
@@ -159,7 +217,7 @@ bool CatenarySolver::SolveHorizontalTensionFromLength() const {
// y = length
// initializes target
- double target_solution = constraint_->limit;
+ double target_solution = value_target_;
// declares and initializes left point
// lowest acceptable value for catenary
@@ -170,7 +228,7 @@ bool CatenarySolver::SolveHorizontalTensionFromLength() const {
point_left.y = UpdateCatenaryLength(point_left.x);
// checks if target length is less than straight line distance
- if (target_solution <= spacing_attachments_->Magnitude()) {
+ if (target_solution <= catenary_.spacing_endpoints().Magnitude()) {
return false;
}
@@ -249,7 +307,7 @@ bool CatenarySolver::SolveHorizontalTensionFromSag() const {
// y = sag
// initializes target
- double target_solution = constraint_->limit;
+ double target_solution = value_target_;
// declares and initializes left point
// lowest acceptable value for catenary
@@ -257,7 +315,7 @@ bool CatenarySolver::SolveHorizontalTensionFromSag() const {
point_left.x = Catenary2d::ConstantMinimum(
catenary_.spacing_endpoints().Magnitude())
* catenary_.weight_unit().Magnitude();
- point_left.y = UpdateCatenarySag(point_left.x);
+ point_left.y = UpdateCatenarySag(point_left.x, position_target_);
// target sag is greater than lowest acceptable catenary value
if (point_left.y < target_solution) {
@@ -267,7 +325,7 @@ bool CatenarySolver::SolveHorizontalTensionFromSag() const {
// declares and initializes right point to 10,000 H/w
Point2d point_right;
point_right.x = point_left.x * 1.10;
- point_right.y = UpdateCatenarySag(point_right.x);
+ point_right.y = UpdateCatenarySag(point_right.x, position_target_);
// declares and initializes current point
Point2d point_current;
@@ -286,7 +344,7 @@ bool CatenarySolver::SolveHorizontalTensionFromSag() const {
+ ((target_solution - point_left.y) / slope_line);
// gets current point y value
- point_current.y = UpdateCatenarySag(point_current.x);
+ point_current.y = UpdateCatenarySag(point_current.x, position_target_);
// updates either left or right point based on current point
if (point_current.x < point_left.x) {
@@ -329,12 +387,12 @@ bool CatenarySolver::SolveHorizontalTensionFromSag() const {
/// This is done iteratively by adjusting the horizontal tension until the
/// support tension is matched.
-bool CatenarySolver::SolveHorizontalTensionFromSupportTension() const {
+bool CatenarySolver::SolveHorizontalTensionFromTension() const {
// x = tension-horizontal
// y = tension-support
// initializes target
- double target_solution = constraint_->limit;
+ double target_solution = value_target_;
// declares and initializes left point
// lowest acceptable value for catenary
@@ -342,7 +400,7 @@ bool CatenarySolver::SolveHorizontalTensionFromSupportTension() const {
point_left.x = Catenary2d::ConstantMinimum(
catenary_.spacing_endpoints().Magnitude())
* catenary_.weight_unit().Magnitude();
- point_left.y = UpdateCatenaryMaxTension(point_left.x);
+ point_left.y = UpdateCatenaryTension(point_left.x, position_target_);
// target is less than lowest acceptable catenary value
if (target_solution < point_left.y) {
@@ -352,8 +410,8 @@ bool CatenarySolver::SolveHorizontalTensionFromSupportTension() const {
// declares and initializes right point
// highest value (horizontal tension cannot exceed support tension)
Point2d point_right;
- point_right.x = constraint_->limit;
- point_right.y = UpdateCatenaryMaxTension(point_right.x);
+ point_right.x = value_target_;
+ point_right.y = UpdateCatenaryTension(point_right.x, position_target_);
// declares and initializes current point
Point2d point_current;
@@ -372,7 +430,7 @@ bool CatenarySolver::SolveHorizontalTensionFromSupportTension() const {
+ ((target_solution - point_left.y) / slope_line);
// gets current point y value
- point_current.y = UpdateCatenaryMaxTension(point_current.x);
+ point_current.y = UpdateCatenaryTension(point_current.x, position_target_);
// updates either left or right point based on current point
if (point_current.x < point_left.x) {
@@ -413,77 +471,39 @@ bool CatenarySolver::SolveHorizontalTensionFromSupportTension() const {
}
}
-bool CatenarySolver::SolveWeightUnit() const {
- // creates a calculator based on the line cable
- CableUnitLoadCalculator calculator;
- calculator.set_diameter_cable(&cable_->diameter);
- calculator.set_weight_unit_cable(&cable_->weight_unit);
-
- // calculates the unit load and updates catenary
- Vector3d load_unit = calculator.UnitCableLoad(*constraint_->case_weather);
- catenary_.set_weight_unit(load_unit);
-
- return true;
-}
-
bool CatenarySolver::Update() const {
// updates catenary
- if (is_updated_catenary_ == false) {
-
- // updates spacing
- catenary_.set_spacing_endpoints(*spacing_attachments_);
-
- // solves for the unit weight
- is_updated_catenary_ = SolveWeightUnit();
- if (is_updated_catenary_ == false) {
+ if (type_target_ == CatenarySolver::TargetType::kConstant) {
+ // solves for horizontal tension based on constant
+ is_updated_ = SolveHorizontalTensionFromConstant();
+ if (is_updated_ == false) {
return false;
}
-
- // solves for the horizontal tension
- if (constraint_->type_limit
- == CableConstraint::LimitType::kCatenaryConstant) {
-
- is_updated_catenary_ = SolveHorizontalTensionFromConstant();
- if (is_updated_catenary_ == false) {
- return false;
- }
-
- } else if (constraint_->type_limit
- == CableConstraint::LimitType::kHorizontalTension) {
-
- catenary_.set_tension_horizontal(constraint_->limit);
-
- } else if (constraint_->type_limit
- == CableConstraint::LimitType::kLength) {
-
- is_updated_catenary_ = SolveHorizontalTensionFromLength();
- if (is_updated_catenary_ == false) {
- return false;
- }
-
- } else if (constraint_->type_limit == CableConstraint::LimitType::kSag) {
-
- is_updated_catenary_ = SolveHorizontalTensionFromSag();
- if (is_updated_catenary_ == false) {
- return false;
- }
-
- } else if (constraint_->type_limit
- == CableConstraint::LimitType::kSupportTension) {
-
- is_updated_catenary_ = SolveHorizontalTensionFromSupportTension();
- if (is_updated_catenary_ == false) {
- return false;
- }
-
- } else {
+ } else if (type_target_ == CatenarySolver::TargetType::kLength) {
+ // solves for horizontal tension based on length
+ is_updated_ = SolveHorizontalTensionFromLength();
+ if (is_updated_ == false) {
return false;
}
-
- // validates catenary to make sure that H/w is valid
- if (catenary_.Validate(false, nullptr) == false) {
+ } else if (type_target_ == CatenarySolver::TargetType::kSag) {
+ // solves for horizontal tension based on sag
+ is_updated_ = SolveHorizontalTensionFromSag();
+ if (is_updated_ == false) {
+ return false;
+ }
+ } else if (type_target_ == CatenarySolver::TargetType::kTension) {
+ // solves for horizontal tension based on tension
+ is_updated_ = SolveHorizontalTensionFromTension();
+ if (is_updated_ == false) {
return false;
}
+ } else {
+ return false;
+ }
+
+ // validates catenary to make sure that H/w is valid
+ if (catenary_.Validate(false, nullptr) == false) {
+ return false;
}
// if it reaches this point, update was successful
@@ -499,20 +519,26 @@ double CatenarySolver::UpdateCatenaryLength(
return catenary_.Length();
}
-double CatenarySolver::UpdateCatenaryMaxTension(
- const double& tension_horizontal) const {
+double CatenarySolver::UpdateCatenarySag(
+ const double& tension_horizontal,
+ const double& position_fraction) const {
// updates catenary
catenary_.set_tension_horizontal(tension_horizontal);
- // returns support tension
- return catenary_.TensionMax();
+ // returns sag at specified position
+ if (position_target_ == -1) {
+ return catenary_.Sag();
+ } else {
+ return catenary_.Sag(position_fraction);
+ }
}
-double CatenarySolver::UpdateCatenarySag(
- const double& tension_horizontal) const {
+double CatenarySolver::UpdateCatenaryTension(
+ const double& tension_horizontal,
+ const double& position_fraction) const {
// updates catenary
catenary_.set_tension_horizontal(tension_horizontal);
- // returns sag
- return catenary_.Sag();
+ // returns tension at specified position
+ return catenary_.Tension(position_fraction);
}
diff --git a/src/transmissionline/line_cable.cc b/src/transmissionline/line_cable.cc
index d99f30b..6209977 100644
--- a/src/transmissionline/line_cable.cc
+++ b/src/transmissionline/line_cable.cc
@@ -5,6 +5,7 @@
#include
+#include "models/transmissionline/cable_unit_load_solver.h"
#include "models/transmissionline/catenary_solver.h"
#include "models/transmissionline/line_structure.h"
@@ -52,6 +53,56 @@ int LineCable::AddConnection(const LineCableConnection& connection) {
return std::distance(connections_.begin(), iter) - 1;
}
+Catenary3d LineCable::CatenaryRulingSpan() const {
+ // initializes
+ Catenary3d catenary;
+ catenary.set_spacing_endpoints(spacing_attachments_ruling_span_);
+
+ // solves for the unit loads
+ CableUnitLoadSolver solver_unit_loads;
+ solver_unit_loads.set_diameter_cable(&cable_->diameter);
+ solver_unit_loads.set_weight_unit_cable(&cable_->weight_unit);
+
+ Vector3d load_unit = solver_unit_loads.UnitCableLoad(
+ *constraint_.case_weather);
+ catenary.set_weight_unit(load_unit);
+
+ // solves for the horizontal tension
+ CatenarySolver solver_tension;
+ solver_tension.set_spacing_endpoints(catenary.spacing_endpoints());
+ solver_tension.set_value_target(constraint_.limit);
+ solver_tension.set_weight_unit(load_unit);
+
+ if (constraint_.type_limit == CableConstraint::LimitType::kCatenaryConstant) {
+ // sets up solver for an analysis target type
+ solver_tension.set_type_target(CatenarySolver::TargetType::kConstant);
+ } else if (constraint_.type_limit
+ == CableConstraint::LimitType::kHorizontalTension) {
+ // horizontal tension is already known
+ catenary.set_tension_horizontal(constraint_.limit);
+ return catenary;
+ } else if (constraint_.type_limit == CableConstraint::LimitType::kLength) {
+ // sets up the solver for a length target type
+ solver_tension.set_type_target(CatenarySolver::TargetType::kLength);
+ } else if (constraint_.type_limit == CableConstraint::LimitType::kSag) {
+ // sets up the solver for a sag target type
+ solver_tension.set_type_target(CatenarySolver::TargetType::kSag);
+ } else if (constraint_.type_limit
+ == CableConstraint::LimitType::kSupportTension) {
+ // sets up the solver for a tension target type
+ solver_tension.set_type_target(CatenarySolver::TargetType::kTension);
+
+ if (spacing_attachments_ruling_span_.z() <= 0) {
+ solver_tension.set_position_target(0);
+ } else {
+ solver_tension.set_position_target(1);
+ }
+ }
+
+ catenary.set_tension_horizontal(solver_tension.TensionHorizontal());
+ return catenary;
+}
+
void LineCable::ClearConnections() {
connections_.clear();
}
@@ -176,13 +227,10 @@ bool LineCable::Validate(const bool& is_included_warnings,
return is_valid;
}
- // validates if catenary can be solved for with contraint and ruling
+ // validates if catenary can be solved for with constraint and ruling
// span geometry
- CatenarySolver solver;
- solver.set_cable(cable_);
- solver.set_constraint(&constraint_);
- solver.set_spacing_attachments(&spacing_attachments_ruling_span_);
- if (solver.Validate(is_included_warnings, messages) == false) {
+ Catenary3d catenary = CatenaryRulingSpan();
+ if (catenary.Validate(is_included_warnings, messages) == false) {
is_valid = false;
}
diff --git a/test/sagtension/line_cable_loader_base_test.cc b/test/sagtension/line_cable_loader_base_test.cc
new file mode 100644
index 0000000..2945d5b
--- /dev/null
+++ b/test/sagtension/line_cable_loader_base_test.cc
@@ -0,0 +1,130 @@
+// This is free and unencumbered software released into the public domain.
+// For more information, please refer to
+
+#include "models/sagtension/line_cable_loader_base.h"
+
+#include "gtest/gtest.h"
+
+#include "factory.h"
+#include "models/base/helper.h"
+
+class LineCableLoaderBaseTest : public ::testing::Test {
+ protected:
+ LineCableLoaderBaseTest() {
+ // gets line cable from factory
+ linecable_ = factory::BuildLineCable();
+
+ // builds fixture object
+ l_.set_line_cable(linecable_);
+ }
+
+ ~LineCableLoaderBaseTest() {
+ factory::DestroyLineCable(linecable_);
+ }
+
+ // allocated dependency objects
+ LineCable* linecable_;
+
+ // test object
+ LineCableLoaderBase l_;
+};
+
+TEST_F(LineCableLoaderBaseTest, StateStretchCreep) {
+ double value = -999999;
+ CableConstraint constraint = linecable_->constraint();
+ CableStretchState state;
+
+ // checks state with constraint type and limit set to initial condition
+ constraint.condition = CableConditionType::kInitial;
+ constraint.limit = 6000;
+ linecable_->set_constraint(constraint);
+ l_.set_line_cable(linecable_);
+
+ state = l_.StretchStateCreep();
+ value = state.temperature;
+ EXPECT_EQ(60, helper::Round(value, 0));
+ EXPECT_EQ(SagTensionCableComponent::PolynomialType::kCreep,
+ state.type_polynomial);
+ value = state.load;
+ EXPECT_EQ(5595, helper::Round(value, 0));
+
+ // checks state with constraint type and limit set to load condition
+ constraint.condition = CableConditionType::kLoad;
+ constraint.limit = 5561.5;
+ linecable_->set_constraint(constraint);
+ l_.set_line_cable(linecable_);
+
+ state = l_.StretchStateCreep();
+ value = state.temperature;
+ EXPECT_EQ(60, helper::Round(value, 0));
+ EXPECT_EQ(SagTensionCableComponent::PolynomialType::kCreep,
+ state.type_polynomial);
+ value = state.load;
+ EXPECT_EQ(5595, helper::Round(value, 0));
+
+ // checks state with constraint type and limit set to creep condition
+ constraint.condition = CableConditionType::kCreep;
+ constraint.limit = 5582.25;
+ linecable_->set_constraint(constraint);
+ l_.set_line_cable(linecable_);
+
+ state = l_.StretchStateCreep();
+ value = state.temperature;
+ EXPECT_EQ(60, helper::Round(value, 0));
+ EXPECT_EQ(SagTensionCableComponent::PolynomialType::kCreep,
+ state.type_polynomial);
+ value = state.load;
+ EXPECT_EQ(5595, helper::Round(value, 0));
+}
+
+TEST_F(LineCableLoaderBaseTest, StateStretchLoad) {
+ double value = -999999;
+ CableConstraint constraint = linecable_->constraint();
+ CableStretchState state;
+
+ // checks state with constraint type and limit set to initial condition
+ constraint.condition = CableConditionType::kInitial;
+ constraint.limit = 6000;
+ linecable_->set_constraint(constraint);
+ l_.set_line_cable(linecable_);
+
+ state = l_.StretchStateLoad();
+ value = state.temperature;
+ EXPECT_EQ(0, helper::Round(value, 0));
+ EXPECT_EQ(SagTensionCableComponent::PolynomialType::kLoadStrain,
+ state.type_polynomial);
+ value = state.load;
+ EXPECT_EQ(12179, helper::Round(value, 0));
+
+ // checks state with constraint type and limit set to load condition
+ constraint.condition = CableConditionType::kLoad;
+ constraint.limit = 5561.5;
+ linecable_->set_constraint(constraint);
+ l_.set_line_cable(linecable_);
+
+ state = l_.StretchStateLoad();
+ value = state.temperature;
+ EXPECT_EQ(0, helper::Round(value, 0));
+ EXPECT_EQ(SagTensionCableComponent::PolynomialType::kLoadStrain,
+ state.type_polynomial);
+ value = state.load;
+ EXPECT_EQ(12179, helper::Round(value, 0));
+
+ // checks state with constraint type and limit set to creep condition
+ constraint.condition = CableConditionType::kCreep;
+ constraint.limit = 5582.25;
+ linecable_->set_constraint(constraint);
+ l_.set_line_cable(linecable_);
+
+ state = l_.StretchStateLoad();
+ value = state.temperature;
+ EXPECT_EQ(0, helper::Round(value, 0));
+ EXPECT_EQ(SagTensionCableComponent::PolynomialType::kLoadStrain,
+ state.type_polynomial);
+ value = state.load;
+ EXPECT_EQ(12179, helper::Round(value, 0));
+}
+
+TEST_F(LineCableLoaderBaseTest, Validate) {
+ EXPECT_TRUE(l_.Validate(true, nullptr));
+}
diff --git a/test/sagtension/line_cable_reloader_test.cc b/test/sagtension/line_cable_reloader_test.cc
index e9136b4..449478a 100644
--- a/test/sagtension/line_cable_reloader_test.cc
+++ b/test/sagtension/line_cable_reloader_test.cc
@@ -49,26 +49,6 @@ TEST_F(LineCableReloaderTest, CatenaryReloaded) {
// more reloading tests are done in the horizontal tension test
}
-TEST_F(LineCableReloaderTest, LengthUnloadedConstraint) {
- const double value = l_.LengthUnloadedConstraint();
- EXPECT_EQ(1201.04, helper::Round(value, 2));
-}
-
-TEST_F(LineCableReloaderTest, LengthUnloadedReloaded) {
- // updates reloader weathercase and condition
- weathercase_reloaded_->description = "0-0-212";
- weathercase_reloaded_->thickness_ice = 0;
- weathercase_reloaded_->density_ice = 0;
- weathercase_reloaded_->pressure_wind = 0;
- weathercase_reloaded_->temperature_cable = 212;
-
- l_.set_weathercase_reloaded(weathercase_reloaded_);
- l_.set_condition_reloaded(CableConditionType::kLoad);
-
- const double value = l_.LengthUnloadedReloaded();
- EXPECT_EQ(1202.26, helper::Round(value, 2));
-}
-
TEST_F(LineCableReloaderTest, StateReloaded) {
CableState state = l_.StateReloaded();
@@ -79,36 +59,6 @@ TEST_F(LineCableReloaderTest, StateReloaded) {
state.type_polynomial);
}
-TEST_F(LineCableReloaderTest, StateStretchCreep) {
- double value = -999999;
-
- CableStretchState state = l_.StretchStateCreep();
-
- value = state.temperature;
- EXPECT_EQ(60, helper::Round(value, 0));
-
- EXPECT_EQ(SagTensionCableComponent::PolynomialType::kCreep,
- state.type_polynomial);
-
- value = state.load;
- EXPECT_EQ(5595, helper::Round(value, 0));
-}
-
-TEST_F(LineCableReloaderTest, StateStretchLoad) {
- double value = -999999;
-
- CableStretchState state = l_.StretchStateLoad();
-
- value = state.temperature;
- EXPECT_EQ(0, helper::Round(value, 0));
-
- EXPECT_EQ(SagTensionCableComponent::PolynomialType::kLoadStrain,
- state.type_polynomial);
-
- value = state.load;
- EXPECT_EQ(12179, helper::Round(value, 0));
-}
-
TEST_F(LineCableReloaderTest, TensionAverageComponent) {
double value = -999999;
@@ -123,14 +73,8 @@ TEST_F(LineCableReloaderTest, TensionAverageComponent) {
TEST_F(LineCableReloaderTest, TensionHorizontal) {
double value = -999999;
- CableConstraint constraint = linecable_->constraint();
-
- // changes the constraint type and limit to initial condition
- constraint.condition = CableConditionType::kInitial;
- constraint.limit = 6000;
- linecable_->set_constraint(constraint);
- l_.set_line_cable(linecable_);
+ // reloads at same case as constraint, checks all conditions
weathercase_reloaded_->description = "0-0-60";
weathercase_reloaded_->thickness_ice = 0;
weathercase_reloaded_->density_ice = 0;
@@ -138,7 +82,6 @@ TEST_F(LineCableReloaderTest, TensionHorizontal) {
weathercase_reloaded_->temperature_cable = 60;
l_.set_weathercase_reloaded(weathercase_reloaded_);
- // reloads at same case as constraint, checks all conditions
l_.set_condition_reloaded(CableConditionType::kInitial);
value = l_.TensionHorizontal();
EXPECT_EQ(6000, helper::Round(value, 0));
@@ -191,58 +134,6 @@ TEST_F(LineCableReloaderTest, TensionHorizontal) {
l_.set_condition_reloaded(CableConditionType::kCreep);
value = l_.TensionHorizontal();
EXPECT_EQ(17123, helper::Round(value, 0));
-
- // changes the constraint type and limit to stretched load condition
- constraint.condition = CableConditionType::kLoad;
- constraint.limit = 5561.5;
- linecable_->set_constraint(constraint);
- l_.set_line_cable(linecable_);
-
- // reloads at same case as constraint, checks all conditions
- weathercase_reloaded_->description = "0-0-60";
- weathercase_reloaded_->thickness_ice = 0;
- weathercase_reloaded_->density_ice = 0;
- weathercase_reloaded_->pressure_wind = 0;
- weathercase_reloaded_->temperature_cable = 60;
- l_.set_weathercase_reloaded(weathercase_reloaded_);
-
- l_.set_condition_reloaded(CableConditionType::kInitial);
- value = l_.TensionHorizontal();
- EXPECT_EQ(6000, helper::Round(value, 0));
-
- l_.set_condition_reloaded(CableConditionType::kLoad);
- value = l_.TensionHorizontal();
- EXPECT_EQ(5561, helper::Round(value, 0));
-
- l_.set_condition_reloaded(CableConditionType::kCreep);
- value = l_.TensionHorizontal();
- EXPECT_EQ(5582, helper::Round(value, 0));
-
- // changes the constraint type and limit to stretched creep condition
- constraint.condition = CableConditionType::kCreep;
- constraint.limit = 5582.25;
- linecable_->set_constraint(constraint);
- l_.set_line_cable(linecable_);
-
- // reloads at same case as constraint, checks all conditions
- weathercase_reloaded_->description = "0-0-60";
- weathercase_reloaded_->thickness_ice = 0;
- weathercase_reloaded_->density_ice = 0;
- weathercase_reloaded_->pressure_wind = 0;
- weathercase_reloaded_->temperature_cable = 60;
- l_.set_weathercase_reloaded(weathercase_reloaded_);
-
- l_.set_condition_reloaded(CableConditionType::kInitial);
- value = l_.TensionHorizontal();
- EXPECT_EQ(6000, helper::Round(value, 0));
-
- l_.set_condition_reloaded(CableConditionType::kLoad);
- value = l_.TensionHorizontal();
- EXPECT_EQ(5562, helper::Round(value, 0));
-
- l_.set_condition_reloaded(CableConditionType::kCreep);
- value = l_.TensionHorizontal();
- EXPECT_EQ(5582, helper::Round(value, 0));
}
TEST_F(LineCableReloaderTest, TensionHorizontalComponent) {
diff --git a/test/sagtension/line_cable_unloader_test.cc b/test/sagtension/line_cable_unloader_test.cc
new file mode 100644
index 0000000..6cb61bc
--- /dev/null
+++ b/test/sagtension/line_cable_unloader_test.cc
@@ -0,0 +1,69 @@
+// This is free and unencumbered software released into the public domain.
+// For more information, please refer to
+
+#include "models/sagtension/line_cable_unloader.h"
+
+#include "gtest/gtest.h"
+
+#include "factory.h"
+#include "models/base/helper.h"
+
+class LineCableUnloaderTest : public ::testing::Test {
+ protected:
+ LineCableUnloaderTest() {
+ // gets a sag-tension cable from factory and removes compression
+ cable_ = factory::BuildCable();
+ cable_->component_core.modulus_compression_elastic_area = 0;
+ cable_->component_shell.modulus_compression_elastic_area = 0;
+
+ // gets line cable from factory
+ // replaces with custom cable
+ linecable_ = factory::BuildLineCable();
+ linecable_->set_cable(cable_);
+
+ // builds fixture object
+ l_.set_line_cable(linecable_);
+ l_.set_condition_unloaded(CableConditionType::kInitial);
+ l_.set_spacing_attachments(Vector3d(1500, 0, 0));
+ l_.set_temperature_unloaded(60);
+ }
+
+ ~LineCableUnloaderTest() {
+ factory::DestroyLineCable(linecable_);
+ }
+
+ // allocated dependency objects
+ Cable* cable_;
+ LineCable* linecable_;
+
+ // test object
+ LineCableUnloader l_;
+};
+
+TEST_F(LineCableUnloaderTest, LengthUnloaded) {
+ double value = -999999;
+
+ // the following results aren't intuitive, but still provide a benchmark
+ //
+ // for this fixture temperature, the cable core defines the unloaded strain
+ // the cable core slope is above and below the tension modulus at varying
+ // strain points, making the unloaded lengths unpredictable between the
+ // different conditions
+
+ // checks all conditions
+ l_.set_condition_unloaded(CableConditionType::kInitial);
+ value = l_.LengthUnloaded();
+ EXPECT_EQ(1502.973, helper::Round(value, 3));
+
+ l_.set_condition_unloaded(CableConditionType::kCreep);
+ value = l_.LengthUnloaded();
+ EXPECT_EQ(1502.951, helper::Round(value, 3));
+
+ l_.set_condition_unloaded(CableConditionType::kLoad);
+ value = l_.LengthUnloaded();
+ EXPECT_EQ(1502.916, helper::Round(value, 3));
+}
+
+TEST_F(LineCableUnloaderTest, Validate) {
+ EXPECT_TRUE(l_.Validate(true, nullptr));
+}
diff --git a/test/test.cbp b/test/test.cbp
index f3207f2..2566acf 100644
--- a/test/test.cbp
+++ b/test/test.cbp
@@ -93,12 +93,18 @@
+
+
+
+
+
+
@@ -144,7 +150,7 @@
-
+
diff --git a/test/test.vcxproj b/test/test.vcxproj
index 3d2e24d..a4e53d4 100644
--- a/test/test.vcxproj
+++ b/test/test.vcxproj
@@ -109,8 +109,10 @@
+
+
@@ -126,7 +128,7 @@
-
+
diff --git a/test/test.vcxproj.filters b/test/test.vcxproj.filters
index 1c76a3d..3abf62e 100644
--- a/test/test.vcxproj.filters
+++ b/test/test.vcxproj.filters
@@ -75,9 +75,6 @@
Tests TransmissionLine
-
- Tests TransmissionLine
-
Tests TransmissionLine
@@ -141,5 +138,14 @@
Tests ThermalRating
+
+ Tests TransmissionLine
+
+
+ Tests SagTension
+
+
+ Tests SagTension
+
\ No newline at end of file
diff --git a/test/transmissionline/cable_unit_load_calculator_test.cc b/test/transmissionline/cable_unit_load_solver_test.cc
similarity index 84%
rename from test/transmissionline/cable_unit_load_calculator_test.cc
rename to test/transmissionline/cable_unit_load_solver_test.cc
index 56ea86e..7b28f1f 100644
--- a/test/transmissionline/cable_unit_load_calculator_test.cc
+++ b/test/transmissionline/cable_unit_load_solver_test.cc
@@ -1,7 +1,7 @@
// This is free and unencumbered software released into the public domain.
// For more information, please refer to
-#include "models/transmissionline/cable_unit_load_calculator.h"
+#include "models/transmissionline/cable_unit_load_solver.h"
#include "gtest/gtest.h"
@@ -9,16 +9,16 @@
#include "models/base/helper.h"
#include "models/base/units.h"
-class CableUnitLoadCalculatorTest : public ::testing::Test {
+class CableUnitLoadSolverTest : public ::testing::Test {
protected:
- CableUnitLoadCalculatorTest() {
+ CableUnitLoadSolverTest() {
cable_ = factory::BuildCable();
c_.set_diameter_cable(&cable_->diameter);
c_.set_weight_unit_cable(&cable_->weight_unit);
}
- ~CableUnitLoadCalculatorTest() {
+ ~CableUnitLoadSolverTest() {
delete cable_;
}
@@ -26,10 +26,10 @@ class CableUnitLoadCalculatorTest : public ::testing::Test {
const Cable* cable_;
// test object
- CableUnitLoadCalculator c_;
+ CableUnitLoadSolver c_;
};
-TEST_F(CableUnitLoadCalculatorTest, UnitCableLoad) {
+TEST_F(CableUnitLoadSolverTest, UnitCableLoad) {
Vector3d load_unit;
// ice only
@@ -71,6 +71,6 @@ TEST_F(CableUnitLoadCalculatorTest, UnitCableLoad) {
EXPECT_EQ(2.099, helper::Round(load_unit.z(), 3));
}
-TEST_F(CableUnitLoadCalculatorTest, Validate) {
+TEST_F(CableUnitLoadSolverTest, Validate) {
EXPECT_TRUE(c_.Validate(true, nullptr));
}
diff --git a/test/transmissionline/catenary_solver_test.cc b/test/transmissionline/catenary_solver_test.cc
index d2ab6ce..9fde715 100644
--- a/test/transmissionline/catenary_solver_test.cc
+++ b/test/transmissionline/catenary_solver_test.cc
@@ -5,101 +5,63 @@
#include "gtest/gtest.h"
-#include "factory.h"
#include "models/base/helper.h"
-#include "models/base/units.h"
class CatenarySolverTest : public ::testing::Test {
protected:
CatenarySolverTest() {
- // builds dependency object - line cable
- cable_ = factory::BuildCable();
-
- weathercase_ = new WeatherLoadCase();
- weathercase_->description = "0.5-8-0";
- weathercase_->thickness_ice =
- units::ConvertLength(0.5, units::LengthConversionType::kInchesToFeet);
- weathercase_->density_ice = 57.3;
- weathercase_->pressure_wind = 8;
- weathercase_->temperature_cable = 0;
-
- constraint_ = new CableConstraint();
- constraint_->case_weather = weathercase_;
- constraint_->condition = CableConditionType::kInitial;
- constraint_->limit = 4000;
- constraint_->type_limit = CableConstraint::LimitType::kCatenaryConstant;
-
- spacing_attachments_ = new Vector3d(1200, 0, 0);
-
// builds fixture object
- c_.set_cable(cable_);
- c_.set_constraint(constraint_);
- c_.set_spacing_attachments(spacing_attachments_);
+ c_.set_position_target(0);
+ c_.set_spacing_endpoints(Vector3d(1200, 0, 0));
+ c_.set_type_target(CatenarySolver::TargetType::kConstant);
+ c_.set_value_target(4000);
+ c_.set_weight_unit(Vector3d(0, 0, 1));
}
~CatenarySolverTest() {
- delete cable_;
- delete constraint_;
- delete spacing_attachments_;
- delete weathercase_;
}
- // allocated dependency objects
- const Cable* cable_;
- CableConstraint* constraint_;
- Vector3d* spacing_attachments_;
- WeatherLoadCase* weathercase_;
-
// test object
CatenarySolver c_;
};
TEST_F(CatenarySolverTest, Catenary) {
- // gets catenary and saves values for comparison
+ // gets catenary and checks horizontal tension
Catenary3d catenary = c_.Catenary();
+ double value = catenary.tension_horizontal();
+ EXPECT_EQ(4000.0, helper::Round(value, 1));
+}
- // weight
- Vector3d weight_unit = catenary.weight_unit();
- EXPECT_EQ(0, helper::Round(weight_unit.x(), 3));
- EXPECT_EQ(1.405, helper::Round(weight_unit.y(), 3));
- EXPECT_EQ(2.099, helper::Round(weight_unit.z(), 3));
-
- // spacing
- Vector3d spacing = catenary.spacing_endpoints();
- EXPECT_EQ(1200, helper::Round(spacing.x(), 0));
- EXPECT_EQ(0, helper::Round(spacing.y(), 0));
- EXPECT_EQ(0, helper::Round(spacing.z(), 0));
-
- // horizontal tension - from catenary constant type constraint
- EXPECT_EQ(10104.3, helper::Round(catenary.tension_horizontal(), 1));
-
- // horizontal tension - from horizontal tension type constraint
- constraint_->limit = 10104.3;
- constraint_->type_limit = CableConstraint::LimitType::kHorizontalTension;
- c_.set_constraint(constraint_);
- catenary = c_.Catenary();
- EXPECT_EQ(10104.3, helper::Round(catenary.tension_horizontal(), 1));
-
- // horizontal tension - from length type constraint
- constraint_->limit = 1204.5051;
- constraint_->type_limit = CableConstraint::LimitType::kLength;
- c_.set_constraint(constraint_);
- catenary = c_.Catenary();
- EXPECT_EQ(10104.3, helper::Round(catenary.tension_horizontal(), 1));
-
- // horizontal tension - from sag type constraint
- constraint_->limit = 45.0844;
- constraint_->type_limit = CableConstraint::LimitType::kSag;
- c_.set_constraint(constraint_);
- catenary = c_.Catenary();
- EXPECT_EQ(10104.3, helper::Round(catenary.tension_horizontal(), 1));
-
- // horizontal tension - from support tension type constraint
- constraint_->limit = 10218.2;
- constraint_->type_limit = CableConstraint::LimitType::kSupportTension;
- c_.set_constraint(constraint_);
- catenary = c_.Catenary();
- EXPECT_EQ(10104.3, helper::Round(catenary.tension_horizontal(), 1));
+TEST_F(CatenarySolverTest, TensionHorizontal) {
+ double value = -999999;
+
+ // checks catenary constant type
+ c_.set_position_target(-1);
+ c_.set_type_target(CatenarySolver::TargetType::kConstant);
+ c_.set_value_target(4000);
+ value = c_.TensionHorizontal();
+ EXPECT_EQ(4000.0, helper::Round(value, 1));
+
+ // checks length type
+ c_.set_position_target(-1);
+ c_.set_type_target(CatenarySolver::TargetType::kLength);
+ c_.set_value_target(1204.505065);
+ value = c_.TensionHorizontal();
+ EXPECT_EQ(4000.0, helper::Round(value, 1));
+
+ // checks sag type
+ c_.set_position_target(-1);
+ c_.set_type_target(CatenarySolver::TargetType::kSag);
+ c_.set_value_target(45.08438);
+ value = c_.TensionHorizontal();
+ EXPECT_EQ(4000.0, helper::Round(value, 1));
+
+ // checks tension type
+ c_.set_position_target(0);
+ c_.set_type_target(CatenarySolver::TargetType::kTension);
+ c_.set_value_target(4045.084438);
+ value = c_.TensionHorizontal();
+ EXPECT_EQ(4000.0, helper::Round(value, 1));
}
TEST_F(CatenarySolverTest, Validate) {
diff --git a/test/transmissionline/catenary_test.cc b/test/transmissionline/catenary_test.cc
index 411ac09..10a5720 100644
--- a/test/transmissionline/catenary_test.cc
+++ b/test/transmissionline/catenary_test.cc
@@ -51,7 +51,7 @@ TEST_F(Catenary2dTest, Coordinate) {
EXPECT_EQ(0, helper::Round(coord.x, 1));
EXPECT_EQ(0, helper::Round(coord.y, 1));
- // inclined geometry
+ // inclined geometry - origin between end points
Vector2d spacing(1000, 100);
c_.set_spacing_endpoints(spacing);
@@ -66,6 +66,54 @@ TEST_F(Catenary2dTest, Coordinate) {
coord = c_.Coordinate(1, true);
EXPECT_EQ(1000, helper::Round(coord.x, 1));
EXPECT_EQ(100, helper::Round(coord.y, 1));
+
+ // inclined geometry - origin beyond end points
+ spacing = Vector2d(1000, 300);
+ c_.set_spacing_endpoints(spacing);
+
+ coord = c_.Coordinate(0, true);
+ EXPECT_EQ(0, helper::Round(coord.x, 1));
+ EXPECT_EQ(0, helper::Round(coord.y, 1));
+
+ coord = c_.Coordinate(0.5, true);
+ EXPECT_EQ(517.9, helper::Round(coord.x, 1));
+ EXPECT_EQ(89.8, helper::Round(coord.y, 1));
+
+ coord = c_.Coordinate(1, true);
+ EXPECT_EQ(1000, helper::Round(coord.x, 1));
+ EXPECT_EQ(300, helper::Round(coord.y, 1));
+
+ // declined geometry - origin between end points
+ spacing = Vector2d(1000, -100);
+ c_.set_spacing_endpoints(spacing);
+
+ coord = c_.Coordinate(0, true);
+ EXPECT_EQ(0, helper::Round(coord.x, 1));
+ EXPECT_EQ(0, helper::Round(coord.y, 1));
+
+ coord = c_.Coordinate(0.5, true);
+ EXPECT_EQ(493.8, helper::Round(coord.x, 1));
+ EXPECT_EQ(-112.5, helper::Round(coord.y, 1));
+
+ coord = c_.Coordinate(1, true);
+ EXPECT_EQ(1000, helper::Round(coord.x, 1));
+ EXPECT_EQ(-100, helper::Round(coord.y, 1));
+
+ // declined geometry - origin beyond end points
+ spacing = Vector2d(1000, -300);
+ c_.set_spacing_endpoints(spacing);
+
+ coord = c_.Coordinate(0, true);
+ EXPECT_EQ(0, helper::Round(coord.x, 1));
+ EXPECT_EQ(0, helper::Round(coord.y, 1));
+
+ coord = c_.Coordinate(0.5, true);
+ EXPECT_EQ(482.1, helper::Round(coord.x, 1));
+ EXPECT_EQ(-210.2, helper::Round(coord.y, 1));
+
+ coord = c_.Coordinate(1, true);
+ EXPECT_EQ(1000, helper::Round(coord.x, 1));
+ EXPECT_EQ(-300, helper::Round(coord.y, 1));
}
TEST_F(Catenary2dTest, CoordinateChord) {
@@ -114,6 +162,21 @@ TEST_F(Catenary2dTest, LengthSlack) {
EXPECT_EQ(9.36, helper::Round(c_.LengthSlack(), 2));
}
+TEST_F(Catenary2dTest, Sag) {
+ double value = -999999;
+
+ // checks max sag
+ value = c_.Sag();
+ EXPECT_EQ(62.83, helper::Round(value, 2));
+
+ // checks sag at various position fractions
+ value = c_.Sag(0.25);
+ EXPECT_EQ(46.94, helper::Round(value, 2));
+
+ value = c_.Sag(0.75);
+ EXPECT_EQ(46.94, helper::Round(value, 2));
+}
+
TEST_F(Catenary2dTest, Tension) {
EXPECT_EQ(1031.41, helper::Round(c_.Tension(0), 2));
EXPECT_EQ(1000.00, helper::Round(c_.Tension(0.5), 2));
@@ -256,6 +319,21 @@ TEST_F(Catenary3dTest, CoordinateChord) {
EXPECT_EQ(100, helper::Round(coord.z, 1));
}
+TEST_F(Catenary3dTest, Sag) {
+ double value = -999999;
+
+ // checks max sag
+ value = c_.Sag();
+ EXPECT_EQ(62.83, helper::Round(value, 2));
+
+ // checks sag at various position fractions
+ value = c_.Sag(0.25);
+ EXPECT_EQ(46.94, helper::Round(value, 2));
+
+ value = c_.Sag(0.75);
+ EXPECT_EQ(46.94, helper::Round(value, 2));
+}
+
TEST_F(Catenary3dTest, SwingAngle) {
double value;
diff --git a/test/transmissionline/line_cable_test.cc b/test/transmissionline/line_cable_test.cc
index c527e73..cc12839 100644
--- a/test/transmissionline/line_cable_test.cc
+++ b/test/transmissionline/line_cable_test.cc
@@ -6,6 +6,7 @@
#include "gtest/gtest.h"
#include "factory.h"
+#include "models/base/helper.h"
class LineCableTest : public ::testing::Test {
protected:
@@ -52,6 +53,26 @@ TEST_F(LineCableTest, AddConnection) {
EXPECT_EQ(1, index);
}
+TEST_F(LineCableTest, CatenaryRulingSpan) {
+ Catenary3d catenary = l_->CatenaryRulingSpan();
+
+ // checks tension
+ const double value = catenary.tension_horizontal();
+ EXPECT_EQ(6000.0, helper::Round(value, 1));
+
+ // checks unit weight
+ Vector3d weight_unit = catenary.weight_unit();
+ EXPECT_EQ(0.000, helper::Round(weight_unit.x(), 3));
+ EXPECT_EQ(0.000, helper::Round(weight_unit.y(), 3));
+ EXPECT_EQ(1.094, helper::Round(weight_unit.z(), 3));
+
+ // checks spacing
+ Vector3d spacing = catenary.spacing_endpoints();
+ EXPECT_EQ(1200, helper::Round(spacing.x(), 0));
+ EXPECT_EQ(0, helper::Round(spacing.y(), 0));
+ EXPECT_EQ(0, helper::Round(spacing.z(), 0));
+}
+
TEST_F(LineCableTest, DeleteConnection) {
// deletes a valid connection
EXPECT_TRUE(l_->DeleteConnection(1));