diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fbba2cb6..e964a9d39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,6 +150,7 @@ add_subdirectory(src) # Create examples and tests enable_testing() add_subdirectory(examples) +add_subdirectory(tests) export(EXPORT gridkit-targets FILE ${CMAKE_CURRENT_BINARY_DIR}/GridKitTargets.cmake) diff --git a/src/Model/EvaluatorDynamics.hpp b/src/Model/EvaluatorDynamics.hpp new file mode 100644 index 000000000..ffa7ad7c5 --- /dev/null +++ b/src/Model/EvaluatorDynamics.hpp @@ -0,0 +1,96 @@ +#pragma once + +#include +#include +#include + +namespace GridKit +{ +namespace Model +{ + /*! + * @brief Abstract class describing a model. + * + */ + template + class EvaluatorDynamics + { + public: + typedef typename GridKit::ScalarTraits::real_type real_type; + + EvaluatorDynamics(){} + virtual ~EvaluatorDynamics(){} + + virtual int allocate() = 0; + virtual int initialize() = 0; + virtual int tagDifferentiable() = 0; + virtual int evaluateResidual() = 0; + virtual int evaluateJacobian() = 0; + virtual int evaluateIntegrand() = 0; + + virtual int initializeAdjoint() = 0; + virtual int evaluateAdjointResidual() = 0; + // virtual int evaluateAdjointJacobian() = 0; + virtual int evaluateAdjointIntegrand() = 0; + + virtual IdxT size() = 0; + virtual IdxT nnz() = 0; + + /** + * @brief Is the Jacobian defined. Used in IDA to determine wether DQ is used or not + * + * @return true + * @return false + */ + virtual bool hasJacobian() = 0; + + virtual IdxT sizeQuadrature() = 0; + virtual IdxT sizeParams() = 0; + virtual void updateTime(real_type t, real_type a) = 0; + virtual void setTolerances(real_type& rtol, real_type& atol) const = 0; + virtual void setMaxSteps(IdxT& msa) const = 0; + + virtual std::vector& y() = 0; + virtual const std::vector& y() const = 0; + + virtual std::vector& yp() = 0; + virtual const std::vector& yp() const = 0; + + virtual std::vector& tag() = 0; + virtual const std::vector& tag() const = 0; + + virtual std::vector& yB() = 0; + virtual const std::vector& yB() const = 0; + + virtual std::vector& ypB() = 0; + virtual const std::vector& ypB() const = 0; + + virtual std::vector& param() = 0; + virtual const std::vector& param() const = 0; + + virtual std::vector& param_up() = 0; + virtual const std::vector& param_up() const = 0; + + virtual std::vector& param_lo() = 0; + virtual const std::vector& param_lo() const = 0; + + virtual std::vector& getResidual() = 0; + virtual const std::vector& getResidual() const = 0; + + + virtual COO_Matrix& getJacobian() = 0; + virtual const COO_Matrix& getJacobian() const = 0; + + virtual std::vector& getIntegrand() = 0; + virtual const std::vector& getIntegrand() const = 0; + + virtual std::vector& getAdjointResidual() = 0; + virtual const std::vector& getAdjointResidual() const = 0; + + virtual std::vector& getAdjointIntegrand() = 0; + virtual const std::vector& getAdjointIntegrand() const = 0; + + }; + +} // namespace Model +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/Branch/Branch.cpp b/src/Model/PhasorDynamics/Branch/Branch.cpp index 0433e0caa..522e79906 100644 --- a/src/Model/PhasorDynamics/Branch/Branch.cpp +++ b/src/Model/PhasorDynamics/Branch/Branch.cpp @@ -1,60 +1,10 @@ -/* - * - * Copyright (c) 2017, Lawrence Livermore National Security, LLC. - * Produced at the Lawrence Livermore National Laboratory. - * Written by Slaven Peles and Duan Nan . - * LLNL-CODE-718378. - * All rights reserved. - * - * This file is part of GridKit™. For details, see github.com/LLNL/GridKit - * Please also read the LICENSE file. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the disclaimer below. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the disclaimer (as noted below) in the - * documentation and/or other materials provided with the distribution. - * - Neither the name of the LLNS/LLNL nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL - * SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY - * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * Lawrence Livermore National Laboratory is operated by Lawrence Livermore - * National Security, LLC, for the U.S. Department of Energy, National - * Nuclear Security Administration under Contract DE-AC52-07NA27344. - * - * This document was prepared as an account of work sponsored by an agency - * of the United States government. Neither the United States government nor - * Lawrence Livermore National Security, LLC, nor any of their employees - * makes any warranty, expressed or implied, or assumes any legal liability - * or responsibility for the accuracy, completeness, or usefulness of any - * information, apparatus, product, or process disclosed, or represents that - * its use would not infringe privately owned rights. Reference herein to - * any specific commercial product, process, or service by trade name, - * trademark, manufacturer, or otherwise does not necessarily constitute or - * imply its endorsement, recommendation, or favoring by the United States - * government or Lawrence Livermore National Security, LLC. The views and - * opinions of authors expressed herein do not necessarily state or reflect - * those of the United States government or Lawrence Livermore National - * Security, LLC, and shall not be used for advertising or product - * endorsement purposes. - * +/** + * @file Branch.hpp + * @author Slaven Peles (peless@ornl.gov) + * @brief Definition of a phasor dynamics branch model. + * + * The model uses Cartesian coordinates. + * */ #include @@ -64,161 +14,212 @@ #include "Branch.hpp" -namespace GridKit { -namespace PhasorDynamics { - -/*! - * @brief Constructor for a pi-model branch - * - * Arguments passed to ModelEvaluatorImpl: - * - Number of equations = 0 - * - Number of independent variables = 0 - * - Number of quadratures = 0 - * - Number of optimization parameters = 0 - */ - -template -Branch::Branch(bus_type* bus1, bus_type* bus2) - : R_(0.0), - X_(0.01), - G_(0.0), - B_(0.0), - bus1ID_(0), - bus2ID_(0), - bus1_(bus1), - bus2_(bus2) -{ - size_ = 0; -} - -template -Branch::Branch(real_type R, - real_type X, - real_type G, - real_type B, - bus_type* bus1, - bus_type* bus2) - : R_(R), - X_(X), - G_(G), - B_(B), - bus1ID_(0), - bus2ID_(0), - bus1_(bus1), - bus2_(bus2) -{ -} - -template -Branch::Branch(bus_type* bus1, bus_type* bus2, BranchData& data) - : R_(data.r), - X_(data.x), - G_(0.0), - B_(data.b), - bus1ID_(data.fbus), - bus2ID_(data.tbus), - bus1_(bus1), - bus2_(bus2) -{ - size_ = 0; -} - - -template -Branch::~Branch() -{ - //std::cout << "Destroy Branch..." << std::endl; -} - -/*! - * @brief allocate method computes sparsity pattern of the Jacobian. - */ -template -int Branch::allocate() -{ - //std::cout << "Allocate Branch..." << std::endl; - return 0; -} - -/** - * Initialization of the branch model - * - */ -template -int Branch::initialize() -{ - return 0; -} - -/** - * \brief Identify differential variables. - */ -template -int Branch::tagDifferentiable() -{ - return 0; -} - -/** - * \brief Residual contribution of the branch is pushed to the - * two terminal buses. - * - * @todo Add and verify conductance to ground (B and G) - */ -template -int Branch::evaluateResidual() +namespace GridKit { - // std::cout << "Evaluating branch residual ...\n"; - real_type b = -X_/(R_*R_ + X_*X_); - real_type g = R_/(R_*R_ + X_*X_); - - Ir1() += -(g + 0.5*G_)*Vr1() + (b + 0.5*B_)*Vi1() + g*Vr2() - b*Vi2(); - Ii1() += -(b + 0.5*B_)*Vr1() - (g + 0.5*G_)*Vi1() + b*Vr2() + g*Vi2(); - Ir2() += g*Vr1() - b*Vi1() - (g + 0.5*G_)*Vr2() + (b + 0.5*B_)*Vi2(); - Ii2() += b*Vr1() + g*Vi1() - (b + 0.5*B_)*Vr2() - (g + 0.5*G_)*Vi2(); - - return 0; -} - -template -int Branch::evaluateJacobian() +namespace PhasorDynamics { - std::cout << "Evaluate Jacobian for Branch..." << std::endl; - std::cout << "Jacobian evaluation not implemented!" << std::endl; - return 0; -} - -template -int Branch::evaluateIntegrand() -{ - // std::cout << "Evaluate Integrand for Branch..." << std::endl; - return 0; -} - -template -int Branch::initializeAdjoint() -{ - //std::cout << "Initialize adjoint for Branch..." << std::endl; - return 0; -} - -template -int Branch::evaluateAdjointResidual() -{ - // std::cout << "Evaluate adjoint residual for Branch..." << std::endl; - return 0; -} - -template -int Branch::evaluateAdjointIntegrand() -{ - // std::cout << "Evaluate adjoint Integrand for Branch..." << std::endl; - return 0; -} - -// Available template instantiations -template class Branch; -template class Branch; + /*! + * @brief Constructor for a pi-model branch + * + * Arguments passed to ModelEvaluatorImpl: + * - Number of equations = 0 + * - Number of independent variables = 0 + * - Number of quadratures = 0 + * - Number of optimization parameters = 0 + */ + template + Branch::Branch(bus_type* bus1, bus_type* bus2) + : bus1_(bus1), + bus2_(bus2), + R_(0.0), + X_(0.01), + G_(0.0), + B_(0.0), + bus1ID_(0), + bus2ID_(0) + { + size_ = 0; + } + + /** + * @brief Construct a new Branch + * + * @tparam ScalarT - scalar type + * @tparam IdxT - matrix/vector index type + * @param bus1 - pointer to bus-1 + * @param bus2 - pointer to bus-2 + * @param R - line series resistance + * @param X - line series reactance + * @param G - line shunt conductance + * @param B - line shunt charging + */ + template + Branch::Branch(bus_type* bus1, + bus_type* bus2, + real_type R, + real_type X, + real_type G, + real_type B) + : bus1_(bus1), + bus2_(bus2), + R_(R), + X_(X), + G_(G), + B_(B), + bus1ID_(0), + bus2ID_(0) + { + } + + template + Branch::Branch(bus_type* bus1, bus_type* bus2, BranchData& data) + : bus1_(bus1), + bus2_(bus2), + R_(data.r), + X_(data.x), + G_(0.0), + B_(data.b), + bus1ID_(data.fbus), + bus2ID_(data.tbus) + { + size_ = 0; + } + + /** + * @brief Destroy the Branch + * + * @tparam ScalarT + * @tparam IdxT + */ + template + Branch::~Branch() + { + //std::cout << "Destroy Branch..." << std::endl; + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int Branch::allocate() + { + //std::cout << "Allocate Branch..." << std::endl; + return 0; + } + + /** + * Initialization of the branch model + * + */ + template + int Branch::initialize() + { + return 0; + } + + /** + * \brief Identify differential variables. + */ + template + int Branch::tagDifferentiable() + { + return 0; + } + + /** + * \brief Residual contribution of the branch is pushed to the + * two terminal buses. + * + */ + template + int Branch::evaluateResidual() + { + // std::cout << "Evaluating branch residual ...\n"; + real_type b = -X_/(R_*R_ + X_*X_); + real_type g = R_/(R_*R_ + X_*X_); + + Ir1() += -(g + 0.5*G_)*Vr1() + (b + 0.5*B_)*Vi1() + g*Vr2() - b*Vi2(); + Ii1() += -(b + 0.5*B_)*Vr1() - (g + 0.5*G_)*Vi1() + b*Vr2() + g*Vi2(); + Ir2() += g*Vr1() - b*Vi1() - (g + 0.5*G_)*Vr2() + (b + 0.5*B_)*Vi2(); + Ii2() += b*Vr1() + g*Vi1() - (b + 0.5*B_)*Vr2() - (g + 0.5*G_)*Vi2(); + + return 0; + } + + /** + * @brief Jacobian evaluation not implemented yet + * + * @tparam ScalarT - scalar data type + * @tparam IdxT - matrix index data type + * @return int - error code, 0 = success + */ + template + int Branch::evaluateJacobian() + { + std::cout << "Evaluate Jacobian for Branch..." << std::endl; + std::cout << "Jacobian evaluation not implemented!" << std::endl; + return 0; + } + + /** + * @brief Integrand (objective) evaluation not implemented yet + * + * @tparam ScalarT - scalar data type + * @tparam IdxT - matrix index data type + * @return int - error code, 0 = success + */ + template + int Branch::evaluateIntegrand() + { + // std::cout << "Evaluate Integrand for Branch..." << std::endl; + return 0; + } + + /** + * @brief Adjoint initialization not implemented yet + * + * @tparam ScalarT - scalar data type + * @tparam IdxT - matrix index data type + * @return int - error code, 0 = success + */ + template + int Branch::initializeAdjoint() + { + //std::cout << "Initialize adjoint for Branch..." << std::endl; + return 0; + } + + /** + * @brief Adjoint residual evaluation not implemented yet + * + * @tparam ScalarT - scalar data type + * @tparam IdxT - matrix index data type + * @return int - error code, 0 = success + */ + template + int Branch::evaluateAdjointResidual() + { + // std::cout << "Evaluate adjoint residual for Branch..." << std::endl; + return 0; + } + + /** + * @brief Adjoint integrand (objective) evaluation not implemented yet + * + * @tparam ScalarT - scalar data type + * @tparam IdxT - matrix index data type + * @return int - error code, 0 = success + */ + template + int Branch::evaluateAdjointIntegrand() + { + // std::cout << "Evaluate adjoint Integrand for Branch..." << std::endl; + return 0; + } + + // Available template instantiations + template class Branch; + template class Branch; } //namespace PhasorDynamics } //namespace GridKit diff --git a/src/Model/PhasorDynamics/Branch/Branch.hpp b/src/Model/PhasorDynamics/Branch/Branch.hpp index d1d973e8b..983a85ef1 100644 --- a/src/Model/PhasorDynamics/Branch/Branch.hpp +++ b/src/Model/PhasorDynamics/Branch/Branch.hpp @@ -1,65 +1,14 @@ -/* - * - * Copyright (c) 2017, Lawrence Livermore National Security, LLC. - * Produced at the Lawrence Livermore National Laboratory. - * Written by Slaven Peles and Duan Nan . - * LLNL-CODE-718378. - * All rights reserved. - * - * This file is part of GridKit™. For details, see github.com/LLNL/GridKit - * Please also read the LICENSE file. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the disclaimer below. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the disclaimer (as noted below) in the - * documentation and/or other materials provided with the distribution. - * - Neither the name of the LLNS/LLNL nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL - * SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY - * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * Lawrence Livermore National Laboratory is operated by Lawrence Livermore - * National Security, LLC, for the U.S. Department of Energy, National - * Nuclear Security Administration under Contract DE-AC52-07NA27344. - * - * This document was prepared as an account of work sponsored by an agency - * of the United States government. Neither the United States government nor - * Lawrence Livermore National Security, LLC, nor any of their employees - * makes any warranty, expressed or implied, or assumes any legal liability - * or responsibility for the accuracy, completeness, or usefulness of any - * information, apparatus, product, or process disclosed, or represents that - * its use would not infringe privately owned rights. Reference herein to - * any specific commercial product, process, or service by trade name, - * trademark, manufacturer, or otherwise does not necessarily constitute or - * imply its endorsement, recommendation, or favoring by the United States - * government or Lawrence Livermore National Security, LLC. The views and - * opinions of authors expressed herein do not necessarily state or reflect - * those of the United States government or Lawrence Livermore National - * Security, LLC, and shall not be used for advertising or product - * endorsement purposes. - * +/** + * @file Branch.hpp + * @author Slaven Peles (peless@ornl.gov) + * @brief Declaration of a phasor dynamics branch model. + * + * The model uses Cartesian coordinates. + * */ - #pragma once -#include +#include // Forward declarations. namespace GridKit @@ -82,51 +31,54 @@ namespace GridKit { namespace PhasorDynamics { - /*! + /** * @brief Implementation of a pi-model branch between two buses. + * + * The model is implemented in Cartesian coordinates. Positive current + * direction is into the busses. * */ template - class Branch : public ModelEvaluatorImpl + class Branch : public Component { - using ModelEvaluatorImpl::size_; - using ModelEvaluatorImpl::nnz_; - using ModelEvaluatorImpl::time_; - using ModelEvaluatorImpl::alpha_; - using ModelEvaluatorImpl::y_; - using ModelEvaluatorImpl::yp_; - using ModelEvaluatorImpl::tag_; - using ModelEvaluatorImpl::f_; - using ModelEvaluatorImpl::g_; - using ModelEvaluatorImpl::yB_; - using ModelEvaluatorImpl::ypB_; - using ModelEvaluatorImpl::fB_; - using ModelEvaluatorImpl::gB_; - using ModelEvaluatorImpl::param_; - - using bus_type = Bus; - using real_type = typename ModelEvaluatorImpl::real_type; + using Component::size_; + using Component::nnz_; + using Component::time_; + using Component::alpha_; + using Component::y_; + using Component::yp_; + using Component::tag_; + using Component::f_; + using Component::g_; + using Component::yB_; + using Component::ypB_; + using Component::fB_; + using Component::gB_; + using Component::param_; + + using bus_type = BusBase; + using real_type = typename Component::real_type; using BranchData = GridKit::PowerSystemData::BranchData; public: Branch(bus_type* bus1, bus_type* bus2); - Branch(real_type R, real_type X, real_type G, real_type B, bus_type* bus1, bus_type* bus2); + Branch(bus_type* bus1, bus_type* bus2, real_type R, real_type X, real_type G, real_type B); Branch(bus_type* bus1, bus_type* bus2, BranchData& data); virtual ~Branch(); - int allocate(); - int initialize(); - int tagDifferentiable(); - int evaluateResidual(); - int evaluateJacobian(); - int evaluateIntegrand(); + virtual int allocate() override; + virtual int initialize() override; + virtual int tagDifferentiable() override; + virtual int evaluateResidual() override; + virtual int evaluateJacobian() override; + virtual int evaluateIntegrand() override; - int initializeAdjoint(); - int evaluateAdjointResidual(); - //int evaluateAdjointJacobian(); - int evaluateAdjointIntegrand(); + virtual int initializeAdjoint() override; + virtual int evaluateAdjointResidual() override; + // virtual int evaluateAdjointJacobian() override; + virtual int evaluateAdjointIntegrand() override; - void updateTime(real_type t, real_type a) + virtual void updateTime(real_type /* t */, real_type /* a */) override { } @@ -194,14 +146,14 @@ namespace PhasorDynamics } private: + bus_type* bus1_; + bus_type* bus2_; real_type R_; real_type X_; real_type G_; real_type B_; const IdxT bus1ID_; const IdxT bus2ID_; - bus_type* bus1_; - bus_type* bus2_; }; } // namespace PhasorDynamics diff --git a/src/Model/PhasorDynamics/Branch/CMakeLists.txt b/src/Model/PhasorDynamics/Branch/CMakeLists.txt index ba05a10a9..b3d400e28 100644 --- a/src/Model/PhasorDynamics/Branch/CMakeLists.txt +++ b/src/Model/PhasorDynamics/Branch/CMakeLists.txt @@ -1,59 +1,3 @@ -# -# Copyright (c) 2017, Lawrence Livermore National Security, LLC. -# Produced at the Lawrence Livermore National Laboratory. -# Written by Slaven Peles . -# LLNL-CODE-718378. -# All rights reserved. -# -# This file is part of GridKit™. For details, see github.com/LLNL/GridKit -# Please also read the LICENSE file. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# - Redistributions of source code must retain the above copyright notice, -# this list of conditions and the disclaimer below. -# - Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the disclaimer (as noted below) in the -# documentation and/or other materials provided with the distribution. -# - Neither the name of the LLNS/LLNL nor the names of its contributors may -# be used to endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL -# SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY -# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -# THE POSSIBILITY OF SUCH DAMAGE. -# -# Lawrence Livermore National Laboratory is operated by Lawrence Livermore -# National Security, LLC, for the U.S. Department of Energy, National -# Nuclear Security Administration under Contract DE-AC52-07NA27344. -# -# This document was prepared as an account of work sponsored by an agency -# of the United States government. Neither the United States government nor -# Lawrence Livermore National Security, LLC, nor any of their employees -# makes any warranty, expressed or implied, or assumes any legal liability -# or responsibility for the accuracy, completeness, or usefulness of any -# information, apparatus, product, or process disclosed, or represents that -# its use would not infringe privately owned rights. Reference herein to -# any specific commercial product, process, or service by trade name, -# trademark, manufacturer, or otherwise does not necessarily constitute or -# imply its endorsement, recommendation, or favoring by the United States -# government or Lawrence Livermore National Security, LLC. The views and -# opinions of authors expressed herein do not necessarily state or reflect -# those of the United States government or Lawrence Livermore National -# Security, LLC, and shall not be used for advertising or product -# endorsement purposes. -# # [[ # Author(s): diff --git a/src/Model/PhasorDynamics/Bus/Bus.cpp b/src/Model/PhasorDynamics/Bus/Bus.cpp index ff3f99696..f085b13a8 100644 --- a/src/Model/PhasorDynamics/Bus/Bus.cpp +++ b/src/Model/PhasorDynamics/Bus/Bus.cpp @@ -1,61 +1,3 @@ -/* - * - * Copyright (c) 2017, Lawrence Livermore National Security, LLC. - * Produced at the Lawrence Livermore National Laboratory. - * Written by Slaven Peles . - * LLNL-CODE-718378. - * All rights reserved. - * - * This file is part of GridKit™. For details, see github.com/LLNL/GridKit - * Please also read the LICENSE file. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the disclaimer below. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the disclaimer (as noted below) in the - * documentation and/or other materials provided with the distribution. - * - Neither the name of the LLNS/LLNL nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL - * SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY - * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * Lawrence Livermore National Laboratory is operated by Lawrence Livermore - * National Security, LLC, for the U.S. Department of Energy, National - * Nuclear Security Administration under Contract DE-AC52-07NA27344. - * - * This document was prepared as an account of work sponsored by an agency - * of the United States government. Neither the United States government nor - * Lawrence Livermore National Security, LLC, nor any of their employees - * makes any warranty, expressed or implied, or assumes any legal liability - * or responsibility for the accuracy, completeness, or usefulness of any - * information, apparatus, product, or process disclosed, or represents that - * its use would not infringe privately owned rights. Reference herein to - * any specific commercial product, process, or service by trade name, - * trademark, manufacturer, or otherwise does not necessarily constitute or - * imply its endorsement, recommendation, or favoring by the United States - * government or Lawrence Livermore National Security, LLC. The views and - * opinions of authors expressed herein do not necessarily state or reflect - * those of the United States government or Lawrence Livermore National - * Security, LLC, and shall not be used for advertising or product - * endorsement purposes. - * - */ #include #include @@ -119,7 +61,9 @@ Bus::Bus(ScalarT Vr, ScalarT Vi) */ template Bus::Bus(BusData& data) - : Vr0_(data.Vm * cos(data.Va)), Vi0_(data.Vm * sin(data.Va)) + : BusBase(data.bus_i), + Vr0_(data.Vm * cos(data.Va)), + Vi0_(data.Vm * sin(data.Va)) { //std::cout << "Create Bus..." << std::endl; //std::cout << "Number of equations is " << size_ << std::endl; @@ -153,6 +97,9 @@ int Bus::allocate() } +/*! + * @brief Bus variables are algebraic. + */ template int Bus::tagDifferentiable() { @@ -193,6 +140,19 @@ int Bus::evaluateResidual() return 0; } +/** + * @brief Jacobian evaluation not implemented + * + * @tparam ScalarT - data type for Jacobian elements + * @tparam IdxT - data type for matrix indices + * @return int - error code + */ +template +int Bus::evaluateJacobian() +{ + return 0; +} + /*! * @brief initialize method sets bus variables to stored initial values. @@ -209,6 +169,13 @@ int Bus::initializeAdjoint() return 0; } +/** + * @brief Bus only initializes adjoint residual elements to zero. + * + * @tparam ScalarT - data type for the integrand + * @tparam IdxT - data type for matrix/vector indices + * @return int - error code + */ template int Bus::evaluateAdjointResidual() { @@ -218,6 +185,32 @@ int Bus::evaluateAdjointResidual() return 0; } +/** + * @brief Quadrature evaluation not implemented + * + * @tparam ScalarT - data type for the integrand + * @tparam IdxT - data type for matrix/vector indices + * @return int - error code + */ +template +int Bus::evaluateIntegrand() +{ + return 0; +} + +/** + * @brief Adjoint quadrature evaluation not implemented + * + * @tparam ScalarT - data type for the integrand + * @tparam IdxT - data type for matrix/vector indices + * @return int - error code + */ +template +int Bus::evaluateAdjointIntegrand() +{ + return 0; +} + // Available template instantiations template class Bus; template class Bus; diff --git a/src/Model/PhasorDynamics/Bus/Bus.hpp b/src/Model/PhasorDynamics/Bus/Bus.hpp index 575124e27..1f34a4925 100644 --- a/src/Model/PhasorDynamics/Bus/Bus.hpp +++ b/src/Model/PhasorDynamics/Bus/Bus.hpp @@ -1,65 +1,7 @@ -/* - * - * Copyright (c) 2017, Lawrence Livermore National Security, LLC. - * Produced at the Lawrence Livermore National Laboratory. - * Written by Slaven Peles . - * LLNL-CODE-718378. - * All rights reserved. - * - * This file is part of GridKit™. For details, see github.com/LLNL/GridKit - * Please also read the LICENSE file. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the disclaimer below. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the disclaimer (as noted below) in the - * documentation and/or other materials provided with the distribution. - * - Neither the name of the LLNS/LLNL nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL - * SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY - * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * Lawrence Livermore National Laboratory is operated by Lawrence Livermore - * National Security, LLC, for the U.S. Department of Energy, National - * Nuclear Security Administration under Contract DE-AC52-07NA27344. - * - * This document was prepared as an account of work sponsored by an agency - * of the United States government. Neither the United States government nor - * Lawrence Livermore National Security, LLC, nor any of their employees - * makes any warranty, expressed or implied, or assumes any legal liability - * or responsibility for the accuracy, completeness, or usefulness of any - * information, apparatus, product, or process disclosed, or represents that - * its use would not infringe privately owned rights. Reference herein to - * any specific commercial product, process, or service by trade name, - * trademark, manufacturer, or otherwise does not necessarily constitute or - * imply its endorsement, recommendation, or favoring by the United States - * government or Lawrence Livermore National Security, LLC. The views and - * opinions of authors expressed herein do not necessarily state or reflect - * those of the United States government or Lawrence Livermore National - * Security, LLC, and shall not be used for advertising or product - * endorsement purposes. - * - */ #pragma once -#include +#include // Forward declaration of BusData structure @@ -85,19 +27,19 @@ namespace PhasorDynamics * */ template - class Bus : public ModelEvaluatorImpl + class Bus : public BusBase { - using ModelEvaluatorImpl::size_; - using ModelEvaluatorImpl::y_; - using ModelEvaluatorImpl::yp_; - using ModelEvaluatorImpl::yB_; - using ModelEvaluatorImpl::ypB_; - using ModelEvaluatorImpl::f_; - using ModelEvaluatorImpl::fB_; - using ModelEvaluatorImpl::tag_; + using BusBase::size_; + using BusBase::y_; + using BusBase::yp_; + using BusBase::yB_; + using BusBase::ypB_; + using BusBase::f_; + using BusBase::fB_; + using BusBase::tag_; public: - using real_type = typename ModelEvaluatorImpl::real_type; + using real_type = typename BusBase::real_type; using BusData = GridKit::PowerSystemData::BusData; Bus(); @@ -105,100 +47,103 @@ namespace PhasorDynamics Bus(BusData& data); virtual ~Bus(); - virtual int allocate(); - virtual int tagDifferentiable(); - virtual int initialize(); - virtual int evaluateResidual(); - virtual int initializeAdjoint(); - virtual int evaluateAdjointResidual(); + virtual int allocate() override; + virtual int tagDifferentiable() override; + virtual int initialize() override; + virtual int evaluateResidual() override; + virtual int evaluateIntegrand() override; + virtual int evaluateJacobian() override; + virtual int initializeAdjoint() override; + virtual int evaluateAdjointIntegrand() override; + virtual int evaluateAdjointResidual() override; - virtual ScalarT& Vr() + + virtual int BusType() const override + { + return BusBase::BusType::DEFAULT; + } + + virtual ScalarT& Vr() override { return y_[0]; } - virtual const ScalarT& Vr() const + virtual const ScalarT& Vr() const override { return y_[0]; } - virtual ScalarT& Vi() + virtual ScalarT& Vi() override { return y_[1]; } - virtual const ScalarT& Vi() const + virtual const ScalarT& Vi() const override { return y_[1]; } - virtual ScalarT& Ir() + virtual ScalarT& Ir() override { return f_[0]; } - virtual const ScalarT& Ir() const + virtual const ScalarT& Ir() const override { return f_[0]; } - virtual ScalarT& Ii() + virtual ScalarT& Ii() override { return f_[1]; } - virtual const ScalarT& Ii() const + virtual const ScalarT& Ii() const override { return f_[1]; } - virtual ScalarT& lambdaIr() - { - return yB_[0]; - } - - virtual const ScalarT& lambdaIr() const - { - return yB_[0]; - } + // virtual ScalarT& VrB() override + // { + // return yB_[0]; + // } - virtual ScalarT& lambdaIi() - { - return yB_[1]; - } + // virtual const ScalarT& VrB() const override + // { + // return yB_[0]; + // } - virtual const ScalarT& lambdaIi() const - { - return yB_[1]; - } + // virtual ScalarT& ViB() override + // { + // return yB_[1]; + // } - virtual ScalarT& IrB() - { - return fB_[0]; - } + // virtual const ScalarT& ViB() const override + // { + // return yB_[1]; + // } - virtual const ScalarT& IrB() const - { - return fB_[0]; - } + // virtual ScalarT& IrB() override + // { + // return fB_[0]; + // } - virtual ScalarT& IiB() - { - return fB_[1]; - } + // virtual const ScalarT& IrB() const override + // { + // return fB_[0]; + // } - virtual const ScalarT& IiB() const - { - return fB_[1]; - } + // virtual ScalarT& IiB() override + // { + // return fB_[1]; + // } - // virtual const int BusType() const + // virtual const ScalarT& IiB() const override // { - // return BaseBus::BusType::PQ; + // return fB_[1]; // } private: - // Default initial values for voltage and phase on PQ bus ScalarT Vr0_{0.0}; ScalarT Vi0_{0.0}; diff --git a/src/Model/PhasorDynamics/Bus/BusInfinite.cpp b/src/Model/PhasorDynamics/Bus/BusInfinite.cpp new file mode 100644 index 000000000..ee8e6b2de --- /dev/null +++ b/src/Model/PhasorDynamics/Bus/BusInfinite.cpp @@ -0,0 +1,203 @@ + +#include +#include + +#include +#include "BusInfinite.hpp" + +namespace GridKit +{ +namespace PhasorDynamics +{ + +/*! + * @brief Constructor for an infinite (slack) bus. + * + * The model is using current balance in Cartesian coordinates. + * + * Arguments to be passed to BusBase: + * - Number of equations = 0 (size_) + * - Number of variables = 0 (size_) + * - Number of quadratures = 0 + * - Number of optimization parameters = 0 + */ +template +BusInfinite::BusInfinite() +{ + //std::cout << "Create BusInfinite..." << std::endl; + //std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 0; +} + +/*! + * @brief BusInfinite constructor. + * + * This constructor sets initial values for active and reactive voltage. + * + * Arguments to be passed to BusBase: + * - Number of equations = 0 (size_) + * - Number of variables = 0 (size_) + * - Number of quadratures = 0 + * - Number of optimization parameters = 0 + */ +template +BusInfinite::BusInfinite(ScalarT Vr, ScalarT Vi) + : Vr_(Vr), Vi_(Vi) +{ + //std::cout << "Create BusInfinite..." << std::endl; + //std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 0; +} + +/** + * @brief Construct a new BusInfinite + * + * Arguments to be set in BusBase: + * - Number of equations = 0 (size_) + * - Number of variables = 0 (size_) + * - Number of quadratures = 0 + * - Number of optimization parameters = 0 + + * @tparam ScalarT - type of scalar variables + * @tparam IdxT - type for vector/matrix indices + * @param[in] data - structure with bus data + */ +template +BusInfinite::BusInfinite(BusData& data) + : BusBase(data.bus_i), + Vr_(data.Vm * cos(data.Va)), + Vi_(data.Vm * sin(data.Va)) +{ + size_ = 0; +} + +template +BusInfinite::~BusInfinite() +{ + //std::cout << "Destroy PQ bus ..." << std::endl; +} + +/*! + * @brief allocate method resizes local solution and residual vectors. + */ +template +int BusInfinite::allocate() +{ + //std::cout << "Nothing to allocate for infinite bus ..." << std::endl; + + return 0; +} + + +template +int BusInfinite::tagDifferentiable() +{ + return 0; +} + + +/*! + * @brief initialize method sets bus variables to stored initial values. + */ +template +int BusInfinite::initialize() +{ + // std::cout << "Initialize BusInfinite..." << std::endl; + + return 0; +} + +/*! + * @brief Reset slack currents to zero. + * + * Infinite bus does not compute residuals, so here we just reset + * current values to zero. Components connected to the infinite bus + * will add their currents to Ir_ and Ii_. The resultant will be slack + * current that the infinite bus has to pick up. + * + * @warning This implementation assumes bus residuals are always evaluated + * _before_ component model residuals. + * + */ +template +int BusInfinite::evaluateResidual() +{ + // std::cout << "Evaluating residual of a PQ bus ...\n"; + Ir_ = 0.0; + Ii_ = 0.0; + return 0; +} + +/** + * @brief Jacobian evaluation not implemented + * + * @tparam ScalarT - data type for Jacobian elements + * @tparam IdxT - data type for matrix indices + * @return int - error code + */ +template +int BusInfinite::evaluateJacobian() +{ + return 0; +} + +/*! + * @brief initialize method sets bus variables to stored initial values. + */ +template +int BusInfinite::initializeAdjoint() +{ + // std::cout << "Initialize BusInfinite..." << std::endl; + + return 0; +} + +/** + * @brief BusInfinite only initializes adjoint residual elements to zero. + * + * @tparam ScalarT - data type for the integrand + * @tparam IdxT - data type for matrix/vector indices + * @return int - error code + */ +template +int BusInfinite::evaluateAdjointResidual() +{ + return 0; +} + +/** + * @brief Quadrature evaluation not implemented + * + * @tparam ScalarT - data type for the integrand + * @tparam IdxT - data type for matrix/vector indices + * @return int - error code + */ +template +int BusInfinite::evaluateIntegrand() +{ + return 0; +} + +/** + * @brief Adjoint quadrature evaluation not implemented + * + * @tparam ScalarT - data type for the integrand + * @tparam IdxT - data type for matrix/vector indices + * @return int - error code + */ +template +int BusInfinite::evaluateAdjointIntegrand() +{ + return 0; +} + + +// Available template instantiations +template class BusInfinite; +template class BusInfinite; + +} // namespace PhasorDynamic +} // namespace GridKit + diff --git a/src/Model/PhasorDynamics/Bus/BusInfinite.hpp b/src/Model/PhasorDynamics/Bus/BusInfinite.hpp new file mode 100644 index 000000000..56aa60644 --- /dev/null +++ b/src/Model/PhasorDynamics/Bus/BusInfinite.hpp @@ -0,0 +1,156 @@ + +#pragma once + +#include + + +// Forward declaration of BusData structure +namespace GridKit +{ +namespace PowerSystemData +{ + template + struct BusData; +} +} + +namespace GridKit +{ +namespace PhasorDynamics +{ + /*! + * @brief Implementation of an "infinite" bus. + * + * + * + */ + template + class BusInfinite : public BusBase + { + using BusBase::size_; + using BusBase::y_; + using BusBase::yp_; + using BusBase::yB_; + using BusBase::ypB_; + using BusBase::f_; + using BusBase::fB_; + using BusBase::tag_; + + public: + using real_type = typename BusBase::real_type; + using BusData = GridKit::PowerSystemData::BusData; + + BusInfinite(); + BusInfinite(ScalarT Vr, ScalarT Vi); + BusInfinite(BusData& data); + virtual ~BusInfinite(); + + virtual int allocate() override; + virtual int tagDifferentiable() override; + virtual int initialize() override; + virtual int evaluateResidual() override; + virtual int evaluateIntegrand() override; + virtual int evaluateJacobian() override; + virtual int initializeAdjoint() override; + virtual int evaluateAdjointIntegrand() override; + virtual int evaluateAdjointResidual() override; + + virtual int BusType() const override + { + return BusBase::BusType::SLACK; + } + + virtual ScalarT& Vr() override + { + return Vr_; + } + + virtual const ScalarT& Vr() const override + { + return Vr_; + } + + virtual ScalarT& Vi() override + { + return Vi_; + } + + virtual const ScalarT& Vi() const override + { + return Vi_; + } + + virtual ScalarT& Ir() override + { + return Ir_; + } + + virtual const ScalarT& Ir() const override + { + return Ir_; + } + + virtual ScalarT& Ii() override + { + return Ii_; + } + + virtual const ScalarT& Ii() const override + { + return Ii_; + } + + // virtual ScalarT& VrB() override + // { + // return VrB_; + // } + + // virtual const ScalarT& VrB() const override + // { + // return VrB_; + // } + + // virtual ScalarT& ViB() override + // { + // return ViB_; + // } + + // virtual const ScalarT& ViB() const override + // { + // return ViB_; + // } + + // virtual ScalarT& IrB() override + // { + // return IrB_; + // } + + // virtual const ScalarT& IrB() const override + // { + // return IrB_; + // } + + // virtual ScalarT& IiB() override + // { + // return IiB_; + // } + + // virtual const ScalarT& IiB() const override + // { + // return IiB_; + // } + + private: + ScalarT Vr_{0.0}; + ScalarT Vi_{0.0}; + ScalarT Ir_{0.0}; + ScalarT Ii_{0.0}; + + ScalarT VrB_{0.0}; + ScalarT ViB_{0.0}; + ScalarT IrB_{0.0}; + ScalarT IiB_{0.0}; + }; + +} // PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/Bus/CMakeLists.txt b/src/Model/PhasorDynamics/Bus/CMakeLists.txt index 356b7f517..636d4dd82 100644 --- a/src/Model/PhasorDynamics/Bus/CMakeLists.txt +++ b/src/Model/PhasorDynamics/Bus/CMakeLists.txt @@ -1,68 +1,13 @@ -# -# Copyright (c) 2017, Lawrence Livermore National Security, LLC. -# Produced at the Lawrence Livermore National Laboratory. -# Written by Slaven Peles . -# LLNL-CODE-718378. -# All rights reserved. -# -# This file is part of GridKit™. For details, see github.com/LLNL/GridKit -# Please also read the LICENSE file. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# - Redistributions of source code must retain the above copyright notice, -# this list of conditions and the disclaimer below. -# - Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the disclaimer (as noted below) in the -# documentation and/or other materials provided with the distribution. -# - Neither the name of the LLNS/LLNL nor the names of its contributors may -# be used to endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL -# SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY -# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -# THE POSSIBILITY OF SUCH DAMAGE. -# -# Lawrence Livermore National Laboratory is operated by Lawrence Livermore -# National Security, LLC, for the U.S. Department of Energy, National -# Nuclear Security Administration under Contract DE-AC52-07NA27344. -# -# This document was prepared as an account of work sponsored by an agency -# of the United States government. Neither the United States government nor -# Lawrence Livermore National Security, LLC, nor any of their employees -# makes any warranty, expressed or implied, or assumes any legal liability -# or responsibility for the accuracy, completeness, or usefulness of any -# information, apparatus, product, or process disclosed, or represents that -# its use would not infringe privately owned rights. Reference herein to -# any specific commercial product, process, or service by trade name, -# trademark, manufacturer, or otherwise does not necessarily constitute or -# imply its endorsement, recommendation, or favoring by the United States -# government or Lawrence Livermore National Security, LLC. The views and -# opinions of authors expressed herein do not necessarily state or reflect -# those of the United States government or Lawrence Livermore National -# Security, LLC, and shall not be used for advertising or product -# endorsement purposes. -# - # [[ # Author(s): # - Cameron Rutherford +# - Slaven Peles #]] gridkit_add_library(phasor_dynamics_bus SOURCES Bus.cpp + BusInfinite.cpp OUTPUT_NAME gridkit_phasor_dynamics_bus) diff --git a/src/Model/PhasorDynamics/BusBase.hpp b/src/Model/PhasorDynamics/BusBase.hpp new file mode 100644 index 000000000..6a94c6476 --- /dev/null +++ b/src/Model/PhasorDynamics/BusBase.hpp @@ -0,0 +1,281 @@ +#pragma once + +#include +#include + +namespace GridKit +{ +namespace PhasorDynamics +{ + /*! + * @brief BusBase model implementation base class. + * + */ + template + class BusBase : public Model::EvaluatorDynamics + { + public: + using real_type = typename Model::EvaluatorDynamics::real_type; + + enum BusType{DEFAULT=1, SLACK}; + + BusBase() + : size_(0), + size_quad_(0), + size_param_(0) + { + } + + BusBase(IdxT bus_id) : bus_id_(bus_id) + { + } + + BusBase(IdxT size, IdxT size_quad, IdxT size_param) + : size_(size), + size_quad_(size_quad), + size_param_(size_param), + y_(size_), + yp_(size_), + f_(size_), + g_(size_quad_), + yB_(size_), + ypB_(size_), + fB_(size_), + gB_(size_param_), + J_(COO_Matrix()), + param_(size_param_), + param_up_(size_param_), + param_lo_(size_param_) + { + } + + virtual ~BusBase() + { + } + + /// Pure virtual function, returns bus type (DEFAULT or SLACK). + virtual int BusType() const = 0; + + virtual IdxT size() override + { + return size_; + } + + virtual IdxT nnz() + { + return nnz_; + } + + virtual bool hasJacobian() + { + return false; + } + + virtual IdxT sizeQuadrature() override + { + return size_quad_; + } + + virtual IdxT sizeParams() override + { + return size_param_; + } + + virtual void updateTime(real_type /* t */, real_type /* a */) + { + // No time to update in bus models + } + + virtual void setTolerances(real_type& rtol, real_type& atol) const + { + rtol = rtol_; + atol = atol_; + } + + virtual void setMaxSteps(IdxT& msa) const + { + msa = max_steps_; + } + + virtual ScalarT& Vr() = 0; + virtual const ScalarT& Vr() const = 0; + virtual ScalarT& Vi() = 0; + virtual const ScalarT& Vi() const = 0; + virtual ScalarT& Ir() = 0; + virtual const ScalarT& Ir() const = 0; + virtual ScalarT& Ii() = 0; + virtual const ScalarT& Ii() const = 0; + + + std::vector& y() override + { + return y_; + } + + const std::vector& y() const override + { + return y_; + } + + std::vector& yp() override + { + return yp_; + } + + const std::vector& yp() const override + { + return yp_; + } + + std::vector& tag() override + { + return tag_; + } + + const std::vector& tag() const override + { + return tag_; + } + + std::vector& yB() override + { + return yB_; + } + + const std::vector& yB() const override + { + return yB_; + } + + std::vector& ypB() override + { + return ypB_; + } + + const std::vector& ypB() const override + { + return ypB_; + } + + std::vector& param() override + { + return param_; + } + + const std::vector& param() const override + { + return param_; + } + + std::vector& param_up() override + { + return param_up_; + } + + const std::vector& param_up() const override + { + return param_up_; + } + + std::vector& param_lo() override + { + return param_lo_; + } + + const std::vector& param_lo() const override + { + return param_lo_; + } + + std::vector& getResidual() override + { + return f_; + } + + const std::vector& getResidual() const override + { + return f_; + } + + COO_Matrix& getJacobian() + { + return J_; + } + + const COO_Matrix& getJacobian() const + { + return J_; + } + + std::vector& getIntegrand() override + { + return g_; + } + + const std::vector& getIntegrand() const override + { + return g_; + } + + std::vector& getAdjointResidual() override + { + return fB_; + } + + const std::vector& getAdjointResidual() const override + { + return fB_; + } + + std::vector& getAdjointIntegrand() override + { + return gB_; + } + + const std::vector& getAdjointIntegrand() const override + { + return gB_; + } + + virtual const IdxT busID() const + { + return bus_id_; + } + + + protected: + const IdxT bus_id_{static_cast(-1)}; + + IdxT size_{0}; + IdxT nnz_{0}; + IdxT size_quad_{0}; + IdxT size_param_{0}; + + std::vector y_; + std::vector yp_; + std::vector tag_; + std::vector f_; + std::vector g_; + + std::vector yB_; + std::vector ypB_; + std::vector fB_; + std::vector gB_; + + COO_Matrix J_; + + std::vector param_; + std::vector param_up_; + std::vector param_lo_; + + real_type time_; + real_type alpha_; + + real_type rtol_; + real_type atol_; + + IdxT max_steps_; + }; + +} // namespace BusBase +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/CMakeLists.txt b/src/Model/PhasorDynamics/CMakeLists.txt index d88233100..08f9613ef 100644 --- a/src/Model/PhasorDynamics/CMakeLists.txt +++ b/src/Model/PhasorDynamics/CMakeLists.txt @@ -1,60 +1,3 @@ -# -# Copyright (c) 2017, Lawrence Livermore National Security, LLC. -# Produced at the Lawrence Livermore National Laboratory. -# Written by Slaven Peles . -# LLNL-CODE-718378. -# All rights reserved. -# -# This file is part of GridKit™. For details, see github.com/LLNL/GridKit -# Please also read the LICENSE file. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# - Redistributions of source code must retain the above copyright notice, -# this list of conditions and the disclaimer below. -# - Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the disclaimer (as noted below) in the -# documentation and/or other materials provided with the distribution. -# - Neither the name of the LLNS/LLNL nor the names of its contributors may -# be used to endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL -# SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY -# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -# THE POSSIBILITY OF SUCH DAMAGE. -# -# Lawrence Livermore National Laboratory is operated by Lawrence Livermore -# National Security, LLC, for the U.S. Department of Energy, National -# Nuclear Security Administration under Contract DE-AC52-07NA27344. -# -# This document was prepared as an account of work sponsored by an agency -# of the United States government. Neither the United States government nor -# Lawrence Livermore National Security, LLC, nor any of their employees -# makes any warranty, expressed or implied, or assumes any legal liability -# or responsibility for the accuracy, completeness, or usefulness of any -# information, apparatus, product, or process disclosed, or represents that -# its use would not infringe privately owned rights. Reference herein to -# any specific commercial product, process, or service by trade name, -# trademark, manufacturer, or otherwise does not necessarily constitute or -# imply its endorsement, recommendation, or favoring by the United States -# government or Lawrence Livermore National Security, LLC. The views and -# opinions of authors expressed herein do not necessarily state or reflect -# those of the United States government or Lawrence Livermore National -# Security, LLC, and shall not be used for advertising or product -# endorsement purposes. -# - # [[ # Author(s): # - Cameron Rutherford @@ -62,3 +5,4 @@ add_subdirectory(Branch) add_subdirectory(Bus) +add_subdirectory(Load) diff --git a/src/Model/PhasorDynamics/Component.hpp b/src/Model/PhasorDynamics/Component.hpp new file mode 100644 index 000000000..deb83cd88 --- /dev/null +++ b/src/Model/PhasorDynamics/Component.hpp @@ -0,0 +1,262 @@ +#pragma once + +#include +#include + +namespace GridKit +{ +namespace PhasorDynamics +{ + + /*! + * @brief Component model implementation base class. + * + */ + template + class Component : public Model::EvaluatorDynamics + { + public: + using real_type = typename Model::EvaluatorDynamics::real_type; + + Component() + : size_(0), + size_quad_(0), + size_param_(0) + {} + + Component(IdxT size, IdxT size_quad, IdxT size_param) + : size_(size), + size_quad_(size_quad), + size_param_(size_param), + y_(size_), + yp_(size_), + f_(size_), + g_(size_quad_), + yB_(size_), + ypB_(size_), + fB_(size_), + gB_(size_param_), + J_(COO_Matrix()), + param_(size_param_), + param_up_(size_param_), + param_lo_(size_param_) + { + } + + virtual IdxT size() override + { + return size_; + } + + virtual IdxT nnz() + { + return nnz_; + } + + virtual bool hasJacobian() + { + return false; + } + + virtual IdxT sizeQuadrature() override + { + return size_quad_; + } + + virtual IdxT sizeParams() override + { + return size_param_; + } + + // virtual void updateTime(real_type t, real_type a) + // { + // time_ = t; + // alpha_ = a; + // std::cout << "updateTime: t = " << time_ << "\n"; + // } + + virtual void setTolerances(real_type& rtol, real_type& atol) const + { + rtol = rtol_; + atol = atol_; + } + + virtual void setMaxSteps(IdxT& msa) const + { + msa = max_steps_; + } + + std::vector& y() override + { + return y_; + } + + const std::vector& y() const override + { + return y_; + } + + std::vector& yp() override + { + return yp_; + } + + const std::vector& yp() const override + { + return yp_; + } + + std::vector& tag() override + { + return tag_; + } + + const std::vector& tag() const override + { + return tag_; + } + + std::vector& yB() override + { + return yB_; + } + + const std::vector& yB() const override + { + return yB_; + } + + std::vector& ypB() override + { + return ypB_; + } + + const std::vector& ypB() const override + { + return ypB_; + } + + std::vector& param() override + { + return param_; + } + + const std::vector& param() const override + { + return param_; + } + + std::vector& param_up() override + { + return param_up_; + } + + const std::vector& param_up() const override + { + return param_up_; + } + + std::vector& param_lo() override + { + return param_lo_; + } + + const std::vector& param_lo() const override + { + return param_lo_; + } + + std::vector& getResidual() override + { + return f_; + } + + const std::vector& getResidual() const override + { + return f_; + } + + COO_Matrix& getJacobian() + { + return J_; + } + + const COO_Matrix& getJacobian() const + { + return J_; + } + + std::vector& getIntegrand() override + { + return g_; + } + + const std::vector& getIntegrand() const override + { + return g_; + } + + std::vector& getAdjointResidual() override + { + return fB_; + } + + const std::vector& getAdjointResidual() const override + { + return fB_; + } + + std::vector& getAdjointIntegrand() override + { + return gB_; + } + + const std::vector& getAdjointIntegrand() const override + { + return gB_; + } + + //@todo Fix ID naming + IdxT getComponentID() const + { + return component_id_; + } + + + + protected: + IdxT size_; + IdxT nnz_; + IdxT size_quad_; + IdxT size_param_; + + std::vector y_; + std::vector yp_; + std::vector tag_; + std::vector f_; + std::vector g_; + + std::vector yB_; + std::vector ypB_; + std::vector fB_; + std::vector gB_; + + COO_Matrix J_; + + std::vector param_; + std::vector param_up_; + std::vector param_lo_; + + real_type time_; + real_type alpha_; + + real_type rtol_; + real_type atol_; + + IdxT max_steps_; + + IdxT component_id_; + }; + +} // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/Load/CMakeLists.txt b/src/Model/PhasorDynamics/Load/CMakeLists.txt new file mode 100644 index 000000000..bfcfa6d0a --- /dev/null +++ b/src/Model/PhasorDynamics/Load/CMakeLists.txt @@ -0,0 +1,13 @@ + + +# [[ +# Author(s): +# - Cameron Rutherford +# ]] + +gridkit_add_library(phasor_dynamics_load + SOURCES + Load.cpp + OUTPUT_NAME + gridkit_phasor_dynamics_load) + diff --git a/src/Model/PhasorDynamics/Load/Load.cpp b/src/Model/PhasorDynamics/Load/Load.cpp new file mode 100644 index 000000000..5afb76ca0 --- /dev/null +++ b/src/Model/PhasorDynamics/Load/Load.cpp @@ -0,0 +1,177 @@ + +#include +#include +#include +#include + +#include "Load.hpp" + +namespace GridKit +{ +namespace PhasorDynamics +{ + /*! + * @brief Constructor for a pi-model load + * + * Arguments passed to ModelEvaluatorImpl: + * - Number of equations = 0 + * - Number of independent variables = 0 + * - Number of quadratures = 0 + * - Number of optimization parameters = 0 + */ + + template + Load::Load(bus_type* bus) : bus_(bus) + { + size_ = 0; + } + + template + Load::Load(bus_type* bus, + real_type R, + real_type X) + : bus_(bus), + R_(R), + X_(X) + + { + } + + template + Load::Load(bus_type* bus, IdxT component_id) + : bus_(bus) + + { + size_ = 0; + component_id_ = component_id; + } + + + template + Load::~Load() + { + //std::cout << "Destroy Load..." << std::endl; + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int Load::allocate() + { + //std::cout << "Allocate Load..." << std::endl; + return 0; + } + + /** + * Initialization of the load model + * + */ + template + int Load::initialize() + { + return 0; + } + + /** + * \brief Identify differential variables. + */ + template + int Load::tagDifferentiable() + { + return 0; + } + + /** + * \brief Residual contribution of the load is pushed to the bus. + * + */ + template + int Load::evaluateResidual() + { + real_type b = -X_/(R_*R_ + X_*X_); + real_type g = R_/(R_*R_ + X_*X_); + + Ir() += -g*Vr() - b*Vi(); + Ii() += b*Vr() - g*Vi(); + + return 0; + } + + /** + * @brief Jacobian evaluation not implemented yet + * + * @tparam ScalarT - scalar data type + * @tparam IdxT - matrix index data type + * @return int - error code, 0 = success + */ + template + int Load::evaluateJacobian() + { + std::cout << "Evaluate Jacobian for Load..." << std::endl; + std::cout << "Jacobian evaluation not implemented!" << std::endl; + return 0; + } + + /** + * @brief Integrand (objective) evaluation not implemented yet + * + * @tparam ScalarT - scalar data type + * @tparam IdxT - matrix index data type + * @return int - error code, 0 = success + */ + template + int Load::evaluateIntegrand() + { + // std::cout << "Evaluate Integrand for Load..." << std::endl; + return 0; + } + + /** + * @brief Adjoint initialization not implemented yet + * + * @tparam ScalarT - scalar data type + * @tparam IdxT - matrix index data type + * @return int - error code, 0 = success + */ + template + int Load::initializeAdjoint() + { + //std::cout << "Initialize adjoint for Load..." << std::endl; + return 0; + } + + /** + * @brief Adjoint residual evaluation not implemented yet + * + * @tparam ScalarT - scalar data type + * @tparam IdxT - matrix index data type + * @return int - error code, 0 = success + */ + template + int Load::evaluateAdjointResidual() + { + // std::cout << "Evaluate adjoint residual for Load..." << std::endl; + return 0; + } + + /** + * @brief Adjoint integrand (objective) evaluation not implemented yet + * + * @tparam ScalarT - scalar data type + * @tparam IdxT - matrix index data type + * @return int - error code, 0 = success + */ + template + int Load::evaluateAdjointIntegrand() + { + // std::cout << "Evaluate adjoint Integrand for Load..." << std::endl; + return 0; + } + + // Available template instantiations + template class Load; + template class Load; + +} //namespace PhasorDynamics +} //namespace GridKit diff --git a/src/Model/PhasorDynamics/Load/Load.hpp b/src/Model/PhasorDynamics/Load/Load.hpp new file mode 100644 index 000000000..31f1d0480 --- /dev/null +++ b/src/Model/PhasorDynamics/Load/Load.hpp @@ -0,0 +1,109 @@ + + +#pragma once + +#include + +// Forward declarations. +namespace GridKit +{ +namespace PhasorDynamics +{ + template class Bus; +} +} + +namespace GridKit +{ +namespace PhasorDynamics +{ + /*! + * @brief Implementation of a constant load. + * + */ + template + class Load : public Component + { + using Component::size_; + using Component::nnz_; + using Component::time_; + using Component::alpha_; + using Component::y_; + using Component::yp_; + using Component::tag_; + using Component::f_; + using Component::g_; + using Component::yB_; + using Component::ypB_; + using Component::fB_; + using Component::gB_; + using Component::param_; + using Component::component_id_; + + using bus_type = BusBase; + using real_type = typename Component::real_type; + + public: + Load(bus_type* bus); + Load(bus_type* bus, real_type R, real_type X); + Load(bus_type* bus, IdxT component_id); + virtual ~Load(); + + virtual int allocate() override; + virtual int initialize() override; + virtual int tagDifferentiable() override; + virtual int evaluateResidual() override; + virtual int evaluateJacobian() override; + virtual int evaluateIntegrand() override; + + virtual int initializeAdjoint() override; + virtual int evaluateAdjointResidual() override; + // virtual int evaluateAdjointJacobian() override; + virtual int evaluateAdjointIntegrand() override; + + virtual void updateTime(real_type /* t */, real_type /* a */) override + { + } + + public: + void setR(real_type R) + { + R_ = R; + } + + void setX(real_type X) + { + // std::cout << "Setting X ...\n"; + X_ = X; + } + + private: + ScalarT& Vr() + { + return bus_->Vr(); + } + + ScalarT& Vi() + { + return bus_->Vi(); + } + + ScalarT& Ir() + { + return bus_->Ir(); + } + + ScalarT& Ii() + { + return bus_->Ii(); + } + + + private: + bus_type* bus_{nullptr}; + real_type R_{0.1}; + real_type X_{0.01}; + }; + +} // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/Load/README.md b/src/Model/PhasorDynamics/Load/README.md new file mode 100644 index 000000000..90bb7f9f7 --- /dev/null +++ b/src/Model/PhasorDynamics/Load/README.md @@ -0,0 +1,29 @@ +# Load Model + +Load modeling is one of the more complex aspects of power system dynamics. +The simplest model, which is used for this challenge problem, is to model +the load as a complex shunt impedance with the impedance given by: +``` math +Z = R + jX +``` +where $`R`$ is the load resistance, $`X`$ is the load reactance. The current +drawn by the load is then obtained as +```math +I_{\mathrm{load}} = \frac{V_{\mathrm{bus}}}{Z}, +``` +where $`V_{bus}`$ is the voltage on the bus to which the load is connected. + +After some algebra, one obtains expressions for real and imaginary components +for the currents entering the bus: +```math +I_{r} = -g V_{r} - b V_{i} +``` + +```math +I_{i} = b V_{r} - g V_{i} +``` +where +```math +g = \frac{R}{R^2+X^2} ~~~\mathrm{and}~~~ b = \frac{-X}{R^2+X^2}. +``` + diff --git a/src/SystemModel.hpp b/src/SystemModel.hpp index 4dee38e03..e4aba2a52 100644 --- a/src/SystemModel.hpp +++ b/src/SystemModel.hpp @@ -83,8 +83,8 @@ namespace GridKit template class SystemModel : public ModelEvaluatorImpl { - typedef BaseBus bus_type; - typedef ModelEvaluatorImpl component_type; + typedef ModelEvaluator bus_type; + typedef ModelEvaluator component_type; using real_type = typename ModelEvaluatorImpl::real_type; using ModelEvaluatorImpl::size_; diff --git a/src/Utilities/TestHelpers.hpp b/src/Utilities/TestHelpers.hpp new file mode 100644 index 000000000..fb84b470a --- /dev/null +++ b/src/Utilities/TestHelpers.hpp @@ -0,0 +1,260 @@ + +/** + * @file UnitTest.hpp + * + * @author Slaven Peles , ORNL + * + */ +#pragma once + +#define THROW_NULL_DEREF throw std::runtime_error("error") + +#include +#include +#include + + +namespace GridKit +{ + +namespace Colors +{ + // must be const pointer and const dest for + // const string declarations to pass -Wwrite-strings + static const char * const RED = "\033[1;31m"; + static const char * const GREEN = "\033[1;32m"; + static const char * const YELLOW = "\033[33;1m"; + static const char * const BLUE = "\033[34;1m"; + static const char * const ORANGE = "\u001b[38;5;208m"; + static const char * const CLEAR = "\033[0m"; +} + +namespace Testing +{ + enum TestOutcome {PASS=0, FAIL, SKIP, EXPECTED_FAIL, UNEXPECTED_PASS}; + + class TestStatus + { + public: + TestStatus() + : outcome_(TestOutcome::PASS) + { + } + + TestStatus(bool success) + : outcome_(success ? TestOutcome::PASS : TestOutcome::FAIL) + { + } + + TestStatus(const char* funcname) + : outcome_(TestOutcome::PASS), + funcname_(funcname) + { + } + + ~TestStatus() + { + } + + TestStatus& operator=(const bool isPass) + { + if(isPass) + outcome_ = TestOutcome::PASS; + else + outcome_ = TestOutcome::FAIL; + return *this; + } + + TestStatus& operator*=(const bool isPass) + { + if(!isPass) + outcome_ = TestOutcome::FAIL; + return *this; + } + + void skipTest() + { + outcome_ = TestOutcome::SKIP; + } + + void expectFailure() + { + expectFailure_ = true; + } + + TestOutcome report() + { + return report(funcname_); + } + + TestOutcome report(const char* funcname) + { + using namespace Colors; + + if (expectFailure_) + { + if ((outcome_ == FAIL) || (outcome_ == EXPECTED_FAIL)) + outcome_ = EXPECTED_FAIL; + else if ((outcome_ == PASS) || (outcome_ == UNEXPECTED_PASS)) + outcome_ = UNEXPECTED_PASS; + else + outcome_ = SKIP; + } + + switch(outcome_) + { + case PASS: + std::cout << "--- " << GREEN << "PASS" << CLEAR + << ": Test " << funcname << "\n"; + break; + case FAIL: + std::cout << "--- " << RED << "FAIL" << CLEAR + << ": Test " << funcname << "\n"; + break; + case SKIP: + std::cout << "--- " << YELLOW << "SKIP" << CLEAR + << ": Test " << funcname << CLEAR << "\n"; + break; + case EXPECTED_FAIL: + std::cout << "--- " << ORANGE << "FAIL" << CLEAR + << " (EXPECTED)" << ": Test " << funcname << "\n"; + break; + case UNEXPECTED_PASS: + std::cout << "--- " << BLUE << "PASS" << CLEAR + << " (UNEXPECTED)" << ": Test " << funcname << "\n"; + break; + default: + std::cout << "--- " << RED << "FAIL" << CLEAR + << "Unrecognized test result " << outcome_ + << " for test " << funcname << "\n"; + } + return outcome_; + } + + private: + TestOutcome outcome_; + const char* funcname_; + bool expectFailure_ = false; + }; + + + + struct TestingResults + { + int success = 0; + int failure = 0; + int skip = 0; + int expected_failure = 0; + int unexpected_success = 0; + + TestingResults(){} + ~TestingResults(){} + TestingResults(const TestingResults& r) + { + this->success = r.success; + this->failure = r.failure; + this->skip = r.skip; + this->expected_failure = r.expected_failure; + this->unexpected_success = r.unexpected_success; + } + + void init() + { + this->success = 0; + this->failure = 0; + this->skip = 0; + this->expected_failure = 0; + this->unexpected_success = 0; + } + + TestingResults& operator+=(const TestingResults& rhs) + { + this->success += rhs.success; + this->failure += rhs.failure; + this->skip += rhs.skip; + this->expected_failure += rhs.expected_failure; + this->unexpected_success += rhs.unexpected_success; + + return *this; + } + + TestingResults& operator+=(const TestOutcome outcome) + { + switch(outcome) + { + case PASS: + this->success++; + break; + case FAIL: + this->failure++; + break; + case SKIP: + this->skip++; + break; + case EXPECTED_FAIL: + this->expected_failure++; + break; + case UNEXPECTED_PASS: + this->unexpected_success++; + break; + default: + std::cout << "Warning: Unrecognized test outcome code " + << outcome << ". Assuming failure ...\n"; + this->failure++; + } + return *this; + } + + int summary() + { + std::cout << "\n\nTest Summary\n"; + std::cout << "----------------------------\n"; + std::cout << "\tSuccessful tests: " << success << "\n"; + std::cout << "\tFailed test: " << failure << "\n"; + std::cout << "\tSkipped tests: " << skip << "\n"; + std::cout << "\tExpected failures: " << expected_failure << "\n"; + std::cout << "\tUnexpected successes: " << unexpected_success << "\n"; + std::cout << "\n"; + + return failure; + } + }; + + TestingResults operator+(const TestingResults& lhs, const TestingResults& rhs) + { + return TestingResults(lhs) += rhs; + } + + TestingResults operator+(const TestingResults& lhs, const TestOutcome outcome) + { + return TestingResults(lhs) += outcome; + } + + TestingResults operator+(const TestOutcome outcome, const TestingResults& rhs) + { + return TestingResults(rhs) += outcome; + } + + + // /// @brief eps = 2.2e-15 for double type + // static const real_type eps_ = 10*std::numeric_limits::epsilon(); + + + // class TestBase + // { + // public: + // TestBase() = default; + // ~TestBase() = default; + + // protected: + // /// Returns true if two real numbers are equal within tolerance + // [[nodiscard]] static + // bool isEqual(const real_type a, const real_type b) + // { + // return (std::abs(a - b)/(1.0 + std::abs(b)) < eps); + // } + + // }; + +} // namespace Testing +} // namespace GridKit diff --git a/src/Utilities/Testing.hpp b/src/Utilities/Testing.hpp index f061cdbd1..b5bd9b489 100644 --- a/src/Utilities/Testing.hpp +++ b/src/Utilities/Testing.hpp @@ -69,6 +69,7 @@ #include #include #include +#include namespace { @@ -84,11 +85,14 @@ inline std::ostream &errs() { namespace GridKit { namespace Testing { -template bool isEqual(const T value, const T ref, const T tol) -{ - T error = std::abs(value - ref) / (1.0 + std::abs(ref)); - return (error < tol); -} + template + bool isEqual(const T value, + const T ref, + const T tol = std::numeric_limits::epsilon()) + { + T error = std::abs(value - ref) / (1.0 + std::abs(ref)); + return (error < tol); + } template inline bool isEqual(PowerSystemData::GenCostData a, diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 000000000..d80cc13bc --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,3 @@ + + +add_subdirectory(UnitTests) diff --git a/tests/UnitTests/CMakeLists.txt b/tests/UnitTests/CMakeLists.txt new file mode 100644 index 000000000..970045256 --- /dev/null +++ b/tests/UnitTests/CMakeLists.txt @@ -0,0 +1,2 @@ +# +add_subdirectory(PhasorDynamics) diff --git a/tests/UnitTests/PhasorDynamics/BranchTests.hpp b/tests/UnitTests/PhasorDynamics/BranchTests.hpp new file mode 100644 index 000000000..103f7af1a --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/BranchTests.hpp @@ -0,0 +1,149 @@ +#include +#include + +#include +#include +#include +#include +#include + +namespace GridKit +{ +namespace Testing +{ + + template + class BranchTests + { + private: + using real_type = typename PhasorDynamics::Component::real_type; + + public: + BranchTests() = default; + ~BranchTests() = default; + + TestOutcome constructor() + { + TestStatus success = true; + + auto* bus1 = new PhasorDynamics::Bus(1.0, 0.0); + auto* bus2 = new PhasorDynamics::Bus(1.0, 0.1); + + PhasorDynamics::Component* branch = + new PhasorDynamics::Branch(bus1, bus2); + + success *= (branch != nullptr); + + if (branch) + { + delete branch; + } + delete bus1; + delete bus2; + + return success.report(__func__); + } + + TestOutcome residual() + { + TestStatus success = true; + + real_type R{2.0}; ///< Branch series resistance + real_type X{4.0}; ///< Branch series reactance + real_type G{0.2}; ///< Branch shunt conductance + real_type B{1.2}; ///< Branch shunt charging + + ScalarT Vr1{10.0}; ///< Bus-1 real voltage + ScalarT Vi1{20.0}; ///< Bus-1 imaginary voltage + ScalarT Vr2{30.0}; ///< Bus-2 real voltage + ScalarT Vi2{40.0}; ///< Bus-2 imaginary voltage + + const ScalarT Ir1{17.0}; ///< Solution: real current entering bus-1 + const ScalarT Ii1{-10.0}; ///< Solution: imaginary current entering bus-1 + const ScalarT Ir2{15.0}; ///< Solution: real current entering bus-2 + const ScalarT Ii2{-20.0}; ///< Solution: imaginary current entering bus-2 + + + PhasorDynamics::BusInfinite bus1(Vr1, Vi1); + PhasorDynamics::BusInfinite bus2(Vr2, Vi2); + + PhasorDynamics::Branch branch(&bus1, &bus2, R, X, G, B); + branch.evaluateResidual(); + + success *= isEqual(bus1.Ir(), Ir1); + success *= isEqual(bus1.Ii(), Ii1); + success *= isEqual(bus2.Ir(), Ir2); + success *= isEqual(bus2.Ii(), Ii2); + + return success.report(__func__); + } + + TestOutcome accessors() + { + TestStatus success = true; + + const real_type zero{0.0}; + + real_type R{2.0}; ///< Branch series resistance + real_type X{4.0}; ///< Branch series reactance + real_type G{0.2}; ///< Branch shunt conductance + real_type B{1.2}; ///< Branch shunt charging + + ScalarT Vr1{-1.0}; ///< Bus-1 real voltage + ScalarT Vi1{-1.0}; ///< Bus-1 imaginary voltage + ScalarT Vr2{1.0}; ///< Bus-2 real voltage + ScalarT Vi2{1.0}; ///< Bus-2 imaginary voltage + + const ScalarT res_R{1.0}; ///< Solution: real current entering bus-1 + const ScalarT res_X{0.5}; ///< Solution: imaginary current entering bus-1 + const ScalarT res_G{3.0}; ///< Solution: real current entering bus-2 + const ScalarT res_B{-4.0}; ///< Solution: imaginary current entering bus-2 + + + PhasorDynamics::BusInfinite bus1(Vr1, Vi1); + PhasorDynamics::BusInfinite bus2(Vr2, Vi2); + + PhasorDynamics::Branch branch(&bus1, + &bus2, + zero, + zero, + zero, + zero); + + // Test setting branch series resistance + branch.setR(R); + bus1.evaluateResidual(); // <- set Ir1 to zero + branch.evaluateResidual(); + success *= isEqual(bus1.Ir(), res_R); + branch.setR(zero); + + // Test setting branch series reactance + branch.setX(X); + bus1.evaluateResidual(); // <- set Ir1 to zero + branch.evaluateResidual(); + success *= isEqual(bus1.Ir(), res_X); + branch.setX(zero); + return success.report(__func__); + + // Test setting branch shunt conductance + branch.setG(G); + bus1.evaluateResidual(); // <- set Ir1 to zero + branch.evaluateResidual(); + success *= isEqual(bus1.Ir(), res_G); + branch.setG(zero); + + // Test setting branch shunt charging + branch.setB(B); + bus1.evaluateResidual(); // <- set Ir1 to zero + branch.evaluateResidual(); + success *= isEqual(bus1.Ir(), res_B); + branch.setB(zero); + + return success.report(__func__); + } + }; // class BranchTest + +} // namespace Testing +} // namespace GridKit + + diff --git a/tests/UnitTests/PhasorDynamics/BusTests.hpp b/tests/UnitTests/PhasorDynamics/BusTests.hpp new file mode 100644 index 000000000..a0ec744d2 --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/BusTests.hpp @@ -0,0 +1,103 @@ +#include +#include + +#include +#include +#include +#include + + +namespace GridKit +{ +namespace Testing +{ + template + class BusTests + { + public: + BusTests() = default; + ~BusTests() = default; + + /// Constructor, allocation, and initialization checks + TestOutcome constructor() + { + TestStatus success = true; + + ScalarT Vr{1.0}; + ScalarT Vi{2.0}; + + PhasorDynamics::BusBase* bus = nullptr; + + // Create an infinite bus + bus = new PhasorDynamics::BusInfinite(); + success *= isEqual(bus->Vr(), 0.0); + success *= isEqual(bus->Vi(), 0.0); + delete bus; + + bus = new PhasorDynamics::BusInfinite(Vr, Vi); + success *= isEqual(bus->Vr(), Vr); + success *= isEqual(bus->Vi(), Vi); + delete bus; + + // Create an default bus + bus = new PhasorDynamics::Bus(); + bus->allocate(); + bus->initialize(); + success *= isEqual(bus->Vr(), 0.0); + success *= isEqual(bus->Vi(), 0.0); + delete bus; + + bus = new PhasorDynamics::Bus(Vr, Vi); + bus->allocate(); + bus->initialize(); + success *= isEqual(bus->Vr(), Vr); + success *= isEqual(bus->Vi(), Vi); + delete bus; + + bus = nullptr; + + return success.report(__func__); + } + + /// Accessor method tests + TestOutcome residual() + { + TestStatus success = true; + + ScalarT Vr{1.0}; + ScalarT Vi{2.0}; + ScalarT Ir{1.0}; + ScalarT Ii{2.0}; + + PhasorDynamics::BusInfinite bus_inf; + bus_inf.Ir() = Ir; + success *= isEqual(bus_inf.Ir(), Ir); + bus_inf.Ii() = Ii; + success *= isEqual(bus_inf.Ii(), Ii); + + bus_inf.evaluateResidual(); + success *= isEqual(bus_inf.Ir(), 0.0); + success *= isEqual(bus_inf.Ii(), 0.0); + + PhasorDynamics::Bus bus(Vr,Vi); + bus.allocate(); + bus.initialize(); + success *= isEqual(bus.Vr(), Vr); + success *= isEqual(bus.Vi(), Vi); + + bus.Ir() = Ir; + success *= isEqual(bus.Ir(), Ir); + bus.Ii() = Ii; + success *= isEqual(bus.Ii(), Ii); + + bus.evaluateResidual(); + success *= isEqual(bus.Ir(), 0.0); + success *= isEqual(bus.Ii(), 0.0); + + return success.report(__func__); + } + + }; + +} // namespace Testing +} // namespace GridKit diff --git a/tests/UnitTests/PhasorDynamics/CMakeLists.txt b/tests/UnitTests/PhasorDynamics/CMakeLists.txt new file mode 100644 index 000000000..30cd2bbbe --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/CMakeLists.txt @@ -0,0 +1,22 @@ +# [[ +# Author(s): +# - Slaven Peles +#]] + + +add_executable(test_phasor_bus runBusTests.cpp) +target_link_libraries(test_phasor_bus GRIDKIT::phasor_dynamics_bus) + +add_executable(test_phasor_branch runBranchTests.cpp) +target_link_libraries(test_phasor_branch GRIDKIT::phasor_dynamics_branch + GRIDKIT::phasor_dynamics_bus) + +add_executable(test_phasor_load runLoadTests.cpp) +target_link_libraries(test_phasor_load GRIDKIT::phasor_dynamics_load + GRIDKIT::phasor_dynamics_bus) + +add_test(NAME PhasorDynamicsBusTest COMMAND $) +add_test(NAME PhasorDynamicsBranchTest COMMAND $) +add_test(NAME PhasorDynamicsLoadTest COMMAND $) + +install(TARGETS test_phasor_bus test_phasor_branch test_phasor_load RUNTIME DESTINATION bin) diff --git a/tests/UnitTests/PhasorDynamics/LoadTests.hpp b/tests/UnitTests/PhasorDynamics/LoadTests.hpp new file mode 100644 index 000000000..ecda1301d --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/LoadTests.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include + +namespace GridKit +{ +namespace Testing +{ + template + class LoadTests + { + public: + using real_type = typename PhasorDynamics::Component::real_type; + + LoadTests() = default; + ~LoadTests() = default; + + TestOutcome constructor() + { + TestStatus success = true; + + auto* bus = new PhasorDynamics::Bus(1.0, 0.0); + + PhasorDynamics::Component* load = + new PhasorDynamics::Load(bus); + + success *= (load != nullptr); + + if (load) + { + delete load; + } + delete bus; + + return success.report(__func__); + } + + TestOutcome residual() + { + TestStatus success = true; + + real_type R{2.0}; ///< Load resistance + real_type X{4.0}; ///< Load reactance + + ScalarT Vr{10.0}; ///< Bus real voltage + ScalarT Vi{20.0}; ///< Bus imaginary voltage + + const ScalarT Ir{3.0}; ///< Solution real current + const ScalarT Ii{-4.0}; ///< Solution imaginary current + + PhasorDynamics::BusInfinite bus(Vr, Vi); + + PhasorDynamics::Load load(&bus, R, X); + load.evaluateResidual(); + + success *= isEqual(bus.Ir(), Ir); + success *= isEqual(bus.Ii(), Ii); + + return success.report(__func__); + } + }; + +} // namespace Testing +} // namespace GridKit + + diff --git a/tests/UnitTests/PhasorDynamics/runBranchTests.cpp b/tests/UnitTests/PhasorDynamics/runBranchTests.cpp new file mode 100644 index 000000000..ea809536b --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/runBranchTests.cpp @@ -0,0 +1,16 @@ +#include "BranchTests.hpp" + +int main() +{ + using namespace GridKit; + using namespace GridKit::Testing; + + GridKit::Testing::TestingResults result; + GridKit::Testing::BranchTests test; + + result += test.constructor(); + result += test.accessors(); + result += test.residual(); + + return result.summary(); +} \ No newline at end of file diff --git a/tests/UnitTests/PhasorDynamics/runBusTests.cpp b/tests/UnitTests/PhasorDynamics/runBusTests.cpp new file mode 100644 index 000000000..0c172ae03 --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/runBusTests.cpp @@ -0,0 +1,15 @@ +#include "BusTests.hpp" + +int main() +{ + using namespace GridKit; + using namespace GridKit::Testing; + + GridKit::Testing::TestingResults result; + GridKit::Testing::BusTests test; + + result += test.constructor(); + result += test.residual(); + + return result.summary(); +} \ No newline at end of file diff --git a/tests/UnitTests/PhasorDynamics/runLoadTests.cpp b/tests/UnitTests/PhasorDynamics/runLoadTests.cpp new file mode 100644 index 000000000..471099859 --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/runLoadTests.cpp @@ -0,0 +1,15 @@ +#include "LoadTests.hpp" + +int main() +{ + using namespace GridKit; + using namespace GridKit::Testing; + + GridKit::Testing::TestingResults result; + GridKit::Testing::LoadTests test; + + result += test.constructor(); + result += test.residual(); + + return result.summary(); +} \ No newline at end of file