diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..2fcec4c5f --- /dev/null +++ b/.clang-format @@ -0,0 +1,72 @@ +--- +Language: Cpp +BasedOnStyle: Microsoft + +# Indentation +IndentWidth: 2 # 2 spaces per indent +AccessModifierOffset: -2 +IndentAccessModifiers: false # Align access modifiers to braces +NamespaceIndentation: All # Indent namspace contents +ConstructorInitializerIndentWidth: 2 + +# Comments which match this regex will be unformatted (and therefore can be longer or have more whitespace than other comments) +CommentPragmas: '^\*\*' + + +# Alignment +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: false + AcrossComments: true + AlignCompound: true + PadOperators: true +AlignConsecutiveBitFields: + Enabled: true + AcrossEmptyLines: false + AcrossComments: true +AlignConsecutiveDeclarations: + Enabled: true + AcrossEmptyLines: false + AcrossComments: true + # For future versions of clang-format + # AlignFunctionDeclarations: false + # AlignFunctionPointers: false +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: false + AcrossComments: true + +# Newlines +ColumnLimit: 0 +BreakBeforeBraces: Allman # Braces on their own lines +SeparateDefinitionBlocks: Always # Separate definitions (functions etc.) with an empty line +AlwaysBreakTemplateDeclarations: true # Put template on their own lines +AllowShortBlocksOnASingleLine: Never +# On a newer version of clang-format, replace with BinPackArguments: OnePerLine +BinPackArguments: false # Don't allow multiple function arguments on the same line unless they all fit +BinPackParameters: false # Same but for parameters +PackConstructorInitializers: NextLine +AllowShortFunctionsOnASingleLine: None +BreakBeforeBinaryOperators: NonAssignment # Put binary operators after a line break, rather than before +AllowShortIfStatementsOnASingleLine: Never + +# Spaces +SpaceBeforeParens: ControlStatementsExceptControlMacros +SpaceAfterCStyleCast: true +PointerAlignment: Left + +# Includes +IncludeBlocks: Regroup # Regroup includes based on config +IncludeCategories: + - Regex: '(^"|\.hpp)' # 'local' includes + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '\/' # Library includes + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' # Everything else + Priority: 1 + SortPriority: 0 + CaseSensitive: false diff --git a/.github/workflows/pre_commit.yaml b/.github/workflows/pre_commit.yaml new file mode 100644 index 000000000..a6ecfed8a --- /dev/null +++ b/.github/workflows/pre_commit.yaml @@ -0,0 +1,22 @@ +name: gridkit-bot pre-commit + +# Won't run on develop/main directly +on: [pull_request] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.ref }} + - uses: actions/setup-python@v5.4.0 + - uses: pre-commit/action@v3.0.1 + - uses: EndBug/add-and-commit@v9.1.4 + # Only need to try and commit if the action failed + if: failure() + with: + fetch: false + committer_name: GitHub Actions + committer_email: actions@github.com + message: Apply pre-commmit fixes diff --git a/.github/workflows/pull_request_template.md b/.github/workflows/pull_request_template.md new file mode 100644 index 000000000..78d42e5f6 --- /dev/null +++ b/.github/workflows/pull_request_template.md @@ -0,0 +1,32 @@ +## Description + + _Please describe the issue that is addressed (bug, new feature, + documentation, enhancement, etc.). Please also include relevant motivation and + context. List any dependencies that are required for this change._ + + _Closes # (issue)_ + + + ## Proposed changes + + _Describe how your changes here address the issue and why the proposed changes + should be accepted._ + + ## Checklist + + _Put an `x` in the boxes that apply. You can also fill these out after creating + the PR. If you're unsure about any of them, don't hesitate to ask. We're here + to help! This is simply a reminder of what we are going to look for before + merging your code._ + + - [ ] I have read the [Contributing Guide](CONTRIBUTING.md) + - [ ] Functionality and unit tests pass locally with my changes + - [ ] The code builds with flags `-Wall -Wconversion -Wextra` without any + compiler warnings + - [ ] I have added regression tests that prove my fix is effective. + - [ ] I have updated the documentation (if appropriate) + + ## Further comments + + _If this is a relatively large or complex change, kick off the discussion by explaining + why you chose the solution you did and what alternatives you considered, etc..._ diff --git a/.github/workflows/spack_default_build.yaml b/.github/workflows/spack_default_build.yaml new file mode 100644 index 000000000..7ce766d54 --- /dev/null +++ b/.github/workflows/spack_default_build.yaml @@ -0,0 +1,175 @@ +# https://spack.readthedocs.io/en/latest/binary_caches.html#spack-build-cache-for-github-actions +name: Spack Ubunutu x86_64 Buildcache + +env: + SPACK_COLOR: always + REGISTRY: ghcr.io/ornl + # Our repo name contains upper case characters, so we can't use ${{ github.repository }} + IMAGE_NAME: gridkit + USERNAME: gridkit-bot + BASE_VERSION: ubuntu-24.04-fortran-v0.2.11 + +# Until we remove the need to clone submodules to build, this should on be in PRs +on: [pull_request] + +jobs: + base_image_build: + name: Build base image + runs-on: ubuntu-24.04 + permissions: + contents: read + packages: write + steps: + # No GHCR base image with skopeo, so this will do... + - name: "Set up skopeo" + uses: warjiang/setup-skopeo@v0.1.3 + with: + version: latest + + # Use skopeo to check for image for convenience + - name: Check for existing base images + run: | + set -e + CONTAINER_TAG=${{ env.BASE_VERSION }} + OCI_URL="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.BASE_VERSION }}" + echo Checking for CONTAINER_TAG $CONTAINER_TAG + skopeo inspect \ + docker://$OCI_URL \ + --raw \ + --creds "${{ env.USERNAME }}:${{ secrets.GITHUB_TOKEN }}" \ + > /dev/null && echo "Image already exists. Please bump version." && exit 0 + echo "IMAGE_EXISTS=false" >> $GITHUB_ENV + + # https://docs.github.com/en/actions/publishing-packages/publishing-docker-images + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ env.USERNAME }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Need to build custom base image with gfortran + - name: Create Dockerfile heredoc + if: ${{ env.IMAGE_EXISTS == 'false' }} + run: | + cat << EOF > Dockerfile + FROM ubuntu:24.04 + RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + software-properties-common \ + gpg-agent \ + openssh-client \ + openssh-server \ + && rm -rf /var/lib/apt/lists/* + RUN add-apt-repository ppa:ubuntu-toolchain-r/test && \ + apt-get install -y --no-install-recommends \ + gcc \ + libstdc++6 \ + && rm -rf /var/lib/apt/lists/* + EOF + + - name: Extract metadata (tags, labels) for Docker + if: ${{ env.IMAGE_EXISTS == 'false' }} + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + labels: org.opencontainers.image.version=${{ env.BASE_VERSION }} + + - name: Build and push Docker base image + if: ${{ env.IMAGE_EXISTS == 'false' }} + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.BASE_VERSION }} + labels: ${{ steps.meta.outputs.labels }} + + gridkit_spack_builds: + name: Build gridkit with Spack + needs: base_image_build + runs-on: ubuntu-24.04 + permissions: + packages: write + contents: read + timeout-minutes: 30 + + strategy: + matrix: + llvm: ["16"] + # Minimal Build(s) - GHCR mirror speeds these up a lot! + spack_spec: + - gridkit@develop +enzyme + + steps: + - name: Add LLVM + run: | + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - + sudo apt-get install -y libmpfr-dev + sudo apt-add-repository "deb http://apt.llvm.org/`lsb_release -c | cut -f2`/ llvm-toolchain-`lsb_release -c | cut -f2`-${{ matrix.llvm }} main" || true + sudo apt-get install -y cmake gcc g++ llvm-${{ matrix.llvm }}-dev libomp-${{ matrix.llvm }}-dev lld-${{ matrix.llvm }} clang-${{ matrix.llvm }} libclang-${{ matrix.llvm }}-dev libeigen3-dev libboost-dev libzstd-dev + + - name: Checkout + uses: actions/checkout@v4 + with: + # Once we move submodule deps into spack, we can do some more builds + # Also need to change build script to use spack from base image + submodules: true + + - name: Setup Spack + run: echo "$PWD/buildsystem/spack/spack/bin" >> "$GITHUB_PATH" + + - name: Create heredoc spack.yaml + run: | + cat << EOF > spack.yaml + spack: + specs: + - ${{ matrix.spack_spec }} target=x86_64_v2 + concretizer: + reuse: dependencies + config: + install_tree: + root: /opt/spack + padded_length: 128 + mirrors: + local-buildcache: oci://${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + spack: https://binaries.spack.io/v0.23.1 + packages: + llvm: + externals: + - spec: llvm@${{ matrix.llvm }} + prefix: /usr/lib/llvm-${{ matrix.llvm }} + EOF + + - name: Configure GHCR mirror + run: spack -e . mirror set --oci-username ${{ env.USERNAME }} --oci-password "${{ secrets.GITHUB_TOKEN }}" local-buildcache + + - name: Trust keys + run: spack -e . buildcache keys --install --trust + + - name: Find external packages + run: spack -e . external find --all --exclude llvm + + - name: Spack develop gridkit + run: spack -e . develop --path=$(pwd) gridkit@develop + + - name: List working directory + run: ls -ltrh $(pwd)/*/*/ + + - name: Concretize + run: spack -e . concretize + + - name: Install dependencies + run: spack -e . install --no-check-signature --only dependencies + + - name: Install package + run: spack -e . install --keep-stage --no-check-signature --no-cache --fresh + + - name: Test Build + run: cd $(spack -e . location --build-dir gridkit@develop) && ctest -VV + + # Push with force to override existing binaries... + - name: Push to binaries to buildcache + run: | + spack -e . buildcache push --force --base-image ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.BASE_VERSION }} --unsigned --update-index local-buildcache + if: ${{ !cancelled() }} diff --git a/.gitignore b/.gitignore index 304aea9a5..928aa52fa 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ .directory *.orig .vscode/ - +*.DS_Store build/ +*.DS_Store diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..b5ba06cd3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "buildsystem/spack/spack"] + path = buildsystem/spack/spack + url = https://github.com/nkoukpaizan/spack.git + branch = Gridkit-package-dev+enzyme diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..eda93831a --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,12 @@ +repos: + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v19.1.7 + hooks: + - id: clang-format + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-toml + - id: forbid-new-submodules + - id: end-of-file-fixer + - id: check-yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 12ba29457..80789bc6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Release Changelog +## v0.1 + +- Refactored code to support adding different model families. +- Added PowerElectronics family of models. +- Prototype for sparse system matrix assembly (for PowerElectronics only). +- Added PhasorDynamics family of models. +- Unit testing framework. +- GridKit now depends on Sundials >= 7.0. + ## v0.0.7 - Added parser for Matpower files. diff --git a/CMake/FindIpopt.cmake b/CMake/FindIpopt.cmake deleted file mode 100644 index f7515c523..000000000 --- a/CMake/FindIpopt.cmake +++ /dev/null @@ -1,119 +0,0 @@ -# -# 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. -# - -#[[ - -Finds Ipopt include directory and libraries and exports target `Ipopt` - -User may set: -- IPOPT_ROOT_DIR - -Author(s): -- Cameron Rutherford - -]] - -find_library(IPOPT_LIBRARY - NAMES - ipopt - PATHS - ${IPOPT_DIR} $ENV{IPOPT_DIR} ${IPOPT_ROOT_DIR} ${IPOPT_LIBRARY_DIR} - ENV LD_LIBRARY_PATH ENV DYLD_LIBRARY_PATH - PATH_SUFFIXES - lib64 lib) - -if(IPOPT_LIBRARY) - set(IPOPT_LIBRARY CACHE FILEPATH "Path to Ipopt library") - message(STATUS "Found Ipopt library: " ${IPOPT_LIBRARY}) - get_filename_component(IPOPT_LIBRARY_DIR ${IPOPT_LIBRARY} DIRECTORY CACHE "Ipopt library directory") - mark_as_advanced(IPOPT_LIBRARY IPOPT_LIBRARY_DIR) - if(NOT IPOPT_DIR) - get_filename_component(IPOPT_DIR ${IPOPT_LIBRARY_DIR} DIRECTORY CACHE) - endif() -endif() - -find_path(IPOPT_INCLUDE_DIR - NAMES - IpTNLP.hpp - PATHS - ${IPOPT_DIR} ${IPOPT_ROOT_DIR} $ENV{IPOPT_DIR} ${IPOPT_LIBRARY_DIR}/.. - PATH_SUFFIXES - include - include/coin - include/coin-or - include/coinor) - -if(IPOPT_LIBRARY) - message(STATUS "Found Ipopt include: ${IPOPT_INCLUDE_DIR}") - mark_as_advanced(IPOPT_INCLUDE_DIR) - add_library(IPOPT INTERFACE IMPORTED) - target_link_libraries(IPOPT INTERFACE ${IPOPT_LIBRARY}) - target_include_directories(IPOPT INTERFACE ${IPOPT_INCLUDE_DIR}) -else() - if(NOT IPOPT_ROOT_DIR) - message(STATUS "Ipopt dir not found! Please provide correct filepath.") - set(IPOPT_DIR ${IPOPT_DIR} CACHE PATH "Path to Ipopt installation root.") - unset(IPOPT_INCLUDE_DIR CACHE) - unset(IPOPT_LIBRARY CACHE) - unset(IPOPT_LIBRARY_DIR CACHE) - elseif(NOT IPOPT_LIB) - message(STATUS "Ipopt library not found! Please provide correct filepath.") - endif() - if(IPOPT_ROOT_DIR AND NOT IPOPT_INCLUDE_DIR) - message(STATUS "Ipopt include directory not found! Please provide correct path.") - endif() -endif() diff --git a/CMake/FindSuiteSparse.cmake b/CMake/FindSuiteSparse.cmake deleted file mode 100644 index 2d73feb76..000000000 --- a/CMake/FindSuiteSparse.cmake +++ /dev/null @@ -1,136 +0,0 @@ -# -# 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. -# - -#[[ - -Finds Sutiesparse include directory and libraries and exports target `Suitesparse` - -User may set: -- SUITESPARSE_ROOT_DIR - -Author(s): -- Cameron Rutherford - -]] -set(SUITESPARSE_MODULES - amd - colamd - klu) - -find_library(SUITESPARSE_LIBRARY - NAMES - suitesparseconfig - ${SUITESPARSE_MODULES} - PATHS - ${SUITESPARSE_DIR} $ENV{SUITESPARSE_DIR} ${SUITESPARSE_ROOT_DIR} - ENV LD_LIBRARY_PATH ENV DYLD_LIBRARY_PATH - PATH_SUFFIXES - lib64 lib) - -if(SUITESPARSE_LIBRARY) - set(SUITESPARSE_LIBRARY CACHE FILEPATH "Path to Suitesparse library") - get_filename_component(SUITESPARSE_LIBRARY_DIR ${SUITESPARSE_LIBRARY} DIRECTORY CACHE "Suitesparse library directory") - message(STATUS "Found Suitesparse libraries in: " ${SUITESPARSE_LIBRARY_DIR}) - mark_as_advanced(SUITESPARSE_LIBRARY SUITESPARSE_LIBRARY_DIR) - if(NOT SUITESPARSE_DIR) - get_filename_component(SUITESPARSE_DIR ${SUITESPARSE_LIBRARY_DIR} DIRECTORY CACHE) - endif() -endif() - -# Find SUITESPARSE header path and ensure all needed files are there -find_path(SUITESPARSE_INCLUDE_DIR - NAMES - amd.h - colamd.h - klu.h - PATHS - ${SUITESPARSE_DIR} $ENV{SUITESPARSE_DIR} ${SUITESPARSE_ROOT_DIR} ${SUITESPARSE_LIBRARY_DIR}/.. - PATH_SUFFIXES - include) - -if(SUITESPARSE_LIBRARY) - message(STATUS "Found Suitesparse include: ${SUITESPARSE_INCLUDE_DIR}") - mark_as_advanced(SUITESPARSE_INCLUDE_DIR) - unset(SUITESPARSE_LIBRARY) - add_library(SUITESPARSE INTERFACE IMPORTED) - target_include_directories(SUITESPARSE INTERFACE ${SUITESPARSE_INCLUDE_DIR}) - foreach(mod ${SUITESPARSE_MODULES}) - find_library(suitesparse_${mod} - NAMES ${mod} - HINTS ${SUITESPARSE_LIBRARY_DIR}) - if(suitesparse_${mod}) - message(STATUS "Found suitesparse internal library " ${mod}) - target_link_libraries(SUITESPARSE INTERFACE ${suitesparse_${mod}}) - mark_as_advanced(suitesparse_${mod}) - else() - message(SEND_ERROR "Suitesparse internal library " ${mod} " not found") - endif() - endforeach(mod) -else() - if(NOT SUITESPARSE_ROOT_DIR) - message(STATUS "Suitesparse dir not found! Please provide correct filepath.") - set(SUITESPARSE_DIR ${SUITESPARSE_DIR} CACHE PATH "Path to Suitesparse installation root.") - unset(SUITESPARSE_LIBRARY CACHE) - unset(SUITESPARSE_INCLUDE_DIR CACHE) - unset(SUITESPARSE_LIBRARY_DIR CACHE) - elseif(NOT SUITESPARSE_LIBRARY) - message(STATUS "Suitesparse library not found! Please provide correct filepath.") - endif() - if(SUITESPARSE_ROOT_DIR AND NOT SUITESPARSE_INCLUDE_DIR) - message(STATUS "Suitesparse include dir not found! Please provide correct filepath.") - endif() -endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 19048d375..24f15839c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,92 +1,46 @@ # -# 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 +# ]] cmake_minimum_required(VERSION 3.12) project(gridkit) set(PACKAGE_NAME "GRIDKIT") -set(PACKAGE_STRING "GRIDKIT 0.0.7") +set(PACKAGE_STRING "GRIDKIT 0.1.0") set(PACKAGE_TARNAME "gridkit") set(PACKAGE_VERSION_MAJOR "0") -set(PACKAGE_VERSION_MINOR "0") -set(PACKAGE_VERSION_PATCH "7") +set(PACKAGE_VERSION_MINOR "1") +set(PACKAGE_VERSION_PATCH "0") set(PACKAGE_VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_PATCH}") +# TODO: Probably beter to set a debug interface target +# set(CMAKE_CXX_FLAGS_DEBUG "-Wall -O0 -g -DDEBUG") + +set(CMAKE_CXX_STANDARD 17) + # Ipopt support is disabled by default -option(GRIDKIT_ENABLE_IPOPT "Enable Ipopt support" ON) +option(GRIDKIT_ENABLE_IPOPT "Enable Ipopt support" OFF) # SUNDIALS support is enabled by default option(GRIDKIT_ENABLE_SUNDIALS "Enable SUNDIALS support" ON) # Enable KLU -option(GRIDKIT_ENABLE_SUNDIALS_SPARSE "Enable SUNDIALS sparse linear solvers" OFF) +option(GRIDKIT_ENABLE_SUNDIALS_SPARSE "Enable SUNDIALS sparse linear solvers" ON) +# Enzyme support is disabled by default +option(GRIDKIT_ENABLE_ENZYME "Enable automatic differentiation with Enzyme" OFF) set(CMAKE_MACOSX_RPATH 1) +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS 1) -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) # https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling#always-full-rpath # use, i.e. don't skip the full RPATH for the build tree @@ -109,21 +63,17 @@ if("${isSystemDir}" STREQUAL "-1") endif("${isSystemDir}" STREQUAL "-1") -# TODO: Probably beter to set a debug interface target -set(CMAKE_CXX_FLAGS_DEBUG "-Wall -O0 -g") - -set(CMAKE_CXX_STANDARD 17) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) option(GRIDKIT_BUILD_SHARED "Build shared libraries" ON) option(GRIDKIT_BUILD_STATIC "Build static libraries" OFF) if(GRIDKIT_ENABLE_IPOPT) include(FindIpopt) + enable_language(Fortran) # Needed for linking to HSL endif() if(GRIDKIT_ENABLE_SUNDIALS) - find_package(SUNDIALS 6.0.0 REQUIRED CONFIG + find_package(SUNDIALS 7.0.0 REQUIRED CONFIG PATHS ${SUNDIALS_DIR} ${SUNDIALS_DIR}/lib/cmake/sundials) message(STATUS "SUNDIALS configuration found: ${SUNDIALS_CONFIG}") @@ -132,23 +82,21 @@ if(GRIDKIT_ENABLE_SUNDIALS_SPARSE) include(FindSuiteSparse) endif() +if(${GRIDKIT_ENABLE_ENZYME}) + include(FindEnzyme) +endif() + # Macro that adds libraries include(GridkitAddLibrary) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -# Create component models -add_subdirectory(ComponentLib) - -# General Utilities and File IO -add_subdirectory(Utilities) - -# Create solvers -add_subdirectory(Solver) +add_subdirectory(src) # Create examples and tests enable_testing() -add_subdirectory(Examples) +add_subdirectory(examples) +add_subdirectory(tests) export(EXPORT gridkit-targets FILE ${CMAKE_CURRENT_BINARY_DIR}/GridKitTargets.cmake) @@ -167,7 +115,7 @@ write_basic_package_version_file( COMPATIBILITY SameMajorVersion) # Generate config file that includes exports -configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Config.cmake.in +configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/GridKitConfig.cmake INSTALL_DESTINATION share/cmake/gridkit NO_SET_AND_CHECK_MACRO diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..01fe28e12 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,401 @@ +# Developer Guidelines + +## Git workflows + +### Keeping your local repository updated + +Main development branch is `develop`. The `main` branch is used for stable, +ready-to-release code. Use `git pull` to keep `develop` branch in your local +repo updated. If you get conflicts when pulling from upstream reset your +local `develop` to the upstream: +``` +git fetch +git checkout develop +git reset --hard origin/develop +``` +Here `origin` is the name of the remote upstream repository in your local +repository. If you set custom name for your remote, replace `origin` with +that name. + + +### Feature branches + +For each new feature feature create a new branch from `develop`. Name your +feature branch `/_dev. Bug fix +branches should follow similar pattern, only ending with `_fix`. Always +use underscores to separate different words. +``` +git checkout -b shaked/sparse_matrix_transpose_dev +``` +In some instances you also might want to branch off a feature branch, for +example to fix a bug or suggest significant changes. + + +### Merging your feature branch + +Feature branches should be merged back to the branch from where they were +branched off (typically `develop`). All merging should be done through +GutHub pull request. Before creating a pull request make sure: +- All tests pass. +- Code compiles cleanly with flags `-Wall -Wpedantic -Wconversion -Wextra`. +- The new code follows GridKit™ style guidelines. +- There are unit tests for the new code. +- The new code is documented. +- The feature branch is rebased with respect to the target branch. + +To rebase your feature branch, first ensure the target branch is up-to-date. +Then use +``` +git checkout +git rebase -i +``` +to rebase your branch to the target branch. Follow the instructions on the +screen. You may need to resolve rebase conflicts. + +Once your branch is ready, create pull request using the template provided +in the GridKit™ repository. There has to be at least one approval before +the pull request can be merged. + + + + +## Code Style + +### Existing non-compliant code +The code that does not comply with these guidelines will be fixed in separate +pull request(s). Any new contribution should follow closely these guidelines +but should not change style in the existing GridKit code. + +### Error handling +Return values of member functions should be of type `int` and used for error +handling. Functions return 0 if no error is encounter, return positive value +for warnings and recoverable error, and negative value for irrecoverable +errors. + +### Output +If an output is needed (for example, a warning needs to be displayed), use +`std::cout` and not `printf` as shown below. There should be a space before +and after each `<<`. If the line needs to be broken, the `<<` operators should +be aligned: + +```c++ +std::cout << "index out of bounds. Row " << i << " starts at: " << start + << " and ends at " << end << std::endl; +``` + +### File names + +Each class should be implemented in a `*.cpp` and a `*.hpp` files with +the same name. Files containing collection of standalone functions should +have a descriptive name starting with lowercase character. + +### Using `clang-format` + +Coding style rules are specified in `.clang-format` file in GridKit root +directory. Use +```shell +clang-format -i +``` +to make sure your code follows the style guidelines. + +### Line length + +Keep line length below 80 characters unless a longer line is needed for better +clarity of the code. If your line is longer than 90 characters, you are +probably doing something wrong. + +`clang-format` is configured so it does not enforce line length; that is +developer's responsibility. Break the long lines at places where it will +improve readability of the code. Running `clang-format` after that will help +align the code properly in accordance with GridKit coding style. + +### Local variables naming + +Local variable names should use C-style name format. +```c++ +double local_variable; // Yes +double localVariable; // No, using lowercase camel instead of C-style name format +``` + +### Member variables naming + +Member variable names should use C-style name format and end with trailing underscore `_`. +```c++ +double member_variable_; // Yes +double another_member; // No, there is no trailing underscore to distinguish it from nonmember variables +double memberVariable_; // No, using lowercase camel instead of C-style name format +``` + +### Function names + +Use lowercase camel format for function names. +```c++ +int myFunction(double x); // Yes +int another_function(); // No, using C-style name format +int YetAnotherFunction(); // No, using uppercase camel name format +``` + +### Class names + +Class names should us uppercase camel name format. +```c++ +class MyClass // Yes +{ + ... +} + +class Matrix // Yes +{ + ... +} + +class My_Class // No, using underscore in class name +{ + ... +} +``` + + + +### Enums (enumerated types) + +Always define `enum`s inside `GridKit` namespace. Type names should be +capitalized and the constant names should be uppercase with underscores +(but there is no underscore at the end!). + +```c++ + enum ExampleEnum { CONST_ONE = 0, + CONST_TWO = 8, + YET_ANOTHER_CONST = 17 }; +``` + +### Constants + +If a constant is used in more than one file, define it in `Common.h`. For +constants with long names, use underscores to separate words in the constant +name. Use all caps (screaming snake case). + +```c++ + constexpr double Pi = 3.1415; // No, use all caps for the constant name + constexpr double SQRT_TWO = 1.4142 // Yes + constexpr double SQRTTWO = 1.4142 // No, the two words not separated by "_" + constexpr double EXP = 2.7183 // Yes +``` + +### Pointers and references + +The pointer `*` or reference `&` belong to the type and there should be no space between them and the type name. +```c++ +double* x; // Yes +int& n; // Yes +double *x, *y; // No, the pointer symbol is a part of `double*` type +int & n; // No, the reference symbol is a part of `int&` type +``` + +### Indentation +Use only spaces for indentation, not tabs. Indent size is 2 spaces. + +When defining a class, the code blocks after `private`, `public` and `protected` +should be aligned with opening/closing braces. There should be an empty line +before each definition (except the first one). See example below. +```c++ +class SomeClass +{ +public: + SomeClass(); + ~SomeClass(); + +private: + int some_variable_; + +protected: + void someFunction(); +}; +``` + +### Braces +All braces should follow Allman style: +```c++ +namespace SomeNamespace +{ + //some code +} +``` +For short functions (i.e., empty constructor), do not inline braces. +```c++ +ClassA::ClassA() +{ +} +``` +Have opening brace at the next line following `for`, `if`, or `while` +statement. When using `else`, follow the example below. +```c++ +if (cond == true) +{ + // some code +} +else +{ + // some other code +} + ``` +Have a space between keywords `for`, `while` and `if` and the parenthesis as +shown here: +```c++ +for (int i = 0; i < n; ++i) +{ + // some code +} +``` + +Do not use one-line `if`s and `for`s. Always use braces. + +### Use of spaces and newlines +There should be spaces between arithmetic operators. +```c++ +x = c * (a + b); // Yes +x = c*(a+b). // No, the clarity is better if there are spaces between + // binary operators and operands. +``` +When defining member functions, use one empty line between the functions. +```c++ +struct MyStruct +{ + int memberFunction() + { + // some code + } + + int anotherMemberFunction() + { + // some other code + } +}; +``` + +### Include files + +Leave one empty line between all the includes and the first line of the actual code. +```c++ +#include + +int main() +{ + std::cout +} +``` + +Header files should be included in 3 separate blocks: standard libraries, +GridKit external dependencies, and GridKit header files. There should be an +empty line between the blocks. External libraries should use `<...>`, while +GridKit headers should be included with `"..."`. + +```c++ +#include // Standard libs headers +#include + +#include // GridKit dependencies +#include + +#include "Ida.hpp" // GridKit internal header +``` + +```c++ +#include + +#include + +int main() +{ + //some code + return 0; +} +``` +The `system` includes should always be listed first. + +### Long function names + +Function declarations and function calls should be written on a single line. +If a function has large number of parameters, the function should be broken +over multiple lines so that each function parameter is on a separate line. +All parameters should be aligned with the first parameter in the function. + +```c++ +int myFunction(double x, double y); // Yes, function on a single line + +int myFunction(double x1, // Yes, function parameters on a separate lines. + double x2, + double x3, + double x4, + double x5, + double x6, + double x7); + +int myFunction(double x1, // No, function broken inconsistently. + double x2, double x3, + double x4, + double x5, double x6, double x7); + +int myFunction( + double x1, // No, first parameter should follow the parenthesis. + double x2, + double x3, + double x4, + double x5, + double x6, + double x7 +); + +``` + +### Initializer list in class constructor + +Short initializer list should follow the constructor on the same line with +space around `:`. Long initializer lists should begin on the next line, +indented and starting with `:`. Initializers should be aligned. +```c++ +// Short initializer list +MyClass(n, m) : n_(n), m_(m) +{ + // ... +} + +// Long initializer list +MyClass(n, m) + : n_(n), + m_(m), + pX_(nullptr), + pY_(nullptr), + pZ_(nullptr), + size_(0) +{ + // ... +} +``` + + + +### Using namespaces +All classes should be in namespace `GridKit`. If needed, define additional +namespaces inside `GridKit`. +```c++ +namespace GridKit +{ + class Solver // Yes, class defined inside GridKit namespace + { + // some code; + }; + + namespace LinearAlgebra + { + class Vector // Yes, class defined inside GridKit namespace + { + // vector code + }; + } +} + +class Matrix // No, class is outside GridKit namespace +{ + // matrix code +}; diff --git a/ComponentLib/Branch/Branch.cpp b/ComponentLib/Branch/Branch.cpp deleted file mode 100644 index 5adf0268a..000000000 --- a/ComponentLib/Branch/Branch.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * - * 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. - * - */ - -#include -#include -#include -#include - -#include "Branch.hpp" - -namespace ModelLib { - -/*! - * @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), - fbusID_(0), - tbusID_(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), - fbusID_(0), - tbusID_(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), - fbusID_(data.fbus), - tbusID_(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() -{ - // std::cout << "Evaluating branch residual ...\n"; - real_type b = -X_/(R_*R_ + X_*X_); - real_type g = R_/(R_*R_ + X_*X_); - ScalarT dtheta = theta1() - theta2(); - - P1() -= ( g + 0.5*G_)*V1()*V1() + V1()*V2()*(-g*cos(dtheta) - b*sin(dtheta)); - Q1() -= (-b - 0.5*B_)*V1()*V1() + V1()*V2()*(-g*sin(dtheta) + b*cos(dtheta)); - P2() -= ( g + 0.5*G_)*V2()*V2() + V1()*V2()*(-g*cos(dtheta) + b*sin(dtheta)); - Q2() -= (-b - 0.5*B_)*V2()*V2() + V1()*V2()*( g*sin(dtheta) + b*cos(dtheta)); - - return 0; -} - -template -int Branch::evaluateJacobian() -{ - 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; - -} //namespace ModelLib diff --git a/ComponentLib/Branch/Branch.hpp b/ComponentLib/Branch/Branch.hpp deleted file mode 100644 index 4637784cd..000000000 --- a/ComponentLib/Branch/Branch.hpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _BRANCH_H_ -#define _BRANCH_H_ - -#include - -namespace ModelLib -{ - template class BaseBus; -} - -namespace ModelLib -{ - /*! - * @brief Implementation of a pi-model branch between two buses. - * - */ - template - class Branch : public ModelEvaluatorImpl - { - 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 = BaseBus; - using real_type = typename ModelEvaluatorImpl::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, BranchData& data); - virtual ~Branch(); - - int allocate(); - int initialize(); - int tagDifferentiable(); - int evaluateResidual(); - int evaluateJacobian(); - int evaluateIntegrand(); - - int initializeAdjoint(); - int evaluateAdjointResidual(); - //int evaluateAdjointJacobian(); - int evaluateAdjointIntegrand(); - - void updateTime(real_type t, real_type a) - { - } - - public: - void setR(real_type R) - { - R_ = R; - } - - void setX(real_type X) - { - // std::cout << "Setting X ...\n"; - X_ = X; - } - - void setG(real_type G) - { - G_ = G; - } - - void setB(real_type B) - { - B_ = B; - } - - private: - ScalarT& V1() - { - return bus1_->V(); - } - - ScalarT& theta1() - { - return bus1_->theta(); - } - - ScalarT& P1() - { - return bus1_->P(); - } - - ScalarT& Q1() - { - return bus1_->Q(); - } - - ScalarT& V2() - { - return bus2_->V(); - } - - ScalarT& theta2() - { - return bus2_->theta(); - } - - ScalarT& P2() - { - return bus2_->P(); - } - - ScalarT& Q2() - { - return bus2_->Q(); - } - - private: - real_type R_; - real_type X_; - real_type G_; - real_type B_; - const IdxT fbusID_; - const IdxT tbusID_; - bus_type* bus1_; - bus_type* bus2_; - }; -} - -#endif // _BRANCH_H diff --git a/ComponentLib/Branch/CMakeLists.txt b/ComponentLib/Branch/CMakeLists.txt deleted file mode 100644 index bd4ff42f1..000000000 --- a/ComponentLib/Branch/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# -# 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 -#]] - -gridkit_add_library(branch - SOURCES - Branch.cpp - OUTPUT_NAME - gridkit_branch) - diff --git a/ComponentLib/Bus/BaseBus.hpp b/ComponentLib/Bus/BaseBus.hpp deleted file mode 100644 index 4e8cbd5f1..000000000 --- a/ComponentLib/Bus/BaseBus.hpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _BASE_BUS_HPP_ -#define _BASE_BUS_HPP_ - -#include - -namespace ModelLib -{ - /*! - * @brief Base class for all power flow buses. - * - * Derived bus types: - * 0 - swing bus (V and theta are constants) - * 1 - PV bus (P and V are constants) - * 2 - PQ bus (P and Q are constants) - * - * @todo Consider static instead of dynamic polymorphism for - * bus types. Create Bus class that takes template parameter - * BusType. - */ - template - class BaseBus : public ModelEvaluatorImpl - { - protected: - using ModelEvaluatorImpl::size_; - using ModelEvaluatorImpl::nnz_; - using ModelEvaluatorImpl::time_; - using ModelEvaluatorImpl::alpha_; - using ModelEvaluatorImpl::rtol_; - using ModelEvaluatorImpl::atol_; - 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 ModelEvaluatorImpl::param_up_; - using ModelEvaluatorImpl::param_lo_; - - public: - typedef typename ModelEvaluatorImpl::real_type real_type; - - enum BusType{PQ=1, PV, Slack, Isolated}; - - BaseBus(IdxT id) : busID_(id) {} - virtual ~BaseBus(){} - - // Set defaults for ModelEvaluator methods - virtual int allocate() { return 0;} - virtual int initialize() { return 0;} - virtual int tagDifferentiable() { return 0;} - virtual int evaluateResidual() { return 0;} - virtual int evaluateJacobian() { return 0;} - virtual int evaluateIntegrand() { return 0;} - - virtual int initializeAdjoint() { return 0;} - virtual int evaluateAdjointResidual() { return 0;} - //virtual int evaluateAdjointJacobian() { return 0;} - virtual int evaluateAdjointIntegrand() { return 0;} - virtual void updateTime(real_type, real_type) {} // <- throw exception here - - // Pure virtual methods specific to Bus types - virtual ScalarT& V() = 0; - virtual const ScalarT& V() const = 0; - virtual ScalarT& theta() = 0; - virtual const ScalarT& theta() const = 0; - virtual ScalarT& P() = 0; - virtual const ScalarT& P() const = 0; - virtual ScalarT& Q() = 0; - virtual const ScalarT& Q() const = 0; - - virtual ScalarT& lambdaP() = 0; - virtual const ScalarT& lambdaP() const = 0; - virtual ScalarT& lambdaQ() = 0; - virtual const ScalarT& lambdaQ() const = 0; - virtual ScalarT& PB() = 0; - virtual const ScalarT& PB() const = 0; - virtual ScalarT& QB() = 0; - virtual const ScalarT& QB() const = 0; - - virtual const int BusType() const = 0; - - virtual const IdxT BusID() const - { - return busID_; - } - - protected: - const IdxT busID_; - }; // class BaseBus - -} // namespace ModelLib - - -#endif // _BASE_BUS_HPP_ diff --git a/ComponentLib/Bus/BusFactory.hpp b/ComponentLib/Bus/BusFactory.hpp deleted file mode 100644 index 68fc5578e..000000000 --- a/ComponentLib/Bus/BusFactory.hpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * - * 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 -#include -#include - -namespace ModelLib { - - template - class BusFactory - { - public: - using real_type = typename ModelEvaluatorImpl::real_type; - using BusData = GridKit::PowerSystemData::BusData; - - BusFactory() = delete; - - static BaseBus* create(BusData& data) - { - BaseBus* bus = nullptr; - switch(data.type) - { - case 1: - bus = new BusPQ(data); - break; - case 2: - bus = new BusPV(data); - break; - case 3: - bus = new BusSlack(data); - break; - default: - // Throw exception - std::cout << "Bus type " << data.type << " unrecognized.\n"; - } - return bus; - } - }; - -} // namespace ModelLib \ No newline at end of file diff --git a/ComponentLib/Bus/BusPQ.cpp b/ComponentLib/Bus/BusPQ.cpp deleted file mode 100644 index 18c6ec22c..000000000 --- a/ComponentLib/Bus/BusPQ.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* - * - * 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 -#include "BusPQ.hpp" - -namespace ModelLib { - -/*! - * @brief Constructor for a PQ bus - * - * @todo Arguments that should be passed to ModelEvaluatorImpl constructor: - * - Number of equations = 2 (size_) - * - Number of variables = 2 (size_) - * - Number of quadratures = 0 - * - Number of optimization parameters = 0 - */ -template -BusPQ::BusPQ() - : BaseBus(0), V0_(0.0), theta0_(0.0) -{ - //std::cout << "Create BusPQ..." << std::endl; - //std::cout << "Number of equations is " << size_ << std::endl; - - size_ = 2; -} - -/*! - * @brief BusPQ constructor. - * - * This constructor sets initial values for voltage and phase angle. - * - * @todo Arguments that should be passed to ModelEvaluatorImpl constructor: - * - Number of equations = 2 (size_) - * - Number of variables = 2 (size_) - * - Number of quadratures = 0 - * - Number of optimization parameters = 0 - */ -template -BusPQ::BusPQ(ScalarT V, ScalarT theta) - : BaseBus(0), V0_(V), theta0_(theta) -{ - //std::cout << "Create BusPQ..." << std::endl; - //std::cout << "Number of equations is " << size_ << std::endl; - - size_ = 2; -} - -template -BusPQ::BusPQ(BusData& data) - : BaseBus(data.bus_i), V0_(data.Vm), theta0_(data.Va) -{ - //std::cout << "Create BusPQ..." << std::endl; - //std::cout << "Number of equations is " << size_ << std::endl; - - size_ = 2; -} - -template -BusPQ::~BusPQ() -{ - //std::cout << "Destroy PQ bus ..." << std::endl; -} - -/*! - * @brief allocate method resizes local solution and residual vectors. - */ -template -int BusPQ::allocate() -{ - //std::cout << "Allocate PQ bus ..." << std::endl; - f_.resize(size_); - y_.resize(size_); - yp_.resize(size_); - tag_.resize(size_); - - fB_.resize(size_); - yB_.resize(size_); - ypB_.resize(size_); - - return 0; -} - - -template -int BusPQ::tagDifferentiable() -{ - tag_[0] = false; - tag_[1] = false; - return 0; -} - - -/*! - * @brief initialize method sets bus variables to stored initial values. - */ -template -int BusPQ::initialize() -{ - // std::cout << "Initialize BusPQ..." << std::endl; - y_[0] = V0_; - y_[1] = theta0_; - yp_[0] = 0.0; - yp_[1] = 0.0; - - return 0; -} - -/*! - * @brief PQ bus does not compute residuals, so here we just reset residual values. - * - * @warning This implementation assumes bus residuals are always evaluated - * _before_ component model residuals. - * - */ -template -int BusPQ::evaluateResidual() -{ - // std::cout << "Evaluating residual of a PQ bus ...\n"; - f_[0] = 0.0; - f_[1] = 0.0; - return 0; -} - - -/*! - * @brief initialize method sets bus variables to stored initial values. - */ -template -int BusPQ::initializeAdjoint() -{ - // std::cout << "Initialize BusPQ..." << std::endl; - yB_[0] = 0.0; - yB_[1] = 0.0; - ypB_[0] = 0.0; - ypB_[1] = 0.0; - - return 0; -} - -template -int BusPQ::evaluateAdjointResidual() -{ - fB_[0] = 0.0; - fB_[1] = 0.0; - - return 0; -} - -// Available template instantiations -template class BusPQ; -template class BusPQ; - - -} // namespace ModelLib - diff --git a/ComponentLib/Bus/BusPQ.hpp b/ComponentLib/Bus/BusPQ.hpp deleted file mode 100644 index 45ed81a65..000000000 --- a/ComponentLib/Bus/BusPQ.hpp +++ /dev/null @@ -1,199 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _BUS_PQ_HPP_ -#define _BUS_PQ_HPP_ - -#include "BaseBus.hpp" -#include - -namespace ModelLib -{ - /*! - * @brief Implementation of a PQ bus. - * - * Voltage _V_ and phase _theta_ are variables in PQ bus model. - * Active and reactive power, _P_ and _Q_, are residual components. - * - * - */ - template - class BusPQ : public BaseBus - { - using BaseBus::size_; - using BaseBus::y_; - using BaseBus::yp_; - using BaseBus::yB_; - using BaseBus::ypB_; - using BaseBus::f_; - using BaseBus::fB_; - using BaseBus::tag_; - - public: - using real_type = typename ModelEvaluatorImpl::real_type; - using BusData = GridKit::PowerSystemData::BusData; - - BusPQ(); - BusPQ(ScalarT V, ScalarT theta); - BusPQ(BusData& data); - virtual ~BusPQ(); - - virtual int allocate(); - virtual int tagDifferentiable(); - virtual int initialize(); - virtual int evaluateResidual(); - virtual int initializeAdjoint(); - virtual int evaluateAdjointResidual(); - - virtual ScalarT& V() - { - return y_[0]; - } - - virtual const ScalarT& V() const - { - return y_[0]; - } - - virtual ScalarT& theta() - { - return y_[1]; - } - - virtual const ScalarT& theta() const - { - return y_[1]; - } - - virtual ScalarT& P() - { - return f_[0]; - } - - virtual const ScalarT& P() const - { - return f_[0]; - } - - virtual ScalarT& Q() - { - return f_[1]; - } - - virtual const ScalarT& Q() const - { - return f_[1]; - } - - virtual ScalarT& lambdaP() - { - return yB_[0]; - } - - virtual const ScalarT& lambdaP() const - { - return yB_[0]; - } - - virtual ScalarT& lambdaQ() - { - return yB_[1]; - } - - virtual const ScalarT& lambdaQ() const - { - return yB_[1]; - } - - virtual ScalarT& PB() - { - return fB_[0]; - } - - virtual const ScalarT& PB() const - { - return fB_[0]; - } - - virtual ScalarT& QB() - { - return fB_[1]; - } - - virtual const ScalarT& QB() const - { - return fB_[1]; - } - - virtual const int BusType() const - { - return BaseBus::BusType::PQ; - } - - private: - // Default initial values for voltage and phase on PQ bus - ScalarT V0_; - ScalarT theta0_; - - }; - -} // namespace ModelLib - - -#endif // _BUS_PQ_HPP_ diff --git a/ComponentLib/Bus/BusPV.cpp b/ComponentLib/Bus/BusPV.cpp deleted file mode 100644 index 5daafa102..000000000 --- a/ComponentLib/Bus/BusPV.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * - * 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 -#include "BusPV.hpp" - -namespace ModelLib { - -/*! - * @brief Constructor for a PV bus - * - * @todo Arguments that should be passed to ModelEvaluatorImpl constructor: - * - Number of equations = 1 (size_) - * - Number of variables = 1 (size_) - * - Number of quadratures = 0 - * - Number of optimization parameters = 0 - */ -template -BusPV::BusPV() - : BaseBus(0), V_(0.0), theta0_(0.0), Pg_(0.0) -{ - //std::cout << "Create BusPV..." << std::endl; - //std::cout << "Number of equations is " << size_ << std::endl; - - size_ = 1; -} - -/*! - * @brief BusPV constructor. - * - * This constructor sets initial values for voltage and phase angle. - * - * @todo Arguments that should be passed to ModelEvaluatorImpl constructor: - * - Number of equations = 1 (size_) - * - Number of variables = 1 (size_) - * - Number of quadratures = 0 - * - Number of optimization parameters = 0 - */ -template -BusPV::BusPV(ScalarT V, ScalarT theta0, ScalarT Pg) - : BaseBus(0), V_(V), theta0_(theta0), Pg_(Pg) -{ - //std::cout << "Create BusPV ..." << std::endl; - //std::cout << "Number of equations is " << size_ << std::endl; - - size_ = 1; -} - -template -BusPV::BusPV(BusData& data) - : BaseBus(data.bus_i), V_(data.Vm), theta0_(data.Va) -{ - //std::cout << "Create BusPV ..." << std::endl; - //std::cout << "Number of equations is " << size_ << std::endl; - - size_ = 1; -} - -template -BusPV::~BusPV() -{ - //std::cout << "Destroy Gen2..." << std::endl; -} - -/*! - * @brief allocate method resizes local solution and residual vectors. - */ -template -int BusPV::allocate() -{ - //std::cout << "Allocate PV bus ..." << std::endl; - f_.resize(size_); - y_.resize(size_); - yp_.resize(size_); - tag_.resize(size_); - - fB_.resize(size_); - yB_.resize(size_); - ypB_.resize(size_); - - return 0; -} - - -template -int BusPV::tagDifferentiable() -{ - tag_[0] = false; - return 0; -} - - -/*! - * @brief initialize method sets bus variables to stored initial values. - */ -template -int BusPV::initialize() -{ - // std::cout << "Initialize BusPV..." << std::endl; - theta() = theta0_; - yp_[0] = 0.0; - - return 0; -} - -/*! - * @brief PV bus does not compute residuals, so here we just reset residual values. - * - * @warning This implementation assumes bus residuals are always evaluated - * _before_ component model residuals. - * - */ -template -int BusPV::evaluateResidual() -{ - // std::cout << "Evaluating residual of a PV bus ...\n"; - P() = Pg_; - Q() = 0.0; - - return 0; -} - - -/*! - * @brief initialize method sets bus variables to stored initial values. - */ -template -int BusPV::initializeAdjoint() -{ - // std::cout << "Initialize BusPV..." << std::endl; - yB_[0] = 0.0; - ypB_[0] = 0.0; - - return 0; -} - -template -int BusPV::evaluateAdjointResidual() -{ - fB_[0] = 0.0; - - return 0; -} - -// Available template instantiations -template class BusPV; -template class BusPV; - - -} // namespace ModelLib - diff --git a/ComponentLib/Bus/BusPV.hpp b/ComponentLib/Bus/BusPV.hpp deleted file mode 100644 index fd0291b69..000000000 --- a/ComponentLib/Bus/BusPV.hpp +++ /dev/null @@ -1,214 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _BUS_PV_HPP_ -#define _BUS_PV_HPP_ - -#include -#include "BaseBus.hpp" -#include - -namespace ModelLib -{ - /*! - * @brief Implementation of a PV bus. - * - * Voltage _V_ and phase _theta_ are variables in PV bus model. - * Active and reactive power, _P_ and _Q_, are residual components. - * - * - */ - template - class BusPV : public BaseBus - { - using BaseBus::size_; - using BaseBus::y_; - using BaseBus::yp_; - using BaseBus::yB_; - using BaseBus::ypB_; - using BaseBus::f_; - using BaseBus::fB_; - using BaseBus::tag_; - - public: - using real_type = typename ModelEvaluatorImpl::real_type; - using BusData = GridKit::PowerSystemData::BusData; - - BusPV(); - BusPV(ScalarT V, ScalarT theta0, ScalarT P); - BusPV(BusData& data); - virtual ~BusPV(); - - virtual int allocate(); - virtual int tagDifferentiable(); - virtual int initialize(); - virtual int evaluateResidual(); - virtual int initializeAdjoint(); - virtual int evaluateAdjointResidual(); - - virtual ScalarT& V() - { - return V_; - } - - virtual const ScalarT& V() const - { - return V_; - } - - virtual ScalarT& theta() - { - return y_[0]; - } - - virtual const ScalarT& theta() const - { - return y_[0]; - } - - virtual ScalarT& P() - { - return f_[0]; - } - - virtual const ScalarT& P() const - { - return f_[0]; - } - - - virtual ScalarT& Q() - { - return Q_; - } - - virtual const ScalarT& Q() const - { - return Q_; - } - - virtual ScalarT& lambdaP() - { - assert(false); - return thetaB_; - } - - virtual const ScalarT& lambdaP() const - { - assert(false); - return thetaB_; - } - - virtual ScalarT& lambdaQ() - { - assert(false); - return VB_; - } - - virtual const ScalarT& lambdaQ() const - { - assert(false); - return VB_; - } - - virtual ScalarT& PB() - { - assert(false); - return PB_; - } - - virtual const ScalarT& PB() const - { - assert(false); - return PB_; - } - - virtual ScalarT& QB() - { - assert(false); - return QB_; - } - - virtual const ScalarT& QB() const - { - assert(false); - return QB_; - } - - virtual const int BusType() const - { - return BaseBus::BusType::PV; - } - - private: - ScalarT V_; - ScalarT theta0_; ///< Default initial value for phase - ScalarT Pg_; ///< Generator injection - ScalarT Q_; - - ScalarT VB_; - ScalarT thetaB_; - ScalarT PB_; - ScalarT QB_; - }; - -} // namespace ModelLib - - -#endif // _BUS_PV_HPP_ diff --git a/ComponentLib/Bus/BusSlack.cpp b/ComponentLib/Bus/BusSlack.cpp deleted file mode 100644 index 80a5ae091..000000000 --- a/ComponentLib/Bus/BusSlack.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * - * 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 -#include "BusSlack.hpp" - -namespace ModelLib { - -/*! - * @brief Constructor for a slack bus - * - * Arguments passed to ModelEvaluatorImpl: - * - Number of equations = 0 (size_) - * - Number of variables = 0 (size_) - * - Number of quadratures = 0 - * - Number of optimization parameters = 0 - */ -template -BusSlack::BusSlack() - : BaseBus(0), V_(0.0), theta_(0.0), P_(0.0), Q_(0.0), PB_(0.0), QB_(0.0) -{ - //std::cout << "Create BusSlack..." << std::endl; - //std::cout << "Number of equations is " << size_ << std::endl; - - size_ = 0; -} - -/*! - * @brief BusSlack constructor. - * - * Arguments passed to ModelEvaluatorImpl: - * - Number of equations = 0 (size_) - * - Number of variables = 0 (size_) - * - Number of quadratures = 0 - * - Number of optimization parameters = 0 - */ -template -BusSlack::BusSlack(ScalarT V, ScalarT theta) - : BaseBus(0), V_(V), theta_(theta), P_(0.0), Q_(0.0), PB_(0.0), QB_(0.0) -{ - //std::cout << "Create BusSlack..." << std::endl; - //std::cout << "Number of equations is " << size_ << std::endl; - size_ = 0; -} - -template -BusSlack::BusSlack(BusData& data) - : BaseBus(data.bus_i), V_(data.Vm), theta_(data.Va) -{ - //std::cout << "Create BusSlack..." << std::endl; - //std::cout << "Number of equations is " << size_ << std::endl; - size_ = 0; -} - -template -BusSlack::~BusSlack() -{ -} - -template -int BusSlack::evaluateResidual() -{ - // std::cout << "Evaluating residual of a slack bus ...\n"; - P() = 0.0; - Q() = 0.0; - return 0; -} - -template -int BusSlack::evaluateAdjointResidual() -{ - PB() = 0.0; - QB() = 0.0; - return 0; -} - - -// Available template instantiations -template class BusSlack; -template class BusSlack; - - -} // namespace ModelLib - diff --git a/ComponentLib/Bus/BusSlack.hpp b/ComponentLib/Bus/BusSlack.hpp deleted file mode 100644 index 19c27d96a..000000000 --- a/ComponentLib/Bus/BusSlack.hpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _BUS_SLACK_HPP_ -#define _BUS_SLACK_HPP_ - -#include "BaseBus.hpp" -#include - -namespace ModelLib -{ - /*! - * @brief Implementation of a slack bus. - * - * Slack bus sets voltage _V_ and phase _theta_ as constants. - * Active and reactive power, _P_ and _Q_, are component model outputs, - * but are computed outside the BusSlack class. - * - * - */ - template - class BusSlack : public BaseBus - { - using BaseBus::size_; - using BaseBus::y_; - using BaseBus::yp_; - using BaseBus::f_; - using BaseBus::g_; - using BaseBus::atol_; - using BaseBus::rtol_; - - public: - using real_type = typename ModelEvaluatorImpl::real_type; - using BusData = GridKit::PowerSystemData::BusData; - - BusSlack(); - BusSlack(ScalarT V, ScalarT theta); - BusSlack(BusData& data); - virtual ~BusSlack(); - virtual int evaluateResidual(); - virtual int evaluateAdjointResidual(); - - /// @todo Should slack bus allow changing voltage? - virtual ScalarT& V() - { - return V_; - } - - virtual const ScalarT& V() const - { - return V_; - } - - /// @todo Should slack bus allow changing phase? - virtual ScalarT& theta() - { - return theta_; - } - - virtual const ScalarT& theta() const - { - return theta_; - } - - virtual ScalarT& P() - { - return P_; - } - - virtual const ScalarT& P() const - { - return P_; - } - - virtual ScalarT& Q() - { - return Q_; - } - - virtual const ScalarT& Q() const - { - return Q_; - } - - /// @todo Should slack bus allow changing voltage? - virtual ScalarT& lambdaP() - { - return thetaB_; - } - - virtual const ScalarT& lambdaP() const - { - return thetaB_; - } - - /// @todo Should slack bus allow changing phase? - virtual ScalarT& lambdaQ() - { - return VB_; - } - - virtual const ScalarT& lambdaQ() const - { - return VB_; - } - - virtual ScalarT& PB() - { - return PB_; - } - - virtual const ScalarT& PB() const - { - return PB_; - } - - virtual ScalarT& QB() - { - return QB_; - } - - virtual const ScalarT& QB() const - { - return QB_; - } - - virtual const int BusType() const - { - return BaseBus::BusType::Slack; - } - - private: - ScalarT V_; - ScalarT theta_; - ScalarT P_; - ScalarT Q_; - - ScalarT VB_; - ScalarT thetaB_; - ScalarT PB_; - ScalarT QB_; - - }; // class BusSlack - -} // namespace ModelLib - - -#endif // _BUS_SLACK_HPP_ diff --git a/ComponentLib/Bus/CMakeLists.txt b/ComponentLib/Bus/CMakeLists.txt deleted file mode 100644 index c53ee6774..000000000 --- a/ComponentLib/Bus/CMakeLists.txt +++ /dev/null @@ -1,70 +0,0 @@ -# -# 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 -#]] - -gridkit_add_library(bus - SOURCES - BusPQ.cpp - BusPV.cpp - BusSlack.cpp - OUTPUT_NAME - gridkit_bus) - diff --git a/ComponentLib/CMakeLists.txt b/ComponentLib/CMakeLists.txt deleted file mode 100644 index 0c422d5b9..000000000 --- a/ComponentLib/CMakeLists.txt +++ /dev/null @@ -1,71 +0,0 @@ -# -# 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 -#]] - -add_subdirectory(Branch) -add_subdirectory(Bus) -add_subdirectory(Generator) -add_subdirectory(Generator2) -add_subdirectory(Generator4) -add_subdirectory(Generator4Governor) -add_subdirectory(Generator4Param) -add_subdirectory(Load) -add_subdirectory(MiniGrid) diff --git a/ComponentLib/Generator/CMakeLists.txt b/ComponentLib/Generator/CMakeLists.txt deleted file mode 100644 index a09c5aed1..000000000 --- a/ComponentLib/Generator/CMakeLists.txt +++ /dev/null @@ -1,70 +0,0 @@ -# -# 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 -#]] - -gridkit_add_library(generator - SOURCES - GeneratorSlack.cpp - GeneratorPV.cpp - GeneratorPQ.cpp - OUTPUT_NAME - gridkit_generator) - diff --git a/ComponentLib/Generator/GeneratorBase.hpp b/ComponentLib/Generator/GeneratorBase.hpp deleted file mode 100644 index e1efa22bd..000000000 --- a/ComponentLib/Generator/GeneratorBase.hpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * - * 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 - -namespace ModelLib -{ - template class BaseBus; -} - - -namespace ModelLib -{ - /** - * @brief Generator base class template - * - * @tparam ScalarT - Scalar type - * @tparam IdxT - Matrix and vector index type - */ - template - class GeneratorBase : public ModelEvaluatorImpl - { - protected: - 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 = BaseBus; - using real_type = typename ModelEvaluatorImpl::real_type; - - public: - GeneratorBase(){} - virtual ~GeneratorBase(){} - - virtual int allocate() { return 0;} - virtual int initialize() { return 0;} - virtual int tagDifferentiable() { return 0;} - virtual int evaluateResidual() { return 0;} - virtual int evaluateJacobian() { return 0;} - virtual int evaluateIntegrand() { return 0;} - - virtual int initializeAdjoint() { return 0;} - virtual int evaluateAdjointResidual() { return 0;} - //virtual int evaluateAdjointJacobian(); - virtual int evaluateAdjointIntegrand() { return 0;} - - void updateTime(real_type, real_type) {} - - virtual ScalarT& P() = 0; - virtual const ScalarT& P() const = 0; - virtual ScalarT& Q() = 0; - virtual const ScalarT& Q() const = 0; - }; -} - diff --git a/ComponentLib/Generator/GeneratorFactory.hpp b/ComponentLib/Generator/GeneratorFactory.hpp deleted file mode 100644 index ccb2c07e1..000000000 --- a/ComponentLib/Generator/GeneratorFactory.hpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * - * 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 -#include -#include -#include - - -namespace ModelLib { - - template - class GeneratorFactory - { - public: - using real_type = typename ModelEvaluatorImpl::real_type; - using GenData = GridKit::PowerSystemData::GenData; - - GeneratorFactory() = delete; - - static GeneratorBase* create(BaseBus* bus, GenData& data) - { - GeneratorBase* gen = nullptr; - switch(bus->BusType()) - { - case 1: - gen = new GeneratorPQ(bus, data); - break; - case 2: - gen = new GeneratorPV(bus, data); - break; - case 3: - gen = new GeneratorSlack(bus, data); - break; - default: - // Throw exception - std::cout << "Generator type " << bus->BusType() << " unrecognized.\n"; - } - return gen; - } - }; - -} // namespace ModelLib \ No newline at end of file diff --git a/ComponentLib/Generator/GeneratorPQ.cpp b/ComponentLib/Generator/GeneratorPQ.cpp deleted file mode 100644 index 981ec786b..000000000 --- a/ComponentLib/Generator/GeneratorPQ.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * - * 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 -#include -#include "GeneratorPQ.hpp" -#include - -namespace ModelLib { - -/*! - * @brief Constructor for a constant load model - * - * Calls default ModelEvaluatorImpl constructor. - */ - -template -GeneratorPQ::GeneratorPQ(bus_type* bus, GenData& data) - : P_(data.Pg), - Q_(data.Qg), - bus_(bus) -{ - //std::cout << "Create a load model with " << size_ << " variables ...\n"; - size_ = 0; -} - -template -GeneratorPQ::~GeneratorPQ() -{ -} - -/*! - * @brief allocate method computes sparsity pattern of the Jacobian. - */ -template -int GeneratorPQ::allocate() -{ - return 0; -} - -/** - * Initialization of the grid model - */ -template -int GeneratorPQ::initialize() -{ - return 0; -} - -/* - * \brief Identify differential variables - */ -template -int GeneratorPQ::tagDifferentiable() -{ - return 0; -} - -/** - * @brief Contributes to the bus residual. - * - * Must be connected to a PQ bus. - */ -template -int GeneratorPQ::evaluateResidual() -{ - // std::cout << "Evaluating load residual ...\n"; - bus_->P() += P_; - bus_->Q() += Q_; - return 0; -} - -template -int GeneratorPQ::evaluateJacobian() -{ - return 0; -} - -template -int GeneratorPQ::evaluateIntegrand() -{ - return 0; -} - -template -int GeneratorPQ::initializeAdjoint() -{ - return 0; -} - -template -int GeneratorPQ::evaluateAdjointResidual() -{ - return 0; -} - -template -int GeneratorPQ::evaluateAdjointIntegrand() -{ - return 0; -} - - -// Available template instantiations -template class GeneratorPQ; -template class GeneratorPQ; - - -} //namespace ModelLib - diff --git a/ComponentLib/Generator/GeneratorPQ.hpp b/ComponentLib/Generator/GeneratorPQ.hpp deleted file mode 100644 index ba72d022a..000000000 --- a/ComponentLib/Generator/GeneratorPQ.hpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * - * 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 -#include -#include "GeneratorBase.hpp" - -namespace ModelLib -{ - template class BaseBus; -} - - -namespace ModelLib -{ - /*! - * @brief Implementation of a PV generator. - * - */ - template - class GeneratorPQ : public GeneratorBase - { - using GeneratorBase::size_; - using GeneratorBase::nnz_; - using GeneratorBase::time_; - using GeneratorBase::alpha_; - using GeneratorBase::y_; - using GeneratorBase::yp_; - using GeneratorBase::tag_; - using GeneratorBase::f_; - using GeneratorBase::g_; - using GeneratorBase::yB_; - using GeneratorBase::ypB_; - using GeneratorBase::fB_; - using GeneratorBase::gB_; - using GeneratorBase::param_; - - using bus_type = BaseBus; - using real_type = typename ModelEvaluatorImpl::real_type; - using GenData = GridKit::PowerSystemData::GenData; - - public: - GeneratorPQ(bus_type* bus, GenData& data); - virtual ~GeneratorPQ(); - - int allocate(); - int initialize(); - int tagDifferentiable(); - int evaluateResidual(); - int evaluateJacobian(); - int evaluateIntegrand(); - - int initializeAdjoint(); - int evaluateAdjointResidual(); - //int evaluateAdjointJacobian(); - int evaluateAdjointIntegrand(); - - virtual ScalarT& P() - { - return P_; - } - - virtual const ScalarT& P() const - { - return P_; - } - - virtual ScalarT& Q() - { - return Q_; - } - - virtual const ScalarT& Q() const - { - return Q_; - } - - private: - ScalarT P_; - ScalarT Q_; - bus_type* bus_; - }; -} - diff --git a/ComponentLib/Generator/GeneratorPV.cpp b/ComponentLib/Generator/GeneratorPV.cpp deleted file mode 100644 index f6e4bd447..000000000 --- a/ComponentLib/Generator/GeneratorPV.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * - * 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 -#include -#include "GeneratorPV.hpp" -#include - -namespace ModelLib { - -/*! - * @brief Constructor for a constant load model - * - * Calls default ModelEvaluatorImpl constructor. - */ - -template -GeneratorPV::GeneratorPV(bus_type* bus, GenData& data) - : P_(data.Pg), - // Q_(data.Qg), - bus_(bus) -{ - //std::cout << "Create a load model with " << size_ << " variables ...\n"; - size_ = 0; -} - -template -GeneratorPV::~GeneratorPV() -{ -} - -/*! - * @brief allocate method computes sparsity pattern of the Jacobian. - */ -template -int GeneratorPV::allocate() -{ - return 0; -} - -/** - * Initialization of the grid model - */ -template -int GeneratorPV::initialize() -{ - return 0; -} - -/* - * \brief Identify differential variables - */ -template -int GeneratorPV::tagDifferentiable() -{ - return 0; -} - -/** - * @brief Contributes to the bus residual. - * - * Must be connected to a PQ bus. - */ -template -int GeneratorPV::evaluateResidual() -{ - // std::cout << "Evaluating load residual ...\n"; - bus_->P() += P_; - // bus_->Q() += Q_; - return 0; -} - -template -int GeneratorPV::evaluateJacobian() -{ - return 0; -} - -template -int GeneratorPV::evaluateIntegrand() -{ - return 0; -} - -template -int GeneratorPV::initializeAdjoint() -{ - return 0; -} - -template -int GeneratorPV::evaluateAdjointResidual() -{ - return 0; -} - -template -int GeneratorPV::evaluateAdjointIntegrand() -{ - return 0; -} - - -// Available template instantiations -template class GeneratorPV; -template class GeneratorPV; - - -} //namespace ModelLib - diff --git a/ComponentLib/Generator/GeneratorPV.hpp b/ComponentLib/Generator/GeneratorPV.hpp deleted file mode 100644 index 5e3be2041..000000000 --- a/ComponentLib/Generator/GeneratorPV.hpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * - * 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 -#include -#include "GeneratorBase.hpp" - -namespace ModelLib -{ - template class BaseBus; -} - - -namespace ModelLib -{ - /*! - * @brief Implementation of a PV generator. - * - */ - template - class GeneratorPV : public GeneratorBase - { - using GeneratorBase::size_; - using GeneratorBase::nnz_; - using GeneratorBase::time_; - using GeneratorBase::alpha_; - using GeneratorBase::y_; - using GeneratorBase::yp_; - using GeneratorBase::tag_; - using GeneratorBase::f_; - using GeneratorBase::g_; - using GeneratorBase::yB_; - using GeneratorBase::ypB_; - using GeneratorBase::fB_; - using GeneratorBase::gB_; - using GeneratorBase::param_; - - using bus_type = BaseBus; - using real_type = typename ModelEvaluatorImpl::real_type; - using GenData = GridKit::PowerSystemData::GenData; - - public: - GeneratorPV(bus_type* bus, GenData& data); - virtual ~GeneratorPV(); - - int allocate(); - int initialize(); - int tagDifferentiable(); - int evaluateResidual(); - int evaluateJacobian(); - int evaluateIntegrand(); - - int initializeAdjoint(); - int evaluateAdjointResidual(); - //int evaluateAdjointJacobian(); - int evaluateAdjointIntegrand(); - - virtual ScalarT& P() - { - return P_; - } - - virtual const ScalarT& P() const - { - return P_; - } - - virtual ScalarT& Q() - { - return bus_->Q(); - } - - virtual const ScalarT& Q() const - { - return bus_->Q(); - } - - private: - ScalarT P_; - bus_type* bus_; - }; -} - diff --git a/ComponentLib/Generator/GeneratorSlack.cpp b/ComponentLib/Generator/GeneratorSlack.cpp deleted file mode 100644 index de97c4752..000000000 --- a/ComponentLib/Generator/GeneratorSlack.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * - * 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 -#include -#include "GeneratorSlack.hpp" -#include - -namespace ModelLib { - -/*! - * @brief Constructor for a constant load model - * - * Calls default ModelEvaluatorImpl constructor. - */ - -template -GeneratorSlack::GeneratorSlack(bus_type* bus, GenData& data) - : bus_(bus) -{ - //std::cout << "Create a load model with " << size_ << " variables ...\n"; - size_ = 0; -} - -template -GeneratorSlack::~GeneratorSlack() -{ -} - -/*! - * @brief allocate method computes sparsity pattern of the Jacobian. - */ -template -int GeneratorSlack::allocate() -{ - return 0; -} - -/** - * Initialization of the grid model - */ -template -int GeneratorSlack::initialize() -{ - return 0; -} - -/* - * \brief Identify differential variables - */ -template -int GeneratorSlack::tagDifferentiable() -{ - return 0; -} - -/** - * @brief Contributes to the bus residual. - * - * Must be connected to a PQ bus. - */ -template -int GeneratorSlack::evaluateResidual() -{ - // std::cout << "Evaluating load residual ...\n"; - // bus_->P() += P_; - // bus_->Q() += Q_; - return 0; -} - -template -int GeneratorSlack::evaluateJacobian() -{ - return 0; -} - -template -int GeneratorSlack::evaluateIntegrand() -{ - return 0; -} - -template -int GeneratorSlack::initializeAdjoint() -{ - return 0; -} - -template -int GeneratorSlack::evaluateAdjointResidual() -{ - return 0; -} - -template -int GeneratorSlack::evaluateAdjointIntegrand() -{ - return 0; -} - - - - -// Available template instantiations -template class GeneratorSlack; -template class GeneratorSlack; - - -} //namespace ModelLib - diff --git a/ComponentLib/Generator/GeneratorSlack.hpp b/ComponentLib/Generator/GeneratorSlack.hpp deleted file mode 100644 index e821f8a6b..000000000 --- a/ComponentLib/Generator/GeneratorSlack.hpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * - * 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 "GeneratorBase.hpp" -#include -#include - -namespace ModelLib -{ - template class BaseBus; -} - - -namespace ModelLib -{ - /*! - * @brief Implementation of a power grid. - * - */ - template - class GeneratorSlack : public GeneratorBase - { - using GeneratorBase::size_; - using GeneratorBase::nnz_; - using GeneratorBase::time_; - using GeneratorBase::alpha_; - using GeneratorBase::y_; - using GeneratorBase::yp_; - using GeneratorBase::tag_; - using GeneratorBase::f_; - using GeneratorBase::g_; - using GeneratorBase::yB_; - using GeneratorBase::ypB_; - using GeneratorBase::fB_; - using GeneratorBase::gB_; - using GeneratorBase::param_; - - using bus_type = BaseBus; - using real_type = typename ModelEvaluatorImpl::real_type; - using GenData = GridKit::PowerSystemData::GenData; - // typedef typename ModelEvaluatorImpl::real_type real_type; - // typedef BaseBus bus_type; - - public: - GeneratorSlack(bus_type* bus, GenData& data); - virtual ~GeneratorSlack(); - - int allocate(); - int initialize(); - int tagDifferentiable(); - int evaluateResidual(); - int evaluateJacobian(); - int evaluateIntegrand(); - - int initializeAdjoint(); - int evaluateAdjointResidual(); - //int evaluateAdjointJacobian(); - int evaluateAdjointIntegrand(); - - virtual ScalarT& P() - { - return bus_->P(); - } - - virtual const ScalarT& P() const - { - return bus_->P(); - } - - virtual ScalarT& Q() - { - return bus_->Q(); - } - - virtual const ScalarT& Q() const - { - return bus_->Q(); - } - - - private: - bus_type* bus_; - }; -} - diff --git a/ComponentLib/Generator2/CMakeLists.txt b/ComponentLib/Generator2/CMakeLists.txt deleted file mode 100644 index a1fbc1d21..000000000 --- a/ComponentLib/Generator2/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# -# 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 -#]] - -gridkit_add_library(generator2 - SOURCES - Generator2.cpp - OUTPUT_NAME - gridkit_generator2) - diff --git a/ComponentLib/Generator2/Generator2.cpp b/ComponentLib/Generator2/Generator2.cpp deleted file mode 100644 index 132475937..000000000 --- a/ComponentLib/Generator2/Generator2.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* - * - * 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 -#include -#include "Generator2.hpp" - -namespace ModelLib { - -/*! - * @brief Constructor for a simple generator model - * - * Arguments passed to ModelEvaluatorImpl: - * - Number of equations = 2 - * - Number of quadratures = 1 - * - Number of optimization parameters = 1 - */ -template -Generator2::Generator2(bus_type* bus) - : ModelEvaluatorImpl(2, 1, 1), - H_(5.0), - D_(0.005), - Pm_(0.7), - Xdp_(0.5), - Eqp_(0.93), - omega_s_(1.0), - omega_b_(2.0*60.0*M_PI), - omega_up_(omega_s_ + 0.0002), - omega_lo_(omega_s_ - 0.0002), - theta_s_(1.0), - c_(10000.0), - beta_(2), - bus_(bus) -{ -} - -template -Generator2::~Generator2() -{ -} - -/*! - * @brief allocate method computes sparsity pattern of the Jacobian. - */ -template -int Generator2::allocate() -{ - tag_.resize(size_); - return 0; -} - -template -int Generator2::tagDifferentiable() -{ - tag_[0] = true; - tag_[1] = true; - return 0; -} - -template -int Generator2::initialize() -{ - // Set optimization parameter value and bounds - param_[0] = Pm_; - param_up_[0] = 1.5; - param_lo_[0] = 0.5; - - y_[0] = asin((Pm_*Xdp_)/(Eqp_*V())) + theta(); // <~ asin(Pm/Pmax) - y_[1] = omega_s_; - yp_[0] = 0.0; - yp_[1] = 0.0; - - return 0; -} - -template -int Generator2::evaluateResidual() -{ - f_[0] = -yp_[0] + omega_b_*(y_[1]-omega_s_); - f_[1] = -yp_[1] + omega_s_/(2.0*H_)*( param_[0] - Eqp_/Xdp_*V()*sin(y_[0] - theta()) - D_*(y_[1]-omega_s_) ); - return 0; -} - -template -int Generator2::evaluateJacobian() -{ - std::cout << "Evaluate Jacobian for Gen2..." << std::endl; - std::cout << "Jacobian evaluation not implemented!" << std::endl; - return 0; -} - -template -int Generator2::evaluateIntegrand() -{ - g_[0] = frequencyPenalty(y_[1]); - return 0; -} - -template -int Generator2::initializeAdjoint() -{ - yB_[0] = 0.0; - yB_[1] = 0.0; - ypB_[0] = 0.0; - ypB_[1] = frequencyPenaltyDer(y_[1]); - - return 0; -} - -template -int Generator2::evaluateAdjointResidual() -{ - fB_[0] = -ypB_[0] + omega_s_/(2.0*H_)*Eqp_/Xdp_*V()*cos(y_[0] - theta()) * yB_[1]; - fB_[1] = -ypB_[1] + omega_s_/(2.0*H_)*D_ * yB_[1] - omega_b_*yB_[0] + frequencyPenaltyDer(y_[1]); - return 0; -} - -// template -// int Generator2::evaluateAdjointJacobian() -// { -// std::cout << "Evaluate adjoint Jacobian for Gen2..." << std::endl; -// std::cout << "Adjoint Jacobian evaluation not implemented!" << std::endl; -// return 0; -// } - -template -int Generator2::evaluateAdjointIntegrand() -{ - // std::cout << "Evaluate adjoint Integrand for Gen2..." << std::endl; - gB_[0] = -omega_s_/(2.0*H_) * yB_[1]; - return 0; -} - - -// -// Private functions -// - -/** - * Frequency penalty is used as the objective function for the generator model. - */ -template -ScalarT Generator2::frequencyPenalty(ScalarT omega) -{ - return c_ * pow(std::max(0.0, std::max(omega - omega_up_, omega_lo_ - omega)), beta_); -} - -/** - * Derivative of frequency penalty cannot be written in terms of min/max functions. - * Need to expand conditional statements instead. - */ -template -ScalarT Generator2::frequencyPenaltyDer(ScalarT omega) -{ - if (omega > omega_up_) - { - return beta_ * c_ * pow(omega - omega_up_, beta_ - 1.0); - } - else if (omega < omega_lo_) - { - return beta_ * c_ * pow(omega - omega_lo_, beta_ - 1.0); - } - else - { - return 0.0; - } -} - - - -// Available template instantiations -template class Generator2; -template class Generator2; - - -} // namespace ModelLib \ No newline at end of file diff --git a/ComponentLib/Generator2/Generator2.hpp b/ComponentLib/Generator2/Generator2.hpp deleted file mode 100644 index 3604ce335..000000000 --- a/ComponentLib/Generator2/Generator2.hpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - * - * 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 - -namespace ModelLib -{ - template class BaseBus; -} - -namespace ModelLib -{ - /*! - * @brief Implementation of a second order generator model. - * - */ - template - class Generator2 : public ModelEvaluatorImpl - { - 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 ModelEvaluatorImpl::param_up_; - using ModelEvaluatorImpl::param_lo_; - - typedef typename ModelEvaluatorImpl::real_type real_type; - typedef BaseBus bus_type; - - public: - Generator2(bus_type* bus); - virtual ~Generator2(); - - int allocate(); - int initialize(); - int tagDifferentiable(); - int evaluateResidual(); - int evaluateJacobian(); - int evaluateIntegrand(); - - int initializeAdjoint(); - int evaluateAdjointResidual(); - //int evaluateAdjointJacobian(); - int evaluateAdjointIntegrand(); - - void updateTime(real_type t, real_type a) - { - time_ = t; - alpha_ = a; - } - - const ScalarT& V() const - { - return bus_->V(); - } - - ScalarT& V() - { - return bus_->V(); - } - - const ScalarT& theta() const - { - return bus_->theta(); - } - - ScalarT& theta() - { - return bus_->theta(); - } - - private: - inline ScalarT frequencyPenalty(ScalarT omega); - inline ScalarT frequencyPenaltyDer(ScalarT omega); - - private: - real_type H_; - real_type D_; - real_type Pm_; - real_type Xdp_; - real_type Eqp_; - real_type omega_s_; - real_type omega_b_; - real_type omega_up_; - real_type omega_lo_; - real_type theta_s_; - real_type c_; - real_type beta_; - - bus_type* bus_; - }; - -} // namespace ModelLib \ No newline at end of file diff --git a/ComponentLib/Generator4/CMakeLists.txt b/ComponentLib/Generator4/CMakeLists.txt deleted file mode 100644 index 527d4ab11..000000000 --- a/ComponentLib/Generator4/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# -# 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 -#]] - -gridkit_add_library(generator4 - SOURCES - Generator4.cpp - OUTPUT_NAME - gridkit_generator4) - diff --git a/ComponentLib/Generator4/Generator4.cpp b/ComponentLib/Generator4/Generator4.cpp deleted file mode 100644 index f6a70e7b2..000000000 --- a/ComponentLib/Generator4/Generator4.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* - * - * 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 -#include -#include "Generator4.hpp" - -namespace ModelLib { - -/*! - * @brief Constructor for a simple generator model - * - * Arguments passed to ModelEvaluatorImpl: - * - Number of equations = 4 differential + 2 algebraic = 6 - * - Number of quadratures = 1 - * - Number of optimization parameters = 2 - */ -template -Generator4::Generator4(bus_type* bus, ScalarT P0, ScalarT Q0) - : ModelEvaluatorImpl(6, 1, 2), - H_(5.0), - D_(0.04), - Xq_(0.85), - Xd_(1.05), - Xqp_(0.35), - Xdp_(0.35), - Rs_(0.01), - Tq0p_(1.0), // [s] - Td0p_(8.0), // [s] - Ef_(1.45), - Pm_(1.0), - omega_s_(1.0), - omega_b_(2.0*60.0*M_PI), - omega_up_(omega_s_ + 0.0001), - omega_lo_(omega_s_ - 0.0001), - c_(10000.0), - beta_(2), - P0_(P0), - Q0_(Q0), - bus_(bus) -{ -} - -template -Generator4::~Generator4() -{ -} - -/*! - * @brief This function will be used to allocate sparse Jacobian matrices. - * - */ -template -int Generator4::allocate() -{ - //std::cout << "Allocate Generator4..." << std::endl; - tag_.resize(size_); - - return 0; -} - -/** - * @brief Initialization of the generator model - * - * Initialization equations are derived from example 9.2 in Power System - * Modeling and Scripting, Federico Milano, Chapter 9, p. 225: - * \f{eqnarray*}{ - * &~& \omega_0 = 0, \\ - * &~& \delta_0 = \tan^{-1} \left(\frac{X_q P_0 - R_s Q_0}{V_0^2 + R_s P_0 + X_q Q_0} \right) + \theta_0, \\ - * &~& \phi_0 = \delta_0 - \theta_0 + \tan^{-1} \left( \frac{Q_0}{P_0} \right), \\ - * &~& I_{d0} = \frac{\sqrt{P_0^2 + Q_0^2}}{V_0} \sin(\phi_0), \\ - * &~& I_{q0} = \frac{\sqrt{P_0^2 + Q_0^2}}{V_0} \cos(\phi_0), \\ - * &~& E_{d0}' = V_0 \sin(\delta_0 - \theta_0) + R_s I_{d0} - X_q' I_{q0}, \\ - * &~& E_{q0}' = V_0 \cos(\delta_0 - \theta_0) + R_s I_{q0} + X_d' I_{d0} - * \f} - * - * The input from exciter and governor is set to the steady state value: - * \f{eqnarray*}{ - * &~& E_{f0} = E_{q0}' + (X_d - X_d') I_{d0}, \\ - * &~& P_{m0} = E_{d0}' I_{d0} + E_{q0}' I_{q0} + ( X_q' - X_d') I_{d0} I_{q0} - * \f} - * - */ -template -int Generator4::initialize() -{ - // std::cout << "Initialize Generator4..." << std::endl; - - // Compute initial guess for the generator voltage phase - const ScalarT delta = atan((Xq_*P0_ - Rs_*Q0_) / (V()*V() + Rs_*P0_ + Xq_*Q0_)) + theta(); - - // Compute initial guess for the generator current phase - const ScalarT phi = theta() - delta - atan(Q0_/P0_); - - // Compute initial gueses for generator currents and potentials in d-q frame - const ScalarT Id = std::sqrt(P0_*P0_ + Q0_*Q0_)/V() * sin(phi); - const ScalarT Iq = std::sqrt(P0_*P0_ + Q0_*Q0_)/V() * cos(phi); - const ScalarT Ed = V()*sin(theta() - delta) + Rs_*Id + Xqp_*Iq; - const ScalarT Eq = V()*cos(theta() - delta) + Rs_*Iq - Xdp_*Id; - - y_[0] = delta; - y_[1] = omega_s_; - y_[2] = Ed; - y_[3] = Eq; - y_[4] = Id; - y_[5] = Iq; - yp_[0] = 0.0; - yp_[1] = 0.0; - yp_[2] = 0.0; - yp_[3] = 0.0; - yp_[4] = 0.0; - yp_[5] = 0.0; - - // Set control parameter values here. - Ef_ = Eq - (Xd_ - Xdp_)*Id; // <~ set to steady state value - Pm_ = Ed*Id + Eq*Iq + (Xdp_ - Xqp_)*Id*Iq; // <~ set to steady state value - - // Initialize optimization parameters - param_[0] = Pm_; - param_up_[0] = 1.5; - param_lo_[0] = 0.0; - - param_[1] = Ef_; - param_up_[1] = 1.7; - param_lo_[1] = 0.0; - - return 0; -} - -/** - * \brief Identify differential variables. - */ -template -int Generator4::tagDifferentiable() -{ - tag_[0] = true; - tag_[1] = true; - tag_[2] = true; - tag_[3] = true; - - for (IdxT i=4; i < size_; ++i) - { - tag_[i] = false; - } - - return 0; -} - -/** - * @brief Computes residual vector for the generator model. - * - * Residual equations are given per model in Power System Modeling and - * Scripting, Federico Milano, Chapter 15, p. 334: - * \f{eqnarray*}{ - * f_0: &~& \dot{\delta} -\omega_b (\omega - \omega_s), \\ - * f_1: &~& 2H/\omega_s \dot{\omega} - L_m(P_m) + E_q' I_q + E_d' I_d + (X_q' - X_d')I_d I_q + D (\omega - \omega_s), \\ - * f_2: &~& T_{q0}' \dot{E}_d' + E_d' - (X_q - X_q')I_q, \\ - * f_3: &~& T_{d0}' \dot{E}_q' + E_q' + (X_d - X_d')I_d - E_f, \\ - * f_4: &~& R_s I_d - X_q' I_q + V \sin(\delta - \theta) - E_d', \\ - * f_5: &~& R_s I_q + X_d' I_d + V \cos(\delta - \theta) - E_q', - * \f} - * where \f$ \Omega_b \f$ is the synchronous frequency in [rad/s], and - * overdot denotes time derivative. - * - * Generator injection active and reactive power are - * \f{eqnarray*}{ - * P_g &=& E_d' I_d + E_q' I_q + (X_q' - X_d') I_d I_q - R_s (I_d^2 + I_q^2), \\ - * Q_q &=& E_q' I_d - E_d' I_q - X_q' I_q^2 - X_d' I_d^2, \\ - * \f} - * respectively. - * - * State variables are: - * \f$ y_0 = \omega \f$, \f$ y_1 = \delta \f$, \f$ y_2 = E_d' \f$, \f$ y_3 = E_q' \f$, - * \f$ y_4 = I_d \f$, \f$ y_5 = I_q \f$. - * - */ -template -int Generator4::evaluateResidual() -{ - // std::cout << "Evaluate residual for Generator4..." << std::endl; - f_[0] = dotDelta() - omega_b_* (omega() - omega_s_); - f_[1] = (2.0*H_)/omega_s_*dotOmega() - Pm() + Eqp()*Iq() + Edp()*Id() + (- Xdp_ + Xqp_)*Id()*Iq() + D_*(omega() - omega_s_); - f_[2] = Tq0p_*dotEdp() + Edp() - (Xq_ - Xqp_)*Iq(); - f_[3] = Td0p_*dotEqp() + Eqp() + (Xd_ - Xdp_)*Id() - Ef(); - f_[4] = Rs_*Id() - Xqp_*Iq() + V()*sin(delta() - theta()) - Edp(); - f_[5] = Xdp_*Id() + Rs_*Iq() + V()*cos(delta() - theta()) - Eqp(); - - // Compute active and reactive load provided by the infinite bus. - P() += Pg(); - Q() += Qg(); - - return 0; -} - -template -int Generator4::evaluateJacobian() -{ - std::cerr << "Evaluate Jacobian for Generator4..." << std::endl; - std::cerr << "Jacobian evaluation not implemented!" << std::endl; - return 0; -} - -template -int Generator4::evaluateIntegrand() -{ - // std::cout << "Evaluate Integrand for Generator4..." << std::endl; - g_[0] = frequencyPenalty(y_[1]); - return 0; -} - -template -int Generator4::initializeAdjoint() -{ - //std::cout << "Initialize adjoint for Generator4..." << std::endl; - for (IdxT i=0; i -int Generator4::evaluateAdjointResidual() -{ - // std::cout << "Evaluate adjoint residual for Generator4..." << std::endl; - ScalarT sinPhi = sin(delta() - theta()); - ScalarT cosPhi = cos(delta() - theta()); - - // Generator adjoint - fB_[0] = ypB_[0] - yB_[4]*V()*cosPhi + yB_[5]*V()*sinPhi; - fB_[1] = 2.0*H_/omega_s_*ypB_[1] + yB_[0]*omega_b_ - yB_[1]*D_ + frequencyPenaltyDer(omega()); - fB_[2] = Tq0p_*ypB_[2] - yB_[1]*Id() - yB_[2] + yB_[4]; - fB_[3] = Td0p_*ypB_[3] - yB_[1]*Iq() - yB_[3] + yB_[5]; - fB_[4] = -yB_[1]*(Edp() + (Xqp_ - Xdp_)*Iq()) - yB_[3]*(Xd_ - Xdp_) - yB_[4]*Rs_ - yB_[5]*Xdp_; - fB_[5] = -yB_[1]*(Eqp() + (Xqp_ - Xdp_)*Id()) + yB_[2]*(Xq_ - Xqp_) + yB_[4]*Xqp_ - yB_[5]*Rs_; - - return 0; -} - -// template -// int Generator4::evaluateAdjointJacobian() -// { -// std::cout << "Evaluate adjoint Jacobian for Generator4..." << std::endl; -// std::cout << "Adjoint Jacobian evaluation not implemented!" << std::endl; -// return 0; -// } - -template -int Generator4::evaluateAdjointIntegrand() -{ - // std::cout << "Evaluate adjoint Integrand for Generator4..." << std::endl; - gB_[0] = yB_[1]; - gB_[1] = yB_[3]; - - return 0; -} - - -// -// Private functions -// - -/** - * Generator active power Pg. - * - * \f[ P_g = E_q' I_q + E_d' I_d + (X_q' - X_d') I_q I_d - R_a (I_d^2 + I_q^2) \f] - * - */ -template -ScalarT Generator4::Pg() -{ - return y_[5]*V()*cos(theta() - y_[0]) + y_[4]*V()*sin(theta() - y_[0]); -} - -/** - * Generator reactive power Qg. - * - * \f[ Q_g = E_q' I_d - E_d' I_q - X_d' I_d^2 - X_q' I_q^2 \f] - */ -template -ScalarT Generator4::Qg() -{ - return y_[5]*V()*sin(theta() - y_[0]) - y_[4]*V()*cos(theta() - y_[0]); -} - -/** - * Frequency penalty is used as the objective function for the generator model. - */ -template -ScalarT Generator4::frequencyPenalty(ScalarT omega) -{ - return c_ * pow(std::max(0.0, std::max(omega - omega_up_, omega_lo_ - omega)), beta_); -} - -/** - * Derivative of frequency penalty cannot be written in terms of min/max functions. - * Need to expand conditional statements instead. - */ -template -ScalarT Generator4::frequencyPenaltyDer(ScalarT omega) -{ - if (omega > omega_up_) - { - return beta_ * c_ * pow(omega - omega_up_, beta_ - 1.0); - } - else if (omega < omega_lo_) - { - return beta_ * c_ * pow(omega - omega_lo_, beta_ - 1.0); - } - else - { - return 0.0; - } -} - - - -// Available template instantiations -template class Generator4; -template class Generator4; - - -} // namespace ModelLib - diff --git a/ComponentLib/Generator4/Generator4.hpp b/ComponentLib/Generator4/Generator4.hpp deleted file mode 100644 index ff4333ef8..000000000 --- a/ComponentLib/Generator4/Generator4.hpp +++ /dev/null @@ -1,262 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _GENERATOR_4_H_ -#define _GENERATOR_4_H_ - -#include - -namespace ModelLib -{ - template class BaseBus; -} - -namespace ModelLib -{ - /*! - * @brief Implementation of a fourth order generator model. - * - */ - template - class Generator4 : public ModelEvaluatorImpl - { - 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 ModelEvaluatorImpl::param_up_; - using ModelEvaluatorImpl::param_lo_; - - typedef typename ModelEvaluatorImpl::real_type real_type; - typedef BaseBus bus_type; - - public: - Generator4(BaseBus* bus, ScalarT P0 = 1.0, ScalarT Q0 = 0.0); - virtual ~Generator4(); - - int allocate(); - int initialize(); - int tagDifferentiable(); - int evaluateResidual(); - int evaluateJacobian(); - int evaluateIntegrand(); - - int initializeAdjoint(); - int evaluateAdjointResidual(); - //int evaluateAdjointJacobian(); - int evaluateAdjointIntegrand(); - - void updateTime(real_type t, real_type a) - { - time_ = t; - alpha_ = a; - } - - // Inline accesor functions - ScalarT& V() - { - return bus_->V(); - } - - const ScalarT& V() const - { - return bus_->V(); - } - - ScalarT& theta() - { - return bus_->theta(); - } - - const ScalarT& theta() const - { - return bus_->theta(); - } - - ScalarT& P() - { - return bus_->P(); - } - - const ScalarT& P() const - { - return bus_->P(); - } - - ScalarT& Q() - { - return bus_->Q(); - } - - const ScalarT& Q() const - { - return bus_->Q(); - } - - - private: - const ScalarT& Pm() const - { - return param_[0]; - } - - const ScalarT& Ef() const - { - return param_[1]; - } - - ScalarT Pg(); - ScalarT Qg(); - ScalarT frequencyPenalty(ScalarT omega); - ScalarT frequencyPenaltyDer(ScalarT omega); - - private: - // - // Private inlined accessor methods - // - - const ScalarT dotDelta() const - { - return yp_[0]; - } - - const ScalarT dotOmega() const - { - return yp_[1]; - } - - const ScalarT dotEdp() const - { - return yp_[2]; - } - - const ScalarT dotEqp() const - { - return yp_[3]; - } - - const ScalarT delta() const - { - return y_[0]; - } - - const ScalarT omega() const - { - return y_[1]; - } - - const ScalarT Edp() const - { - return y_[2]; - } - - const ScalarT Eqp() const - { - return y_[3]; - } - - const ScalarT Id() const - { - return y_[4]; - } - - const ScalarT Iq() const - { - return y_[5]; - } - - private: - real_type H_; ///< Inertia constant [s] - real_type D_; ///< Damping constant [pu] - real_type Xq_; ///< q-axis synchronous reactance [pu] - real_type Xd_; ///< d-axis synchronous reactance [pu] - real_type Xqp_; ///< q-axis transient reactance [pu] - real_type Xdp_; ///< d-axis transient reactance [pu] - real_type Rs_; ///< stator armature resistance [pu] - real_type Tq0p_; ///< q-axis open circuit transient time constant [s] - real_type Td0p_; ///< d-axis open circuit transient time constant [s] - real_type Ef_; - real_type Pm_; - real_type omega_s_; - real_type omega_b_; - real_type omega_up_; - real_type omega_lo_; - real_type c_; - real_type beta_; - - ScalarT P0_; - ScalarT Q0_; - - bus_type* bus_; - }; - -} // namespace ModelLib - - -#endif // _GENERATOR_4_H_ diff --git a/ComponentLib/Generator4Governor/CMakeLists.txt b/ComponentLib/Generator4Governor/CMakeLists.txt deleted file mode 100644 index 24e2d9d21..000000000 --- a/ComponentLib/Generator4Governor/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# -# 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 -#]] - -gridkit_add_library(generator4governor - SOURCES - Generator4Governor.cpp - OUTPUT_NAME - gridkit_generator4governor) - diff --git a/ComponentLib/Generator4Governor/Generator4Governor.cpp b/ComponentLib/Generator4Governor/Generator4Governor.cpp deleted file mode 100644 index 0bd2fc1fb..000000000 --- a/ComponentLib/Generator4Governor/Generator4Governor.cpp +++ /dev/null @@ -1,504 +0,0 @@ -/* - * - * 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. - * - */ - - -#include -#include -#include "Generator4Governor.hpp" -#include "ComponentLib/Bus/BaseBus.hpp" - -namespace ModelLib { - - -/*! - * @brief Constructor for a model of generator with governor - * - * Arguments passed to ModelEvaluatorImpl: - * - Number of equations = 6 differential + 3 algebraic = 9 - * - Number of quadratures = 1 - * - Number of optimization parameters = 2 - * - */ -template -Generator4Governor::Generator4Governor(bus_type* bus, ScalarT P0, ScalarT Q0) - : ModelEvaluatorImpl(9, 1, 2), - H_(5.0), - D_(0.04), - Xq_(0.85), - Xd_(1.05), - Xqp_(0.35), - Xdp_(0.35), - Rs_(0.01), - Tq0p_(1.0), // [s] - Td0p_(8.0), // [s] - Ef0_(1.45), - Pm0_(1.0), - deltaPm_(0.5), // 0.5 - deltaPn_(1.0), // 1.0 - omega_s_(1.0), - omega_b_(2.0*60.0*M_PI), // [rad/s] - omega_up_(omega_s_ + 0.0001), - omega_lo_(omega_s_ - 0.0001), - c_(10000.0), - beta_(2), - T1_(0.1), - T2_(0.15), - T3_(0.05), - K_(16.67), - offsetGen_(0), - offsetGov_(6), - P0_(P0), - Q0_(Q0), - bus_(bus) -{ -} - - -template -Generator4Governor::~Generator4Governor() -{ - //std::cout << "Destroy Gen2..." << std::endl; -} - -/*! - * @brief allocate method computes sparsity pattern of the Jacobian. - */ -template -int Generator4Governor::allocate() -{ - //std::cout << "Allocate Gen2..." << std::endl; - tag_.resize(size_); - - return 0; -} - -/** - * @brief Initialization of the generator model - * - * Initialization equations are derived from example 9.2 in Power System - * Modeling and Scripting, Federico Milano, Chapter 9, p. 225: - * \f{eqnarray*}{ - * \omega_0 &=& 0, \\ - * \delta_0 &=& \tan^{-1} \left(\frac{X_q P_0 - R_s Q_0}{V_0^2 + R_s P_0 + X_q Q_0} \right) + \theta_0, \\ - * \phi_0 &=& \delta_0 - \theta_0 + \tan^{-1} \left( \frac{Q_0}{P_0} \right), \\ - * I_{d0} &=& \frac{\sqrt{P_0^2 + Q_0^2}}{V_0} \sin(\phi_0), \\ - * I_{q0} &=& \frac{\sqrt{P_0^2 + Q_0^2}}{V_0} \cos(\phi_0), \\ - * E_{d0}' &=& V_0 \sin(\delta_0 - \theta_0) + R_s I_{d0} - X_q' I_{q0}, \\ - * E_{q0}' &=& V_0 \cos(\delta_0 - \theta_0) + R_s I_{q0} + X_d' I_{d0} - * \f} - * - * The input from exciter and governor is set to the steady state value: - * \f{eqnarray*}{ - * E_{f0} &=& E_{q0}' + (X_d - X_d') I_{d0}, \\ - * P_{m0} &=& E_{d0}' I_{d0} + E_{q0}' I_{q0} + ( X_q' - X_d') I_{d0} I_{q0} - * \f} - * - */ -template -int Generator4Governor::initialize() -{ - // std::cout << "Initialize Generator4Governor..." << std::endl; - - // Compute generator voltage phase - const ScalarT delta = atan((Xq_*P0_ - Rs_*Q0_) / (V()*V() + Rs_*P0_ + Xq_*Q0_)) + theta(); - - // Compute generator current phase - const ScalarT phi = delta - theta() + atan(Q0_/P0_); - - // Compute generator currents and potentials in d-q frame - const ScalarT Id = std::sqrt(P0_*P0_ + Q0_*Q0_)/V() * sin(phi); - const ScalarT Iq = std::sqrt(P0_*P0_ + Q0_*Q0_)/V() * cos(phi); - const ScalarT Edp = V()*sin(delta - theta()) + Rs_*Id - Xqp_*Iq; - const ScalarT Eqp = V()*cos(delta - theta()) + Rs_*Iq + Xdp_*Id; - - // Initialize generator - y_[offsetGen_ + 0] = delta; - y_[offsetGen_ + 1] = omega_s_ + 0.2; // <~ this is hack to perturb omega - y_[offsetGen_ + 2] = Edp; - y_[offsetGen_ + 3] = Eqp; - y_[offsetGen_ + 4] = Id; - y_[offsetGen_ + 5] = Iq; - yp_[offsetGen_ + 0] = 0.0; - yp_[offsetGen_ + 1] = 0.0; - yp_[offsetGen_ + 2] = 0.0; - yp_[offsetGen_ + 3] = 0.0; - yp_[offsetGen_ + 4] = 0.0; - yp_[offsetGen_ + 5] = 0.0; - - Pm0_ = Edp*Id + Eqp*Iq + (Xqp_ - Xdp_)*Id*Iq; // <~ set to steady state value - Ef0_ = Eqp + (Xd_ - Xdp_)*Id; // <~ set to steady state value - - // Initialize governor - y_[offsetGov_ + 0] = Pm0_; - y_[offsetGov_ + 1] = 0.0; - y_[offsetGov_ + 2] = 0.0; - yp_[offsetGov_ + 0] = 0.0; - yp_[offsetGov_ + 1] = 0.0; - yp_[offsetGov_ + 2] = 0.0; - - param_[1] = K_; - param_up_[1] = 20.0; - param_lo_[1] = 0.0; - - param_[0] = T2_; - param_up_[0] = 5.5; - param_lo_[0] = 0.1; - - return 0; -} - -/** - * \brief Identify differential variables. - */ -template -int Generator4Governor::tagDifferentiable() -{ - //std::cout << "size of tag vector is " << tag_.size() << "\n"; - tag_[offsetGen_ + 0] = true; - tag_[offsetGen_ + 1] = true; - tag_[offsetGen_ + 2] = true; - tag_[offsetGen_ + 3] = true; - tag_[offsetGen_ + 4] = false; - tag_[offsetGen_ + 5] = false; - - tag_[offsetGov_ + 0] = true; - tag_[offsetGov_ + 1] = true; - tag_[offsetGov_ + 2] = false; - - return 0; -} - -/** - * @brief Computes residual vector for the generator model. - * - * Residual equations are given as: - * \f{eqnarray*}{ - * f_0: &~& \dot{\delta} -\omega_b (\omega - \omega_s), \\ - * f_1: &~& 2H/\omega_s \dot{\omega} - L_m(P_m) + E_q' I_q + E_d' I_d + (X_q' - X_d')I_d I_q + D (\omega - \omega_s), \\ - * f_2: &~& T_{q0}' \dot{E}_d' + E_d' - (X_q - X_q')I_q, \\ - * f_3: &~& T_{d0}' \dot{E}_q' + E_q' + (X_d - X_d')I_d - E_f, \\ - * f_4: &~& R_s I_d - X_q' I_q + V \sin(\delta - \theta) - E_d', \\ - * f_5: &~& R_s I_q + X_d' I_d + V \cos(\delta - \theta) - E_q', \\ - * f_6: &~& \dot{P}_m - L_n(P_n), \\ - * f_7: &~& T_1 \dot{X} + X - (1 - T_2 / T_1) (\omega - \omega_s), \\ - * f_8: &~& T_3 P_n - P_{m0} + L_m(P_m) + K X + K T_2 / T_1 (\omega - \omega_s) - * \f} - * where \f$ \Omega_b \f$ is the synchronous frequency in [rad/s], and - * overdot denotes time derivative. - * \f$ \omega \f$ is machine frequency in [p.u.]. - * \f$ L_m() \f$ and \f$ L_n() \f$ are limiter functions, their derivatives will be - * denoted as \f$ dL_m() \f$ and \f$ dL_n() \f$ - * - * Generator injection active and reactive power are - * \f{eqnarray*}{ - * P_g &=& E_d' I_d + E_q' I_q + (X_q' - X_d') I_d I_q - R_s (I_d^2 + I_q^2), \\ - * Q_g &=& E_q' I_d - E_d' I_q - X_q' I_q^2 - X_d' I_d^2, \\ - * \f} - * respectively. - * - * State variables for the generator are: - * \f$ y_0 = \omega \f$, \f$ y_1 = \delta \f$, \f$ y_2 = E_d' \f$, \f$ y_3 = E_q' \f$, - * \f$ y_4 = I_d \f$, \f$ y_5 = I_q \f$, - * \f$ y_6 = P_m \f$, \f$ y_7 = X \f$, \f$ y_{8} = P_n \f$ - * Bus voltage \f$ V \f$ and bus phase \f$ \theta \f$ are bus state variable. - * - */ - -template -int Generator4Governor::evaluateResidual() -{ - // Generator equations - f_[offsetGen_ + 0] = dotDelta() - omega_b_*(omega() - omega_s_); - f_[offsetGen_ + 1] = (2.0*H_)/omega_s_*dotOmega() - Lm(y_[offsetGov_ + 0]) + Eqp()*Iq() + Edp()*Id() + (- Xdp_ + Xqp_)*Id()*Iq() + D_*(omega() - omega_s_); - f_[offsetGen_ + 2] = Tq0p_*dotEdp() + Edp() - (Xq_ - Xqp_)*Iq(); - f_[offsetGen_ + 3] = Td0p_*dotEqp() + Eqp() + (Xd_ - Xdp_)*Id() - Ef0_; - f_[offsetGen_ + 4] = Rs_*Id() - Xqp_*Iq() + V()*sin(delta() - theta()) - Edp(); - f_[offsetGen_ + 5] = Xdp_*Id() + Rs_*Iq() + V()*cos(delta() - theta()) - Eqp(); - - // Bus equations - P() += Pg(); - Q() += Qg(); - - // Governor equations - f_[offsetGov_ + 0] = yp_[offsetGov_ + 0] - Ln(y_[offsetGov_ + 2]); - f_[offsetGov_ + 1] = T1()*yp_[offsetGov_ + 1] + y_[offsetGov_ + 1] - (1.0 - T2()/T1())*(omega() - omega_s_); - f_[offsetGov_ + 2] = T3()*y_[offsetGov_ + 2] - Pm0_ + Lm(y_[offsetGov_ + 0]) + K()*y_[offsetGov_ + 1] + K()*T2()/T1()*(omega() - omega_s_); - - return 0; -} - -/* - * @brief Jacobian for the order 4 generator model (not implemented yet). - * - * - */ -template -int Generator4Governor::evaluateJacobian() -{ - std::cout << "Evaluate Jacobian for Gen2..." << std::endl; - std::cout << "Jacobian evaluation not implemented!" << std::endl; - return 0; -} - -template -int Generator4Governor::evaluateIntegrand() -{ - // std::cout << "Evaluate Integrand for Gen2..." << std::endl; - g_[0] = frequencyPenalty(omega()); - return 0; -} - -template -int Generator4Governor::initializeAdjoint() -{ - //std::cout << "Initialize adjoint for Generator4Governor..." << std::endl; - for (IdxT i=0; i -int Generator4Governor::evaluateAdjointResidual() -{ - // std::cout << "Evaluate adjoint residual for Gen2..." << std::endl; - ScalarT sinPhi = sin(delta() - theta()); - ScalarT cosPhi = cos(delta() - theta()); - - // Generator adjoint - fB_[offsetGen_ + 0] = ypB_[offsetGen_ + 0] - yB_[offsetGen_ + 4]*V()*cosPhi + yB_[offsetGen_ + 5]*V()*sinPhi; - fB_[offsetGen_ + 1] = 2.0*H_/omega_s_*ypB_[offsetGen_ + 1] + yB_[offsetGen_ + 0]*omega_b_ - yB_[offsetGen_ + 1]*D_ + frequencyPenaltyDer(omega()) - + yB_[offsetGov_ + 1]*(1.0 - T2()/T1()) - yB_[offsetGov_ + 2]*K()*T2()/T1(); - fB_[offsetGen_ + 2] = Tq0p_*ypB_[offsetGen_ + 2] - yB_[offsetGen_ + 1]*Id() - yB_[offsetGen_ + 2] + yB_[offsetGen_ + 4] - + lambdaP()*Id() - lambdaQ()*Iq(); - fB_[offsetGen_ + 3] = Td0p_*ypB_[offsetGen_ + 3] - yB_[offsetGen_ + 1]*Iq() - yB_[offsetGen_ + 3] + yB_[offsetGen_ + 5] - + lambdaP()*Iq() + lambdaQ()*Id(); - fB_[offsetGen_ + 4] = -yB_[offsetGen_ + 1]*(Edp() + (Xqp_ - Xdp_)*Iq()) - yB_[offsetGen_ + 3]*(Xd_ - Xdp_) - yB_[offsetGen_ + 4]*Rs_ - yB_[offsetGen_ + 5]*Xdp_ - + lambdaP()*(Edp() + (Xqp_ - Xdp_)*Iq() - 2.0*Rs_*Id()) + lambdaQ()*(Eqp() - 2.0*Xdp_*Id()); - fB_[offsetGen_ + 5] = -yB_[offsetGen_ + 1]*(Eqp() + (Xqp_ - Xdp_)*Id()) + yB_[offsetGen_ + 2]*(Xq_ - Xqp_) + yB_[offsetGen_ + 4]*Xqp_ - yB_[offsetGen_ + 5]*Rs_ - + lambdaP()*(Eqp() + (Xqp_ -Xdp_)*Id() - 2.0*Rs_*Iq()) - lambdaQ()*(Edp() + 2.0*Xqp_*Iq()); - - // Bus adjoint - PB() += (-yB_[offsetGen_ + 4]*sinPhi - yB_[offsetGen_ + 5]*cosPhi); - QB() += ( yB_[offsetGen_ + 4]*V()*cosPhi - yB_[offsetGen_ + 5]*V()*sinPhi); - - // Governor adjoint - fB_[offsetGov_ + 0] = ypB_[offsetGov_ + 0] - yB_[offsetGov_ + 2]*dLm(y_[offsetGov_ + 0]) + yB_[offsetGen_ + 1]*dLm(y_[offsetGov_ + 0]); - fB_[offsetGov_ + 1] = ypB_[offsetGov_ + 1]*T1() - yB_[offsetGov_ + 1] - yB_[offsetGov_ + 2]*K(); - fB_[offsetGov_ + 2] = yB_[offsetGov_ + 0]*dLn(y_[offsetGov_ + 2]) - yB_[offsetGov_ + 2]*T3(); - - return 0; -} - -// template -// int Generator4Governor::evaluateAdjointJacobian() -// { -// std::cout << "Evaluate adjoint Jacobian for Gen2..." << std::endl; -// std::cout << "Adjoint Jacobian evaluation not implemented!" << std::endl; -// return 0; -// } - -template -int Generator4Governor::evaluateAdjointIntegrand() -{ - // std::cout << "Evaluate adjoint Integrand for Gen2..." << std::endl; - - // K adjoint - gB_[1] = -yB_[offsetGov_ + 2]*(y_[offsetGov_ + 1] + T2()/T1()*(omega() - omega_s_)); - - // T2 adjoint - gB_[0] = -yB_[offsetGov_ + 1]*(omega() - omega_s_)/T1() - yB_[offsetGov_ + 2]*K()/T1()*(omega() - omega_s_); - - return 0; -} - - - - - -// -// Private functions -// - -/** - * Generator active power Pg. - * - * \f[ P_g = E_q' I_q + E_d' I_d + (X_q' - X_d') I_q I_d - R_a (I_d^2 + I_q^2) \f] - * - */ -template -ScalarT Generator4Governor::Pg() -{ - return Iq()*Eqp() + Id()*Edp() + (Xqp_ - Xdp_)*Id()*Iq() - Rs_*(Id()*Id() + Iq()*Iq()); -} - -/** - * Generator reactive power Qg. - * - * \f[ Q_g = E_q' I_d - E_d' I_q - X_d' I_d^2 - X_q' I_q^2 \f] - */ -template -ScalarT Generator4Governor::Qg() -{ - return -Iq()*Edp() + Id()*Eqp() - Xdp_*Id()*Id() - Xqp_*Iq()*Iq(); -} - -/** - * Frequency penalty is used as the objective function for the generator model. - * - * @todo Use smooth penalty function! - * - */ -template -ScalarT Generator4Governor::frequencyPenalty(ScalarT omega) -{ - return c_ * pow(std::max(0.0, std::max(omega - omega_up_, omega_lo_ - omega)), beta_); -} - -/** - * Derivative of frequency penalty cannot be written in terms of min/max functions. - * Need to expand conditional statements instead. - * - * @todo Use smooth penalty function! - * - */ -template -ScalarT Generator4Governor::frequencyPenaltyDer(ScalarT omega) -{ - if (omega > omega_up_) - { - return beta_ * c_ * pow(omega - omega_up_, beta_ - 1.0); - } - else if (omega < omega_lo_) - { - return beta_ * c_ * pow(omega - omega_lo_, beta_ - 1.0); - } - else - { - return 0.0; - } -} - - -template -ScalarT Generator4Governor::Lm(ScalarT Pm) -{ - return Pm0_ + deltaPm_*std::tanh(Pm); -} - -template -ScalarT Generator4Governor::dLm(ScalarT Pm) -{ - return deltaPm_/(std::cosh(Pm) * std::cosh(Pm)); -} - - -template -ScalarT Generator4Governor::Ln(ScalarT Pn) -{ - return deltaPn_*std::tanh(Pn); -} - -template -ScalarT Generator4Governor::dLn(ScalarT Pn) -{ - return deltaPn_/(std::cosh(Pn) * std::cosh(Pn)); -} - - - - - -// Available template instantiations -template class Generator4Governor; -template class Generator4Governor; - - -} // namespace ModelLib diff --git a/ComponentLib/Generator4Governor/Generator4Governor.hpp b/ComponentLib/Generator4Governor/Generator4Governor.hpp deleted file mode 100644 index c8fd2c424..000000000 --- a/ComponentLib/Generator4Governor/Generator4Governor.hpp +++ /dev/null @@ -1,325 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _GENERATOR_4_GOVERNOR_B_HPP_ -#define _GENERATOR_4_GOVERNOR_B_HPP_ - -#include - -namespace ModelLib -{ - template class BaseBus; -} - -namespace ModelLib -{ - /*! - * @brief Implementation of a fourth order generator model with - * a simple governor. - * - */ - template - class Generator4Governor : public ModelEvaluatorImpl - { - 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 ModelEvaluatorImpl::param_up_; - using ModelEvaluatorImpl::param_lo_; - - public: - typedef typename ModelEvaluatorImpl::real_type real_type; - typedef BaseBus bus_type; - - Generator4Governor(bus_type* bus, ScalarT P0, ScalarT Q0); - virtual ~Generator4Governor(); - - int allocate(); - int initialize(); - int tagDifferentiable(); - int evaluateResidual(); - int evaluateJacobian(); - int evaluateIntegrand(); - - int initializeAdjoint(); - int evaluateAdjointResidual(); - //int evaluateAdjointJacobian(); - int evaluateAdjointIntegrand(); - - void updateTime(real_type t, real_type a) - { - time_ = t; - alpha_ = a; - } - - private: - // - // Private model methods - // - - ScalarT Pg(); - ScalarT Qg(); - - inline ScalarT frequencyPenalty(ScalarT omega); - inline ScalarT frequencyPenaltyDer(ScalarT omega); - - inline ScalarT Lm(ScalarT Pm); - inline ScalarT dLm(ScalarT Pm); - - inline ScalarT Ln(ScalarT Pn); - inline ScalarT dLn(ScalarT Pn); - - - public: - // - // Public inline accesor functions - // - - ScalarT& V() - { - return bus_->V(); - } - - const ScalarT& V() const - { - return bus_->V(); - } - - ScalarT& theta() - { - return bus_->theta(); - } - - const ScalarT& theta() const - { - return bus_->theta(); - } - - ScalarT& P() - { - return bus_->P(); - } - - const ScalarT& P() const - { - return bus_->P(); - } - - ScalarT& Q() - { - return bus_->Q(); - } - - const ScalarT& Q() const - { - return bus_->Q(); - } - - const ScalarT& lambdaP() const - { - return bus_->lambdaP(); - } - - const ScalarT& lambdaQ() const - { - return bus_->lambdaQ(); - } - - ScalarT& PB() - { - return bus_->PB(); - } - - ScalarT& QB() - { - return bus_->QB(); - } - - - private: - // - // Private inlined accessor methods - // - - const ScalarT dotDelta() const - { - return yp_[offsetGen_ + 0]; - } - - const ScalarT dotOmega() const - { - return yp_[offsetGen_ + 1]; - } - - const ScalarT dotEdp() const - { - return yp_[offsetGen_ + 2]; - } - - const ScalarT dotEqp() const - { - return yp_[offsetGen_ + 3]; - } - - const ScalarT delta() const - { - return y_[offsetGen_ + 0]; - } - - const ScalarT omega() const - { - return y_[offsetGen_ + 1]; - } - - const ScalarT Edp() const - { - return y_[offsetGen_ + 2]; - } - - const ScalarT Eqp() const - { - return y_[offsetGen_ + 3]; - } - - const ScalarT Id() const - { - return y_[offsetGen_ + 4]; - } - - const ScalarT Iq() const - { - return y_[offsetGen_ + 5]; - } - - const ScalarT K() const - { - return param_[1]; - } - - const ScalarT T1() const - { - return T1_; - } - - const ScalarT T2() const - { - return param_[0]; - } - - const ScalarT T3() const - { - return T3_; - } - - - private: - // Generator parameters - real_type H_; - real_type D_; - real_type Xq_; - real_type Xd_; - real_type Xqp_; - real_type Xdp_; - real_type Rs_; - real_type Tq0p_; - real_type Td0p_; - real_type Ef0_; - real_type Pm0_; - real_type deltaPm_; - real_type deltaPn_; - real_type omega_s_; - real_type omega_b_; - real_type omega_up_; - real_type omega_lo_; - real_type c_; - real_type beta_; - - // Governor parameters - real_type T1_; - real_type T2_; - real_type T3_; - real_type K_; - - // Index offsets - const IdxT offsetGen_; - const IdxT offsetGov_; - - // Initial power flow values - ScalarT P0_; - ScalarT Q0_; - - // Bus to which the generator is connected - bus_type* bus_; - }; - -} // namespace ModelLib - - -#endif // _GENERATOR_4_GOVERNOR_B_HPP_ diff --git a/ComponentLib/Generator4Param/CMakeLists.txt b/ComponentLib/Generator4Param/CMakeLists.txt deleted file mode 100644 index 457ebc407..000000000 --- a/ComponentLib/Generator4Param/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# -# 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 -#]] - -gridkit_add_library(generator4param - SOURCES - Generator4Param.cpp - OUTPUT_NAME - gridkit_generator4param) - diff --git a/ComponentLib/Generator4Param/Generator4Param.cpp b/ComponentLib/Generator4Param/Generator4Param.cpp deleted file mode 100644 index 36e3c193c..000000000 --- a/ComponentLib/Generator4Param/Generator4Param.cpp +++ /dev/null @@ -1,475 +0,0 @@ -/* - * - * 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 -#include -#include "Generator4Param.hpp" - -namespace ModelLib { - -/*! - * @brief Constructor for a simple generator model - * - * Arguments passed to ModelEvaluatorImpl: - * - Number of equations = 4 differential + 2 algebraic = 6 - * - Number of quadratures = 1 - * - Number of optimization parameters = 1 - */ -template -Generator4Param::Generator4Param(bus_type* bus, ScalarT P0, ScalarT Q0) - : ModelEvaluatorImpl(6, 1, 1), - H_(5.0), - D_(0.04), - Xq_(0.85), - Xd_(1.05), - Xqp_(0.35), - Xdp_(0.35), - Rs_(0.01), - Tq0p_(1.0), // [s] - Td0p_(8.0), // [s] - Ef_(1.45), - Pm_(1.0), - omega_s_(1.0), - omega_b_(2.0*60.0*M_PI), - P0_(P0), - Q0_(Q0), - bus_(bus) -{ -} - -template -Generator4Param::~Generator4Param() -{ -} - -/*! - * @brief This function will be used to allocate sparse Jacobian matrices. - * - */ -template -int Generator4Param::allocate() -{ - //std::cout << "Allocate Generator4Param..." << std::endl; - tag_.resize(size_); - - return 0; -} - -/** - * @brief Initialization of the generator model - * - * Initialization equations are derived from example 9.2 in Power System - * Modeling and Scripting, Federico Milano, Chapter 9, p. 225: - * \f{eqnarray*}{ - * &~& \omega_0 = 0, \\ - * &~& \delta_0 = \tan^{-1} \left(\frac{X_q P_0 - R_s Q_0}{V_0^2 + R_s P_0 + X_q Q_0} \right) + \theta_0, \\ - * &~& \phi_0 = \delta_0 - \theta_0 + \tan^{-1} \left( \frac{Q_0}{P_0} \right), \\ - * &~& I_{d0} = \frac{\sqrt{P_0^2 + Q_0^2}}{V_0} \sin(\phi_0), \\ - * &~& I_{q0} = \frac{\sqrt{P_0^2 + Q_0^2}}{V_0} \cos(\phi_0), \\ - * &~& E_{d0}' = V_0 \sin(\delta_0 - \theta_0) + R_s I_{d0} - X_q' I_{q0}, \\ - * &~& E_{q0}' = V_0 \cos(\delta_0 - \theta_0) + R_s I_{q0} + X_d' I_{d0} - * \f} - * - * The input from exciter and governor is set to the steady state value: - * \f{eqnarray*}{ - * &~& E_{f0} = E_{q0}' + (X_d - X_d') I_{d0}, \\ - * &~& P_{m0} = E_{d0}' I_{d0} + E_{q0}' I_{q0} + ( X_q' - X_d') I_{d0} I_{q0} - * \f} - * - */ -template -int Generator4Param::initialize() -{ - // std::cout << "Initialize Generator4Param..." << std::endl; - - // Compute initial guess for the generator voltage phase - const ScalarT delta = atan((Xq_*P0_ - Rs_*Q0_) / (V()*V() + Rs_*P0_ + Xq_*Q0_)) + theta(); - - // Compute initial guess for the generator current phase - const ScalarT phi = theta() - delta - atan(Q0_/P0_); - - // Compute initial gueses for generator currents and potentials in d-q frame - const ScalarT Id = std::sqrt(P0_*P0_ + Q0_*Q0_)/V() * sin(phi); - const ScalarT Iq = std::sqrt(P0_*P0_ + Q0_*Q0_)/V() * cos(phi); - const ScalarT Ed = V()*sin(theta() - delta) + Rs_*Id + Xqp_*Iq; - const ScalarT Eq = V()*cos(theta() - delta) + Rs_*Iq - Xdp_*Id; - - y_[0] = delta; - y_[1] = omega_s_; - y_[2] = Ed; - y_[3] = Eq; - y_[4] = Id; - y_[5] = Iq; - yp_[0] = 0.0; - yp_[1] = 0.0; - yp_[2] = 0.0; - yp_[3] = 0.0; - yp_[4] = 0.0; - yp_[5] = 0.0; - - // Set control parameter values here. - Ef_ = Eq - (Xd_ - Xdp_)*Id; // <~ set to steady state value - Pm_ = Ed*Id + Eq*Iq + (Xdp_ - Xqp_)*Id*Iq; // <~ set to steady state value - - // Initialize optimization parameters - param_[0] = H_; - param_up_[0] = 10.0; - param_lo_[0] = 2.0; - - // param_[0] = Pm_; - // param_up_[0] = 1.5; - // param_lo_[0] = 0.0; - - // param_[1] = Ef_; - // param_up_[1] = 1.7; - // param_lo_[1] = 0.0; - - return 0; -} - -/** - * \brief Identify differential variables. - */ -template -int Generator4Param::tagDifferentiable() -{ - tag_[0] = true; - tag_[1] = true; - tag_[2] = true; - tag_[3] = true; - - for (IdxT i=4; i < size_; ++i) - { - tag_[i] = false; - } - - return 0; -} - -/** - * @brief Computes residual vector for the generator model. - * - * Residual equations are given per model in Power System Modeling and - * Scripting, Federico Milano, Chapter 15, p. 334: - * \f{eqnarray*}{ - * f_0: &~& \dot{\delta} -\omega_b (\omega - \omega_s), \\ - * f_1: &~& 2H/\omega_s \dot{\omega} - L_m(P_m) + E_q' I_q + E_d' I_d + (X_q' - X_d')I_d I_q + D (\omega - \omega_s), \\ - * f_2: &~& T_{q0}' \dot{E}_d' + E_d' - (X_q - X_q')I_q, \\ - * f_3: &~& T_{d0}' \dot{E}_q' + E_q' + (X_d - X_d')I_d - E_f, \\ - * f_4: &~& R_s I_d - X_q' I_q + V \sin(\delta - \theta) - E_d', \\ - * f_5: &~& R_s I_q + X_d' I_d + V \cos(\delta - \theta) - E_q', - * \f} - * where \f$ \Omega_b \f$ is the synchronous frequency in [rad/s], and - * overdot denotes time derivative. - * - * Generator injection active and reactive power are - * \f{eqnarray*}{ - * P_g &=& E_d' I_d + E_q' I_q + (X_q' - X_d') I_d I_q - R_s (I_d^2 + I_q^2), \\ - * Q_q &=& E_q' I_d - E_d' I_q - X_q' I_q^2 - X_d' I_d^2, \\ - * \f} - * respectively. - * - * State variables are: - * \f$ y_0 = \omega \f$, \f$ y_1 = \delta \f$, \f$ y_2 = E_d' \f$, \f$ y_3 = E_q' \f$, - * \f$ y_4 = I_d \f$, \f$ y_5 = I_q \f$. - * - */ -template -int Generator4Param::evaluateResidual() -{ - // std::cout << "Evaluate residual for Generator4Param..." << std::endl; - f_[0] = dotDelta() - omega_b_* (omega() - omega_s_); - f_[1] = (2.0*H())/omega_s_*dotOmega() - Pm() + Eqp()*Iq() + Edp()*Id() + (- Xdp_ + Xqp_)*Id()*Iq() + D_*(omega() - omega_s_); - f_[2] = Tq0p_*dotEdp() + Edp() - (Xq_ - Xqp_)*Iq(); - f_[3] = Td0p_*dotEqp() + Eqp() + (Xd_ - Xdp_)*Id() - Ef(); - f_[4] = Rs_*Id() - Xqp_*Iq() + V()*sin(delta() - theta()) - Edp(); - f_[5] = Xdp_*Id() + Rs_*Iq() + V()*cos(delta() - theta()) - Eqp(); - - // Compute active and reactive load provided by the infinite bus. - P() += Pg(); - Q() += Qg(); - - //std::cout << "Residual: t = " << time_ << std::endl; - - return 0; -} - -template -int Generator4Param::evaluateJacobian() -{ - std::cerr << "Evaluate Jacobian for Generator4Param..." << std::endl; - std::cerr << "Jacobian evaluation not implemented!" << std::endl; - return 0; -} - -template -int Generator4Param::evaluateIntegrand() -{ - // std::cout << "Evaluate Integrand for Generator4Param..." << std::endl; - g_[0] = trajectoryPenalty(time_); - return 0; -} - -template -int Generator4Param::initializeAdjoint() -{ - //std::cout << "Initialize adjoint for Generator4Param..." << std::endl; - for (IdxT i=0; i -int Generator4Param::evaluateAdjointResidual() -{ - // std::cout << "Evaluate adjoint residual for Generator4Param..." << std::endl; - ScalarT sinPhi = sin(delta() - theta()); - ScalarT cosPhi = cos(delta() - theta()); - - // Generator adjoint - fB_[0] = ypB_[0] - yB_[4]*V()*cosPhi + yB_[5]*V()*sinPhi; - fB_[1] = 2.0*H()/omega_s_*ypB_[1] + yB_[0]*omega_b_ - yB_[1]*D_; //+ frequencyPenaltyDer(omega()); - fB_[2] = Tq0p_*ypB_[2] - yB_[1]*Id() - yB_[2] + yB_[4] + trajectoryPenaltyDerEdp(time_); - fB_[3] = Td0p_*ypB_[3] - yB_[1]*Iq() - yB_[3] + yB_[5] + trajectoryPenaltyDerEqp(time_); - fB_[4] = -yB_[1]*(Edp() + (Xqp_ - Xdp_)*Iq()) - yB_[3]*(Xd_ - Xdp_) - yB_[4]*Rs_ - yB_[5]*Xdp_; - fB_[5] = -yB_[1]*(Eqp() + (Xqp_ - Xdp_)*Id()) + yB_[2]*(Xq_ - Xqp_) + yB_[4]*Xqp_ - yB_[5]*Rs_; - - return 0; -} - -// template -// int Generator4Param::evaluateAdjointJacobian() -// { -// std::cout << "Evaluate adjoint Jacobian for Generator4Param..." << std::endl; -// std::cout << "Adjoint Jacobian evaluation not implemented!" << std::endl; -// return 0; -// } - -template -int Generator4Param::evaluateAdjointIntegrand() -{ - // std::cout << "Evaluate adjoint Integrand for Generator4Param..." << std::endl; - gB_[0] = -2.0*yB_[1]*dotOmega()/omega_s_; - - return 0; -} - - -// -// Private functions -// - -/** - * Generator active power Pg. - * - * \f[ P_g = E_q' I_q + E_d' I_d + (X_q' - X_d') I_q I_d - R_a (I_d^2 + I_q^2) \f] - * - */ -template -ScalarT Generator4Param::Pg() -{ - return y_[5]*V()*cos(theta() - y_[0]) + y_[4]*V()*sin(theta() - y_[0]); -} - -/** - * Generator reactive power Qg. - * - * \f[ Q_g = E_q' I_d - E_d' I_q - X_d' I_d^2 - X_q' I_q^2 \f] - */ -template -ScalarT Generator4Param::Qg() -{ - return y_[5]*V()*sin(theta() - y_[0]) - y_[4]*V()*cos(theta() - y_[0]); -} - -/** - * @brief Difference between computed system state and look-up table value. - * - * @todo Look-up table should probably live outside the generator model. - */ -template -ScalarT Generator4Param::trajectoryPenalty(ScalarT t) const -{ - size_t N = table_.size(); - double ti = table_[0][0]; - double tf = table_[N-1][0]; - double dt = (tf - ti)/(N-1); - int n = std::trunc(t/tf*(N-1.0)); - - double Edp_est = 0.0; - double Eqp_est = 0.0; - - if(t >= ti && t < tf) - { - // Interpolate from look-up table - Edp_est = (table_[n+1][3] - table_[n][3])/(table_[n+1][0] - table_[n][0]) * (t - table_[n][0]) + table_[n][3]; - Eqp_est = (table_[n+1][4] - table_[n][4])/(table_[n+1][0] - table_[n][0]) * (t - table_[n][0]) + table_[n][4]; - } - else - { - if(tf <= t && t < tf + dt) - { - // Extrapolate from look-up table - Edp_est = (table_[n][3] - table_[n-1][3])/(table_[n][0] - table_[n-1][0]) * (t - table_[n-1][0]) + table_[n-1][3]; - Eqp_est = (table_[n][4] - table_[n-1][4])/(table_[n][0] - table_[n-1][0]) * (t - table_[n-1][0]) + table_[n-1][4]; - } - else - { - // Too far away to extrapolate - std::cerr << "Trajectory penalty: Out of time bounds at time " << t << "\n"; - return -1.0; - } - } - double d = (Edp() - Edp_est); - double q = (Eqp() - Eqp_est); - return (d*d + q*q); -} - -template -ScalarT Generator4Param::trajectoryPenaltyDerEdp(ScalarT t) const -{ - size_t N = table_.size(); - double ti = table_[0][0]; - double tf = table_[N-1][0]; - double dt = (tf - ti)/(N-1); - int n = std::trunc(t/tf*(N-1.0)); - double Edp_est = 0.0; - - if(t >= ti && t < tf) - { - Edp_est = (table_[n+1][3] - table_[n][3])/(table_[n+1][0] - table_[n][0]) * (t - table_[n][0]) + table_[n][3]; - } - else - { - if(tf <= t && t < tf + dt) - { - Edp_est = (table_[n][3] - table_[n-1][3])/(table_[n][0] - table_[n-1][0]) * (t - table_[n-1][0]) + table_[n-1][3]; - } - else - { - std::cerr << "Trajectory penalty: Out of time bounds at time " << t << "\n"; - return -1.0; - } - } - double d = (Edp() - Edp_est); - - return 2.0*d; -} - -template -ScalarT Generator4Param::trajectoryPenaltyDerEqp(ScalarT t) const -{ - size_t N = table_.size(); - double ti = table_[0][0]; - double tf = table_[N-1][0]; - double dt = (tf - ti)/(N-1); - int n = std::trunc(t/tf*(N-1.0)); - double Eqp_est = 0.0; - - if(t >= ti && t < tf) - { - Eqp_est = (table_[n+1][4] - table_[n][4])/(table_[n+1][0] - table_[n][0]) * (t - table_[n][0]) + table_[n][4]; - } - else - { - if(tf <= t && t < tf + dt) - { - Eqp_est = (table_[n][4] - table_[n-1][4])/(table_[n][0] - table_[n-1][0]) * (t - table_[n-1][0]) + table_[n-1][4]; - } - else - { - std::cerr << "Trajectory penalty: Out of time bounds at time " << t << "\n"; - return -1.0; - } - } - double q = (Eqp() - Eqp_est); - - return 2.0*q; -} - -template class Generator4Param; -template class Generator4Param; - - -} // namespace ModelLib - diff --git a/ComponentLib/Generator4Param/Generator4Param.hpp b/ComponentLib/Generator4Param/Generator4Param.hpp deleted file mode 100644 index ea8774b82..000000000 --- a/ComponentLib/Generator4Param/Generator4Param.hpp +++ /dev/null @@ -1,279 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _GENERATOR_4_H_ -#define _GENERATOR_4_H_ - -#include - -namespace ModelLib -{ - template class BaseBus; -} - -namespace ModelLib -{ - /*! - * @brief Implementation of a fourth order generator model. - * - */ - template - class Generator4Param : public ModelEvaluatorImpl - { - 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 ModelEvaluatorImpl::param_up_; - using ModelEvaluatorImpl::param_lo_; - - typedef typename ModelEvaluatorImpl::real_type real_type; - typedef BaseBus bus_type; - - public: - Generator4Param(BaseBus* bus, ScalarT P0 = 1.0, ScalarT Q0 = 0.0); - virtual ~Generator4Param(); - - int allocate(); - int initialize(); - int tagDifferentiable(); - int evaluateResidual(); - int evaluateJacobian(); - int evaluateIntegrand(); - - int initializeAdjoint(); - int evaluateAdjointResidual(); - //int evaluateAdjointJacobian(); - int evaluateAdjointIntegrand(); - - void updateTime(real_type t, real_type a) - { - time_ = t; - alpha_ = a; - } - - // Inline accesor functions - ScalarT& V() - { - return bus_->V(); - } - - const ScalarT& V() const - { - return bus_->V(); - } - - ScalarT& theta() - { - return bus_->theta(); - } - - const ScalarT& theta() const - { - return bus_->theta(); - } - - ScalarT& P() - { - return bus_->P(); - } - - const ScalarT& P() const - { - return bus_->P(); - } - - ScalarT& Q() - { - return bus_->Q(); - } - - const ScalarT& Q() const - { - return bus_->Q(); - } - - ScalarT trajectoryPenalty(ScalarT t) const; - ScalarT trajectoryPenaltyDerEqp(ScalarT t) const; - ScalarT trajectoryPenaltyDerEdp(ScalarT t) const; - - std::vector>& getLookupTable() - { - return table_; - } - - std::vector> const& getLookupTable() const - { - return table_; - } - - private: - const ScalarT& H() const - { - return param_[0]; - } - - const ScalarT& Pm() const - { - return Pm_; - // return param_[0]; - } - - const ScalarT& Ef() const - { - return Ef_; - // return param_[1]; - } - - ScalarT Pg(); - ScalarT Qg(); - - private: - // - // Private inlined accessor methods - // - - const ScalarT dotDelta() const - { - return yp_[0]; - } - - const ScalarT dotOmega() const - { - return yp_[1]; - } - - const ScalarT dotEdp() const - { - return yp_[2]; - } - - const ScalarT dotEqp() const - { - return yp_[3]; - } - - const ScalarT delta() const - { - return y_[0]; - } - - const ScalarT omega() const - { - return y_[1]; - } - - const ScalarT Edp() const - { - return y_[2]; - } - - const ScalarT Eqp() const - { - return y_[3]; - } - - const ScalarT Id() const - { - return y_[4]; - } - - const ScalarT Iq() const - { - return y_[5]; - } - - private: - real_type H_; ///< Inertia constant [s] - real_type D_; ///< Damping constant [pu] - real_type Xq_; ///< q-axis synchronous reactance [pu] - real_type Xd_; ///< d-axis synchronous reactance [pu] - real_type Xqp_; ///< q-axis transient reactance [pu] - real_type Xdp_; ///< d-axis transient reactance [pu] - real_type Rs_; ///< stator armature resistance [pu] - real_type Tq0p_; ///< q-axis open circuit transient time constant [s] - real_type Td0p_; ///< d-axis open circuit transient time constant [s] - real_type Ef_; - real_type Pm_; - real_type omega_s_; - real_type omega_b_; - - ScalarT P0_; - ScalarT Q0_; - - bus_type* bus_; - - /// Look-up table data. @todo This should be part of a separate model. - std::vector> table_; - }; - -} // namespace ModelLib - - -#endif // _GENERATOR_4_H_ diff --git a/ComponentLib/Generator4Param/static_data.hpp b/ComponentLib/Generator4Param/static_data.hpp deleted file mode 100644 index 88dbac519..000000000 --- a/ComponentLib/Generator4Param/static_data.hpp +++ /dev/null @@ -1,101 +0,0 @@ -{ 0, 0.092182, 0.99596, -0.17574, 0.98107, 2.7864, 0.58172}, -{ 0.05, 0.032044, 0.99785, -0.15175, 0.98425, -0.058476, 0.52344}, -{ 0.1, 0.016599, 1.0006, -0.1331, 0.98738, -0.047843, 0.42635}, -{ 0.15, 0.05483, 1.0034, -0.11578, 0.99044, -0.036909, 0.48633}, -{ 0.2, 0.14141, 1.0056, -0.096146, 0.99341, -0.0096526, 0.67712}, -{ 0.25, 0.25913, 1.0067, -0.071796, 0.99616, 0.057594, 0.93888}, -{ 0.3, 0.38426, 1.0064, -0.042151, 0.9985, 0.16989, 1.1964}, -{ 0.35, 0.49314, 1.005, -0.0084123, 1.0003, 0.30164, 1.3852}, -{ 0.4, 0.5676, 1.0028, 0.02705, 1.0015, 0.41029, 1.4705}, -{ 0.45, 0.59823, 1.0004, 0.061508, 1.0024, 0.46162, 1.4465}, -{ 0.5, 0.58551, 0.99831, 0.092489, 1.0031, 0.44697, 1.3275}, -{ 0.55, 0.53921, 0.99693, 0.11815, 1.0041, 0.3845, 1.1404}, -{ 0.6, 0.47618, 0.99657, 0.13756, 1.0054, 0.30672, 0.92541}, -{ 0.65, 0.41655, 0.99727, 0.15094, 1.0069, 0.24321, 0.7317}, -{ 0.7, 0.37865, 0.99881, 0.1597, 1.0087, 0.20996, 0.60591}, -{ 0.75, 0.37438, 1.0008, 0.16612, 1.0105, 0.21157, 0.57628}, -{ 0.8, 0.40628, 1.0026, 0.17271, 1.0123, 0.24931, 0.64279}, -{ 0.85, 0.46736, 1.0038, 0.18152, 1.0138, 0.32351, 0.77782}, -{ 0.9, 0.5435, 1.0041, 0.19359, 1.0148, 0.42737, 0.93662}, -{ 0.95, 0.61757, 1.0036, 0.20876, 1.0154, 0.54119, 1.0735}, -{ 1, 0.67388, 1.0023, 0.2259, 1.0156, 0.63599, 1.1557}, -{ 1.05, 0.70183, 1.0006, 0.24337, 1.0154, 0.68574, 1.1689}, -{ 1.1, 0.69804, 0.999, 0.25946, 1.0151, 0.67947, 1.1144}, -{ 1.15, 0.66677, 0.99778, 0.27273, 1.0149, 0.62579, 1.0057}, -{ 1.2, 0.61875, 0.99726, 0.28227, 1.015, 0.54794, 0.86636}, -{ 1.25, 0.56848, 0.99754, 0.28791, 1.0155, 0.4729, 0.72906}, -{ 1.3, 0.53046, 0.99852, 0.2903, 1.0163, 0.42123, 0.62812}, -{ 1.35, 0.51537, 0.99991, 0.29083, 1.0172, 0.40344, 0.58875}, -{ 1.4, 0.52734, 1.0013, 0.29123, 1.0181, 0.42221, 0.6178}, -{ 1.45, 0.5631, 1.0024, 0.29303, 1.0188, 0.47491, 0.70149}, -{ 1.5, 0.61328, 1.0028, 0.29718, 1.0193, 0.5526, 0.81115}, -{ 1.55, 0.66527, 1.0026, 0.30377, 1.0194, 0.63849, 0.91394}, -{ 1.6, 0.70664, 1.0017, 0.31219, 1.0191, 0.71058, 0.98342}, -{ 1.65, 0.72829, 1.0005, 0.32131, 1.0186, 0.74915, 1.0051}, -{ 1.7, 0.72648, 0.9993, 0.3299, 1.018, 0.74483, 0.97655}, -{ 1.75, 0.70346, 0.99833, 0.33682, 1.0175, 0.70235, 0.90588}, -{ 1.8, 0.66675, 0.99787, 0.34134, 1.0173, 0.63805, 0.80994}, -{ 1.85, 0.62709, 0.99802, 0.34322, 1.0173, 0.5727, 0.7123}, -{ 1.9, 0.59559, 0.99871, 0.34287, 1.0176, 0.52403, 0.6382}, -{ 1.95, 0.58072, 0.99974, 0.34122, 1.0181, 0.50266, 0.60693}, -{ 2, 0.58615, 1.0008, 0.33951, 1.0186, 0.51207, 0.62506}, -{ 2.05, 0.60997, 1.0016, 0.33885, 1.0189, 0.54977, 0.68425}, -{ 2.1, 0.64547, 1.002, 0.33998, 1.0191, 0.6075, 0.76477}, -{ 2.15, 0.68324, 1.0019, 0.34304, 1.019, 0.67146, 0.8428}, -{ 2.2, 0.71374, 1.0013, 0.3476, 1.0186, 0.72486, 0.89803}, -{ 2.25, 0.72981, 1.0004, 0.35287, 1.018, 0.75305, 0.91825}, -{ 2.3, 0.72833, 0.99946, 0.35791, 1.0174, 0.749, 0.90057}, -{ 2.35, 0.71076, 0.99873, 0.36186, 1.0169, 0.71588, 0.8506}, -{ 2.4, 0.68267, 0.99837, 0.36412, 1.0166, 0.66543, 0.78114}, -{ 2.45, 0.65212, 0.99847, 0.36452, 1.0165, 0.61318, 0.70996}, -{ 2.5, 0.62752, 0.99898, 0.36334, 1.0166, 0.57309, 0.65581}, -{ 2.55, 0.61534, 0.99975, 0.36125, 1.0169, 0.55418, 0.63292}, -{ 2.6, 0.61846, 1.0006, 0.35916, 1.0171, 0.55973, 0.64633}, -{ 2.65, 0.63555, 1.0012, 0.3579, 1.0173, 0.58767, 0.69028}, -{ 2.7, 0.66163, 1.0015, 0.358, 1.0174, 0.63107, 0.75061}, -{ 2.75, 0.68963, 1.0014, 0.35959, 1.0172, 0.67891, 0.80984}, -{ 2.8, 0.71231, 1.001, 0.36238, 1.0168, 0.71845, 0.85255}, -{ 2.85, 0.7242, 1.0003, 0.36575, 1.0163, 0.73892, 0.86907}, -{ 2.9, 0.72287, 0.99958, 0.36901, 1.0158, 0.73524, 0.85679}, -{ 2.95, 0.7094, 0.99903, 0.3715, 1.0154, 0.70971, 0.81993}, -{ 3, 0.68797, 0.99876, 0.37276, 1.015, 0.67092, 0.76835}, -{ 3.05, 0.66468, 0.99883, 0.37265, 1.0149, 0.6304, 0.71561}, -{ 3.1, 0.64588, 0.99922, 0.3714, 1.0149, 0.59888, 0.67568}, -{ 3.15, 0.63643, 0.9998, 0.3695, 1.0151, 0.58359, 0.65904}, -{ 3.2, 0.63853, 1.0004, 0.36763, 1.0152, 0.58731, 0.66933}, -{ 3.25, 0.65119, 1.0009, 0.36639, 1.0153, 0.6084, 0.70238}, -{ 3.3, 0.67068, 1.0011, 0.36619, 1.0153, 0.64122, 0.74782}, -{ 3.35, 0.69166, 1.0011, 0.36714, 1.0151, 0.67717, 0.79271}, -{ 3.4, 0.70866, 1.0007, 0.369, 1.0148, 0.70663, 0.82539}, -{ 3.45, 0.71753, 1.0002, 0.37133, 1.0144, 0.72165, 0.83832}, -{ 3.5, 0.71642, 0.99968, 0.3736, 1.014, 0.71856, 0.82936}, -{ 3.55, 0.70615, 0.99926, 0.37529, 1.0136, 0.69908, 0.80173}, -{ 3.6, 0.68988, 0.99906, 0.37608, 1.0133, 0.66953, 0.76303}, -{ 3.65, 0.67221, 0.99911, 0.37585, 1.0132, 0.63849, 0.72359}, -{ 3.7, 0.65794, 0.99941, 0.37477, 1.0131, 0.61413, 0.69389}, -{ 3.75, 0.65073, 0.99984, 0.37322, 1.0132, 0.60214, 0.68163}, -{ 3.8, 0.65224, 1.0003, 0.3717, 1.0133, 0.60478, 0.68948}, -{ 3.85, 0.66172, 1.0007, 0.37066, 1.0133, 0.62075, 0.71435}, -{ 3.9, 0.67638, 1.0008, 0.37041, 1.0133, 0.64561, 0.74862}, -{ 3.95, 0.69218, 1.0008, 0.37103, 1.0131, 0.67272, 0.78261}, -{ 4, 0.70501, 1.0005, 0.37235, 1.0129, 0.6948, 0.80753}, -{ 4.05, 0.7117, 1.0002, 0.37404, 1.0125, 0.70598, 0.81755}, -{ 4.1, 0.71085, 0.99976, 0.37569, 1.0122, 0.70356, 0.81094}, -{ 4.15, 0.70308, 0.99944, 0.37691, 1.0118, 0.68882, 0.79015}, -{ 4.2, 0.69077, 0.99929, 0.37744, 1.0116, 0.66641, 0.76101}, -{ 4.25, 0.67741, 0.99933, 0.37722, 1.0115, 0.64275, 0.73138}, -{ 4.3, 0.66659, 0.99955, 0.37636, 1.0114, 0.62405, 0.70911}, -{ 4.35, 0.6611, 0.99988, 0.37516, 1.0115, 0.61473, 0.69993}, -{ 4.4, 0.66219, 1.0002, 0.37397, 1.0115, 0.61659, 0.70582}, -{ 4.45, 0.66931, 1.0005, 0.37315, 1.0115, 0.62866, 0.7245}, -{ 4.5, 0.68036, 1.0006, 0.37293, 1.0115, 0.64748, 0.75033}, -{ 4.55, 0.6923, 1.0006, 0.37336, 1.0113, 0.66796, 0.77607}, -{ 4.6, 0.70202, 1.0004, 0.37433, 1.0111, 0.6846, 0.79507}, -{ 4.65, 0.70713, 1.0001, 0.37559, 1.0108, 0.69303, 0.80285}, -{ 4.7, 0.70653, 0.99982, 0.37681, 1.0105, 0.69123, 0.79801}, -{ 4.75, 0.7007, 0.99958, 0.37772, 1.0103, 0.68014, 0.78239}, -{ 4.8, 0.69142, 0.99946, 0.37811, 1.0101, 0.6632, 0.76043}, -{ 4.85, 0.68132, 0.99949, 0.37794, 1.0099, 0.64521, 0.73809}, -{ 4.9, 0.67312, 0.99966, 0.37728, 1.0099, 0.63087, 0.7213}, -{ 4.95, 0.66892, 0.99991, 0.37636, 1.0099, 0.62362, 0.71433}, -{ 5, 0.66968, 1.0002, 0.37545, 1.0099, 0.6249, 0.71867} \ No newline at end of file diff --git a/ComponentLib/Load/CMakeLists.txt b/ComponentLib/Load/CMakeLists.txt deleted file mode 100644 index 46abf3a22..000000000 --- a/ComponentLib/Load/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# -# 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 -#]] - -gridkit_add_library(load - SOURCES - Load.cpp - OUTPUT_NAME - gridkit_load) - diff --git a/ComponentLib/Load/Load.cpp b/ComponentLib/Load/Load.cpp deleted file mode 100644 index 65d44cfc5..000000000 --- a/ComponentLib/Load/Load.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * - * 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 -#include -#include "Load.hpp" -#include - -namespace ModelLib { - -/*! - * @brief Constructor for a constant load model - * - * Calls default ModelEvaluatorImpl constructor. - */ - -template -Load::Load(bus_type* bus, ScalarT P, ScalarT Q) - : P_(P), - Q_(Q), - busID_(0), - bus_(bus) -{ - //std::cout << "Create a load model with " << size_ << " variables ...\n"; - size_ = 0; -} - -template -Load::Load(bus_type* bus, LoadData& data) - : P_(data.Pd), - Q_(data.Qd), - busID_(data.bus_i), - bus_(bus) -{ - //std::cout << "Create a load model with " << size_ << " variables ...\n"; - size_ = 0; -} - -template -Load::~Load() -{ -} - -/*! - * @brief allocate method computes sparsity pattern of the Jacobian. - */ -template -int Load::allocate() -{ - return 0; -} - -/** - * Initialization of the grid model - */ -template -int Load::initialize() -{ - return 0; -} - -/* - * \brief Identify differential variables - */ -template -int Load::tagDifferentiable() -{ - return 0; -} - -/** - * @brief Contributes to the bus residual. - * - * Must be connected to a PQ bus. - */ -template -int Load::evaluateResidual() -{ - // std::cout << "Evaluating load residual ...\n"; - bus_->P() -= P_; - bus_->Q() -= Q_; - return 0; -} - -template -int Load::evaluateJacobian() -{ - return 0; -} - -template -int Load::evaluateIntegrand() -{ - return 0; -} - -template -int Load::initializeAdjoint() -{ - return 0; -} - -template -int Load::evaluateAdjointResidual() -{ - return 0; -} - -template -int Load::evaluateAdjointIntegrand() -{ - return 0; -} - - - - -// Available template instantiations -template class Load; -template class Load; - - -} //namespace ModelLib - diff --git a/ComponentLib/Load/Load.hpp b/ComponentLib/Load/Load.hpp deleted file mode 100644 index c6d3d55a2..000000000 --- a/ComponentLib/Load/Load.hpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _LOAD_HPP_ -#define _LOAD_HPP_ - -#include -#include - -namespace ModelLib -{ - template class BaseBus; -} - - -namespace ModelLib -{ - /*! - * @brief Declaration of a passive load class. - * - */ - template - class Load : public ModelEvaluatorImpl - { - 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_; - - // typedef typename ModelEvaluatorImpl::real_type real_type; - // typedef BaseBus bus_type; - using bus_type = BaseBus; - using real_type = typename ModelEvaluatorImpl::real_type; - using LoadData = GridKit::PowerSystemData::LoadData; - - public: - Load(bus_type* bus, ScalarT P, ScalarT Q); - Load(bus_type* bus, LoadData& data); - virtual ~Load(); - - int allocate(); - int initialize(); - int tagDifferentiable(); - int evaluateResidual(); - int evaluateJacobian(); - int evaluateIntegrand(); - - int initializeAdjoint(); - int evaluateAdjointResidual(); - //int evaluateAdjointJacobian(); - int evaluateAdjointIntegrand(); - - void updateTime(real_type t, real_type a) - { - time_ = t; - alpha_ = a; - } - - private: - ScalarT P_; - ScalarT Q_; - const IdxT busID_; - bus_type* bus_; - }; -} - -#endif // _LOAD_HPP_ diff --git a/ComponentLib/MiniGrid/CMakeLists.txt b/ComponentLib/MiniGrid/CMakeLists.txt deleted file mode 100644 index c88608b53..000000000 --- a/ComponentLib/MiniGrid/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# -# 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 -#]] - -gridkit_add_library(minigrid - SOURCES - MiniGrid.cpp - OUTPUT_NAME - gridkit_minigrid) - diff --git a/ComponentLib/MiniGrid/MiniGrid.cpp b/ComponentLib/MiniGrid/MiniGrid.cpp deleted file mode 100644 index fbcfe1491..000000000 --- a/ComponentLib/MiniGrid/MiniGrid.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * - * 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 -#include -#include "MiniGrid.hpp" -#include - -namespace ModelLib { - -/*! - * @brief Constructor for a constant load model - * - * Calls default ModelEvaluatorImpl constructor. - */ - -template -MiniGrid::MiniGrid() - : ModelEvaluatorImpl(3, 0, 0), - Pl2_( 2.5), - Ql2_( -0.8), - Pg3_( 2.0), - V1_ ( 1.0), - th1_( 0.0), - V3_ ( 1.1), - B12_( 10.0), - B13_( 15.0), - B22_(-22.0), - B23_( 12.0) -{ - //std::cout << "Create a load model with " << size_ << " variables ...\n"; - rtol_ = 1e-5; - atol_ = 1e-5; -} - -template -MiniGrid::~MiniGrid() -{ -} - -/*! - * @brief allocate method computes sparsity pattern of the Jacobian. - */ -template -int MiniGrid::allocate() -{ - return 0; -} - -/** - * Initialization of the grid model - */ -template -int MiniGrid::initialize() -{ - th2() = 0.0; // th2 - V2() = 1.0; // V2 - th3() = 0.0; // th3 - return 0; -} - - -/** - * @brief Contributes to the bus residual. - * - * Must be connected to a PQ bus. - */ -template -int MiniGrid::evaluateResidual() -{ - f_[0] = -Pl2_ - V2()*(V1_*B12_*sin(th2()-th1_) + V3_*B23_*sin(th2() - th3())); - f_[1] = -Ql2_ + V2()*(V1_*B12_*cos(th2()-th1_) + B22_*V2() + V3_*B23_*cos(th2() - th3())); - f_[2] = Pg3_ - V3_ *(V1_*B13_*sin(th3()-th1_) + V2()*B23_*sin(th3() - th2())); - - return 0; -} - -template -int MiniGrid::evaluateJacobian() -{ - return 0; -} - -// Available template instantiations -template class MiniGrid; -template class MiniGrid; - - -} //namespace ModelLib - diff --git a/ComponentLib/MiniGrid/MiniGrid.hpp b/ComponentLib/MiniGrid/MiniGrid.hpp deleted file mode 100644 index 1ec9e431a..000000000 --- a/ComponentLib/MiniGrid/MiniGrid.hpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * - * 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 - -namespace ModelLib -{ - /*! - * @brief Implementation of a power grid. - * - */ - template - class MiniGrid : public ModelEvaluatorImpl - { - using ModelEvaluatorImpl::size_; - using ModelEvaluatorImpl::nnz_; - using ModelEvaluatorImpl::time_; - using ModelEvaluatorImpl::y_; - using ModelEvaluatorImpl::f_; - using ModelEvaluatorImpl::rtol_; - using ModelEvaluatorImpl::atol_; - - typedef typename ModelEvaluatorImpl::real_type real_type; - - public: - MiniGrid(); - virtual ~MiniGrid(); - - int allocate(); - int initialize(); - int tagDifferentiable() {return -1;} - int evaluateResidual(); - int evaluateJacobian(); - int evaluateIntegrand() {return -1;} - - int initializeAdjoint() {return -1;} - int evaluateAdjointResidual() {return -1;} - //int evaluateAdjointJacobian() {return -1;} - int evaluateAdjointIntegrand() {return -1;} - - void updateTime(real_type t, real_type a) {} - - // const accessors are public - ScalarT const& th2() const - { - return y_[0]; - } - - ScalarT const& V2() const - { - return y_[1]; - } - - ScalarT const& th3() const - { - return y_[2]; - } - - ScalarT& th2() - { - return y_[0]; - } - - ScalarT& V2() - { - return y_[1]; - } - - ScalarT& th3() - { - return y_[2]; - } - - private: - ScalarT Pl2_; - ScalarT Ql2_; - ScalarT Pg3_; - ScalarT V1_ ; - ScalarT th1_; - ScalarT V3_ ; - ScalarT B12_; - ScalarT B13_; - ScalarT B22_; - ScalarT B23_; - }; -} diff --git a/Doxyfile b/Doxyfile index 501e61448..9662cec3f 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1,26 +1,3 @@ -# Doxyfile 1.8.18 -# -# 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. -# - # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # diff --git a/Examples/AdjointSensitivity/AdjointSensitivity.cpp b/Examples/AdjointSensitivity/AdjointSensitivity.cpp deleted file mode 100644 index 9c35d2006..000000000 --- a/Examples/AdjointSensitivity/AdjointSensitivity.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - * - * 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 - -#include -#include -#include -#include -#include - -/* - * Compute gradient of an objective function expressed as an integral over - * system trajectory. The gradient is computed numerically and using - * adjoint sensitivity analysis. - * - * The test case is a 4th order generator connected to an infinite bus. - * The objective function is total frequency deviation computed over - * system trajectory after generator short circuit fault. - * - */ -int main() -{ - using namespace ModelLib; - using namespace AnalysisManager::Sundials; - using namespace AnalysisManager; - using namespace GridKit::Testing; - - // Create an infinite bus - BaseBus* bus = new BusSlack(1.0, 0.0); - - // Attach a generator to that bus - Generator4* gen = new Generator4(bus, 0.8, 0.3); - - // Create a system model - SystemModel* model = new SystemModel(); - model->addBus(bus); - model->addComponent(gen); - - // allocate model components - model->allocate(); - - // Create numerical integrator and configure it for the generator model - Ida* idas = new Ida(model); - - double t_init = 0.0; - double t_final = 15.0; - - // setup simulation - idas->configureSimulation(); - idas->configureAdjoint(); - idas->getDefaultInitialCondition(); - idas->initializeSimulation(t_init); - idas->configureQuadrature(); - idas->initializeQuadrature(); - - - idas->runSimulation(0.1, 2); - idas->saveInitialCondition(); - - // create initial condition after a fault - { - idas->getSavedInitialCondition(); - idas->initializeSimulation(t_init); - gen->V() = 0.0; - idas->runSimulation(0.1, 20); - gen->V() = 1.0; - idas->saveInitialCondition(); - } - - // Get pointer the objective function - const double* Q = idas->getIntegral(); - - // Compute the objective function as an integral over the system trajectory - idas->getSavedInitialCondition(); - idas->initializeSimulation(t_init); - idas->initializeQuadrature(); - idas->runSimulationQuadrature(t_final, 100); - - std::cout << "\n\nCost of computing objective function:\n\n"; - idas->printFinalStats(); - - const double g1 = Q[0]; - const double eps = 2e-3; - - // Compute gradient of the objective function numerically - std::vector dGdp(model->size_opt()); - - for (unsigned i=0; isize_opt(); ++i) - { - model->param()[i] += eps; - idas->getSavedInitialCondition(); - idas->initializeSimulation(t_init); - idas->initializeQuadrature(); - idas->runSimulationQuadrature(t_final,100); - - std::cout << "\n\nCost of computing derivative with respect to parameter " - << i << ":\n\n"; - idas->printFinalStats(); - double g2 = Q[0]; - - // restore parameter to original value - model->param()[i] -= eps; - - // Evaluate dG/dp numerically - dGdp[i] = (g2 - g1)/eps; - } - - // Compute gradient of the objective function using adjoint method - idas->initializeAdjoint(); - idas->getSavedInitialCondition(); - idas->initializeSimulation(t_init); - idas->initializeQuadrature(); - idas->runForwardSimulation(t_final, 100); - - std::cout << "\n\nCost of forward simulation for adjoint\n" - << "sensitivity analysis:\n\n"; - idas->printFinalStats(); - - idas->initializeBackwardSimulation(t_final); - idas->runBackwardSimulation(t_init); - - std::cout << "\n\nCost of adjoint sensitivity analysis:\n\n"; - idas->printFinalStats(); - - // Compare results - int retval = 0; - std::cout << "\n\nComparison of numerical and adjoint results:\n\n"; - double* neg_dGdp = idas->getAdjointIntegral(); - for (unsigned i=0; isize_opt(); ++i) - { - std::cout << "dG/dp" << i << " (numerical) = " << dGdp[i] << "\n"; - std::cout << "dG/dp" << i << " (adjoint) = " << -neg_dGdp[i] << "\n\n"; - if(!isEqual(dGdp[i], -neg_dGdp[i], 10*eps)) - --retval; - } - - if(retval < 0) - { - std::cout << "The two results differ beyond solver tolerance!\n"; - } - - return retval; -} diff --git a/Examples/AdjointSensitivity/CMakeLists.txt b/Examples/AdjointSensitivity/CMakeLists.txt deleted file mode 100644 index 18121888a..000000000 --- a/Examples/AdjointSensitivity/CMakeLists.txt +++ /dev/null @@ -1,69 +0,0 @@ -# -# 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 -#]] - -add_executable(adjoint AdjointSensitivity.cpp) -target_link_libraries(adjoint GRIDKIT::bus GRIDKIT::generator4 GRIDKIT::solvers_dyn) -install(TARGETS adjoint DESTINATION bin) - -add_test(NAME AdjointSens COMMAND $ ) - - diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt deleted file mode 100644 index feec6623a..000000000 --- a/Examples/CMakeLists.txt +++ /dev/null @@ -1,72 +0,0 @@ -# -# 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. -# - -add_subdirectory(MatPowerTesting) - -if(TARGET SUNDIALS::kinsol) - add_subdirectory(Grid3Bus) -endif() - -if(TARGET SUNDIALS::idas) - add_subdirectory(AdjointSensitivity) - if(GRIDKIT_ENABLE_IPOPT) - add_subdirectory(DynamicConstrainedOpt) - add_subdirectory(GenConstLoad) - add_subdirectory(GenInfiniteBus) - add_subdirectory(ParameterEstimation) - endif() -endif() diff --git a/Examples/DynamicConstrainedOpt/CMakeLists.txt b/Examples/DynamicConstrainedOpt/CMakeLists.txt deleted file mode 100644 index a89ac0968..000000000 --- a/Examples/DynamicConstrainedOpt/CMakeLists.txt +++ /dev/null @@ -1,67 +0,0 @@ -# -# 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 -#]] - -add_executable(dynconopt DynamicConstrainedOpt.cpp) -target_link_libraries(dynconopt GRIDKIT::generator4 GRIDKIT::generator2 GRIDKIT::bus GRIDKIT::solvers_dyn GRIDKIT::solvers_opt) -install(TARGETS dynconopt DESTINATION bin) - -add_test(NAME DynamicConOpt COMMAND $) diff --git a/Examples/DynamicConstrainedOpt/DynamicConstrainedOpt.cpp b/Examples/DynamicConstrainedOpt/DynamicConstrainedOpt.cpp deleted file mode 100644 index 80f36fc13..000000000 --- a/Examples/DynamicConstrainedOpt/DynamicConstrainedOpt.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * - * 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 - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -int main() -{ - using namespace ModelLib; - using namespace AnalysisManager::Sundials; - using namespace AnalysisManager; - using namespace GridKit::Testing; - - // Create an infinite bus - BaseBus* bus = new BusSlack(1.0, 0.0); - - // Attach a generator to that bus - Generator2* gen = new Generator2(bus); - - // Create a system model - SystemModel* model = new SystemModel(); - model->addBus(bus); - model->addComponent(gen); - - // allocate model components - model->allocate(); - - // Create numerical integrator and configure it for the generator model - Ida* idas = new Ida(model); - - double t_init = 0.0; - double t_final = 20.0; - - // setup simulation - idas->configureSimulation(); - idas->configureAdjoint(); - idas->getDefaultInitialCondition(); - idas->initializeSimulation(t_init); - idas->configureQuadrature(); - idas->initializeQuadrature(); - - double t_fault = 0.02; - double t_clear = 0.06; - idas->runSimulation(t_fault); - // create initial condition after a fault - { - gen->V() = 0.0; - idas->runSimulation(t_clear, 2); - gen->V() = 1.0; - gen->theta() = -0.01; - idas->saveInitialCondition(); - } - - // Set integration time for dynamic constrained optimization - idas->setIntegrationTime(t_init, t_final, 100); - - // Guess optimization parameter value - double Pm = 0.7; - - // Create an instance of the IpoptApplication - Ipopt::SmartPtr ipoptApp = IpoptApplicationFactory(); - - // Initialize the IpoptApplication and process the options - Ipopt::ApplicationReturnStatus status; - status = ipoptApp->Initialize(); - if (status != Ipopt::Solve_Succeeded) { - std::cout << "\n\n*** Initialization failed! ***\n\n"; - return (int) status; - } - - // Set solver tolerance - const double tol = 1e-4; - - // Configure Ipopt application - ipoptApp->Options()->SetStringValue("hessian_approximation", "limited-memory"); - ipoptApp->Options()->SetNumericValue("tol", tol); - ipoptApp->Options()->SetIntegerValue("print_level", 0); - - // Create dynamic objective interface to Ipopt solver - Ipopt::SmartPtr ipoptDynamicObjectiveInterface = - new IpoptInterface::DynamicObjective(idas); - - // Initialize problem - model->param()[0] = Pm; - - // Solve the problem - status = ipoptApp->OptimizeTNLP(ipoptDynamicObjectiveInterface); - std::cout << "\n\nProblem formulated as dynamic objective optimization ...\n"; - - if (status == Ipopt::Solve_Succeeded) { - // Print result - std::cout << "\nSucess:\n The problem solved in " - << ipoptApp->Statistics()->IterationCount() << " iterations!\n" - << " Optimal value of Pm = " << model->param()[0] << "\n" - << " The final value of the objective function G(Pm) = " - << ipoptApp->Statistics()->FinalObjective() << "\n\n"; - } - - // Store dynamic objective optimization results - double* results = new double[model->size_opt()]; - for(unsigned i=0; i size_opt(); ++i) - { - results[i] = model->param()[i]; - } - - // Create dynamic constraint interface to Ipopt solver - Ipopt::SmartPtr ipoptDynamicConstraintInterface = - new IpoptInterface::DynamicConstraint(idas); - - // Initialize problem - model->param()[0] = Pm; - - // Solve the problem - status = ipoptApp->OptimizeTNLP(ipoptDynamicConstraintInterface); - std::cout << "\n\nProblem formulated as dynamic constraint optimization ...\n"; - - if (status == Ipopt::Solve_Succeeded) { - // Print result - std::cout << "\nSucess:\n The problem solved in " - << ipoptApp->Statistics()->IterationCount() << " iterations!\n" - << " Optimal value of Pm = " << model->param()[0] << "\n" - << " The final value of the objective function G(Pm) = " - << ipoptApp->Statistics()->FinalObjective() << "\n\n"; - } - - // Compare results of the two optimization methods - int retval = 0; - for(unsigned i=0; i size_opt(); ++i) - { - if(!isEqual(results[i], model->param()[i], 10*tol)) - --retval; - } - - if(retval < 0) - { - std::cout << "The two results differ beyond solver tolerance!\n"; - } - - delete [] results; - delete idas; - delete model; - return retval; -} diff --git a/Examples/GenConstLoad/CMakeLists.txt b/Examples/GenConstLoad/CMakeLists.txt deleted file mode 100644 index 8fb9adf92..000000000 --- a/Examples/GenConstLoad/CMakeLists.txt +++ /dev/null @@ -1,67 +0,0 @@ -# -# 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 -#]] - -add_executable(genconstload GenConstLoad.cpp) -target_link_libraries(genconstload GRIDKIT::generator4governor GRIDKIT::bus GRIDKIT::load GRIDKIT::solvers_dyn GRIDKIT::solvers_opt) -install(TARGETS genconstload DESTINATION bin) - -add_test(NAME GenConstLoad COMMAND $) diff --git a/Examples/GenConstLoad/GenConstLoad.cpp b/Examples/GenConstLoad/GenConstLoad.cpp deleted file mode 100644 index 744f0a86b..000000000 --- a/Examples/GenConstLoad/GenConstLoad.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - * - * 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. - * - */ - - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -int main() -{ - using namespace ModelLib; - using namespace AnalysisManager::Sundials; - using namespace AnalysisManager; - using namespace GridKit::Testing; - - // Create a bus - BaseBus* bus = new BusPQ(1.0, 0.0); - - // Attach a generator to the bus and signal ports - ModelEvaluatorImpl* gen = new Generator4Governor(bus, 0.8, 0.3); - - // Attach load to the bus - ModelEvaluatorImpl* load = new Load(bus, 0.8, 0.3); - - // Create system model - SystemModel* model = new SystemModel(); - model->addBus(bus); - model->addComponent(gen); - model->addComponent(load); - - // Create numerical integrator and configure it for the generator model - Ida* idas = new Ida(model); - - model->allocate(); - - double t_init = 0.0; - double t_final = 15.0; - - // setup simulation - idas->configureSimulation(); - idas->configureAdjoint(); - idas->getDefaultInitialCondition(); - idas->initializeSimulation(t_init, true); - idas->configureQuadrature(); - idas->initializeQuadrature(); - - idas->runSimulationQuadrature(0.1, 2); - idas->saveInitialCondition(); - - // Set integration time for dynamic constrained optimization - idas->setIntegrationTime(t_init, t_final, 250); - - // Guess optimization parameter values - double T2 = 0.15; - double K = 16.0; - - // Create an instance of the IpoptApplication - Ipopt::SmartPtr ipoptApp = IpoptApplicationFactory(); - - // Initialize the IpoptApplication and process the options - Ipopt::ApplicationReturnStatus status; - status = ipoptApp->Initialize(); - if (status != Ipopt::Solve_Succeeded) { - std::cout << "\n\n*** Initialization failed! ***\n\n"; - return (int) status; - } - - // Set solver tolerance - const double tol = 1e-4; - - // Configure Ipopt application - ipoptApp->Options()->SetStringValue("hessian_approximation", "limited-memory"); - ipoptApp->Options()->SetNumericValue("tol", tol); - ipoptApp->Options()->SetIntegerValue("print_level", 5); - - // Create interface to Ipopt solver - Ipopt::SmartPtr ipoptDynamicObjectiveInterface = - new IpoptInterface::DynamicObjective(idas); - - // Initialize problem - model->param()[0] = T2; - model->param()[1] = K; - - // Solve the problem - status = ipoptApp->OptimizeTNLP(ipoptDynamicObjectiveInterface); - - if (status == Ipopt::Solve_Succeeded) { - // Print result - std::cout << "\nSucess: The problem solved in " - << ipoptApp->Statistics()->IterationCount() - << " iterations!\n"; - std::cout << "Optimal value: T2 = " - << model->param()[0] - << ", K = " - << model->param()[1] << "\n"; - std::cout << "The final value of the objective function G(T2,K) = " - << ipoptApp->Statistics()->FinalObjective() << "\n\n"; - } - - // Compare results of the two optimization methods - int retval = - isEqual(ipoptApp->Statistics()->FinalObjective(), 1239.0, 10*tol) ? 0 : 1; - - if(retval != 0) - { - std::cout << "The two results differ beyond solver tolerance!\n"; - } - - - delete idas; - delete gen; - delete load; - delete bus; - delete model; - - return 0; -} diff --git a/Examples/GenInfiniteBus/CMakeLists.txt b/Examples/GenInfiniteBus/CMakeLists.txt deleted file mode 100644 index c6e90c26d..000000000 --- a/Examples/GenInfiniteBus/CMakeLists.txt +++ /dev/null @@ -1,67 +0,0 @@ -# -# 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 -#]] - -add_executable(geninfbus GenInfiniteBus.cpp) -target_link_libraries(geninfbus GRIDKIT::bus GRIDKIT::generator4 GRIDKIT::solvers_opt GRIDKIT::solvers_dyn) -install(TARGETS geninfbus DESTINATION bin) - -add_test(NAME GenInfiniteBus COMMAND $) diff --git a/Examples/GenInfiniteBus/GenInfiniteBus.cpp b/Examples/GenInfiniteBus/GenInfiniteBus.cpp deleted file mode 100644 index d4305ae05..000000000 --- a/Examples/GenInfiniteBus/GenInfiniteBus.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * - * 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 - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -int main() -{ - using namespace ModelLib; - using namespace AnalysisManager::Sundials; - using namespace AnalysisManager; - using namespace GridKit::Testing; - - // Create an infinite bus - BaseBus* bus = new BusSlack(1.0, 0.0); - - // Attach a generator to that bus - Generator4* gen = new Generator4(bus); - - // Create a system model - SystemModel* model = new SystemModel(); - model->addBus(bus); - model->addComponent(gen); - - // allocate model components - model->allocate(); - - // Create numerical integrator and configure it for the generator model - Ida* idas = new Ida(model); - - double t_init = 0.0; - double t_final = 15.0; - - // setup simulation - idas->configureSimulation(); - idas->configureAdjoint(); - idas->getDefaultInitialCondition(); - idas->initializeSimulation(t_init); - idas->configureQuadrature(); - idas->initializeQuadrature(); - - double t_fault = 0.1; - double t_clear = 0.1; - idas->runSimulation(t_fault); - idas->saveInitialCondition(); - // create initial condition after a fault - { - idas->getSavedInitialCondition(); - idas->initializeSimulation(t_init); - gen->V() = 0.0; - idas->runSimulation(t_clear, 20); - gen->V() = 1.0; - idas->saveInitialCondition(); - } - - // Set integration time for dynamic constrained optimization - idas->setIntegrationTime(t_init, t_final, 100); - - // Guess initial values of optimization parameters - double Pm = 1.0; - double Ef = 1.45; - - // Create an instance of the IpoptApplication - Ipopt::SmartPtr ipoptApp = IpoptApplicationFactory(); - - // Initialize the IpoptApplication and process the options - Ipopt::ApplicationReturnStatus status; - status = ipoptApp->Initialize(); - if (status != Ipopt::Solve_Succeeded) { - std::cout << "\n\n*** Initialization failed! ***\n\n"; - return (int) status; - } - - // Set solver tolerance - const double tol = 1e-4; - - // Configure Ipopt application - ipoptApp->Options()->SetStringValue("hessian_approximation", "limited-memory"); - ipoptApp->Options()->SetNumericValue("tol", tol); - ipoptApp->Options()->SetIntegerValue("print_level", 0); - - // Create dynamic objective interface to Ipopt solver - Ipopt::SmartPtr ipoptDynamicObjectiveInterface = - new IpoptInterface::DynamicObjective(idas); - - // Initialize the problem - model->param()[0] = Pm; - model->param()[1] = Ef; - - // Solve the problem - status = ipoptApp->OptimizeTNLP(ipoptDynamicObjectiveInterface); - std::cout << "\n\nProblem formulated as dynamic objective optimiztion ...\n"; - - if (status == Ipopt::Solve_Succeeded) { - // Print result - std::cout << "\nSucess:\n The problem solved in " - << ipoptApp->Statistics()->IterationCount() << " iterations!\n" - << " Optimal value of Pm = " << model->param()[0] << "\n" - << " Optimal value of Ef = " << model->param()[1] << "\n" - << " The final value of the objective function G(Pm,Ef) = " - << ipoptApp->Statistics()->FinalObjective() << "\n\n"; - } - - // Create dynamic constraint interface to Ipopt solver - Ipopt::SmartPtr ipoptDynamicConstraintInterface = - new IpoptInterface::DynamicConstraint(idas); - - // Store dynamic objective optimization results - double* results = new double[model->size_opt()]; - for(unsigned i=0; i size_opt(); ++i) - { - results[i] = model->param()[i]; - } - - // Initialize the problem - model->param()[0] = Pm; - model->param()[1] = Ef; - - // Solve the problem - status = ipoptApp->OptimizeTNLP(ipoptDynamicConstraintInterface); - std::cout << "\n\nProblem formulated as dynamic constraint optimiztion ...\n"; - - if (status == Ipopt::Solve_Succeeded) { - // Print result - std::cout << "\nSucess:\n The problem solved in " - << ipoptApp->Statistics()->IterationCount() << " iterations!\n" - << " Optimal value of Pm = " << model->param()[0] << "\n" - << " Optimal value of Ef = " << model->param()[1] << "\n" - << " The final value of the objective function G(Pm,Ef) = " - << ipoptApp->Statistics()->FinalObjective() << "\n\n"; - } - - // Compare results of the two optimization methods - int retval = 0; - for(unsigned i=0; i size_opt(); ++i) - { - if(!isEqual(results[i], model->param()[i], 100*tol)) - --retval; - } - - if(retval < 0) - { - std::cout << "The two results differ beyond solver tolerance!\n"; - } - - delete [] results; - delete idas; - delete model; - return 0; -} diff --git a/Examples/Grid3Bus/CMakeLists.txt b/Examples/Grid3Bus/CMakeLists.txt deleted file mode 100644 index 5aededa5e..000000000 --- a/Examples/Grid3Bus/CMakeLists.txt +++ /dev/null @@ -1,76 +0,0 @@ -# -# 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 -#]] - -# add_executable(grid3bus Grid3Bus.cpp) -# target_link_libraries(grid3bus GRIDKIT::minigrid GRIDKIT::solvers_steady) -# install(TARGETS grid3bus RUNTIME DESTINATION bin) - -add_executable(grid3bus Grid3BusSys.cpp) -target_link_libraries(grid3bus GRIDKIT::minigrid - GRIDKIT::bus - GRIDKIT::generator - GRIDKIT::branch - GRIDKIT::load - GRIDKIT::solvers_steady) -install(TARGETS grid3bus RUNTIME DESTINATION bin) - -add_test(NAME Grid3Bus COMMAND $) diff --git a/Examples/Grid3Bus/Grid3BusSys.cpp b/Examples/Grid3Bus/Grid3BusSys.cpp deleted file mode 100644 index a379f4015..000000000 --- a/Examples/Grid3Bus/Grid3BusSys.cpp +++ /dev/null @@ -1,394 +0,0 @@ -/* - * - * 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. - * - */ - -/** - * @file Grid3BusSys.cpp - * @author Slaven Peles - * @author Reid Gomillion - * - * Simple 3-bus grid example. Two models are tested here -- a hard-wired model - * and a model assembled using GridKit's system composer. - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static const std::string BUS3_DATA_STRING = R"( -function mpc = case5 -% Created by Reid Gomillion - -% MATPOWER - -%% MATPOWER Case Format : Version 2 -mpc.version = '2'; - -%%----- Power Flow Data -----%% -%% system MVA base -mpc.baseMVA = 100; - -%% bus data -% bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin -mpc.bus = [ - 1 3 2.0 0.0 0 0 0 1 0.0 0 0 0 0.0; - 2 1 2.5 -0.8 0 0 0 1 0.0 0 0 0 0.0; - 3 2 0 0 0 0 0 1.1 0.0 0 0 0 0.0; -]; - -%% generator data -% bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf -mpc.gen = [ - 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; - 3 2.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; -]; - -%% branch data -% fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax -mpc.branch = [ - 1 2 0 0.1 0 0 0 0 0 0 0 0 0; - 1 3 0 0.0666666 0 0 0 0 0 0 0 0 0; - 2 3 0 0.0833333 0 0 0 0 0 0 0 0 0; -]; - -%%----- OPF Data -----%% -%% generator cost data -% 1 startup shutdown n x1 y1 ... xn yn -% 2 startup shutdown n c(n-1) ... c0 -mpc.gencost = [ - 2 0 0 3 0 14 0; - 2 0 0 3 0 15 0; - 2 0 0 3 0 30 0; -]; - -)"; - - -using namespace ModelLib; -using namespace AnalysisManager::Sundials; -using namespace AnalysisManager; -using namespace GridKit::Testing; -using namespace GridKit::PowerSystemData; - - -/** - * Testing the monlithic case via the class MiniGrid - * @return returns 0 if pass o.w. fails -*/ -int monolithic_case() -{ - std::cout << "\nSolving power flow for a 3-bus monolithic model ...\n\n"; - // Create a 3-bus model - MiniGrid* model = new MiniGrid(); - - // allocate model - model->allocate(); - std::cout << "Model size: " << model->size() << "\n\n"; - - // Create numerical solver and attach the model to it. - // Here we use Kinsol solver from SUNDIALS library - Kinsol* kinsol = new Kinsol(model); - - // setup simulation - kinsol->configureSimulation(); - // initialize simulation with default initial guess V=1, theta=0 - kinsol->getDefaultInitialCondition(); - // Compute solution - kinsol->runSimulation(); - // Print solution - double th2 = model->th2() * 180.0/M_PI; - double V2 = model->V2(); - double th3 = model->th3() * 180.0/M_PI; - std::cout << "Solution:\n"; - std::cout << " theta2 = " << th2 << " deg, expected = " << " -4.87979 deg\n"; - std::cout << " V2 = " << V2 << " p.u., expected = " << " 1.08281 p.u.\n"; - std::cout << " theta3 = " << th3 << " deg, expected = " << " 1.46241 deg\n\n"; - - // Print solver performance statistics - kinsol->printFinalStats(); - - int retval1 = 0; - retval1 += !isEqual(th2, -4.87979, 1e-4); - retval1 += !isEqual(V2, 1.08281, 1e-4); - retval1 += !isEqual(th3, 1.46241, 1e-4); - - if(retval1 == 0) - std::cout << "\nSuccess!\n\n\n"; - else - std::cout << "\nFailed!\n\n\n"; - - // Delete solver and model - delete kinsol; kinsol = nullptr; - delete model; model = nullptr; - return retval1; -} - -/** - * Run the Testing case for parser setup - * @return returns 0 if pass o.w. fail -*/ -int parser_case() -{ - std::cout << "Solving same problem, but assembled from components via a parser ...\n\n"; - - //Data File Reading - GridKit::PowerSystemData::SystemModelData mp; - - std::istringstream iss(BUS3_DATA_STRING); - GridKit::readMatPower(mp, iss); - - - // Create an empty system model and pass the system model data to it - SystemSteadyStateModel* sysmodel = new SystemSteadyStateModel(mp); - - // allocate model - sysmodel->allocate(); - std::cout << "Model size: " << sysmodel->size() << "\n\n"; - - // Create numerical solver and attach the model to it. - // Here we use Kinsol solver from SUNDIALS library - Kinsol* kinsol = new Kinsol(sysmodel); - - // setup simulation - kinsol->configureSimulation(); - // initialize simulation with default initial guess - kinsol->getDefaultInitialCondition(); - // Compute solution - kinsol->runSimulation(); - // Print solution - double th2 = sysmodel->getBus(2)->theta() * 180.0/M_PI; - double V2 = sysmodel->getBus(2)->V(); - double th3 = sysmodel->getBus(3)->theta() * 180.0/M_PI; - - - std::cout << "Solution:\n"; - std::cout << " theta2 = " << th2 << " deg, expected = " << " -4.87979 deg\n"; - std::cout << " V2 = " << V2 << " p.u., expected = " << " 1.08281 p.u.\n"; - std::cout << " theta3 = " << th3 << " deg, expected = " << " 1.46241 deg\n\n"; - - // Print solver performance statistics - kinsol->printFinalStats(); - - int retval2 = 0; - retval2 += !isEqual(th2, -4.87979, 1e-4); - retval2 += !isEqual(V2, 1.08281, 1e-4); - retval2 += !isEqual(th3, 1.46241, 1e-4); - - if(retval2 == 0) - std::cout << "\nSuccess!\n\n\n"; - else - std::cout << "\nFailed!\n\n\n"; - - - // Delete solver and model - - delete kinsol; kinsol = nullptr; - delete sysmodel; sysmodel = nullptr; - - return retval2; -} - -/** - * Hardwired Test Case - * @return 0 if pass otherwise fails -*/ -int hardwired_case() -{ - std::cout << "Solving same problem, but assembled from components manually ...\n\n"; - - // First, create an empty system model - SystemSteadyStateModel* sysmodel = new SystemSteadyStateModel(); - - // Next create and add buses ... - // Create a slack bus, fix V=1, theta=0, bus ID = 1 - BusData bd1; - bd1.bus_i = 1; bd1.type = 3; bd1.Vm = 1.0; bd1.Va = 0.0; - auto* bus1 = BusFactory::create(bd1); - sysmodel->addBus(bus1); - - //Create a PQ bus, initialize V=1, theta=0, bus ID = 2 - BusData bd2; - bd2.bus_i = 2; bd2.type = 1; bd2.Vm = 1.0; bd2.Va = 0.0; - auto* bus2 = BusFactory::create(bd2); - sysmodel->addBus(bus2); - - // Create a PV bus, fix V=1.1, initialize theta=0, and set power injection Pg=2 - BusData bd3; - bd3.bus_i = 3; bd3.type = 2; bd3.Vm = 1.1; bd3.Va = 0.0; - auto* bus3 = BusFactory::create(bd3); - sysmodel->addBus(bus3); - - // Create and add generators ... - // Create and add slack generator connected to bus1 - GenData gd1; - gd1.bus = 1; - auto* gen1 = GeneratorFactory::create(sysmodel->getBus(gd1.bus), gd1); - sysmodel->addComponent(gen1); - - // Create and add PV generator connected to bus3 - GenData gd3; - gd3.Pg = 2.0; gd3.bus = 3; - auto* gen3 = GeneratorFactory::create(sysmodel->getBus(gd3.bus), gd3); - sysmodel->addComponent(gen3); - - // Create and add branches ... - // Branch 1-2 - BranchData brd12; - brd12.fbus = 1; brd12.tbus = 2; brd12.x = 1.0/10.0; brd12.r = 0.0; brd12.b = 0.0; - Branch* branch12 = new Branch(sysmodel->getBus(brd12.fbus), sysmodel->getBus(brd12.tbus), brd12); - sysmodel->addComponent(branch12); - - // Branch 1-3 - BranchData brd13; - brd13.fbus = 1; brd13.tbus = 3; brd13.x = 1.0/15.0; brd13.r = 0.0; brd13.b = 0.0; - Branch* branch13 = new Branch(sysmodel->getBus(brd13.fbus), sysmodel->getBus(brd13.tbus), brd13); - sysmodel->addComponent(branch13); - - // Branch 2-3 - BranchData brd23; - brd23.fbus = 2; brd23.tbus = 3; brd23.x = 1.0/12.0; brd23.r = 0.0; brd23.b = 0.0; - Branch* branch23 = new Branch(sysmodel->getBus(brd23.fbus), sysmodel->getBus(brd23.tbus), brd23); - sysmodel->addComponent(branch23); - - - // Create and add loads ... - // Load on bus1 - LoadData ld1; - ld1.bus_i = 1; ld1.Pd = 2.0; ld1.Qd = 0.0; - Load* load1 = new Load(sysmodel->getBus(ld1.bus_i), ld1); - sysmodel->addComponent(load1); - - // Load on bus2 - LoadData ld2; - ld2.bus_i = 2; ld2.Pd = 2.5; ld2.Qd = -0.8; - Load* load2 = new Load(sysmodel->getBus(ld2.bus_i), ld2); - sysmodel->addComponent(load2); - - // allocate model - sysmodel->allocate(); - std::cout << "Model size: " << sysmodel->size() << "\n\n"; - - // Create numerical solver and attach the model to it. - // Here we use Kinsol solver from SUNDIALS library - Kinsol* kinsol = new Kinsol(sysmodel); - - // setup simulation - kinsol->configureSimulation(); - // initialize simulation with default initial guess - kinsol->getDefaultInitialCondition(); - // Compute solution - kinsol->runSimulation(); - // Print solution - double th2 = bus2->theta() * 180.0/M_PI; - double V2 = bus2->V(); - double th3 = bus3->theta() * 180.0/M_PI; - - - std::cout << "Solution:\n"; - std::cout << " theta2 = " << th2 << " deg, expected = " << " -4.87979 deg\n"; - std::cout << " V2 = " << V2 << " p.u., expected = " << " 1.08281 p.u.\n"; - std::cout << " theta3 = " << th3 << " deg, expected = " << " 1.46241 deg\n\n"; - - // Print solver performance statistics - kinsol->printFinalStats(); - - int retval2 = 0; - retval2 += !isEqual(th2, -4.87979, 1e-4); - retval2 += !isEqual(V2, 1.08281, 1e-4); - retval2 += !isEqual(th3, 1.46241, 1e-4); - - if(retval2 == 0) - std::cout << "\nSuccess!\n\n\n"; - else - std::cout << "\nFailed!\n\n\n"; - - - // Delete solver and model - delete kinsol; kinsol = nullptr; - delete sysmodel; sysmodel = nullptr; - return retval2; -} - - -int main() -{ - //return the results of each case - int resolve = 0; - std::cout << std::string(32,'-') << std::endl; - resolve += monolithic_case(); - std::cout << std::string(32,'-') << std::endl; - resolve += hardwired_case(); - std::cout << std::string(32,'-') << std::endl; - resolve += parser_case(); - return resolve; -} diff --git a/Examples/ParameterEstimation/CMakeLists.txt b/Examples/ParameterEstimation/CMakeLists.txt deleted file mode 100644 index 1a223998a..000000000 --- a/Examples/ParameterEstimation/CMakeLists.txt +++ /dev/null @@ -1,74 +0,0 @@ -# -# 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 -#]] - -add_executable(paramest ParameterEstimation.cpp) -target_link_libraries(paramest - GRIDKIT::bus - GRIDKIT::generator4param - GRIDKIT::solvers_opt - GRIDKIT::solvers_dyn - GRIDKIT::Utilities - ) -install(TARGETS paramest RUNTIME DESTINATION bin) -install(FILES lookup_table.dat DESTINATION bin) - -add_test(NAME ParameterEst COMMAND $ ${CMAKE_SOURCE_DIR}/Examples/ParameterEstimation/lookup_table.dat) diff --git a/Examples/ParameterEstimation/ParameterEstimation.cpp b/Examples/ParameterEstimation/ParameterEstimation.cpp deleted file mode 100644 index 874195552..000000000 --- a/Examples/ParameterEstimation/ParameterEstimation.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* - * - * 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 - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -int main(int argc, char** argv) -{ - using namespace ModelLib; - using namespace AnalysisManager::Sundials; - using namespace AnalysisManager; - using namespace GridKit::Testing; - - // Create an infinite bus - BaseBus* bus = new BusSlack(1.0, 0.0); - - // Attach a generator to that bus - Generator4Param* gen = new Generator4Param(bus); - - // Create a system model - SystemModel* model = new SystemModel(); - model->addBus(bus); - model->addComponent(gen); - - // allocate model components - model->allocate(); - - // Create numerical integrator and configure it for the generator model - Ida* idas = new Ida(model); - - const std::string input_data = (argc == 2) ? argv[1] : "lookup_table.dat"; - double t_init = -1.0; - double t_final = -1.0; - - GridKit::setLookupTable(gen->getLookupTable(), input_data, t_init, t_final); - - std::cout << "Performing parameter estimation with respect to data\nfrom " - << "t_init = " << t_init << " to t_final = " << t_final << "\n"; - - // setup simulation - idas->configureSimulation(); - idas->configureAdjoint(); - idas->getDefaultInitialCondition(); - idas->initializeSimulation(t_init); - idas->configureQuadrature(); - idas->initializeQuadrature(); - - double t_fault = 0.1; - double t_clear = 0.1; - idas->runSimulation(t_fault); - idas->saveInitialCondition(); - // create initial condition after a fault - { - idas->getSavedInitialCondition(); - idas->initializeSimulation(t_init); - gen->V() = 0.0; - idas->runSimulation(t_clear, 20); - gen->V() = 1.0; - idas->saveInitialCondition(); - } - - // Set integration time for dynamic constrained optimization - idas->setIntegrationTime(t_init, t_final, 100); - - // Guess value of inertia coefficient - model->param()[0] = 3.0; - - // Create an instance of the IpoptApplication - Ipopt::SmartPtr ipoptApp = IpoptApplicationFactory(); - - // Set solver tolerance - const double tol = 1e-5; - - // Initialize the IpoptApplication and process the options - Ipopt::ApplicationReturnStatus status; - status = ipoptApp->Initialize(); - if (status != Ipopt::Solve_Succeeded) - { - std::cout << "\n\n*** Initialization failed! ***\n\n"; - return (int) status; - } - - // Configure Ipopt application - ipoptApp->Options()->SetStringValue("hessian_approximation", "limited-memory"); - ipoptApp->Options()->SetNumericValue("tol", tol); - ipoptApp->Options()->SetIntegerValue("print_level", 0); - - // Create dynamic objective interface to Ipopt solver - Ipopt::SmartPtr ipoptDynamicObjectiveInterface = - new IpoptInterface::DynamicObjective(idas); - - // Solve the problem - status = ipoptApp->OptimizeTNLP(ipoptDynamicObjectiveInterface); - std::cout << "\n\nProblem formulated as dynamic objective optimiztion ...\n"; - - if (status == Ipopt::Solve_Succeeded) - { - // Print result - std::cout << "\nSucess:\n The problem solved in " - << ipoptApp->Statistics()->IterationCount() << " iterations!\n" - << " Optimal value of H = " << model->param()[0] << "\n" - << " The final value of the objective function G(H) = " - << ipoptApp->Statistics()->FinalObjective() << "\n\n"; - } - - // Store dynamic objective optimization results - double* results = new double[model->size_opt()]; - for(unsigned i=0; i size_opt(); ++i) - { - results[i] = model->param()[i]; - } - - // Guess value of inertia coefficient - model->param()[0] = 3.0; - - // Create dynamic constraint interface to Ipopt solver - Ipopt::SmartPtr ipoptDynamicConstraintInterface = - new IpoptInterface::DynamicConstraint(idas); - - // Solve the problem - status = ipoptApp->OptimizeTNLP(ipoptDynamicConstraintInterface); - std::cout << "\n\nProblem formulated as dynamic constraint optimiztion ...\n"; - - if (status == Ipopt::Solve_Succeeded) - { - // Print result - std::cout << "\nSucess:\n The problem solved in " - << ipoptApp->Statistics()->IterationCount() << " iterations!\n" - << " Optimal value of H = " << model->param()[0] << "\n" - << " The final value of the objective function G(H) = " - << ipoptApp->Statistics()->FinalObjective() << "\n\n"; - } - - // Compare results of the two optimization methods - int retval = 0; - for(unsigned i=0; i size_opt(); ++i) - { - if(!isEqual(results[i], model->param()[i], 100*tol)) - --retval; - } - - if(retval < 0) - { - std::cout << "The two results differ beyond solver tolerance!\n"; - } - - delete [] results; - delete idas; - delete model; - return retval; -} diff --git a/LICENSE b/LICENSE index 7c44911c8..a027757f3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,63 +1,46 @@ -******************************************************************************* - -GridKit™: ................................, version 0.0.5 - -Copyright (c) 2017, Lawrence Livermore National Security, LLC. -Produced at the Lawrence Livermore National Laboratory. -Written by Slaven Peles . -LLNL-CODE-718378. -OCEC-17-011 +Copyright (c) 2025, UT-Battelle. All rights reserved. - -******************************************************************************* - -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) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -Additional BSD Notice ---------------------- - -1. This notice is required to be provided under our contract with the U.S. -Department of Energy (DOE). This work was produced at Lawrence Livermore -National Laboratory under Contract No. DE-AC52-07NA27344 with the DOE. - -2. Neither the United States Government nor Lawrence Livermore National -Security, LLC nor any of their employees, makes any warranty, express or -implied, or assumes any 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. - -3. Also, reference herein to any specific commercial products, process, -or services 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. +GridKit™ version 0.1 + + +Open Source License: + +Subject to the conditions of this License, UT-Battelle, LLC, hereby grants +free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable copyright license to use, copy, modify, +merge, publish, distribute, and/or sublicense copies of the Software. + +1. Redistributions of Software must retain the above open source license grant, +copyright and license notices, this list of conditions, and the disclaimer +listed below. Changes or modifications to, or derivative works of the +Software must be noted with comments and the contributor and organization's +name. If the Software is protected by a proprietary trademark owned by +UT-Battelle, LLC or the Department of Energy, then derivative works of the +Software may not be distributed using the trademark without the prior written +approval of the trademark owner. + +2. Neither the names of Licensor nor the Department of Energy may be used to +endorse or promote products derived from this Software without their specific +prior written permission. + +3. The Software, with or without modification, must include the following +acknowledgment: "This product includes software produced by UT-Battelle, LLC +under Contract No. DE-AC05-00OR22725 with the Department of Energy.” + + + +------------------------------------------------------------------------------- + +DISCLAIMER: + +UT-BATTELLE, LLC, AND THE GOVERNMENT MAKE NO REPRESENTATIONS AND DISCLAIM ALL +WARRANTIES, BOTH EXPRESSED AND IMPLIED. THERE ARE NO EXPRESS OR IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, OR THAT THE +USE OF THE SOFTWARE WILL NOT INFRINGE ANY PATENT, COPYRIGHT, TRADEMARK, OR +OTHER PROPRIETARY RIGHTS, OR THAT THE SOFTWARE WILL ACCOMPLISH THE INTENDED +RESULTS OR THAT THE SOFTWARE OR ITS USE WILL NOT RESULT IN INJURY OR DAMAGE. +THE USER ASSUMES RESPONSIBILITY FOR ALL LIABILITIES, PENALTIES, FINES, CLAIMS, +CAUSES OF ACTION, AND COSTS AND EXPENSES, CAUSED BY, RESULTING FROM OR ARISING +OUT OF, IN WHOLE OR IN PART THE USE, STORAGE OR DISPOSAL OF THE SOFTWARE. diff --git a/ModelEvaluator.hpp b/ModelEvaluator.hpp deleted file mode 100644 index 5eda481de..000000000 --- a/ModelEvaluator.hpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _MODEL_EVALUATOR_HPP_ -#define _MODEL_EVALUATOR_HPP_ - -#include -#include - -namespace ModelLib -{ - - /*! - * @brief Abstract class describing a model. - * - */ - template - class ModelEvaluator - { - public: - typedef typename GridKit::ScalarTraits::real_type real_type; - - ModelEvaluator(){} - virtual ~ModelEvaluator(){} - - 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; - virtual IdxT size_quad() = 0; - virtual IdxT size_opt() = 0; - virtual void updateTime(real_type t, real_type a) = 0; - virtual void setTolerances(real_type& rtol, real_type& atol) 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 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 ModelLib - -#endif // _MODEL_EVALUATOR_HPP_ \ No newline at end of file diff --git a/ModelEvaluatorImpl.hpp b/ModelEvaluatorImpl.hpp deleted file mode 100644 index a4ef43a00..000000000 --- a/ModelEvaluatorImpl.hpp +++ /dev/null @@ -1,289 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _MODEL_EVALUATOR_IMPL_HPP_ -#define _MODEL_EVALUATOR_IMPL_HPP_ - -#include -#include - -namespace ModelLib -{ - - /*! - * @brief Model implementation base class. - * - */ - template - class ModelEvaluatorImpl : public ModelEvaluator - { - public: - typedef typename ModelEvaluator::real_type real_type; - - ModelEvaluatorImpl() - : size_(0), - size_quad_(0), - size_opt_(0) - {} - - ModelEvaluatorImpl(IdxT size, IdxT size_quad, IdxT size_opt) - : size_(size), - size_quad_(size_quad), - size_opt_(size_opt), - y_(size_), - yp_(size_), - f_(size_), - g_(size_quad_), - yB_(size_), - ypB_(size_), - fB_(size_), - gB_(size_opt_), - param_(size_opt_), - param_up_(size_opt_), - param_lo_(size_opt_) - {} - - virtual IdxT size() - { - return size_; - } - - virtual IdxT nnz() - { - return nnz_; - } - - virtual IdxT size_quad() - { - return size_quad_; - } - - virtual IdxT size_opt() - { - return size_opt_; - } - - // 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_; - } - - std::vector& y() - { - return y_; - } - - const std::vector& y() const - { - return y_; - } - - std::vector& yp() - { - return yp_; - } - - const std::vector& yp() const - { - return yp_; - } - - std::vector& tag() - { - return tag_; - } - - const std::vector& tag() const - { - return tag_; - } - - std::vector& yB() - { - return yB_; - } - - const std::vector& yB() const - { - return yB_; - } - - std::vector& ypB() - { - return ypB_; - } - - const std::vector& ypB() const - { - return ypB_; - } - - std::vector& param() - { - return param_; - } - - const std::vector& param() const - { - return param_; - } - - std::vector& param_up() - { - return param_up_; - } - - const std::vector& param_up() const - { - return param_up_; - } - - std::vector& param_lo() - { - return param_lo_; - } - - const std::vector& param_lo() const - { - return param_lo_; - } - - std::vector& getResidual() - { - return f_; - } - - const std::vector& getResidual() const - { - return f_; - } - - std::vector& getIntegrand() - { - return g_; - } - - const std::vector& getIntegrand() const - { - return g_; - } - - std::vector& getAdjointResidual() - { - return fB_; - } - - const std::vector& getAdjointResidual() const - { - return fB_; - } - - std::vector& getAdjointIntegrand() - { - return gB_; - } - - const std::vector& getAdjointIntegrand() const - { - return gB_; - } - - - - protected: - IdxT size_; - IdxT nnz_; - IdxT size_quad_; - IdxT size_opt_; - - 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_; - - std::vector param_; - std::vector param_up_; - std::vector param_lo_; - - real_type time_; - real_type alpha_; - - real_type rtol_; - real_type atol_; - - }; - - -} // namespace ModelLib - -#endif // _MODEL_EVALUATOR_IMPL_HPP_ \ No newline at end of file diff --git a/NOTICE b/NOTICE new file mode 100644 index 000000000..f7cf60ac8 --- /dev/null +++ b/NOTICE @@ -0,0 +1,22 @@ +Disclaimer: + +This material was prepared as an account of work sponsored by an agency of the +United States Government. Neither the United States Government nor the United +States Department of Energy, nor UT-Battelle, nor any of their employees, nor +any jurisdiction or organization that has cooperated in the development of +these materials, makes any warranty, express or implied, or assumes any legal +liability or responsibility for the accuracy, completeness, or usefulness or +any information, apparatus, product, software, 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 any agency thereof, or UT Batelle. The views and opinions +of authors expressed herein do not necessarily state or reflect those of the +United States Government or any agency thereof. + +OAK RIDGE NATIONAL LABORATORY +operated by UT-BATTELLE for the +UNITED STATES DEPARTMENT OF ENERGY +under Contract DE-AC05-00OR22725 diff --git a/PowerSystemData.hpp b/PowerSystemData.hpp deleted file mode 100644 index 67294db4f..000000000 --- a/PowerSystemData.hpp +++ /dev/null @@ -1,242 +0,0 @@ -#pragma once -#include -#include -#include -#include - -/** - * - * @file PowerSystemData.hpp - * @author Asher Mancinelli - * - * @remark `std::stringstream` is preferred over `operator+(std::string, ...)` - * since stringstream does not reallocate on append. - * - */ - -namespace GridKit -{ - -namespace PowerSystemData -{ - - template - struct BusData - { - IdxT bus_i; ///< Bus ID - IdxT type; ///< Bus type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated - RealT Gs; ///< Shunt conductance (MW demanded at V = 1.0 p.u.) - RealT Bs; ///< Shunt susceptance (MVAr injected at V = 1.0 p.u.) - IdxT area; ///< Area number (>0) - RealT Vm; ///< Voltage magnitude (p.u.) - RealT Va; ///< Voltage phase (deg) - RealT baseKV; ///< Base voltage [kV] - IdxT zone; ///< Loss zone number (>0) - RealT Vmax; ///< Maximum voltage magnitude (p.u.) - RealT Vmin; ///< Minimum voltage magnitude (p.u.) - - inline std::string str() const - { - std::stringstream ss; - std::cerr << std::setw(10) << bus_i - << std::setw(10) << type - << std::setw(10) << Gs - << std::setw(10) << Bs - << std::setw(10) << area - << std::setw(10) << Vm - << std::setw(10) << Va - << std::setw(10) << baseKV - << std::setw(10) << zone - << std::setw(10) << Vmax - << std::setw(10) << Vmin; - ss << "\n"; - return ss.str(); - } - }; - - template - struct LoadData - { - IdxT bus_i; ///< Bus ID - RealT Pd; ///< Active power demand [MW] - RealT Qd; ///< Reactive power demand [MVAr] - - inline std::string str() const - { - std::stringstream ss; - std::cerr << std::setw(10) << bus_i - << std::setw(10) << Pd - << std::setw(10) << Qd; - ss << "\n"; - return ss.str(); - } - }; - - template - struct GenData - { - IdxT bus; ///< Bus ID - RealT Pg; ///< Active power output [MW] - RealT Qg; ///< Reactive power output [MVAr] - RealT Qmax; ///< Maximum reactive power output [MVAr] - RealT Qmin; ///< Minimum reactive power output [MVAr] - RealT Vg; ///< - RealT mBase; ///< Total MVA base of machine - IdxT status; ///< Service status (>0 in service, <=0 out of service) - RealT Pmax; ///< Maximum active power output [MVAr] - RealT Pmin; ///< Minimum active power output [MVAr] - RealT Pc1; ///< - RealT Pc2; ///< - RealT Qc1min; ///< - RealT Qc1max; ///< - RealT Qc2min; ///< - RealT Qc2max; ///< - RealT ramp_agc; ///< - RealT ramp_10; ///< - RealT ramp_30; ///< - RealT ramp_q; ///< - RealT apf; ///< - - inline std::string str() const - { - std::stringstream ss; - ss << std::setw(10) << bus - << std::setw(10) << Pg - << std::setw(10) << Qg - << std::setw(10) << Qmax - << std::setw(10) << Qmin - << std::setw(10) << Vg - << std::setw(10) << mBase - << std::setw(10) << status - << std::setw(10) << Pmax - << std::setw(10) << Pmin - << std::setw(10) << Pc1 - << std::setw(10) << Pc2 - << std::setw(10) << Qc1min - << std::setw(10) << Qc1max - << std::setw(10) << Qc2min - << std::setw(10) << Qc2max - << std::setw(10) << ramp_agc - << std::setw(10) << ramp_10 - << std::setw(10) << ramp_30 - << std::setw(10) << ramp_q - << std::setw(10) << apf; - ss << "\n"; - return ss.str(); - } - }; - - template - struct BranchData - { - IdxT fbus; ///< "From" bus ID - IdxT tbus; ///< "To" bus ID - RealT r; ///< Resistance (p.u.) - RealT x; ///< Reactance (p.u.) - RealT b; ///< Total line charging susceptance (p.u.) - RealT rateA; ///< MVA rating A (long term rating), 0=unlimited - RealT rateB; ///< MVA rating B (short term rating), 0=unlimited - RealT rateC; ///< MVA rating C (emergency rating), 0=unlimited - RealT ratio; ///< Transformer off nominal turns ratio - RealT angle; ///< Transformer phase shift angle [deg], positive ⇒ delay - IdxT status; ///< Initial service status: 1=in-service, 0=out-of-service - RealT angmin; ///< Minimum anngle difference af - at [deg] - RealT angmax; ///< Maximum anngle difference af - at [deg] - - inline std::string str() const - { - std::stringstream ss; - ss << std::setw(10) << fbus - << std::setw(10) << tbus - << std::setw(10) << r - << std::setw(10) << x - << std::setw(10) << b - << std::setw(10) << rateA - << std::setw(10) << rateB - << std::setw(10) << rateC - << std::setw(10) << ratio - << std::setw(10) << angle - << std::setw(10) << status - << std::setw(10) << angmin - << std::setw(10) << angmax; - ss << "\n"; - return ss.str(); - } - }; - - template - struct GenCostData - { - IdxT kind; - IdxT startup; - IdxT shutdown; - IdxT n; - std::vector rest; - - inline std::string str() const - { - std::stringstream ss; - ss << std::setw(10) << kind - << std::setw(10) << startup - << std::setw(10) << shutdown - << std::setw(10) << n; - for (const auto& val : rest) - ss << std::setw(10) << val; - ss << "\n"; - return ss.str(); - } - }; - - template - struct SystemModelData - { - using BusDataT = BusData; - using GenDataT = GenData; - using BranchDataT = BranchData; - using GenCostDataT = GenCostData; - using LoadDataT = LoadData; - - std::string version; - IdxT baseMVA; - std::vector bus; - std::vector gen; - std::vector branch; - std::vector gencost; - std::vector load; - - // Not sure if these should be in this struct... Not all matpower files - // I found contained them. - // - // std::string name; - // std::vector bus_name; - - inline std::string str() const - { - std::stringstream ss; - ss << "Version: " << version << "\n" - << "Base MVA: " << baseMVA << "\n"; - - ss << "Bus:\n"; - for (const auto& v : bus) - ss << bus.str() << "\n"; - - ss << "Gen:\n"; - for (const auto& v : gen) - ss << gen.str(); - - ss << "Branch:\n"; - for (const auto& v : branch) - ss << branch.str(); - - ss << "GenCost:\n"; - for (const auto& v : gencost) - ss << gencost.str(); - - ss << "\n"; - - return ss.str(); - } - }; // struct SystemModelData - -} // namespace PowerSystemData -} // namespace GridKit diff --git a/README.md b/README.md index 600516ea6..f3b44b4ce 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # GridKit™ -This is experimental code for prototyping interfaces for dynamic -simulations, sensitivity analysis and optimization. Target applications -are power grids, but the methodology and the framework could be used -in other areas without major modifications. +The objective of GridKit™ is to provide a modeling framework for power +systems simulations and analysis that can support multiple advanced +analysys methods, such as dynamic constrained optimization and partitioned +numerical integrators for systems of differential and algebraic equations. +While target applications are power grids, but the methodology and the +framework could be used in other areas without major modifications. ## Installation Guide @@ -14,9 +16,13 @@ Before installing GridKit™ make sure you have all needed dependencies. ### Dependencies You should have all of the following installed before installing GridKit™ - A version of - - [SUNDIALS](https://github.com/LLNL/sundials) >= 6.0.0 - - [Suitesparse](https://github.com/DrTimothyAldenDavis/SuiteSparse) >= 5.x (optional) - - [Ipopt](https://github.com/coin-or/Ipopt) >= 3.x (optional) + - [SUNDIALS](https://github.com/LLNL/sundials) >= 7.0.0 + - [Suitesparse](https://github.com/DrTimothyAldenDavis/SuiteSparse) >= 5.x (optional) + - If using Suitesparse, SUNDIALS must also be built with [KLU support](https://sundials.readthedocs.io/en/latest/sundials/Install_link.html#cmakeoption-ENABLE_KLU) + - [Ipopt](https://github.com/coin-or/Ipopt) >= 3.x (optional) + - [Enzyme](https://github.com/EnzymeAD/Enzyme) >=0.0.131 (optional) + - [LLVM](https://github.com/llvm/llvm-project) >= 15.x. GridKit is + currently tested with LLVM 16. - [CMake](https://cmake.org/) >= 3.12 - C++ 17 compliant compiler @@ -44,5 +50,8 @@ as functionality test and executed by running `ctest` in the build directory. ## Contributors -GridKit™ is written by Slaven Peles (peless@ornl.gov) and has received contributions -from Tamara Becejac (Avangrid), R. Cameron Rutherford (PNNL), Asher J. Mancinelli (NVIDIA), and Reid Gomillion (Virginia Tech). +GridKit™ is written by Slaven Peles (peless@ornl.gov) and has received +contribution from Abdourahman Barry (Virginia Tech), Tamara Becejac (Avangrid), +Adam Birchfield (Texas A&M), Reid Gomillion (Virginia Tech), Nicholson +Koukpaizan (ORNL), Asher J. Mancinelli (NVIDIA), Alex Novotny (Virginia Tech), +Shaked Regev (ORNL), and R. Cameron Rutherford (PNNL). diff --git a/ScalarTraits.hpp b/ScalarTraits.hpp deleted file mode 100644 index 072e83710..000000000 --- a/ScalarTraits.hpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _SCALAR_TRAITS_HPP_ -#define _SCALAR_TRAITS_HPP_ - -namespace GridKit -{ - template - class ScalarTraits - { - }; - - template<> - class ScalarTraits - { - public: - typedef double real_type; - typedef double norm_type; - typedef double scalar_type; - }; - -} // namespace GridKit - -#endif // _SCALAR_TRAITS_HPP_ diff --git a/Solver/CMakeLists.txt b/Solver/CMakeLists.txt deleted file mode 100644 index 8be94fdae..000000000 --- a/Solver/CMakeLists.txt +++ /dev/null @@ -1,73 +0,0 @@ -# -# 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 -#]] - -if(TARGET SUNDIALS::kinsol) - add_subdirectory(SteadyState) -endif() - -if(TARGET SUNDIALS::idas) - add_subdirectory(Dynamic) - if(GRIDKIT_ENABLE_IPOPT) - add_subdirectory(Optimization) - endif() -endif() diff --git a/Solver/Dynamic/CMakeLists.txt b/Solver/Dynamic/CMakeLists.txt deleted file mode 100644 index 759829967..000000000 --- a/Solver/Dynamic/CMakeLists.txt +++ /dev/null @@ -1,71 +0,0 @@ -# -# 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 -#]] - -gridkit_add_library(solvers_dyn - SOURCES - Ida.cpp - LINK_LIBRARIES - PUBLIC SUNDIALS::nvecserial - PUBLIC SUNDIALS::idas - OUTPUT_NAME - gridkit_solvers_dyn) - diff --git a/Solver/Dynamic/DynamicSolver.hpp b/Solver/Dynamic/DynamicSolver.hpp deleted file mode 100644 index 7094d8a45..000000000 --- a/Solver/Dynamic/DynamicSolver.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * - * 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. - * - */ - - -#ifndef _DYNAMIC_SOLVER_HPP_ -#define _DYNAMIC_SOLVER_HPP_ - -#include "ModelEvaluator.hpp" - -namespace AnalysisManager -{ - template - class DynamicSolver - { - public: - DynamicSolver(ModelLib::ModelEvaluator* model) : model_(model) - { - } - virtual ~DynamicSolver(){} - - ModelLib::ModelEvaluator* getModel() - { - return model_; - } - - protected: - ModelLib::ModelEvaluator* model_; - }; - -} - - -#endif // _DYNAMIC_SOLVER_HPP_ diff --git a/Solver/Dynamic/Ida.cpp b/Solver/Dynamic/Ida.cpp deleted file mode 100644 index c71a8fd07..000000000 --- a/Solver/Dynamic/Ida.cpp +++ /dev/null @@ -1,711 +0,0 @@ -/* - * - * 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 - -// #include -#include /* access to IDADls interface */ -#include - -#include "ModelEvaluator.hpp" -#include "Ida.hpp" - - -namespace AnalysisManager -{ - -namespace Sundials -{ - - template - Ida::Ida(ModelLib::ModelEvaluator* model) : DynamicSolver(model) - { - int retval = 0; - - // Create the SUNDIALS context that all SUNDIALS objects require - retval = SUNContext_Create(NULL, &context_); - checkOutput(retval, "SUNContext"); - solver_ = IDACreate(context_); - tag_ = NULL; - } - - template - Ida::~Ida() - { - } - - template - int Ida::configureSimulation() - { - int retval = 0; - - // Allocate solution vectors - yy_ = N_VNew_Serial(model_->size(), context_); - checkAllocation((void*) yy_, "N_VNew_Serial"); - yp_ = N_VClone(yy_); - checkAllocation((void*) yp_, "N_VClone"); - - // Create vectors to store restart initial condition - yy0_ = N_VClone(yy_); - checkAllocation((void*) yy0_, "N_VClone"); - yp0_ = N_VClone(yy_); - checkAllocation((void*) yp0_, "N_VClone"); - - // Dummy initial time; will be overridden. - const realtype t0 = RCONST(0.0); - - // Allocate and initialize IDA workspace - retval = IDAInit(solver_, this->Residual, t0, yy_, yp_); - checkOutput(retval, "IDAInit"); - - // Set pointer to model data - retval = IDASetUserData(solver_, model_); - checkOutput(retval, "IDASetUserData"); - - // Set tolerances - realtype rtol; - realtype atol; - - model_->setTolerances(rtol, atol); ///< \todo Function name should be "getTolerances"! - retval = IDASStolerances(solver_, rtol, atol); - checkOutput(retval, "IDASStolerances"); - - // Tag differential variables - std::vector& tag = model_->tag(); - if (static_cast(tag.size()) == model_->size()) - { - tag_ = N_VClone(yy_); - checkAllocation((void*) tag_, "N_VClone"); - model_->tagDifferentiable(); - copyVec(tag, tag_); - - retval = IDASetId(solver_, tag_); - checkOutput(retval, "IDASetId"); - retval = IDASetSuppressAlg(solver_, SUNTRUE); - checkOutput(retval, "IDASetSuppressAlg"); - } - - // Set up linear solver - JacobianMat_ = SUNDenseMatrix(model_->size(), model_->size(), context_); - checkAllocation((void*) JacobianMat_, "SUNDenseMatrix"); - - linearSolver_ = SUNLinSol_Dense(yy_, JacobianMat_, context_); - checkAllocation((void*) linearSolver_, "SUNLinSol_Dense"); - - retval = IDASetLinearSolver(solver_, linearSolver_, JacobianMat_); - checkOutput(retval, "IDASetLinearSolver"); - - return retval; - } - - template - int Ida::configureLinearSolver() - { - int retval = 0; - - // Set up linear solver - JacobianMat_ = SUNDenseMatrix(model_->size(), model_->size(), context_); - checkAllocation((void*) JacobianMat_, "SUNDenseMatrix"); - - linearSolver_ = SUNLinSol_Dense(yy_, JacobianMat_, context_); - checkAllocation((void*) linearSolver_, "SUNLinSol_Dense"); - - retval = IDASetLinearSolver(solver_, linearSolver_, JacobianMat_); - checkOutput(retval, "IDASetLinearSolver"); - - return retval; - } - - template - int Ida::getDefaultInitialCondition() - { - model_->initialize(); - - copyVec(model_->y(), yy_); - copyVec(model_->yp(), yp_); - - return 0; - } - - template - int Ida::setIntegrationTime(real_type t_init, real_type t_final, int nout) - { - t_init_ = t_init; - t_final_ = t_final; - nout_ = nout; - return 0; - } - - template - int Ida::initializeSimulation(real_type t0, bool findConsistent) - { - int retval = 0; - - // Need to reinitialize IDA to set to get correct initial conditions - retval = IDAReInit(solver_, t0, yy_, yp_); - checkOutput(retval, "IDAReInit"); - - // Find a consistent set of initial conditions for DAE - if (findConsistent) - { - int initType = IDA_Y_INIT; - - if (tag_) - initType = IDA_YA_YDP_INIT; - - retval = IDACalcIC(solver_, initType, 0.1); - checkOutput(retval, "IDACalcIC"); - } - - return retval; - } - - template - int Ida::runSimulation(real_type tf, int nout) - { - int retval = 0; - int iout = 0; - real_type tret; - real_type dt = tf/nout; - real_type tout = dt; - - /* In loop, call IDASolve, print results, and test for error. - * Break out of loop when NOUT preset output times have been reached. */ - //printOutput(0.0); - while(nout > iout) - { - retval = IDASolve(solver_, tout, &tret, yy_, yp_, IDA_NORMAL); - checkOutput(retval, "IDASolve"); - //printOutput(tout); - - if (retval == IDA_SUCCESS) - { - ++iout; - tout += dt; - } - } - //std::cout << "\n"; - return retval; - } - - template - int Ida::deleteSimulation() - { - IDAFree(&solver_); - SUNLinSolFree(linearSolver_); - N_VDestroy(yy_); - N_VDestroy(yp_); - return 0; - } - - - template - int Ida::configureQuadrature() - { - int retval = 0; - - // Create and initialize quadratures - q_ = N_VNew_Serial(model_->size_quad(), context_); - checkAllocation((void*) q_, "N_VNew_Serial"); - - // Set integrand function and allocate quadrature workspace - retval = IDAQuadInit(solver_, this->Integrand, q_); - checkOutput(retval, "IDAQuadInit"); - - // Set tolerances and error control for quadratures - real_type rtol, atol; - model_->setTolerances(rtol, atol); - - // Set tolerances for quadrature stricter than for integration - retval = IDAQuadSStolerances(solver_, rtol*0.1, atol*0.1); - checkOutput(retval, "IDAQuadSStolerances"); - - // Include quadrature in eror checking - retval = IDASetQuadErrCon(solver_, SUNTRUE); - checkOutput(retval, "IDASetQuadErrCon"); - - return retval; - } - - - template - int Ida::initializeQuadrature() - { - int retval = 0; - - // Set all quadratures to zero - N_VConst(RCONST(0.0), q_); - - // Initialize quadratures - retval = IDAQuadReInit(solver_, q_); - checkOutput(retval, "IDAQuadInit"); - - return retval; - } - - - template - int Ida::runSimulationQuadrature(real_type tf, int nout) - { - int retval = 0; - real_type tret; - - //std::cout << "Forward integration for initial value problem ... \n"; - - real_type dt = tf/nout; - real_type tout = dt; - //printOutput(0.0); - //printSpecial(0.0, yy_); - for(int i = 0; i < nout; ++i) - { - retval = IDASolve(solver_, tout, &tret, yy_, yp_, IDA_NORMAL); - checkOutput(retval, "IDASolve"); - //printSpecial(tout, yy_); - //printOutput(tout); - - if (retval == IDA_SUCCESS) - { - tout += dt; - } - - retval = IDAGetQuad(solver_, &tret, q_); - checkOutput(retval, "IDAGetQuad"); - } - - return retval; - } - - - template - int Ida::deleteQuadrature() - { - IDAQuadFree(solver_); - N_VDestroy(q_); - - return 0; - } - - - template - int Ida::configureAdjoint() - { - // Allocate adjoint vector, derivatives and quadrature - yyB_ = N_VNew_Serial(model_->size(), context_); - checkAllocation((void*) yyB_, "N_VNew_Serial"); - - ypB_ = N_VClone(yyB_); - checkAllocation((void*) ypB_, "N_VClone"); - - qB_ = N_VNew_Serial(model_->size_opt(), context_); - checkAllocation((void*) qB_, "N_VNew_Serial"); - - return 0; - } - - template - int Ida::initializeAdjoint(IdxT steps) - { - int retval = 0; - - // Create adjoint workspace - retval = IDAAdjInit(solver_, steps, IDA_HERMITE); - checkOutput(retval, "IDAAdjInit"); - - return retval; - } - - template - int Ida::initializeBackwardSimulation(real_type tf) - { - int retval = 0; - realtype rtol; - realtype atol; - - model_->initializeAdjoint(); - - copyVec(model_->yB(), yyB_); - copyVec(model_->ypB(), ypB_); - N_VConst(0.0, qB_); - - retval = IDACreateB(solver_, &backwardID_); - checkOutput(retval, "IDACreateB"); - - // IDAInitB must be called after forward simulation run. - retval = IDAInitB(solver_, backwardID_, this->adjointResidual, tf, yyB_, ypB_); - checkOutput(retval, "IDAInitB"); - - model_->setTolerances(rtol, atol); - retval = IDASStolerancesB(solver_, backwardID_, rtol, atol); - checkOutput(retval, "IDASStolerancesB"); - - retval = IDASetUserDataB(solver_, backwardID_, model_); - checkOutput(retval, "IDASetUserDataB"); - - /// \todo Need to set max number of steps based on user input! - retval = IDASetMaxNumStepsB(solver_, backwardID_, 2000); - checkOutput(retval, "IDASetMaxNumSteps"); - - // Set up linear solver - JacobianMatB_ = SUNDenseMatrix(model_->size(), model_->size(), context_); - checkAllocation((void*) JacobianMatB_, "SUNDenseMatrix"); - - linearSolverB_ = SUNLinSol_Dense(yyB_, JacobianMatB_, context_); - checkAllocation((void*) linearSolverB_, "SUNLinSol_Dense"); - - retval = IDASetLinearSolverB(solver_, backwardID_, linearSolverB_, JacobianMatB_); - checkOutput(retval, "IDASetLinearSolverB"); - - - // Also reinitialize quadratures. - retval = IDAQuadInitB(solver_, backwardID_, this->adjointIntegrand, qB_); - checkOutput(retval, "IDAQuadInitB"); - - //retval = IDAQuadSStolerancesB(solver_, backwardID_, rtol*1.1, atol*1.1); - retval = IDAQuadSStolerancesB(solver_, backwardID_, rtol*0.1, atol*0.1); - checkOutput(retval, "IDAQuadSStolerancesB"); - - // Include quadratures in error control - retval = IDASetQuadErrConB(solver_, backwardID_, SUNTRUE); - checkOutput(retval, "IDASetQuadErrConB"); - - - return retval; - } - - template - int Ida::configureLinearSolverBackward() - { - int retval = 0; - - // Create Jacobian matrix - JacobianMatB_ = SUNDenseMatrix(model_->size(), model_->size(), context_); - checkAllocation((void*) JacobianMatB_, "SUNDenseMatrix"); - - // Create linear solver - linearSolverB_ = SUNLinSol_Dense(yyB_, JacobianMatB_, context_); - checkAllocation((void*) linearSolverB_, "SUNLinSol_Dense"); - - // Attach linear solver to IDA - retval = IDASetLinearSolverB(solver_, backwardID_, linearSolverB_, JacobianMatB_); - checkOutput(retval, "IDASetLinearSolverB"); - - return retval; - } - - template - int Ida::runForwardSimulation(real_type tf, int nout) - { - int retval = 0; - int ncheck; - real_type time; - - //std::cout << "Forward integration for adjoint analysis ... \n"; - - real_type dt = tf/nout; - real_type tout = dt; - for(int i = 0; i < nout; ++i) - { - retval = IDASolveF(solver_, tout, &time, yy_, yp_, IDA_NORMAL, &ncheck); - checkOutput(retval, "IDASolveF"); - - if (retval == IDA_SUCCESS) - { - tout += dt; - } - - retval = IDAGetQuad(solver_, &time, q_); - checkOutput(retval, "IDASolve"); - } - - return retval; - } - - template - int Ida::runBackwardSimulation(real_type t_init) - { - int retval = 0; - long int nstB; - real_type time; - - //std::cout << "Backward integration for adjoint analysis ... "; - - retval = IDASolveB(solver_, t_init, IDA_NORMAL); - checkOutput(retval, "IDASolveB"); - - IDAGetNumSteps(IDAGetAdjIDABmem(solver_, backwardID_), &nstB); - //std::cout << "done ( nst = " << nstB << " )\n"; - - retval = IDAGetB(solver_, backwardID_, &time, yyB_, ypB_); - checkOutput(retval, "IDAGetB"); - - retval = IDAGetQuadB(solver_, backwardID_, &time, qB_); - checkOutput(retval, "IDAGetQuadB"); - - return retval; - } - - template - int Ida::deleteAdjoint() - { - IDAAdjFree(solver_); - return 0; - } - - template - int Ida::Residual(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data) - { - ModelLib::ModelEvaluator* model = static_cast*>(user_data); - - model->updateTime(tres, 0.0); - copyVec(yy, model->y()); - copyVec(yp, model->yp()); - - model->evaluateResidual(); - const std::vector& f = model->getResidual(); - copyVec(f, rr); - - return 0; - } - - - template - int Ida::Integrand(realtype tt, N_Vector yy, N_Vector yp, N_Vector rhsQ, void *user_data) - { - ModelLib::ModelEvaluator* model = static_cast*>(user_data); - - model->updateTime(tt, 0.0); - copyVec(yy, model->y()); - copyVec(yp, model->yp()); - - model->evaluateIntegrand(); - const std::vector& g = model->getIntegrand(); - copyVec(g, rhsQ); - - return 0; - } - - template - int Ida::adjointResidual(realtype tt, N_Vector yy, N_Vector yp, N_Vector yyB, N_Vector ypB, N_Vector rrB, void *user_data) - { - ModelLib::ModelEvaluator* model = static_cast*>(user_data); - - model->updateTime(tt, 0.0); - copyVec(yy, model->y()); - copyVec(yp, model->yp()); - copyVec(yyB, model->yB()); - copyVec(ypB, model->ypB()); - - model->evaluateAdjointResidual(); - const std::vector& fB = model->getAdjointResidual(); - copyVec(fB, rrB); - - return 0; - } - - - template - int Ida::adjointIntegrand(realtype tt, N_Vector yy, N_Vector yp, N_Vector yyB, N_Vector ypB, N_Vector rhsQB, void *user_data) - { - ModelLib::ModelEvaluator* model = static_cast*>(user_data); - - model->updateTime(tt, 0.0); - copyVec(yy, model->y()); - copyVec(yp, model->yp()); - copyVec(yyB, model->yB()); - copyVec(ypB, model->ypB()); - - model->evaluateAdjointIntegrand(); - const std::vector& gB = model->getAdjointIntegrand(); - copyVec(gB, rhsQB); - - return 0; - } - - - template - void Ida::copyVec(const N_Vector x, std::vector< ScalarT >& y) - { - const ScalarT* xdata = NV_DATA_S(x); - for(unsigned int i = 0; i < y.size(); ++i) - { - y[i] = xdata[i]; - } - } - - - template - void Ida::copyVec(const std::vector< ScalarT >& x, N_Vector y) - { - ScalarT* ydata = NV_DATA_S(y); - for(unsigned int i = 0; i < x.size(); ++i) - { - ydata[i] = x[i]; - } - } - - template - void Ida::copyVec(const std::vector< bool >& x, N_Vector y) - { - ScalarT* ydata = NV_DATA_S(y); - for(unsigned int i = 0; i < x.size(); ++i) - { - if (x[i]) - ydata[i] = 1.0; - else - ydata[i] = 0.0; - } - } - - - template - void Ida::printOutput(realtype t) - { - realtype *yval = N_VGetArrayPointer_Serial(yy_); - realtype *ypval = N_VGetArrayPointer_Serial(yp_); - - std::cout << std::setprecision(5) << std::setw(7) << t << " "; - for (IdxT i = 0; i < model_->size(); ++i) - { - std::cout << yval[i] << " "; - } - for (IdxT i = 0; i < model_->size(); ++i) - { - std::cout << ypval[i] << " "; - } - std::cout << "\n"; - } - - template - void Ida::printSpecial(realtype t, N_Vector y) - { - realtype *yval = N_VGetArrayPointer_Serial(y); - IdxT N = static_cast(N_VGetLength_Serial(y)); - std::cout << "{"; - std::cout << std::setprecision(5) << std::setw(7) << t; - for (IdxT i = 0; i < N; ++i) - { - std::cout << ", " << yval[i]; - } - std::cout << "},\n"; - } - - template - void Ida::printFinalStats() - { - int retval = 0; - void* mem = solver_; - long int nst; - long int nre; - long int nje; - long int nni; - long int netf; - long int ncfn; - - retval = IDAGetNumSteps(mem, &nst); - checkOutput(retval, "IDAGetNumSteps"); - retval = IDAGetNumResEvals(mem, &nre); - checkOutput(retval, "IDAGetNumResEvals"); - retval = IDAGetNumJacEvals(mem, &nje); - checkOutput(retval, "IDAGetNumJacEvals"); - retval = IDAGetNumNonlinSolvIters(mem, &nni); - checkOutput(retval, "IDAGetNumNonlinSolvIters"); - retval = IDAGetNumErrTestFails(mem, &netf); - checkOutput(retval, "IDAGetNumErrTestFails"); - retval = IDAGetNumNonlinSolvConvFails(mem, &ncfn); - checkOutput(retval, "IDAGetNumNonlinSolvConvFails"); - - // std::cout << "\nFinal Run Statistics: \n\n"; - std::cout << "Number of steps = " << nst << "\n"; - std::cout << "Number of residual evaluations = " << nre << "\n"; - //std::cout << "Number of Jacobian evaluations = " << nje << "\n"; - std::cout << "Number of nonlinear iterations = " << nni << "\n"; - std::cout << "Number of error test failures = " << netf << "\n"; - std::cout << "Number of nonlinear conv. failures = " << ncfn << "\n"; - } - - - template - void Ida::checkAllocation(void* v, const char* functionName) - { - if (v == NULL) - { - std::cerr << "\nERROR: Function " << functionName << " failed -- returned NULL pointer!\n\n"; - throw SundialsException(); - } - } - - template - void Ida::checkOutput(int retval, const char* functionName) - { - if (retval < 0) - { - std::cerr << "\nERROR: Function " << functionName << " failed with flag " << retval << "!\n\n"; - throw SundialsException(); - } - } - - // Compiler will prevent building modules with data type incompatible with realtype - template class Ida; - template class Ida; - template class Ida; - -} // namespace Sundials -} // namespace AnalysisManager diff --git a/Solver/Dynamic/Ida.hpp b/Solver/Dynamic/Ida.hpp deleted file mode 100644 index 3fa3368c9..000000000 --- a/Solver/Dynamic/Ida.hpp +++ /dev/null @@ -1,237 +0,0 @@ -/* - * - * 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. - * - */ - - -#ifndef _IDA_HPP_ -#define _IDA_HPP_ - -#include -#include -#include -#include /* access to sparse SUNMatrix */ -// #include /* access to KLU linear solver */ -#include /* access to dense linear solver */ - -#include "ModelEvaluator.hpp" -#include "DynamicSolver.hpp" - -namespace AnalysisManager -{ - namespace Sundials - { - template - class Ida : public DynamicSolver - { - using DynamicSolver::model_; - - typedef typename GridKit::ScalarTraits::real_type real_type; - - public: - Ida(ModelLib::ModelEvaluator* model); - ~Ida(); - - int configureSimulation(); - int configureLinearSolver(); - int getDefaultInitialCondition(); - int setIntegrationTime(real_type t_init, real_type t_final, int nout); - int initializeSimulation(real_type t0, bool findConsistent=false); - int runSimulation(real_type tf, int nout=1); - int deleteSimulation(); - - int configureQuadrature(); - int initializeQuadrature(); - int runSimulationQuadrature(real_type tf, int nout=1); - int deleteQuadrature(); - - int configureAdjoint(); - int configureLinearSolverBackward(); - int initializeAdjoint(IdxT steps = 100); - int initializeBackwardSimulation(real_type tf); - int runForwardSimulation(real_type tf, int nout=1); - int runBackwardSimulation(real_type t0); - int deleteAdjoint(); - - - int saveInitialCondition() - { - N_VScale(1.0, yy_, yy0_); - N_VScale(1.0, yp_, yp0_); - return 0; - } - - int getSavedInitialCondition() - { - N_VScale(1.0, yy0_, yy_); - N_VScale(1.0, yp0_, yp_); - return 0; - } - - real_type getInitialTime() - { - return t_init_; - } - - real_type getFinalTime() - { - return t_final_; - } - - int getNumberOutputTimes() - { - return nout_; - } - - const real_type* getIntegral() const - { - return NV_DATA_S(q_); - } - - real_type* getIntegral() - { - return NV_DATA_S(q_); - } - - const real_type* getAdjointIntegral() const - { - return NV_DATA_S(qB_); - } - - real_type* getAdjointIntegral() - { - return NV_DATA_S(qB_); - } - - void printOutput(realtype t); - void printSpecial(realtype t, N_Vector x); - void printFinalStats(); - - private: - static int Residual(realtype t, - N_Vector yy, N_Vector yp, - N_Vector rr, void *user_data); - - static int Integrand(realtype t, - N_Vector yy, N_Vector yp, - N_Vector rhsQ, void *user_data); - - static int adjointResidual(realtype t, - N_Vector yy, N_Vector yp, - N_Vector yyB, N_Vector ypB, - N_Vector rrB, void *user_data); - - static int adjointIntegrand(realtype t, - N_Vector yy, N_Vector yp, - N_Vector yyB, N_Vector ypB, - N_Vector rhsQB, void *user_data); - - private: - void* solver_; - SUNContext context_; - SUNMatrix JacobianMat_; - SUNMatrix JacobianMatB_; - SUNLinearSolver linearSolver_; - SUNLinearSolver linearSolverB_; - - real_type t_init_; - real_type t_final_; - int nout_; ///< Number of integration outputs - - N_Vector yy_; ///< Solution vector - N_Vector yp_; ///< Solution derivatives vector - N_Vector tag_; ///< Tags differential variables - N_Vector q_; ///< Integrand vector - - N_Vector yy0_; ///< Storage for initial values - N_Vector yp0_; ///< Storage for initial derivatives - - N_Vector yyB_; ///< Adjoint solution vector - N_Vector ypB_; ///< Adjoint solution derivatives vector - N_Vector qB_; ///< Backward integrand vector - - int backwardID_; - - private: - //static void copyMat(ModelEvaluator::Mat& J, SlsMat Jida); - static void copyVec(const N_Vector x, std::vector& y); - static void copyVec(const std::vector& x, N_Vector y); - static void copyVec(const std::vector& x, N_Vector y); - - //int check_flag(void *flagvalue, const char *funcname, int opt); - inline void checkAllocation(void* v, const char* functionName); - inline void checkOutput(int retval, const char* functionName); - - }; - - /// Simple exception to use within Ida class. - class SundialsException : public std::exception - { - virtual const char* what() const throw() - { - return "Method in Ida class failed!\n"; - } - }; - - - } // namespace Sundials - - -} // namespace AnalysisManager - - -#endif // _IDA_HPP_ diff --git a/Solver/Optimization/CMakeLists.txt b/Solver/Optimization/CMakeLists.txt deleted file mode 100644 index 756dfa572..000000000 --- a/Solver/Optimization/CMakeLists.txt +++ /dev/null @@ -1,72 +0,0 @@ -# -# 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 -#]] - -gridkit_add_library(solvers_opt - SOURCES - DynamicObjective.cpp - DynamicConstraint.cpp - LINK_LIBRARIES - PUBLIC IPOPT - PUBLIC GRIDKIT::solvers_dyn - OUTPUT_NAME - gridkit_solvers_opt) - diff --git a/Solver/Optimization/DynamicConstraint.cpp b/Solver/Optimization/DynamicConstraint.cpp deleted file mode 100644 index 486570e3b..000000000 --- a/Solver/Optimization/DynamicConstraint.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/* - * - * 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 - -#include "DynamicConstraint.hpp" - -namespace AnalysisManager { -namespace IpoptInterface { - -template -DynamicConstraint::DynamicConstraint(Sundials::Ida* integrator) - : OptimizationSolver(integrator), - t_init_(integrator_->getInitialTime()), - t_final_(integrator_->getFinalTime()), - nout_(integrator_->getNumberOutputTimes()) -{ - model_ = integrator_->getModel(); -} - -template -DynamicConstraint::~DynamicConstraint() -{ -} - - -template -bool DynamicConstraint::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g, - Index& nnz_h_lag, IndexStyleEnum& index_style) -{ - // This code handles one objective function - assert(model_->size_quad() == 1); - - // Number of parameters is size of the system plus 1 fictitious parameter - // to store the objective value. - n = model_->size_opt() + 1; - - // There is one constraint - m = 1; - - // Jacobian is a dense row matrix of length n+1. - nnz_jac_g = model_->size_opt() + 1; - - // Using numerical Hessian. - nnz_h_lag = 0; - - // Use the C index style (0-based) for row/column entries - index_style = C_STYLE; - - return true; -} - - -template -bool DynamicConstraint::get_bounds_info(Index n, Number* x_l, Number* x_u, - Index m, Number* g_l, Number* g_u) -{ - // Check if sizes are set correctly - assert(n == (Index) (model_->size_opt() + 1)); - assert(m == 1); - - // Get boundaries for the optimization parameters - for(IdxT i = 0; i < model_->size_opt(); ++i) - { - x_l[i] = model_->param_lo()[i]; - x_u[i] = model_->param_up()[i]; - } - - // No boundaries for fictitious parameter x[n] - x_l[model_->size_opt()] = -1e20; - x_u[model_->size_opt()] = +1e20; - - // Set constraint g[0] to be equality constraint g[0] = 0 - g_l[0] = 0.0; - g_u[0] = 0.0; - - return true; -} - - -template -bool DynamicConstraint::get_starting_point(Index n, bool init_x, Number* x, - bool init_z, Number* z_L, Number* z_U, - Index m, bool init_lambda, - Number* lambda) -{ - // Only initial values for x provided. - assert(init_x == true); - assert(init_z == false); - assert(init_lambda == false); - - // Initialize optimization parameters x - for(IdxT i = 0; i < model_->size_opt(); ++i) - x[i] = model_->param()[i]; - - // Initialize fictitious parameter x[n-1] to zero - x[model_->size_opt()] = 0.0; - - return true; -} - - -template -bool DynamicConstraint::eval_f(Index n, const Number* x, bool new_x, Number& obj_value) -{ - // Set objective to fictitious optimization parameter x[n-1] - obj_value = x[model_->size_opt()]; - - return true; -} - - -template -bool DynamicConstraint::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f) -{ - // Objective function equals to the fictitious parameter x[n-1]. - // Gradient, then assumes the simple form: - for(IdxT i = 0; i < model_->size_opt(); ++i) - grad_f[i] = 0.0; - grad_f[model_->size_opt()] = 1.0; - - return true; -} - - -template -bool DynamicConstraint::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g) -{ - // Update optimization parameters - for(IdxT i = 0; i < model_->size_opt(); ++i) - { - model_->param()[i] = x[i]; - //std::cout << "x[" << i << "] = " << x[i] << "\n"; - } - - // Evaluate objective function - integrator_->getSavedInitialCondition(); - integrator_->initializeSimulation(t_init_); - integrator_->initializeQuadrature(); - - int status = 0; - status = integrator_->runSimulationQuadrature(t_final_, nout_); - if (status) - { - std::cerr << "Integration failed when using Pm = " << x[0] << "\n"; - return false; - } - - // For now assumes only one forward integrand and multiple optimization parameters. - g[0] = (integrator_->getIntegral())[0] - x[model_->size_opt()]; - //std::cout << "constraint:" << g[0] << std::endl; - return true; -} - - -template -bool DynamicConstraint::eval_jac_g(Index n, const Number* x, bool new_x, - Index m, Index nele_jac, Index* iRow, Index *jCol, - Number* values) -{ - // Set Jacobian sparsity pattern ... - if(!values) - { - for(IdxT i = 0; i < model_->size_opt(); ++i) - { - iRow[i] = 0; - jCol[i] = i; - } - iRow[model_->size_opt()] = 0; - jCol[model_->size_opt()] = model_->size_opt(); - } - // ... or compute Jacobian derivatives - else - { - // Update optimization parameters - for(IdxT i = 0; i < model_->size_opt(); ++i) - model_->param()[i] = x[i]; - - // evaluate the gradient of the objective function grad_{x} f(x) - // This is creating and deleting adjoint system for each iteration! - // Currently there is no more efficient solution. - integrator_->initializeAdjoint(); - - integrator_->getSavedInitialCondition(); - integrator_->initializeSimulation(t_init_); - integrator_->initializeQuadrature(); - - int status = 0; - status = integrator_->runForwardSimulation(t_final_, nout_); - if (status) - { - std::cerr << "Forward integration for adjoint solution failed when using Pm = " << x[0] << "\n"; - return false; - } - - integrator_->initializeBackwardSimulation(t_final_); - - status = integrator_->runBackwardSimulation(t_init_); - if (status) - { - std::cerr << "Backward integration for adjoint solution failed when using Pm = " << x[0] << "\n"; - return false; - } - - // For now assumes only one forward integrand and multiple optimization parameters. - for(IdxT i = 0; i < model_->size_opt(); ++i) - { - values[i] = -((integrator_->getAdjointIntegral())[i]); - } - values[model_->size_opt()] = -1.0; - - integrator_->deleteAdjoint(); - } - return true; -} - - -template -bool DynamicConstraint::eval_h(Index n, const Number* x, bool new_x, - Number obj_factor, Index m, const Number* lambda, - bool new_lambda, Index nele_hess, Index* iRow, - Index* jCol, Number* values) -{ - return false; -} - - -template -void DynamicConstraint::finalize_solution(SolverReturn status, - Index n, const Number* x, const Number* z_L, const Number* z_U, - Index m, const Number* g, const Number* lambda, - Number obj_value, - const IpoptData* ip_data, - IpoptCalculatedQuantities* ip_cq) -{ - -} - - - - -template class DynamicConstraint; -template class DynamicConstraint; - -} // namespace IpoptInterface -} // namespace AnalysisManager diff --git a/Solver/Optimization/DynamicConstraint.hpp b/Solver/Optimization/DynamicConstraint.hpp deleted file mode 100644 index 234ebcfb7..000000000 --- a/Solver/Optimization/DynamicConstraint.hpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * - * 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. - * - */ - - - -#ifndef _IPOPT_DYNAMIC_CONSTRAINT_HPP_ -#define _IPOPT_DYNAMIC_CONSTRAINT_HPP_ - -#include -#include "OptimizationSolver.hpp" - -namespace AnalysisManager { - - namespace IpoptInterface { - - /** - * Implementation of Ipopt's pure virtual TNLP class. - * - * TNLP defines Ipopt's interface to the model. This is in fact - * the model evaluator interface to Ipopt. In this case however, - * the model evaluator calls dynamic solver to compute the objective - * and the gradient. - * - * \note This clas is based on Cosmin's reformulation of the dynamic - * constrained optimization problem. For now it is hard-wired to - * 1-parameter optimization problems. - * - */ - template - class DynamicConstraint : public Ipopt::TNLP, public OptimizationSolver - { - using OptimizationSolver::integrator_; - using OptimizationSolver::model_; - - typedef typename GridKit::ScalarTraits::real_type real_type; - - typedef Ipopt::Index Index; - typedef Ipopt::Number Number; - typedef Ipopt::SolverReturn SolverReturn; - typedef Ipopt::IpoptCalculatedQuantities IpoptCalculatedQuantities; - typedef Ipopt::IpoptData IpoptData; - - public: - DynamicConstraint(Sundials::Ida* integrator); - virtual ~DynamicConstraint(); - - /// Returns sizes of the model components - virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g, - Index& nnz_h_lag, IndexStyleEnum& index_style); - - /// Returns problem bounds - virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u, - Index m, Number* g_l, Number* g_u); - - /// Initialize optimization - virtual bool get_starting_point(Index n, bool init_x, Number* x, - bool init_z, Number* z_L, Number* z_U, - Index m, bool init_lambda, - Number* lambda); - - /// Evaluate objective - virtual bool eval_f(Index n, const Number* x, bool new_x, Number& obj_value); - - /// Evaluate objective gradient - virtual bool eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f); - - /// Evaluate constraint residuals (not used here) - virtual bool eval_g(Index n, const Number* x, bool new_x, Index m, Number* g); - - /// Evaluate Jacobian (not used here) - virtual bool eval_jac_g(Index n, const Number* x, bool new_x, - Index m, Index nele_jac, Index* iRow, Index *jCol, - Number* values); - - /// Evaluate Hessian (have Ipopt estimate Hessian) - virtual bool eval_h(Index n, const Number* x, bool new_x, - Number obj_factor, Index m, const Number* lambda, - bool new_lambda, Index nele_hess, Index* iRow, - Index* jCol, Number* values); - - /// Postprocessing of the results (not used here) - virtual void finalize_solution(SolverReturn status, - Index n, const Number* x, const Number* z_L, const Number* z_U, - Index m, const Number* g, const Number* lambda, - Number obj_value, - const IpoptData* ip_data, - IpoptCalculatedQuantities* ip_cq); - private: - real_type t_init_; - real_type t_final_; - int nout_; - }; - - } // namespace IpoptInterface -} // namespace AnalysisManager - -#endif // _IPOPT_DYNAMIC_CONSTRAINT_HPP_ diff --git a/Solver/Optimization/DynamicObjective.cpp b/Solver/Optimization/DynamicObjective.cpp deleted file mode 100644 index 04396d0cf..000000000 --- a/Solver/Optimization/DynamicObjective.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* - * - * 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 - -#include "DynamicObjective.hpp" - -namespace AnalysisManager { -namespace IpoptInterface { - -template -DynamicObjective::DynamicObjective(Sundials::Ida* integrator) - : OptimizationSolver(integrator), - t_init_(integrator_->getInitialTime()), - t_final_(integrator_->getFinalTime()), - nout_(integrator_->getNumberOutputTimes()) -{ - model_ = integrator_->getModel(); -} - -template -DynamicObjective::~DynamicObjective() -{ -} - - -template -bool DynamicObjective::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g, - Index& nnz_h_lag, IndexStyleEnum& index_style) -{ - // This code handles one objective function - assert(model_->size_quad() == 1); - - // Number of optimization variables. - n = model_->size_opt(); - - // There are no constraints - m = 0; - - // No constraints, empty Jacobian. This is only temporary. - nnz_jac_g = 0; - - // Using numerical Hessian. - nnz_h_lag = 0; - - // Use the C index style (0-based) for row/column entries - index_style = C_STYLE; - - return true; -} - - -template -bool DynamicObjective::get_bounds_info(Index n, Number* x_l, Number* x_u, - Index m, Number* g_l, Number* g_u) -{ - // Check if sizes are set correctly - assert(n == (Index) model_->size_opt()); - assert(m == 0); - - // Get boundaries for the optimization parameters - for(IdxT i = 0; i < model_->size_opt(); ++i) - { - x_l[i] = model_->param_lo()[i]; - x_u[i] = model_->param_up()[i]; - } - - return true; -} - - -template -bool DynamicObjective::get_starting_point(Index n, bool init_x, Number* x, - bool init_z, Number* z_L, Number* z_U, - Index m, bool init_lambda, - Number* lambda) -{ - // Only initial values for x provided. - assert(init_x == true); - assert(init_z == false); - assert(init_lambda == false); - - // Initialize optimization parameters x - for(IdxT i = 0; i < model_->size_opt(); ++i) - x[i] = model_->param()[i]; - - return true; -} - - -template -bool DynamicObjective::eval_f(Index n, const Number* x, bool new_x, Number& obj_value) -{ - // Update optimization parameters - for(IdxT i = 0; i < model_->size_opt(); ++i) - model_->param()[i] = x[i]; - - // Evaluate objective function - integrator_->getSavedInitialCondition(); - integrator_->initializeSimulation(t_init_); - integrator_->initializeQuadrature(); - integrator_->runSimulationQuadrature(t_final_, nout_); - - // Assuming objective function is given as the integral (quadrature) 0 - obj_value = (integrator_->getIntegral())[0]; - - return true; -} - - -template -bool DynamicObjective::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f) -{ - assert(model_->size_opt() == static_cast(n)); - // Update optimization parameters - for(IdxT i = 0; i < model_->size_opt(); ++i) - model_->param()[i] = x[i]; - - // evaluate the gradient of the objective function grad_{x} f(x) - // This is creating and deleting adjoint system for each iteration! - // Currently there is no more efficient solution. - integrator_->initializeAdjoint(); - - integrator_->getSavedInitialCondition(); - integrator_->initializeSimulation(t_init_); - integrator_->initializeQuadrature(); - integrator_->runForwardSimulation(t_final_, nout_); - - integrator_->initializeBackwardSimulation(t_final_); - integrator_->runBackwardSimulation(t_init_); - - // For now assumes only one forward integrand and multiple optimization parameters. - for(IdxT i = 0; i < model_->size_opt(); ++i) - grad_f[i] = -((integrator_->getAdjointIntegral())[i]); - - integrator_->deleteAdjoint(); - - return true; -} - - -template -bool DynamicObjective::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g) -{ - return false; -} - - -template -bool DynamicObjective::eval_jac_g(Index n, const Number* x, bool new_x, - Index m, Index nele_jac, Index* iRow, Index *jCol, - Number* values) -{ - return false; -} - - -template -bool DynamicObjective::eval_h(Index n, const Number* x, bool new_x, - Number obj_factor, Index m, const Number* lambda, - bool new_lambda, Index nele_hess, Index* iRow, - Index* jCol, Number* values) -{ - return false; -} - - -template -void DynamicObjective::finalize_solution(SolverReturn status, - Index n, const Number* x, const Number* z_L, const Number* z_U, - Index m, const Number* g, const Number* lambda, - Number obj_value, - const IpoptData* ip_data, - IpoptCalculatedQuantities* ip_cq) -{ - -} - - - - -template class DynamicObjective; -template class DynamicObjective; - -} // namespace IpoptInterface -} // namespace AnalysisManager diff --git a/Solver/Optimization/DynamicObjective.hpp b/Solver/Optimization/DynamicObjective.hpp deleted file mode 100644 index d2999730a..000000000 --- a/Solver/Optimization/DynamicObjective.hpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - * - * 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. - * - */ - - - -#ifndef _IPOPT_DYNAMIC_OBJECTIVE_HPP_ -#define _IPOPT_DYNAMIC_OBJECTIVE_HPP_ - -#include -#include "OptimizationSolver.hpp" - -namespace AnalysisManager { - - namespace IpoptInterface { - - /** - * Implementation of Ipopt's pure virtual TNLP class. - * - * TNLP defines Ipopt's interface to the model. This is in fact - * the model evaluator interface to Ipopt. In this case however, - * the model evaluator calls dynamic solver to compute the objective - * and the gradient. - * - */ - template - class DynamicObjective : public Ipopt::TNLP, public OptimizationSolver - { - using OptimizationSolver::integrator_; - using OptimizationSolver::model_; - - typedef typename GridKit::ScalarTraits::real_type real_type; - - typedef Ipopt::Index Index; - typedef Ipopt::Number Number; - typedef Ipopt::SolverReturn SolverReturn; - typedef Ipopt::IpoptCalculatedQuantities IpoptCalculatedQuantities; - typedef Ipopt::IpoptData IpoptData; - - public: - DynamicObjective(Sundials::Ida* integrator); - virtual ~DynamicObjective(); - - /// Returns sizes of the model components - virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g, - Index& nnz_h_lag, IndexStyleEnum& index_style); - - /// Returns problem bounds - virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u, - Index m, Number* g_l, Number* g_u); - - /// Initialize optimization - virtual bool get_starting_point(Index n, bool init_x, Number* x, - bool init_z, Number* z_L, Number* z_U, - Index m, bool init_lambda, - Number* lambda); - - /// Evaluate objective - virtual bool eval_f(Index n, const Number* x, bool new_x, Number& obj_value); - - /// Evaluate objective gradient - virtual bool eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f); - - /// Evaluate constraint residuals (not used here) - virtual bool eval_g(Index n, const Number* x, bool new_x, Index m, Number* g); - - /// Evaluate Jacobian (not used here) - virtual bool eval_jac_g(Index n, const Number* x, bool new_x, - Index m, Index nele_jac, Index* iRow, Index *jCol, - Number* values); - - /// Evaluate Hessian (have Ipopt estimate Hessian) - virtual bool eval_h(Index n, const Number* x, bool new_x, - Number obj_factor, Index m, const Number* lambda, - bool new_lambda, Index nele_hess, Index* iRow, - Index* jCol, Number* values); - - /// Postprocessing of the results (not used here) - virtual void finalize_solution(SolverReturn status, - Index n, const Number* x, const Number* z_L, const Number* z_U, - Index m, const Number* g, const Number* lambda, - Number obj_value, - const IpoptData* ip_data, - IpoptCalculatedQuantities* ip_cq); - private: - real_type t_init_; - real_type t_final_; - int nout_; - }; - - } // namespace IpoptInterface -} // namespace AnalysisManager - -#endif // _IPOPT_DYNAMIC_OBJECTIVE_HPP_ diff --git a/Solver/Optimization/OptimizationSolver.hpp b/Solver/Optimization/OptimizationSolver.hpp deleted file mode 100644 index 4da398145..000000000 --- a/Solver/Optimization/OptimizationSolver.hpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _OPTIMIZATION_SOLVER_HPP_ -#define _OPTIMIZATION_SOLVER_HPP_ - -#include "ModelEvaluator.hpp" -#include - -namespace AnalysisManager -{ - template - class DynamicSolver; - - template - class OptimizationSolver - { - public: - OptimizationSolver() - { - } - - OptimizationSolver(Sundials::Ida* integrator) : integrator_(integrator) - { - } - - virtual ~OptimizationSolver(){} - - protected: - ModelLib::ModelEvaluator* model_; - Sundials::Ida* integrator_; - }; - -} - - -#endif // _OPTIMIZATION_SOLVER_HPP_ diff --git a/Solver/SteadyState/CMakeLists.txt b/Solver/SteadyState/CMakeLists.txt deleted file mode 100644 index 3d71c5a19..000000000 --- a/Solver/SteadyState/CMakeLists.txt +++ /dev/null @@ -1,70 +0,0 @@ -# -# 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 -#]] - -gridkit_add_library(solvers_steady - SOURCES - Kinsol.cpp - LINK_LIBRARIES - PUBLIC SUNDIALS::kinsol - OUTPUT_NAME - gridkit_solvers_steady) - diff --git a/Solver/SteadyState/Kinsol.cpp b/Solver/SteadyState/Kinsol.cpp deleted file mode 100644 index 9c00c2afc..000000000 --- a/Solver/SteadyState/Kinsol.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/* - * - * 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. - * - */ - -/** - * @file Kinsol.cpp - * @author Slaven Peles - * - * Contains definition of interface to KINSOL nonlinear solver from - * SUNDIALS library. - * - */ - -#include -#include - -#include // access to KINSOL func., consts. -#include // access to serial N_Vector -#include // access to dense SUNMatrix -#include // access to dense SUNLinearSolver - -#include "ModelEvaluator.hpp" -#include "Kinsol.hpp" - - -namespace AnalysisManager -{ - -namespace Sundials -{ - - template - Kinsol::Kinsol(ModelLib::ModelEvaluator* model) - : SteadyStateSolver(model) - { - int retval = 0; - - // Create the SUNDIALS context that all SUNDIALS objects require - retval = SUNContext_Create(NULL, &context_); - checkOutput(retval, "SUNContext"); - - solver_ = KINCreate(context_); - tag_ = NULL; - } - - template - Kinsol::~Kinsol() - { - SUNContext_Free(&context_); - KINFree(&solver_); - - N_VDestroy_Serial(this->yy_); - N_VDestroy_Serial(this->yy0_); - N_VDestroy_Serial(this->scale_); - - SUNMatDestroy(this->JacobianMat_); - SUNLinSolFree_Dense(this->linearSolver_); - - solver_ = 0; - } - - template - int Kinsol::configureSimulation() - { - int retval = 0; - - // Allocate solution vectors - yy_ = N_VNew_Serial(model_->size(), context_); - checkAllocation((void*) yy_, "N_VNew_Serial"); - - // Allocate scaling vector - scale_ = N_VClone(yy_); - checkAllocation((void*) scale_, "N_VClone"); - - // Create vectors to store restart initial condition - yy0_ = N_VClone(yy_); - checkAllocation((void*) yy0_, "N_VClone"); - - // Allocate and initialize KIN workspace - retval = KINInit(solver_, this->Residual, yy_); - checkOutput(retval, "KINInit"); - - // Set pointer to model data - retval = KINSetUserData(solver_, model_); - checkOutput(retval, "KINSetUserData"); - - // Set output verbosity level - retval = KINSetPrintLevel(solver_, 0); - checkOutput(retval, "KINSetPrintLevel"); - - // Set tolerances - realtype fnormtol; ///< Residual tolerance - realtype scsteptol; ///< Scaled step tolerance - - model_->setTolerances(fnormtol, scsteptol); ///< \todo Function name should be "getTolerances"! - retval = KINSetFuncNormTol(solver_, fnormtol); - checkOutput(retval, "KINSetFuncNormTol"); - - retval = KINSetScaledStepTol(solver_, scsteptol); - checkOutput(retval, "KINSetScaledStepTol"); - - // Set up linear solver - JacobianMat_ = SUNDenseMatrix(model_->size(), model_->size(), context_); - checkAllocation((void*) JacobianMat_, "SUNDenseMatrix"); - - linearSolver_ = SUNLinSol_Dense(yy_, JacobianMat_, context_); - checkAllocation((void*) linearSolver_, "SUNLinSol_Dense"); - - retval = KINSetLinearSolver(solver_, linearSolver_, JacobianMat_); - checkOutput(retval, "KINSetLinearSolver"); - - return retval; - } - - template - int Kinsol::configureLinearSolver() - { - int retval = 0; - - // Set up linear solver - JacobianMat_ = SUNDenseMatrix(model_->size(), model_->size(), context_); - checkAllocation((void*) JacobianMat_, "SUNDenseMatrix"); - - linearSolver_ = SUNLinSol_Dense(yy_, JacobianMat_, context_); - checkAllocation((void*) linearSolver_, "SUNLinSol_Dense"); - - retval = KINSetLinearSolver(solver_, linearSolver_, JacobianMat_); - checkOutput(retval, "KINSetLinearSolver"); - - return retval; - } - - template - int Kinsol::getDefaultInitialCondition() - { - model_->initialize(); - - copyVec(model_->y(), yy_); - - return 0; - } - - template - int Kinsol::runSimulation() - { - int retval = 0; - N_VConst(1.0, scale_); - retval = KINSol(solver_, yy_, KIN_LINESEARCH, scale_, scale_); - checkOutput(retval, "KINSol"); - //printOutput(tout); - //std::cout << "\n"; - return retval; - } - - template - int Kinsol::deleteSimulation() - { - SUNLinSolFree(linearSolver_); - KINFree(&solver_); - N_VDestroy(yy_); - N_VDestroy(scale_); - return 0; - } - - template - int Kinsol::Residual(N_Vector yy, N_Vector rr, void *user_data) - { - ModelLib::ModelEvaluator* model = - static_cast*>(user_data); - - copyVec(yy, model->y()); - - model->evaluateResidual(); - const std::vector& f = model->getResidual(); - copyVec(f, rr); - - return 0; - } - - template - void Kinsol::copyVec(const N_Vector x, std::vector< ScalarT >& y) - { - const ScalarT* xdata = NV_DATA_S(x); - for(unsigned int i = 0; i < y.size(); ++i) - { - y[i] = xdata[i]; - } - } - - - template - void Kinsol::copyVec(const std::vector< ScalarT >& x, N_Vector y) - { - ScalarT* ydata = NV_DATA_S(y); - for(unsigned int i = 0; i < x.size(); ++i) - { - ydata[i] = x[i]; - } - } - - template - void Kinsol::copyVec(const std::vector< bool >& x, N_Vector y) - { - ScalarT* ydata = NV_DATA_S(y); - for(unsigned int i = 0; i < x.size(); ++i) - { - if (x[i]) - ydata[i] = 1.0; - else - ydata[i] = 0.0; - } - } - - - template - void Kinsol::printOutput() - { - realtype *yval = N_VGetArrayPointer_Serial(yy_); - - std::cout << std::setprecision(5) << std::setw(7); - for (IdxT i = 0; i < model_->size(); ++i) - { - std::cout << yval[i] << " "; - } - std::cout << "\n"; - } - - template - void Kinsol::printSpecial(realtype t, N_Vector y) - { - realtype *yval = N_VGetArrayPointer_Serial(y); - IdxT N = N_VGetLength_Serial(y); - std::cout << "{"; - std::cout << std::setprecision(5) << std::setw(7) << t; - for (IdxT i = 0; i < N; ++i) - { - std::cout << ", " << yval[i]; - } - std::cout << "},\n"; - } - - template - void Kinsol::printFinalStats() - { - int retval = 0; - void* mem = solver_; - long int nni; - long int nfe; - long int nje; - long int nlfe; - - // retval = KINGetNumSteps(mem, &nst); - // checkOutput(retval, "KINGetNumSteps"); - retval = KINGetNumNonlinSolvIters(mem, &nni); - checkOutput(retval, "KINGetNumNonlinSolvIters"); - retval = KINGetNumFuncEvals(mem, &nfe); - checkOutput(retval, "KINGetNumFuncEvals"); - retval = KINGetNumJacEvals(mem, &nje); - checkOutput(retval, "KINGetNumJacEvals"); - retval = KINGetNumLinFuncEvals(mem, &nlfe); - checkOutput(retval, "KINGetNumLinFuncEvals"); - - // std::cout << "\nFinal Run Statistics: \n\n"; - std::cout << "Number of nonlinear iterations = " << nni << "\n"; - std::cout << "Number of function evaluations = " << nfe << "\n"; - std::cout << "Number of Jacobian evaluations = " << nje << "\n"; - std::cout << "Number of linear function evals. = " << nlfe << "\n"; - } - - - template - void Kinsol::checkAllocation(void* v, const char* functionName) - { - if (v == NULL) - { - std::cerr << "\nERROR: Function " << functionName << " failed -- returned NULL pointer!\n\n"; - throw SundialsException(); - } - } - - template - void Kinsol::checkOutput(int retval, const char* functionName) - { - if (retval < 0) - { - std::cerr << "\nERROR: Function " << functionName << " failed with flag " << retval << "!\n\n"; - throw SundialsException(); - } - } - - // Compiler will prevent building modules with data type incompatible with realtype - template class Kinsol; - template class Kinsol; - template class Kinsol; - -} // namespace Sundials -} // namespace AnalysisManager diff --git a/Solver/SteadyState/Kinsol.hpp b/Solver/SteadyState/Kinsol.hpp deleted file mode 100644 index f9b281791..000000000 --- a/Solver/SteadyState/Kinsol.hpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * - * 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. - * - */ - - -/** - * @file Kinsol.hpp - * @author Slaven Peles - * - * Contains declaration of interface to KINSOL nonlinear solver from - * SUNDIALS library. - * - */ -#pragma once - -#include -#include -#include -#include /* access to sparse SUNMatrix */ -// #include /* access to KLU linear solver */ -#include /* access to dense linear solver */ - -#include "ModelEvaluator.hpp" -#include "SteadyStateSolver.hpp" - -namespace AnalysisManager -{ - namespace Sundials - { - template - class Kinsol : public SteadyStateSolver - { - using SteadyStateSolver::model_; - - typedef typename GridKit::ScalarTraits::real_type real_type; - - public: - Kinsol(ModelLib::ModelEvaluator* model); - ~Kinsol(); - - int configureSimulation(); - int configureLinearSolver(); - int getDefaultInitialCondition(); - // int setIntegrationTime(real_type t_init, real_type t_final, int nout); - // int initializeSimulation(); - int runSimulation(); - int deleteSimulation(); - - // int configureQuadrature(); - // int initializeQuadrature(); - // int runSimulationQuadrature(real_type tf, int nout=1); - // int deleteQuadrature(); - - // int configureAdjoint(); - // int configureLinearSolverBackward(); - // int initializeAdjoint(IdxT steps = 100); - // int initializeBackwardSimulation(real_type tf); - // int runForwardSimulation(real_type tf, int nout=1); - // int runBackwardSimulation(real_type t0); - // int deleteAdjoint(); - - - int saveInitialCondition() - { - N_VScale(1.0, yy_, yy0_); - return 0; - } - - int getSavedInitialCondition() - { - N_VScale(1.0, yy0_, yy_); - return 0; - } - - // real_type getInitialTime() - // { - // return t_init_; - // } - - // real_type getFinalTime() - // { - // return t_final_; - // } - - // int getNumberOutputTimes() - // { - // return nout_; - // } - - // const real_type* getIntegral() const - // { - // return NV_DATA_S(q_); - // } - - // real_type* getIntegral() - // { - // return NV_DATA_S(q_); - // } - - // const real_type* getAdjointIntegral() const - // { - // return NV_DATA_S(qB_); - // } - - // real_type* getAdjointIntegral() - // { - // return NV_DATA_S(qB_); - // } - - void printOutput(); - void printSpecial(realtype t, N_Vector x); - void printFinalStats(); - - private: - static int Residual(N_Vector yy, N_Vector rr, void *user_data); - - // static int Integrand(realtype t, - // N_Vector yy, N_Vector yp, - // N_Vector rhsQ, void *user_data); - - // static int adjointResidual(realtype t, - // N_Vector yy, N_Vector yp, - // N_Vector yyB, N_Vector ypB, - // N_Vector rrB, void *user_data); - - // static int adjointIntegrand(realtype t, - // N_Vector yy, N_Vector yp, - // N_Vector yyB, N_Vector ypB, - // N_Vector rhsQB, void *user_data); - - private: - void* solver_; - SUNContext context_; - SUNMatrix JacobianMat_; - SUNLinearSolver linearSolver_; - - N_Vector yy_; ///< Solution vector - N_Vector scale_; ///< Scaling vector - N_Vector tag_; ///< Tags differential variables - N_Vector q_; ///< Integrand vector - - N_Vector yy0_; ///< Storage for initial values - - private: - //static void copyMat(ModelEvaluator::Mat& J, SlsMat Jida); - static void copyVec(const N_Vector x, std::vector& y); - static void copyVec(const std::vector& x, N_Vector y); - static void copyVec(const std::vector& x, N_Vector y); - - //int check_flag(void *flagvalue, const char *funcname, int opt); - inline void checkAllocation(void* v, const char* functionName); - inline void checkOutput(int retval, const char* functionName); - - }; - - /// Simple exception to use within Kinsol class. - class SundialsException : public std::exception - { - virtual const char* what() const throw() - { - return "Method in Kinsol class failed!\n"; - } - }; - - - } // namespace Sundials - - -} // namespace AnalysisManager diff --git a/Solver/SteadyState/SteadyStateSolver.hpp b/Solver/SteadyState/SteadyStateSolver.hpp deleted file mode 100644 index eb9380cfc..000000000 --- a/Solver/SteadyState/SteadyStateSolver.hpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * 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 "ModelEvaluator.hpp" - -namespace AnalysisManager -{ - template - class SteadyStateSolver - { - public: - SteadyStateSolver(ModelLib::ModelEvaluator* model) : model_(model) - { - } - virtual ~SteadyStateSolver(){} - - ModelLib::ModelEvaluator* getModel() - { - return model_; - } - - protected: - ModelLib::ModelEvaluator* model_; - }; - -} diff --git a/SystemModel.hpp b/SystemModel.hpp deleted file mode 100644 index 34c7ff120..000000000 --- a/SystemModel.hpp +++ /dev/null @@ -1,703 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef _SYSTEM_MODEL_HPP_ -#define _SYSTEM_MODEL_HPP_ - -#include -#include -#include - -#include -#include - -namespace ModelLib -{ - -/** - * @brief Prototype for a system model class - * - * This class maps component data to system data and implements - * ModelEvaluator for the system model. This is still work in - * progress and code is not optimized. - * - * @todo Address thread safety for the system model methods. - * - */ -template -class SystemModel : public ModelEvaluatorImpl -{ - typedef BaseBus bus_type; - typedef ModelEvaluatorImpl component_type; - using real_type = typename ModelEvaluatorImpl::real_type; - - using ModelEvaluatorImpl::size_; - using ModelEvaluatorImpl::size_quad_; - using ModelEvaluatorImpl::size_opt_; - using ModelEvaluatorImpl::nnz_; - using ModelEvaluatorImpl::time_; - using ModelEvaluatorImpl::alpha_; - using ModelEvaluatorImpl::y_; - using ModelEvaluatorImpl::yp_; - using ModelEvaluatorImpl::yB_; - using ModelEvaluatorImpl::ypB_; - using ModelEvaluatorImpl::tag_; - using ModelEvaluatorImpl::f_; - using ModelEvaluatorImpl::fB_; - using ModelEvaluatorImpl::g_; - using ModelEvaluatorImpl::gB_; - using ModelEvaluatorImpl::rtol_; - using ModelEvaluatorImpl::atol_; - using ModelEvaluatorImpl::param_; - using ModelEvaluatorImpl::param_up_; - using ModelEvaluatorImpl::param_lo_; - -public: - /** - * @brief Constructor for the system model - */ - SystemModel() : ModelEvaluatorImpl(0, 0, 0) - { - // Set system model tolerances - rtol_ = 1e-7; - atol_ = 1e-9; - } - - /** - * @brief Destructor for the system model - */ - virtual ~SystemModel() - { - } - - /** - * @brief Allocate buses, components, and system objects. - * - * This method first allocates bus objects, then component objects, - * and computes system size (number of unknowns). Once the size is - * computed, system global objects are allocated. - * - * @post size_quad_ == 0 or 1 - * @post size_ >= 1 - * @post size_opt_ >= 0 - * - */ - int allocate() - { - size_ = 0; - size_quad_ = 0; - size_opt_ = 0; - - // Allocate all buses - for(const auto& bus: buses_) - { - bus->allocate(); - size_ += bus->size(); - size_quad_ += bus->size_quad(); - size_opt_ += bus->size_opt(); - } - - // Allocate all components - for(const auto& component : components_) - { - component->allocate(); - size_ += component->size(); - size_quad_ += component->size_quad(); - size_opt_ += component->size_opt(); - } - - // Allocate global vectors - y_.resize(size_); - yp_.resize(size_); - yB_.resize(size_); - ypB_.resize(size_); - f_.resize(size_); - fB_.resize(size_); - tag_.resize(size_); - - g_.resize(size_quad_); - gB_.resize(size_quad_*size_opt_); - - param_.resize(size_opt_); - param_lo_.resize(size_opt_); - param_up_.resize(size_opt_); - - assert(size_quad_ == 1 or size_quad_ == 0); - - return 0; - } - - /** - * @brief Initialize buses first, then all the other components. - * - * @pre All buses and components must be allocated at this point. - * @pre Bus variables are written before component variables in the - * system variable vector. - * - * Buses must be initialized before other components, because other - * components may write to buses during the initialization. - * - * Also, generators may write to control devices (e.g. governors, - * exciters, etc.) during the initialization. - * - * @todo Implement writting to system vectors in a thread-safe way. - */ - int initialize() - { - // Set initial values for global solution vectors - IdxT varOffset = 0; - IdxT optOffset = 0; - - for(const auto& bus: buses_) - { - bus->initialize(); - } - - for(const auto& bus: buses_) - { - for(IdxT j=0; jsize(); ++j) - { - y_[varOffset + j] = bus->y()[j]; - yp_[varOffset + j] = bus->yp()[j]; - } - varOffset += bus->size(); - - for(IdxT j=0; jsize_opt(); ++j) - { - param_[optOffset + j] = bus->param()[j]; - param_lo_[optOffset + j] = bus->param_lo()[j]; - param_up_[optOffset + j] = bus->param_up()[j]; - } - optOffset += bus->size_opt(); - } - - // Initialize components - for(const auto& component : components_) - { - component->initialize(); - } - - for(const auto& component : components_) - { - for(IdxT j=0; jsize(); ++j) - { - y_[varOffset + j] = component->y()[j]; - yp_[varOffset + j] = component->yp()[j]; - } - varOffset += component->size(); - - for(IdxT j=0; jsize_opt(); ++j) - { - param_[optOffset + j] = component->param()[j]; - param_lo_[optOffset + j] = component->param_lo()[j]; - param_up_[optOffset + j] = component->param_up()[j]; - } - optOffset += component->size_opt(); - } - - return 0; - } - - /** - * @todo Tagging differential variables - * - * Identify what variables in the system of differential-algebraic - * equations are differential variables, i.e. their derivatives - * appear in the equations. - */ - int tagDifferentiable() - { - // Set initial values for global solution vectors - IdxT offset = 0; - for(const auto& bus: buses_) - { - bus->tagDifferentiable(); - for(IdxT j=0; jsize(); ++j) - { - tag_[offset + j] = bus->tag()[j]; - } - offset += bus->size(); - } - - for(const auto& component: components_) - { - component->tagDifferentiable(); - for(IdxT j=0; jsize(); ++j) - { - tag_[offset + j] = component->tag()[j]; - } - offset += component->size(); - } - - return 0; - } - - /** - * @brief Compute system residual vector - * - * First, update bus and component variables from the system solution - * vector. Next, evaluate residuals in buses and components, and - * then copy values to the global residual vector. - * - * @warning Residuals must be computed for buses, before component - * residuals are computed. Buses own residuals for active and - * power P and Q, but the contributions to these residuals come - * from components. Buses assign their residual values, while components - * add to those values by in-place adition. This is why bus residuals - * need to be computed first. - * - * @todo Here, components write to local values, which are then copied - * to global system vectors. Make components write to the system - * vectors directly. - */ - int evaluateResidual() - { - // Update variables - IdxT varOffset = 0; - IdxT optOffset = 0; - for(const auto& bus: buses_) - { - for(IdxT j=0; jsize(); ++j) - { - bus->y()[j] = y_[varOffset + j]; - bus->yp()[j] = yp_[varOffset + j]; - } - varOffset += bus->size(); - - for(IdxT j=0; jsize_opt(); ++j) - { - bus->param()[j] = param_[optOffset + j]; - } - optOffset += bus->size_opt(); - - bus->evaluateResidual(); - } - - for(const auto& component : components_) - { - for(IdxT j=0; jsize(); ++j) - { - component->y()[j] = y_[varOffset + j]; - component->yp()[j] = yp_[varOffset + j]; - } - varOffset += component->size(); - - for(IdxT j=0; jsize_opt(); ++j) - { - component->param()[j] = param_[optOffset + j]; - } - optOffset += component->size_opt(); - - component->evaluateResidual(); - } - - // Update residual vector - IdxT resOffset = 0; - for(const auto& bus: buses_) - { - for(IdxT j=0; jsize(); ++j) - { - f_[resOffset + j] = bus->getResidual()[j]; - } - resOffset += bus->size(); - } - - for(const auto& component : components_) - { - for(IdxT j=0; jsize(); ++j) - { - f_[resOffset + j] = component->getResidual()[j]; - } - resOffset += component->size(); - } - - return 0; - } - - /** - * @brief Evaluate system Jacobian. - * - * @todo Need to implement Jacobian. For now, using finite difference - * approximation provided by IDA. This works for dense Jacobian matrix - * only. - * - */ - int evaluateJacobian(){return 0;} - - /** - * @brief Evaluate integrands for the system quadratures. - */ - int evaluateIntegrand() - { - // Update variables - IdxT varOffset = 0; - IdxT optOffset = 0; - for(const auto& bus: buses_) - { - for(IdxT j=0; jsize(); ++j) - { - bus->y()[j] = y_[varOffset + j]; - bus->yp()[j] = yp_[varOffset + j]; - } - varOffset += bus->size(); - - for(IdxT j=0; jsize_opt(); ++j) - { - bus->param()[j] = param_[optOffset + j]; - } - optOffset += bus->size_opt(); - - bus->evaluateIntegrand(); - } - - for(const auto& component : components_) - { - for(IdxT j=0; jsize(); ++j) - { - component->y()[j] = y_[varOffset + j]; - component->yp()[j] = yp_[varOffset + j]; - } - varOffset += component->size(); - - for(IdxT j=0; jsize_opt(); ++j) - { - component->param()[j] = param_[optOffset + j]; - } - optOffset += component->size_opt(); - - component->evaluateIntegrand(); - } - - // Update integrand vector - IdxT intOffset = 0; - for(const auto& bus: buses_) - { - for(IdxT j=0; jsize_quad(); ++j) - { - g_[intOffset + j] = bus->getIntegrand()[j]; - } - intOffset += bus->size_quad(); - } - - for(const auto& component : components_) - { - for(IdxT j=0; jsize_quad(); ++j) - { - g_[intOffset + j] = component->getIntegrand()[j]; - } - intOffset += component->size_quad(); - } - - return 0; - } - - /** - * @brief Initialize system adjoint. - * - * Updates variables and optimization parameters, then initializes - * adjoints locally and copies them to the system adjoint vector. - */ - int initializeAdjoint() - { - IdxT offset = 0; - IdxT optOffset = 0; - - // Update bus variables and optimization parameters - for(const auto& bus: buses_) - { - for(IdxT j=0; jsize(); ++j) - { - bus->y()[j] = y_[offset + j]; - bus->yp()[j] = yp_[offset + j]; - } - offset += bus->size(); - - for(IdxT j=0; jsize_opt(); ++j) - { - bus->param()[j] = param_[optOffset + j]; - } - optOffset += bus->size_opt(); - } - - // Update component variables and optimization parameters - for(const auto& component: components_) - { - for(IdxT j=0; jsize(); ++j) - { - component->y()[j] = y_[offset + j]; - component->yp()[j] = yp_[offset + j]; - } - offset += component->size(); - - for(IdxT j=0; jsize_opt(); ++j) - { - component->param()[j] = param_[optOffset + j]; - } - optOffset += component->size_opt(); - } - - // Reset counter - offset = 0; - - // Initialize bus adjoints - for(const auto& bus: buses_) - { - bus->initializeAdjoint(); - - for(IdxT j=0; jsize(); ++j) - { - yB_[offset + j] = bus->yB()[j]; - ypB_[offset + j] = bus->ypB()[j]; - } - offset += bus->size(); - } - - // Initialize component adjoints - for(const auto& component: components_) - { - component->initializeAdjoint(); - - for(IdxT j=0; jsize(); ++j) - { - yB_[offset + j] = component->yB()[j]; - ypB_[offset + j] = component->ypB()[j]; - } - offset += component->size(); - } - - return 0; - } - - /** - * @brief Compute adjoint residual for the system model. - * - * @warning Components write to bus residuals. Do not copy bus residuals - * to system vectors before components computed their residuals. - * - */ - int evaluateAdjointResidual() - { - IdxT varOffset = 0; - IdxT optOffset = 0; - - // Update variables in component models - for(const auto& bus: buses_) - { - for(IdxT j=0; jsize(); ++j) - { - bus->y()[j] = y_[varOffset + j]; - bus->yp()[j] = yp_[varOffset + j]; - bus->yB()[j] = yB_[varOffset + j]; - bus->ypB()[j] = ypB_[varOffset + j]; - } - varOffset += bus->size(); - - for(IdxT j=0; jsize_opt(); ++j) - { - bus->param()[j] = param_[optOffset + j]; - } - optOffset += bus->size_opt(); - - } - - for(const auto& component : components_) - { - for(IdxT j=0; jsize(); ++j) - { - component->y()[j] = y_[varOffset + j]; - component->yp()[j] = yp_[varOffset + j]; - component->yB()[j] = yB_[varOffset + j]; - component->ypB()[j] = ypB_[varOffset + j]; - } - varOffset += component->size(); - - for(IdxT j=0; jsize_opt(); ++j) - { - component->param()[j] = param_[optOffset + j]; - } - optOffset += component->size_opt(); - - } - - for(const auto& bus: buses_) - { - bus->evaluateAdjointResidual(); - } - - for(const auto& component : components_) - { - component->evaluateAdjointResidual(); - } - - // Update residual vector - IdxT resOffset = 0; - for(const auto& bus: buses_) - { - for(IdxT j=0; jsize(); ++j) - { - fB_[resOffset + j] = bus->getAdjointResidual()[j]; - } - resOffset += bus->size(); - } - - for(const auto& component : components_) - { - for(IdxT j=0; jsize(); ++j) - { - fB_[resOffset + j] = component->getAdjointResidual()[j]; - } - resOffset += component->size(); - } - - return 0; - } - - //int evaluateAdjointJacobian(){return 0;} - - /** - * @brief Evaluate adjoint integrand for the system model. - * - * @pre Assumes there are no integrands in bus models. - * @pre Assumes integrand is implemented in only _one_ component. - * - */ - int evaluateAdjointIntegrand() - { - // First, update variables - IdxT varOffset = 0; - IdxT optOffset = 0; - for(const auto& bus: buses_) - { - for(IdxT j=0; jsize(); ++j) - { - bus->y()[j] = y_[varOffset + j]; - bus->yp()[j] = yp_[varOffset + j]; - bus->yB()[j] = yB_[varOffset + j]; - bus->ypB()[j] = ypB_[varOffset + j]; - } - varOffset += bus->size(); - - for(IdxT j=0; jsize_opt(); ++j) - { - bus->param()[j] = param_[optOffset + j]; - } - optOffset += bus->size_opt(); - } - - for(const auto& component : components_) - { - for(IdxT j=0; jsize(); ++j) - { - component->y()[j] = y_[varOffset + j]; - component->yp()[j] = yp_[varOffset + j]; - component->yB()[j] = yB_[varOffset + j]; - component->ypB()[j] = ypB_[varOffset + j]; - } - varOffset += component->size(); - - for(IdxT j=0; jsize_opt(); ++j) - { - component->param()[j] = param_[optOffset + j]; - } - optOffset += component->size_opt(); - } - - // Evaluate integrand and update global vector - for(const auto& component : components_) - { - if(component->size_quad() == 1) - { - component->evaluateAdjointIntegrand(); - for(IdxT j=0; jgetAdjointIntegrand()[j]; - } - break; - } - } - return 0; - } - - void updateTime(real_type t, real_type a) - { - for(const auto& component : components_) - { - component->updateTime(t, a); - } - } - - void addBus(bus_type* bus) - { - buses_.push_back(bus); - } - - void addComponent(component_type* component) - { - components_.push_back(component); - } - -private: - std::vector buses_; - std::vector components_; - -}; // class SystemModel - -} // namespace ModelLib - -#endif // _SYSTEM_MODEL_HPP_ \ No newline at end of file diff --git a/SystemSteadyStateModel.hpp b/SystemSteadyStateModel.hpp deleted file mode 100644 index c32dd5ec3..000000000 --- a/SystemSteadyStateModel.hpp +++ /dev/null @@ -1,429 +0,0 @@ -/* - * - * 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. - * - */ - -/** - * @file SystemSteadyStaeModel.hpp - * @author Slaven Peles - * - * Contains definition of power flow analysis class. - * - */ -#pragma once - -#include -#include -#include - -#include -#include - -namespace ModelLib -{ - -/** - * @brief Prototype for a system model class - * - * This class maps component data to system data and implements - * ModelEvaluator for the system model. This is still work in - * progress and code is not optimized. - * - * @todo Address thread safety for the system model methods. - * - * @todo Tolerance management needs to be reconsidered. - * - */ -template -class SystemSteadyStateModel : public ModelEvaluatorImpl -{ - typedef BaseBus bus_type; - typedef ModelEvaluatorImpl component_type; - using real_type = typename ModelEvaluatorImpl::real_type; - - using ModelEvaluatorImpl::size_; - // using ModelEvaluatorImpl::size_quad_; - // using ModelEvaluatorImpl::size_opt_; - using ModelEvaluatorImpl::nnz_; - // using ModelEvaluatorImpl::time_; - // using ModelEvaluatorImpl::alpha_; - using ModelEvaluatorImpl::y_; - // using ModelEvaluatorImpl::yp_; - // using ModelEvaluatorImpl::yB_; - // using ModelEvaluatorImpl::ypB_; - // using ModelEvaluatorImpl::tag_; - using ModelEvaluatorImpl::f_; - // using ModelEvaluatorImpl::fB_; - // using ModelEvaluatorImpl::g_; - // using ModelEvaluatorImpl::gB_; - using ModelEvaluatorImpl::rtol_; - using ModelEvaluatorImpl::atol_; - // using ModelEvaluatorImpl::param_; - // using ModelEvaluatorImpl::param_up_; - // using ModelEvaluatorImpl::param_lo_; - -public: - /** - * @brief Constructor for the system model - */ - SystemSteadyStateModel() : ModelEvaluatorImpl(0, 0, 0) - { - // Set system model tolerances - rtol_ = 1e-5; - atol_ = 1e-5; - } - - /** - * @brief Construct a new System Steady State Model object. Allows for simple allocation. - * - * @param mp model data - */ - SystemSteadyStateModel(GridKit::PowerSystemData::SystemModelData mp) : ModelEvaluatorImpl(0,0,0) - { - rtol_ = 1e-5; - atol_ = 1e-5; - - //add buses - for(auto busdata : mp.bus) - { - auto* bus = BusFactory::create(busdata); - this->addBus(bus); - } - - //add generators - for (auto gendata : mp.gen) - { - auto* gen = GeneratorFactory::create(this->getBus(gendata.bus),gendata); - this->addComponent(gen); - } - - //add branches - for (auto branchdata : mp.branch) - { - auto* branch = new Branch(this->getBus(branchdata.fbus),this->getBus(branchdata.tbus),branchdata); - this->addComponent(branch); - } - - //add loads - for (auto loaddata : mp.load) - { - auto* loadm = new Load(this->getBus(loaddata.bus_i),loaddata); - this->addComponent(loadm); - } - - //There is no Generator Cost Object - //TODO: Implment for GenCost - } - - /** - * @brief Destructor for the system model - */ - virtual ~SystemSteadyStateModel() - { - for (auto comp : this->components_) delete comp; - for (auto bus : this->buses_) delete bus; - } - - /** - * @brief Allocate buses, components, and system objects. - * - * This method first allocates bus objects, then component objects, - * and computes system size (number of unknowns). Once the size is - * computed, system global objects are allocated. - * - * @post size_quad_ == 0 or 1 - * @post size_ >= 1 - * @post size_opt_ >= 0 - * - */ - int allocate() - { - size_ = 0; - - // Allocate all buses - for(const auto& bus: buses_) - { - bus->allocate(); - size_ += bus->size(); - } - - // Allocate all components - for(const auto& component : components_) - { - component->allocate(); - size_ += component->size(); - } - - // Allocate global vectors - y_.resize(size_); - f_.resize(size_); - - return 0; - } - - /** - * @brief Initialize buses first, then all the other components. - * - * @pre All buses and components must be allocated at this point. - * @pre Bus variables are written before component variables in the - * system variable vector. - * - * Buses must be initialized before other components, because other - * components may write to buses during the initialization. - * - * Also, generators may write to control devices (e.g. governors, - * exciters, etc.) during the initialization. - * - * @todo Implement writting to system vectors in a thread-safe way. - */ - int initialize() - { - // Set initial values for global solution vectors - IdxT varOffset = 0; - - for(const auto& bus: buses_) - { - bus->initialize(); - } - - for(const auto& bus: buses_) - { - for(IdxT j=0; jsize(); ++j) - { - y_[varOffset + j] = bus->y()[j]; - } - varOffset += bus->size(); - } - - // Initialize components - for(const auto& component : components_) - { - component->initialize(); - } - - for(const auto& component : components_) - { - for(IdxT j=0; jsize(); ++j) - { - y_[varOffset + j] = component->y()[j]; - } - varOffset += component->size(); - } - return 0; - } - - /** - * @todo Tagging differential variables - * - * Identify what variables in the system of differential-algebraic - * equations are differential variables, i.e. their derivatives - * appear in the equations. - */ - int tagDifferentiable() - { - return 0; - } - - /** - * @brief Compute system residual vector - * - * First, update bus and component variables from the system solution - * vector. Next, evaluate residuals in buses and components, and - * then copy values to the global residual vector. - * - * @warning Residuals must be computed for buses, before component - * residuals are computed. Buses own residuals for active and - * power P and Q, but the contributions to these residuals come - * from components. Buses assign their residual values, while components - * add to those values by in-place adition. This is why bus residuals - * need to be computed first. - * - * @todo Here, components write to local values, which are then copied - * to global system vectors. Make components write to the system - * vectors directly. - */ - int evaluateResidual() - { - // Update variables - IdxT varOffset = 0; - for(const auto& bus: buses_) - { - for(IdxT j=0; jsize(); ++j) - { - bus->y()[j] = y_[varOffset + j]; - } - varOffset += bus->size(); - bus->evaluateResidual(); - } - - for(const auto& component : components_) - { - for(IdxT j=0; jsize(); ++j) - { - component->y()[j] = y_[varOffset + j]; - } - varOffset += component->size(); - component->evaluateResidual(); - } - - // Update system residual vector - IdxT resOffset = 0; - for(const auto& bus : buses_) - { - for(IdxT j=0; jsize(); ++j) - { - f_[resOffset + j] = bus->getResidual()[j]; - } - resOffset += bus->size(); - } - - for(const auto& component : components_) - { - for(IdxT j=0; jsize(); ++j) - { - f_[resOffset + j] = component->getResidual()[j]; - } - resOffset += component->size(); - } - - return 0; - } - - /** - * @brief Evaluate system Jacobian. - * - * @todo Need to implement Jacobian. For now, using finite difference - * approximation provided by IDA. This works for dense Jacobian matrix - * only. - * - */ - int evaluateJacobian(){return 0;} - - /** - * @brief Evaluate integrands for the system quadratures. - */ - int evaluateIntegrand() - { - - return 0; - } - - /** - * @brief Initialize system adjoint. - * - * Updates variables and optimization parameters, then initializes - * adjoints locally and copies them to the system adjoint vector. - */ - int initializeAdjoint() - { - return 0; - } - - /** - * @brief Compute adjoint residual for the system model. - * - * @warning Components write to bus residuals. Do not copy bus residuals - * to system vectors before components computed their residuals. - * - */ - int evaluateAdjointResidual() - { - return 0; - } - - //int evaluateAdjointJacobian(){return 0;} - - /** - * @brief Evaluate adjoint integrand for the system model. - * - * @pre Assumes there are no integrands in bus models. - * @pre Assumes integrand is implemented in only _one_ component. - * - */ - int evaluateAdjointIntegrand() - { - return 0; - } - - void updateTime(real_type t, real_type a) - { - } - - void addBus(bus_type* bus) - { - buses_.push_back(bus); - } - - void addComponent(component_type* component) - { - components_.push_back(component); - } - - bus_type* getBus(IdxT busid) - { - // Need to implement mapping of bus IDs to buses in the system model - assert( (buses_[busid - 1])->BusID() == busid ); - return buses_[busid - 1]; - } - -private: - std::vector buses_; - std::vector components_; - -}; // class SystemSteadyStateModel - -} // namespace ModelLib diff --git a/Utilities/FileIO.hpp b/Utilities/FileIO.hpp deleted file mode 100644 index 825123c97..000000000 --- a/Utilities/FileIO.hpp +++ /dev/null @@ -1,377 +0,0 @@ -/* - * - * 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. - * - */ - -/** - * @file FileIO.hpp - * @author Slaven Peles - * - * Contains definition of a utility for reading lookup tables. - * - */ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace -{ - -using namespace GridKit; -using namespace GridKit::PowerSystemData; - -static const std::string matlab_syntax_error{ - "Only a subset of Matlab syntax is supported." - "\n\t'=' for assignment must be on the same line as the field, eg " - "`mpc.version = '2'`." - "\n\tOpen brace ('[') must be on the same line as the field for matrix " - "initialization." - "\n\tEach row of a matrix must be terminated by a semicolon."}; - -std::ostream& logs() -{ -#ifndef NDEBUG - std::cerr << "[FileIO.hpp]: "; - return std::cerr; -#else - static std::ofstream ofs; - ofs.setstate(std::ios_base::badbit); - return ofs; -#endif -} - -void ltrim(std::string& s) -{ - const std::string nothing = ""; - s = std::regex_replace(s, std::regex("^\\s+"), nothing); -} - -void rtrim(std::string& s) -{ - const std::string nothing = ""; - s = std::regex_replace(s, std::regex("\\s+$"), nothing); -} - -void trim_matlab_comments(std::string& s) -{ - const std::string nothing = ""; - s = std::regex_replace(s, std::regex("%.+"), nothing); -} - -// Retrive MATPOWER component from assignment line. -// -// For example, the string " mpc.bus = [ ... ] % Some comment" will -// return the value "bus". -std::string getMatPowerComponent(const std::string& line) -{ - logs() << "Getting matpower component from line\n"; - std::regex pat("mpc.([a-zA-Z]+)\\s*=.+"); - std::smatch matches; - std::string component; - if (std::regex_match(line, matches, pat)) - { - component = matches[1].str(); - } - else - { - throw std::runtime_error(matlab_syntax_error + "\nGot line " + line); - } - ltrim(component); - rtrim(component); - return component; -} - -// Ensure that all of the given line has been consumed, and that the only -// remaining non-whitespace character left in the line is a semicolon. -void checkEndOfMatrixRow(std::istream& is) -{ - std::string rest; - is >> rest; - ltrim(rest); - rtrim(rest); - if (rest != ";") - throw std::runtime_error(matlab_syntax_error); -} - -template -void readMatPowerBusRow(const std::string& row, BusData& br, LoadData& lr) -{ - logs() << "Parsing MATPOWER bus row\n"; - std::stringstream is(row); - is >> br.bus_i // Bus ID - >> br.type // Bus type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated - >> lr.Pd // Active power demand [MW] - >> lr.Qd // Reactive power demand [MVAr] - >> br.Gs // Shunt conductance (MW demanded at V = 1.0 p.u.) - >> br.Bs // Shunt susceptance (MVAr injected at V = 1.0 p.u.) - >> br.area // Area number (>0) - >> br.Vm // Voltage magnitude (p.u.) - >> br.Va // Voltage phase (deg) - >> br.baseKV // Base voltage [kV] - >> br.zone // Loss zone number (>0) - >> br.Vmax // Maximum voltage magnitude (p.u.) - >> br.Vmin; // Minimum voltage magnitude (p.u.) - - lr.bus_i = br.bus_i; - - // std::cout << br.str(); - // logs() << "Read BusData with the following values:\n" << br.str(); - // return br; -} - -template -void readMatPowerGenRow(GenData& gr, std::string& row) -{ - logs() << "Parsing MATPOWER gen row\n"; - std::stringstream is(row); - is >> gr.bus >> gr.Pg >> gr.Qg >> gr.Qmax >> gr.Qmin >> gr.Vg >> gr.mBase - >> gr.status >> gr.Pmax >> gr.Pmin >> gr.Pc1 >> gr.Pc2 >> gr.Qc1min - >> gr.Qc1max >> gr.Qc2min >> gr.Qc2max >> gr.ramp_agc >> gr.ramp_10 - >> gr.ramp_30 >> gr.ramp_q >> gr.apf; - checkEndOfMatrixRow(is); -} - -template -void readMatPowerBranchRow(BranchData& br, std::string& row) -{ - logs() << "Parsing MATPOWER branch row\n"; - std::stringstream is(row); - is >> br.fbus >> br.tbus >> br.r >> br.x >> br.b >> br.rateA >> br.rateB - >> br.rateC >> br.ratio >> br.angle >> br.status >> br.angmin - >> br.angmax; - checkEndOfMatrixRow(is); -} - -template -void readMatPowerGenCostRow(GenCostData& gcr, std::string& row) -{ - logs() << "Parsing MATPOWER gen cost row\n"; - // Ensure last character is semicolon. - rtrim(row); - if (row[row.size() - 1] != ';') - throw std::runtime_error(matlab_syntax_error + "\nGot line " + row); - - std::stringstream is(row); - is >> gcr.kind >> gcr.startup >> gcr.shutdown >> gcr.n; - - for (RealT r; is >> r;) { - gcr.rest.push_back(r); - } -} - -template -void readMatPowerVersion(SystemModelData& mp, std::string& line) -{ - logs() << "Parsing matpower version\n"; - std::regex pat("mpc\\.version\\s*=\\s*'([0-9])';"); - std::smatch matches; - if (std::regex_match(line, matches, pat)) { - mp.version = matches[1].str(); - } else { - throw std::runtime_error(matlab_syntax_error + "\nGot line '" + line + "'"); - } -} - -template -void readMatPowerBaseMVA(SystemModelData& mp, std::string& line) -{ - std::regex pat("mpc\\.baseMVA\\s*=\\s*([0-9]+);"); - std::smatch matches; - if (std::regex_match(line, matches, pat)) { - std::string s = matches[1]; - mp.baseMVA = std::atoi(s.c_str()); - } else { - throw std::runtime_error(matlab_syntax_error + "\nGot line '" + line + "'"); - } -} - -} // namespace - -namespace GridKit -{ -template -void setLookupTable(std::vector>& table, - std::string filename, - ScalarT& ti, - ScalarT& tf) -{ - std::ifstream idata(filename); - std::string line; - int oldwordcount = -1; - while (std::getline(idata, line)) { - std::istringstream iss(line); - double word; - int wordcount = 0; - std::vector row; - while (iss >> word) { - row.push_back(word); - ++wordcount; - } - table.push_back(std::move(row)); - if (oldwordcount != -1) { - if (oldwordcount != wordcount) { - std::cerr << "Corrupted input data!\n"; - return; - } - } else { - oldwordcount = wordcount; - } - } - - size_t N = table.size(); - ti = table[0][0]; - tf = table[N - 1][0]; -} - -template -void printLookupTable(std::vector> const& table) -{ - for (size_t i = 0; i < table.size(); ++i) { - for (size_t j = 0; j < table[i].size(); ++j) { - std::cout << table[i][j] << " "; - } - std::cout << "\n"; - } -} - -template -void readMatPowerFile(SystemModelData& mp, std::string& filename) -{ - std::ifstream ifs{filename}; - readMatPower(mp, ifs); -} - -template -void readMatPower(SystemModelData& mp, std::istream& is) -{ - using BusDataT = BusData; - using GenDataT = GenData; - using BranchDataT = BranchData; - using GenCostDataT = GenCostData; - using LoadDataT = LoadData; - - for (std::string line; std::getline(is, line);) { - // Trim whitespace and remove comments - ltrim(line); - rtrim(line); - logs() << line << "\n"; - trim_matlab_comments(line); - - // Skip empty lines and comment-only lines - if (line.size() == 0) continue; - - // Skip the matlab function declaration - if (line.find("function") != std::string::npos) continue; - - // Check for MATPOWER component definitions - if (line.find("mpc") != std::string::npos) { - const std::string component = getMatPowerComponent(line); - logs() << "Got component: '" << component << "'\n"; - // First, parse matrix components - if (component == "bus") { - while (std::getline(is, line)) { - if (line.find("];") != std::string::npos) break; - BusDataT br; - LoadDataT lr; - readMatPowerBusRow(line, br, lr); - mp.bus.push_back(std::move(br)); - mp.load.push_back(std::move(lr)); - } - } else if (component == "gen") { - while (std::getline(is, line)) { - if (line.find("];") != std::string::npos) break; - GenDataT gr; - readMatPowerGenRow(gr, line); - mp.gen.push_back(gr); - } - } else if (component == "branch") { - while (std::getline(is, line)) { - if (line.find("];") != std::string::npos) break; - BranchDataT br; - readMatPowerBranchRow(br, line); - mp.branch.push_back(br); - } - } else if (component == "gencost") { - while (std::getline(is, line)) { - if (line.find("];") != std::string::npos) break; - GenCostDataT gcr; - readMatPowerGenCostRow(gcr, line); - mp.gencost.push_back(gcr); - } - } - - // Next, parse scalar components - else if (component == "version") { - readMatPowerVersion(mp, line); - } else if (component == "baseMVA") { - readMatPowerBaseMVA(mp, line); - } - } - } -} - -} // namespace GridKit diff --git a/Utilities/Testing.hpp b/Utilities/Testing.hpp deleted file mode 100644 index f061cdbd1..000000000 --- a/Utilities/Testing.hpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - * - * 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. - * - */ - -/** - * @file Testing.hpp - * @author Slaven Peles - * - * Contains utilies for testing. - * - */ -#pragma once - -#include -#include -#include - -namespace { - -static constexpr double tol_ = 1e-8; - -inline std::ostream &errs() { - std::cerr << "[Utils/Testing.hpp]: "; - return std::cerr; -} - -} // namespace - -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 -inline bool isEqual(PowerSystemData::GenCostData a, - PowerSystemData::GenCostData b, - RealT tol = tol_) -{ - int fail = 0; - fail += a.kind != b.kind; - fail += a.startup != b.startup; - fail += a.shutdown != b.shutdown; - fail += a.n != b.n; - if (fail) { - errs() << "Got failure!\na=" << a.str() << "\nb=" << b.str(); - } - return fail == 0; -} - -template -inline bool isEqual(PowerSystemData::GenData a, - PowerSystemData::GenData b, - RealT tol = tol_) -{ - int fail = 0; - fail += a.bus != b.bus; - fail += !isEqual(a.Pg, b.Pg, tol); - fail += !isEqual(a.Qg, b.Qg, tol); - fail += !isEqual(a.Qmax, b.Qmax, tol); - fail += !isEqual(a.Qmin, b.Qmin, tol); - fail += !isEqual(a.Vg, b.Vg, tol); - fail += a.mBase != b.mBase; - fail += a.status != b.status; - fail += a.Pmax != b.Pmax; - fail += a.Pmin != b.Pmin; - fail += a.Pc1 != b.Pc1; - fail += a.Pc2 != b.Pc2; - fail += a.Qc1min != b.Qc1min; - fail += a.Qc1max != b.Qc1max; - fail += a.Qc2min != b.Qc2min; - fail += a.Qc2max != b.Qc2max; - fail += a.ramp_agc != b.ramp_agc; - fail += a.ramp_10 != b.ramp_10; - fail += a.ramp_30 != b.ramp_30; - fail += a.ramp_q != b.ramp_q; - fail += a.apf != b.apf; - if (fail) { - errs() << "Got failure!\na=" << a.str() << "\nb=" << b.str(); - } - return fail == 0; -} - -template -inline bool isEqual(PowerSystemData::BusData a, - PowerSystemData::BusData b, - RealT tol = tol_) -{ - int fail = 0; - fail += a.bus_i != b.bus_i; - fail += a.type != b.type; - fail += a.Gs != b.Gs; - fail += a.Bs != b.Bs; - fail += a.area != b.area; - fail += !isEqual(a.Vm, b.Vm, tol); - fail += !isEqual(a.Va, b.Va, tol); - fail += a.baseKV != b.baseKV; - fail += a.zone != b.zone; - fail += !isEqual(a.Vmax, b.Vmax, tol); - fail += !isEqual(a.Vmin, b.Vmin, tol); - if (fail) { - errs() << "bus_i: a=" << a.bus_i << ", b=" << b.bus_i << "\n" - << "type: a=" << a.type << ", b=" << b.type << "\n" - << "Gs: a=" << a.Gs << ", b=" << b.Gs << "\n" - << "Bs: a=" << a.Bs << ", b=" << b.Bs << "\n" - << "area: a=" << a.area << ", b=" << b.area << "\n" - << "Vm: a=" << a.Vm << ", b=" << b.Vm << "\n" - << "Va: a=" << a.Va << ", b=" << b.Va << "\n" - << "baseKV: a=" << a.baseKV << ", b=" << b.baseKV << "\n" - << "zone: a=" << a.zone << ", b=" << b.zone << "\n" - << "Vmax: a=" << a.Vmax << ", b=" << b.Vmax << "\n" - << "Vmin: a=" << a.Vmin << ", b=" << b.Vmin << "\n"; - } - return fail == 0; -} - -template -inline bool isEqual(PowerSystemData::LoadData a, - PowerSystemData::LoadData b, - RealT tol = tol_) -{ - int fail = 0; - fail += a.bus_i != b.bus_i; - fail += !isEqual(a.Pd, b.Pd, tol); - fail += !isEqual(a.Qd, b.Qd, tol); - if (fail) { - errs() << "bus_i: a=" << a.bus_i << ", b=" << b.bus_i << "\n" - << "Pd: a=" << a.Pd << ", b=" << b.Pd << "\n" - << "Qd: a=" << a.Qd << ", b=" << b.Qd << "\n"; - } - return fail == 0; -} - -template -inline bool isEqual(PowerSystemData::BranchData a, - PowerSystemData::BranchData b, - RealT tol = tol_) -{ - int fail = 0; - fail += a.fbus != b.fbus; - fail += a.tbus != b.tbus; - fail += !isEqual(a.r, b.r, tol); - fail += !isEqual(a.x, b.x, tol); - fail += !isEqual(a.b, b.b, tol); - fail += a.rateA != b.rateA; - fail += a.rateB != b.rateB; - fail += a.rateC != b.rateC; - fail += a.ratio != b.ratio; - fail += a.angle != b.angle; - fail += a.status != b.status; - fail += a.angmin != b.angmin; - fail += a.angmax != b.angmax; - if (fail) { - errs() << "Got failure!\na=" << a.str() << "\nb=" << b.str(); - } - return fail == 0; -} - -template -inline bool isEqual(std::vector a, std::vector b, double tol = tol_) -{ - if (a.size() != b.size()) - throw std::runtime_error([&] { - std::stringstream errs; - errs << "Containers do not have the same size!\n" - << "\tGot a.size() == " << a.size() << "\n" - << "\tGot b.size() == " << b.size() << "\n"; - return errs.str(); - }()); - - int fail = 0; - for (std::size_t i = 0; i < a.size(); i++) { - if (!isEqual(a[i], b[i])) { - fail++; - errs() << "[isEqual>]: Got failure with i=" << i << ".\n"; - } - } - - return fail == 0; -} - -template -inline bool isEqual(PowerSystemData::SystemModelData a, - PowerSystemData::SystemModelData b) -{ - int fail = 0; - fail += a.version != b.version; - fail += a.baseMVA != b.baseMVA; - fail += !isEqual(a.bus, b.bus); - fail += !isEqual(a.gen, b.gen); - fail += !isEqual(a.gencost, b.gencost); - fail += !isEqual(a.branch, b.branch); - fail += !isEqual(a.load, b.load); - return fail == 0; -} - -} // namespace Testing - -} // namespace GridKit diff --git a/buildsystem/.gitkeep b/buildsystem/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/buildsystem/spack/spack b/buildsystem/spack/spack new file mode 160000 index 000000000..2452bf8bc --- /dev/null +++ b/buildsystem/spack/spack @@ -0,0 +1 @@ +Subproject commit 2452bf8bc7d1c8a80ae9214a037193867d48f77c diff --git a/CMake/Config.cmake.in b/cmake/Config.cmake.in similarity index 100% rename from CMake/Config.cmake.in rename to cmake/Config.cmake.in diff --git a/cmake/FindEnzyme.cmake b/cmake/FindEnzyme.cmake new file mode 100644 index 000000000..8ef1371ef --- /dev/null +++ b/cmake/FindEnzyme.cmake @@ -0,0 +1,122 @@ +# +#[[ + +Finds Enzyme Clang plugin + +User may set: +- ENZYME_DIR + +Author(s): +- Asher Mancinelli +- Nicholson Koukpaizan + +]] + +find_package(Enzyme REQUIRED CONFIG + PATHS + ${ENZYME_DIR} + ${ENZYME_DIR}/lib/cmake/Enzyme) +message(STATUS "Enzyme configuration found: ${Enzyme_CONFIG}") + +find_library(ENZYME_LLVM_PLUGIN_LIBRARY + NAMES + LLVMEnzyme-${Enzyme_LLVM_VERSION_MAJOR}.so + LLVMEnzyme-${Enzyme_LLVM_VERSION_MAJOR}.dylib + LLVMEnzyme-${Enzyme_LLVM_VERSION_MAJOR}.dll + PATHS + ${ENZYME_DIR} + ENV LD_LIBRARY_PATH + ENV DYLD_LIBRARY_PATH + PATH_SUFFIXES + lib64 lib + REQUIRED) +message(STATUS "Enzyme LLVM plugin library: ${ENZYME_LLVM_PLUGIN_LIBRARY}") + +find_program(GRIDKIT_LLVM_LINK llvm-link + PATHS ${Enzyme_LLVM_BINARY_DIR} + REQUIRED) +message(STATUS "llvm-link: ${GRIDKIT_LLVM_LINK}") + +find_program(GRIDKIT_OPT opt + PATHS ${Enzyme_LLVM_BINARY_DIR} + REQUIRED) +message(STATUS "opt: ${GRIDKIT_OPT}") + +macro(enzyme_add_executable) + set(options) + set(oneValueArgs NAME) + set(multiValueArgs SOURCES LINK_LIBRARIES INCLUDE_DIRECTORIES) + cmake_parse_arguments(enzyme_add_executable "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN}) + + set(PHASE2 "${CMAKE_CURRENT_BINARY_DIR}/${enzyme_add_executable_NAME}.bc") + set(PHASE3 "${CMAKE_CURRENT_BINARY_DIR}/${enzyme_add_executable_NAME}_enzyme.ll") + set(PHASE4 "${CMAKE_CURRENT_BINARY_DIR}/${enzyme_add_executable_NAME}_opt.ll") + set(PHASE5 "${CMAKE_CURRENT_BINARY_DIR}/${enzyme_add_executable_NAME}") + + set(OBJS "") + set(includes "${enzyme_add_executable_INCLUDE_DIRECTORIES}") + + foreach(lib ${enzyme_add_executable_LINK_LIBRARIES}) + get_target_property(include ${lib} INCLUDE_DIRECTORIES) + set(includes "${includes}" ${include}) + + get_target_property(libsource ${lib} SOURCES) + string(FIND "${libsource}" "TARGET" found) + if(NOT(${found} EQUAL -1)) + list(APPEND LINKER_FLAGS "-Wl,${libsource}") + endif() + endforeach() + + foreach(dir ${includes}) + if(EXISTS ${dir}) + list(APPEND INCLUDE_COMPILER_LIST "-I${dir}") + endif() + endforeach() + + foreach(SRC ${enzyme_add_executable_SOURCES}) + set(PHASE0 "${CMAKE_CURRENT_SOURCE_DIR}/${SRC}") + set(PHASE1 "${CMAKE_CURRENT_BINARY_DIR}/${enzyme_add_executable_NAME}_${SRC}_compile.o") + add_custom_command( + DEPENDS ${PHASE0} + OUTPUT ${PHASE1} + COMMAND ${CMAKE_CXX_COMPILER} -flto -c ${PHASE0} ${INCLUDE_COMPILER_LIST} -O2 -fno-vectorize -ffast-math -fno-unroll-loops -o ${PHASE1} + COMMENT "Compiling ${SRC} to object file for target ${enzyme_add_executable_NAME}" + ) + set(OBJS "${OBJS} ${PHASE1}") + endforeach() + + cmake_language(EVAL CODE " + add_custom_command( + DEPENDS ${OBJS} + OUTPUT ${PHASE2} + COMMAND ${GRIDKIT_LLVM_LINK} ${OBJS} -o ${PHASE2} + COMMENT \"Linking object files to LLVM bytecode for target ${enzyme_add_executable_NAME}\" + ) + ") + + add_custom_command( + DEPENDS ${PHASE2} + OUTPUT ${PHASE3} + COMMAND ${GRIDKIT_OPT} ${PHASE2} -load-pass-plugin=${ENZYME_LLVM_PLUGIN_LIBRARY} -passes=enzyme -o ${PHASE3} -S + COMMENT "Running Enzyme opt pass on target ${enzyme_add_executable_NAME}" + ) + + add_custom_command( + DEPENDS ${PHASE3} + OUTPUT ${PHASE4} + COMMAND ${GRIDKIT_OPT} ${PHASE3} -O2 -o ${PHASE4} -S + COMMENT "Running remaining opt passes on target ${enzyme_add_executable_NAME}" + ) + + add_custom_command( + DEPENDS ${PHASE4} ${enzyme_add_executable_LINK_LIBRARIES} + OUTPUT ${PHASE5} + COMMAND ${CMAKE_CXX_COMPILER} ${LINKER_FLAGS} ${PHASE4} -o ${PHASE5} + ) + + add_custom_target( + "${enzyme_add_executable_NAME}_target" ALL + DEPENDS ${PHASE5} + ) +endmacro() diff --git a/cmake/FindIpopt.cmake b/cmake/FindIpopt.cmake new file mode 100644 index 000000000..4a99468d8 --- /dev/null +++ b/cmake/FindIpopt.cmake @@ -0,0 +1,63 @@ +# +#[[ + +Finds Ipopt include directory and libraries and exports target `Ipopt` + +User may set: +- IPOPT_ROOT_DIR + +Author(s): +- Cameron Rutherford + +]] + +find_library(IPOPT_LIBRARY + NAMES + ipopt + PATHS + ${IPOPT_DIR} $ENV{IPOPT_DIR} ${IPOPT_ROOT_DIR} ${IPOPT_LIBRARY_DIR} + ENV LD_LIBRARY_PATH ENV DYLD_LIBRARY_PATH + PATH_SUFFIXES + lib64 lib) + +if(IPOPT_LIBRARY) + set(IPOPT_LIBRARY CACHE FILEPATH "Path to Ipopt library") + message(STATUS "Found Ipopt library: " ${IPOPT_LIBRARY}) + get_filename_component(IPOPT_LIBRARY_DIR ${IPOPT_LIBRARY} DIRECTORY CACHE "Ipopt library directory") + mark_as_advanced(IPOPT_LIBRARY IPOPT_LIBRARY_DIR) + if(NOT IPOPT_DIR) + get_filename_component(IPOPT_DIR ${IPOPT_LIBRARY_DIR} DIRECTORY CACHE) + endif() +endif() + +find_path(IPOPT_INCLUDE_DIR + NAMES + IpTNLP.hpp + PATHS + ${IPOPT_DIR} ${IPOPT_ROOT_DIR} $ENV{IPOPT_DIR} ${IPOPT_LIBRARY_DIR}/.. + PATH_SUFFIXES + include + include/coin + include/coin-or + include/coinor) + +if(IPOPT_LIBRARY) + message(STATUS "Found Ipopt include: ${IPOPT_INCLUDE_DIR}") + mark_as_advanced(IPOPT_INCLUDE_DIR) + add_library(IPOPT INTERFACE IMPORTED) + target_link_libraries(IPOPT INTERFACE ${IPOPT_LIBRARY}) + target_include_directories(IPOPT INTERFACE ${IPOPT_INCLUDE_DIR}) +else() + if(NOT IPOPT_ROOT_DIR) + message(STATUS "Ipopt dir not found! Please provide correct filepath.") + set(IPOPT_DIR ${IPOPT_DIR} CACHE PATH "Path to Ipopt installation root.") + unset(IPOPT_INCLUDE_DIR CACHE) + unset(IPOPT_LIBRARY CACHE) + unset(IPOPT_LIBRARY_DIR CACHE) + elseif(NOT IPOPT_LIB) + message(STATUS "Ipopt library not found! Please provide correct filepath.") + endif() + if(IPOPT_ROOT_DIR AND NOT IPOPT_INCLUDE_DIR) + message(STATUS "Ipopt include directory not found! Please provide correct path.") + endif() +endif() diff --git a/cmake/FindSuiteSparse.cmake b/cmake/FindSuiteSparse.cmake new file mode 100644 index 000000000..2a3d678eb --- /dev/null +++ b/cmake/FindSuiteSparse.cmake @@ -0,0 +1,81 @@ +# +#[[ + +Finds Sutiesparse include directory and libraries and exports target `Suitesparse` + +User may set: +- SUITESPARSE_ROOT_DIR + +Author(s): +- Cameron Rutherford + +]] +set(SUITESPARSE_MODULES + amd + colamd + klu + suitesparseconfig) + +find_library(SUITESPARSE_LIBRARY + NAMES + ${SUITESPARSE_MODULES} + PATHS + ${SUITESPARSE_DIR} $ENV{SUITESPARSE_DIR} ${SUITESPARSE_ROOT_DIR} + ENV LD_LIBRARY_PATH ENV DYLD_LIBRARY_PATH + PATH_SUFFIXES + lib64 lib) + +if(SUITESPARSE_LIBRARY) + set(SUITESPARSE_LIBRARY CACHE FILEPATH "Path to Suitesparse library") + get_filename_component(SUITESPARSE_LIBRARY_DIR ${SUITESPARSE_LIBRARY} DIRECTORY CACHE "Suitesparse library directory") + message(STATUS "Found Suitesparse libraries in: " ${SUITESPARSE_LIBRARY_DIR}) + mark_as_advanced(SUITESPARSE_LIBRARY SUITESPARSE_LIBRARY_DIR) + if(NOT SUITESPARSE_DIR) + get_filename_component(SUITESPARSE_DIR ${SUITESPARSE_LIBRARY_DIR} DIRECTORY CACHE) + endif() +endif() + +# Find SUITESPARSE header path and ensure all needed files are there +find_path(SUITESPARSE_INCLUDE_DIR + NAMES + amd.h + colamd.h + klu.h + SuiteSparse_config.h + PATHS + ${SUITESPARSE_DIR} $ENV{SUITESPARSE_DIR} ${SUITESPARSE_ROOT_DIR} ${SUITESPARSE_LIBRARY_DIR}/.. + PATH_SUFFIXES + include) + +if(SUITESPARSE_LIBRARY) + message(STATUS "Found Suitesparse include: ${SUITESPARSE_INCLUDE_DIR}") + mark_as_advanced(SUITESPARSE_INCLUDE_DIR) + unset(SUITESPARSE_LIBRARY) + add_library(SUITESPARSE INTERFACE IMPORTED) + target_include_directories(SUITESPARSE INTERFACE ${SUITESPARSE_INCLUDE_DIR}) + foreach(mod ${SUITESPARSE_MODULES}) + find_library(suitesparse_${mod} + NAMES ${mod} + HINTS ${SUITESPARSE_LIBRARY_DIR}) + if(suitesparse_${mod}) + message(STATUS "Found suitesparse internal library " ${mod}) + target_link_libraries(SUITESPARSE INTERFACE ${suitesparse_${mod}}) + mark_as_advanced(suitesparse_${mod}) + else() + message(SEND_ERROR "Suitesparse internal library " ${mod} " not found") + endif() + endforeach(mod) +else() + if(NOT SUITESPARSE_ROOT_DIR) + message(STATUS "Suitesparse dir not found! Please provide correct filepath.") + set(SUITESPARSE_DIR ${SUITESPARSE_DIR} CACHE PATH "Path to Suitesparse installation root.") + unset(SUITESPARSE_LIBRARY CACHE) + unset(SUITESPARSE_INCLUDE_DIR CACHE) + unset(SUITESPARSE_LIBRARY_DIR CACHE) + elseif(NOT SUITESPARSE_LIBRARY) + message(STATUS "Suitesparse library not found! Please provide correct filepath.") + endif() + if(SUITESPARSE_ROOT_DIR AND NOT SUITESPARSE_INCLUDE_DIR) + message(STATUS "Suitesparse include dir not found! Please provide correct filepath.") + endif() +endif() diff --git a/CMake/GridkitAddLibrary.cmake b/cmake/GridkitAddLibrary.cmake similarity index 100% rename from CMake/GridkitAddLibrary.cmake rename to cmake/GridkitAddLibrary.cmake diff --git a/docs/.gitkeep b/docs/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/Documentation/Figures/EXDC1.JPG b/docs/Figures/EXDC1.JPG similarity index 100% rename from Documentation/Figures/EXDC1.JPG rename to docs/Figures/EXDC1.JPG diff --git a/Documentation/Figures/GENROU.JPG b/docs/Figures/GENROU.JPG similarity index 100% rename from Documentation/Figures/GENROU.JPG rename to docs/Figures/GENROU.JPG diff --git a/Documentation/Figures/GENSAL.JPG b/docs/Figures/GENSAL.JPG similarity index 100% rename from Documentation/Figures/GENSAL.JPG rename to docs/Figures/GENSAL.JPG diff --git a/Documentation/Figures/PSS1A.JPG b/docs/Figures/PSS1A.JPG similarity index 100% rename from Documentation/Figures/PSS1A.JPG rename to docs/Figures/PSS1A.JPG diff --git a/Documentation/Figures/SM1.JPG b/docs/Figures/SM1.JPG similarity index 100% rename from Documentation/Figures/SM1.JPG rename to docs/Figures/SM1.JPG diff --git a/Documentation/Figures/TGOV1.JPG b/docs/Figures/TGOV1.JPG similarity index 100% rename from Documentation/Figures/TGOV1.JPG rename to docs/Figures/TGOV1.JPG diff --git a/Documentation/Figures/TL.jpg b/docs/Figures/TL.jpg similarity index 100% rename from Documentation/Figures/TL.jpg rename to docs/Figures/TL.jpg diff --git a/Documentation/Figures/branch.jpg b/docs/Figures/branch.jpg similarity index 100% rename from Documentation/Figures/branch.jpg rename to docs/Figures/branch.jpg diff --git a/docs/Figures/branch_phasor_dynamics.png b/docs/Figures/branch_phasor_dynamics.png new file mode 100644 index 000000000..2d13c9ab2 Binary files /dev/null and b/docs/Figures/branch_phasor_dynamics.png differ diff --git a/Documentation/Figures/bus_variables.jpg b/docs/Figures/bus_variables.jpg similarity index 100% rename from Documentation/Figures/bus_variables.jpg rename to docs/Figures/bus_variables.jpg diff --git a/Documentation/Figures/example1.jpg b/docs/Figures/example1.jpg similarity index 100% rename from Documentation/Figures/example1.jpg rename to docs/Figures/example1.jpg diff --git a/Documentation/Figures/gen1.png b/docs/Figures/gen1.png similarity index 100% rename from Documentation/Figures/gen1.png rename to docs/Figures/gen1.png diff --git a/Documentation/Figures/gen2.png b/docs/Figures/gen2.png similarity index 100% rename from Documentation/Figures/gen2.png rename to docs/Figures/gen2.png diff --git a/docs/Figures/transformer-branch.png b/docs/Figures/transformer-branch.png new file mode 100644 index 000000000..084cf0ab8 Binary files /dev/null and b/docs/Figures/transformer-branch.png differ diff --git a/docs/LICENSE.LLNS b/docs/LICENSE.LLNS new file mode 100644 index 000000000..7c44911c8 --- /dev/null +++ b/docs/LICENSE.LLNS @@ -0,0 +1,63 @@ +******************************************************************************* + +GridKit™: ................................, version 0.0.5 + +Copyright (c) 2017, Lawrence Livermore National Security, LLC. +Produced at the Lawrence Livermore National Laboratory. +Written by Slaven Peles . +LLNL-CODE-718378. +OCEC-17-011 +All rights reserved. + + +******************************************************************************* + +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) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Additional BSD Notice +--------------------- + +1. This notice is required to be provided under our contract with the U.S. +Department of Energy (DOE). This work was produced at Lawrence Livermore +National Laboratory under Contract No. DE-AC52-07NA27344 with the DOE. + +2. Neither the United States Government nor Lawrence Livermore National +Security, LLC nor any of their employees, makes any warranty, express or +implied, or assumes any 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. + +3. Also, reference herein to any specific commercial products, process, +or services 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. diff --git a/examples/AdjointSensitivity/AdjointSensitivity.cpp b/examples/AdjointSensitivity/AdjointSensitivity.cpp new file mode 100644 index 000000000..bab5f20df --- /dev/null +++ b/examples/AdjointSensitivity/AdjointSensitivity.cpp @@ -0,0 +1,142 @@ + +#include +#include + +#include +#include +#include +#include +#include + +/* + * Compute gradient of an objective function expressed as an integral over + * system trajectory. The gradient is computed numerically and using + * adjoint sensitivity analysis. + * + * The test case is a 4th order generator connected to an infinite bus. + * The objective function is total frequency deviation computed over + * system trajectory after generator short circuit fault. + * + */ +int main() +{ + using namespace GridKit; + using namespace AnalysisManager::Sundials; + using namespace AnalysisManager; + using namespace GridKit::Testing; + + // Create an infinite bus + BaseBus* bus = new BusSlack(1.0, 0.0); + + // Attach a generator to that bus + Generator4* gen = new Generator4(bus, 0.8, 0.3); + + // Create a system model + SystemModel* model = new SystemModel(); + model->addBus(bus); + model->addComponent(gen); + + // allocate model components + model->allocate(); + + // Create numerical integrator and configure it for the generator model + Ida* idas = new Ida(model); + + double t_init = 0.0; + double t_final = 15.0; + + // setup simulation + idas->configureSimulation(); + idas->configureAdjoint(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init); + idas->configureQuadrature(); + idas->initializeQuadrature(); + + idas->runSimulation(0.1, 2); + idas->saveInitialCondition(); + + // create initial condition after a fault + { + idas->getSavedInitialCondition(); + idas->initializeSimulation(t_init); + gen->V() = 0.0; + idas->runSimulation(0.1, 20); + gen->V() = 1.0; + idas->saveInitialCondition(); + } + + // Get pointer the objective function + const double* Q = idas->getIntegral(); + + // Compute the objective function as an integral over the system trajectory + idas->getSavedInitialCondition(); + idas->initializeSimulation(t_init); + idas->initializeQuadrature(); + idas->runSimulationQuadrature(t_final, 100); + + std::cout << "\n\nCost of computing objective function:\n\n"; + idas->printFinalStats(); + + const double g1 = Q[0]; + const double eps = 2e-3; + + // Compute gradient of the objective function numerically + std::vector dGdp(model->sizeParams()); + + for (unsigned i = 0; i < model->sizeParams(); ++i) + { + model->param()[i] += eps; + idas->getSavedInitialCondition(); + idas->initializeSimulation(t_init); + idas->initializeQuadrature(); + idas->runSimulationQuadrature(t_final, 100); + + std::cout << "\n\nCost of computing derivative with respect to parameter " + << i << ":\n\n"; + idas->printFinalStats(); + double g2 = Q[0]; + + // restore parameter to original value + model->param()[i] -= eps; + + // Evaluate dG/dp numerically + dGdp[i] = (g2 - g1) / eps; + } + + // Compute gradient of the objective function using adjoint method + idas->initializeAdjoint(); + idas->getSavedInitialCondition(); + idas->initializeSimulation(t_init); + idas->initializeQuadrature(); + idas->runForwardSimulation(t_final, 100); + + std::cout << "\n\nCost of forward simulation for adjoint\n" + << "sensitivity analysis:\n\n"; + idas->printFinalStats(); + + idas->initializeBackwardSimulation(t_final); + idas->runBackwardSimulation(t_init); + + std::cout << "\n\nCost of adjoint sensitivity analysis:\n\n"; + idas->printFinalStats(); + + // Compare results + int retval = 0; + std::cout << "\n\nComparison of numerical and adjoint results:\n\n"; + double* neg_dGdp = idas->getAdjointIntegral(); + for (unsigned i = 0; i < model->sizeParams(); ++i) + { + std::cout << "dG/dp" << i << " (numerical) = " << dGdp[i] << "\n"; + std::cout << "dG/dp" << i << " (adjoint) = " << -neg_dGdp[i] << "\n\n"; + if (!isEqual(dGdp[i], -neg_dGdp[i], 10 * eps)) + --retval; + } + + if (retval < 0) + { + std::cout << "The two results differ beyond solver tolerance!\n"; + } + + return retval; +} diff --git a/examples/AdjointSensitivity/CMakeLists.txt b/examples/AdjointSensitivity/CMakeLists.txt new file mode 100644 index 000000000..b4bdecf8e --- /dev/null +++ b/examples/AdjointSensitivity/CMakeLists.txt @@ -0,0 +1,12 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +add_executable(adjoint AdjointSensitivity.cpp) +target_link_libraries(adjoint GRIDKIT::bus GRIDKIT::generator4 GRIDKIT::solvers_dyn) +install(TARGETS adjoint DESTINATION bin) + +add_test(NAME AdjointSens COMMAND $ ) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 000000000..6e0382b71 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,27 @@ +# + +add_subdirectory(MatPowerTesting) +add_subdirectory(LinearAlgebra) +add_subdirectory(DistributedGeneratorTest) + +if(TARGET SUNDIALS::kinsol) + add_subdirectory(Grid3Bus) +endif() + +if(TARGET SUNDIALS::idas) + add_subdirectory(AdjointSensitivity) + add_subdirectory(RLCircuit) + add_subdirectory(Microgrid) + add_subdirectory(ScaleMicrogrid) + add_subdirectory(PhasorDynamics) + if(GRIDKIT_ENABLE_IPOPT) + add_subdirectory(DynamicConstrainedOpt) + add_subdirectory(GenConstLoad) + add_subdirectory(GenInfiniteBus) + add_subdirectory(ParameterEstimation) + endif() +endif() + +if(GRIDKIT_ENABLE_ENZYME) + add_subdirectory(Enzyme) +endif() diff --git a/examples/DistributedGeneratorTest/CMakeLists.txt b/examples/DistributedGeneratorTest/CMakeLists.txt new file mode 100644 index 000000000..6ed544e93 --- /dev/null +++ b/examples/DistributedGeneratorTest/CMakeLists.txt @@ -0,0 +1,12 @@ + + + + +add_executable(dgtest DGTest.cpp) +target_link_libraries(dgtest GRIDKIT::power_elec_disgen + GRIDKIT::power_elec_microline + GRIDKIT::power_elec_microload + GRIDKIT::solvers_dyn) + +add_test(NAME DistributedGeneratorTest COMMAND $) +install(TARGETS dgtest RUNTIME DESTINATION bin) diff --git a/examples/DistributedGeneratorTest/DGTest.cpp b/examples/DistributedGeneratorTest/DGTest.cpp new file mode 100644 index 000000000..10e10c58a --- /dev/null +++ b/examples/DistributedGeneratorTest/DGTest.cpp @@ -0,0 +1,84 @@ + + +#include +#include +#include +#include +#include +#include + +#include + +/** + * @brief Testing for the Distributed Generators outputs + * + * @param argc + * @param argv + * @return int + */ +int main(int argc, char const* argv[]) +{ + + GridKit::DistributedGeneratorParameters parms; + // Parameters from MATLAB Microgrid code for first DG + parms.wb_ = 2.0 * M_PI * 50.0; + parms.wc_ = 31.41; + parms.mp_ = 9.4e-5; + parms.Vn_ = 380; + parms.nq_ = 1.3e-3; + parms.F_ = 0.75; + parms.Kiv_ = 420.0; + parms.Kpv_ = 0.1; + parms.Kic_ = 20.0 * 1.0e3; + parms.Kpc_ = 15.0; + parms.Cf_ = 50.0e-6; + parms.rLf_ = 0.1; + parms.Lf_ = 1.35e-3; + parms.rLc_ = 0.03; + parms.Lc_ = 0.35e-3; + + GridKit::DistributedGenerator* dg = new GridKit::DistributedGenerator(0, parms, true); + + std::vector t1(16, 0.0); + std::vector t2{0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5}; + + dg->allocate(); + + dg->y() = t2; + dg->yp() = t1; + + dg->evaluateResidual(); + + std::cout << "Output: {"; + for (double i : dg->getResidual()) + { + printf("%e ,", i); + } + std::cout << "}\n"; + + // Generated from matlab code with same parameters and inputs + std::vector true_vec{3.141592277589793e+02, + 8.941907747838389e-01, + 1.846733023014284e+00, + 3.141592277589793e+02, + 1.014543000000000e+02, + -1.507680000000000e+01, + 3.787993500000000e+02, + -1.300000000000000e+00, + 2.899095146477517e+02, + 2.939138495559215e+02, + 1.507210571826699e+07, + 1.659799832843673e+07, + -7.591593003913325e+03, + -8.376991073310774e+03, + 3.337988298081817e+03, + 2.684419146397466e+03}; + + std::cout << "Test the Relative Error\n"; + for (size_t i = 0; i < true_vec.size(); i++) + { + printf("%e ,\n", (true_vec[i] - dg->getResidual()[i]) / true_vec[i]); + } + + return 0; +} diff --git a/examples/DynamicConstrainedOpt/CMakeLists.txt b/examples/DynamicConstrainedOpt/CMakeLists.txt new file mode 100644 index 000000000..5df1750c2 --- /dev/null +++ b/examples/DynamicConstrainedOpt/CMakeLists.txt @@ -0,0 +1,20 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +# - Slaven Peles +#]] + +add_executable(dynconopt DynamicConstrainedOpt.cpp) +target_link_libraries(dynconopt + GRIDKIT::generator4 + GRIDKIT::generator2 + GRIDKIT::bus GRIDKIT::solvers_dyn + GRIDKIT::solvers_opt +) +# Fortran linker needed to link to HSL solvers +set_property(TARGET dynconopt PROPERTY LINKER_LANGUAGE Fortran) +install(TARGETS dynconopt DESTINATION bin) + +add_test(NAME DynamicConOpt COMMAND $) diff --git a/examples/DynamicConstrainedOpt/DynamicConstrainedOpt.cpp b/examples/DynamicConstrainedOpt/DynamicConstrainedOpt.cpp new file mode 100644 index 000000000..b8def3c11 --- /dev/null +++ b/examples/DynamicConstrainedOpt/DynamicConstrainedOpt.cpp @@ -0,0 +1,154 @@ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + using namespace GridKit; + using namespace AnalysisManager::Sundials; + using namespace AnalysisManager; + using namespace GridKit::Testing; + + // Create an infinite bus + BaseBus* bus = new BusSlack(1.0, 0.0); + + // Attach a generator to that bus + Generator2* gen = new Generator2(bus); + + // Create a system model + SystemModel* model = new SystemModel(); + model->addBus(bus); + model->addComponent(gen); + + // allocate model components + model->allocate(); + + // Create numerical integrator and configure it for the generator model + Ida* idas = new Ida(model); + + double t_init = 0.0; + double t_final = 20.0; + + // setup simulation + idas->configureSimulation(); + idas->configureAdjoint(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init); + idas->configureQuadrature(); + idas->initializeQuadrature(); + + double t_fault = 0.02; + double t_clear = 0.06; + idas->runSimulation(t_fault); + // create initial condition after a fault + { + gen->V() = 0.0; + idas->runSimulation(t_clear, 2); + gen->V() = 1.0; + gen->theta() = -0.01; + idas->saveInitialCondition(); + } + + // Set integration time for dynamic constrained optimization + idas->setIntegrationTime(t_init, t_final, 100); + + // Guess optimization parameter value + double Pm = 0.7; + + // Create an instance of the IpoptApplication + Ipopt::SmartPtr ipoptApp = IpoptApplicationFactory(); + + // Initialize the IpoptApplication and process the options + Ipopt::ApplicationReturnStatus status; + status = ipoptApp->Initialize(); + if (status != Ipopt::Solve_Succeeded) + { + std::cout << "\n\n*** Initialization failed! ***\n\n"; + return (int) status; + } + + // Set solver tolerance + const double tol = 1e-4; + + // Configure Ipopt application + ipoptApp->Options()->SetStringValue("hessian_approximation", "limited-memory"); + ipoptApp->Options()->SetNumericValue("tol", tol); + ipoptApp->Options()->SetIntegerValue("print_level", 0); + + // Create dynamic objective interface to Ipopt solver + Ipopt::SmartPtr ipoptDynamicObjectiveInterface = + new IpoptInterface::DynamicObjective(idas); + + // Initialize problem + model->param()[0] = Pm; + + // Solve the problem + status = ipoptApp->OptimizeTNLP(ipoptDynamicObjectiveInterface); + std::cout << "\n\nProblem formulated as dynamic objective optimization ...\n"; + + if (status == Ipopt::Solve_Succeeded) + { + // Print result + std::cout << "\nSucess:\n The problem solved in " + << ipoptApp->Statistics()->IterationCount() << " iterations!\n" + << " Optimal value of Pm = " << model->param()[0] << "\n" + << " The final value of the objective function G(Pm) = " + << ipoptApp->Statistics()->FinalObjective() << "\n\n"; + } + + // Store dynamic objective optimization results + double* results = new double[model->sizeParams()]; + for (unsigned i = 0; i < model->sizeParams(); ++i) + { + results[i] = model->param()[i]; + } + + // Create dynamic constraint interface to Ipopt solver + Ipopt::SmartPtr ipoptDynamicConstraintInterface = + new IpoptInterface::DynamicConstraint(idas); + + // Initialize problem + model->param()[0] = Pm; + + // Solve the problem + status = ipoptApp->OptimizeTNLP(ipoptDynamicConstraintInterface); + std::cout << "\n\nProblem formulated as dynamic constraint optimization ...\n"; + + if (status == Ipopt::Solve_Succeeded) + { + // Print result + std::cout << "\nSucess:\n The problem solved in " + << ipoptApp->Statistics()->IterationCount() << " iterations!\n" + << " Optimal value of Pm = " << model->param()[0] << "\n" + << " The final value of the objective function G(Pm) = " + << ipoptApp->Statistics()->FinalObjective() << "\n\n"; + } + + // Compare results of the two optimization methods + int retval = 0; + for (unsigned i = 0; i < model->sizeParams(); ++i) + { + if (!isEqual(results[i], model->param()[i], 10 * tol)) + --retval; + } + + if (retval < 0) + { + std::cout << "The two results differ beyond solver tolerance!\n"; + } + + delete[] results; + delete idas; + delete model; + return retval; +} diff --git a/examples/Enzyme/CMakeLists.txt b/examples/Enzyme/CMakeLists.txt new file mode 100644 index 000000000..f7ed45025 --- /dev/null +++ b/examples/Enzyme/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(Standalone) +add_subdirectory(Library) +add_subdirectory(PowerElectronics) diff --git a/examples/Enzyme/Library/CMakeLists.txt b/examples/Enzyme/Library/CMakeLists.txt new file mode 100644 index 000000000..6dec74892 --- /dev/null +++ b/examples/Enzyme/Library/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(Scalar) +add_subdirectory(Vector) diff --git a/examples/Enzyme/Library/Scalar/CMakeLists.txt b/examples/Enzyme/Library/Scalar/CMakeLists.txt new file mode 100644 index 000000000..6dff430a6 --- /dev/null +++ b/examples/Enzyme/Library/Scalar/CMakeLists.txt @@ -0,0 +1,6 @@ +enzyme_add_executable( + NAME EnzymeLibScalarCheck + SOURCES EnzymeScalar.cpp ScalarModel.cpp +) + +add_test(NAME "EnzymeLibScalarCheck" COMMAND ${CMAKE_CURRENT_BINARY_DIR}/EnzymeLibScalarCheck) diff --git a/examples/Enzyme/Library/Scalar/EnzymeScalar.cpp b/examples/Enzyme/Library/Scalar/EnzymeScalar.cpp new file mode 100644 index 000000000..a20f69e13 --- /dev/null +++ b/examples/Enzyme/Library/Scalar/EnzymeScalar.cpp @@ -0,0 +1,33 @@ +#include +#include + +#include "ScalarModel.hpp" + +/** + * @brief Example that computes the derivative of a library function + * (implemented as the member function of a class and operating directly on class members) + * by automatic differentiation via Enzyme. + * + * TODO: Convert this into a unit test. + */ + +int main() +{ + int fail = 0; + ScalarModel scalar_model; + double var = 5.0; + scalar_model.setVariable(var); + scalar_model.evalFunction(); + scalar_model.evalDerivative(); + double sq = scalar_model.getFunctionValue(); + double dsq = scalar_model.getDerivativeValue(); + + std::cout << "x = " << var << ", x^2 = " << sq << ", d(x^2)/dx = " << dsq << "\n"; + if (std::abs(dsq - 2.0 * var) > std::numeric_limits::epsilon()) + { + fail++; + std::cout << "Result incorrect\n"; + } + std::cout << "Status: " << fail << "\n"; + return fail; +} diff --git a/examples/Enzyme/Library/Scalar/EnzymeWrapper.hpp b/examples/Enzyme/Library/Scalar/EnzymeWrapper.hpp new file mode 100644 index 000000000..57d582700 --- /dev/null +++ b/examples/Enzyme/Library/Scalar/EnzymeWrapper.hpp @@ -0,0 +1,16 @@ +#pragma once + +int enzyme_dup; +int enzyme_dupnoneed; +int enzyme_out; +int enzyme_const; + +template +return_type __enzyme_fwddiff(return_type*, int, T*...); + +template +return_type wrapper(T* obj) +{ + obj->evalFunction(); + return obj->getFunctionValue(); +} diff --git a/examples/Enzyme/Library/Scalar/ScalarModel.cpp b/examples/Enzyme/Library/Scalar/ScalarModel.cpp new file mode 100644 index 000000000..0d0a790fb --- /dev/null +++ b/examples/Enzyme/Library/Scalar/ScalarModel.cpp @@ -0,0 +1,50 @@ +#include "ScalarModel.hpp" + +#include + +#include "EnzymeWrapper.hpp" + +ScalarModel::ScalarModel() +{ +} + +inline double ScalarModel::square(double x) +{ + return x * x; +} + +void ScalarModel::setVariable(double x) +{ + x_ = x; +} + +void ScalarModel::evalFunction() +{ + f_ = square(x_); +} + +void ScalarModel::evalDerivative() +{ + ScalarModel d_scalar_model; + d_scalar_model.setVariable(1.0); + df_dx_ = __enzyme_fwddiff((double*) wrapper, enzyme_dup, this, &d_scalar_model); +} + +double ScalarModel::getVariable() const +{ + return x_; +} + +double ScalarModel::getFunctionValue() const +{ + return f_; +} + +double ScalarModel::getDerivativeValue() const +{ + return df_dx_; +} + +ScalarModel::~ScalarModel() +{ +} diff --git a/examples/Enzyme/Library/Scalar/ScalarModel.hpp b/examples/Enzyme/Library/Scalar/ScalarModel.hpp new file mode 100644 index 000000000..091502955 --- /dev/null +++ b/examples/Enzyme/Library/Scalar/ScalarModel.hpp @@ -0,0 +1,22 @@ +#pragma once + +/** + * @brief Class providing methods to evaluate a function and its derivative. + * This is used to test automatic differentiation. + */ +class ScalarModel +{ +private: + double x_, f_, df_dx_; + inline double square(double); + +public: + ScalarModel(); + void setVariable(double); + void evalFunction(); + void evalDerivative(); + double getVariable() const; + double getFunctionValue() const; + double getDerivativeValue() const; + ~ScalarModel(); +}; diff --git a/examples/Enzyme/Library/Vector/CMakeLists.txt b/examples/Enzyme/Library/Vector/CMakeLists.txt new file mode 100644 index 000000000..eda952de8 --- /dev/null +++ b/examples/Enzyme/Library/Vector/CMakeLists.txt @@ -0,0 +1,7 @@ +enzyme_add_executable( + NAME EnzymeLibVectorCheck + SOURCES EnzymeVector.cpp VectorModel.cpp + LINK_LIBRARIES GRIDKIT::DenseMatrix +) + +add_test(NAME "EnzymeLibVectorCheck" COMMAND ${CMAKE_CURRENT_BINARY_DIR}/EnzymeLibVectorCheck) diff --git a/examples/Enzyme/Library/Vector/EnzymeVector.cpp b/examples/Enzyme/Library/Vector/EnzymeVector.cpp new file mode 100644 index 000000000..8a3e69259 --- /dev/null +++ b/examples/Enzyme/Library/Vector/EnzymeVector.cpp @@ -0,0 +1,88 @@ +#include +#include + +#include "VectorModel.hpp" + +/** + * @brief Example that computes the Jacobian of a vector-valued residual + * (implemented as the member function of a class and operating directly on class members) + * by automatic differentiation via Enzyme. + * + * TODO: Convert this into a unit test. + */ + +inline double dsquare_ref_scalar(double x) +{ + return 2.0 * x; +} + +// Reference Jacobian +DenseMatrix dsquare_ref(std::vector x, std::vector y) +{ + DenseMatrix jac(x.size(), y.size()); + for (int idy = 0; idy < y.size(); ++idy) + { + for (int idx = 0; idx < x.size(); ++idx) + { + if (idx == idy) + jac.setValue(idx, idy, dsquare_ref_scalar(x[idx])); + } + } + return jac; +} + +int main() +{ + // Size and variable declarations + constexpr int n = 10; + std::vector var(n); + + // Random input values + srand(time(NULL)); + for (int idx = 0; idx < var.size(); ++idx) + { + var[idx] = rand(); + } + + // Model + VectorModel* vector_model = new VectorModel(n); + vector_model->setVariable(var); + vector_model->evalResidual(); + vector_model->evalJacobian(); + std::vector var_temp = vector_model->getVariable(); + std::vector res = vector_model->getResidual(); + DenseMatrix jac = vector_model->getJacobian(); + + // Reference Jacobian + DenseMatrix jac_ref = dsquare_ref(var, res); + + // Check + int fail = 0; + bool verbose = true; + for (int idy = 0; idy < res.size(); ++idy) + { + for (int idx = 0; idx < var.size(); ++idx) + { + if (std::abs(jac.getValue(idx, idy) - jac_ref.getValue(idx, idy)) > std::numeric_limits::epsilon()) + { + fail++; + if (verbose) + { + std::cout << "Result incorrect at line = " << idy << ", column = " << idx << "\n"; + std::cout << "x = " << var_temp[idx] << ", x^2 = " << res[idx] << ", d(x^2)/dx = " << jac.getValue(idx, idy) << "\n"; + } + } + } + } + if (verbose) + { + jac.printMatrix("Autodiff Jacobian"); + jac_ref.printMatrix("Reference Jacobian"); + } + std::cout << "Status: " << fail << "\n"; + + // Cleanup + delete vector_model; + + return fail; +} diff --git a/examples/Enzyme/Library/Vector/EnzymeWrapper.hpp b/examples/Enzyme/Library/Vector/EnzymeWrapper.hpp new file mode 100644 index 000000000..588436f36 --- /dev/null +++ b/examples/Enzyme/Library/Vector/EnzymeWrapper.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include + +int enzyme_dup; +int enzyme_dupnoneed; +int enzyme_out; +int enzyme_const; + +template +std::vector __enzyme_fwddiff(std::vector*, int, T*, T*); + +template +std::vector wrapper(T* obj) +{ + obj->evalResidual(); + return obj->getResidual(); +} diff --git a/examples/Enzyme/Library/Vector/VectorModel.cpp b/examples/Enzyme/Library/Vector/VectorModel.cpp new file mode 100644 index 000000000..cb4d89f5e --- /dev/null +++ b/examples/Enzyme/Library/Vector/VectorModel.cpp @@ -0,0 +1,87 @@ +#include "VectorModel.hpp" + +#include + +#include "EnzymeWrapper.hpp" + +VectorModel::VectorModel(int n) + : x_(n), + f_(n), + df_dx_(n, n) +{ +} + +inline double VectorModel::square_scalar(double x) +{ + return x * x; +} + +void VectorModel::square(std::vector& x, std::vector& y) +{ + for (int idx = 0; idx < x.size(); ++idx) + { + y[idx] = this->square_scalar(x[idx]); + } +} + +void VectorModel::setVariable(std::vector x) +{ + for (int idx = 0; idx < x.size(); ++idx) + { + x_[idx] = x[idx]; + } +} + +void VectorModel::evalResidual() +{ + square(x_, f_); +} + +void VectorModel::evalJacobian() +{ + const int n = x_.size(); + std::vector v(n); + VectorModel d_vector_model(n); + for (int idy = 0; idy < n; ++idy) + { + // Elementary vector for Jacobian-vector product + for (int idx = 0; idx < n; ++idx) + { + v[idx] = 0.0; + } + v[idy] = 1.0; + d_vector_model.setVariable(v); + + // Autodiff + std::vector d_res = __enzyme_fwddiff( + (std::vector*) wrapper, + enzyme_dup, + this, + &d_vector_model); + + // Store result + for (int idx = 0; idx < n; ++idx) + { + df_dx_.setValue(idx, idy, d_res[idx]); + } + } +} + +std::vector& VectorModel::getVariable() +{ + return x_; +} + +std::vector& VectorModel::getResidual() +{ + return f_; +} + +DenseMatrix& VectorModel::getJacobian() +{ + return df_dx_; +} + +VectorModel::~VectorModel() +{ +} diff --git a/examples/Enzyme/Library/Vector/VectorModel.hpp b/examples/Enzyme/Library/Vector/VectorModel.hpp new file mode 100644 index 000000000..da66f696f --- /dev/null +++ b/examples/Enzyme/Library/Vector/VectorModel.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +using DenseMatrix = GridKit::LinearAlgebra::DenseMatrix; + +/** + * @brief Class providing methods to evaluate a vector-valued residual and its Jacobian. + * This is used to test automatic differentiation. + */ +class VectorModel +{ +private: + std::vector x_, f_; + DenseMatrix df_dx_; + inline double square_scalar(double); + void square(std::vector&, std::vector&); + +public: + VectorModel(int); + void setVariable(std::vector); + void evalResidual(); + void evalJacobian(); + std::vector& getVariable(); + std::vector& getResidual(); + DenseMatrix& getJacobian(); + ~VectorModel(); +}; diff --git a/examples/Enzyme/PowerElectronics/CMakeLists.txt b/examples/Enzyme/PowerElectronics/CMakeLists.txt new file mode 100644 index 000000000..a8e74e881 --- /dev/null +++ b/examples/Enzyme/PowerElectronics/CMakeLists.txt @@ -0,0 +1,7 @@ +enzyme_add_executable( + NAME EnzymePowerElectronicsCheck + SOURCES main.cpp + LINK_LIBRARIES GRIDKIT::DenseMatrix GRIDKIT::power_elec_disgen +) + +add_test(NAME "EnzymePowerElectronicsCheck" COMMAND ${CMAKE_CURRENT_BINARY_DIR}/EnzymePowerElectronicsCheck) diff --git a/examples/Enzyme/PowerElectronics/main.cpp b/examples/Enzyme/PowerElectronics/main.cpp new file mode 100644 index 000000000..eff14ddb0 --- /dev/null +++ b/examples/Enzyme/PowerElectronics/main.cpp @@ -0,0 +1,199 @@ +#include +#include + +#include +#include +#include + +/** + * @brief Standalone example that computes the Jacobian associated with the + * residual function of DistributedGenerator. We compare the Jacobian obtained + * by automatic differentiation via Enzyme to the analytical Jacobian + * implemented witin GridKit. + * + * TODO: Move automatic differentiation inside GridKit and convert this into a unit test. + */ + +using DenseMatrix = GridKit::LinearAlgebra::DenseMatrix; +using SparseMatrix = COO_Matrix; +using DG = GridKit::DistributedGenerator; +using DGParameters = GridKit::DistributedGeneratorParameters; + +int enzyme_dupnoneed; +int enzyme_dup; +int enzyme_const; +void __enzyme_fwddiff(void*, int, std::vector, std::vector, int, std::vector, std::vector*); + +// Copy from DistributedGenerator::evaluateResidual +// Need to find a way to differentiate the member function directly +void evaluateResidual(std::vector y_, std::vector f_) +{ + constexpr double wb_ = 2.0 * M_PI * 50.0; + constexpr double wc_ = 31.41; + constexpr double mp_ = 9.4e-5; + constexpr double Vn_ = 380.0; + constexpr double nq_ = 1.3e-3; + constexpr double F_ = 0.75; + constexpr double Kiv_ = 420.0; + constexpr double Kpv_ = 0.1; + constexpr double Kic_ = 2.0e4; + constexpr double Kpc_ = 15.0; + constexpr double Cf_ = 5.0e-5; + constexpr double rLf_ = 0.1; + constexpr double Lf_ = 1.35e-3; + constexpr double rLc_ = 0.03; + constexpr double Lc_ = 0.35e-3; + + constexpr bool ref_frame_ = true; + + std::vector yp_(0); + + double omega = wb_ - mp_ * y_[4]; + if (ref_frame_) + { + f_[0] = omega - y_[0]; + } + else + { + f_[0] = 0.0; + } + + f_[1] = cos(y_[3]) * y_[14] - sin(y_[3]) * y_[15]; + f_[2] = sin(y_[3]) * y_[14] + cos(y_[3]) * y_[15]; + + double vbd_in = cos(y_[3]) * y_[1] + sin(y_[3]) * y_[2]; + double vbq_in = -sin(y_[3]) * y_[1] + cos(y_[3]) * y_[2]; + + f_[3] = -yp_[3] + omega - y_[0]; + f_[4] = -yp_[4] + wc_ * (y_[12] * y_[14] + y_[13] * y_[15] - y_[4]); + f_[5] = -yp_[5] + wc_ * (-y_[12] * y_[15] + y_[13] * y_[14] - y_[5]); + + double vod_star = Vn_ - nq_ * y_[5]; + double voq_star = 0.0; + + f_[6] = -yp_[6] + vod_star - y_[12]; + f_[7] = -yp_[7] + voq_star - y_[13]; + + double ild_star = F_ * y_[14] - wb_ * Cf_ * y_[13] + Kpv_ * (vod_star - y_[12]) + Kiv_ * y_[6]; + double ilq_star = F_ * y_[15] + wb_ * Cf_ * y_[12] + Kpv_ * (voq_star - y_[13]) + Kiv_ * y_[7]; + + f_[8] = -yp_[8] + ild_star - y_[10]; + f_[9] = -yp_[9] + ilq_star - y_[11]; + + double vid_star = -wb_ * Lf_ * y_[11] + Kpc_ * (ild_star - y_[10]) + Kic_ * y_[8]; + double viq_star = wb_ * Lf_ * y_[10] + Kpc_ * (ilq_star - y_[11]) + Kic_ * y_[9]; + + f_[10] = -yp_[10] - (rLf_ / Lf_) * y_[10] + omega * y_[11] + (vid_star - y_[12]) / Lf_; + f_[11] = -yp_[11] - (rLf_ / Lf_) * y_[11] - omega * y_[10] + (viq_star - y_[13]) / Lf_; + + f_[12] = -yp_[12] + omega * y_[13] + (y_[10] - y_[14]) / Cf_; + f_[13] = -yp_[13] - omega * y_[12] + (y_[11] - y_[15]) / Cf_; + + f_[14] = -yp_[14] - (rLc_ / Lc_) * y_[14] + omega * y_[15] + (y_[12] - vbd_in) / Lc_; + f_[15] = -yp_[15] - (rLc_ / Lc_) * y_[15] - omega * y_[14] + (y_[13] - vbq_in) / Lc_; +} + +// Function that computes the Jacobian via automatic differentiation +template +void EnzymeModelJacobian(T* model, DenseMatrix& jac) +{ + int N = model->size(); + std::vector y(N); + std::vector v(N); + std::vector res(N); + std::vector d_res(N); + for (int idy = 0; idy < N; ++idy) + { + // Elementary vector for Jacobian-vector product + for (int idx = 0; idx < N; ++idx) + { + y[idx] = (model->y())[idx]; + res[idx] = (model->getResidual())[idx]; + v[idx] = 0.0; + } + v[idy] = 1.0; + + // Autodiff + __enzyme_fwddiff((void*) evaluateResidual, + enzyme_dup, + y, + v, + enzyme_dupnoneed, + res, + &d_res); + + // Store result + for (int idx = 0; idx < N; ++idx) + { + jac.setValue(idx, idy, d_res[idx]); + } + } +} + +int main() +{ + // Model + DGParameters parms; + parms.wb_ = 2.0 * M_PI * 50.0; + parms.wc_ = 31.41; + parms.mp_ = 9.4e-5; + parms.Vn_ = 380.0; + parms.nq_ = 1.3e-3; + parms.F_ = 0.75; + parms.Kiv_ = 420.0; + parms.Kpv_ = 0.1; + parms.Kic_ = 2.0e4; + parms.Kpc_ = 15.0; + parms.Cf_ = 5.0e-5; + parms.rLf_ = 0.1; + parms.Lf_ = 1.35e-3; + parms.rLc_ = 0.03; + parms.Lc_ = 0.35e-3; + DG* dg = new DG(0, parms, true); + dg->allocate(); + dg->initialize(); + dg->updateTime(0.0, 0.0); + + // Residual evaluation and reference Jacobian + dg->evaluateResidual(); + dg->evaluateJacobian(); + std::vector y = dg->y(); + std::vector yp = dg->yp(); + std::vector res = dg->getResidual(); + SparseMatrix jac_ref = dg->getJacobian(); + DenseMatrix jac_ref_dense(dg->size(), dg->size()); + jac_ref_dense.setValues(jac_ref); + + // Enzyme Jacobian + DenseMatrix jac_autodiff(dg->size(), dg->size()); + EnzymeModelJacobian(dg, jac_autodiff); + + // Check + int fail = 0; + bool verbose = true; + for (int idy = 0; idy < dg->size(); ++idy) + { + for (int idx = 0; idx < dg->size(); ++idx) + { + if (std::abs(jac_autodiff.getValue(idx, idy) - jac_ref_dense.getValue(idx, idy)) > std::numeric_limits::epsilon()) + { + fail++; + if (verbose) + { + std::cout << "Result incorrect at line = " << idy << ", column = " << idx << "\n"; + } + } + } + } + if (verbose) + { + jac_autodiff.printMatrix("Autodiff Jacobian"); + jac_ref_dense.printMatrix("Reference Jacobian"); + } + std::cout << "Status: " << fail << "\n"; + + // Cleanup + delete dg; + + return fail; +} diff --git a/examples/Enzyme/Standalone/CMakeLists.txt b/examples/Enzyme/Standalone/CMakeLists.txt new file mode 100644 index 000000000..fe41dc744 --- /dev/null +++ b/examples/Enzyme/Standalone/CMakeLists.txt @@ -0,0 +1,13 @@ +enzyme_add_executable( + NAME EnzymeStandaloneScalarCheck + SOURCES EnzymeScalar.cpp +) + +enzyme_add_executable( + NAME EnzymeStandaloneVectorCheck + SOURCES EnzymeVector.cpp + LINK_LIBRARIES GRIDKIT::DenseMatrix +) + +add_test(NAME "EnzymeStandaloneScalarCheck" COMMAND ${CMAKE_CURRENT_BINARY_DIR}/EnzymeStandaloneScalarCheck) +add_test(NAME "EnzymeStandaloneVectorCheck" COMMAND ${CMAKE_CURRENT_BINARY_DIR}/EnzymeStandaloneVectorCheck) diff --git a/examples/Enzyme/Standalone/EnzymeScalar.cpp b/examples/Enzyme/Standalone/EnzymeScalar.cpp new file mode 100644 index 000000000..d799e9b0f --- /dev/null +++ b/examples/Enzyme/Standalone/EnzymeScalar.cpp @@ -0,0 +1,37 @@ +#include +#include + +/** + * @brief Standalone example that computes the derivative of a scalar function + * by automatic differentiation via Enzyme. + * + * TODO: Convert this into a unit test. + */ + +double square(double x) +{ + return x * x; +} + +double __enzyme_autodiff(double (*)(double), ...); + +double dsquare(double x) +{ + return __enzyme_autodiff(square, x); +} + +int main() +{ + int fail = 0; + double var = 5.0; + double sq = square(var); + double dsq = dsquare(var); + std::cout << "x = " << var << ", x^2 = " << sq << ", d(x^2)/dx = " << dsq << "\n"; + if (std::abs(dsq - 2.0 * var) > std::numeric_limits::epsilon()) + { + fail++; + std::cout << "Result incorrect\n"; + } + std::cout << "Status: " << fail << "\n"; + return fail; +} diff --git a/examples/Enzyme/Standalone/EnzymeVector.cpp b/examples/Enzyme/Standalone/EnzymeVector.cpp new file mode 100644 index 000000000..94a10f9a4 --- /dev/null +++ b/examples/Enzyme/Standalone/EnzymeVector.cpp @@ -0,0 +1,127 @@ +#include +#include +#include + +#include + +/** + * @brief Standalone example that computes the Jacobian of a vector-valued function + * by automatic differentiation via Enzyme. + * + * TODO: Convert this into a unit test. + */ + +using DenseMatrix = GridKit::LinearAlgebra::DenseMatrix; +int enzyme_dupnoneed; +int enzyme_dup; +int enzyme_const; +void __enzyme_fwddiff(void*, int, std::vector, std::vector, int, std::vector, std::vector*); + +inline double square_scalar(double x) +{ + return x * x; +} + +inline double dsquare_ref_scalar(double x) +{ + return 2.0 * x; +} + +// Vector-valued function to differentiate +void square(std::vector x, std::vector& y) +{ + for (int idx = 0; idx < x.size(); ++idx) + { + y[idx] = square_scalar(x[idx]); + } +} + +// Reference Jacobian +void dsquare_ref(std::vector x, std::vector y, DenseMatrix& dy) +{ + for (int idy = 0; idy < y.size(); ++idy) + { + for (int idx = 0; idx < x.size(); ++idx) + { + if (idx == idy) + dy.setValue(idx, idy, dsquare_ref_scalar(x[idx])); + } + } +} + +// Function that computes the Jacobian via automatic differentiation +void dsquare(std::vector x, std::vector y, DenseMatrix& dy) +{ + std::vector v(x.size()); + std::vector d_y(y.size()); + for (int idy = 0; idy < y.size(); ++idy) + { + // Elementary vector for Jacobian-vector product + for (int idx = 0; idx < x.size(); ++idx) + { + v[idx] = 0.0; + } + v[idy] = 1.0; + + // Autodiff + __enzyme_fwddiff((void*) square, enzyme_dup, x, v, enzyme_dupnoneed, y, &d_y); + + // Store result + for (int idx = 0; idx < x.size(); ++idx) + { + dy.setValue(idx, idy, d_y[idx]); + } + } +} + +int main() +{ + // Vector and matrix declarations + constexpr int N = 10; + std::vector x(N); + std::vector sq(N); + DenseMatrix dsq = DenseMatrix(N, N); + DenseMatrix dsq_ref = DenseMatrix(N, N); + + // Random input values + srand(time(NULL)); + for (int idx = 0; idx < x.size(); ++idx) + { + x[idx] = rand(); + } + + // Function evaluation + square(x, sq); + + // Reference Jacobian + dsquare_ref(x, sq, dsq_ref); + + // Enzyme Jacobian + dsquare(x, sq, dsq); + + // Check + int fail = 0; + bool verbose = true; + for (int idy = 0; idy < sq.size(); ++idy) + { + for (int idx = 0; idx < x.size(); ++idx) + { + if (std::abs(dsq.getValue(idx, idy) - dsq_ref.getValue(idx, idy)) > std::numeric_limits::epsilon()) + { + fail++; + if (verbose) + { + std::cout << "Result incorrect at line = " << idy << ", column = " << idx << "\n"; + std::cout << "x = " << x[idx] << ", x^2 = " << sq[idx] << ", d(x^2)/dx = " << dsq.getValue(idx, idy) << "\n"; + } + } + } + } + if (verbose) + { + dsq.printMatrix("Autodiff Jacobian"); + dsq_ref.printMatrix("Reference Jacobian"); + } + std::cout << "Status: " << fail << "\n"; + return fail; +} diff --git a/examples/GenConstLoad/CMakeLists.txt b/examples/GenConstLoad/CMakeLists.txt new file mode 100644 index 000000000..1854dc3c2 --- /dev/null +++ b/examples/GenConstLoad/CMakeLists.txt @@ -0,0 +1,20 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +# - Slaven Peles +#]] + +add_executable(genconstload GenConstLoad.cpp) +target_link_libraries(genconstload + GRIDKIT::generator4governor + GRIDKIT::bus GRIDKIT::load + GRIDKIT::solvers_dyn + GRIDKIT::solvers_opt +) +# Fortran linker needed to link to HSL solvers +set_property(TARGET genconstload PROPERTY LINKER_LANGUAGE Fortran) +install(TARGETS genconstload DESTINATION bin) + +add_test(NAME GenConstLoad COMMAND $) diff --git a/examples/GenConstLoad/GenConstLoad.cpp b/examples/GenConstLoad/GenConstLoad.cpp new file mode 100644 index 000000000..78cae0d86 --- /dev/null +++ b/examples/GenConstLoad/GenConstLoad.cpp @@ -0,0 +1,125 @@ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + using namespace GridKit; + using namespace AnalysisManager::Sundials; + using namespace AnalysisManager; + using namespace GridKit::Testing; + + // Create a bus + BaseBus* bus = new BusPQ(1.0, 0.0); + + // Attach a generator to the bus and signal ports + ModelEvaluatorImpl* gen = new Generator4Governor(bus, 0.8, 0.3); + + // Attach load to the bus + ModelEvaluatorImpl* load = new Load(bus, 0.8, 0.3); + + // Create system model + SystemModel* model = new SystemModel(); + model->addBus(bus); + model->addComponent(gen); + model->addComponent(load); + + // Create numerical integrator and configure it for the generator model + Ida* idas = new Ida(model); + + model->allocate(); + + double t_init = 0.0; + double t_final = 15.0; + + // setup simulation + idas->configureSimulation(); + idas->configureAdjoint(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init, true); + idas->configureQuadrature(); + idas->initializeQuadrature(); + + idas->runSimulationQuadrature(0.1, 2); + idas->saveInitialCondition(); + + // Set integration time for dynamic constrained optimization + idas->setIntegrationTime(t_init, t_final, 250); + + // Guess optimization parameter values + double T2 = 0.15; + double K = 16.0; + + // Create an instance of the IpoptApplication + Ipopt::SmartPtr ipoptApp = IpoptApplicationFactory(); + + // Initialize the IpoptApplication and process the options + Ipopt::ApplicationReturnStatus status; + status = ipoptApp->Initialize(); + if (status != Ipopt::Solve_Succeeded) + { + std::cout << "\n\n*** Initialization failed! ***\n\n"; + return (int) status; + } + + // Set solver tolerance + const double tol = 1e-4; + + // Configure Ipopt application + ipoptApp->Options()->SetStringValue("hessian_approximation", "limited-memory"); + ipoptApp->Options()->SetNumericValue("tol", tol); + ipoptApp->Options()->SetIntegerValue("print_level", 5); + + // Create interface to Ipopt solver + Ipopt::SmartPtr ipoptDynamicObjectiveInterface = + new IpoptInterface::DynamicObjective(idas); + + // Initialize problem + model->param()[0] = T2; + model->param()[1] = K; + + // Solve the problem + status = ipoptApp->OptimizeTNLP(ipoptDynamicObjectiveInterface); + + if (status == Ipopt::Solve_Succeeded) + { + // Print result + std::cout << "\nSucess: The problem solved in " + << ipoptApp->Statistics()->IterationCount() + << " iterations!\n"; + std::cout << "Optimal value: T2 = " + << model->param()[0] + << ", K = " + << model->param()[1] << "\n"; + std::cout << "The final value of the objective function G(T2,K) = " + << ipoptApp->Statistics()->FinalObjective() << "\n\n"; + } + + // Compare results of the two optimization methods + int retval = + isEqual(ipoptApp->Statistics()->FinalObjective(), 1239.0, 10 * tol) ? 0 : 1; + + if (retval != 0) + { + std::cout << "The two results differ beyond solver tolerance!\n"; + } + + delete idas; + delete gen; + delete load; + delete bus; + delete model; + + return 0; +} diff --git a/examples/GenInfiniteBus/CMakeLists.txt b/examples/GenInfiniteBus/CMakeLists.txt new file mode 100644 index 000000000..c36f4ec85 --- /dev/null +++ b/examples/GenInfiniteBus/CMakeLists.txt @@ -0,0 +1,20 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +# - Slaven Peles +#]] + +add_executable(geninfbus GenInfiniteBus.cpp) +target_link_libraries(geninfbus + GRIDKIT::bus + GRIDKIT::generator4 + GRIDKIT::solvers_opt + GRIDKIT::solvers_dyn +) +# Fortran linker needed to link to HSL solvers +set_property(TARGET geninfbus PROPERTY LINKER_LANGUAGE Fortran) +install(TARGETS geninfbus DESTINATION bin) + +add_test(NAME GenInfiniteBus COMMAND $) diff --git a/examples/GenInfiniteBus/GenInfiniteBus.cpp b/examples/GenInfiniteBus/GenInfiniteBus.cpp new file mode 100644 index 000000000..b3ea77a08 --- /dev/null +++ b/examples/GenInfiniteBus/GenInfiniteBus.cpp @@ -0,0 +1,161 @@ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + using namespace GridKit; + using namespace AnalysisManager::Sundials; + using namespace AnalysisManager; + using namespace GridKit::Testing; + + // Create an infinite bus + BaseBus* bus = new BusSlack(1.0, 0.0); + + // Attach a generator to that bus + Generator4* gen = new Generator4(bus); + + // Create a system model + SystemModel* model = new SystemModel(); + model->addBus(bus); + model->addComponent(gen); + + // allocate model components + model->allocate(); + + // Create numerical integrator and configure it for the generator model + Ida* idas = new Ida(model); + + double t_init = 0.0; + double t_final = 15.0; + + // setup simulation + idas->configureSimulation(); + idas->configureAdjoint(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init); + idas->configureQuadrature(); + idas->initializeQuadrature(); + + double t_fault = 0.1; + double t_clear = 0.1; + idas->runSimulation(t_fault); + idas->saveInitialCondition(); + // create initial condition after a fault + { + idas->getSavedInitialCondition(); + idas->initializeSimulation(t_init); + gen->V() = 0.0; + idas->runSimulation(t_clear, 20); + gen->V() = 1.0; + idas->saveInitialCondition(); + } + + // Set integration time for dynamic constrained optimization + idas->setIntegrationTime(t_init, t_final, 100); + + // Guess initial values of optimization parameters + double Pm = 1.0; + double Ef = 1.45; + + // Create an instance of the IpoptApplication + Ipopt::SmartPtr ipoptApp = IpoptApplicationFactory(); + + // Initialize the IpoptApplication and process the options + Ipopt::ApplicationReturnStatus status; + status = ipoptApp->Initialize(); + if (status != Ipopt::Solve_Succeeded) + { + std::cout << "\n\n*** Initialization failed! ***\n\n"; + return (int) status; + } + + // Set solver tolerance + const double tol = 1e-4; + + // Configure Ipopt application + ipoptApp->Options()->SetStringValue("hessian_approximation", "limited-memory"); + ipoptApp->Options()->SetNumericValue("tol", tol); + ipoptApp->Options()->SetIntegerValue("print_level", 0); + + // Create dynamic objective interface to Ipopt solver + Ipopt::SmartPtr ipoptDynamicObjectiveInterface = + new IpoptInterface::DynamicObjective(idas); + + // Initialize the problem + model->param()[0] = Pm; + model->param()[1] = Ef; + + // Solve the problem + status = ipoptApp->OptimizeTNLP(ipoptDynamicObjectiveInterface); + std::cout << "\n\nProblem formulated as dynamic objective optimiztion ...\n"; + + if (status == Ipopt::Solve_Succeeded) + { + // Print result + std::cout << "\nSucess:\n The problem solved in " + << ipoptApp->Statistics()->IterationCount() << " iterations!\n" + << " Optimal value of Pm = " << model->param()[0] << "\n" + << " Optimal value of Ef = " << model->param()[1] << "\n" + << " The final value of the objective function G(Pm,Ef) = " + << ipoptApp->Statistics()->FinalObjective() << "\n\n"; + } + + // Create dynamic constraint interface to Ipopt solver + Ipopt::SmartPtr ipoptDynamicConstraintInterface = + new IpoptInterface::DynamicConstraint(idas); + + // Store dynamic objective optimization results + double* results = new double[model->sizeParams()]; + for (unsigned i = 0; i < model->sizeParams(); ++i) + { + results[i] = model->param()[i]; + } + + // Initialize the problem + model->param()[0] = Pm; + model->param()[1] = Ef; + + // Solve the problem + status = ipoptApp->OptimizeTNLP(ipoptDynamicConstraintInterface); + std::cout << "\n\nProblem formulated as dynamic constraint optimiztion ...\n"; + + if (status == Ipopt::Solve_Succeeded) + { + // Print result + std::cout << "\nSucess:\n The problem solved in " + << ipoptApp->Statistics()->IterationCount() << " iterations!\n" + << " Optimal value of Pm = " << model->param()[0] << "\n" + << " Optimal value of Ef = " << model->param()[1] << "\n" + << " The final value of the objective function G(Pm,Ef) = " + << ipoptApp->Statistics()->FinalObjective() << "\n\n"; + } + + // Compare results of the two optimization methods + int retval = 0; + for (unsigned i = 0; i < model->sizeParams(); ++i) + { + if (!isEqual(results[i], model->param()[i], 100 * tol)) + --retval; + } + + if (retval < 0) + { + std::cout << "The two results differ beyond solver tolerance!\n"; + } + + delete[] results; + delete idas; + delete model; + return 0; +} diff --git a/examples/Grid3Bus/3bus.mat b/examples/Grid3Bus/3bus.mat new file mode 100644 index 000000000..cacc79555 --- /dev/null +++ b/examples/Grid3Bus/3bus.mat @@ -0,0 +1,47 @@ +( +function mpc = case5 +% Created by Reid Gomillion + +% MATPOWER + +%% MATPOWER Case Format : Version 2 +mpc.version = '2'; + +%%----- Power Flow Data -----%% +%% system MVA base +mpc.baseMVA = 100; + +%% bus data +% bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin +mpc.bus = [ + 1 3 2.0 0.0 0 0 0 1 0.0 0 0 0 0.0; + 2 1 2.5 -0.8 0 0 0 1 0.0 0 0 0 0.0; + 3 2 0 0 0 0 0 1.1 0.0 0 0 0 0.0; +]; + +%% generator data +% bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf +mpc.gen = [ + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 3 2.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; +]; + +%% branch data +% fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax +mpc.branch = [ + 1 2 0 0.1 0 0 0 0 0 0 0 0 0; + 1 3 0 0.0666666 0 0 0 0 0 0 0 0 0; + 2 3 0 0.0833333 0 0 0 0 0 0 0 0 0; +]; + +%%----- OPF Data -----%% +%% generator cost data +% 1 startup shutdown n x1 y1 ... xn yn +% 2 startup shutdown n c(n-1) ... c0 +mpc.gencost = [ + 2 0 0 3 0 14 0; + 2 0 0 3 0 15 0; + 2 0 0 3 0 30 0; +]; + +) diff --git a/examples/Grid3Bus/CMakeLists.txt b/examples/Grid3Bus/CMakeLists.txt new file mode 100644 index 000000000..ac356a894 --- /dev/null +++ b/examples/Grid3Bus/CMakeLists.txt @@ -0,0 +1,21 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +# add_executable(grid3bus Grid3Bus.cpp) +# target_link_libraries(grid3bus GRIDKIT::minigrid GRIDKIT::solvers_steady) +# install(TARGETS grid3bus RUNTIME DESTINATION bin) + +add_executable(grid3bus Grid3BusSys.cpp) +target_link_libraries(grid3bus GRIDKIT::minigrid + GRIDKIT::bus + GRIDKIT::generator + GRIDKIT::branch + GRIDKIT::load + GRIDKIT::solvers_steady) +install(TARGETS grid3bus RUNTIME DESTINATION bin) + +add_test(NAME Grid3Bus COMMAND $) diff --git a/examples/Grid3Bus/Grid3BusSys.cpp b/examples/Grid3Bus/Grid3BusSys.cpp new file mode 100644 index 000000000..970e02ace --- /dev/null +++ b/examples/Grid3Bus/Grid3BusSys.cpp @@ -0,0 +1,375 @@ + +/** + * @file Grid3BusSys.cpp + * @author Slaven Peles + * @author Reid Gomillion + * + * Simple 3-bus grid example. Two models are tested here -- a hard-wired model + * and a model assembled using GridKit's system composer. + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const std::string BUS3_DATA_STRING = R"( +function mpc = case5 +% Created by Reid Gomillion + +% MATPOWER + +%% MATPOWER Case Format : Version 2 +mpc.version = '2'; + +%%----- Power Flow Data -----%% +%% system MVA base +mpc.baseMVA = 100; + +%% bus data +% bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin +mpc.bus = [ + 1 3 2.0 0.0 0 0 0 1.0 0.0 0 0 0 0.0; + 2 1 2.5 -0.8 0 0 0 1.0 0.0 0 0 0 0.0; + 3 2 0 0 0 0 0 1.1 0.0 0 0 0 0.0; +]; + +%% generator data +% bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf +mpc.gen = [ + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; + 3 2.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; +]; + +%% branch data +% fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax +mpc.branch = [ + 1 2 0 0.1 0 0 0 0 0 0 0 0 0; + 1 3 0 0.0666666 0 0 0 0 0 0 0 0 0; + 2 3 0 0.0833333 0 0 0 0 0 0 0 0 0; +]; + +%%----- OPF Data -----%% +%% generator cost data +% 1 startup shutdown n x1 y1 ... xn yn +% 2 startup shutdown n c(n-1) ... c0 +mpc.gencost = [ + 2 0 0 3 0 14 0; + 2 0 0 3 0 15 0; + 2 0 0 3 0 30 0; +]; + +)"; + +using namespace GridKit; +using namespace AnalysisManager::Sundials; +using namespace AnalysisManager; +using namespace GridKit::Testing; +using namespace GridKit::PowerSystemData; + +constexpr double theta2_ref = -4.87979; // [deg] +constexpr double V2_ref = 1.08281; // [p.u.] +constexpr double theta3_ref = 1.46241; // [deg] + +/** + * Testing the monlithic case via the class MiniGrid + * @return returns 0 if pass o.w. fails + */ +int monolithicCase() +{ + std::cout << "\nSolving power flow for a 3-bus monolithic model ...\n\n"; + // Create a 3-bus model + MiniGrid* model = new MiniGrid(); + + // allocate model + model->allocate(); + model->initialize(); + std::cout << "Model size: " << model->size() << "\n\n"; + + // Create numerical solver and attach the model to it. + // Here we use Kinsol solver from SUNDIALS library + Kinsol* kinsol = new Kinsol(model); + + // setup simulation + kinsol->configureSimulation(); + // initialize simulation with default initial guess V=1, theta=0 + kinsol->getDefaultInitialCondition(); + // Compute solution + kinsol->runSimulation(); + // Print solution + double th2 = model->th2() * 180.0 / M_PI; + double V2 = model->V2(); + double th3 = model->th3() * 180.0 / M_PI; + std::cout << "Solution:\n"; + std::cout << " theta2 = " << th2 << " deg, expected = " << theta2_ref << " deg\n"; + std::cout << " V2 = " << V2 << " p.u., expected = " << V2_ref << " p.u.\n"; + std::cout << " theta3 = " << th3 << " deg, expected = " << theta3_ref << " deg\n\n"; + + // Print solver performance statistics + kinsol->printFinalStats(); + + int retval1 = 0; + retval1 += !isEqual(th2, theta2_ref, 1e-4); + retval1 += !isEqual(V2, V2_ref, 1e-4); + retval1 += !isEqual(th3, theta3_ref, 1e-4); + + if (retval1 == 0) + std::cout << "\nSuccess!\n\n\n"; + else + std::cout << "\nFailed!\n\n\n"; + + // Delete solver and model + delete kinsol; + kinsol = nullptr; + delete model; + model = nullptr; + return retval1; +} + +/** + * Run the Testing case for parser setup + * @return returns 0 if pass o.w. fail + */ +int parserCase() +{ + std::cout << "Solving same problem, but assembled from components via a parser ...\n\n"; + + // Data File Reading + GridKit::PowerSystemData::SystemModelData mp; + + std::istringstream iss(BUS3_DATA_STRING); + GridKit::readMatPower(mp, iss); + + // Create an empty system model and pass the system model data to it + SystemSteadyStateModel* sysmodel = new SystemSteadyStateModel(mp); + + // allocate model + sysmodel->allocate(); + sysmodel->initialize(); + std::cout << "Model size: " << sysmodel->size() << "\n\n"; + + // Create numerical solver and attach the model to it. + // Here we use Kinsol solver from SUNDIALS library + Kinsol* kinsol = new Kinsol(sysmodel); + + // setup simulation + kinsol->configureSimulation(); + // initialize simulation with default initial guess + kinsol->getDefaultInitialCondition(); + // Compute solution + kinsol->runSimulation(); + // Print solution + double th2 = sysmodel->getBus(2)->theta() * 180.0 / M_PI; + double V2 = sysmodel->getBus(2)->V(); + double th3 = sysmodel->getBus(3)->theta() * 180.0 / M_PI; + + std::cout << "Solution:\n"; + std::cout << " theta2 = " << th2 << " deg, expected = " << theta2_ref << " deg\n"; + std::cout << " V2 = " << V2 << " p.u., expected = " << V2_ref << " p.u.\n"; + std::cout << " theta3 = " << th3 << " deg, expected = " << theta3_ref << " deg\n\n"; + + // Print solver performance statistics + kinsol->printFinalStats(); + + int retval2 = 0; + retval2 += !isEqual(th2, theta2_ref, 1e-4); + retval2 += !isEqual(V2, V2_ref, 1e-4); + retval2 += !isEqual(th3, theta3_ref, 1e-4); + + if (retval2 == 0) + std::cout << "\nSuccess!\n\n\n"; + else + std::cout << "\nFailed!\n\n\n"; + + // Delete solver and model + + delete kinsol; + kinsol = nullptr; + delete sysmodel; + sysmodel = nullptr; + + return retval2; +} + +/** + * Hardwired Test Case + * @return 0 if pass otherwise fails + */ +int hardwiredCase() +{ + std::cout << "Solving same problem, but assembled from components manually ...\n\n"; + + // First, create an empty system model + SystemSteadyStateModel* sysmodel = new SystemSteadyStateModel(); + + // Next create and add buses ... + // Create a slack bus, fix V=1, theta=0, bus ID = 1 + BusData bd1; + bd1.bus_i = 1; + bd1.type = 3; + bd1.Vm = 1.0; + bd1.Va = 0.0; + auto* bus1 = BusFactory::create(bd1); + sysmodel->addBus(bus1); + + // Create a PQ bus, initialize V=1, theta=0, bus ID = 2 + BusData bd2; + bd2.bus_i = 2; + bd2.type = 1; + bd2.Vm = 1.0; + bd2.Va = 0.0; + auto* bus2 = BusFactory::create(bd2); + sysmodel->addBus(bus2); + + // Create a PV bus, fix V=1.1, initialize theta=0, and set power injection Pg=2 + BusData bd3; + bd3.bus_i = 3; + bd3.type = 2; + bd3.Vm = 1.1; + bd3.Va = 0.0; + auto* bus3 = BusFactory::create(bd3); + sysmodel->addBus(bus3); + + // Create and add generators ... + // Create and add slack generator connected to bus1 + GenData gd1; + gd1.bus = 1; + auto* gen1 = GeneratorFactory::create(sysmodel->getBus(gd1.bus), gd1); + sysmodel->addComponent(gen1); + + // Create and add PV generator connected to bus3 + GenData gd3; + gd3.Pg = 2.0; + gd3.bus = 3; + auto* gen3 = GeneratorFactory::create(sysmodel->getBus(gd3.bus), gd3); + sysmodel->addComponent(gen3); + + // Create and add branches ... + // Branch 1-2 + BranchData brd12; + brd12.fbus = 1; + brd12.tbus = 2; + brd12.x = 1.0 / 10.0; + brd12.r = 0.0; + brd12.b = 0.0; + Branch* branch12 = new Branch(sysmodel->getBus(brd12.fbus), sysmodel->getBus(brd12.tbus), brd12); + sysmodel->addComponent(branch12); + + // Branch 1-3 + BranchData brd13; + brd13.fbus = 1; + brd13.tbus = 3; + brd13.x = 1.0 / 15.0; + brd13.r = 0.0; + brd13.b = 0.0; + Branch* branch13 = new Branch(sysmodel->getBus(brd13.fbus), sysmodel->getBus(brd13.tbus), brd13); + sysmodel->addComponent(branch13); + + // Branch 2-3 + BranchData brd23; + brd23.fbus = 2; + brd23.tbus = 3; + brd23.x = 1.0 / 12.0; + brd23.r = 0.0; + brd23.b = 0.0; + Branch* branch23 = new Branch(sysmodel->getBus(brd23.fbus), sysmodel->getBus(brd23.tbus), brd23); + sysmodel->addComponent(branch23); + + // Create and add loads ... + // Load on bus1 + LoadData ld1; + ld1.bus_i = 1; + ld1.Pd = 2.0; + ld1.Qd = 0.0; + Load* load1 = new Load(sysmodel->getBus(ld1.bus_i), ld1); + sysmodel->addComponent(load1); + + // Load on bus2 + LoadData ld2; + ld2.bus_i = 2; + ld2.Pd = 2.5; + ld2.Qd = -0.8; + Load* load2 = new Load(sysmodel->getBus(ld2.bus_i), ld2); + sysmodel->addComponent(load2); + + // allocate model + sysmodel->allocate(); + sysmodel->initialize(); + std::cout << "Model size: " << sysmodel->size() << "\n\n"; + + // Create numerical solver and attach the model to it. + // Here we use Kinsol solver from SUNDIALS library + Kinsol* kinsol = new Kinsol(sysmodel); + + // setup simulation + kinsol->configureSimulation(); + // initialize simulation with default initial guess + kinsol->getDefaultInitialCondition(); + // Compute solution + kinsol->runSimulation(); + // Print solution + double th2 = bus2->theta() * 180.0 / M_PI; + double V2 = bus2->V(); + double th3 = bus3->theta() * 180.0 / M_PI; + + std::cout << "Solution:\n"; + std::cout << " theta2 = " << th2 << " deg, expected = " << theta2_ref << " deg\n"; + std::cout << " V2 = " << V2 << " p.u., expected = " << V2_ref << " p.u.\n"; + std::cout << " theta3 = " << th3 << " deg, expected = " << theta3_ref << " deg\n\n"; + + // Print solver performance statistics + kinsol->printFinalStats(); + + int retval2 = 0; + retval2 += !isEqual(th2, theta2_ref, 1e-4); + retval2 += !isEqual(V2, V2_ref, 1e-4); + retval2 += !isEqual(th3, theta3_ref, 1e-4); + + if (retval2 == 0) + std::cout << "\nSuccess!\n\n\n"; + else + std::cout << "\nFailed!\n\n\n"; + + // Delete solver and model + delete kinsol; + kinsol = nullptr; + delete sysmodel; + sysmodel = nullptr; + return retval2; +} + +int main() +{ + // return the results of each case + int resolve = 0; + std::cout << std::string(32, '-') << std::endl; + resolve |= monolithicCase(); + std::cout << std::string(32, '-') << std::endl; + resolve |= parserCase(); + std::cout << std::string(32, '-') << std::endl; + resolve |= hardwiredCase(); + + if (resolve) + { + std::cout << "Failure!\n"; + } + else + { + std::cout << "Success!\n"; + } + + return resolve; +} diff --git a/Examples/Grid3Bus/README.md b/examples/Grid3Bus/README.md similarity index 90% rename from Examples/Grid3Bus/README.md rename to examples/Grid3Bus/README.md index 39d27740f..31bd6f9bc 100644 --- a/Examples/Grid3Bus/README.md +++ b/examples/Grid3Bus/README.md @@ -10,7 +10,7 @@ The mathematical model of the power flow problem is formulated as a set of nonli The model and its parameters are described in Figure 1:
- + Figure 1: A simple 3-bus grid example. @@ -22,19 +22,19 @@ Problem variables are voltage magnitudes and phases; they are stored in bus obje **Bus 1**: Slack bus, does not store variables no residuals. Voltage and phase are set to $`V_1 \equiv 1`$p.u. and $`\theta_1 \equiv 0`$, respectively. -**Bus 2**: PQ bus, stores variables $`V_2, \theta_2`$ and residuals $`P_2, Q_2`$. Load $`P_{L2} = 2.5`$p.u., $`Q_{L2} = -j0.8`$p.u. is attached to it. From the equations for [branch](../../ComponentLib/Branch/README.md) and [load](../../ComponentLib/Load/README.md) components, we assemble Bus 2 residuals as: +**Bus 2**: PQ bus, stores variables $`V_2, \theta_2`$ and residuals $`P_2, Q_2`$. Load $`P_{L1} = 2.5`$p.u., $`Q_{L1} = -j0.8`$p.u. is attached to it. From the equations for [branch](../../src/Model/PowerFlow/Branch/README.md) and [load](../../src/Model/PowerFlow/Load/README.md) components, we assemble Bus 2 residuals as: ```math \begin{array}{rcll} -P_2 & = &-P_{L2} &~~~\mathrm{(load ~2)} \\ +P_2 & = &-P_{L1} &~~~\mathrm{(load ~2)} \\ &&+ b_{12}|V_1||V_2|\sin(\theta_2-\theta_1) &~~~\mathrm{(branch ~12)} \\ &&+ b_{23}|V_2||V_3|\sin(\theta_2-\theta_3) &~~~\mathrm{(branch ~23)} \\ -Q_2 & = & -Q_{L2} &~~~\mathrm{(load ~2)} \\ +Q_2 & = & -Q_{L1} &~~~\mathrm{(load ~2)} \\ &&+ b_{12}|V_2|^2 - b_{12}|V_1||V_2|\cos(\theta_2-\theta_1) &~~~\mathrm{(branch ~12)} \\ &&+ b_{23}|V_2|^2 - b_{23}|V_2||V_3|\cos(\theta_2-\theta_3) &~~~\mathrm{(branch ~23)} \end{array} ``` -**Bus 3**: PV bus, stores variable $`\theta_3`$ and residual $`P_3`$. Voltage is set to $`|V_3| \equiv 1.1`$p.u.. Generator $`P_{G3} = 2`$p.u. is attached to it. From the equations for [branch](../../ComponentLib/Branch/README.md) and [generator](../../ComponentLib/Gen/README.md) components, we assemble Bus 3 residual as: +**Bus 3**: PV bus, stores variable $`\theta_3`$ and residual $`P_3`$. Voltage is set to $`|V_3| \equiv 1.1`$p.u.. Generator $`P_{G3} = 2`$p.u. is attached to it. From the equations for [branch](../../src/Model/PowerFlow/Branch/README.md) and [generator](../../src/Model/PowerFlow/Gen/README.md) components, we assemble Bus 3 residual as: ```math \begin{array}{rcll} P_3 & = &P_{G3} &~~~\mathrm{(generator ~3)} \\ diff --git a/examples/LinearAlgebra/CMakeLists.txt b/examples/LinearAlgebra/CMakeLists.txt new file mode 100644 index 000000000..553b0587e --- /dev/null +++ b/examples/LinearAlgebra/CMakeLists.txt @@ -0,0 +1,3 @@ + +add_subdirectory(SparseTest) +add_subdirectory(DenseTest) diff --git a/examples/LinearAlgebra/DenseTest/CMakeLists.txt b/examples/LinearAlgebra/DenseTest/CMakeLists.txt new file mode 100644 index 000000000..5d3bf7b5c --- /dev/null +++ b/examples/LinearAlgebra/DenseTest/CMakeLists.txt @@ -0,0 +1,6 @@ + +add_executable(densemattest DenseTest.cpp) +target_link_libraries(densemattest GRIDKIT::DenseMatrix) + +add_test(NAME DenseMatrixTest COMMAND $) +install(TARGETS densemattest RUNTIME DESTINATION bin) diff --git a/examples/LinearAlgebra/DenseTest/DenseTest.cpp b/examples/LinearAlgebra/DenseTest/DenseTest.cpp new file mode 100644 index 000000000..3148ced6c --- /dev/null +++ b/examples/LinearAlgebra/DenseTest/DenseTest.cpp @@ -0,0 +1,26 @@ + +#include + +int main() +{ + int fail = 0; + + size_t m = 4; + size_t n = 4; + GridKit::LinearAlgebra::DenseMatrix A = + GridKit::LinearAlgebra::DenseMatrix(m, n); + + double val = 0.0; + for (size_t j = 0; j < n; ++j) + { + for (size_t i = 0; i < m; ++i) + { + A.setValue(i, j, val); + val += 1.0; + } + } + A.printMatrix("Dense matrix test output"); + (A.getValuesCOO())->printMatrix(); + + return fail; +} diff --git a/examples/LinearAlgebra/SparseTest/CMakeLists.txt b/examples/LinearAlgebra/SparseTest/CMakeLists.txt new file mode 100644 index 000000000..ef5c8ae0c --- /dev/null +++ b/examples/LinearAlgebra/SparseTest/CMakeLists.txt @@ -0,0 +1,7 @@ + + +add_executable(spmattest SparseTest.cpp) +target_link_libraries(spmattest GRIDKIT::SparseMatrix) + +add_test(NAME SparseMatrixTest COMMAND $) +install(TARGETS spmattest RUNTIME DESTINATION bin) diff --git a/examples/LinearAlgebra/SparseTest/SparseTest.cpp b/examples/LinearAlgebra/SparseTest/SparseTest.cpp new file mode 100644 index 000000000..3c7fe99ef --- /dev/null +++ b/examples/LinearAlgebra/SparseTest/SparseTest.cpp @@ -0,0 +1,102 @@ + + +#include +#include +#include +#include +#include +#include +#include + +#include + +int main(int argc, char const* argv[]) +{ + std::vector val{0.1, 0.2, 0.3, 0.4}; + std::vector x{2, 1, 3, 1}; + std::vector y{1, 3, 2, 2}; + size_t n = 4; + size_t m = 4; + + COO_Matrix A = COO_Matrix(x, y, val, m, n); + + std::vector valn(4); + std::vector xn(4); + std::vector yn(4); + + std::tie(xn, yn, valn) = A.getEntries(); + + for (size_t i = 0; i < valn.size(); i++) + { + std::cout << valn[i] << "\n"; + } + + std::cout << "A:\n"; + A.printMatrix(); + + std::vector val2{0.5, 0.6, 0.7, 0.8, 1.0}; + std::vector x2{0, 2, 0, 2, 1}; + std::vector y2{3, 3, 2, 2, 3}; + COO_Matrix B = COO_Matrix(x2, y2, val2, m, n); + + std::cout << "B:\n"; + B.printMatrix(); + + A.axpy(2.0, B); + + std::cout << "A + 2B:\n"; + A.printMatrix(); + + std::vector r; + std::vector c; + std::vector v; + std::tie(r, c, v) = A.setDataToCSR(); + + for (size_t i = 0; i < r.size() - 1; i++) + { + std::cout << r[i] << std::endl; + size_t rdiff = r[i + 1] - r[i]; + for (size_t j = 0; j < rdiff; j++) + { + std::cout << c[j + r[i]] << ", " << v[j + r[i]] << std::endl; + } + } + std::cout << r[r.size() - 1] << std::endl; + + // Basic Verification test + std::vector rtest = {0, 2, 4, 7, 8}; + std::vector ctest = {2, 3, 2, 3, 1, 2, 3, 2}; + std::vector valtest = {1.4, 1.0, 0.4, 2.2, 0.1, 1.6, 1.2, 0.3}; + + assert(rtest.size() == r.size()); + assert(ctest.size() == c.size()); + assert(valtest.size() == v.size()); + + int failval = 0; + for (size_t i = 0; i < rtest.size(); i++) + { + if (r[i] != rtest[i]) + { + failval--; + } + } + for (size_t i = 0; i < ctest.size(); i++) + { + double vdiff = v[i] - valtest[i]; + if (c[i] != ctest[i] || -1e-14 > vdiff || vdiff > 1e-14) + { + failval--; + } + } + + if (failval == 0) + { + std::cout << "Success!" << std::endl; + } + else + { + std::cout << "Failed!" << std::endl; + } + + return failval; +} diff --git a/Examples/MatPowerTesting/CMakeLists.txt b/examples/MatPowerTesting/CMakeLists.txt similarity index 100% rename from Examples/MatPowerTesting/CMakeLists.txt rename to examples/MatPowerTesting/CMakeLists.txt diff --git a/Examples/MatPowerTesting/test_parse_branch_row.cpp b/examples/MatPowerTesting/test_parse_branch_row.cpp similarity index 88% rename from Examples/MatPowerTesting/test_parse_branch_row.cpp rename to examples/MatPowerTesting/test_parse_branch_row.cpp index 8d87d9e82..f6bb3c0d1 100644 --- a/Examples/MatPowerTesting/test_parse_branch_row.cpp +++ b/examples/MatPowerTesting/test_parse_branch_row.cpp @@ -1,19 +1,21 @@ +#include + #include #include #include -#include using namespace GridKit; using namespace GridKit::Testing; using namespace GridKit::PowerSystemData; -namespace { +namespace +{ -using IdxT = int; -using RealT = double; + using IdxT = int; + using RealT = double; -static const std::string matpower_data{ - R"( + static const std::string matpower_data{ + R"( %% branch data % fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax @@ -31,8 +33,9 @@ mpc.branch = [ } // namespace -int main(int argc, char **argv) { - int fail = 0; +int main(int argc, char** argv) +{ + int fail = 0; std::vector> branch_answer{ {1, 2, 0.00281, 0.0281, 0.00712, 400, 400, 400, 0, 0, 1, -360, 360}, {1, 4, 0.00304, 0.0304, 0.00658, 0, 0, 0, 0, 0, 1, -360, 360}, diff --git a/Examples/MatPowerTesting/test_parse_bus_row.cpp b/examples/MatPowerTesting/test_parse_bus_row.cpp similarity index 66% rename from Examples/MatPowerTesting/test_parse_bus_row.cpp rename to examples/MatPowerTesting/test_parse_bus_row.cpp index 38695c5fa..92c1062cc 100644 --- a/Examples/MatPowerTesting/test_parse_bus_row.cpp +++ b/examples/MatPowerTesting/test_parse_bus_row.cpp @@ -1,19 +1,21 @@ +#include + #include #include #include -#include using namespace GridKit; using namespace GridKit::Testing; using namespace GridKit::PowerSystemData; -namespace { +namespace +{ -using IdxT = int; -using RealT = double; + using IdxT = int; + using RealT = double; -static const std::string matpower_data{ - R"( + static const std::string matpower_data{ + R"( %% bus data mpc.bus = [ 1 2 0 0 0 0 1 1 0 230 1 1.1 0.0; @@ -24,10 +26,11 @@ mpc.bus = [ ]; )"}; -} // namespace +} // namespace -int main(int argc, char** argv) { - int fail = 0; +int main(int argc, char** argv) +{ + int fail = 0; std::vector> bus_answer{ {1, 2, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, {2, 1, 0, 0, 1, 1, 0, 230, 1, 1.1, 0.0}, @@ -37,30 +40,32 @@ int main(int argc, char** argv) { }; std::vector> load_answer{ - {1, 0, 0}, - {2, 300, 98.61}, - {3, 300, 98.61}, + {1, 0, 0}, + {2, 300, 98.61}, + {3, 300, 98.61}, {4, 400, 131.47}, - {5, 0, 0}, + {5, 0, 0}, }; { SystemModelData mp; - std::istringstream iss(matpower_data); + std::istringstream iss(matpower_data); GridKit::readMatPower(mp, iss); - if (!isEqual(mp.bus, bus_answer)) fail++; + if (!isEqual(mp.bus, bus_answer)) + fail++; std::cout << "After reading the bus component, fail == " << fail << "\n"; } { SystemModelData mp; - std::istringstream iss(matpower_data); + std::istringstream iss(matpower_data); GridKit::readMatPower(mp, iss); - if (!isEqual(mp.load, load_answer)) fail++; + if (!isEqual(mp.load, load_answer)) + fail++; std::cout << "After reading the bus component, fail == " << fail << "\n"; } - std::cout << "Tests " << (fail?"FAILED":"PASSED") << "\n"; + std::cout << "Tests " << (fail ? "FAILED" : "PASSED") << "\n"; return fail; } diff --git a/Examples/MatPowerTesting/test_parse_gen_row.cpp b/examples/MatPowerTesting/test_parse_gen_row.cpp similarity index 71% rename from Examples/MatPowerTesting/test_parse_gen_row.cpp rename to examples/MatPowerTesting/test_parse_gen_row.cpp index b524ae899..63a1d5501 100644 --- a/Examples/MatPowerTesting/test_parse_gen_row.cpp +++ b/examples/MatPowerTesting/test_parse_gen_row.cpp @@ -1,19 +1,21 @@ +#include + #include #include #include -#include using namespace GridKit; using namespace GridKit::Testing; using namespace GridKit::PowerSystemData; -namespace { +namespace +{ -using IdxT = int; -using RealT = double; + using IdxT = int; + using RealT = double; -static const std::string matpower_data{ - R"( + static const std::string matpower_data{ + R"( %% generator data % bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf mpc.gen = [ @@ -28,17 +30,15 @@ mpc.gen = [ } // namespace -int main(int argc, char **argv) { - int fail = 0; +int main(int argc, char** argv) +{ + int fail = 0; std::vector> gen_answer{ {1, 40, 0, 30, -30, 1, 100, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {1, 170, 0, 127.5, -127.5, 1, 100, 1, 170, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {3, 323.49, 0, 390, -390, 1, 100, 1, 520, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 170, 0, 127.5, -127.5, 1, 100, 1, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 323.49, 0, 390, -390, 1, 100, 1, 520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {4, 0, 0, 150, -150, 1, 100, 1, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {5, 466.51, 0, 450, -450, 1, 100, 1, 600, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; + {5, 466.51, 0, 450, -450, 1, 100, 1, 600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; SystemModelData mp; { diff --git a/Examples/MatPowerTesting/test_parse_gencost_row.cpp b/examples/MatPowerTesting/test_parse_gencost_row.cpp similarity index 74% rename from Examples/MatPowerTesting/test_parse_gencost_row.cpp rename to examples/MatPowerTesting/test_parse_gencost_row.cpp index efc409d89..adddc1edb 100644 --- a/Examples/MatPowerTesting/test_parse_gencost_row.cpp +++ b/examples/MatPowerTesting/test_parse_gencost_row.cpp @@ -1,19 +1,21 @@ +#include + #include #include #include -#include using namespace GridKit; using namespace GridKit::Testing; using namespace GridKit::PowerSystemData; -namespace { +namespace +{ -using IdxT = int; -using RealT = double; + using IdxT = int; + using RealT = double; -static const std::string matpower_data{ - R"( + static const std::string matpower_data{ + R"( %%----- OPF Data -----%% %% generator cost data @@ -31,11 +33,14 @@ mpc.gencost = [ } // namespace -int main(int argc, char **argv) { - int fail = 0; +int main(int argc, char** argv) +{ + int fail = 0; std::vector> gencost_answer{ - {2, 0, 0, 3, {0, 14, 0}}, {2, 0, 0, 3, {0, 15, 0}}, - {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, + {2, 0, 0, 3, {0, 14, 0}}, + {2, 0, 0, 3, {0, 15, 0}}, + {2, 0, 0, 3, {0, 30, 0}}, + {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; SystemModelData mp; diff --git a/Examples/MatPowerTesting/test_parse_matpower.cpp b/examples/MatPowerTesting/test_parse_matpower.cpp similarity index 79% rename from Examples/MatPowerTesting/test_parse_matpower.cpp rename to examples/MatPowerTesting/test_parse_matpower.cpp index fa926cad2..2994804b5 100644 --- a/Examples/MatPowerTesting/test_parse_matpower.cpp +++ b/examples/MatPowerTesting/test_parse_matpower.cpp @@ -1,19 +1,21 @@ +#include + #include #include #include -#include using namespace GridKit; using namespace GridKit::Testing; using namespace GridKit::PowerSystemData; -namespace { +namespace +{ -using IdxT = int; -using RealT = double; + using IdxT = int; + using RealT = double; -static const std::string matpower_data{ - R"( + static const std::string matpower_data{ + R"( function mpc = case5 %CASE5 Power flow data for modified 5 bus, 5 gen case based on PJM 5-bus system % Please see CASEFORMAT for details on the case file format. @@ -81,16 +83,17 @@ mpc.gencost = [ } // namespace -int main(int argc, char **argv) { +int main(int argc, char** argv) +{ int fail = 0; // All types will use the scalar types at the top of the file - using BusDataT = BusData; - using GenDataT = GenData; - using BranchDataT = BranchData; - using GenCostDataT = GenCostData; + using BusDataT = BusData; + using GenDataT = GenData; + using BranchDataT = BranchData; + using GenCostDataT = GenCostData; using SystemModelDataT = SystemModelData; - using LoadDataT = LoadData; + using LoadDataT = LoadData; // Create the struct of expected values std::vector branch_answer{ @@ -110,33 +113,31 @@ int main(int argc, char **argv) { }; std::vector gen_answer{ {1, 40, 0, 30, -30, 1, 100, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {1, 170, 0, 127.5, -127.5, 1, 100, 1, 170, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {3, 323.49, 0, 390, -390, 1, 100, 1, 520, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 170, 0, 127.5, -127.5, 1, 100, 1, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 323.49, 0, 390, -390, 1, 100, 1, 520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {4, 0, 0, 150, -150, 1, 100, 1, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {5, 466.51, 0, 450, -450, 1, 100, 1, 600, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; + {5, 466.51, 0, 450, -450, 1, 100, 1, 600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; std::vector gencost_answer{ - {2, 0, 0, 3, {0, 14, 0}}, {2, 0, 0, 3, {0, 15, 0}}, - {2, 0, 0, 3, {0, 30, 0}}, {2, 0, 0, 3, {0, 40, 0}}, + {2, 0, 0, 3, {0, 14, 0}}, + {2, 0, 0, 3, {0, 15, 0}}, + {2, 0, 0, 3, {0, 30, 0}}, + {2, 0, 0, 3, {0, 40, 0}}, {2, 0, 0, 3, {0, 10, 0}}, }; std::vector load_answer{ - {1, 0, 0}, - {2, 300, 98.61}, - {3, 300, 98.61}, + {1, 0, 0}, + {2, 300, 98.61}, + {3, 300, 98.61}, {4, 400, 131.47}, - {5, 0, 0}, + {5, 0, 0}, }; - SystemModelDataT mp_answer; mp_answer.gencost = gencost_answer; - mp_answer.gen = gen_answer; - mp_answer.bus = bus_answer; - mp_answer.branch = branch_answer; - mp_answer.load = load_answer; + mp_answer.gen = gen_answer; + mp_answer.bus = bus_answer; + mp_answer.branch = branch_answer; + mp_answer.load = load_answer; mp_answer.version = "2"; mp_answer.baseMVA = 100; diff --git a/examples/Microgrid/CMakeLists.txt b/examples/Microgrid/CMakeLists.txt new file mode 100644 index 000000000..9d627fcac --- /dev/null +++ b/examples/Microgrid/CMakeLists.txt @@ -0,0 +1,13 @@ + + + + +add_executable(microgrid Microgrid.cpp) +target_link_libraries(microgrid GRIDKIT::power_elec_disgen + GRIDKIT::power_elec_microline + GRIDKIT::power_elec_microload + GRIDKIT::solvers_dyn + GRIDKIT::power_elec_microbusdq) + +add_test(NAME Microgrid COMMAND $) +install(TARGETS microgrid RUNTIME DESTINATION bin) diff --git a/examples/Microgrid/Microgrid.cpp b/examples/Microgrid/Microgrid.cpp new file mode 100644 index 000000000..a3afb966d --- /dev/null +++ b/examples/Microgrid/Microgrid.cpp @@ -0,0 +1,433 @@ + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const* argv[]) +{ + ///@todo Needs to be modified. Some components are small relative to others thus there error is high (or could be matlab vector issue) + double abs_tol = 1.0e-8; + double rel_tol = 1.0e-8; + size_t max_step_amount = 3000; + bool use_jac = true; + + // Create model + GridKit::PowerElectronicsModel* sysmodel = new GridKit::PowerElectronicsModel(rel_tol, abs_tol, use_jac, max_step_amount); + + // Modeled after the problem in the paper + double RN = 1.0e4; + + // DG Params + GridKit::DistributedGeneratorParameters parms1; + parms1.wb_ = 2.0 * M_PI * 50.0; + parms1.wc_ = 31.41; + parms1.mp_ = 9.4e-5; + parms1.Vn_ = 380.0; + parms1.nq_ = 1.3e-3; + parms1.F_ = 0.75; + parms1.Kiv_ = 420.0; + parms1.Kpv_ = 0.1; + parms1.Kic_ = 2.0e4; + parms1.Kpc_ = 15.0; + parms1.Cf_ = 5.0e-5; + parms1.rLf_ = 0.1; + parms1.Lf_ = 1.35e-3; + parms1.rLc_ = 0.03; + parms1.Lc_ = 0.35e-3; + + GridKit::DistributedGeneratorParameters parms2; + // Parameters from MATLAB Microgrid code for first DG + parms2.wb_ = 2.0 * M_PI * 50.0; + parms2.wc_ = 31.41; + parms2.mp_ = 12.5e-5; + parms2.Vn_ = 380.0; + parms2.nq_ = 1.5e-3; + parms2.F_ = 0.75; + parms2.Kiv_ = 390.0; + parms2.Kpv_ = 0.05; + parms2.Kic_ = 16.0e3; + parms2.Kpc_ = 10.5; + parms2.Cf_ = 50.0e-6; + parms2.rLf_ = 0.1; + parms2.Lf_ = 1.35e-3; + parms2.rLc_ = 0.03; + parms2.Lc_ = 0.35e-3; + + // Line params + double rline1 = 0.23; + double Lline1 = 0.1 / (2.0 * M_PI * 50.0); + + double rline2 = 0.35; + double Lline2 = 0.58 / (2.0 * M_PI * 50.0); + + double rline3 = 0.23; + double Lline3 = 0.1 / (2.0 * M_PI * 50.0); + + // load parms + double rload1 = 3.0; + double Lload1 = 2.0 / (2.0 * M_PI * 50.0); + + double rload2 = 2.0; + double Lload2 = 1.0 / (2.0 * M_PI * 50.0); + + // indexing sets + size_t Nsize = 2; + // DGs + - refframe Lines + Loads + size_t vec_size_internals = 13 * (2 * Nsize) - 1 + (2 + 4 * (Nsize - 1)) + 2 * Nsize; + // \omegaref + BusDQ + size_t vec_size_externals = 1 + 2 * (2 * Nsize); + size_t dqbus1 = vec_size_internals + 1; + size_t dqbus2 = vec_size_internals + 3; + size_t dqbus3 = vec_size_internals + 5; + size_t dqbus4 = vec_size_internals + 7; + + size_t vec_size_total = vec_size_internals + vec_size_externals; + + size_t indexv = 0; + + // dg 1 + GridKit::DistributedGenerator* dg1 = new GridKit::DistributedGenerator(0, parms1, true); + // ref motor + dg1->setExternalConnectionNodes(0, vec_size_internals); + // outputs + dg1->setExternalConnectionNodes(1, dqbus1); + dg1->setExternalConnectionNodes(2, dqbus1 + 1); + //"grounding" of the difference + dg1->setExternalConnectionNodes(3, -1); + // internal connections + for (size_t i = 0; i < 12; i++) + { + + dg1->setExternalConnectionNodes(4 + i, indexv + i); + } + indexv += 12; + sysmodel->addComponent(dg1); + + // dg 2 + GridKit::DistributedGenerator* dg2 = new GridKit::DistributedGenerator(1, parms1, false); + // ref motor + dg2->setExternalConnectionNodes(0, vec_size_internals); + // outputs + dg2->setExternalConnectionNodes(1, dqbus2); + dg2->setExternalConnectionNodes(2, dqbus2 + 1); + // internal connections + for (size_t i = 0; i < 13; i++) + { + + dg2->setExternalConnectionNodes(3 + i, indexv + i); + } + indexv += 13; + sysmodel->addComponent(dg2); + + // dg 3 + GridKit::DistributedGenerator* dg3 = new GridKit::DistributedGenerator(2, parms2, false); + // ref motor + dg3->setExternalConnectionNodes(0, vec_size_internals); + // outputs + dg3->setExternalConnectionNodes(1, dqbus3); + dg3->setExternalConnectionNodes(2, dqbus3 + 1); + // internal connections + for (size_t i = 0; i < 13; i++) + { + + dg3->setExternalConnectionNodes(3 + i, indexv + i); + } + indexv += 13; + sysmodel->addComponent(dg3); + + // dg 4 + GridKit::DistributedGenerator* dg4 = new GridKit::DistributedGenerator(3, parms2, false); + // ref motor + dg4->setExternalConnectionNodes(0, vec_size_internals); + // outputs + dg4->setExternalConnectionNodes(1, dqbus4); + dg4->setExternalConnectionNodes(2, dqbus4 + 1); + + // internal connections + for (size_t i = 0; i < 13; i++) + { + + dg4->setExternalConnectionNodes(3 + i, indexv + i); + } + indexv += 13; + sysmodel->addComponent(dg4); + + // Lines + + // line 1 + GridKit::MicrogridLine* l1 = new GridKit::MicrogridLine(4, rline1, Lline1); + // ref motor + l1->setExternalConnectionNodes(0, vec_size_internals); + // input connections + l1->setExternalConnectionNodes(1, dqbus1); + l1->setExternalConnectionNodes(2, dqbus1 + 1); + // output connections + l1->setExternalConnectionNodes(3, dqbus2); + l1->setExternalConnectionNodes(4, dqbus2 + 1); + // internal connections + for (size_t i = 0; i < 2; i++) + { + + l1->setExternalConnectionNodes(5 + i, indexv + i); + } + indexv += 2; + sysmodel->addComponent(l1); + + // line 2 + GridKit::MicrogridLine* l2 = new GridKit::MicrogridLine(5, rline2, Lline2); + // ref motor + l2->setExternalConnectionNodes(0, vec_size_internals); + // input connections + l2->setExternalConnectionNodes(1, dqbus2); + l2->setExternalConnectionNodes(2, dqbus2 + 1); + // output connections + l2->setExternalConnectionNodes(3, dqbus3); + l2->setExternalConnectionNodes(4, dqbus3 + 1); + // internal connections + for (size_t i = 0; i < 2; i++) + { + + l2->setExternalConnectionNodes(5 + i, indexv + i); + } + indexv += 2; + sysmodel->addComponent(l2); + + // line 3 + GridKit::MicrogridLine* l3 = new GridKit::MicrogridLine(6, rline3, Lline3); + // ref motor + l3->setExternalConnectionNodes(0, vec_size_internals); + // input connections + l3->setExternalConnectionNodes(1, dqbus3); + l3->setExternalConnectionNodes(2, dqbus3 + 1); + // output connections + l3->setExternalConnectionNodes(3, dqbus4); + l3->setExternalConnectionNodes(4, dqbus4 + 1); + // internal connections + for (size_t i = 0; i < 2; i++) + { + + l3->setExternalConnectionNodes(5 + i, indexv + i); + } + indexv += 2; + sysmodel->addComponent(l3); + + // loads + + // load 1 + GridKit::MicrogridLoad* load1 = new GridKit::MicrogridLoad(7, rload1, Lload1); + // ref motor + load1->setExternalConnectionNodes(0, vec_size_internals); + // input connections + load1->setExternalConnectionNodes(1, dqbus1); + load1->setExternalConnectionNodes(2, dqbus1 + 1); + // internal connections + for (size_t i = 0; i < 2; i++) + { + + load1->setExternalConnectionNodes(3 + i, indexv + i); + } + indexv += 2; + sysmodel->addComponent(load1); + + // load 2 + GridKit::MicrogridLoad* load2 = new GridKit::MicrogridLoad(8, rload2, Lload2); + // ref motor + load2->setExternalConnectionNodes(0, vec_size_internals); + // input connections + load2->setExternalConnectionNodes(1, dqbus3); + load2->setExternalConnectionNodes(2, dqbus3 + 1); + // internal connections + for (size_t i = 0; i < 2; i++) + { + + load2->setExternalConnectionNodes(3 + i, indexv + i); + } + indexv += 2; + sysmodel->addComponent(load2); + + // Virtual PQ Buses + GridKit::MicrogridBusDQ* bus1 = new GridKit::MicrogridBusDQ(9, RN); + + bus1->setExternalConnectionNodes(0, dqbus1); + bus1->setExternalConnectionNodes(1, dqbus1 + 1); + sysmodel->addComponent(bus1); + + GridKit::MicrogridBusDQ* bus2 = new GridKit::MicrogridBusDQ(10, RN); + + bus2->setExternalConnectionNodes(0, dqbus2); + bus2->setExternalConnectionNodes(1, dqbus2 + 1); + sysmodel->addComponent(bus2); + + GridKit::MicrogridBusDQ* bus3 = new GridKit::MicrogridBusDQ(11, RN); + + bus3->setExternalConnectionNodes(0, dqbus3); + bus3->setExternalConnectionNodes(1, dqbus3 + 1); + sysmodel->addComponent(bus3); + + GridKit::MicrogridBusDQ* bus4 = new GridKit::MicrogridBusDQ(12, RN); + + bus4->setExternalConnectionNodes(0, dqbus4); + bus4->setExternalConnectionNodes(1, dqbus4 + 1); + sysmodel->addComponent(bus4); + + sysmodel->allocate(vec_size_total); + + std::cout << sysmodel->y().size() << std::endl; + std::cout << vec_size_internals << ", " << vec_size_externals << "\n"; + + // Create Intial points for states + for (size_t i = 0; i < vec_size_total; i++) + { + sysmodel->y()[i] = 0.0; + sysmodel->yp()[i] = 0.0; + } + + // Create Intial derivatives specifics generated in MATLAB + // DGs 1 + sysmodel->yp()[2] = parms1.Vn_; + sysmodel->yp()[4] = parms1.Kpv_ * parms1.Vn_; + sysmodel->yp()[6] = (parms1.Kpc_ * parms1.Kpv_ * parms1.Vn_) / parms1.Lf_; + sysmodel->yp()[12 + 3] = parms1.Vn_; + sysmodel->yp()[12 + 5] = parms1.Kpv_ * parms1.Vn_; + sysmodel->yp()[12 + 7] = (parms1.Kpc_ * parms1.Kpv_ * parms1.Vn_) / parms1.Lf_; + for (size_t i = 2; i < 4; i++) + { + sysmodel->yp()[13 * i - 1 + 3] = parms2.Vn_; + sysmodel->yp()[13 * i - 1 + 5] = parms2.Kpv_ * parms2.Vn_; + sysmodel->yp()[13 * i - 1 + 7] = (parms2.Kpc_ * parms2.Kpv_ * parms2.Vn_) / parms2.Lf_; + } + + // since the intial P_com = 0 + sysmodel->y()[vec_size_internals] = parms1.wb_; + + sysmodel->initialize(); + sysmodel->evaluateResidual(); + + std::vector& fres = sysmodel->getResidual(); + std::cout << "Verify Intial Resisdual is Zero: {\n"; + for (size_t i = 0; i < fres.size(); i++) + { + printf("%lu : %e \n", i, fres[i]); + } + std::cout << "}\n"; + + sysmodel->updateTime(0.0, 1.0e-8); + sysmodel->evaluateJacobian(); + std::cout << "Intial Jacobian with alpha:\n"; + + // Create numerical integrator and configure it for the generator model + AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); + + double t_init = 0.0; + double t_final = 1.0; + + // setup simulation + idas->configureSimulation(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init); + + idas->runSimulation(t_final); + + std::vector& yfinial = sysmodel->y(); + + std::cout << "Final Vector y\n"; + for (size_t i = 0; i < yfinial.size(); i++) + { + std::cout << yfinial[i] << "\n"; + } + + // Generate from MATLAB code ODE form with tolerances of 1e-12 + std::vector true_vec{ + 2.297543153595780e+04, + 1.275311524125022e+04, + 3.763060183116022e-02, + -2.098153459325261e-02, + 1.848285659119097e-02, + -1.563291404944864e-04, + 6.321941907011718e+01, + -2.942264300846256e+01, + 3.634209302905854e+02, + -2.668928293656362e-06, + 6.321941919221522e+01, + -3.509200178595996e+01, + -7.555954467454730e-03, + 2.297580486511343e+04, + 8.742028429066131e+03, + 3.710079564796484e-02, + -1.421122598056797e-02, + 1.874079517807597e-02, + -9.891304812687215e-05, + 6.232933298360234e+01, + -1.796494061423331e+01, + 3.686353885026506e+02, + 3.465673854181523e-05, + 6.232933406188410e+01, + -2.371564475187742e+01, + -8.273939686941580e-02, + 1.727775042678524e+04, + 1.649365247247288e+04, + 3.116555157570849e-02, + -2.985990066758010e-02, + 2.250012115906506e-02, + -2.643873146501096e-04, + 4.861823510250247e+01, + -4.088592755441309e+01, + 3.552597163751238e+02, + -1.496407194199739e-04, + 4.861823504694532e+01, + -4.642797132602495e+01, + -8.445727984408551e-02, + 1.727723725566433e+04, + 9.182386962936238e+03, + 3.024959333190777e-02, + -1.617250828202081e-02, + 2.318056864131751e-02, + -1.295918667730514e-04, + 4.718938244522050e+01, + -1.935782085675469e+01, + 3.662262287803608e+02, + 1.076423957830039e-04, + 4.718938116520511e+01, + -2.507094256286497e+01, + -1.881248349415025e+01, + 2.114714832305742e+01, + 4.329946674909793e+01, + -3.037887936225145e+00, + -4.487023117352992e+01, + 2.895883729832657e+01, + 8.199613345691378e+01, + -5.623856502948122e+01, + 1.327498499660322e+02, + -8.228065162347022e+01, + 3.119995747945993e+02, + 3.576922945168803e+02, + -5.850795361581618e+00, + 3.641193316268954e+02, + -8.846325267612976e+00, + 3.472146752739036e+02, + -3.272400970143252e+01, + 3.604108939430972e+02, + -3.492842627398574e+01}; + + std::cout << "Test the Relative Error\n"; + for (size_t i = 0; i < true_vec.size(); i++) + { + printf("%lu : %e ,\n", i, abs(true_vec[i] - yfinial[i]) / abs(true_vec[i])); + } + + delete idas; + delete sysmodel; + + return 0; +} diff --git a/examples/ParameterEstimation/CMakeLists.txt b/examples/ParameterEstimation/CMakeLists.txt new file mode 100644 index 000000000..00b2ce2da --- /dev/null +++ b/examples/ParameterEstimation/CMakeLists.txt @@ -0,0 +1,21 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +# - Slaven Peles +#]] + +add_executable(paramest ParameterEstimation.cpp) +target_link_libraries(paramest + GRIDKIT::bus + GRIDKIT::generator4param + GRIDKIT::solvers_opt + GRIDKIT::solvers_dyn + GRIDKIT::Utilities +) +# Fortran linker needed to link to HSL solvers +set_property(TARGET paramest PROPERTY LINKER_LANGUAGE Fortran) +install(TARGETS paramest RUNTIME DESTINATION bin) + +add_test(NAME ParameterEst COMMAND $) diff --git a/examples/ParameterEstimation/ParameterEstimation.cpp b/examples/ParameterEstimation/ParameterEstimation.cpp new file mode 100644 index 000000000..0899dfa44 --- /dev/null +++ b/examples/ParameterEstimation/ParameterEstimation.cpp @@ -0,0 +1,162 @@ + +#include +#include +#include + +#include "lookup_table.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + using namespace GridKit; + using namespace AnalysisManager::Sundials; + using namespace AnalysisManager; + using namespace GridKit::Testing; + + // Create an infinite bus + BaseBus* bus = new BusSlack(1.0, 0.0); + + // Attach a generator to that bus + Generator4Param* gen = new Generator4Param(bus); + + // Create a system model + SystemModel* model = new SystemModel(); + model->addBus(bus); + model->addComponent(gen); + + // allocate model components + model->allocate(); + + // Create numerical integrator and configure it for the generator model + Ida* idas = new Ida(model); + + double t_init = -1.0; + double t_final = -1.0; + + std::istringstream input_data(lookup_table); + GridKit::setLookupTable(gen->getLookupTable(), input_data, t_init, t_final); + + std::cout << "Performing parameter estimation with respect to data\nfrom " + << "t_init = " << t_init << " to t_final = " << t_final << "\n"; + + // setup simulation + idas->configureSimulation(); + idas->configureAdjoint(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init); + idas->configureQuadrature(); + idas->initializeQuadrature(); + + double t_fault = 0.1; + double t_clear = 0.1; + idas->runSimulation(t_fault); + idas->saveInitialCondition(); + // create initial condition after a fault + { + idas->getSavedInitialCondition(); + idas->initializeSimulation(t_init); + gen->V() = 0.0; + idas->runSimulation(t_clear, 20); + gen->V() = 1.0; + idas->saveInitialCondition(); + } + + // Set integration time for dynamic constrained optimization + idas->setIntegrationTime(t_init, t_final, 100); + + // Guess value of inertia coefficient + model->param()[0] = 3.0; + + // Create an instance of the IpoptApplication + Ipopt::SmartPtr ipoptApp = IpoptApplicationFactory(); + + // Set solver tolerance + const double tol = 1e-5; + + // Initialize the IpoptApplication and process the options + Ipopt::ApplicationReturnStatus status; + status = ipoptApp->Initialize(); + if (status != Ipopt::Solve_Succeeded) + { + std::cout << "\n\n*** Initialization failed! ***\n\n"; + return (int) status; + } + + // Configure Ipopt application + ipoptApp->Options()->SetStringValue("hessian_approximation", "limited-memory"); + ipoptApp->Options()->SetNumericValue("tol", tol); + ipoptApp->Options()->SetIntegerValue("print_level", 0); + + // Create dynamic objective interface to Ipopt solver + Ipopt::SmartPtr ipoptDynamicObjectiveInterface = + new IpoptInterface::DynamicObjective(idas); + + // Solve the problem + status = ipoptApp->OptimizeTNLP(ipoptDynamicObjectiveInterface); + std::cout << "\n\nProblem formulated as dynamic objective optimiztion ...\n"; + + if (status == Ipopt::Solve_Succeeded) + { + // Print result + std::cout << "\nSucess:\n The problem solved in " + << ipoptApp->Statistics()->IterationCount() << " iterations!\n" + << " Optimal value of H = " << model->param()[0] << "\n" + << " The final value of the objective function G(H) = " + << ipoptApp->Statistics()->FinalObjective() << "\n\n"; + } + + // Store dynamic objective optimization results + double* results = new double[model->sizeParams()]; + for (unsigned i = 0; i < model->sizeParams(); ++i) + { + results[i] = model->param()[i]; + } + + // Guess value of inertia coefficient + model->param()[0] = 3.0; + + // Create dynamic constraint interface to Ipopt solver + Ipopt::SmartPtr ipoptDynamicConstraintInterface = + new IpoptInterface::DynamicConstraint(idas); + + // Solve the problem + status = ipoptApp->OptimizeTNLP(ipoptDynamicConstraintInterface); + std::cout << "\n\nProblem formulated as dynamic constraint optimiztion ...\n"; + + if (status == Ipopt::Solve_Succeeded) + { + // Print result + std::cout << "\nSucess:\n The problem solved in " + << ipoptApp->Statistics()->IterationCount() << " iterations!\n" + << " Optimal value of H = " << model->param()[0] << "\n" + << " The final value of the objective function G(H) = " + << ipoptApp->Statistics()->FinalObjective() << "\n\n"; + } + + // Compare results of the two optimization methods + int retval = 0; + for (unsigned i = 0; i < model->sizeParams(); ++i) + { + if (!isEqual(results[i], model->param()[i], 100 * tol)) + --retval; + } + + if (retval < 0) + { + std::cout << "The two results differ beyond solver tolerance!\n"; + } + + delete[] results; + delete idas; + delete model; + return retval; +} diff --git a/Examples/ParameterEstimation/lookup_table.dat b/examples/ParameterEstimation/lookup_table.hpp similarity index 98% rename from Examples/ParameterEstimation/lookup_table.dat rename to examples/ParameterEstimation/lookup_table.hpp index bd4785e5b..735f1db18 100644 --- a/Examples/ParameterEstimation/lookup_table.dat +++ b/examples/ParameterEstimation/lookup_table.hpp @@ -1,4 +1,5 @@ - 0 0.092182 0.99596 -0.17574 0.98107 2.7864 0.58172 -1.5217 0.092914 0.4666 -0.18534 -0.49105 -1.3472 +std::string lookup_table = + R"( 0 0.092182 0.99596 -0.17574 0.98107 2.7864 0.58172 -1.5217 0.092914 0.4666 -0.18534 -0.49105 -1.3472 0.05 0.032044 0.99785 -0.15175 0.98425 -0.058476 0.52344 -0.80946 0.048601 0.41347 0.063192 0.20608 -3.487 0.1 0.016599 1.0006 -0.1331 0.98738 -0.047843 0.42635 0.22214 0.058264 0.34627 0.061871 0.19728 -0.34913 0.15 0.05483 1.0034 -0.11578 0.99044 -0.036909 0.48633 1.2885 0.052391 0.35895 0.060531 0.29873 2.6589 @@ -99,3 +100,4 @@ 4.9 0.67312 0.99966 0.37728 1.0099 0.63087 0.7213 -0.12935 0.0043559 -0.016631 -0.00033208 -0.22427 -0.24786 4.95 0.66892 0.99991 0.37636 1.0099 0.62362 0.71433 -0.035255 0.0053896 -0.019197 0.000302 -0.060867 -0.025908 5 0.66968 1.0002 0.37545 1.0099 0.6249 0.71867 0.064531 0.0049577 -0.016122 0.00018828 0.10945 0.19374 +)"; diff --git a/examples/PhasorDynamics/CMakeLists.txt b/examples/PhasorDynamics/CMakeLists.txt new file mode 100644 index 000000000..c758e4e56 --- /dev/null +++ b/examples/PhasorDynamics/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(Example1) diff --git a/examples/PhasorDynamics/Example1/CMakeLists.txt b/examples/PhasorDynamics/Example1/CMakeLists.txt new file mode 100644 index 000000000..c04e061ca --- /dev/null +++ b/examples/PhasorDynamics/Example1/CMakeLists.txt @@ -0,0 +1,14 @@ +add_executable(phasordynamics_example1 example1.cpp) +target_link_libraries(phasordynamics_example1 + GRIDKIT::phasor_dynamics_bus + GRIDKIT::phasor_dynamics_bus_fault + GRIDKIT::phasor_dynamics_branch + GRIDKIT::phasor_dynamics_genrou + SUNDIALS::sunlinsolklu + SUNDIALS::core + SUNDIALS::ida + SUNDIALS::idas + SUNDIALS::sunmatrixdense) +install(TARGETS phasordynamics_example1 RUNTIME DESTINATION bin) + +add_test(NAME GenrouTest COMMAND $) diff --git a/examples/PhasorDynamics/Example1/Example1_Powerworld_Reference.hpp b/examples/PhasorDynamics/Example1/Example1_Powerworld_Reference.hpp new file mode 100644 index 000000000..3076c2f5f --- /dev/null +++ b/examples/PhasorDynamics/Example1/Example1_Powerworld_Reference.hpp @@ -0,0 +1,2406 @@ +#include + +// Columns: +// Time, Machine Speed (PowerWorld), Bus 1 Voltage Magnitude (PowerWorld)}, +std::vector> reference_solution = + {{0, 1, 0}, // It should be {0,1,1.000000477} but something is wrong in GridKit + {0.004167, 1, 1.000000477}, + {0.008333, 1, 1.000000477}, + {0.0125, 0.99999994, 1.000000477}, + {0.016667, 0.99999994, 1.000000477}, + {0.020833, 0.99999994, 1.000000477}, + {0.025, 0.99999994, 1.000000477}, + {0.029167, 0.99999994, 1.000000477}, + {0.033333, 0.99999994, 1.000000477}, + {0.0375, 0.99999994, 1.000000477}, + {0.041667, 0.99999994, 1.000000477}, + {0.045833, 0.99999994, 1.000000477}, + {0.05, 0.999999881, 1.000000477}, + {0.054167, 0.999999881, 1.000000477}, + {0.058333, 0.999999881, 1.000000477}, + {0.0625, 0.999999881, 1.000000477}, + {0.066667, 0.999999881, 1.000000477}, + {0.070833, 0.999999881, 1.000000477}, + {0.075, 0.999999881, 1.000000477}, + {0.079167, 0.999999881, 1.000000477}, + {0.083333, 0.999999881, 1.000000477}, + {0.0875, 0.999999881, 1.000000477}, + {0.091667, 0.999999881, 1.000000477}, + {0.095833, 0.999999881, 1.000000477}, + {0.1, 0.999999881, 1.000000477}, + {0.104167, 0.999999881, 1.000000477}, + {0.108333, 0.999999881, 1.000000477}, + {0.1125, 0.999999881, 1.000000477}, + {0.116667, 0.999999881, 1.000000477}, + {0.120833, 0.999999881, 1.000000477}, + {0.125, 0.999999881, 1.000000477}, + {0.129167, 0.999999881, 1.000000477}, + {0.133333, 0.999999881, 1.000000477}, + {0.1375, 0.99999994, 1.000000477}, + {0.141667, 0.99999994, 1.000000477}, + {0.145833, 0.99999994, 1.000000477}, + {0.15, 0.99999994, 1.000000477}, + {0.154167, 0.99999994, 1.000000477}, + {0.158333, 0.99999994, 1.000000477}, + {0.1625, 0.99999994, 1.000000477}, + {0.166667, 0.99999994, 1.000000477}, + {0.170833, 0.99999994, 1.000000477}, + {0.175, 0.99999994, 1.000000477}, + {0.179167, 0.99999994, 1.000000477}, + {0.183333, 0.99999994, 1.000000477}, + {0.1875, 0.99999994, 1.000000477}, + {0.191667, 0.99999994, 1.000000477}, + {0.195833, 1, 1.000000477}, + {0.2, 1, 1.000000477}, + {0.204167, 1, 1.000000477}, + {0.208333, 1, 1.000000477}, + {0.2125, 1, 1.000000477}, + {0.216667, 1, 1.000000477}, + {0.220833, 1, 1.000000477}, + {0.225, 1, 1.000000477}, + {0.229167, 1, 1.000000477}, + {0.233333, 1, 1.000000477}, + {0.2375, 1, 1.000000477}, + {0.241667, 1, 1.000000477}, + {0.245833, 1, 1.000000477}, + {0.25, 1, 1.000000477}, + {0.254167, 1, 1.000000477}, + {0.258333, 1, 1.000000477}, + {0.2625, 1, 1.000000477}, + {0.266667, 1, 1.000000477}, + {0.270833, 1, 1.000000477}, + {0.275, 1, 1.000000477}, + {0.279167, 1, 1.000000477}, + {0.283333, 1, 1.000000477}, + {0.2875, 1, 1.000000477}, + {0.291667, 1, 1.000000477}, + {0.295833, 1.000000119, 1.000000477}, + {0.3, 1.000000119, 1.000000477}, + {0.304167, 1.000000119, 1.000000477}, + {0.308333, 1.000000119, 1.000000477}, + {0.3125, 1.000000119, 1.000000477}, + {0.316667, 1.000000119, 1.000000477}, + {0.320833, 1.000000119, 1.000000477}, + {0.325, 1.000000119, 1.000000477}, + {0.329167, 1.000000119, 1.000000477}, + {0.333333, 1.000000119, 1.000000477}, + {0.3375, 1.000000119, 1.000000477}, + {0.341667, 1.000000119, 1.000000477}, + {0.345833, 1.000000119, 1.000000477}, + {0.35, 1.000000119, 1.000000477}, + {0.354167, 1.000000119, 1.000000477}, + {0.358333, 1.000000119, 1.000000477}, + {0.3625, 1, 1.000000477}, + {0.366667, 1, 1.000000477}, + {0.370833, 1, 1.000000477}, + {0.375, 1, 1.000000477}, + {0.379167, 1, 1.000000477}, + {0.383333, 1, 1.000000477}, + {0.3875, 1, 1.000000477}, + {0.391667, 1, 1.000000477}, + {0.395833, 1, 1.000000477}, + {0.4, 1, 1.000000477}, + {0.404167, 1, 1.000000477}, + {0.408333, 1, 1.000000477}, + {0.4125, 1, 1.000000477}, + {0.416667, 1, 1.000000477}, + {0.420833, 1, 1.000000477}, + {0.425, 1, 1.000000477}, + {0.429167, 1, 1.000000477}, + {0.433333, 1, 1.000000477}, + {0.4375, 1, 1.000000477}, + {0.441667, 1, 1.000000477}, + {0.445833, 1, 1.000000477}, + {0.45, 1, 1.000000477}, + {0.454167, 1, 1.000000477}, + {0.458333, 1, 1.000000477}, + {0.4625, 1, 1.000000477}, + {0.466667, 1, 1.000000477}, + {0.470833, 1, 1.000000477}, + {0.475, 1, 1.000000477}, + {0.479167, 1, 1.000000477}, + {0.483333, 1, 1.000000477}, + {0.4875, 1, 1.000000477}, + {0.491667, 1, 1.000000477}, + {0.495833, 1, 1.000000477}, + {0.5, 1, 1.000000477}, + {0.504167, 1, 1.000000477}, + {0.508333, 1, 1.000000477}, + {0.5125, 0.99999994, 1.000000477}, + {0.516667, 0.99999994, 1.000000477}, + {0.520833, 0.99999994, 1.000000477}, + {0.525, 0.99999994, 1.000000477}, + {0.529167, 0.99999994, 1.000000477}, + {0.533333, 0.99999994, 1.000000477}, + {0.5375, 0.99999994, 1.000000477}, + {0.541667, 0.99999994, 1.000000477}, + {0.545833, 0.99999994, 1.000000477}, + {0.55, 0.99999994, 1.000000477}, + {0.554167, 0.99999994, 1.000000477}, + {0.558333, 0.99999994, 1.000000477}, + {0.5625, 0.99999994, 1.000000477}, + {0.566667, 0.99999994, 1.000000477}, + {0.570833, 0.99999994, 1.000000477}, + {0.575, 0.99999994, 1.000000477}, + {0.579167, 0.99999994, 1.000000477}, + {0.583333, 0.99999994, 1.000000477}, + {0.5875, 0.99999994, 1.000000477}, + {0.591667, 0.99999994, 1.000000477}, + {0.595833, 0.99999994, 1.000000477}, + {0.6, 0.99999994, 1.000000477}, + {0.604167, 0.99999994, 1.000000477}, + {0.608333, 0.99999994, 1.000000477}, + {0.6125, 0.99999994, 1.000000477}, + {0.616667, 0.99999994, 1.000000477}, + {0.620833, 1, 1.000000477}, + {0.625, 1, 1.000000477}, + {0.629167, 1, 1.000000477}, + {0.633333, 1, 1.000000477}, + {0.6375, 1, 1.000000477}, + {0.641667, 1, 1.000000477}, + {0.645833, 1, 1.000000477}, + {0.65, 1, 1.000000477}, + {0.654167, 1, 1.000000477}, + {0.658333, 1, 1.000000477}, + {0.6625, 1, 1.000000477}, + {0.666667, 1, 1.000000477}, + {0.670833, 1, 1.000000477}, + {0.675, 1, 1.000000477}, + {0.679167, 1, 1.000000477}, + {0.683333, 1, 1.000000477}, + {0.6875, 1, 1.000000477}, + {0.691667, 1, 1.000000477}, + {0.695833, 1, 1.000000477}, + {0.7, 1, 1.000000477}, + {0.704167, 1, 1.000000477}, + {0.708333, 1, 1.000000477}, + {0.7125, 1, 1.000000477}, + {0.716667, 1, 1.000000477}, + {0.720833, 1, 1.000000477}, + {0.725, 1, 1.000000477}, + {0.729167, 1, 1.000000477}, + {0.733333, 1, 1.000000477}, + {0.7375, 1, 1.000000477}, + {0.741667, 1, 1.000000477}, + {0.745833, 1, 1.000000477}, + {0.75, 1, 1.000000477}, + {0.754167, 1, 1.000000477}, + {0.758333, 1, 1.000000477}, + {0.7625, 1, 1.000000477}, + {0.766667, 1, 1.000000477}, + {0.770833, 1, 1.000000477}, + {0.775, 1, 1.000000477}, + {0.779167, 1, 1.000000477}, + {0.783333, 1, 1.000000477}, + {0.7875, 1, 1.000000477}, + {0.791667, 1, 1.000000477}, + {0.795833, 1, 1.000000477}, + {0.8, 1, 1.000000477}, + {0.804167, 1, 1.000000477}, + {0.808333, 1, 1.000000477}, + {0.8125, 1, 1.000000477}, + {0.816667, 1, 1.000000477}, + {0.820833, 1, 1.000000477}, + {0.825, 1, 1.000000477}, + {0.829167, 1, 1.000000477}, + {0.833333, 1, 1.000000477}, + {0.8375, 1, 1.000000477}, + {0.841667, 1, 1.000000477}, + {0.845833, 1, 1.000000477}, + {0.85, 1, 1.000000477}, + {0.854167, 1, 1.000000477}, + {0.858333, 1, 1.000000477}, + {0.8625, 1, 1.000000477}, + {0.866667, 1, 1.000000477}, + {0.870833, 1, 1.000000477}, + {0.875, 1, 1.000000477}, + {0.879167, 1, 1.000000477}, + {0.883333, 1, 1.000000477}, + {0.8875, 1, 1.000000477}, + {0.891667, 1, 1.000000477}, + {0.895833, 1, 1.000000477}, + {0.9, 1, 1.000000477}, + {0.904167, 1, 1.000000477}, + {0.908333, 1, 1.000000477}, + {0.9125, 1, 1.000000477}, + {0.916667, 1, 1.000000477}, + {0.920833, 1, 1.000000477}, + {0.925, 1, 1.000000477}, + {0.929167, 1, 1.000000477}, + {0.933333, 1, 1.000000477}, + {0.9375, 1, 1.000000477}, + {0.941667, 1, 1.000000477}, + {0.945833, 1, 1.000000477}, + {0.95, 1, 1.000000477}, + {0.954167, 1, 1.000000477}, + {0.958333, 1, 1.000000477}, + {0.9625, 1, 1.000000477}, + {0.966667, 1, 1.000000477}, + {0.970833, 1, 1.000000477}, + {0.975, 1, 1.000000477}, + {0.979167, 1, 1.000000477}, + {0.983333, 1, 1.000000477}, + {0.9875, 1, 1.000000477}, + {0.991667, 1, 1.000000477}, + {0.995833, 1, 1.000000477}, + {1, 1, 1.000000477}, + {1.004167, 1.000682712, 0.015128844}, + {1.008333, 1.001363397, 0.014973078}, + {1.0125, 1.002042532, 0.014841928}, + {1.016667, 1.002720356, 0.014729479}, + {1.020833, 1.00339675, 0.014631276}, + {1.025, 1.004072189, 0.014543867}, + {1.029167, 1.004746675, 0.01446466}, + {1.033333, 1.00541997, 0.014391631}, + {1.0375, 1.006092548, 0.01432314}, + {1.041667, 1.006764412, 0.014257919}, + {1.045833, 1.007435203, 0.014194945}, + {1.05, 1.008105278, 0.014133334}, + {1.054167, 1.008774638, 0.014072391}, + {1.058333, 1.009443045, 0.014011139}, + {1.0625, 1.010110855, 0.01395021}, + {1.066667, 1.010777831, 0.013887996}, + {1.070833, 1.011443853, 0.013824509}, + {1.075, 1.01210916, 0.013759368}, + {1.079167, 1.012773633, 0.013692267}, + {1.083333, 1.013437271, 0.013622929}, + {1.0875, 1.014100075, 0.013551049}, + {1.091667, 1.014762163, 0.013476389}, + {1.095833, 1.015423179, 0.013398723}, + {1.1, 1.016083598, 0.013398723}, + {1.104167, 1.015262365, 0.88047874}, + {1.108333, 1.014493585, 0.89023459}, + {1.1125, 1.013762116, 0.898759723}, + {1.116667, 1.013056278, 0.906125188}, + {1.120833, 1.012367129, 0.912427425}, + {1.125, 1.01168704, 0.917777061}, + {1.129167, 1.011010766, 0.922281682}, + {1.133333, 1.010334253, 0.926045954}, + {1.1375, 1.009654403, 0.929170609}, + {1.141667, 1.008969307, 0.931745946}, + {1.145833, 1.008277893, 0.93385452}, + {1.15, 1.007579207, 0.935571969}, + {1.154167, 1.006873131, 0.936964393}, + {1.158333, 1.006160259, 0.938090801}, + {1.1625, 1.005440712, 0.939003944}, + {1.166667, 1.0047158, 0.9397493}, + {1.170833, 1.003986597, 0.940366805}, + {1.175, 1.003253937, 0.940891325}, + {1.179167, 1.002519608, 0.941352487}, + {1.183333, 1.001785278, 0.94177556}, + {1.1875, 1.001052022, 0.942182004}, + {1.191667, 1.000321627, 0.942589283}, + {1.195833, 0.999596179, 0.943011642}, + {1.2, 0.998876929, 0.943460345}, + {1.204167, 0.998165727, 0.943943799}, + {1.208333, 0.997464538, 0.944467604}, + {1.2125, 0.996774673, 0.945035696}, + {1.216667, 0.996098042, 0.945649385}, + {1.220833, 0.995436549, 0.946308196}, + {1.225, 0.994791448, 0.947010458}, + {1.229167, 0.994164526, 0.947752595}, + {1.233333, 0.993557453, 0.948529899}, + {1.2375, 0.99297154, 0.949337125}, + {1.241667, 0.992408335, 0.950167537}, + {1.245833, 0.99186933, 0.951014042}, + {1.25, 0.991355598, 0.951869369}, + {1.254167, 0.990868449, 0.952725708}, + {1.258333, 0.990409136, 0.953574955}, + {1.2625, 0.989978492, 0.954409778}, + {1.266667, 0.989577591, 0.955215633}, + {1.270833, 0.989207327, 0.956005096}, + {1.275, 0.988868177, 0.956751525}, + {1.279167, 0.988560915, 0.957458079}, + {1.283333, 0.988285899, 0.958120406}, + {1.2875, 0.988043547, 0.958723307}, + {1.291667, 0.987834036, 0.959283113}, + {1.295833, 0.987657607, 0.959768534}, + {1.3, 0.987514019, 0.960213661}, + {1.304167, 0.987403274, 0.96057564}, + {1.308333, 0.987325132, 0.96090132}, + {1.3125, 0.987279058, 0.961140752}, + {1.316667, 0.987264812, 0.961349428}, + {1.320833, 0.987281561, 0.961474001}, + {1.325, 0.987328827, 0.961574197}, + {1.329167, 0.987405658, 0.961597323}, + {1.333333, 0.987511337, 0.961602867}, + {1.3375, 0.987644792, 0.96154201}, + {1.341667, 0.987805247, 0.961470485}, + {1.345833, 0.987991393, 0.961345851}, + {1.35, 0.988202393, 0.961207449}, + {1.354167, 0.988437057, 0.961049318}, + {1.358333, 0.988694072, 0.960876703}, + {1.3625, 0.988972366, 0.960694611}, + {1.366667, 0.989270747, 0.960507751}, + {1.370833, 0.989587843, 0.96032083}, + {1.375, 0.989922643, 0.960137904}, + {1.379167, 0.990273893, 0.959962845}, + {1.383333, 0.990640223, 0.95979917}, + {1.3875, 0.991020679, 0.959649861}, + {1.391667, 0.991413951, 0.959517598}, + {1.395833, 0.991818845, 0.959404588}, + {1.4, 0.992234349, 0.959312677}, + {1.404167, 0.99265933, 0.959243178}, + {1.408333, 0.993092477, 0.959197223}, + {1.4125, 0.993533015, 0.959175408}, + {1.416667, 0.993979812, 0.95917803}, + {1.420833, 0.994431734, 0.959205091}, + {1.425, 0.994888008, 0.959256351}, + {1.429167, 0.995347559, 0.959331334}, + {1.433333, 0.995809376, 0.959429204}, + {1.4375, 0.996272743, 0.959549129}, + {1.441667, 0.996736646, 0.95968461}, + {1.445833, 0.997200072, 0.959850907}, + {1.45, 0.997662604, 0.960024655}, + {1.454167, 0.998123169, 0.960226417}, + {1.458333, 0.998580933, 0.960433066}, + {1.4625, 0.999035299, 0.960664332}, + {1.466667, 0.999485552, 0.96089834}, + {1.470833, 0.99993068, 0.961153209}, + {1.475, 1.000370383, 0.961408794}, + {1.479167, 1.000803709, 0.961681604}, + {1.483333, 1.001230001, 0.961953163}, + {1.4875, 1.001648784, 0.962238312}, + {1.491667, 1.00205946, 0.962520778}, + {1.495833, 1.002461076, 0.962813199}, + {1.5, 1.002853513, 0.963101745}, + {1.504167, 1.003236055, 0.963396966}, + {1.508333, 1.003607988, 0.96368736}, + {1.5125, 1.003968954, 0.963981271}, + {1.516667, 1.004318357, 0.964269757}, + {1.520833, 1.004655838, 0.964558721}, + {1.525, 1.004980803, 0.964841962}, + {1.529167, 1.005292892, 0.965122938}, + {1.533333, 1.005591631, 0.965397894}, + {1.5375, 1.00587666, 0.965667963}, + {1.541667, 1.006147623, 0.96593219}, + {1.545833, 1.006403923, 0.966188729}, + {1.55, 1.006645441, 0.966439664}, + {1.554167, 1.00687182, 0.966680348}, + {1.558333, 1.007082582, 0.966915607}, + {1.5625, 1.007277608, 0.967138052}, + {1.566667, 1.00745666, 0.967355549}, + {1.570833, 1.007619381, 0.96755743}, + {1.575, 1.007765532, 0.967754841}, + {1.579167, 1.007894993, 0.967934012}, + {1.583333, 1.008007526, 0.968109071}, + {1.5875, 1.008103132, 0.968263447}, + {1.591667, 1.008181453, 0.968414128}, + {1.595833, 1.008242607, 0.968541622}, + {1.6, 1.008286357, 0.968665838}, + {1.604167, 1.008312702, 0.968764782}, + {1.608333, 1.008321762, 0.968860805}, + {1.6125, 1.008313417, 0.968929827}, + {1.616667, 1.008287787, 0.968996286}, + {1.620833, 1.008244872, 0.969034612}, + {1.625, 1.00818491, 0.969070733}, + {1.629167, 1.00810802, 0.969078183}, + {1.633333, 1.008014202, 0.969083905}, + {1.6375, 1.007904053, 0.969061136}, + {1.641667, 1.007777452, 0.969037175}, + {1.645833, 1.007634878, 0.968985915}, + {1.65, 1.007476687, 0.96893394}, + {1.654167, 1.007303119, 0.968856812}, + {1.658333, 1.007114768, 0.968779624}, + {1.6625, 1.006911874, 0.968680382}, + {1.666667, 1.006694913, 0.968581617}, + {1.670833, 1.00646472, 0.968464911}, + {1.675, 1.006221414, 0.968349338}, + {1.679167, 1.005965829, 0.968220592}, + {1.683333, 1.005698442, 0.968093693}, + {1.6875, 1.005420089, 0.967959166}, + {1.691667, 1.005131125, 0.967827022}, + {1.695833, 1.004832625, 0.967693269}, + {1.7, 1.004525065, 0.967562377}, + {1.704167, 1.00420928, 0.967436075}, + {1.708333, 1.003885984, 0.967313051}, + {1.7125, 1.003556132, 0.967200637}, + {1.716667, 1.003220201, 0.967091799}, + {1.720833, 1.0028795, 0.966999233}, + {1.725, 1.00253439, 0.966910303}, + {1.729167, 1.00218606, 0.966842711}, + {1.733333, 1.001835227, 0.966778576}, + {1.7375, 1.001482844, 0.966739953}, + {1.741667, 1.001129627, 0.966711283}, + {1.745833, 1.000776529, 0.966690898}, + {1.75, 1.000424623, 0.966700375}, + {1.754167, 1.000074387, 0.96671176}, + {1.758333, 0.999727011, 0.966754198}, + {1.7625, 0.999383092, 0.966797709}, + {1.766667, 0.999043643, 0.966872096}, + {1.770833, 0.998709381, 0.966946483}, + {1.775, 0.998381138, 0.967050433}, + {1.779167, 0.99805963, 0.967153192}, + {1.783333, 0.997745872, 0.96728301}, + {1.7875, 0.997440159, 0.967410386}, + {1.791667, 0.997143567, 0.967561364}, + {1.795833, 0.99685663, 0.967714787}, + {1.8, 0.996579885, 0.967869997}, + {1.804167, 0.996314168, 0.968042195}, + {1.808333, 0.996059835, 0.968208969}, + {1.8125, 0.995817542, 0.968387842}, + {1.816667, 0.995587707, 0.968560398}, + {1.820833, 0.995370924, 0.968739927}, + {1.825, 0.995167375, 0.968912601}, + {1.829167, 0.994977593, 0.969087243}, + {1.833333, 0.994801879, 0.969254494}, + {1.8375, 0.99464041, 0.96941936}, + {1.841667, 0.994493544, 0.969576657}, + {1.845833, 0.994361401, 0.969727576}, + {1.85, 0.994244099, 0.969871104}, + {1.854167, 0.994141817, 0.970005214}, + {1.858333, 0.994054556, 0.970132172}, + {1.8625, 0.993982315, 0.970247447}, + {1.866667, 0.993925095, 0.970356286}, + {1.870833, 0.993882775, 0.97045207}, + {1.875, 0.993855238, 0.970542192}, + {1.879167, 0.993842363, 0.970618844}, + {1.883333, 0.993843973, 0.970690787}, + {1.8875, 0.993859708, 0.970749676}, + {1.891667, 0.993889451, 0.97080493}, + {1.895833, 0.993932843, 0.970848203}, + {1.9, 0.993989527, 0.970888972}, + {1.904167, 0.994059205, 0.97091943}, + {1.908333, 0.994141459, 0.970948577}, + {1.9125, 0.994235873, 0.970969498}, + {1.916667, 0.994342029, 0.970990121}, + {1.920833, 0.99445945, 0.971004903}, + {1.925, 0.994587719, 0.971020401}, + {1.929167, 0.9947263, 0.971032619}, + {1.933333, 0.994874775, 0.971046269}, + {1.9375, 0.995032549, 0.971059203}, + {1.941667, 0.995199144, 0.971074224}, + {1.945833, 0.995373964, 0.971090853}, + {1.95, 0.995556593, 0.971110106}, + {1.954167, 0.995746374, 0.971133053}, + {1.958333, 0.995942831, 0.971158922}, + {1.9625, 0.996145368, 0.971190274}, + {1.966667, 0.996353567, 0.971224725}, + {1.970833, 0.996566653, 0.97126615}, + {1.975, 0.996784389, 0.971310556}, + {1.979167, 0.997005939, 0.971363068}, + {1.983333, 0.997230887, 0.971418381}, + {1.9875, 0.997458696, 0.971482456}, + {1.991667, 0.997688949, 0.971549094}, + {1.995833, 0.997920871, 0.971624851}, + {2, 0.998154223, 0.971702695}, + {2.004167, 0.99838829, 0.971789718}, + {2.008333, 0.998622656, 0.971878409}, + {2.0125, 0.998856843, 0.971975863}, + {2.016667, 0.999090433, 0.972074568}, + {2.020833, 0.999322772, 0.972181499}, + {2.025, 0.999553561, 0.972289145}, + {2.029167, 0.999782324, 0.972404182}, + {2.033333, 1.000008583, 0.972519457}, + {2.0375, 1.000231862, 0.97264123}, + {2.041667, 1.000451922, 0.972762704}, + {2.045833, 1.000668168, 0.972889543}, + {2.05, 1.000880361, 0.973015666}, + {2.054167, 1.001088023, 0.973146021}, + {2.058333, 1.001290798, 0.973275185}, + {2.0625, 1.001488328, 0.973407388}, + {2.066667, 1.001680374, 0.973538041}, + {2.070833, 1.00186646, 0.973670363}, + {2.075, 1.002046466, 0.973800957}, + {2.079167, 1.002219915, 0.973931909}, + {2.083333, 1.002386689, 0.974060893}, + {2.0875, 1.00254631, 0.974188983}, + {2.091667, 1.002698779, 0.974314928}, + {2.095833, 1.002843618, 0.974438667}, + {2.1, 1.002980828, 0.974560261}, + {2.104167, 1.003109932, 0.974678457}, + {2.108333, 1.003231049, 0.974794388}, + {2.1125, 1.003343701, 0.974905789}, + {2.116667, 1.003448009, 0.975015044}, + {2.120833, 1.003543615, 0.975118697}, + {2.125, 1.003630638, 0.975220263}, + {2.129167, 1.00370872, 0.975315332}, + {2.133333, 1.003777862, 0.975408375}, + {2.1375, 1.003837943, 0.975494087}, + {2.141667, 1.003889084, 0.97557801}, + {2.145833, 1.003931046, 0.975653946}, + {2.15, 1.003963828, 0.975728214}, + {2.154167, 1.003987551, 0.975794077}, + {2.158333, 1.004002213, 0.97585845}, + {2.1625, 1.004007816, 0.975914061}, + {2.166667, 1.00400424, 0.97596848}, + {2.170833, 1.003991842, 0.976014078}, + {2.175, 1.003970623, 0.976058662}, + {2.179167, 1.003940463, 0.976094544}, + {2.183333, 1.003901839, 0.976129651}, + {2.1875, 1.003854632, 0.976156354}, + {2.191667, 1.003799081, 0.97618264}, + {2.195833, 1.003735423, 0.976201057}, + {2.2, 1.003663778, 0.976219237}, + {2.204167, 1.003584385, 0.976230323}, + {2.208333, 1.003497481, 0.97624141}, + {2.2125, 1.003403306, 0.976246357}, + {2.216667, 1.003302097, 0.976251602}, + {2.220833, 1.003194094, 0.976251721}, + {2.225, 1.003079653, 0.976252377}, + {2.229167, 1.002959013, 0.976249218}, + {2.233333, 1.002832532, 0.976246715}, + {2.2375, 1.002700567, 0.976241708}, + {2.241667, 1.002563357, 0.976237595}, + {2.245833, 1.002421498, 0.97623235}, + {2.25, 1.00227499, 0.976228058}, + {2.254167, 1.002124429, 0.976224005}, + {2.258333, 1.001970172, 0.976221025}, + {2.2625, 1.001812577, 0.976219654}, + {2.266667, 1.001652002, 0.976219356}, + {2.270833, 1.001489043, 0.976221859}, + {2.275, 1.001323819, 0.976225436}, + {2.279167, 1.001156807, 0.976232946}, + {2.283333, 1.000988603, 0.976241529}, + {2.2875, 1.000819445, 0.97625488}, + {2.291667, 1.000649691, 0.976269126}, + {2.295833, 1.000480056, 0.976288915}, + {2.3, 1.00031054, 0.976309478}, + {2.304167, 1.00014174, 0.976336062}, + {2.308333, 0.999974132, 0.976363182}, + {2.3125, 0.999808013, 0.97639662}, + {2.316667, 0.999643743, 0.976430357}, + {2.320833, 0.999481857, 0.976470292}, + {2.325, 0.999322474, 0.976510406}, + {2.329167, 0.999166131, 0.97655654}, + {2.333333, 0.999013186, 0.976602495}, + {2.3375, 0.998863876, 0.976654112}, + {2.341667, 0.998718619, 0.976705313}, + {2.345833, 0.998577714, 0.97676152}, + {2.35, 0.998441339, 0.976817131}, + {2.354167, 0.99830997, 0.976876974}, + {2.358333, 0.998183727, 0.976935983}, + {2.3625, 0.998062968, 0.976998508}, + {2.366667, 0.997947812, 0.97706002}, + {2.370833, 0.997838557, 0.977124095}, + {2.375, 0.997735381, 0.977187037}, + {2.379167, 0.997638524, 0.977251768}, + {2.383333, 0.997548044, 0.977315128}, + {2.3875, 0.99746418, 0.97737956}, + {2.391667, 0.997386992, 0.977442563}, + {2.395833, 0.997316659, 0.977505863}, + {2.4, 0.99725318, 0.977567792}, + {2.404167, 0.997196674, 0.977629304}, + {2.408333, 0.997147202, 0.977689505}, + {2.4125, 0.997104764, 0.977748811}, + {2.416667, 0.997069418, 0.977806926}, + {2.420833, 0.997041106, 0.977863729}, + {2.425, 0.997019887, 0.977919519}, + {2.429167, 0.997005641, 0.977973759}, + {2.433333, 0.99699831, 0.978027105}, + {2.4375, 0.996997893, 0.978078902}, + {2.441667, 0.997004211, 0.978129923}, + {2.445833, 0.997017264, 0.978179455}, + {2.45, 0.997036815, 0.97822845}, + {2.454167, 0.997062802, 0.978276134}, + {2.458333, 0.997095108, 0.97832346}, + {2.4625, 0.997133493, 0.978369713}, + {2.466667, 0.997177839, 0.978415847}, + {2.470833, 0.997227907, 0.978461266}, + {2.475, 0.997283578, 0.978506744}, + {2.479167, 0.997344553, 0.978551865}, + {2.483333, 0.997410715, 0.978597224}, + {2.4875, 0.997481763, 0.978642642}, + {2.491667, 0.99755758, 0.978688478}, + {2.495833, 0.997637749, 0.978734732}, + {2.5, 0.997722149, 0.978781521}, + {2.504167, 0.997810483, 0.978829205}, + {2.508333, 0.997902572, 0.978877366}, + {2.5125, 0.997998059, 0.978926837}, + {2.516667, 0.998096764, 0.978976846}, + {2.520833, 0.99819833, 0.979028463}, + {2.525, 0.998302639, 0.979080617}, + {2.529167, 0.998409212, 0.97913456}, + {2.533333, 0.998517931, 0.979189098}, + {2.5375, 0.998628497, 0.979245543}, + {2.541667, 0.998740673, 0.979302526}, + {2.545833, 0.998854041, 0.979361534}, + {2.55, 0.998968482, 0.97942096}, + {2.554167, 0.999083698, 0.979482412}, + {2.558333, 0.99919939, 0.979544222}, + {2.5625, 0.999315321, 0.97960794}, + {2.566667, 0.999431312, 0.979671896}, + {2.570833, 0.999546885, 0.979737639}, + {2.575, 0.999662042, 0.979803562}, + {2.579167, 0.999776363, 0.979871035}, + {2.583333, 0.999889672, 0.979938447}, + {2.5875, 1.000001788, 0.980007231}, + {2.591667, 1.000112414, 0.980075896}, + {2.595833, 1.000221252, 0.980145454}, + {2.6, 1.000328302, 0.980214894}, + {2.604167, 1.000433087, 0.98028487}, + {2.608333, 1.000535607, 0.980354488}, + {2.6125, 1.000635624, 0.980424404}, + {2.616667, 1.000732899, 0.980493844}, + {2.620833, 1.000827312, 0.980563104}, + {2.625, 1.000918627, 0.980631888}, + {2.629167, 1.001006722, 0.980700076}, + {2.633333, 1.001091361, 0.980767667}, + {2.6375, 1.001172543, 0.980834305}, + {2.641667, 1.001250029, 0.980900288}, + {2.645833, 1.001323581, 0.980964839}, + {2.65, 1.001393318, 0.981028795}, + {2.654167, 1.001459002, 0.981091022}, + {2.658333, 1.001520634, 0.981152534}, + {2.6625, 1.001577854, 0.98121196}, + {2.666667, 1.001630902, 0.98127073}, + {2.670833, 1.00167942, 0.981327116}, + {2.675, 1.001723647, 0.981382847}, + {2.679167, 1.001763225, 0.981435895}, + {2.683333, 1.001798391, 0.981488407}, + {2.6875, 1.001828909, 0.981538057}, + {2.691667, 1.001854777, 0.981587112}, + {2.695833, 1.001875997, 0.981633246}, + {2.7, 1.001892686, 0.981678843}, + {2.704167, 1.001904726, 0.981721342}, + {2.708333, 1.001912117, 0.981763482}, + {2.7125, 1.001914978, 0.981802464}, + {2.716667, 1.001913309, 0.981841147}, + {2.720833, 1.00190711, 0.981876731}, + {2.725, 1.001896501, 0.981912136}, + {2.729167, 1.00188148, 0.981944501}, + {2.733333, 1.001862168, 0.981976748}, + {2.7375, 1.001838684, 0.982006192}, + {2.741667, 1.001811028, 0.982035518}, + {2.745833, 1.001779318, 0.98206234}, + {2.75, 1.001743793, 0.982089102}, + {2.754167, 1.001704335, 0.98211354}, + {2.758333, 1.001661181, 0.982138097}, + {2.7625, 1.001614571, 0.982160687}, + {2.766667, 1.001564503, 0.982183337}, + {2.770833, 1.001511216, 0.982204437}, + {2.775, 1.001454711, 0.982225657}, + {2.779167, 1.001395345, 0.982245624}, + {2.783333, 1.001333117, 0.98226589}, + {2.7875, 1.001268268, 0.982285261}, + {2.791667, 1.001200914, 0.982304871}, + {2.795833, 1.001131415, 0.982324004}, + {2.8, 1.001059771, 0.982343495}, + {2.804167, 1.000986099, 0.982362807}, + {2.808333, 1.000910878, 0.982382476}, + {2.8125, 1.000833988, 0.982402384}, + {2.816667, 1.000755906, 0.98242265}, + {2.820833, 1.000676632, 0.982443452}, + {2.825, 1.000596285, 0.982464552}, + {2.829167, 1.000515342, 0.982486546}, + {2.833333, 1.000433803, 0.982508838}, + {2.8375, 1.000351906, 0.982532263}, + {2.841667, 1.000269771, 0.982555926}, + {2.845833, 1.000187874, 0.9825809}, + {2.85, 1.000106096, 0.982606173}, + {2.854167, 1.000024676, 0.982632816}, + {2.858333, 0.999943972, 0.982659698}, + {2.8625, 0.999864042, 0.982688129}, + {2.866667, 0.999785066, 0.98271668}, + {2.870833, 0.999707282, 0.98274678}, + {2.875, 0.999630749, 0.982777059}, + {2.879167, 0.999555767, 0.982808828}, + {2.883333, 0.999482453, 0.982840717}, + {2.8875, 0.999410987, 0.982874095}, + {2.891667, 0.999341428, 0.982907474}, + {2.895833, 0.999274015, 0.982942283}, + {2.9, 0.999208868, 0.982977033}, + {2.904167, 0.999146104, 0.983013093}, + {2.908333, 0.999085844, 0.983049035}, + {2.9125, 0.999028206, 0.983086228}, + {2.916667, 0.99897325, 0.983123243}, + {2.920833, 0.998921216, 0.98316133}, + {2.925, 0.998872042, 0.983199179}, + {2.929167, 0.998825967, 0.983237982}, + {2.933333, 0.998782873, 0.983276546}, + {2.9375, 0.998742998, 0.983315885}, + {2.941667, 0.998706341, 0.983354986}, + {2.945833, 0.998672962, 0.983394682}, + {2.95, 0.998642862, 0.9834342}, + {2.954167, 0.998616099, 0.983474135}, + {2.958333, 0.998592734, 0.983513892}, + {2.9625, 0.998572767, 0.983554006}, + {2.966667, 0.998556137, 0.983593881}, + {2.970833, 0.998542905, 0.983634114}, + {2.975, 0.99853307, 0.983674109}, + {2.979167, 0.998526633, 0.983714342}, + {2.983333, 0.998523533, 0.983754396}, + {2.9875, 0.998523712, 0.98379463}, + {2.991667, 0.998527169, 0.983834684}, + {2.995833, 0.998533845, 0.983874977}, + {3, 0.998543739, 0.983915091}, + {3.004167, 0.998556674, 0.983955443}, + {3.008333, 0.998572707, 0.983995676}, + {3.0125, 0.998591661, 0.984036088}, + {3.016667, 0.998613536, 0.98407644}, + {3.020833, 0.998638153, 0.984117031}, + {3.025, 0.998665512, 0.984157622}, + {3.029167, 0.998695493, 0.984198391}, + {3.033333, 0.998727977, 0.984239221}, + {3.0375, 0.998762906, 0.984280348}, + {3.041667, 0.998800099, 0.984321475}, + {3.045833, 0.998839438, 0.9843629}, + {3.05, 0.998880863, 0.984404445}, + {3.054167, 0.998924255, 0.984446287}, + {3.058333, 0.998969436, 0.984488249}, + {3.0625, 0.999016345, 0.984530509}, + {3.066667, 0.999064803, 0.984572887}, + {3.070833, 0.999114692, 0.984615624}, + {3.075, 0.999165893, 0.98465848}, + {3.079167, 0.999218225, 0.984701633}, + {3.083333, 0.999271631, 0.984744906}, + {3.0875, 0.999325931, 0.984788537}, + {3.091667, 0.999381006, 0.984832227}, + {3.095833, 0.999436736, 0.984876215}, + {3.1, 0.999492943, 0.984920263}, + {3.104167, 0.999549508, 0.984964609}, + {3.108333, 0.999606311, 0.985008955}, + {3.1125, 0.999663234, 0.98505348}, + {3.116667, 0.999720097, 0.985098004}, + {3.120833, 0.99977684, 0.985142648}, + {3.125, 0.999833286, 0.985187292}, + {3.129167, 0.999889314, 0.985231936}, + {3.133333, 0.999944806, 0.98527652}, + {3.1375, 0.999999642, 0.985321045}, + {3.141667, 1.000053763, 0.98536545}, + {3.145833, 1.000106931, 0.985409677}, + {3.15, 1.000159144, 0.985453784}, + {3.154167, 1.000210285, 0.985497534}, + {3.158333, 1.000260115, 0.985541224}, + {3.1625, 1.000308752, 0.985584378}, + {3.166667, 1.000355959, 0.985627472}, + {3.170833, 1.000401735, 0.985669911}, + {3.175, 1.000445843, 0.98571223}, + {3.179167, 1.0004884, 0.985753834}, + {3.183333, 1.00052917, 0.985795259}, + {3.1875, 1.000568032, 0.98583585}, + {3.191667, 1.000605226, 0.985876262}, + {3.195833, 1.000640273, 0.98591572}, + {3.2, 1.000673413, 0.985955}, + {3.204167, 1.000704527, 0.985993266}, + {3.208333, 1.000733614, 0.986031294}, + {3.2125, 1.000760436, 0.986068249}, + {3.216667, 1.000785112, 0.986105025}, + {3.220833, 1.000807524, 0.986140609}, + {3.225, 1.000827789, 0.986176014}, + {3.229167, 1.00084579, 0.986210167}, + {3.233333, 1.000861406, 0.986244142}, + {3.2375, 1.000874758, 0.986276925}, + {3.241667, 1.000885844, 0.986309528}, + {3.245833, 1.000894666, 0.986340821}, + {3.25, 1.000901222, 0.986372054}, + {3.254167, 1.000905395, 0.986401975}, + {3.258333, 1.000907302, 0.986431777}, + {3.2625, 1.000906944, 0.986460388}, + {3.266667, 1.000904441, 0.986488879}, + {3.270833, 1.000899673, 0.986516178}, + {3.275, 1.000892639, 0.986543477}, + {3.279167, 1.000883579, 0.986569583}, + {3.283333, 1.000872493, 0.98659569}, + {3.2875, 1.000859261, 0.986620784}, + {3.291667, 1.000844121, 0.986645818}, + {3.295833, 1.000826955, 0.986669898}, + {3.3, 1.000807881, 0.986694038}, + {3.304167, 1.000787139, 0.986717284}, + {3.308333, 1.000764608, 0.986740589}, + {3.3125, 1.00074029, 0.986763179}, + {3.316667, 1.000714421, 0.986785829}, + {3.320833, 1.000687122, 0.986807883}, + {3.325, 1.000658274, 0.986829996}, + {3.329167, 1.000628114, 0.986851633}, + {3.333333, 1.000596523, 0.986873388}, + {3.3375, 1.00056386, 0.986894786}, + {3.341667, 1.000530124, 0.986916244}, + {3.345833, 1.000495315, 0.986937523}, + {3.35, 1.000459552, 0.986958921}, + {3.354167, 1.000423074, 0.986980259}, + {3.358333, 1.000385761, 0.987001657}, + {3.3625, 1.000347853, 0.987023056}, + {3.366667, 1.000309348, 0.987044632}, + {3.370833, 1.000270367, 0.987066269}, + {3.375, 1.000231028, 0.987088084}, + {3.379167, 1.000191569, 0.987110138}, + {3.383333, 1.000151753, 0.987132251}, + {3.3875, 1.000112057, 0.987154663}, + {3.391667, 1.000072241, 0.987177193}, + {3.395833, 1.000032663, 0.987200141}, + {3.4, 0.999993145, 0.987223148}, + {3.404167, 0.999954045, 0.987246573}, + {3.408333, 0.999915302, 0.987270117}, + {3.4125, 0.999877036, 0.987294137}, + {3.416667, 0.999839365, 0.987318218}, + {3.420833, 0.999802351, 0.987342775}, + {3.425, 0.999765992, 0.987367451}, + {3.429167, 0.999730527, 0.987392604}, + {3.433333, 0.999695897, 0.987417817}, + {3.4375, 0.99966222, 0.987443566}, + {3.441667, 0.999629617, 0.987469375}, + {3.445833, 0.999598086, 0.98749572}, + {3.45, 0.999567688, 0.987522006}, + {3.454167, 0.999538481, 0.987548888}, + {3.458333, 0.999510586, 0.98757571}, + {3.4625, 0.999484062, 0.987603068}, + {3.466667, 0.999458849, 0.987630427}, + {3.470833, 0.999435067, 0.987658262}, + {3.475, 0.999412715, 0.987686098}, + {3.479167, 0.999391854, 0.98771435}, + {3.483333, 0.999372542, 0.987742543}, + {3.4875, 0.999354839, 0.987771213}, + {3.491667, 0.999338627, 0.987799883}, + {3.495833, 0.999324083, 0.987828851}, + {3.5, 0.999311149, 0.987857878}, + {3.504167, 0.999299824, 0.987887204}, + {3.508333, 0.999290168, 0.987916529}, + {3.5125, 0.999282122, 0.987946153}, + {3.516667, 0.999275744, 0.987975776}, + {3.520833, 0.999270976, 0.988005638}, + {3.525, 0.999267876, 0.9880355}, + {3.529167, 0.999266386, 0.98806566}, + {3.533333, 0.999266505, 0.98809576}, + {3.5375, 0.999268234, 0.988126099}, + {3.541667, 0.999271512, 0.988156438}, + {3.545833, 0.99927634, 0.988187015}, + {3.55, 0.999282718, 0.988217533}, + {3.554167, 0.999290526, 0.988248229}, + {3.558333, 0.999299765, 0.988278985}, + {3.5625, 0.999310493, 0.98830986}, + {3.566667, 0.999322534, 0.988340735}, + {3.570833, 0.999335885, 0.988371789}, + {3.575, 0.999350548, 0.988402784}, + {3.579167, 0.999366403, 0.988433957}, + {3.583333, 0.99938345, 0.98846513}, + {3.5875, 0.999401629, 0.988496423}, + {3.591667, 0.999420881, 0.988527715}, + {3.595833, 0.999441147, 0.988559127}, + {3.6, 0.999462366, 0.988590479}, + {3.604167, 0.999484479, 0.98862195}, + {3.608333, 0.999507427, 0.988653421}, + {3.6125, 0.99953115, 0.988684893}, + {3.616667, 0.999555588, 0.988716424}, + {3.620833, 0.999580622, 0.988747954}, + {3.625, 0.999606252, 0.988779485}, + {3.629167, 0.999632418, 0.988810956}, + {3.633333, 0.999659002, 0.988842487}, + {3.6375, 0.999685943, 0.988873959}, + {3.641667, 0.999713242, 0.98890543}, + {3.645833, 0.99974072, 0.988936782}, + {3.65, 0.999768436, 0.988968134}, + {3.654167, 0.999796212, 0.988999367}, + {3.658333, 0.999824107, 0.9890306}, + {3.6625, 0.999851942, 0.989061654}, + {3.666667, 0.999879658, 0.989092648}, + {3.670833, 0.999907255, 0.989123464}, + {3.675, 0.999934673, 0.989154279}, + {3.679167, 0.999961793, 0.989184797}, + {3.683333, 0.999988556, 0.989215255}, + {3.6875, 1.00001502, 0.989245474}, + {3.691667, 1.000041008, 0.989275634}, + {3.695833, 1.0000664, 0.989305437}, + {3.7, 1.000091314, 0.989335179}, + {3.704167, 1.000115633, 0.989364564}, + {3.708333, 1.000139356, 0.98939383}, + {3.7125, 1.000162244, 0.989422739}, + {3.716667, 1.000184536, 0.989451587}, + {3.720833, 1.000205874, 0.989479899}, + {3.725, 1.000226498, 0.989508212}, + {3.729167, 1.000246286, 0.989535987}, + {3.733333, 1.000265121, 0.989563704}, + {3.7375, 1.000283003, 0.989590943}, + {3.741667, 1.000299931, 0.989618063}, + {3.745833, 1.000315905, 0.989644587}, + {3.75, 1.000330806, 0.989671111}, + {3.754167, 1.000344634, 0.989697039}, + {3.758333, 1.000357509, 0.989722848}, + {3.7625, 1.000369191, 0.98974812}, + {3.766667, 1.000379801, 0.989773333}, + {3.770833, 1.000389338, 0.98979789}, + {3.775, 1.000397801, 0.989822447}, + {3.779167, 1.000405073, 0.989846408}, + {3.783333, 1.000411153, 0.98987025}, + {3.7875, 1.00041616, 0.989893556}, + {3.791667, 1.000419974, 0.989916801}, + {3.795833, 1.000422716, 0.989939451}, + {3.8, 1.000424385, 0.989962041}, + {3.804167, 1.000424862, 0.989984095}, + {3.808333, 1.000424266, 0.990006089}, + {3.8125, 1.000422597, 0.990027547}, + {3.816667, 1.000419736, 0.990049005}, + {3.820833, 1.000415921, 0.990069926}, + {3.825, 1.000411034, 0.990090847}, + {3.829167, 1.000405192, 0.990111291}, + {3.833333, 1.000398278, 0.990131736}, + {3.8375, 1.00039053, 0.990151703}, + {3.841667, 1.000381708, 0.990171731}, + {3.845833, 1.000372052, 0.99019134}, + {3.85, 1.000361443, 0.99021095}, + {3.854167, 1.000350118, 0.990230203}, + {3.858333, 1.000337839, 0.990249455}, + {3.8625, 1.000324965, 0.990268469}, + {3.866667, 1.000311255, 0.990287483}, + {3.870833, 1.000296831, 0.990306258}, + {3.875, 1.000281811, 0.990325034}, + {3.879167, 1.000266194, 0.99034363}, + {3.883333, 1.000249982, 0.990362227}, + {3.8875, 1.000233293, 0.990380764}, + {3.891667, 1.000216126, 0.990399241}, + {3.895833, 1.000198603, 0.990417659}, + {3.9, 1.000180602, 0.990436137}, + {3.904167, 1.000162244, 0.990454555}, + {3.908333, 1.000143766, 0.990473032}, + {3.9125, 1.000124931, 0.990491509}, + {3.916667, 1.000105858, 0.990509987}, + {3.920833, 1.000086665, 0.990528524}, + {3.925, 1.000067472, 0.990547061}, + {3.929167, 1.000048161, 0.990565717}, + {3.933333, 1.000028849, 0.990584433}, + {3.9375, 1.000009537, 0.990603209}, + {3.941667, 0.999990344, 0.990622103}, + {3.945833, 0.999971271, 0.990641057}, + {3.95, 0.999952376, 0.990660071}, + {3.954167, 0.99993372, 0.990679264}, + {3.958333, 0.999915302, 0.990698457}, + {3.9625, 0.999897242, 0.990717828}, + {3.966667, 0.999879479, 0.990737259}, + {3.970833, 0.999862075, 0.990756929}, + {3.975, 0.999845088, 0.990776539}, + {3.979167, 0.999828577, 0.990796447}, + {3.983333, 0.999812543, 0.990816295}, + {3.9875, 0.999797046, 0.990836442}, + {3.991667, 0.999782085, 0.990856528}, + {3.995833, 0.999767721, 0.990876913}, + {4, 0.999753952, 0.990897238}, + {4.004167, 0.999740779, 0.990917861}, + {4.008333, 0.999728322, 0.990938425}, + {4.0125, 0.99971652, 0.990959287}, + {4.016667, 0.999705434, 0.990980089}, + {4.020833, 0.999695063, 0.991001189}, + {4.025, 0.999685407, 0.991022229}, + {4.029167, 0.999676526, 0.991043508}, + {4.033333, 0.999668419, 0.991064787}, + {4.0375, 0.999661088, 0.991086245}, + {4.041667, 0.999654531, 0.991107702}, + {4.045833, 0.99964875, 0.991129398}, + {4.05, 0.999643803, 0.991151035}, + {4.054167, 0.99963963, 0.99117291}, + {4.058333, 0.999636233, 0.991194725}, + {4.0625, 0.99963367, 0.991216719}, + {4.066667, 0.999631941, 0.991238713}, + {4.070833, 0.999630928, 0.991260886}, + {4.075, 0.999630749, 0.991283059}, + {4.079167, 0.999631345, 0.991305292}, + {4.083333, 0.999632716, 0.991327584}, + {4.0875, 0.999634802, 0.991349995}, + {4.091667, 0.999637663, 0.991372347}, + {4.095833, 0.999641299, 0.991394877}, + {4.1, 0.999645591, 0.991417348}, + {4.104167, 0.999650598, 0.991439939}, + {4.108333, 0.99965626, 0.991462469}, + {4.1125, 0.999662578, 0.991485119}, + {4.116667, 0.999669552, 0.991507709}, + {4.120833, 0.999677122, 0.991530359}, + {4.125, 0.999685287, 0.991553009}, + {4.129167, 0.99969399, 0.991575718}, + {4.133333, 0.999703228, 0.991598368}, + {4.1375, 0.999713004, 0.991621077}, + {4.141667, 0.999723196, 0.991643786}, + {4.145833, 0.999733865, 0.991666436}, + {4.15, 0.999745011, 0.991689086}, + {4.154167, 0.999756455, 0.991711676}, + {4.158333, 0.999768317, 0.991734326}, + {4.1625, 0.999780476, 0.991756856}, + {4.166667, 0.999792933, 0.991779447}, + {4.170833, 0.999805629, 0.991801858}, + {4.175, 0.999818563, 0.991824329}, + {4.179167, 0.999831676, 0.991846681}, + {4.183333, 0.999844968, 0.991869032}, + {4.1875, 0.999858439, 0.991891265}, + {4.191667, 0.999871969, 0.991913497}, + {4.195833, 0.999885499, 0.991935551}, + {4.2, 0.999899149, 0.991957605}, + {4.204167, 0.999912739, 0.99197948}, + {4.208333, 0.999926329, 0.992001355}, + {4.2125, 0.999939859, 0.992023051}, + {4.216667, 0.99995327, 0.992044747}, + {4.220833, 0.999966562, 0.992066205}, + {4.225, 0.999979734, 0.992087603}, + {4.229167, 0.999992669, 0.992108822}, + {4.233333, 1.000005484, 0.992130041}, + {4.2375, 1.000018001, 0.992150962}, + {4.241667, 1.00003016, 0.992171884}, + {4.245833, 1.0000422, 0.992192566}, + {4.25, 1.000053763, 0.99221319}, + {4.254167, 1.000065088, 0.992233574}, + {4.258333, 1.000076056, 0.9922539}, + {4.2625, 1.000086665, 0.992273927}, + {4.266667, 1.000096798, 0.992293954}, + {4.270833, 1.000106454, 0.992313683}, + {4.275, 1.000115752, 0.992333353}, + {4.279167, 1.000124574, 0.992352784}, + {4.283333, 1.000133038, 0.992372096}, + {4.2875, 1.000140905, 0.992391169}, + {4.291667, 1.000148177, 0.992410183}, + {4.295833, 1.000155091, 0.992428839}, + {4.3, 1.000161409, 0.992447555}, + {4.304167, 1.000167251, 0.992465854}, + {4.308333, 1.000172496, 0.992484212}, + {4.3125, 1.000177264, 0.992502213}, + {4.316667, 1.000181437, 0.992520213}, + {4.320833, 1.000185013, 0.992537856}, + {4.325, 1.000188112, 0.992555499}, + {4.329167, 1.000190616, 0.992572844}, + {4.333333, 1.000192642, 0.992590189}, + {4.3375, 1.000193954, 0.992607176}, + {4.341667, 1.000194788, 0.992624164}, + {4.345833, 1.000195146, 0.992640913}, + {4.35, 1.000194907, 0.992657602}, + {4.354167, 1.000194073, 0.992673993}, + {4.358333, 1.000192881, 0.992690444}, + {4.3625, 1.000190973, 0.992706597}, + {4.366667, 1.000188708, 0.99272275}, + {4.370833, 1.000185847, 0.992738664}, + {4.375, 1.000182509, 0.992754579}, + {4.379167, 1.000178695, 0.992770255}, + {4.383333, 1.000174522, 0.992785931}, + {4.3875, 1.000169754, 0.992801368}, + {4.391667, 1.000164747, 0.992816865}, + {4.395833, 1.000159144, 0.992832184}, + {4.4, 1.000153303, 0.992847502}, + {4.404167, 1.000146985, 0.992862642}, + {4.408333, 1.000140309, 0.992877781}, + {4.4125, 1.000133276, 0.992892802}, + {4.416667, 1.000126004, 0.992907822}, + {4.420833, 1.000118494, 0.992922723}, + {4.425, 1.000110626, 0.992937624}, + {4.429167, 1.00010252, 0.992952466}, + {4.433333, 1.000094175, 0.992967308}, + {4.4375, 1.000085592, 0.99298209}, + {4.441667, 1.00007689, 0.992996871}, + {4.445833, 1.000067949, 0.993011653}, + {4.45, 1.000058889, 0.993026376}, + {4.454167, 1.00004971, 0.993041158}, + {4.458333, 1.000040531, 0.99305588}, + {4.4625, 1.000031233, 0.993070602}, + {4.466667, 1.000021815, 0.993085384}, + {4.470833, 1.000012517, 0.993100107}, + {4.475, 1.000003099, 0.993114889}, + {4.479167, 0.999993742, 0.99312973}, + {4.483333, 0.999984443, 0.993144512}, + {4.4875, 0.999975204, 0.993159413}, + {4.491667, 0.999966025, 0.993174255}, + {4.495833, 0.999956965, 0.993189216}, + {4.5, 0.999948025, 0.993204176}, + {4.504167, 0.999939263, 0.993219137}, + {4.508333, 0.99993062, 0.993234158}, + {4.5125, 0.999922216, 0.993249297}, + {4.516667, 0.999913991, 0.993264377}, + {4.520833, 0.999906003, 0.993279576}, + {4.525, 0.999898255, 0.993294775}, + {4.529167, 0.999890745, 0.993310034}, + {4.533333, 0.999883533, 0.993325353}, + {4.5375, 0.999876559, 0.993340731}, + {4.541667, 0.999869883, 0.993356109}, + {4.545833, 0.999863565, 0.993371606}, + {4.55, 0.999857545, 0.993387103}, + {4.554167, 0.999851882, 0.993402719}, + {4.558333, 0.999846518, 0.993418276}, + {4.5625, 0.999841511, 0.993434012}, + {4.566667, 0.999836922, 0.993449688}, + {4.570833, 0.99983263, 0.993465483}, + {4.575, 0.999828756, 0.993481219}, + {4.579167, 0.999825239, 0.993497133}, + {4.583333, 0.99982208, 0.993512988}, + {4.5875, 0.999819338, 0.993528962}, + {4.591667, 0.999817014, 0.993544877}, + {4.595833, 0.999815047, 0.99356091}, + {4.6, 0.999813497, 0.993576944}, + {4.604167, 0.999812305, 0.993593037}, + {4.608333, 0.99981153, 0.99360913}, + {4.6125, 0.999811113, 0.993625283}, + {4.616667, 0.999811053, 0.993641496}, + {4.620833, 0.999811411, 0.993657649}, + {4.625, 0.999812186, 0.993673861}, + {4.629167, 0.999813259, 0.993690133}, + {4.633333, 0.999814749, 0.993706405}, + {4.6375, 0.999816537, 0.993722677}, + {4.641667, 0.999818742, 0.993738949}, + {4.645833, 0.999821246, 0.993755221}, + {4.65, 0.999824047, 0.993771493}, + {4.654167, 0.999827206, 0.993787825}, + {4.658333, 0.999830663, 0.993804097}, + {4.6625, 0.999834418, 0.993820429}, + {4.666667, 0.999838471, 0.993836701}, + {4.670833, 0.999842763, 0.993852973}, + {4.675, 0.999847353, 0.993869245}, + {4.679167, 0.999852121, 0.993885517}, + {4.683333, 0.999857187, 0.99390173}, + {4.6875, 0.999862432, 0.993917942}, + {4.691667, 0.999867916, 0.993934095}, + {4.695833, 0.999873579, 0.993950248}, + {4.7, 0.99987936, 0.993966401}, + {4.704167, 0.99988538, 0.993982494}, + {4.708333, 0.99989146, 0.993998528}, + {4.7125, 0.999897718, 0.994014502}, + {4.716667, 0.999904037, 0.994030535}, + {4.720833, 0.999910533, 0.99404639}, + {4.725, 0.99991703, 0.994062304}, + {4.729167, 0.999923587, 0.9940781}, + {4.733333, 0.999930203, 0.994093835}, + {4.7375, 0.999936879, 0.994109511}, + {4.741667, 0.999943554, 0.994125187}, + {4.745833, 0.999950171, 0.994140744}, + {4.75, 0.999956846, 0.994156241}, + {4.754167, 0.999963462, 0.994171679}, + {4.758333, 0.999970019, 0.994187057}, + {4.7625, 0.999976516, 0.994202256}, + {4.766667, 0.999982893, 0.994217515}, + {4.770833, 0.999989212, 0.994232595}, + {4.775, 0.99999547, 0.994247675}, + {4.779167, 1.00000155, 0.994262576}, + {4.783333, 1.00000751, 0.994277477}, + {4.7875, 1.000013351, 0.994292259}, + {4.791667, 1.000018954, 0.994306982}, + {4.795833, 1.000024438, 0.994321525}, + {4.8, 1.000029802, 0.994336069}, + {4.804167, 1.000034928, 0.994350433}, + {4.808333, 1.000039816, 0.994364798}, + {4.8125, 1.000044584, 0.994378984}, + {4.816667, 1.000048995, 0.99439317}, + {4.820833, 1.000053287, 0.994407177}, + {4.825, 1.00005734, 0.994421124}, + {4.829167, 1.000061154, 0.994434953}, + {4.833333, 1.000064611, 0.994448721}, + {4.8375, 1.000067949, 0.994462311}, + {4.841667, 1.000071049, 0.994475901}, + {4.845833, 1.000073791, 0.994489312}, + {4.85, 1.000076294, 0.994502723}, + {4.854167, 1.000078559, 0.994515955}, + {4.858333, 1.000080466, 0.994529188}, + {4.8625, 1.000082254, 0.994542241}, + {4.866667, 1.000083685, 0.994555235}, + {4.870833, 1.000084758, 0.99456811}, + {4.875, 1.000085711, 0.994580984}, + {4.879167, 1.000086308, 0.99459368}, + {4.883333, 1.000086665, 0.994606376}, + {4.8875, 1.000086784, 0.994618893}, + {4.891667, 1.000086546, 0.99463141}, + {4.895833, 1.000086069, 0.994643748}, + {4.9, 1.000085354, 0.994656146}, + {4.904167, 1.0000844, 0.994668365}, + {4.908333, 1.000083208, 0.994680583}, + {4.9125, 1.000081778, 0.994692683}, + {4.916667, 1.000080109, 0.994704783}, + {4.920833, 1.000078201, 0.994716704}, + {4.925, 1.000076056, 0.994728684}, + {4.929167, 1.000073791, 0.994740546}, + {4.933333, 1.000071168, 0.994752407}, + {4.9375, 1.000068426, 0.994764149}, + {4.941667, 1.000065565, 0.994775891}, + {4.945833, 1.000062346, 0.994787514}, + {4.95, 1.000059128, 0.994799197}, + {4.954167, 1.000055671, 0.99481076}, + {4.958333, 1.000052094, 0.994822323}, + {4.9625, 1.000048399, 0.994833887}, + {4.966667, 1.000044465, 0.99484539}, + {4.970833, 1.000040531, 0.994856834}, + {4.975, 1.000036478, 0.994868279}, + {4.979167, 1.000032187, 0.994879723}, + {4.983333, 1.000028014, 0.994891107}, + {4.9875, 1.000023603, 0.994902492}, + {4.991667, 1.000019193, 0.994913876}, + {4.995833, 1.000014782, 0.994925261}, + {5, 1.000010252, 0.994936585}, + {5.004167, 1.000005722, 0.99494797}, + {5.008333, 1.000001192, 0.994959295}, + {5.0125, 0.999996662, 0.99497062}, + {5.016667, 0.999992073, 0.994981945}, + {5.020833, 0.999987543, 0.994993329}, + {5.025, 0.999983072, 0.995004654}, + {5.029167, 0.999978602, 0.995015979}, + {5.033333, 0.999974132, 0.995027363}, + {5.0375, 0.99996978, 0.995038688}, + {5.041667, 0.999965489, 0.995050073}, + {5.045833, 0.999961257, 0.995061457}, + {5.05, 0.999957144, 0.995072842}, + {5.054167, 0.999953091, 0.995084286}, + {5.058333, 0.999949157, 0.99509567}, + {5.0625, 0.999945343, 0.995107114}, + {5.066667, 0.999941587, 0.995118558}, + {5.070833, 0.999938011, 0.995130002}, + {5.075, 0.999934614, 0.995141506}, + {5.079167, 0.999931276, 0.99515301}, + {5.083333, 0.999928117, 0.995164514}, + {5.0875, 0.999925137, 0.995176017}, + {5.091667, 0.999922276, 0.995187581}, + {5.095833, 0.999919593, 0.995199144}, + {5.1, 0.99991709, 0.995210707}, + {5.104167, 0.999914765, 0.99522233}, + {5.108333, 0.99991262, 0.995233953}, + {5.1125, 0.999910653, 0.995245576}, + {5.116667, 0.999908865, 0.995257199}, + {5.120833, 0.999907255, 0.995268881}, + {5.125, 0.999905825, 0.995280504}, + {5.129167, 0.999904573, 0.995292187}, + {5.133333, 0.99990356, 0.995303869}, + {5.1375, 0.999902725, 0.995315611}, + {5.141667, 0.99990201, 0.995327294}, + {5.145833, 0.999901593, 0.995339036}, + {5.15, 0.999901295, 0.995350778}, + {5.154167, 0.999901176, 0.99536252}, + {5.158333, 0.999901295, 0.995374262}, + {5.1625, 0.999901593, 0.995386004}, + {5.166667, 0.99990201, 0.995397747}, + {5.170833, 0.999902666, 0.995409489}, + {5.175, 0.9999035, 0.995421231}, + {5.179167, 0.999904454, 0.995432973}, + {5.183333, 0.999905646, 0.995444715}, + {5.1875, 0.999906957, 0.995456457}, + {5.191667, 0.999908388, 0.995468199}, + {5.195833, 0.999910057, 0.995479882}, + {5.2, 0.999911845, 0.995491624}, + {5.204167, 0.999913752, 0.995503306}, + {5.208333, 0.999915779, 0.995514989}, + {5.2125, 0.999917984, 0.995526671}, + {5.216667, 0.999920249, 0.995538294}, + {5.220833, 0.999922693, 0.995549917}, + {5.225, 0.999925196, 0.99556154}, + {5.229167, 0.999927878, 0.995573103}, + {5.233333, 0.999930561, 0.995584726}, + {5.2375, 0.999933362, 0.99559623}, + {5.241667, 0.999936283, 0.995607734}, + {5.245833, 0.999939263, 0.995619237}, + {5.25, 0.999942303, 0.995630682}, + {5.254167, 0.999945343, 0.995642126}, + {5.258333, 0.999948502, 0.99565351}, + {5.2625, 0.999951661, 0.995664835}, + {5.266667, 0.999954879, 0.99567616}, + {5.270833, 0.999958098, 0.995687425}, + {5.275, 0.999961376, 0.99569869}, + {5.279167, 0.999964654, 0.995709896}, + {5.283333, 0.999967933, 0.995721042}, + {5.2875, 0.999971151, 0.995732129}, + {5.291667, 0.99997443, 0.995743215}, + {5.295833, 0.999977648, 0.995754182}, + {5.3, 0.999980807, 0.995765209}, + {5.304167, 0.999983966, 0.995776117}, + {5.308333, 0.999987125, 0.995787024}, + {5.3125, 0.999990165, 0.995797813}, + {5.316667, 0.999993205, 0.995808601}, + {5.320833, 0.999996126, 0.995819271}, + {5.325, 0.999999046, 0.995829999}, + {5.329167, 1.000001788, 0.995840549}, + {5.333333, 1.00000453, 0.995851159}, + {5.3375, 1.000007153, 0.99586159}, + {5.341667, 1.000009775, 0.99587208}, + {5.345833, 1.000012159, 0.995882452}, + {5.35, 1.000014544, 0.995892823}, + {5.354167, 1.000016809, 0.995903075}, + {5.358333, 1.000018954, 0.995913327}, + {5.3625, 1.000020981, 0.99592346}, + {5.366667, 1.000022888, 0.995933592}, + {5.370833, 1.000024676, 0.995943606}, + {5.375, 1.000026345, 0.995953619}, + {5.379167, 1.000027895, 0.995963573}, + {5.383333, 1.000029325, 0.995973468}, + {5.3875, 1.000030637, 0.995983303}, + {5.391667, 1.000031829, 0.995993078}, + {5.395833, 1.000032783, 0.996002793}, + {5.4, 1.000033736, 0.996012509}, + {5.404167, 1.000034451, 0.996022105}, + {5.408333, 1.000035167, 0.996031642}, + {5.4125, 1.000035644, 0.996041179}, + {5.416667, 1.000036001, 0.996050656}, + {5.420833, 1.00003624, 0.996060073}, + {5.425, 1.000036359, 0.996069431}, + {5.429167, 1.00003624, 0.99607873}, + {5.433333, 1.00003612, 0.996088028}, + {5.4375, 1.000035882, 0.996097267}, + {5.441667, 1.000035405, 0.996106446}, + {5.445833, 1.000034928, 0.996115625}, + {5.45, 1.000034213, 0.996124744}, + {5.454167, 1.000033498, 0.996133745}, + {5.458333, 1.000032663, 0.996142805}, + {5.4625, 1.00003159, 0.996151805}, + {5.466667, 1.000030518, 0.996160746}, + {5.470833, 1.000029325, 0.996169686}, + {5.475, 1.000028014, 0.996178567}, + {5.479167, 1.000026703, 0.996187449}, + {5.483333, 1.000025153, 0.99619627}, + {5.4875, 1.000023603, 0.996205091}, + {5.491667, 1.000022054, 0.996213853}, + {5.495833, 1.000020266, 0.996222615}, + {5.5, 1.000018477, 0.996231318}, + {5.504167, 1.000016689, 0.99624002}, + {5.508333, 1.000014782, 0.996248722}, + {5.5125, 1.000012755, 0.996257365}, + {5.516667, 1.000010729, 0.996266007}, + {5.520833, 1.000008702, 0.99627465}, + {5.525, 1.000006676, 0.996283293}, + {5.529167, 1.00000453, 0.996291876}, + {5.533333, 1.000002384, 0.996300459}, + {5.5375, 1.000000238, 0.996309042}, + {5.541667, 0.999998033, 0.996317625}, + {5.545833, 0.999995828, 0.996326149}, + {5.55, 0.999993622, 0.996334672}, + {5.554167, 0.999991417, 0.996343195}, + {5.558333, 0.999989212, 0.996351779}, + {5.5625, 0.999987006, 0.996360302}, + {5.566667, 0.99998486, 0.996368825}, + {5.570833, 0.999982715, 0.996377289}, + {5.575, 0.999980569, 0.996385813}, + {5.579167, 0.999978483, 0.996394336}, + {5.583333, 0.999976397, 0.99640286}, + {5.5875, 0.99997443, 0.996411324}, + {5.591667, 0.999972463, 0.996419847}, + {5.595833, 0.999970496, 0.99642837}, + {5.6, 0.999968648, 0.996436894}, + {5.604167, 0.99996686, 0.996445358}, + {5.608333, 0.999965072, 0.996453881}, + {5.6125, 0.999963403, 0.996462405}, + {5.616667, 0.999961793, 0.996470869}, + {5.620833, 0.999960244, 0.996479392}, + {5.625, 0.999958754, 0.996487916}, + {5.629167, 0.999957383, 0.996496439}, + {5.633333, 0.999956071, 0.996504962}, + {5.6375, 0.99995482, 0.996513486}, + {5.641667, 0.999953687, 0.996522009}, + {5.645833, 0.999952614, 0.996530533}, + {5.65, 0.999951661, 0.996539056}, + {5.654167, 0.999950767, 0.99654758}, + {5.658333, 0.999949932, 0.996556044}, + {5.6625, 0.999949276, 0.996564627}, + {5.666667, 0.999948621, 0.99657315}, + {5.670833, 0.999948144, 0.996581614}, + {5.675, 0.999947667, 0.996590137}, + {5.679167, 0.999947369, 0.996598661}, + {5.683333, 0.999947131, 0.996607184}, + {5.6875, 0.999946952, 0.996615708}, + {5.691667, 0.999946892, 0.996624231}, + {5.695833, 0.999946952, 0.996632755}, + {5.7, 0.999947071, 0.996641219}, + {5.704167, 0.999947309, 0.996649742}, + {5.708333, 0.999947608, 0.996658266}, + {5.7125, 0.999947965, 0.996666729}, + {5.716667, 0.999948442, 0.996675193}, + {5.720833, 0.999948978, 0.996683657}, + {5.725, 0.999949634, 0.996692121}, + {5.729167, 0.999950349, 0.996700585}, + {5.733333, 0.999951124, 0.996709049}, + {5.7375, 0.999952018, 0.996717453}, + {5.741667, 0.999952912, 0.996725857}, + {5.745833, 0.999953926, 0.996734262}, + {5.75, 0.999954998, 0.996742666}, + {5.754167, 0.999956131, 0.99675101}, + {5.758333, 0.999957263, 0.996759415}, + {5.7625, 0.999958515, 0.9967677}, + {5.766667, 0.999959826, 0.996776044}, + {5.770833, 0.999961138, 0.996784329}, + {5.775, 0.999962509, 0.996792674}, + {5.779167, 0.999963939, 0.9968009}, + {5.783333, 0.99996537, 0.996809185}, + {5.7875, 0.99996686, 0.99681735}, + {5.791667, 0.99996835, 0.996825576}, + {5.795833, 0.9999699, 0.996833742}, + {5.8, 0.999971449, 0.996841908}, + {5.804167, 0.999972999, 0.996850014}, + {5.808333, 0.999974608, 0.99685812}, + {5.8125, 0.999976218, 0.996866167}, + {5.816667, 0.999977827, 0.996874273}, + {5.820833, 0.999979436, 0.99688226}, + {5.825, 0.999980986, 0.996890247}, + {5.829167, 0.999982595, 0.996898234}, + {5.833333, 0.999984205, 0.996906161}, + {5.8375, 0.999985754, 0.996914029}, + {5.841667, 0.999987304, 0.996921897}, + {5.845833, 0.999988854, 0.996929765}, + {5.85, 0.999990344, 0.996937573}, + {5.854167, 0.999991834, 0.996945322}, + {5.858333, 0.999993324, 0.99695307}, + {5.8625, 0.999994755, 0.996960759}, + {5.866667, 0.999996126, 0.996968508}, + {5.870833, 0.999997497, 0.996976137}, + {5.875, 0.999998748, 0.996983767}, + {5.879167, 1, 0.996991277}, + {5.883333, 1.000001311, 0.996998847}, + {5.8875, 1.000002384, 0.997006357}, + {5.891667, 1.000003576, 0.997013867}, + {5.895833, 1.000004649, 0.997021258}, + {5.9, 1.000005603, 0.997028708}, + {5.904167, 1.000006557, 0.99703604}, + {5.908333, 1.00000751, 0.997043431}, + {5.9125, 1.000008345, 0.997050703}, + {5.916667, 1.00000906, 0.997057974}, + {5.920833, 1.000009775, 0.997065246}, + {5.925, 1.00001049, 0.997072458}, + {5.929167, 1.000011086, 0.997079611}, + {5.933333, 1.000011563, 0.997086763}, + {5.9375, 1.00001204, 0.997093856}, + {5.941667, 1.000012398, 0.997100949}, + {5.945833, 1.000012755, 0.997107983}, + {5.95, 1.000012994, 0.997115016}, + {5.954167, 1.000013232, 0.99712199}, + {5.958333, 1.000013351, 0.997128963}, + {5.9625, 1.000013351, 0.997135878}, + {5.966667, 1.000013471, 0.997142792}, + {5.970833, 1.000013351, 0.997149646}, + {5.975, 1.000013232, 0.997156501}, + {5.979167, 1.000013113, 0.997163296}, + {5.983333, 1.000012875, 0.99717015}, + {5.9875, 1.000012517, 0.997176886}, + {5.991667, 1.000012159, 0.997183621}, + {5.995833, 1.000011802, 0.997190356}, + {6, 1.000011325, 0.997197032}, + {6.004167, 1.000010729, 0.997203708}, + {6.008333, 1.000010252, 0.997210383}, + {6.0125, 1.000009656, 0.997217}, + {6.016667, 1.000008941, 0.997223616}, + {6.020833, 1.000008225, 0.997230172}, + {6.025, 1.00000751, 0.997236729}, + {6.029167, 1.000006676, 0.997243285}, + {6.033333, 1.00000596, 0.997249842}, + {6.0375, 1.000005007, 0.997256339}, + {6.041667, 1.000004172, 0.997262836}, + {6.045833, 1.000003219, 0.997269332}, + {6.05, 1.000002265, 0.99727577}, + {6.054167, 1.000001311, 0.997282207}, + {6.058333, 1.000000358, 0.997288644}, + {6.0625, 0.999999344, 0.997295082}, + {6.066667, 0.999998331, 0.997301519}, + {6.070833, 0.999997258, 0.997307897}, + {6.075, 0.999996245, 0.997314274}, + {6.079167, 0.999995172, 0.997320652}, + {6.083333, 0.999994099, 0.99732703}, + {6.0875, 0.999993026, 0.997333407}, + {6.091667, 0.999992013, 0.997339785}, + {6.095833, 0.99999094, 0.997346103}, + {6.1, 0.999989867, 0.997352421}, + {6.104167, 0.999988794, 0.997358739}, + {6.108333, 0.999987781, 0.997365057}, + {6.1125, 0.999986768, 0.997371376}, + {6.116667, 0.999985754, 0.997377694}, + {6.120833, 0.999984741, 0.997384012}, + {6.125, 0.999983788, 0.99739027}, + {6.129167, 0.999982834, 0.997396588}, + {6.133333, 0.99998188, 0.997402847}, + {6.1375, 0.999980986, 0.997409165}, + {6.141667, 0.999980092, 0.997415423}, + {6.145833, 0.999979258, 0.997421682}, + {6.15, 0.999978423, 0.99742794}, + {6.154167, 0.999977648, 0.997434199}, + {6.158333, 0.999976933, 0.997440457}, + {6.1625, 0.999976218, 0.997446716}, + {6.166667, 0.999975562, 0.997452974}, + {6.170833, 0.999974906, 0.997459233}, + {6.175, 0.99997431, 0.997465432}, + {6.179167, 0.999973774, 0.99747169}, + {6.183333, 0.999973238, 0.997477889}, + {6.1875, 0.999972761, 0.997484148}, + {6.191667, 0.999972343, 0.997490346}, + {6.195833, 0.999971986, 0.997496605}, + {6.2, 0.999971628, 0.997502804}, + {6.204167, 0.99997133, 0.997509003}, + {6.208333, 0.999971092, 0.997515202}, + {6.2125, 0.999970913, 0.9975214}, + {6.216667, 0.999970734, 0.997527599}, + {6.220833, 0.999970615, 0.997533798}, + {6.225, 0.999970555, 0.997539937}, + {6.229167, 0.999970555, 0.997546136}, + {6.233333, 0.999970555, 0.997552276}, + {6.2375, 0.999970615, 0.997558475}, + {6.241667, 0.999970734, 0.997564614}, + {6.245833, 0.999970853, 0.997570753}, + {6.25, 0.999971092, 0.997576892}, + {6.254167, 0.99997133, 0.997583032}, + {6.258333, 0.999971569, 0.997589111}, + {6.2625, 0.999971926, 0.997595251}, + {6.266667, 0.999972284, 0.99760133}, + {6.270833, 0.999972641, 0.99760741}, + {6.275, 0.999973059, 0.99761349}, + {6.279167, 0.999973536, 0.997619569}, + {6.283333, 0.999974012, 0.997625649}, + {6.2875, 0.999974549, 0.997631669}, + {6.291667, 0.999975085, 0.997637689}, + {6.295833, 0.999975681, 0.997643709}, + {6.3, 0.999976277, 0.997649729}, + {6.304167, 0.999976933, 0.997655749}, + {6.308333, 0.999977589, 0.99766171}, + {6.3125, 0.999978244, 0.99766767}, + {6.316667, 0.99997896, 0.997673631}, + {6.320833, 0.999979675, 0.997679532}, + {6.325, 0.99998039, 0.997685492}, + {6.329167, 0.999981165, 0.997691393}, + {6.333333, 0.99998188, 0.997697234}, + {6.3375, 0.999982655, 0.997703135}, + {6.341667, 0.99998343, 0.997708976}, + {6.345833, 0.999984205, 0.997714818}, + {6.35, 0.999985039, 0.997720659}, + {6.354167, 0.999985814, 0.99772644}, + {6.358333, 0.999986589, 0.997732222}, + {6.3625, 0.999987364, 0.997737944}, + {6.366667, 0.999988139, 0.997743726}, + {6.370833, 0.999988973, 0.997749448}, + {6.375, 0.999989748, 0.99775517}, + {6.379167, 0.999990463, 0.997760832}, + {6.383333, 0.999991238, 0.997766495}, + {6.3875, 0.999992013, 0.997772098}, + {6.391667, 0.999992728, 0.99777776}, + {6.395833, 0.999993443, 0.997783363}, + {6.4, 0.999994159, 0.997788966}, + {6.404167, 0.999994814, 0.997794509}, + {6.408333, 0.99999547, 0.997800052}, + {6.4125, 0.999996126, 0.997805536}, + {6.416667, 0.999996781, 0.997811079}, + {6.420833, 0.999997377, 0.997816503}, + {6.425, 0.999997973, 0.997821987}, + {6.429167, 0.99999851, 0.997827411}, + {6.433333, 0.999999046, 0.997832835}, + {6.4375, 0.999999523, 0.997838199}, + {6.441667, 1, 0.997843623}, + {6.445833, 1.000000477, 0.997848928}, + {6.45, 1.000000834, 0.997854292}, + {6.454167, 1.000001192, 0.997859597}, + {6.458333, 1.00000155, 0.997864902}, + {6.4625, 1.000001907, 0.997870147}, + {6.466667, 1.000002265, 0.997875392}, + {6.470833, 1.000002503, 0.997880638}, + {6.475, 1.000002742, 0.997885823}, + {6.479167, 1.000002861, 0.997891009}, + {6.483333, 1.000003099, 0.997896194}, + {6.4875, 1.000003219, 0.99790132}, + {6.491667, 1.000003338, 0.997906446}, + {6.495833, 1.000003457, 0.997911572}, + {6.5, 1.000003457, 0.997916639}, + {6.504167, 1.000003457, 0.997921705}, + {6.508333, 1.000003457, 0.997926772}, + {6.5125, 1.000003338, 0.997931838}, + {6.516667, 1.000003338, 0.997936845}, + {6.520833, 1.000003219, 0.997941852}, + {6.525, 1.000003099, 0.997946858}, + {6.529167, 1.000002861, 0.997951806}, + {6.533333, 1.000002742, 0.997956753}, + {6.5375, 1.000002503, 0.9979617}, + {6.541667, 1.000002265, 0.997966647}, + {6.545833, 1.000002027, 0.997971535}, + {6.55, 1.000001669, 0.997976422}, + {6.554167, 1.000001311, 0.99798131}, + {6.558333, 1.000001073, 0.997986197}, + {6.5625, 1.000000715, 0.997991025}, + {6.566667, 1.000000238, 0.997995913}, + {6.570833, 0.999999881, 0.998000741}, + {6.575, 0.999999523, 0.998005509}, + {6.579167, 0.999999046, 0.998010337}, + {6.583333, 0.999998629, 0.998015106}, + {6.5875, 0.999998152, 0.998019934}, + {6.591667, 0.999997735, 0.998024702}, + {6.595833, 0.999997258, 0.998029411}, + {6.6, 0.999996781, 0.998034179}, + {6.604167, 0.999996245, 0.998038948}, + {6.608333, 0.999995768, 0.998043656}, + {6.6125, 0.999995232, 0.998048365}, + {6.616667, 0.999994755, 0.998053074}, + {6.620833, 0.999994218, 0.998057783}, + {6.625, 0.999993742, 0.998062491}, + {6.629167, 0.999993205, 0.998067141}, + {6.633333, 0.999992728, 0.998071849}, + {6.6375, 0.999992192, 0.998076499}, + {6.641667, 0.999991715, 0.998081207}, + {6.645833, 0.999991179, 0.998085856}, + {6.65, 0.999990702, 0.998090506}, + {6.654167, 0.999990225, 0.998095095}, + {6.658333, 0.999989748, 0.998099744}, + {6.6625, 0.999989271, 0.998104393}, + {6.666667, 0.999988794, 0.998108983}, + {6.670833, 0.999988377, 0.998113632}, + {6.675, 0.99998796, 0.998118222}, + {6.679167, 0.999987543, 0.998122811}, + {6.683333, 0.999987125, 0.998127401}, + {6.6875, 0.999986708, 0.99813199}, + {6.691667, 0.999986351, 0.99813658}, + {6.695833, 0.999985993, 0.99814117}, + {6.7, 0.999985635, 0.998145759}, + {6.704167, 0.999985337, 0.998150289}, + {6.708333, 0.999985039, 0.998154879}, + {6.7125, 0.999984741, 0.998159409}, + {6.716667, 0.999984503, 0.998163998}, + {6.720833, 0.999984264, 0.998168528}, + {6.725, 0.999984026, 0.998173058}, + {6.729167, 0.999983847, 0.998177588}, + {6.733333, 0.999983668, 0.998182118}, + {6.7375, 0.99998349, 0.998186648}, + {6.741667, 0.99998337, 0.998191178}, + {6.745833, 0.999983251, 0.998195648}, + {6.75, 0.999983132, 0.998200178}, + {6.754167, 0.999983072, 0.998204648}, + {6.758333, 0.999983072, 0.998209178}, + {6.7625, 0.999983013, 0.998213649}, + {6.766667, 0.999983013, 0.998218119}, + {6.770833, 0.999983013, 0.998222589}, + {6.775, 0.999983072, 0.99822706}, + {6.779167, 0.999983132, 0.99823153}, + {6.783333, 0.999983251, 0.998235941}, + {6.7875, 0.999983311, 0.998240411}, + {6.791667, 0.99998343, 0.998244822}, + {6.795833, 0.999983609, 0.998249233}, + {6.8, 0.999983728, 0.998253644}, + {6.804167, 0.999983907, 0.998258054}, + {6.808333, 0.999984145, 0.998262465}, + {6.8125, 0.999984324, 0.998266876}, + {6.816667, 0.999984562, 0.998271227}, + {6.820833, 0.999984801, 0.998275638}, + {6.825, 0.999985099, 0.998279989}, + {6.829167, 0.999985337, 0.99828434}, + {6.833333, 0.999985635, 0.998288691}, + {6.8375, 0.999985933, 0.998292983}, + {6.841667, 0.999986291, 0.998297334}, + {6.845833, 0.999986589, 0.998301625}, + {6.85, 0.999986947, 0.998305976}, + {6.854167, 0.999987304, 0.998310208}, + {6.858333, 0.999987662, 0.9983145}, + {6.8625, 0.999988019, 0.998318791}, + {6.866667, 0.999988377, 0.998323023}, + {6.870833, 0.999988735, 0.998327315}, + {6.875, 0.999989152, 0.998331547}, + {6.879167, 0.99998951, 0.998335719}, + {6.883333, 0.999989927, 0.998339951}, + {6.8875, 0.999990284, 0.998344183}, + {6.891667, 0.999990702, 0.998348355}, + {6.895833, 0.999991059, 0.998352528}, + {6.9, 0.999991477, 0.9983567}, + {6.904167, 0.999991834, 0.998360813}, + {6.908333, 0.999992251, 0.998364985}, + {6.9125, 0.999992609, 0.998369098}, + {6.916667, 0.999993026, 0.99837321}, + {6.920833, 0.999993384, 0.998377264}, + {6.925, 0.999993742, 0.998381376}, + {6.929167, 0.999994099, 0.998385429}, + {6.933333, 0.999994457, 0.998389482}, + {6.9375, 0.999994814, 0.998393536}, + {6.941667, 0.999995172, 0.998397589}, + {6.945833, 0.99999547, 0.998401582}, + {6.95, 0.999995768, 0.998405576}, + {6.954167, 0.999996126, 0.998409569}, + {6.958333, 0.999996424, 0.998413563}, + {6.9625, 0.999996662, 0.998417497}, + {6.966667, 0.99999696, 0.99842149}, + {6.970833, 0.999997199, 0.998425424}, + {6.975, 0.999997497, 0.998429298}, + {6.979167, 0.999997735, 0.998433232}, + {6.983333, 0.999997914, 0.998437107}, + {6.9875, 0.999998152, 0.998440981}, + {6.991667, 0.999998331, 0.998444855}, + {6.995833, 0.99999851, 0.99844873}, + {7, 0.999998689, 0.998452544}, + {7.004167, 0.999998808, 0.998456359}, + {7.008333, 0.999998927, 0.998460233}, + {7.0125, 0.999999046, 0.998463988}, + {7.016667, 0.999999166, 0.998467803}, + {7.020833, 0.999999225, 0.998471558}, + {7.025, 0.999999344, 0.998475313}, + {7.029167, 0.999999404, 0.998479068}, + {7.033333, 0.999999404, 0.998482823}, + {7.0375, 0.999999464, 0.998486519}, + {7.041667, 0.999999464, 0.998490274}, + {7.045833, 0.999999464, 0.998493969}, + {7.05, 0.999999404, 0.998497665}, + {7.054167, 0.999999404, 0.99850136}, + {7.058333, 0.999999344, 0.998504996}, + {7.0625, 0.999999285, 0.998508692}, + {7.066667, 0.999999225, 0.998512328}, + {7.070833, 0.999999106, 0.998515964}, + {7.075, 0.999998987, 0.998519599}, + {7.079167, 0.999998868, 0.998523176}, + {7.083333, 0.999998748, 0.998526812}, + {7.0875, 0.999998629, 0.998530388}, + {7.091667, 0.99999845, 0.998533964}, + {7.095833, 0.999998331, 0.99853754}, + {7.1, 0.999998152, 0.998541117}, + {7.104167, 0.999997973, 0.998544693}, + {7.108333, 0.999997795, 0.99854821}, + {7.1125, 0.999997616, 0.998551726}, + {7.116667, 0.999997377, 0.998555303}, + {7.120833, 0.999997199, 0.998558819}, + {7.125, 0.99999696, 0.998562336}, + {7.129167, 0.999996722, 0.998565793}, + {7.133333, 0.999996483, 0.99856931}, + {7.1375, 0.999996305, 0.998572826}, + {7.141667, 0.999996066, 0.998576283}, + {7.145833, 0.999995828, 0.998579741}, + {7.15, 0.999995589, 0.998583198}, + {7.154167, 0.999995351, 0.998586655}, + {7.158333, 0.999995053, 0.998590112}, + {7.1625, 0.999994814, 0.998593569}, + {7.166667, 0.999994576, 0.998597026}, + {7.170833, 0.999994338, 0.998600423}, + {7.175, 0.999994099, 0.99860388}, + {7.179167, 0.999993861, 0.998607278}, + {7.183333, 0.999993622, 0.998610675}, + {7.1875, 0.999993384, 0.998614073}, + {7.191667, 0.999993145, 0.99861753}, + {7.195833, 0.999992907, 0.998620868}, + {7.2, 0.999992728, 0.998624265}, + {7.204167, 0.99999249, 0.998627663}, + {7.208333, 0.999992311, 0.99863106}, + {7.2125, 0.999992073, 0.998634398}, + {7.216667, 0.999991894, 0.998637795}, + {7.220833, 0.999991715, 0.998641133}, + {7.225, 0.999991536, 0.998644471}, + {7.229167, 0.999991357, 0.998647809}, + {7.233333, 0.999991179, 0.998651147}, + {7.2375, 0.999991, 0.998654485}, + {7.241667, 0.99999088, 0.998657823}, + {7.245833, 0.999990702, 0.99866116}, + {7.25, 0.999990582, 0.998664498}, + {7.254167, 0.999990463, 0.998667777}, + {7.258333, 0.999990344, 0.998671114}, + {7.2625, 0.999990225, 0.998674393}, + {7.266667, 0.999990165, 0.998677671}, + {7.270833, 0.999990106, 0.998681009}, + {7.275, 0.999989986, 0.998684287}, + {7.279167, 0.999989927, 0.998687565}, + {7.283333, 0.999989927, 0.998690844}, + {7.2875, 0.999989867, 0.998694062}, + {7.291667, 0.999989867, 0.99869734}, + {7.295833, 0.999989808, 0.998700619}, + {7.3, 0.999989808, 0.998703837}, + {7.304167, 0.999989808, 0.998707116}, + {7.308333, 0.999989867, 0.998710334}, + {7.3125, 0.999989867, 0.998713553}, + {7.316667, 0.999989927, 0.998716831}, + {7.320833, 0.999989927, 0.99872005}, + {7.325, 0.999989986, 0.998723269}, + {7.329167, 0.999990046, 0.998726428}, + {7.333333, 0.999990165, 0.998729646}, + {7.3375, 0.999990225, 0.998732865}, + {7.341667, 0.999990344, 0.998736024}, + {7.345833, 0.999990404, 0.998739183}, + {7.35, 0.999990523, 0.998742402}, + {7.354167, 0.999990642, 0.998745561}, + {7.358333, 0.999990761, 0.99874872}, + {7.3625, 0.99999094, 0.998751879}, + {7.366667, 0.999991059, 0.998755038}, + {7.370833, 0.999991238, 0.998758137}, + {7.375, 0.999991357, 0.998761296}, + {7.379167, 0.999991536, 0.998764396}, + {7.383333, 0.999991715, 0.998767495}, + {7.3875, 0.999991834, 0.998770654}, + {7.391667, 0.999992013, 0.998773754}, + {7.395833, 0.999992192, 0.998776793}, + {7.4, 0.999992371, 0.998779893}, + {7.404167, 0.999992549, 0.998782992}, + {7.408333, 0.999992788, 0.998786032}, + {7.4125, 0.999992967, 0.998789132}, + {7.416667, 0.999993145, 0.998792171}, + {7.420833, 0.999993324, 0.998795211}, + {7.425, 0.999993563, 0.998798251}, + {7.429167, 0.999993742, 0.998801291}, + {7.433333, 0.99999392, 0.998804271}, + {7.4375, 0.999994099, 0.998807311}, + {7.441667, 0.999994338, 0.998810291}, + {7.445833, 0.999994516, 0.998813272}, + {7.45, 0.999994695, 0.998816252}, + {7.454167, 0.999994874, 0.998819232}, + {7.458333, 0.999995053, 0.998822212}, + {7.4625, 0.999995232, 0.998825133}, + {7.466667, 0.99999541, 0.998828113}, + {7.470833, 0.999995589, 0.998831034}, + {7.475, 0.999995768, 0.998833954}, + {7.479167, 0.999995947, 0.998836875}, + {7.483333, 0.999996126, 0.998839796}, + {7.4875, 0.999996305, 0.998842716}, + {7.491667, 0.999996424, 0.998845577}, + {7.495833, 0.999996603, 0.998848498}, + {7.5, 0.999996722, 0.998851359}, + {7.504167, 0.999996841, 0.99885422}, + {7.508333, 0.99999696, 0.998857081}, + {7.5125, 0.999997139, 0.998859942}, + {7.516667, 0.999997258, 0.998862803}, + {7.520833, 0.999997318, 0.998865604}, + {7.525, 0.999997437, 0.998868406}, + {7.529167, 0.999997556, 0.998871207}, + {7.533333, 0.999997616, 0.998874068}, + {7.5375, 0.999997735, 0.99887681}, + {7.541667, 0.999997795, 0.998879611}, + {7.545833, 0.999997854, 0.998882413}, + {7.55, 0.999997914, 0.998885155}, + {7.554167, 0.999997973, 0.998887956}, + {7.558333, 0.999998033, 0.998890698}, + {7.5625, 0.999998033, 0.99889344}, + {7.566667, 0.999998093, 0.998896182}, + {7.570833, 0.999998093, 0.998898864}, + {7.575, 0.999998093, 0.998901606}, + {7.579167, 0.999998093, 0.998904347}, + {7.583333, 0.999998093, 0.99890703}, + {7.5875, 0.999998093, 0.998909712}, + {7.591667, 0.999998093, 0.998912394}, + {7.595833, 0.999998093, 0.998915076}, + {7.6, 0.999998033, 0.998917758}, + {7.604167, 0.999998033, 0.998920441}, + {7.608333, 0.999997973, 0.998923063}, + {7.6125, 0.999997914, 0.998925745}, + {7.616667, 0.999997854, 0.998928368}, + {7.620833, 0.999997795, 0.998930991}, + {7.625, 0.999997735, 0.998933613}, + {7.629167, 0.999997675, 0.998936236}, + {7.633333, 0.999997616, 0.998938859}, + {7.6375, 0.999997497, 0.998941481}, + {7.641667, 0.999997437, 0.998944104}, + {7.645833, 0.999997318, 0.998946667}, + {7.65, 0.999997258, 0.998949289}, + {7.654167, 0.999997139, 0.998951852}, + {7.658333, 0.999997079, 0.998954415}, + {7.6625, 0.99999696, 0.998956978}, + {7.666667, 0.999996841, 0.998959541}, + {7.670833, 0.999996722, 0.998962104}, + {7.675, 0.999996662, 0.998964667}, + {7.679167, 0.999996543, 0.99896723}, + {7.683333, 0.999996424, 0.998969734}, + {7.6875, 0.999996305, 0.998972297}, + {7.691667, 0.999996185, 0.9989748}, + {7.695833, 0.999996066, 0.998977304}, + {7.7, 0.999995947, 0.998979867}, + {7.704167, 0.999995828, 0.99898237}, + {7.708333, 0.999995708, 0.998984873}, + {7.7125, 0.999995589, 0.998987377}, + {7.716667, 0.99999547, 0.99898988}, + {7.720833, 0.99999541, 0.998992324}, + {7.725, 0.999995291, 0.998994827}, + {7.729167, 0.999995172, 0.998997331}, + {7.733333, 0.999995053, 0.998999774}, + {7.7375, 0.999994934, 0.999002278}, + {7.741667, 0.999994874, 0.999004722}, + {7.745833, 0.999994755, 0.999007165}, + {7.75, 0.999994636, 0.999009669}, + {7.754167, 0.999994576, 0.999012113}, + {7.758333, 0.999994457, 0.999014556}, + {7.7625, 0.999994397, 0.999017}, + {7.766667, 0.999994338, 0.999019444}, + {7.770833, 0.999994218, 0.999021828}, + {7.775, 0.999994159, 0.999024272}, + {7.779167, 0.999994099, 0.999026716}, + {7.783333, 0.99999404, 0.9990291}, + {7.7875, 0.99999398, 0.999031544}, + {7.791667, 0.99999392, 0.999033928}, + {7.795833, 0.999993861, 0.999036372}, + {7.8, 0.999993801, 0.999038756}, + {7.804167, 0.999993801, 0.99904114}, + {7.808333, 0.999993742, 0.999043524}, + {7.8125, 0.999993742, 0.999045908}, + {7.816667, 0.999993682, 0.999048293}, + {7.820833, 0.999993682, 0.999050677}, + {7.825, 0.999993682, 0.999053061}, + {7.829167, 0.999993682, 0.999055445}, + {7.833333, 0.999993682, 0.99905777}, + {7.8375, 0.999993682, 0.999060154}, + {7.841667, 0.999993682, 0.999062479}, + {7.845833, 0.999993682, 0.999064863}, + {7.85, 0.999993682, 0.999067187}, + {7.854167, 0.999993742, 0.999069512}, + {7.858333, 0.999993742, 0.999071836}, + {7.8625, 0.999993801, 0.999074161}, + {7.866667, 0.999993801, 0.999076486}, + {7.870833, 0.999993861, 0.99907881}, + {7.875, 0.99999392, 0.999081135}, + {7.879167, 0.99999398, 0.999083459}, + {7.883333, 0.99999398, 0.999085724}, + {7.8875, 0.99999404, 0.999088049}, + {7.891667, 0.999994099, 0.999090314}, + {7.895833, 0.999994218, 0.999092638}, + {7.9, 0.999994278, 0.999094903}, + {7.904167, 0.999994338, 0.999097168}, + {7.908333, 0.999994397, 0.999099433}, + {7.9125, 0.999994516, 0.999101698}, + {7.916667, 0.999994576, 0.999103963}, + {7.920833, 0.999994636, 0.999106228}, + {7.925, 0.999994755, 0.999108434}, + {7.929167, 0.999994814, 0.999110699}, + {7.933333, 0.999994934, 0.999112964}, + {7.9375, 0.999994993, 0.999115169}, + {7.941667, 0.999995112, 0.999117374}, + {7.945833, 0.999995232, 0.999119639}, + {7.95, 0.999995291, 0.999121845}, + {7.954167, 0.99999541, 0.99912405}, + {7.958333, 0.99999547, 0.999126256}, + {7.9625, 0.999995589, 0.999128401}, + {7.966667, 0.999995708, 0.999130607}, + {7.970833, 0.999995768, 0.999132812}, + {7.975, 0.999995887, 0.999134958}, + {7.979167, 0.999996006, 0.999137163}, + {7.983333, 0.999996066, 0.999139309}, + {7.9875, 0.999996185, 0.999141455}, + {7.991667, 0.999996245, 0.99914366}, + {7.995833, 0.999996364, 0.999145746}, + {8, 0.999996483, 0.999147892}, + {8.004167, 0.999996543, 0.999150038}, + {8.008333, 0.999996662, 0.999152184}, + {8.0125, 0.999996722, 0.999154329}, + {8.016667, 0.999996781, 0.999156415}, + {8.020833, 0.999996901, 0.999158502}, + {8.025, 0.99999696, 0.999160647}, + {8.029167, 0.99999702, 0.999162734}, + {8.033333, 0.999997139, 0.99916482}, + {8.0375, 0.999997199, 0.999166906}, + {8.041667, 0.999997258, 0.999168992}, + {8.045833, 0.999997318, 0.999171078}, + {8.05, 0.999997377, 0.999173105}, + {8.054167, 0.999997437, 0.999175191}, + {8.058333, 0.999997497, 0.999177277}, + {8.0625, 0.999997556, 0.999179304}, + {8.066667, 0.999997616, 0.99918133}, + {8.070833, 0.999997675, 0.999183357}, + {8.075, 0.999997675, 0.999185443}, + {8.079167, 0.999997735, 0.99918741}, + {8.083333, 0.999997795, 0.999189436}, + {8.0875, 0.999997795, 0.999191463}, + {8.091667, 0.999997854, 0.99919349}, + {8.095833, 0.999997854, 0.999195457}, + {8.1, 0.999997854, 0.999197483}, + {8.104167, 0.999997914, 0.99919945}, + {8.108333, 0.999997914, 0.999201477}, + {8.1125, 0.999997914, 0.999203444}, + {8.116667, 0.999997914, 0.99920541}, + {8.120833, 0.999997914, 0.999207377}, + {8.125, 0.999997914, 0.999209344}, + {8.129167, 0.999997914, 0.999211311}, + {8.133333, 0.999997914, 0.999213278}, + {8.1375, 0.999997914, 0.999215186}, + {8.141667, 0.999997854, 0.999217153}, + {8.145833, 0.999997854, 0.99921906}, + {8.15, 0.999997854, 0.999221027}, + {8.154167, 0.999997795, 0.999222934}, + {8.158333, 0.999997795, 0.999224842}, + {8.1625, 0.999997735, 0.999226749}, + {8.166667, 0.999997735, 0.999228716}, + {8.170833, 0.999997675, 0.999230564}, + {8.175, 0.999997675, 0.999232471}, + {8.179167, 0.999997616, 0.999234378}, + {8.183333, 0.999997556, 0.999236286}, + {8.1875, 0.999997556, 0.999238193}, + {8.191667, 0.999997497, 0.999240041}, + {8.195833, 0.999997437, 0.999241948}, + {8.2, 0.999997377, 0.999243796}, + {8.204167, 0.999997318, 0.999245644}, + {8.208333, 0.999997318, 0.999247551}, + {8.2125, 0.999997258, 0.999249399}, + {8.216667, 0.999997199, 0.999251246}, + {8.220833, 0.999997139, 0.999253094}, + {8.225, 0.999997079, 0.999254942}, + {8.229167, 0.99999702, 0.99925679}, + {8.233333, 0.99999696, 0.999258637}, + {8.2375, 0.999996901, 0.999260485}, + {8.241667, 0.999996901, 0.999262273}, + {8.245833, 0.999996841, 0.999264121}, + {8.25, 0.999996781, 0.999265969}, + {8.254167, 0.999996722, 0.999267757}, + {8.258333, 0.999996662, 0.999269605}, + {8.2625, 0.999996603, 0.999271393}, + {8.266667, 0.999996543, 0.999273181}, + {8.270833, 0.999996483, 0.999274969}, + {8.275, 0.999996483, 0.999276817}, + {8.279167, 0.999996424, 0.999278605}, + {8.283333, 0.999996364, 0.999280393}, + {8.2875, 0.999996305, 0.999282181}, + {8.291667, 0.999996305, 0.999283969}, + {8.295833, 0.999996245, 0.999285758}, + {8.3, 0.999996185, 0.999287486}, + {8.304167, 0.999996185, 0.999289274}, + {8.308333, 0.999996126, 0.999291062}, + {8.3125, 0.999996126, 0.999292791}, + {8.316667, 0.999996066, 0.999294579}, + {8.320833, 0.999996066, 0.999296308}, + {8.325, 0.999996006, 0.999298096}, + {8.329167, 0.999996006, 0.999299824}, + {8.333333, 0.999996006, 0.999301553}, + {8.3375, 0.999995947, 0.999303341}, + {8.341667, 0.999995947, 0.999305069}, + {8.345833, 0.999995947, 0.999306798}, + {8.35, 0.999995947, 0.999308527}, + {8.354167, 0.999995887, 0.999310255}, + {8.358333, 0.999995887, 0.999311984}, + {8.3625, 0.999995887, 0.999313712}, + {8.366667, 0.999995887, 0.999315381}, + {8.370833, 0.999995887, 0.99931711}, + {8.375, 0.999995887, 0.999318838}, + {8.379167, 0.999995887, 0.999320507}, + {8.383333, 0.999995947, 0.999322236}, + {8.3875, 0.999995947, 0.999323905}, + {8.391667, 0.999995947, 0.999325633}, + {8.395833, 0.999995947, 0.999327302}, + {8.4, 0.999996006, 0.999329031}, + {8.404167, 0.999996006, 0.999330699}, + {8.408333, 0.999996006, 0.999332368}, + {8.4125, 0.999996066, 0.999334037}, + {8.416667, 0.999996066, 0.999335706}, + {8.420833, 0.999996126, 0.999337375}, + {8.425, 0.999996126, 0.999339044}, + {8.429167, 0.999996185, 0.999340713}, + {8.433333, 0.999996185, 0.999342322}, + {8.4375, 0.999996245, 0.999343991}, + {8.441667, 0.999996305, 0.99934566}, + {8.445833, 0.999996305, 0.99934727}, + {8.45, 0.999996364, 0.999348938}, + {8.454167, 0.999996424, 0.999350548}, + {8.458333, 0.999996483, 0.999352217}, + {8.4625, 0.999996483, 0.999353826}, + {8.466667, 0.999996543, 0.999355435}, + {8.470833, 0.999996603, 0.999357045}, + {8.475, 0.999996662, 0.999358654}, + {8.479167, 0.999996662, 0.999360263}, + {8.483333, 0.999996722, 0.999361873}, + {8.4875, 0.999996781, 0.999363482}, + {8.491667, 0.999996841, 0.999365091}, + {8.495833, 0.999996901, 0.999366701}, + {8.5, 0.99999696, 0.99936825}, + {8.504167, 0.99999696, 0.99936986}, + {8.508333, 0.99999702, 0.999371409}, + {8.5125, 0.999997079, 0.999373019}, + {8.516667, 0.999997139, 0.999374568}, + {8.520833, 0.999997199, 0.999376178}, + {8.525, 0.999997258, 0.999377728}, + {8.529167, 0.999997258, 0.999379277}, + {8.533333, 0.999997318, 0.999380827}, + {8.5375, 0.999997377, 0.999382377}, + {8.541667, 0.999997437, 0.999383926}, + {8.545833, 0.999997497, 0.999385476}, + {8.55, 0.999997497, 0.999387026}, + {8.554167, 0.999997556, 0.999388516}, + {8.558333, 0.999997616, 0.999390066}, + {8.5625, 0.999997616, 0.999391615}, + {8.566667, 0.999997675, 0.999393106}, + {8.570833, 0.999997735, 0.999394655}, + {8.575, 0.999997735, 0.999396145}, + {8.579167, 0.999997795, 0.999397635}, + {8.583333, 0.999997795, 0.999399185}, + {8.5875, 0.999997854, 0.999400675}, + {8.591667, 0.999997914, 0.999402165}, + {8.595833, 0.999997914, 0.999403656}, + {8.6, 0.999997914, 0.999405146}, + {8.604167, 0.999997973, 0.999406636}, + {8.608333, 0.999997973, 0.999408126}, + {8.6125, 0.999998033, 0.999409556}, + {8.616667, 0.999998033, 0.999411047}, + {8.620833, 0.999998033, 0.999412537}, + {8.625, 0.999998093, 0.999413967}, + {8.629167, 0.999998093, 0.999415457}, + {8.633333, 0.999998093, 0.999416888}, + {8.6375, 0.999998093, 0.999418318}, + {8.641667, 0.999998093, 0.999419808}, + {8.645833, 0.999998152, 0.999421239}, + {8.65, 0.999998152, 0.999422669}, + {8.654167, 0.999998152, 0.9994241}, + {8.658333, 0.999998152, 0.99942553}, + {8.6625, 0.999998152, 0.999426961}, + {8.666667, 0.999998152, 0.999428391}, + {8.670833, 0.999998152, 0.999429822}, + {8.675, 0.999998152, 0.999431252}, + {8.679167, 0.999998152, 0.999432623}, + {8.683333, 0.999998093, 0.999434054}, + {8.6875, 0.999998093, 0.999435425}, + {8.691667, 0.999998093, 0.999436855}, + {8.695833, 0.999998093, 0.999438226}, + {8.7, 0.999998093, 0.999439657}, + {8.704167, 0.999998033, 0.999441028}, + {8.708333, 0.999998033, 0.999442399}, + {8.7125, 0.999998033, 0.999443829}, + {8.716667, 0.999998033, 0.9994452}, + {8.720833, 0.999997973, 0.999446571}, + {8.725, 0.999997973, 0.999447942}, + {8.729167, 0.999997973, 0.999449313}, + {8.733333, 0.999997914, 0.999450684}, + {8.7375, 0.999997914, 0.999452055}, + {8.741667, 0.999997914, 0.999453425}, + {8.745833, 0.999997854, 0.999454737}, + {8.75, 0.999997854, 0.999456108}, + {8.754167, 0.999997795, 0.999457479}, + {8.758333, 0.999997795, 0.99945879}, + {8.7625, 0.999997795, 0.999460161}, + {8.766667, 0.999997735, 0.999461472}, + {8.770833, 0.999997735, 0.999462843}, + {8.775, 0.999997675, 0.999464154}, + {8.779167, 0.999997675, 0.999465525}, + {8.783333, 0.999997675, 0.999466836}, + {8.7875, 0.999997616, 0.999468148}, + {8.791667, 0.999997616, 0.999469459}, + {8.795833, 0.999997616, 0.99947077}, + {8.8, 0.999997556, 0.999472082}, + {8.804167, 0.999997556, 0.999473393}, + {8.808333, 0.999997497, 0.999474704}, + {8.8125, 0.999997497, 0.999476016}, + {8.816667, 0.999997497, 0.999477327}, + {8.820833, 0.999997437, 0.999478638}, + {8.825, 0.999997437, 0.999479949}, + {8.829167, 0.999997437, 0.999481261}, + {8.833333, 0.999997377, 0.999482512}, + {8.8375, 0.999997377, 0.999483824}, + {8.841667, 0.999997377, 0.999485135}, + {8.845833, 0.999997377, 0.999486387}, + {8.85, 0.999997318, 0.999487698}, + {8.854167, 0.999997318, 0.99948895}, + {8.858333, 0.999997318, 0.999490201}, + {8.8625, 0.999997318, 0.999491513}, + {8.866667, 0.999997318, 0.999492764}, + {8.870833, 0.999997318, 0.999494016}, + {8.875, 0.999997258, 0.999495268}, + {8.879167, 0.999997258, 0.999496579}, + {8.883333, 0.999997258, 0.999497831}, + {8.8875, 0.999997258, 0.999499083}, + {8.891667, 0.999997258, 0.999500334}, + {8.895833, 0.999997258, 0.999501586}, + {8.9, 0.999997258, 0.999502838}, + {8.904167, 0.999997258, 0.999504089}, + {8.908333, 0.999997258, 0.999505281}, + {8.9125, 0.999997258, 0.999506533}, + {8.916667, 0.999997258, 0.999507785}, + {8.920833, 0.999997318, 0.999509037}, + {8.925, 0.999997318, 0.999510229}, + {8.929167, 0.999997318, 0.99951148}, + {8.933333, 0.999997318, 0.999512672}, + {8.9375, 0.999997318, 0.999513924}, + {8.941667, 0.999997318, 0.999515116}, + {8.945833, 0.999997377, 0.999516368}, + {8.95, 0.999997377, 0.99951756}, + {8.954167, 0.999997377, 0.999518752}, + {8.958333, 0.999997377, 0.999520004}, + {8.9625, 0.999997437, 0.999521196}, + {8.966667, 0.999997437, 0.999522388}, + {8.970833, 0.999997437, 0.99952358}, + {8.975, 0.999997497, 0.999524772}, + {8.979167, 0.999997497, 0.999525964}, + {8.983333, 0.999997497, 0.999527156}, + {8.9875, 0.999997556, 0.999528348}, + {8.991667, 0.999997556, 0.999529541}, + {8.995833, 0.999997616, 0.999530733}, + {9, 0.999997616, 0.999531865}, + {9.004167, 0.999997616, 0.999533057}, + {9.008333, 0.999997675, 0.999534249}, + {9.0125, 0.999997675, 0.999535382}, + {9.016667, 0.999997735, 0.999536574}, + {9.020833, 0.999997735, 0.999537706}, + {9.025, 0.999997735, 0.999538898}, + {9.029167, 0.999997795, 0.999540031}, + {9.033333, 0.999997795, 0.999541223}, + {9.0375, 0.999997854, 0.999542356}, + {9.041667, 0.999997854, 0.999543488}, + {9.045833, 0.999997914, 0.999544621}, + {9.05, 0.999997914, 0.999545753}, + {9.054167, 0.999997973, 0.999546945}, + {9.058333, 0.999997973, 0.999548078}, + {9.0625, 0.999997973, 0.99954921}, + {9.066667, 0.999998033, 0.999550343}, + {9.070833, 0.999998033, 0.999551415}, + {9.075, 0.999998093, 0.999552548}, + {9.079167, 0.999998093, 0.99955368}, + {9.083333, 0.999998093, 0.999554813}, + {9.0875, 0.999998152, 0.999555945}, + {9.091667, 0.999998152, 0.999557018}, + {9.095833, 0.999998212, 0.999558151}, + {9.1, 0.999998212, 0.999559224}, + {9.104167, 0.999998212, 0.999560356}, + {9.108333, 0.999998271, 0.999561429}, + {9.1125, 0.999998271, 0.999562562}, + {9.116667, 0.999998271, 0.999563634}, + {9.120833, 0.999998331, 0.999564707}, + {9.125, 0.999998331, 0.99956584}, + {9.129167, 0.999998331, 0.999566913}, + {9.133333, 0.999998331, 0.999567986}, + {9.1375, 0.999998391, 0.999569058}, + {9.141667, 0.999998391, 0.999570131}, + {9.145833, 0.999998391, 0.999571204}, + {9.15, 0.999998391, 0.999572277}, + {9.154167, 0.999998391, 0.99957335}, + {9.158333, 0.99999845, 0.999574423}, + {9.1625, 0.99999845, 0.999575496}, + {9.166667, 0.99999845, 0.999576569}, + {9.170833, 0.99999845, 0.999577582}, + {9.175, 0.99999845, 0.999578655}, + {9.179167, 0.99999845, 0.999579728}, + {9.183333, 0.99999845, 0.999580741}, + {9.1875, 0.99999845, 0.999581814}, + {9.191667, 0.99999845, 0.999582827}, + {9.195833, 0.99999851, 0.9995839}, + {9.2, 0.99999851, 0.999584913}, + {9.204167, 0.99999851, 0.999585927}, + {9.208333, 0.99999851, 0.999586999}, + {9.2125, 0.99999851, 0.999588013}, + {9.216667, 0.99999851, 0.999589026}, + {9.220833, 0.99999845, 0.999590039}, + {9.225, 0.99999845, 0.999591053}, + {9.229167, 0.99999845, 0.999592125}, + {9.233333, 0.99999845, 0.999593139}, + {9.2375, 0.99999845, 0.999594152}, + {9.241667, 0.99999845, 0.999595165}, + {9.245833, 0.99999845, 0.999596119}, + {9.25, 0.99999845, 0.999597132}, + {9.254167, 0.99999845, 0.999598145}, + {9.258333, 0.99999845, 0.999599159}, + {9.2625, 0.99999845, 0.999600172}, + {9.266667, 0.999998391, 0.999601126}, + {9.270833, 0.999998391, 0.999602139}, + {9.275, 0.999998391, 0.999603152}, + {9.279167, 0.999998391, 0.999604106}, + {9.283333, 0.999998391, 0.999605119}, + {9.2875, 0.999998391, 0.999606073}, + {9.291667, 0.999998331, 0.999607086}, + {9.295833, 0.999998331, 0.99960804}, + {9.3, 0.999998331, 0.999609053}, + {9.304167, 0.999998331, 0.999610007}, + {9.308333, 0.999998331, 0.99961096}, + {9.3125, 0.999998331, 0.999611914}, + {9.316667, 0.999998271, 0.999612927}, + {9.320833, 0.999998271, 0.999613881}, + {9.325, 0.999998271, 0.999614835}, + {9.329167, 0.999998271, 0.999615788}, + {9.333333, 0.999998271, 0.999616742}, + {9.3375, 0.999998271, 0.999617696}, + {9.341667, 0.999998212, 0.999618649}, + {9.345833, 0.999998212, 0.999619603}, + {9.35, 0.999998212, 0.999620557}, + {9.354167, 0.999998212, 0.999621511}, + {9.358333, 0.999998212, 0.999622464}, + {9.3625, 0.999998212, 0.999623418}, + {9.366667, 0.999998212, 0.999624312}, + {9.370833, 0.999998152, 0.999625266}, + {9.375, 0.999998152, 0.999626219}, + {9.379167, 0.999998152, 0.999627173}, + {9.383333, 0.999998152, 0.999628067}, + {9.3875, 0.999998152, 0.999629021}, + {9.391667, 0.999998152, 0.999629915}, + {9.395833, 0.999998152, 0.999630868}, + {9.4, 0.999998152, 0.999631763}, + {9.404167, 0.999998152, 0.999632716}, + {9.408333, 0.999998152, 0.99963361}, + {9.4125, 0.999998152, 0.999634564}, + {9.416667, 0.999998152, 0.999635458}, + {9.420833, 0.999998152, 0.999636352}, + {9.425, 0.999998152, 0.999637246}, + {9.429167, 0.999998152, 0.9996382}, + {9.433333, 0.999998152, 0.999639094}, + {9.4375, 0.999998152, 0.999639988}, + {9.441667, 0.999998152, 0.999640882}, + {9.445833, 0.999998152, 0.999641776}, + {9.45, 0.999998152, 0.99964267}, + {9.454167, 0.999998152, 0.999643564}, + {9.458333, 0.999998152, 0.999644458}, + {9.4625, 0.999998152, 0.999645352}, + {9.466667, 0.999998152, 0.999646246}, + {9.470833, 0.999998152, 0.999647141}, + {9.475, 0.999998212, 0.999648035}, + {9.479167, 0.999998212, 0.999648929}, + {9.483333, 0.999998212, 0.999649763}, + {9.4875, 0.999998212, 0.999650657}, + {9.491667, 0.999998212, 0.999651551}, + {9.495833, 0.999998212, 0.999652445}, + {9.5, 0.999998212, 0.99965328}, + {9.504167, 0.999998271, 0.999654174}, + {9.508333, 0.999998271, 0.999655008}, + {9.5125, 0.999998271, 0.999655902}, + {9.516667, 0.999998271, 0.999656737}, + {9.520833, 0.999998271, 0.999657631}, + {9.525, 0.999998331, 0.999658465}, + {9.529167, 0.999998331, 0.999659359}, + {9.533333, 0.999998331, 0.999660194}, + {9.5375, 0.999998331, 0.999661028}, + {9.541667, 0.999998331, 0.999661863}, + {9.545833, 0.999998391, 0.999662757}, + {9.55, 0.999998391, 0.999663591}, + {9.554167, 0.999998391, 0.999664426}, + {9.558333, 0.999998391, 0.99966526}, + {9.5625, 0.99999845, 0.999666095}, + {9.566667, 0.99999845, 0.999666929}, + {9.570833, 0.99999845, 0.999667764}, + {9.575, 0.99999845, 0.999668598}, + {9.579167, 0.99999845, 0.999669433}, + {9.583333, 0.99999851, 0.999670267}, + {9.5875, 0.99999851, 0.999671102}, + {9.591667, 0.99999851, 0.999671936}, + {9.595833, 0.99999851, 0.999672771}, + {9.6, 0.999998569, 0.999673545}, + {9.604167, 0.999998569, 0.99967438}, + {9.608333, 0.999998569, 0.999675214}, + {9.6125, 0.999998569, 0.999676049}, + {9.616667, 0.999998629, 0.999676824}, + {9.620833, 0.999998629, 0.999677658}, + {9.625, 0.999998629, 0.999678433}, + {9.629167, 0.999998629, 0.999679267}, + {9.633333, 0.999998629, 0.999680042}, + {9.6375, 0.999998689, 0.999680877}, + {9.641667, 0.999998689, 0.999681652}, + {9.645833, 0.999998689, 0.999682486}, + {9.65, 0.999998689, 0.999683261}, + {9.654167, 0.999998689, 0.999684036}, + {9.658333, 0.999998689, 0.999684811}, + {9.6625, 0.999998748, 0.999685645}, + {9.666667, 0.999998748, 0.99968642}, + {9.670833, 0.999998748, 0.999687195}, + {9.675, 0.999998748, 0.99968797}, + {9.679167, 0.999998748, 0.999688745}, + {9.683333, 0.999998748, 0.999689519}, + {9.6875, 0.999998748, 0.999690294}, + {9.691667, 0.999998748, 0.999691069}, + {9.695833, 0.999998808, 0.999691844}, + {9.7, 0.999998808, 0.999692619}, + {9.704167, 0.999998808, 0.999693394}, + {9.708333, 0.999998808, 0.999694169}, + {9.7125, 0.999998808, 0.999694943}, + {9.716667, 0.999998808, 0.999695718}, + {9.720833, 0.999998808, 0.999696434}, + {9.725, 0.999998808, 0.999697208}, + {9.729167, 0.999998808, 0.999697983}, + {9.733333, 0.999998808, 0.999698699}, + {9.7375, 0.999998808, 0.999699473}, + {9.741667, 0.999998808, 0.999700248}, + {9.745833, 0.999998808, 0.999700963}, + {9.75, 0.999998808, 0.999701738}, + {9.754167, 0.999998808, 0.999702454}, + {9.758333, 0.999998808, 0.999703228}, + {9.7625, 0.999998808, 0.999703944}, + {9.766667, 0.999998808, 0.999704719}, + {9.770833, 0.999998808, 0.999705434}, + {9.775, 0.999998808, 0.999706149}, + {9.779167, 0.999998808, 0.999706924}, + {9.783333, 0.999998808, 0.999707639}, + {9.7875, 0.999998808, 0.999708354}, + {9.791667, 0.999998808, 0.99970907}, + {9.795833, 0.999998808, 0.999709845}, + {9.8, 0.999998808, 0.99971056}, + {9.804167, 0.999998808, 0.999711275}, + {9.808333, 0.999998808, 0.99971199}, + {9.8125, 0.999998808, 0.999712706}, + {9.816667, 0.999998808, 0.999713421}, + {9.820833, 0.999998808, 0.999714136}, + {9.825, 0.999998808, 0.999714851}, + {9.829167, 0.999998808, 0.999715567}, + {9.833333, 0.999998748, 0.999716282}, + {9.8375, 0.999998748, 0.999716997}, + {9.841667, 0.999998748, 0.999717712}, + {9.845833, 0.999998748, 0.999718368}, + {9.85, 0.999998748, 0.999719083}, + {9.854167, 0.999998748, 0.999719799}, + {9.858333, 0.999998748, 0.999720514}, + {9.8625, 0.999998748, 0.999721169}, + {9.866667, 0.999998748, 0.999721885}, + {9.870833, 0.999998748, 0.9997226}, + {9.875, 0.999998748, 0.999723256}, + {9.879167, 0.999998748, 0.999723971}, + {9.883333, 0.999998748, 0.999724686}, + {9.8875, 0.999998748, 0.999725342}, + {9.891667, 0.999998748, 0.999726057}, + {9.895833, 0.999998748, 0.999726713}, + {9.9, 0.999998689, 0.999727428}, + {9.904167, 0.999998689, 0.999728084}, + {9.908333, 0.999998689, 0.999728799}, + {9.9125, 0.999998689, 0.999729455}, + {9.916667, 0.999998689, 0.99973011}, + {9.920833, 0.999998689, 0.999730825}, + {9.925, 0.999998689, 0.999731481}, + {9.929167, 0.999998689, 0.999732137}, + {9.933333, 0.999998689, 0.999732792}, + {9.9375, 0.999998689, 0.999733508}, + {9.941667, 0.999998689, 0.999734163}, + {9.945833, 0.999998689, 0.999734819}, + {9.95, 0.999998689, 0.999735475}, + {9.954167, 0.999998689, 0.99973613}, + {9.958333, 0.999998689, 0.999736786}, + {9.9625, 0.999998689, 0.999737501}, + {9.966667, 0.999998689, 0.999738157}, + {9.970833, 0.999998689, 0.999738812}, + {9.975, 0.999998689, 0.999739468}, + {9.979167, 0.999998689, 0.999740124}, + {9.983333, 0.999998689, 0.99974072}, + {9.9875, 0.999998689, 0.999741375}, + {9.991667, 0.999998748, 0.999742031}, + {9.995833, 0.999998748, 0.999742687}, + {10, 0.999998748, 0.999743342}}; diff --git a/examples/PhasorDynamics/Example1/example1.cpp b/examples/PhasorDynamics/Example1/example1.cpp new file mode 100644 index 000000000..d3d3bdbfd --- /dev/null +++ b/examples/PhasorDynamics/Example1/example1.cpp @@ -0,0 +1,168 @@ +#include +#define _USE_MATH_DEFINES +#include +#include + +// #include +#include +#include +#include +#include +#include + +#include "Example1_Powerworld_Reference.hpp" +#include "Model/PhasorDynamics/Branch/Branch.cpp" +#include "Model/PhasorDynamics/Branch/Branch.hpp" +#include "Model/PhasorDynamics/Bus/Bus.cpp" +#include "Model/PhasorDynamics/Bus/Bus.hpp" +#include "Model/PhasorDynamics/Bus/BusInfinite.cpp" +#include "Model/PhasorDynamics/Bus/BusInfinite.hpp" +#include "Model/PhasorDynamics/BusFault/BusFault.hpp" +#include "Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp" +#include "Model/PhasorDynamics/SystemModel.hpp" +#include "Solver/Dynamic/Ida.cpp" +#include "Solver/Dynamic/Ida.hpp" +#include + +#define _CRT_SECURE_NO_WARNINGS + +int main() +{ + using namespace GridKit::PhasorDynamics; + using namespace AnalysisManager::Sundials; + + printf("Example 1 version 2\n"); + + /* Create model parts */ + SystemModel sys; + Bus bus1(0.9949877346411762, 0.09999703952427966); + BusInfinite bus2(1.0, 0.0); + Branch branch(&bus1, &bus2, 0, 0.1, 0, 0); + BusFault fault(&bus1, 0, 1e-3, 0); + + Genrou gen(&bus1, + 1, + 1., + 0.05013, + 3., + 0., + 0., + 7., + .04, + .05, + .75, + 2.1, + 0.2, + 0.18, + 0.5, + 0.5, + 0.18, + 0.15, + 0., + 0.); + + /* Connect everything together */ + sys.addBus(&bus1); + sys.addBus(&bus2); + sys.addComponent(&branch); + sys.addComponent(&fault); + sys.addComponent(&gen); + sys.allocate(); + + double dt = 1.0 / 4.0 / 60.0; + + std::stringstream buffer; + + /* Set up simulation */ + Ida ida(&sys); + ida.configureSimulation(); + + /* Run simulation */ + double start = static_cast(clock()); + // ida.printOutputF(0, 0, buffer); + ida.initializeSimulation(0.0, false); + ida.runSimulationFixed(0.0, dt, 1.0, buffer); + fault.setStatus(1); + ida.initializeSimulation(1.0, false); + ida.runSimulationFixed(1.0, dt, 1.1, buffer); + fault.setStatus(0); + ida.initializeSimulation(1.1, false); + ida.runSimulationFixed(1.1, dt, 10.0, buffer); + double stop = static_cast(clock()); + + // Go to the beginning of the data buffer + buffer.seekg(0, std::ios::beg); + + double data; + + size_t i = 0; // data row counter + size_t j = 0; // data column counter + double Vr = 0.0; // Bus real voltage + double Vi = 0.0; // Bus imaginary voltage + double dw = 0.0; // Generator frequency deviation [rad/s] + double ti = 0.0; // time + double error_V = 0.0; // error in |V| + + // Read through the simulation data storred in the buffer + while (buffer >> data) + { + // At the end of each data line compare computed data to Powerworld results + // and reset column counter to zero. + if ((i % 48) == 0) + { + double err = + std::abs(std::sqrt(Vr * Vr + Vi * Vi) - reference_solution[i / 48][2]) + / (1.0 + std::abs(reference_solution[i / 48][2])); + if (err > error_V) + error_V = err; + // std::cout << "t = " << ti << ": Vr = " << Vr << ", Vi = " << Vi << ", dw = " << dw; + std::cout << "GridKit: t = " << ti + << ", |V| = " << std::sqrt(Vr * Vr + Vi * Vi) + << ", w = " << (1.0 + dw) << "\n"; + std::cout << "Ref : t = " << reference_solution[i / 48][0] + << ", |V| = " << reference_solution[i / 48][2] + << ", w = " << reference_solution[i / 48][1] + << "\n"; + std::cout << "Error in |V| = " + << err + << "\n"; + j = 0; + Vr = 0.0; + Vi = 0.0; + std::cout << "\n"; + } + if (j == 0) + { + ti = data; + } + if (j == 2) + { + Vr = data; + } + if (j == 3) + { + Vi = data; + } + if (j == 5) + { + dw = data; + } + ++j; + ++i; + // if (i > 500) + // break; + } + + // std::cout << buffer.str(); + int status = 0; + std::cout << "Max error in |V| = " << error_V << "\n"; + if (error_V > 2e-4) + { + std::cout << "Test failed with error too large!\n"; + status = 1; + } + + std::cout << "\n\nComplete in " << (stop - start) / CLOCKS_PER_SEC << " seconds\n"; + + return 0; +} diff --git a/examples/RLCircuit/CMakeLists.txt b/examples/RLCircuit/CMakeLists.txt new file mode 100644 index 000000000..56599c521 --- /dev/null +++ b/examples/RLCircuit/CMakeLists.txt @@ -0,0 +1,13 @@ + + + + +add_executable(rlcircuit RLCircuit.cpp) +target_link_libraries(rlcircuit GRIDKIT::power_elec_capacitor + GRIDKIT::power_elec_inductor + GRIDKIT::power_elec_resistor + GRIDKIT::power_elec_voltagesource + GRIDKIT::solvers_dyn) + +add_test(NAME RLCircuit COMMAND $) +install(TARGETS rlcircuit RUNTIME DESTINATION bin) diff --git a/examples/RLCircuit/RLCircuit.cpp b/examples/RLCircuit/RLCircuit.cpp new file mode 100644 index 000000000..841395c3a --- /dev/null +++ b/examples/RLCircuit/RLCircuit.cpp @@ -0,0 +1,138 @@ + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const* argv[]) +{ + double abs_tol = 1.0e-8; + double rel_tol = 1.0e-8; + bool use_jac = true; + + // TODO:setup as named parameters + // Create circuit model + auto* sysmodel = new GridKit::PowerElectronicsModel(rel_tol, abs_tol, use_jac); + + size_t idoff = 0; + + // RL circuit parameters + double rinit = 1.0; + double linit = 1.0; + double vinit = 1.0; + + // inductor + GridKit::Inductor* induct = new GridKit::Inductor(idoff, linit); + // Form index to node uid realations + // input + induct->setExternalConnectionNodes(0, 1); + // output + induct->setExternalConnectionNodes(1, -1); + // internal + induct->setExternalConnectionNodes(2, 2); + // add component + sysmodel->addComponent(induct); + + // resistor + idoff++; + GridKit::Resistor* resis = new GridKit::Resistor(idoff, rinit); + // Form index to node uid realations + // input + resis->setExternalConnectionNodes(0, 0); + // output + resis->setExternalConnectionNodes(1, 1); + // add + sysmodel->addComponent(resis); + + // voltage source + idoff++; + GridKit::VoltageSource* vsource = new GridKit::VoltageSource(idoff, vinit); + // Form index to node uid realations + // input + vsource->setExternalConnectionNodes(0, -1); + // output + vsource->setExternalConnectionNodes(1, 0); + // internal + vsource->setExternalConnectionNodes(2, 3); + + sysmodel->addComponent(vsource); + + sysmodel->allocate(4); + + std::cout << sysmodel->y().size() << std::endl; + + // Grounding for IDA. If no grounding then circuit is \mu > 1 + // v_0 (grounded) + // Create Intial points + sysmodel->y()[0] = vinit; // v_1 + sysmodel->y()[1] = vinit; // v_2 + sysmodel->y()[2] = 0.0; // i_L + sysmodel->y()[3] = 0.0; // i_s + + sysmodel->yp()[0] = 0.0; // v'_1 + sysmodel->yp()[1] = 0.0; // v'_2 + sysmodel->yp()[2] = -vinit / linit; // i'_s + sysmodel->yp()[3] = -vinit / linit; // i'_L + + sysmodel->initialize(); + sysmodel->evaluateResidual(); + + std::cout << "Verify Intial Resisdual is Zero: {"; + for (double i : sysmodel->getResidual()) + { + std::cout << i << ", "; + } + std::cout << "}\n"; + + sysmodel->updateTime(0.0, 1.0); + sysmodel->evaluateJacobian(); + std::cout << "Intial Jacobian with alpha = 1:\n"; + sysmodel->getJacobian().printMatrix(); + + // Create numerical integrator and configure it for the generator model + AnalysisManager::Sundials::Ida* idas = new AnalysisManager::Sundials::Ida(sysmodel); + + double t_init = 0.0; + double t_final = 1.0; + + // setup simulation + idas->configureSimulation(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init); + + idas->runSimulation(t_final); + + std::vector& yfinial = sysmodel->y(); + + std::cout << "Final Vector y\n"; + for (size_t i = 0; i < yfinial.size(); i++) + { + std::cout << yfinial[i] << "\n"; + } + + std::vector yexact(4); + + // analytical solution to the circuit + yexact[0] = vinit; + yexact[2] = (vinit / rinit) * (exp(-(rinit / linit) * t_final) - 1.0); + yexact[3] = yexact[2]; + yexact[1] = vinit + rinit * yexact[2]; + + std::cout << "Element-wise Relative error at t=" << t_final << "\n"; + for (size_t i = 0; i < yfinial.size(); i++) + { + std::cout << abs((yfinial[i] - yexact[i]) / yexact[i]) << "\n"; + } + + return 0; +} diff --git a/examples/ScaleMicrogrid/CMakeLists.txt b/examples/ScaleMicrogrid/CMakeLists.txt new file mode 100644 index 000000000..1f0fe0cbb --- /dev/null +++ b/examples/ScaleMicrogrid/CMakeLists.txt @@ -0,0 +1,13 @@ + + + + +add_executable(scalemicrogrid ScaleMicrogrid.cpp) +target_link_libraries(scalemicrogrid GRIDKIT::power_elec_disgen + GRIDKIT::power_elec_microline + GRIDKIT::power_elec_microload + GRIDKIT::solvers_dyn + GRIDKIT::power_elec_microbusdq) + +add_test(NAME ScaleMicrogrid COMMAND $) +install(TARGETS scalemicrogrid RUNTIME DESTINATION bin) diff --git a/examples/ScaleMicrogrid/ScaleMicrogrid.cpp b/examples/ScaleMicrogrid/ScaleMicrogrid.cpp new file mode 100644 index 000000000..819c4f767 --- /dev/null +++ b/examples/ScaleMicrogrid/ScaleMicrogrid.cpp @@ -0,0 +1,381 @@ + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using index_type = size_t; +using real_type = double; + +// Include solution keys for the three test cases N = (2, 4, 8) plus tolerances here: +#include "SolutionKeys.hpp" + +static int test(index_type Nsize, real_type test_tolerance, bool error_tol = false); + +/** + * @brief Run Scale Microgrid test cases of N = (2,4,8) and check for correctness. + * + * @param argc unused + * @param argv unsued + * @return int + */ +int main(int argc, char const* argv[]) +{ + int retval = 0; + bool debug_out = false; + real_type tol = SCALE_MICROGRID_ERROR_TOL; + + retval += test(2, tol, debug_out); + retval += test(4, tol, debug_out); + retval += test(8, tol, debug_out); + if (retval > 0) + { + std::cout << "Some tests fail!!\n"; + } + else + { + std::cout << "All tests pass!!\n"; + } + return retval; +} + +/** + * @brief Tests network of distributed generators. + * + * @param Nsize - The number of DG line load cobinations to generate for scale + * @param error_tol - The tolerance for the model to meet to pass + * @param debug_output - Enable debug output + * @param use_DAE_keys - Choice between using DAE or ODE keys + * @return int returns 0 if successful, >0 otherwise + */ +int test(index_type Nsize, real_type error_tol, bool debug_output) +{ + using namespace GridKit; + + bool use_jac = true; + + real_type t_init = 0.0; + real_type t_final = 1.0; + + real_type rel_tol = SCALE_MICROGRID_REL_TOL; + real_type abs_tol = SCALE_MICROGRID_ABS_TOL; + + // Create circuit model + auto* sysmodel = new PowerElectronicsModel(rel_tol, + abs_tol, + use_jac, + SCALE_MICROGRID_MAX_STEPS); + + const std::vector* true_vec = &answer_key_N8; + + switch (Nsize) + { + case 2: + true_vec = &answer_key_N2; + break; + case 4: + true_vec = &answer_key_N4; + break; + case 8: + // true_vec = &answer_key_N8; + break; + default: + std::cout << "No reference solution for Nsize = " << Nsize << ".\n"; + std::cout << "Using default Nsize = 8.\n"; + } + + // Modeled after the problem in the paper + // Every Bus has the same virtual resistance. This is due to the numerical stability as mentioned in the paper. + real_type RN = 1.0e4; + + // DG Params Vector + // All DGs have the same set of parameters except for the first two. + GridKit::DistributedGeneratorParameters DG_parms1; + DG_parms1.wb_ = 2.0 * M_PI * 50.0; + DG_parms1.wc_ = 31.41; + DG_parms1.mp_ = 9.4e-5; + DG_parms1.Vn_ = 380.0; + DG_parms1.nq_ = 1.3e-3; + DG_parms1.F_ = 0.75; + DG_parms1.Kiv_ = 420.0; + DG_parms1.Kpv_ = 0.1; + DG_parms1.Kic_ = 2.0e4; + DG_parms1.Kpc_ = 15.0; + DG_parms1.Cf_ = 5.0e-5; + DG_parms1.rLf_ = 0.1; + DG_parms1.Lf_ = 1.35e-3; + DG_parms1.rLc_ = 0.03; + DG_parms1.Lc_ = 0.35e-3; + + GridKit::DistributedGeneratorParameters DG_parms2; + DG_parms2.wb_ = 2.0 * M_PI * 50.0; + DG_parms2.wc_ = 31.41; + DG_parms2.mp_ = 12.5e-5; + DG_parms2.Vn_ = 380.0; + DG_parms2.nq_ = 1.5e-3; + DG_parms2.F_ = 0.75; + DG_parms2.Kiv_ = 390.0; + DG_parms2.Kpv_ = 0.05; + DG_parms2.Kic_ = 16.0e3; + DG_parms2.Kpc_ = 10.5; + DG_parms2.Cf_ = 50.0e-6; + DG_parms2.rLf_ = 0.1; + DG_parms2.Lf_ = 1.35e-3; + DG_parms2.rLc_ = 0.03; + DG_parms2.Lc_ = 0.35e-3; + + std::vector> DGParams_list(2 * Nsize, DG_parms2); + + DGParams_list[0] = DG_parms1; + DGParams_list[1] = DG_parms1; + + // line vector params + // Every odd line has the same parameters and every even line has the same parameters + real_type rline1 = 0.23; + real_type Lline1 = 0.1 / (2.0 * M_PI * 50.0); + real_type rline2 = 0.35; + real_type Lline2 = 0.58 / (2.0 * M_PI * 50.0); + std::vector rline_list(2 * Nsize - 1, 0.0); + std::vector Lline_list(2 * Nsize - 1, 0.0); + for (index_type i = 0; i < rline_list.size(); i++) + { + rline_list[i] = (i % 2) ? rline2 : rline1; + Lline_list[i] = (i % 2) ? Lline2 : Lline1; + } + + // load parms + // Only the first load has the same paramaters. + real_type rload1 = 3.0; + real_type Lload1 = 2.0 / (2.0 * M_PI * 50.0); + real_type rload2 = 2.0; + real_type Lload2 = 1.0 / (2.0 * M_PI * 50.0); + + std::vector rload_list(Nsize, rload2); + std::vector Lload_list(Nsize, Lload2); + rload_list[0] = rload1; + Lload_list[0] = Lload1; + + // DGs + - refframe Lines + Loads + index_type vec_size_internals = 13 * (2 * Nsize) - 1 + (2 + 4 * (Nsize - 1)) + 2 * Nsize; + // \omegaref + BusDQ + index_type vec_size_externals = 1 + 2 * (2 * Nsize); + + std::vector vdqbus_index(2 * Nsize, 0); + vdqbus_index[0] = vec_size_internals + 1; + for (index_type i = 1; i < vdqbus_index.size(); i++) + { + vdqbus_index[i] = vdqbus_index[i - 1] + 2; + } + + // Total size of the vector setup + index_type vec_size_total = vec_size_internals + vec_size_externals; + + // Create the reference DG + auto* dg_ref = new DistributedGenerator(0, + DGParams_list[0], + true); + // ref motor + dg_ref->setExternalConnectionNodes(0, vec_size_internals); + // outputs + dg_ref->setExternalConnectionNodes(1, vdqbus_index[0]); + dg_ref->setExternalConnectionNodes(2, vdqbus_index[0] + 1); + //"grounding" of the difference + dg_ref->setExternalConnectionNodes(3, -1); + // internal connections + for (index_type i = 0; i < 12; i++) + { + dg_ref->setExternalConnectionNodes(4 + i, i); + } + sysmodel->addComponent(dg_ref); + + // Keep track of models and index location + index_type indexv = 12; + index_type model_id = 1; + // Add all other DGs + for (index_type i = 1; i < 2 * Nsize; i++) + { + // current DG to add + auto* dg = new DistributedGenerator(model_id++, + DGParams_list[i], + false); + // ref motor + dg->setExternalConnectionNodes(0, vec_size_internals); + // outputs + dg->setExternalConnectionNodes(1, vdqbus_index[i]); + dg->setExternalConnectionNodes(2, vdqbus_index[i] + 1); + // internal connections + for (index_type j = 0; j < 13; j++) + { + dg->setExternalConnectionNodes(3 + j, indexv + j); + } + indexv += 13; + sysmodel->addComponent(dg); + } + + // Load all the Line compoenents + for (index_type i = 0; i < 2 * Nsize - 1; i++) + { + // line + auto* line_model = new MicrogridLine(model_id++, + rline_list[i], + Lline_list[i]); + // ref motor + line_model->setExternalConnectionNodes(0, vec_size_internals); + // input connections + line_model->setExternalConnectionNodes(1, vdqbus_index[i]); + line_model->setExternalConnectionNodes(2, vdqbus_index[i] + 1); + // output connections + line_model->setExternalConnectionNodes(3, vdqbus_index[i + 1]); + line_model->setExternalConnectionNodes(4, vdqbus_index[i + 1] + 1); + // internal connections + for (index_type j = 0; j < 2; j++) + { + line_model->setExternalConnectionNodes(5 + j, indexv + j); + } + indexv += 2; + sysmodel->addComponent(line_model); + } + + // Load all the Load components + for (index_type i = 0; i < Nsize; i++) + { + auto* load_model = new MicrogridLoad(model_id++, + rload_list[i], + Lload_list[i]); + // ref motor + load_model->setExternalConnectionNodes(0, vec_size_internals); + // input connections + load_model->setExternalConnectionNodes(1, vdqbus_index[2 * i]); + load_model->setExternalConnectionNodes(2, vdqbus_index[2 * i] + 1); + // internal connections + for (index_type j = 0; j < 2; j++) + { + load_model->setExternalConnectionNodes(3 + j, indexv + j); + } + indexv += 2; + sysmodel->addComponent(load_model); + } + + // Add all the microgrid Virtual DQ Buses + for (index_type i = 0; i < 2 * Nsize; i++) + { + auto* virDQbus_model = new MicrogridBusDQ(model_id++, RN); + + virDQbus_model->setExternalConnectionNodes(0, vdqbus_index[i]); + virDQbus_model->setExternalConnectionNodes(1, vdqbus_index[i] + 1); + sysmodel->addComponent(virDQbus_model); + } + + // allocate all the intial conditions + sysmodel->allocate(vec_size_total); + + if (debug_output) + { + std::cout << sysmodel->y().size() << std::endl; + std::cout << vec_size_internals << ", " << vec_size_externals << "\n"; + } + + // Create Intial points for states. Every state is to specified to the zero intially + for (index_type i = 0; i < vec_size_total; i++) + { + sysmodel->y()[i] = 0.0; + sysmodel->yp()[i] = 0.0; + } + + // Create Intial derivatives specifics generated in MATLAB + for (index_type i = 0; i < 2 * Nsize; i++) + { + sysmodel->yp()[13 * i - 1 + 3] = DGParams_list[i].Vn_; + sysmodel->yp()[13 * i - 1 + 5] = DGParams_list[i].Kpv_ * DGParams_list[i].Vn_; + sysmodel->yp()[13 * i - 1 + 7] = (DGParams_list[i].Kpc_ * DGParams_list[i].Kpv_ * DGParams_list[i].Vn_) / DGParams_list[i].Lf_; + } + + // since the intial P_com = 0, the set the intial vector to the reference frame + sysmodel->y()[vec_size_internals] = DG_parms1.wb_; + + sysmodel->initialize(); + sysmodel->evaluateResidual(); + + std::vector& fres = sysmodel->getResidual(); + if (debug_output) + { + std::cout << "Verify Intial Resisdual is Zero: {\n"; + for (index_type i = 0; i < fres.size(); i++) + { + std::cout << i << " : " << fres[i] << "\n"; + } + std::cout << "}\n"; + } + + sysmodel->updateTime(0.0, 1.0e-8); + sysmodel->evaluateJacobian(); + if (debug_output) + std::cout << "Intial Jacobian with alpha:\n"; + + // Create numerical integrator and configure it for the generator model + auto* idas = new AnalysisManager::Sundials::Ida(sysmodel); + + // setup simulation + idas->configureSimulation(); + idas->getDefaultInitialCondition(); + idas->initializeSimulation(t_init); + + idas->runSimulation(t_final); + + std::vector& yfinal = sysmodel->y(); + + if (debug_output) + { + std::cout << "Final Vector y\n"; + for (index_type i = 0; i < yfinal.size(); i++) + { + std::cout << i << " : " << yfinal[i] << "\n"; + } + } + + bool test_pass = true; + + real_type sumtop = 0.0; + real_type sumbottom = 0.0; + + // check relative error + std::cout << "Test the Relative Error for N = " << Nsize << "\n"; + for (index_type i = 0; i < true_vec->size(); i++) + { + // Print the Elementwise Relative Error + if (debug_output) + std::cout << i << " : " << abs(true_vec->at(i) - yfinal[i]) / abs(true_vec->at(i)) << "\n"; + + sumtop += (true_vec->at(i) - yfinal[i]) * (true_vec->at(i) - yfinal[i]); + sumbottom += (true_vec->at(i) * true_vec->at(i)); + } + + real_type norm2error = (sqrt(sumtop) / sqrt(sumbottom)); + std::cout << "2-Norm Relative Error: " << norm2error << std::endl; + test_pass = norm2error < error_tol; + + delete idas; + delete sysmodel; + + if (test_pass) + { + std::cout << "Test with Nsize = " << Nsize << " passes!\n"; + return 0; + } + else + { + std::cout << "Test with Nsize = " << Nsize << " fails!\n"; + return 1; + } +} diff --git a/examples/ScaleMicrogrid/SolutionKeys.hpp b/examples/ScaleMicrogrid/SolutionKeys.hpp new file mode 100644 index 000000000..f604b5e9e --- /dev/null +++ b/examples/ScaleMicrogrid/SolutionKeys.hpp @@ -0,0 +1,535 @@ +/** + * @file SolutionKeys.hpp + * @author Reid Gomillion (rjg18@vt.edu) + * @author Slaven Peles (peless@ornl.gov) + * @brief Answer keys for Scaled Microgrid test with Nsize = 2, 4, 8 + * + * Data generated with Matlab ode23tb solver with tolerances set to + * abs_tol = 1e-12 and rel_tol = 1e-12 for the ODE derivation of the model. + * No index reduction was preformed to get to the ODE model. + * + * @note This file is only to be included in ScaleMicrogrid.cpp. It has no + * use anywhere else. + */ + +#include + +/// +/** + * The SCALE_MICROGRID_ERROR_TOL is a metric to determine if the error is good enough to pass the test. + * REL_TOL and ABS_TOL determine the amount of error the problem produces. As the tolerance decrease so does the error. + * + * For References keys on N=8: + * 2-Norm Relative Error: 2.33318e-07 (rel/abs tol = 1e-6) + * 2-Norm Relative Error: 8.65796e-08 (rel/abs tol = 1e-7) + * 2-Norm Relative Error: 1.1618e-08 (rel/abs tol = 1e-8) + * + */ +constexpr real_type SCALE_MICROGRID_ERROR_TOL = 1.0e-6; +constexpr real_type SCALE_MICROGRID_REL_TOL = 1.0e-8; +constexpr real_type SCALE_MICROGRID_ABS_TOL = 1.0e-8; +constexpr index_type SCALE_MICROGRID_MAX_STEPS = 10000; + +const std::vector answer_key_N2 = { + 22975.4182636905, + 12753.1173017451, + 0.0376305671131306, + -0.0209815421114537, + 0.0184828563235406, + -0.00015632917065729, + 63.2193617412383, + -29.4226556659582, + 363.420924977355, + -3.01001804456668e-06, + 63.2193618667302, + -35.0920143829141, + -0.00755583999797958, + 22975.8457840701, + 8742.0172166684, + 0.0371009878165673, + -0.0142112776774797, + 0.0187407972932474, + -9.8913852531819e-05, + 62.3296548917654, + -17.9650261562766, + 368.635407345931, + 3.79041261513032e-05, + 62.3296560841534, + -23.7157298601546, + -0.0827401584095097, + 17277.712521392, + 16493.7578328327, + 0.0311645357391787, + -0.0298601153771274, + 0.0225001003469904, + -0.000264388302121386, + 48.6166482764357, + -40.8862612232969, + 355.25957014696, + -0.000167008045114112, + 48.6166481095298, + -46.4283022775928, + -0.0844566209033113, + 17277.2493364959, + 9182.29479881977, + 0.0302503981389185, + -0.0161722538457184, + 0.023180586071601, + -0.000129590157483103, + 47.1906392248137, + -19.3574255862892, + 366.226354188735, + 0.000121054462396047, + 47.19063792117, + -25.0705499054599, + -18.8125403122072, + 21.1471334522508, + 43.2997340692497, + -3.03798323340816, + -44.8715356440453, + 28.9585224749495, + 81.99613295014, + -56.2385627562355, + 132.749774614687, + -82.280664729262, + 311.999576042192, + 357.692287974629, + -5.85078929333349, + 364.119335219897, + -8.84631033126304, + 347.214535767435, + -32.7241067379802, + 360.411028950125, + -34.9283280833745}; + +const std::vector answer_key_N4 = { + 27828.3291148094, + 10602.3611530864, + 0.0452452394028709, + -0.0173410584955486, + 0.018686818367312, + -0.000129595027000909, + 76.0120809944985, + -23.2367034227098, + 366.216582730654, + -0.000167782960864797, + 76.0120710728117, + -28.9413214479885, + -0.0154989336357971, + 27832.0772154743, + 7838.80352597054, + 0.0448129806183038, + -0.0127296381144373, + 0.0188642014642206, + -9.04502393904097e-05, + 75.2859236720964, + -15.4316980534341, + 369.809174828127, + -5.17440472732025e-05, + 75.285919083362, + -21.1922719962368, + -0.142596248886844, + 20950.1519748442, + 16334.3924580166, + 0.0377787488551238, + -0.0295717781600636, + 0.0225780601074885, + -0.000265567743682681, + 58.9348270364006, + -40.4081583028089, + 355.498460539903, + -8.66167274613643e-05, + 58.9348242715342, + -45.9457664944992, + -0.164628885385433, + 20956.2846481359, + 12345.7855779785, + 0.0371673110634281, + -0.0220171188824754, + 0.0229486760225139, + -0.000191111142238558, + 57.9810673844105, + -28.5265491599081, + 361.481100853144, + 8.24481547667206e-05, + 57.9810719040216, + -34.1573355283559, + -0.245126576498858, + 20978.9206932923, + 17875.6825958711, + 0.0380785081131898, + -0.0325621468970297, + 0.0224354615928625, + -0.000295085318936756, + 59.4025243779293, + -45.1101946009202, + 353.186117339098, + 5.52721744209165e-05, + 59.4025238741703, + -50.6117204294148, + -0.253672269778405, + 20990.6142554844, + 11779.5685373245, + 0.0371243965775962, + -0.0209716906203726, + 0.0230016494389548, + -0.000180846578022512, + 57.9140614794815, + -26.8817831662193, + 362.331254349606, + 0.000209247259473183, + 57.9140782926947, + -32.5257339504705, + -0.288747285297145, + 21004.5418902462, + 16686.981801999, + 0.0379131316203435, + -0.0302602142538338, + 0.0225460339603269, + -0.000272422675391038, + 59.1444740212228, + -41.4902940591195, + 354.969993387113, + 8.14114753778542e-05, + 59.1444846638236, + -47.0195494892644, + -0.285876486857154, + 21005.895228757, + 8274.13913126834, + 0.0366267978764156, + -0.0145584209340773, + 0.0233276948336748, + -0.000117627382397687, + 57.1378568500881, + -16.7923279871216, + 367.58883605301, + 0.000263351556352378, + 57.1378679159653, + -22.518140603782, + -6.57009481597077, + 28.1053117219546, + 68.341829672125, + 5.75010361666728, + -7.27398138223966, + 42.3413009908014, + 44.2901915856089, + -0.850144510998897, + -26.9214526328474, + 37.7939474726438, + 20.9421230166698, + -8.2155394685309, + -48.4341275019927, + 37.706248875936, + 82.5460878639016, + -57.0458911301263, + 127.388509162578, + -90.4406093871607, + 116.522583626035, + -102.149734009655, + 112.650118587972, + -107.825883544914, + 311.543402422187, + 360.780248808368, + -7.42039816792328, + 365.078323407317, + -13.2331839185884, + 344.46378568747, + -54.5546252592288, + 350.335287885457, + -63.572021962256, + 334.342198258035, + -88.749585714325, + 344.281369936645, + -94.7726681838823, + 332.2248206198, + -103.942854393111, + 347.103721199815, + -107.812479611979}; + +const std::vector answer_key_N8 = { + 29266.6517718661, + 9842.93617289812, + 0.0475360674334622, + -0.0160323945316821, + 0.0187557247105805, + -0.000119821248231538, + 79.8612117213119, + -21.0144010498971, + 367.201497494684, + -0.00135963018489767, + 79.8611351716573, + -26.7318789917162, + -0.018074876389402, + 29296.9645459408, + 7415.51099954903, + 0.0471789367393934, + -0.0120180219897291, + 0.0189117902285582, + -8.57914733703415e-05, + 79.2614266664798, + -14.2194852461262, + 370.357116139458, + -0.00065261697325357, + 79.261388452934, + -19.9860446882469, + -0.161178046356866, + 22178.7337755581, + 15750.48869542, + 0.0399575496599213, + -0.028431003000158, + 0.0226540351215628, + -0.000255811047442045, + 62.3338080750298, + -38.6061338491152, + 356.372404460464, + -0.000888421043595241, + 62.3337589017493, + -44.1546192236143, + -0.191206982234175, + 22245.3587939821, + 12476.0312983393, + 0.0395296431152022, + -0.0222832972915751, + 0.0229591349358969, + -0.000195357283522886, + 61.6667253463805, + -28.9363062720176, + 361.284131747149, + 0.000606091049765824, + 61.6667589580497, + -34.5611135316627, + -0.300475535038271, + 22471.354929649, + 17410.9400696732, + 0.0407475331761201, + -0.0316496339533813, + 0.0225047347006168, + -0.000287941144857336, + 63.5662158978541, + -43.6654709736205, + 353.882194971394, + -0.00050508442766251, + 63.5661867600733, + -49.1745383652835, + -0.321406735230742, + 22562.1063953332, + 12532.040739496, + 0.0400730650460856, + -0.0224103188019356, + 0.0229590093469276, + -0.000197040279593967, + 62.5145400797163, + -29.1337602252211, + 361.200953962968, + 0.00123813270414561, + 62.5146115608051, + -34.7565572443792, + -0.398765881347133, + 22822.9625175864, + 17526.9123376124, + 0.0413769691613727, + -0.0318846988884131, + 0.0224996948233429, + -0.000290724959665147, + 64.5480523645119, + -44.0326735095454, + 353.709220392926, + -0.000255137918253834, + 64.548036917491, + -49.5382706457328, + -0.409294621792759, + 22917.4640781459, + 11700.1980576741, + 0.0405370737861658, + -0.0208717910251266, + 0.0230419643488667, + -0.000182321342412399, + 63.2383663569188, + -26.7111380754575, + 362.449323338104, + 0.00143605100750772, + 63.2384503029344, + -32.3525635247183, + -0.460038982115987, + 23175.0870418607, + 17429.0372806116, + 0.0419717095772374, + -0.0317010913432995, + 0.0225145433123769, + -0.000289381352876061, + 65.4757968347883, + -43.7415548084125, + 353.856643943042, + -0.000116590766441278, + 65.4757901489451, + -49.2486679790579, + -0.461848591689221, + 23264.6732405303, + 10919.0360806903, + 0.0409947737541995, + -0.0194331296392293, + 0.0231200668519233, + -0.000168575863901554, + 63.9522672718067, + -24.4455560147541, + 363.621937642842, + 0.00154556746783549, + 63.9523565934322, + -30.1044436917781, + -0.491529580804623, + 23488.6137650364, + 17313.8654584652, + 0.0424952351974662, + -0.0314883547842804, + 0.0225303364455447, + -0.000287714847080755, + 66.2924442955506, + -43.4048501801219, + 354.030311475628, + 0.000169934086992562, + 66.2924545883603, + -48.9139721676174, + -0.486548093474613, + 23557.6136117665, + 10241.0790360359, + 0.0413774884672506, + -0.0181860120867723, + 0.0231877453638413, + -0.000156639599075328, + 64.5492156984859, + -22.4816084883194, + 364.639179755733, + 0.00142420279185394, + 64.5492984953198, + -28.1556597465189, + -0.499726325044563, + 23722.4168131373, + 16958.7765974266, + 0.0428487548646152, + -0.0308090857078185, + 0.0225672437721518, + -0.000281355782039133, + 66.8440182379463, + -42.3350991467661, + 354.562942832682, + 0.000573219240561573, + 66.844044569212, + -47.8519918014414, + -0.490219448053285, + 23769.8747006891, + 9267.5206785042, + 0.0415639300026818, + -0.0164109903099032, + 0.0232814268213158, + -0.000139385907988285, + 64.8399200066663, + -19.6874999818575, + 366.100410278813, + 0.00128332197988872, + 64.8400012051758, + -25.3838027935624, + -0.491586583798841, + 23854.0240861864, + 15160.7060140903, + 0.0427385845553072, + -0.0273659210853948, + 0.0227360281885303, + -0.00024756822257102, + 66.6722121992594, + -36.9193366680176, + 357.260483774461, + 0.000734666517031364, + 66.6722602990682, + -42.4779079553274, + -0.482907936930927, + 23870.5548740189, + 6166.60742794455, + 0.0412253604361869, + -0.0108406830677542, + 0.0235710268609798, + -8.45378382385454e-05, + 64.3117067426907, + -10.9219886629635, + 370.751596332923, + 0.00130490570318174, + 64.3117765573399, + -16.6904284244068, + -2.9267653635869, + 30.5878043390112, + 75.9238910016987, + 9.17392754248112, + 4.3701560041079, + 48.7765765968327, + 58.3101300775815, + 3.13323809951331, + -6.37573932293514, + 46.1701408549949, + 41.9244199648313, + -6.5432868117422, + -17.3691293511209, + 41.8611610718482, + 27.7383173553277, + -12.9709065074016, + -27.5322418670623, + 38.9032728624808, + 16.2733736528389, + -16.5280348065045, + -36.4800564569504, + 37.0627808819117, + 7.38198504755967, + -17.9899033675727, + -44.0731708800056, + 36.9539474625741, + 1.14781892918688, + -15.9507601441003, + -49.1751072411967, + 44.6278268007059, + 82.7517114852138, + -57.3188928805757, + 125.959171148664, + -93.1822145893453, + 110.816672146529, + -108.811406393296, + 99.5107131550674, + -119.104827911048, + 92.0427992280762, + -125.056967118294, + 88.0811872722293, + -127.985464658329, + 87.1649116220972, + -128.957730829954, + 89.0189233593932, + -129.480383815729, + 311.408200092424, + 361.890500304156, + -7.90450151715305, + 365.594288034004, + -14.6504114199963, + 344.278948204657, + -61.517809887448, + 348.104769580715, + -73.1715704285651, + 329.472137794467, + -107.797643650827, + 335.509251816504, + -117.787067889008, + 317.044841017058, + -139.602945170765, + 325.182412285621, + -147.51178633583, + 307.989533967543, + -158.91998673915, + 318.171184823086, + -165.141414351062, + 302.951769665185, + -168.712626964975, + 315.009688292198, + -173.624287308414, + 302.070219389208, + -171.572667424371, + 315.86470341008, + -175.706947618597, + 306.288884765777, + -170.785573848562, + 322.018589824395, + -176.179397251772}; diff --git a/mainpage.dox b/mainpage.dox index 572d450ed..36abc0798 100644 --- a/mainpage.dox +++ b/mainpage.dox @@ -1,60 +1,5 @@ /** * \mainpage * - * \copyright - * 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. * */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 000000000..ffd1613c0 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,11 @@ +# Create component models +add_subdirectory(Model) + +# General Utilities and File IO +add_subdirectory(Utilities) + +# Local Sparse matrix operations +add_subdirectory(LinearAlgebra) + +# Create solvers +add_subdirectory(Solver) diff --git a/src/CircuitGraph.hpp b/src/CircuitGraph.hpp new file mode 100644 index 000000000..26d5d6a2f --- /dev/null +++ b/src/CircuitGraph.hpp @@ -0,0 +1,123 @@ + + +#include +#include +#include +#include +#include + +/** + * @brief A very basic hypergraph setup for circuit representation. + * This forms the hypergraph as a bipartite graph. Doesn't allow + * removing. Can only grab sets of connections to nodes + * + * @todo should replace with something better and more efficent. + * Should replace with a libraries setup instead. This would allow + * fast and easy partitioning of circuits + * + * @todo This is to replace inserting vector size for allocating PowerElectronicsModel + * + * @todo should replace N and E with Node and Component classes respectively. + * + * @note Tested but currently not used in the rest of the code. + * + * @tparam IdxT + * @tparam Label + */ +template +class CircuitGraph +{ +private: + std::set hypernodes; + std::set hyperedges; + std::map> edgestonodes; + +public: + CircuitGraph(); + ~CircuitGraph(); + bool addHyperEdge(E he); + bool addHyperNode(N hn); + bool addConnection(N hn, E he); + std::set getHyperEdgeConnections(E he); + size_t amountHyperNodes(); + size_t amountHyperEdges(); + void printBiPartiteGraph(bool verbose = false); +}; + +template +CircuitGraph::CircuitGraph() +{ +} + +template +CircuitGraph::~CircuitGraph() +{ +} + +template +bool CircuitGraph::addHyperNode(N hn) +{ + return this->hypernodes.insert(hn).second; +} + +template +bool CircuitGraph::addHyperEdge(E he) +{ + return this->hyperedges.insert(he).second; +} + +template +bool CircuitGraph::addConnection(N hn, E he) +{ + if (this->hyperedges.count(he) == 0 || this->hypernodes.count(hn) == 0) + { + return false; + } + return this->edgestonodes[he].insert(hn).second; +} + +template +std::set CircuitGraph::getHyperEdgeConnections(E he) +{ + return this->edgestonodes[he]; +} + +template +size_t CircuitGraph::amountHyperNodes() +{ + return this->hypernodes.size(); +} + +template +size_t CircuitGraph::amountHyperEdges() +{ + return this->hyperedges.size(); +} + +/** + * @brief Print the bipartite graph + * + * @todo need to add verbose printing for connections display + * + * @tparam IdxT + * @param[in] verbose if true will print connections, + * otherwise just the number of nodes and edges + */ + +template +void CircuitGraph::printBiPartiteGraph(bool verbose) +{ + + std::cout << "Amount of HyperNodes: " << this->amountHyperNodes() << std::endl; + std::cout << "Amount of HyperEdges: " << this->amountHyperEdges() << std::endl; + std::cout << "Connections per Edge:" << std::endl; + for (auto i : this->edgestonodes) + { + std::cout << i.first << " : {"; + for (auto j : i.second) + { + std::cout << j << ", "; + } + std::cout << "}\n"; + } +} diff --git a/src/LinearAlgebra/CMakeLists.txt b/src/LinearAlgebra/CMakeLists.txt new file mode 100644 index 000000000..d290617be --- /dev/null +++ b/src/LinearAlgebra/CMakeLists.txt @@ -0,0 +1,3 @@ + +add_subdirectory(SparseMatrix) +add_subdirectory(DenseMatrix) diff --git a/src/LinearAlgebra/DenseMatrix/CMakeLists.txt b/src/LinearAlgebra/DenseMatrix/CMakeLists.txt new file mode 100644 index 000000000..6b555da41 --- /dev/null +++ b/src/LinearAlgebra/DenseMatrix/CMakeLists.txt @@ -0,0 +1,5 @@ + +add_library(DenseMatrix INTERFACE) +include_directories(DenseMatrix INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +add_library(GRIDKIT::DenseMatrix ALIAS DenseMatrix) diff --git a/src/LinearAlgebra/DenseMatrix/DenseMatrix.hpp b/src/LinearAlgebra/DenseMatrix/DenseMatrix.hpp new file mode 100644 index 000000000..264689d6a --- /dev/null +++ b/src/LinearAlgebra/DenseMatrix/DenseMatrix.hpp @@ -0,0 +1,229 @@ +#pragma once + +#include +#include +#include +#include + +#include + +/** + * @brief Class to provide dense matrices. + * + * This is intended for small matrices that store model Jacobians to be subsequently copied + * into large sparse matrices. + */ +namespace GridKit +{ + namespace LinearAlgebra + { + template + class DenseMatrix + { + private: + IdxT rows_size_; + IdxT columns_size_; + std::vector values_; + COO_Matrix values_COO_; + bool values_changed_ = false; + bool sparsified_ = false; + + public: + // Constructors and destructors + DenseMatrix(const IdxT rows_size, const IdxT columns_size); + ~DenseMatrix(); + + // Getters and setters + ScalarT getValue(const IdxT i, const IdxT j) const; + void setValue(const IdxT i, const IdxT j, const ScalarT value); + void setValues(COO_Matrix values_COO); + std::vector* getValues(); + COO_Matrix* getValuesCOO(); + + // Utilities + void toCOO(); + void printMatrix(std::string name = ""); + + // Purposefully not defining BLAS operations. This class should not be used + // for compute. + }; + + /** + * @brief DenseMatrix constructor + * + * @tparam ScalarT + * @tparam IdxT + * + * @param[in] IdxT - rows_size + * @param[in] IdxT - columns_size + */ + template + DenseMatrix::DenseMatrix(const IdxT rows_size, const IdxT columns_size) + : rows_size_(rows_size), + columns_size_(columns_size), + values_(rows_size * columns_size, 0), + values_COO_(rows_size, columns_size) + { + } + + /** + * @brief DenseMatrix single value getter + * + * @tparam ScalarT + * @tparam IdxT + * + * @param[in] IdxT - i row index + * @param[in] IdxT - j column index + * @return ScalarT - value + */ + template + inline ScalarT DenseMatrix::getValue(const IdxT i, const IdxT j) const + { + assert(i < this->columns_size_); + assert(j < this->rows_size_); + return this->values_[j * rows_size_ + i]; + } + + /** + * @brief DenseMatrix single value setter + * + * @tparam ScalarT + * @tparam IdxT + * + * @param[in] IdxT - i row index + * @param[in] IdxT - j column index + * @param[in] ScalarT - value + */ + template + inline void DenseMatrix::setValue(const IdxT i, const IdxT j, const ScalarT value) + { + assert(i < this->columns_size_); + assert(j < this->rows_size_); + this->values_[j * rows_size_ + i] = value; + values_changed_ = true; + } + + /** + * @brief DenseMatrix value setter from COO + * + * @tparam ScalarT + * @tparam IdxT + * + * @param[in] COO_Matrix - values_COO + */ + template + inline void DenseMatrix::setValues(COO_Matrix values_COO) + { + std::tuple&, std::vector&, std::vector&> entries = values_COO.getEntries(); + const auto [rcord, ccord, vals] = entries; + for (IdxT idx = 0; idx < values_COO.nnz(); ++idx) + { + this->setValue(rcord[idx], ccord[idx], vals[idx]); + } + } + + /** + * @brief DenseMatrix getter for all values stored as a vector + * + * @tparam ScalarT + * @tparam IdxT + * + * @return Address of the vector containing matrix values + */ + template + inline std::vector* DenseMatrix::getValues() + { + return &(this->values_); + } + + /** + * @brief DenseMatrix getter for all values stored as a COO sparse matrix + * + * @tparam ScalarT + * @tparam IdxT + * + * @return Address of the COO matrix containing the sparsified matrix values + */ + template + inline COO_Matrix* DenseMatrix::getValuesCOO() + { + if (!sparsified_ || values_changed_) + { + this->toCOO(); + } + return &(this->values_COO_); + } + + /** + * @brief Dense matrix conversion to COO form + * + * @tparam ScalarT + * @tparam IdxT + */ + template + inline void DenseMatrix::toCOO() + { + if (!sparsified_ || values_changed_) + { + IdxT nnz = 0; + std::vector rcord; + std::vector ccord; + std::vector vals; + for (IdxT j = 0; j < this->columns_size_; ++j) + { + for (IdxT i = 0; i < this->rows_size_; ++i) + { + ScalarT value = this->values_[j * rows_size_ + i]; + if (std::abs(value) > std::numeric_limits::epsilon()) + { + nnz++; + rcord.push_back(i); + ccord.push_back(j); + vals.push_back(value); + } + } + } + values_COO_.setValues(rcord, ccord, vals); + sparsified_ = true; + values_changed_ = false; + } + } + + /** + * @brief Print matrix + * + * @tparam ScalarT + * @tparam IdxT + * + * @param[in] name to identify the specific matrix printed + */ + template + inline void DenseMatrix::printMatrix(std::string name) + { + std::cout << "Dense matrix: " << name << "\n"; + for (IdxT i = 0; i < this->rows_size_; ++i) + { + for (IdxT j = 0; j < this->columns_size_; ++j) + { + std::cout << this->values_[j * rows_size_ + i] << " "; + } + std::cout << "\n"; + } + } + + /** + * @brief DenseMatrix destructor + * + * @tparam ScalarT + * @tparam IdxT + */ + template + DenseMatrix::~DenseMatrix() + { + } + + // Available template instantiations + template class DenseMatrix; + + } // namespace LinearAlgebra +} // namespace GridKit diff --git a/src/LinearAlgebra/SparseMatrix/CMakeLists.txt b/src/LinearAlgebra/SparseMatrix/CMakeLists.txt new file mode 100644 index 000000000..e92b5d190 --- /dev/null +++ b/src/LinearAlgebra/SparseMatrix/CMakeLists.txt @@ -0,0 +1,5 @@ + +add_library(SparseMatrix INTERFACE) +include_directories(SparseMatrix INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +add_library(GRIDKIT::SparseMatrix ALIAS SparseMatrix) diff --git a/src/LinearAlgebra/SparseMatrix/COO_Matrix.hpp b/src/LinearAlgebra/SparseMatrix/COO_Matrix.hpp new file mode 100644 index 000000000..33d28324e --- /dev/null +++ b/src/LinearAlgebra/SparseMatrix/COO_Matrix.hpp @@ -0,0 +1,880 @@ +#ifndef COO_MATRIX_HPP +#define COO_MATRIX_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief Quick class to provide sparse matrices of COO type. + * + * Simplifies data movement + * + * @todo add functionality to keep track of multiple sorted lists. Faster + * adding of new entries and will have a threshold to sort completely. + * + * m x n sparse matrix + */ +template +class COO_Matrix +{ +private: + std::vector values_; + std::vector row_indices_; + std::vector column_indices_; + IdxT rows_size_; + IdxT columns_size_; + bool sorted_; + +public: + // Constructors + COO_Matrix(std::vector r, std::vector c, std::vector v, IdxT m, IdxT n); + COO_Matrix(IdxT m, IdxT n); + COO_Matrix(); + ~COO_Matrix(); + + // Operations + + // --- Functions which call sort --- + std::tuple, std::vector> getRowCopy(IdxT r); + std::tuple&, std::vector&, std::vector&> getEntries(); + std::tuple, std::vector, std::vector> getEntryCopies(); + std::tuple, std::vector, std::vector> getEntryCopiesSubMatrix(std::vector submap); + + std::tuple, std::vector, std::vector> setDataToCSR(); + std::vector getCSRRowData(); + + // BLAS. Will sort before running + void setValues(std::vector r, std::vector c, std::vector v); + void axpy(ScalarT alpha, COO_Matrix& a); + void axpy(ScalarT alpha, std::vector r, std::vector c, std::vector v); + void scal(ScalarT alpha); + ScalarT frobNorm(); + + // --- Permutation Operations --- + // Sorting is only done if not already sorted. + void permutation(std::vector row_perm, std::vector col_perm); + void permutationSizeMap(std::vector row_perm, std::vector col_perm, IdxT m, IdxT n); + + void zeroMatrix(); + + void identityMatrix(IdxT n); + + // Resort values_ + void sortSparse(); + bool isSorted(); + IdxT nnz(); + + std::tuple getDimensions(); + + void printMatrix(std::string name = ""); + + static void sortSparseCOO(std::vector& rows, std::vector& columns, std::vector& values); + +private: + IdxT indexStartRow(const std::vector& rows, IdxT r); + IdxT sparseCordBinarySearch(const std::vector& rows, const std::vector& columns, IdxT ri, IdxT ci); + bool checkIncreaseSize(IdxT r, IdxT c); +}; + +/** + * @brief Get copy of row index + * + * @tparam ScalarT + * @tparam IdxT + * @param[in] r row index + * @return std::tuple, std::vector> + */ +template +inline std::tuple, std::vector> COO_Matrix::getRowCopy(IdxT r) +{ + if (!this->sorted_) + { + this->sortSparse(); + } + IdxT row_index = this->indexStartRow(r); + + if (row_index == -1) + { + return {std::vector(), std::vector()}; + } + + IdxT rsize = row_index; + do + { + rsize++; + } while (rsize < this->values_.size() && this->row_indices_[rsize] == r); + + return {{this->column_indices_.begin() + row_index, this->column_indices_.begin() + rsize}, + {this->values_.begin() + row_index, this->values_.begin() + rsize}}; +} + +/** + * @brief Get all entry pointers. Will sort before returning + * + * @tparam ScalarT + * @tparam IdxT + * @return std::tuple, std::vector, std::vector> + */ +template +inline std::tuple&, std::vector&, std::vector&> COO_Matrix::getEntries() +{ + if (!this->sorted_) + { + this->sortSparse(); + } + return {this->row_indices_, this->column_indices_, this->values_}; +} + +/** + * @brief Sorts the data if it's not already sorted + * + * @tparam ScalarT + * @tparam IdxT + * @return std::tuple, std::vector, std::vector> + */ +template +inline std::tuple, std::vector, std::vector> COO_Matrix::getEntryCopies() +{ + if (!this->sorted_) + { + this->sortSparse(); + } + return {this->row_indices_, this->column_indices_, this->values_}; +} + +/** + * @brief Returns the data in CSR Format + * + * @tparam ScalarT + * @tparam IdxT + * @return std::tuple, std::vector, std::vector> + */ +template +inline std::tuple, std::vector, std::vector> COO_Matrix::setDataToCSR() +{ + if (!this->isSorted()) + this->sortSparse(); + std::vector row_size_vec(this->rows_size_ + 1, 0); + IdxT counter = 0; + for (IdxT i = 0; i < static_cast(row_size_vec.size() - 1); i++) + { + row_size_vec[i + 1] = row_size_vec[i]; + while (counter < static_cast(this->row_indices_.size()) && i == this->row_indices_[counter]) + { + row_size_vec[i + 1]++; + counter++; + } + } + return {row_size_vec, this->column_indices_, this->values_}; +} + +/** + * @brief Only creates the row data + * + * @todo swap this with having the matrix store the data and updates. This can then be passed by reference + * + * + * @tparam ScalarT + * @tparam IdxT + * @return std::vector + */ +template +inline std::vector COO_Matrix::getCSRRowData() +{ + if (!this->isSorted()) + this->sortSparse(); + std::vector row_size_vec(this->rows_size_ + 1, 0); + IdxT counter = 0; + for (IdxT i = 0; i < static_cast(row_size_vec.size() - 1); i++) + { + row_size_vec[i + 1] = row_size_vec[i]; + while (counter < static_cast(this->row_indices_.size()) && i == this->row_indices_[counter]) + { + row_size_vec[i + 1]++; + counter++; + } + } + return row_size_vec; +} + +/** + * @brief Set coordinates and values of the matrix. + * + * Matrix entries will be sorted in row-major order before the method returns. + * + * @tparam ScalarT + * @tparam IdxT + * @param[in] r row indices of the matrix + * @param[in] c column indices of the matrix + * @param[in] v values of the matrix + * + * @pre r.size() == c.size() == v.size() + * @pre r,c,v represent an array in COO format + * + * @post Coordinates and values are set in the matrix. + */ +template +inline void COO_Matrix::setValues(std::vector r, std::vector c, std::vector v) +{ + // sort input + this->sortSparseCOO(r, c, v); + + // Duplicated with axpy. Could replace with function depdent on lambda expression + IdxT a_iter = 0; + // iterate for all current values_ in matrix + for (IdxT i = 0; i < static_cast(this->row_indices_.size()); i++) + { + // pushback values_ when they are not in current matrix + while (a_iter < static_cast(r.size()) && (r[a_iter] < this->row_indices_[i] || (r[a_iter] == this->row_indices_[i] && c[a_iter] < this->column_indices_[i]))) + { + this->row_indices_.push_back(r[a_iter]); + this->column_indices_.push_back(c[a_iter]); + this->values_.push_back(v[a_iter]); + this->checkIncreaseSize(r[a_iter], c[a_iter]); + a_iter++; + } + if (a_iter >= static_cast(r.size())) + { + break; + } + + if (r[a_iter] == this->row_indices_[i] && c[a_iter] == this->column_indices_[i]) + { + this->values_[i] = v[a_iter]; + a_iter++; + } + } + // push back rest that was not found sorted + for (IdxT i = a_iter; i < static_cast(r.size()); i++) + { + this->row_indices_.push_back(r[i]); + this->column_indices_.push_back(c[i]); + this->values_.push_back(v[i]); + + this->checkIncreaseSize(r[i], c[i]); + } + + this->sorted_ = false; +} + +/** + * @brief Implements axpy this += alpha * a. Will sort before running + * + * @tparam ScalarT + * @tparam IdxT + * @param[in] alpha matrix to be added + * @param[in] a scalar to multiply by + * + * @post this = this + alpha * a + */ +template +inline void COO_Matrix::axpy(ScalarT alpha, COO_Matrix& a) +{ + if (alpha == 0) + { + return; + } + + if (!this->sorted_) + { + this->sortSparse(); + } + if (!a.isSorted()) + { + a.sortSparse(); + } + IdxT m = 0; + IdxT n = 0; + std::tuple&, std::vector&, std::vector&> tpm = a.getEntries(); + const auto& [r, c, val] = tpm; + std::tie(m, n) = a.getDimensions(); + + // Increase size as necessary + this->rows_size_ = this->rows_size_ > m ? this->rows_size_ : m; + this->columns_size_ = this->columns_size_ > n ? this->columns_size_ : n; + + IdxT a_iter = 0; + // iterate for all current values in matrix + for (IdxT i = 0; i < static_cast(this->row_indices_.size()); i++) + { + // pushback values when they are not in current matrix + while (a_iter < static_cast(r.size()) && (r[a_iter] < this->row_indices_[i] || (r[a_iter] == this->row_indices_[i] && c[a_iter] < this->column_indices_[i]))) + { + this->row_indices_.push_back(r[a_iter]); + this->column_indices_.push_back(c[a_iter]); + this->values_.push_back(alpha * val[a_iter]); + + this->checkIncreaseSize(r[a_iter], c[a_iter]); + a_iter++; + } + if (a_iter >= static_cast(r.size())) + { + break; + } + + if (r[a_iter] == this->row_indices_[i] && c[a_iter] == this->column_indices_[i]) + { + this->values_[i] += alpha * val[a_iter]; + a_iter++; + } + } + // push back rest that was not found sorted_ + for (IdxT i = a_iter; i < static_cast(r.size()); i++) + { + this->row_indices_.push_back(r[i]); + this->column_indices_.push_back(c[i]); + this->values_.push_back(alpha * val[i]); + + this->checkIncreaseSize(r[i], c[i]); + } + + this->sorted_ = false; +} + +/** + * @brief axpy on a COO representation of a matrix. Will sort before running + * + * @tparam ScalarT + * @tparam IdxT + * @param alpha scalar to multiply by + * @param r row indices + * @param c column indices + * @param v values + * + * @pre r.size() == c.size() == v.size() + * @pre r,c,v represent an array a in COO format + * + * @post this = this + alpha * a + */ +template +inline void COO_Matrix::axpy(ScalarT alpha, std::vector r, std::vector c, std::vector v) +{ + if (alpha == 0) + return; + + if (!this->sorted_) + { + this->sortSparse(); + } + + // sort input + this->sortSparseCOO(r, c, v); + + IdxT a_iter = 0; + // iterate for all current values_ in matrix + for (IdxT i = 0; i < static_cast(this->row_indices_.size()); i++) + { + // pushback values_ when they are not in current matrix + while (a_iter < static_cast(r.size()) && (r[a_iter] < this->row_indices_[i] || (r[a_iter] == this->row_indices_[i] && c[a_iter] < this->column_indices_[i]))) + { + this->row_indices_.push_back(r[a_iter]); + this->column_indices_.push_back(c[a_iter]); + this->values_.push_back(alpha * v[a_iter]); + + this->checkIncreaseSize(r[a_iter], c[a_iter]); + a_iter++; + } + if (a_iter >= static_cast(r.size())) + { + break; + } + + if (r[a_iter] == this->row_indices_[i] && c[a_iter] == this->column_indices_[i]) + { + this->values_[i] += alpha * v[a_iter]; + a_iter++; + } + } + // push back rest that was not found sorted_ + for (IdxT i = a_iter; i < static_cast(r.size()); i++) + { + this->row_indices_.push_back(r[i]); + this->column_indices_.push_back(c[i]); + this->values_.push_back(alpha * v[i]); + + this->checkIncreaseSize(r[i], c[i]); + } + + this->sorted_ = false; +} + +/** + * @brief Scale all values by alpha + * + * @tparam ScalarT + * @tparam IdxT + * @param[in] alpha scalar to scale by + */ +template +inline void COO_Matrix::scal(ScalarT alpha) +{ + for (auto i = this->values_.begin(); i < this->values_.end(); i++) + { + *i *= alpha; + } +} + +/** + * @brief Calculates the Frobenius Norm of the matrix + * + * @tparam ScalarT + * @tparam IdxT + * @return ScalarT - Frobenius Norm of the matrix + */ +template +inline ScalarT COO_Matrix::frobNorm() +{ + ScalarT totsum = 0.0; + for (auto i = this->values_.begin(); i < this->values_.end(); i++) + { + totsum += abs(*i) ^ 2; + } + return totsum; +} + +/** + * @brief Permutate the matrix to a different one. Only changes the coordinates + * + * @tparam ScalarT + * @param[in] row_perm + * @param[out] col_perm + * + * @pre row_perm.size() == this->rows_size_ = col_perm.size() == this->columns_size_ + * + * @post this = this(row_perm, col_perm) + */ +template +inline void COO_Matrix::permutation(std::vector row_perm, std::vector col_perm) +{ + assert(row_perm.size() = this->rows_size_); + assert(col_perm.size() = this->columns_size_); + + for (int i = 0; i < this->values_.size(); i++) + { + this->row_indices_[i] = row_perm[this->row_indices_[i]]; + this->column_indices_[i] = col_perm[this->column_indices_[i]]; + } + this->sorted_ = false; + // cycle sorting maybe useful since permutations are already known +} + +/** + * @brief Permutes the matrix and can change its size efficently + * + * @tparam ScalarT + * @tparam IdxT + * @param[in] row_perm row permutation + * @param[in] col_perm column permutation + * @param[in] m number of rows + * @param[in] n number of columns + * + * @pre row_perm.size() == this->rows_size_ + * @pre col_perm.size() == this->columns_size_ + * @pre indices are set to -1 if they are to be removed + * + * @post this = this(row_perm, col_perm) and removed indices have corresponding values set to 0 + */ +template +inline void COO_Matrix::permutationSizeMap(std::vector row_perm, std::vector col_perm, IdxT m, IdxT n) +{ + assert(row_perm.size() == this->rows_size_); + assert(col_perm.size() == this->columns_size_); + + this->rows_size_ = m; + this->columns_size_ = n; + + for (int i = 0; i < this->values_.size(); i++) + { + if (row_perm[this->row_indices_[i]] == -1 || col_perm[this->column_indices_[i]] == -1) + { + this->values_[i] = 0; + } + else + { + this->row_indices_[i] = row_perm[this->row_indices_[i]]; + this->column_indices_[i] = col_perm[this->column_indices_[i]]; + } + } + this->sorted_ = false; +} + +/** + * @brief Turn matrix into the zero matrix. Does not actually delete memory + * + * @tparam ScalarT + * @tparam IdxT + * + */ +template +inline void COO_Matrix::zeroMatrix() +{ + // resize doesn't effect capacity if smaller + this->column_indices_.resize(0); + this->row_indices_.resize(0); + this->values_.resize(0); + this->sorted_ = true; +} + +/** + * @brief Turn matrix into the identity matrix + * + * @tparam ScalarT + * @tparam IdxT + * + * @param[in] n size of the identity matrix + * + * @post this = I_n + * + * @todo - it might be better to explicitly zero out the matrix and require to be so in preconditions + */ + +template +inline void COO_Matrix::identityMatrix(IdxT n) +{ + // Reset Matrix + this->zeroMatrix(); + for (IdxT i = 0; i < n; i++) + { + this->column_indices_[i] = i; + this->row_indices_[i] = i; + this->values_[i] = 1.0; + } + this->sorted_ = true; +} + +/** + * @brief Restructure the sparse matrix for faster accesses and modifications + * + * @tparam ScalarT + * @tparam IdxT + */ +template +inline void COO_Matrix::sortSparse() +{ + this->sortSparseCOO(this->row_indices_, this->column_indices_, this->values_); + this->sorted_ = true; +} + +/** + * @brief Check if the matrix is sorted + * + * @tparam ScalarT + * @tparam IdxT + * + * @param[out] bool - true if sorted, false otherwise + */ + +template +inline bool COO_Matrix::isSorted() +{ + return this->sorted_; +} + +/** + * @brief Get the number of non-zero elements in the matrix + * + * @tparam ScalarT + * @tparam IdxT + * + * @param[out] IdxT - number of non-zero elements in the matrix + */ +template +inline IdxT COO_Matrix::nnz() +{ + return static_cast(this->values_.size()); +} + +template +inline std::tuple COO_Matrix::getDimensions() +{ + return std::tuple(this->rows_size_, this->columns_size_); +} + +/** + * @brief Print matrix in sorted order + * + * @tparam ScalarT + * @tparam IdxT + * + * @param[in] name to identify the specific matrix printed + */ +template +inline void COO_Matrix::printMatrix(std::string name) +{ + if (this->sorted_ == false) + { + this->sortSparse(); + } + + std::cout << "Sparse COO Matrix: " << name << "\n"; + std::cout << "(x , y, value)\n"; + for (size_t i = 0; i < this->values_.size(); i++) + { + std::cout << "(" << this->row_indices_[i] + << ", " << this->column_indices_[i] + << ", " << this->values_[i] << ")\n"; + } + std::cout << std::flush; +} + +/** + * @brief Find the lowest row cordinate from set of provided coordinates + * + * Assumes rows and columns are sorted + * @tparam ScalarT + * @tparam IdxT + * + * @param[in] rows - row indices + * @param[in] r - row index + * + * @return IdxT - index of lowest row + */ +template +inline IdxT COO_Matrix::indexStartRow(const std::vector& rows, IdxT r) +{ + // Specialized Binary Search for Lowest Row + IdxT i1 = 0; + IdxT i2 = rows->size() - 1; + IdxT m_smallest = -1; + IdxT m = -1; + while (i1 <= i2) + { + m = (i2 + i1) / 2; + // rows + if (rows[m] < r) + { + i1 = m + 1; + } + else if (r < rows[m]) + { + i2 = m - 1; + } + else + { + if (i1 == i2) + { + return m_smallest; + } + + // Keep track of smallest cordinate + m_smallest = m; + i2 = m - 1; + } + } + return m_smallest; +} + +/** + * @brief Basic binary search + * + * @tparam ScalarT + * @tparam IdxT + * @param[in] rows - row indices + * @param[in] columns - column indices + * @param[in] ri - row index + * @param[in] ci - column index + * @return IdxT - returns the index of the coordinate + */ +template +inline IdxT COO_Matrix::sparseCordBinarySearch(const std::vector& rows, const std::vector& columns, IdxT ri, IdxT ci) +{ + assert(rows.size() == columns.size()); + // basic binary search + IdxT i1 = 0; + IdxT i2 = rows.size() - 1; + IdxT m = 0; + while (i1 <= i2) + { + m = (i2 + i1) / 2; + // rows + if (rows[m] < ri) + { + i1 = m + 1; + } + else if (ri < rows[m]) + { + i2 = m - 1; + } + else + { + if (columns[m] < ci) + { + i1 = m + 1; + } + else if (ci < columns[m]) + { + i2 = m - 1; + } + break; + } + } + + return m; +} + +/** + * @brief Check if the size of the matrix needs to be increased + * + * @tparam ScalarT + * @tparam IdxT + * @param[in] r row index + * @param[in] c column index + * @return true if size was increased + */ + +template +inline bool COO_Matrix::checkIncreaseSize(IdxT r, IdxT c) +{ + bool changed = false; + if (r + 1 > this->rows_size_) + { + this->rows_size_ = r + 1; + changed = true; + } + if (c + 1 > this->columns_size_) + { + this->columns_size_ = c + 1; + changed = true; + } + + return changed; +} + +/** + * @brief Sorts unordered COO matrix + * + * Matrix entries can appear in arbitrary order and will be sorted in + * row-major order before the method returns. + * Duplicate entries are not allowed and should be pre-summed. + * + * @pre rows, columns, and values are of the same size and represent a COO matrix with no duplicates + * @post Matrix entries are sorted in row-major order + * + * @todo simple setup. Should add stable sorting since lists are pre-sorted_ + * + * @tparam ScalarT + * @tparam IdxT + * @param rows + * @param columns + * @param values + */ +template +inline void COO_Matrix::sortSparseCOO(std::vector& rows, std::vector& columns, std::vector& values) +{ + + // index based sort code + // https://stackoverflow.com/questions/25921706/creating-a-vector-of-indices-of-a-sorted_-vector + // cannot call sort since two arrays are used instead + std::vector ordervec(rows.size()); + std::size_t n(0); + std::generate(std::begin(ordervec), std::end(ordervec), [&] + { return n++; }); + + // Sort by row first then column. + std::sort(std::begin(ordervec), + std::end(ordervec), + [&](int i1, int i2) + { return (rows[i1] < rows[i2]) || (rows[i1] == rows[i2] && columns[i1] < columns[i2]); }); + + // reorder based of index-sorting. Only swap cost no extra memory. + // @todo see if extra memory creation is fine + // https://stackoverflow.com/a/22183350 + for (size_t i = 0; i < ordervec.size(); i++) + { + // permutation swap + while (ordervec[i] != ordervec[ordervec[i]]) + { + std::swap(rows[ordervec[i]], rows[ordervec[ordervec[i]]]); + std::swap(columns[ordervec[i]], columns[ordervec[ordervec[i]]]); + std::swap(values[ordervec[i]], values[ordervec[ordervec[i]]]); + + // swap orderings + std::swap(ordervec[i], ordervec[ordervec[i]]); + } + } +} + +/** + * @brief Constructor for COO Matrix with given cooridnates and values + * + * @tparam ScalarT + * @tparam IdxT + * + * @param[in] r row indices + * @param[in] c column indices + * @param[in] v values + * @param[in] m number of rows + * @param[in] n number of columns + * + * @pre r.size() == c.size() == v.size() + * @pre r,c,v represent an array in COO format + * + * @post COO_Matrix is created with given coordinates and values + */ + +template +inline COO_Matrix::COO_Matrix(std::vector r, std::vector c, std::vector v, IdxT m, IdxT n) +{ + this->values_ = v; + this->row_indices_ = r; + this->column_indices_ = c; + this->rows_size_ = m; + this->columns_size_ = n; + this->sorted_ = false; // Set to false until explicitly sorted, though logically it is sorted. +} + +/** + * @brief Constructor for empty COO Matrix of a given size + * + * @tparam ScalarT + * @tparam IdxT + * + * @param[in] m number of rows + * @param[in] n number of columns + * + * @post empty COO Matrix is created with given size + */ + +template +inline COO_Matrix::COO_Matrix(IdxT m, IdxT n) +{ + this->rows_size_ = m; + this->columns_size_ = n; + this->values_ = std::vector(); + this->row_indices_ = std::vector(); + this->column_indices_ = std::vector(); + this->sorted_ = false; // Set to false until explicitly sorted, though logically it is sorted. +} + +/** + * @brief Constructor for empty COO Matrix of size 0 + * + * @tparam ScalarT + * @tparam IdxT + * + * @post empty COO Matrix of size 0 is created + */ + +template +inline COO_Matrix::COO_Matrix() +{ + this->rows_size_ = 0; + this->columns_size_ = 0; + this->values_ = std::vector(); + this->row_indices_ = std::vector(); + this->column_indices_ = std::vector(); + this->sorted_ = false; // Set to false until explicitly sorted, though logically it is sorted. +} + +template +COO_Matrix::~COO_Matrix() +{ +} + +#endif diff --git a/src/LinearAlgebra/SparsityPattern/Variable.hpp b/src/LinearAlgebra/SparsityPattern/Variable.hpp new file mode 100644 index 000000000..4015f65af --- /dev/null +++ b/src/LinearAlgebra/SparsityPattern/Variable.hpp @@ -0,0 +1,330 @@ +/** + \file Variable.hpp +*/ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace GridKit +{ + namespace Sparse + { + + /** + @brief The Variable class is used to store the unknowns of the + system and define abstract elementary algebra. + + \author Stefan Klus + \author Slaven Peles + */ + class Variable + { + public: + /** + @brief Default constructor. + */ + Variable() + : value_(0.0), + variable_number_(INVALID_VAR_NUMBER), + is_fixed_(false), + dependencies_(new DependencyMap) + { + } + + /** + @brief Constructor which initializes the value. + */ + explicit Variable(double value) + : value_(value), + variable_number_(INVALID_VAR_NUMBER), + is_fixed_(false), + dependencies_(new DependencyMap) + { + } + + /** + @brief Constructor which initializes the value and variable + number. + + */ + Variable(double value, size_t variable_number) + : value_(value), + variable_number_(variable_number), + is_fixed_(false), + dependencies_(new DependencyMap) + { + (*dependencies_)[variable_number_] = 1.0; + } + + /** + @brief Copy constructor. + */ + Variable(const Variable& v) + : value_(v.value_), + variable_number_(INVALID_VAR_NUMBER), + is_fixed_(false), + dependencies_(new DependencyMap(*v.dependencies_)) + { + } + + /** + @brief Destructor deletes the dependency map. + */ + ~Variable() + { + delete dependencies_; + } + + /** + @brief Assignment operator. Assigning double value to + Variable removes its dependencies. Use only if you know + what you are doing. + */ + Variable& operator=(const double& rhs) + { + value_ = rhs; + + dependencies_->clear(); + return *this; + } + + /** + @brief Assignment operator. + + This operator: + - assigns value from the right hand side + - leaves variable ID unchanged + - clears any existing and adds new dependencies from rhs + */ + Variable& operator=(const Variable& rhs) + { + if (this == &rhs) // self-assignment + return *this; + + // set value from rhs + value_ = rhs.value_; + + // if rhs is a constant so is *this + setFixed(rhs.is_fixed()); + + // set dependencies from rhs + dependencies_->clear(); // clear map just in case + addDependencies(rhs); // use only dependencies from the rhs + + return *this; + } + + /** + @brief Operator () returns the value of a variable. + + This is just short notation to avoid using + getValue and setValue. + */ + double& operator()() + { + return value_; + } + + /** + @brief Operator() returns the value of a variable + (const version). + + This is just short notation to avoid using getValue. + */ + const double& operator()() const + { + return value_; + } + + /** + @brief Return the current value of the variable. + */ + double getValue() const + { + return value_; + } + + /** + @brief Overwrite the current value of the variable. + */ + void setValue(double value) + { + value_ = value; + } + + /** + @brief Return derivative of *this with respect to + dependency i. + */ + double der(size_t i) const + { + return (*dependencies_)[i]; + } + + /** + @brief Returns the variable number. + + This number is assigned to state variables (variables + updated directly by the solver) only. + */ + size_t getVariableNumber() const + { + return variable_number_; + } + + /** + @brief Sets the variable number. + */ + void setVariableNumber(size_t variable_number) + { + dependencies_->clear(); + variable_number_ = variable_number; + (*dependencies_)[variable_number_] = 1.0; + } + + /** + @brief Checks whether the variable was registered as + an unknown of the system. + + INVALID_VAR_NUMBER is used to mark parameters and + temporary variables + */ + bool isRegistered() const + { + return variable_number_ != INVALID_VAR_NUMBER; + } + + /** + @brief Checks whether the variable is fixed or not. + */ + bool is_fixed() const + { + return is_fixed_; + } + + /** + @brief Turns variable into parameter, or vice versa. + */ + void setFixed(bool b = false) + { + is_fixed_ = b; + } + + // get the 'input set' of a variable + using DependencyMap = std::map; + inline const DependencyMap& getDependencies() const; + + // set as the independent state variable and assign ID to it + inline void registerVariable(std::vector& x, + const size_t& offset); + + // adds all dependencies of v to *this + inline void addDependencies(const Variable& v); + + // scale dependencies (derivatives) by scalar @a c. + inline void scaleDependencies(double c); + + // print to output stream + inline void print(std::ostream& os) const; + + // += + inline Variable& operator+=(const double& rhs); + inline Variable& operator+=(const Variable& rhs); + + // -= + inline Variable& operator-=(const double& rhs); + inline Variable& operator-=(const Variable& rhs); + + // *= + inline Variable& operator*=(const double& rhs); + inline Variable& operator*=(const Variable& rhs); + + // /= + inline Variable& operator/=(const double& rhs); + inline Variable& operator/=(const Variable& rhs); + + private: + double value_; ///< Value of the variable. + size_t variable_number_; ///< Independent variable ID + bool is_fixed_; ///< Constant parameter flag. + + mutable DependencyMap* dependencies_; + static const size_t INVALID_VAR_NUMBER = static_cast(-1); + }; + + //------------------------------------ + // non-member operators and functions + //------------------------------------ + + // unary - + inline const Variable operator-(const Variable& v); + + // + + inline const Variable operator+(const Variable& lhs, const Variable& rhs); + inline const Variable operator+(const Variable& lhs, const double& rhs); + inline const Variable operator+(const double& lhs, const Variable& rhs); + + // - + inline const Variable operator-(const Variable& lhs, const Variable& rhs); + inline const Variable operator-(const Variable& lhs, const double& rhs); + inline const Variable operator-(const double& lhs, const Variable& rhs); + + // * + inline const Variable operator*(const Variable& lhs, const Variable& rhs); + inline const Variable operator*(const Variable& lhs, const double& rhs); + inline const Variable operator*(const double& lhs, const Variable& rhs); + + // / + inline const Variable operator/(const Variable& lhs, const Variable& rhs); + inline const Variable operator/(const Variable& lhs, const double& rhs); + inline const Variable operator/(const double& lhs, const Variable& rhs); + + // == + inline bool operator==(const Variable& lhs, const Variable& rhs); + inline bool operator==(const Variable& lhs, const double& rhs); + inline bool operator==(const double& lhs, const Variable& rhs); + + // != + inline bool operator!=(const Variable& lhs, const Variable& rhs); + inline bool operator!=(const Variable& lhs, const double& rhs); + inline bool operator!=(const double& lhs, const Variable& rhs); + + // < + inline bool operator<(const Variable& lhs, const Variable& rhs); + inline bool operator<(const Variable& lhs, const double& rhs); + inline bool operator<(const double& lhs, const Variable& rhs); + + // > + inline bool operator>(const Variable& lhs, const Variable& rhs); + inline bool operator>(const Variable& lhs, const double& rhs); + inline bool operator>(const double& lhs, const Variable& rhs); + + // <= + inline bool operator<=(const Variable& lhs, const Variable& rhs); + inline bool operator<=(const Variable& lhs, const double& rhs); + inline bool operator<=(const double& lhs, const Variable& rhs); + + // >= + inline bool operator>=(const Variable& lhs, const Variable& rhs); + inline bool operator>=(const Variable& lhs, const double& rhs); + inline bool operator>=(const double& lhs, const Variable& rhs); + + inline std::ostream& operator<<(std::ostream& os, const Variable& v); + inline Variable& operator<<(Variable& u, const Variable& v); + + inline std::istream& operator>>(std::istream& is, Variable& v); + + } // namespace Sparse +} // namespace GridKit + +#include "VariableImplementation.hpp" +#include "VariableOperators.hpp" diff --git a/src/LinearAlgebra/SparsityPattern/VariableImplementation.hpp b/src/LinearAlgebra/SparsityPattern/VariableImplementation.hpp new file mode 100644 index 000000000..30661e4b6 --- /dev/null +++ b/src/LinearAlgebra/SparsityPattern/VariableImplementation.hpp @@ -0,0 +1,208 @@ +/** + \file VariableImplementation.hpp +*/ + +#pragma once + +namespace GridKit +{ + namespace Sparse + { + /** + @brief Returns the list of derivatives. + */ + const Variable::DependencyMap& Variable::getDependencies() const + { + assert(dependencies_ != 0); + return *dependencies_; + } + + /** + @brief Registers a variable as an unknown of the system and + adds a pointer to the global @a x vector. + */ + void Variable::registerVariable(std::vector& x, + const size_t& offset) + { + setVariableNumber(offset); // define global variable number + setFixed(false); // not a constant + + x[offset] = this; + } + + /** + @brief Adds all dependencies of v to *this. + */ + void Variable::addDependencies(const Variable& v) + { + for (auto& p : *(v.dependencies_)) + (*dependencies_)[p.first] = p.second; + } + + /** + @brief Multiplies each partial derivative of @a this by @a c. + */ + void Variable::scaleDependencies(double c) + { + for (auto& p : *dependencies_) + (*dependencies_)[p.first] *= c; + } + + /** + @brief Prints the value and input set of the variable. + */ + void Variable::print(std::ostream& os) const + { + os << value_; + + if (is_fixed_) + { + os << " (fixed)"; + return; + } + + if (variable_number_ != INVALID_VAR_NUMBER) + { + os << " (variable " << variable_number_ << ")"; + return; + } + + if (dependencies_ != NULL && !dependencies_->empty()) + { + os << " dependencies: [ "; + for (auto& p : *dependencies_) + os << "(" << p.first << ", " << p.second << ") "; + os << "]"; + } + } + + //------------------------------------ + // compound assignment operators + //------------------------------------ + + /** + @brief Compound addition-assignment operator. Right hand + side is a built-in double type. + */ + Variable& Variable::operator+=(const double& rhs) + { + value_ += rhs; + return *this; + } + + /** + @brief Compound addition-assignment operator. Right hand side + is Variable type. + */ + Variable& Variable::operator+=(const Variable& rhs) + { + // compute partial derivatives of *this + for (auto& p : *(rhs.dependencies_)) + (*dependencies_)[p.first] += (p.second); + + // compute value of *this + value_ += rhs.value_; + + return *this; + } + + // -= + /** + @brief Compound subtraction-assignment operator. Right hand + side is a built-in double type. + */ + Variable& Variable::operator-=(const double& rhs) + { + value_ -= rhs; + return *this; + } + + /** + @brief Compound subtraction-assignment operator. Right hand + side is a Variable type. + */ + Variable& Variable::operator-=(const Variable& rhs) + { + // compute partial derivatives of *this + for (auto& p : *(rhs.dependencies_)) + (*dependencies_)[p.first] -= (p.second); + + // compute value of *this + value_ -= rhs.value_; + + return *this; + } + + // *= + /** + @brief Compound multiplication-assignment operator. Right hand + side is a built-in double type. + */ + Variable& Variable::operator*=(const double& rhs) + { + // Compute derivatives of this + scaleDependencies(rhs); + + // compute value + value_ *= rhs; + + return *this; + } + + /** + @brief Compound multiplication-assignment operator. Right + hand side is a Variable type. + */ + Variable& Variable::operator*=(const Variable& rhs) + { + // derivation by parts of @ *this + scaleDependencies(rhs.value_); + + // compute partial derivatives of rhs and add them to *this + for (auto& p : *(rhs.dependencies_)) + (*dependencies_)[p.first] += (p.second * value_); + + // compute value of this + value_ *= rhs.value_; + + return *this; + } + + // /= + /** + @brief Compound division-assignment operator. Right hand side + is a built-in double type. + */ + Variable& Variable::operator/=(const double& rhs) + { + double inverseRhs = 1.0 / rhs; + + // compute derivatives of @a *this + scaleDependencies(inverseRhs); + + value_ *= inverseRhs; + return *this; + } + + /** + @brief Compound division-assignment operator. Right hand + side is a Variable type. + */ + Variable& Variable::operator/=(const Variable& rhs) + { + double inverseRhs = 1.0 / rhs.value_; + double inverseRhsSq = inverseRhs * inverseRhs; + + // derivation by parts of @a *this + scaleDependencies(inverseRhs); + for (auto& p : *(rhs.dependencies_)) + (*dependencies_)[p.first] -= (p.second * value_ * inverseRhsSq); + + // compute value of this + value_ *= inverseRhs; + + return *this; + } + + } // namespace Sparse +} // namespace GridKit diff --git a/src/LinearAlgebra/SparsityPattern/VariableOperators.hpp b/src/LinearAlgebra/SparsityPattern/VariableOperators.hpp new file mode 100644 index 000000000..ce5727246 --- /dev/null +++ b/src/LinearAlgebra/SparsityPattern/VariableOperators.hpp @@ -0,0 +1,356 @@ +/** + \file VariableOperators.hpp + +*/ +#pragma once + +namespace GridKit +{ + namespace Sparse + { + //------------------------------------ + // non-member operators and functions + //------------------------------------ + + // unary - + const Variable operator-(const Variable& v) + { + return -1.0 * v; + } + + // + + const Variable operator+(const Variable& lhs, const Variable& rhs) + { + return Variable(lhs) += rhs; + } + + const Variable operator+(const Variable& lhs, const double& rhs) + { + return Variable(lhs) += rhs; + } + + const Variable operator+(const double& lhs, const Variable& rhs) + { + return Variable(rhs) += lhs; + } + + // - + const Variable operator-(const Variable& lhs, const Variable& rhs) + { + return Variable(lhs) -= rhs; + } + + const Variable operator-(const Variable& lhs, const double& rhs) + { + return Variable(lhs) -= rhs; + } + + const Variable operator-(const double& lhs, const Variable& rhs) + { + return Variable(lhs) -= rhs; + } + + // * + const Variable operator*(const Variable& lhs, const Variable& rhs) + { + return Variable(lhs) *= rhs; + } + + const Variable operator*(const Variable& lhs, const double& rhs) + { + return Variable(lhs) *= rhs; + } + + const Variable operator*(const double& lhs, const Variable& rhs) + { + return Variable(lhs) *= rhs; + } + + // / + const Variable operator/(const Variable& lhs, const Variable& rhs) + { + return Variable(lhs) /= rhs; + } + + const Variable operator/(const Variable& lhs, const double& rhs) + { + return Variable(lhs) /= rhs; + } + + const Variable operator/(const double& lhs, const Variable& rhs) + { + return Variable(lhs) /= rhs; + } + + // == + bool operator==(const Variable& lhs, const Variable& rhs) + { + return lhs.getValue() == rhs.getValue(); + } + + bool operator==(const Variable& lhs, const double& rhs) + { + return lhs.getValue() == rhs; + } + + bool operator==(const double& lhs, const Variable& rhs) + { + return lhs == rhs.getValue(); + } + + // != + bool operator!=(const Variable& lhs, const Variable& rhs) + { + return !(lhs.getValue() == rhs.getValue()); + } + + bool operator!=(const Variable& lhs, const double& rhs) + { + return !(lhs.getValue() == rhs); + } + + bool operator!=(const double& lhs, const Variable& rhs) + { + return !(lhs == rhs.getValue()); + } + + // < + bool operator<(const Variable& lhs, const Variable& rhs) + { + return lhs.getValue() < rhs.getValue(); + } + + bool operator<(const Variable& lhs, const double& rhs) + { + return lhs.getValue() < rhs; + } + + bool operator<(const double& lhs, const Variable& rhs) + { + return lhs < rhs.getValue(); + } + + // > + bool operator>(const Variable& lhs, const Variable& rhs) + { + return lhs.getValue() > rhs.getValue(); + } + + bool operator>(const Variable& lhs, const double& rhs) + { + return lhs.getValue() > rhs; + } + + bool operator>(const double& lhs, const Variable& rhs) + { + return lhs > rhs.getValue(); + } + + // <= + bool operator<=(const Variable& lhs, const Variable& rhs) + { + return lhs < rhs || lhs == rhs; + } + + bool operator<=(const Variable& lhs, const double& rhs) + { + return lhs < rhs || lhs == rhs; + } + + bool operator<=(const double& lhs, const Variable& rhs) + { + return lhs < rhs || lhs == rhs; + } + + // >= + bool operator>=(const Variable& lhs, const Variable& rhs) + { + return lhs > rhs || lhs == rhs; + } + + bool operator>=(const Variable& lhs, const double& rhs) + { + return lhs > rhs || lhs == rhs; + } + + bool operator>=(const double& lhs, const Variable& rhs) + { + return lhs > rhs || lhs == rhs; + } + + //------------------------------------ + // non-member operators + //------------------------------------ + + /** + @brief Stream insertion operator for variables. + */ + std::ostream& operator<<(std::ostream& os, const Variable& v) + { + v.print(os); + return os; + } + + /** + @brief Adds all dependencies of a variable, i.e. v << u means + that v depends on u. + + \attention Use only if you know what you are doing! + */ + Variable& operator<<(Variable& u, const Variable& v) + { + u.addDependencies(v); + return u; + } + + /** + @brief Stream extraction operator for variables. + */ + std::istream& operator>>(std::istream& is, Variable& v) + { + return is >> v(); + } + + //------------------------------------------- + // definitions of cmath functions derivatives + //------------------------------------------- + + /// Derivative of sine + inline double sin_derivative(double x) + { + return std::cos(x); + } + + /// Derivative of cosine + inline double cos_derivative(double x) + { + return -std::sin(x); + } + + /// Derivative of tangent + inline double tan_derivative(double x) + { + return 1.0 / (std::cos(x) * std::cos(x)); + } + + /// Derivative of arc sine + inline double asin_derivative(double x) + { + return std::sqrt(1.0 - x * x); + } + + /// Derivative of arc cosine + inline double acos_derivative(double x) + { + return -std::sqrt(1.0 - x * x); + } + + /// Derivative of arc tangent + inline double atan_derivative(double x) + { + return 1.0 / (1.0 + x * x); + } + + /// Derivative of hyperbolic sine + inline double sinh_derivative(double x) + { + return std::cosh(x); + } + + /// Derivative of hyperbolic cosine + inline double cosh_derivative(double x) + { + return std::sinh(x); + } + + /// Derivative of hyperbolic tangent + inline double tanh_derivative(double x) + { + return 1.0 / (std::cosh(x) * std::cosh(x)); + } + + /// Derivative of hyperbolic arc sine + inline double asinh_derivative(double x) + { + return std::sqrt(1.0 + x * x); + } + + /// Derivative of hyperbolic arc cosine + inline double acosh_derivative(double x) + { + return std::sqrt(x * x - 1.0); + } + + /// Derivative of hyperbolic arc tangent + inline double atanh_derivative(double x) + { + return 1.0 / (1.0 - x * x); + } + + /// Derivative of exponential function. + inline double exp_derivative(double x) + { + return std::exp(x); + } + + /// Derivative of natural logarithm function. + inline double log_derivative(double x) + { + return 1.0 / x; + } + + /// Derivative of logarithm to base 10 function: 1/(x*log(10)). + inline double log10_derivative(double x) + { + return 0.4342944819032518 / x; + } + + /// Derivative of square root function. + inline double sqrt_derivative(double x) + { + return 0.5 / std::sqrt(x); + } + + /// Derivative of absolute value function. + inline double abs_derivative(double x) + { + return x > 0.0 ? 1.0 : -1.0; + } + + } // namespace Sparse +} // namespace GridKit + +// Add all mathematical functions to the namespace std so that, +// for instance, std::sin(x) also works with objects of type Variable. +namespace std +{ + +#define IMPL_FUN_1(FUN, DER) \ + inline GridKit::Sparse::Variable FUN(const GridKit::Sparse::Variable& x) \ + { \ + double val = FUN(x()); \ + double der = DER(x()); \ + GridKit::Sparse::Variable res(x); /* copy derivatives of x*/ \ + res.setValue(val); /* set function value f(x) */ \ + res.scaleDependencies(der); /* compute derivatives of f(x) */ \ + return res; \ + } + + IMPL_FUN_1(sin, GridKit::Sparse::sin_derivative) + IMPL_FUN_1(cos, GridKit::Sparse::cos_derivative) + IMPL_FUN_1(tan, GridKit::Sparse::tan_derivative) + IMPL_FUN_1(asin, GridKit::Sparse::asin_derivative) + IMPL_FUN_1(acos, GridKit::Sparse::acos_derivative) + IMPL_FUN_1(atan, GridKit::Sparse::atan_derivative) + IMPL_FUN_1(sinh, GridKit::Sparse::sinh_derivative) + IMPL_FUN_1(cosh, GridKit::Sparse::cosh_derivative) + IMPL_FUN_1(tanh, GridKit::Sparse::tanh_derivative) + IMPL_FUN_1(exp, GridKit::Sparse::exp_derivative) + IMPL_FUN_1(log, GridKit::Sparse::log_derivative) + IMPL_FUN_1(log10, GridKit::Sparse::log10_derivative) + IMPL_FUN_1(sqrt, GridKit::Sparse::sqrt_derivative) + IMPL_FUN_1(abs, GridKit::Sparse::abs_derivative) + +#undef IMPL_FUN_1 + +} // namespace std diff --git a/src/Model/CMakeLists.txt b/src/Model/CMakeLists.txt new file mode 100644 index 000000000..a50f0aeaf --- /dev/null +++ b/src/Model/CMakeLists.txt @@ -0,0 +1,10 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +add_subdirectory(PhasorDynamics) +add_subdirectory(PowerFlow) +add_subdirectory(PowerElectronics) diff --git a/src/Model/Evaluator.hpp b/src/Model/Evaluator.hpp new file mode 100644 index 000000000..b4a447dd6 --- /dev/null +++ b/src/Model/Evaluator.hpp @@ -0,0 +1,100 @@ +#pragma once + +#include + +#include +#include + +namespace GridKit +{ + namespace Model + { + /*! + * @brief Abstract class describing a model. + * + */ + template + class Evaluator + { + public: + typedef typename GridKit::ScalarTraits::real_type real_type; + + Evaluator() + { + } + + virtual ~Evaluator() + { + } + + 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 new file mode 100644 index 000000000..75ccb8d74 --- /dev/null +++ b/src/Model/PhasorDynamics/Branch/Branch.cpp @@ -0,0 +1,226 @@ +/** + * @file Branch.hpp + * @author Slaven Peles (peless@ornl.gov) + * @brief Definition of a phasor dynamics branch model. + * + * The model uses Cartesian coordinates. + * + */ + +#include "Branch.hpp" + +#include +#include + +#include +#include + +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) + : 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 new file mode 100644 index 000000000..9d6ac38d9 --- /dev/null +++ b/src/Model/PhasorDynamics/Branch/Branch.hpp @@ -0,0 +1,162 @@ +/** + * @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 + +// Forward declarations. +namespace GridKit +{ + namespace PowerSystemData + { + template + struct BranchData; + } +} // namespace GridKit + +namespace GridKit +{ + namespace PhasorDynamics + { + template + class BusBase; + } +} // namespace GridKit + +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 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 bus_type = BusBase; + using real_type = typename Component::real_type; + using BranchData = GridKit::PowerSystemData::BranchData; + + public: + Branch(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(); + + 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; + } + + void setG(real_type G) + { + G_ = G; + } + + void setB(real_type B) + { + B_ = B; + } + + private: + ScalarT& Vr1() + { + return bus1_->Vr(); + } + + ScalarT& Vi1() + { + return bus1_->Vi(); + } + + ScalarT& Ir1() + { + return bus1_->Ir(); + } + + ScalarT& Ii1() + { + return bus1_->Ii(); + } + + ScalarT& Vr2() + { + return bus2_->Vr(); + } + + ScalarT& Vi2() + { + return bus2_->Vi(); + } + + ScalarT& Ir2() + { + return bus2_->Ir(); + } + + ScalarT& Ii2() + { + return bus2_->Ii(); + } + + 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_; + }; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/Branch/CMakeLists.txt b/src/Model/PhasorDynamics/Branch/CMakeLists.txt new file mode 100644 index 000000000..44523fbd3 --- /dev/null +++ b/src/Model/PhasorDynamics/Branch/CMakeLists.txt @@ -0,0 +1,12 @@ + +# [[ +# Author(s): +# - Cameron Rutherford +# - Slaven Peles +# ]] + +gridkit_add_library(phasor_dynamics_branch + SOURCES + Branch.cpp + OUTPUT_NAME + gridkit_phasor_dynamics_branch) diff --git a/src/Model/PhasorDynamics/Branch/README.md b/src/Model/PhasorDynamics/Branch/README.md new file mode 100644 index 000000000..a566c1626 --- /dev/null +++ b/src/Model/PhasorDynamics/Branch/README.md @@ -0,0 +1,120 @@ +# Branch Model + +Transmission lines and different types of transformers (traditional, Load +Tap-Changing transformers (LTC) and Phase Angle Regulators (PARs)) can be +modeled with a common branch model. + +## Transmission Line Model + +The most common circuit that is used to represent the transmission line model +is $`\pi`$ circuit as shown in Figure 1. The positive flow direction is into +buses. Commonly used convention is to define positive direction to be from +sending to receiving bus. We decide to use this symmetric convention because it +provides more flexibility for modeling. + +
+ + + Figure 1: Transmission line $`\pi`$ equivalent circuit +
+ +Here +``` math +Z = R + jX +``` +and +``` math +Y = G + jB, +``` +where $`R`$ is line series resistance, $`X`$ is line series reactance, $`B`$ is +line shunt charging, and $`G`$ is line shunt conductance. As can be seen from +Figure 1 total $`B`$ and $`G`$ are separated between two buses. The current +entering bus 1 can be obtained from Kirchhoff's current law as +```math +I_1 = y(V_2 - V_1) - \frac{Y}{2} V_1, +``` +where $`V_1`$ and $`V_2`$ are respective bus voltages and +```math +y = \frac{1}{Z} = \frac{R}{R^2+X^2} + j\frac{-X}{R^2+X^2} = g + jb. +``` +Similarly, current entering bus 2 is given as +```math +I_2 = y(V_1 - V_2) + \frac{Y}{2} V_2. +``` +These equations can be written in a compact form as: +```math +\begin{bmatrix} +I_{1}\\ +I_{2} +\end{bmatrix} += \mathbf{Y} +\begin{bmatrix} +V_{1}\\ +V_{2} +\end{bmatrix} +``` +where: +```math +\mathbf{Y}_{TL}=\begin{bmatrix} +-(g + jb) - \dfrac{G+jB}{2} & g + jb \\ + g + jb & -(g + jb) - \dfrac{G+jB}{2} +\end{bmatrix} +``` + +### Branch contributions to residuals at adjacent buses + +After some algebra, one obtains expressions for real and imaginary components +for the currents entering adjacent buses: +```math +I_{r1} = -\left(g + \frac{G}{2}\right) V_{r1} + \left(b + \frac{B}{2} \right) V_{i1} + + g V_{r2} - b V_{i2} +``` + +```math +I_{i1} = -\left(b + \frac{B}{2} \right) V_{r1} - \left(g + \frac{G}{2}\right) V_{i1} + + b V_{r2} + g V_{i2} +``` + +```math +I_{r2} = g V_{r1} - b V_{i1} + - \left(g + \frac{G}{2}\right) V_{r2} + \left(b + \frac{B}{2} \right) V_{i2} +``` + +```math +I_{i1} = b V_{r1} + g V_{i1} + - \left(b + \frac{B}{2} \right) V_{r2} - \left(g + \frac{G}{2}\right) V_{i2} +``` + + +## Transformer Branch Model + +**Note: Transformer model not yet implemented** + +The branch model can be created by adding the ideal transformer in series with +the $`\pi`$ circuit as shown in Figure 2 where $`\tau`$ is a tap ratio +magnitude and $`\theta`$ is the phase shift angle and +$`N = \tau e^{j \theta}`$. + +
+ + + + Figure 2: Branch equivalent circuit +
+ + +The branch admitance matrix is then: + +```math +\mathbf{Y}_{BR}= +\begin{bmatrix} + -\left(g + jb + \dfrac{G+jB}{2} \right) \dfrac{1}{\tau^2} & (g + jb)\dfrac{1}{\tau e^{-j\theta}}\\ + & \\ + (g + jb)\dfrac{1}{\tau e^{j\theta}} & -\left(g + jb + \dfrac{G+jB}{2}\right) +\end{bmatrix} +``` + +### Branch contribution to residuals at adjacent busses + +The currents entering adjacent buses are obtained in a similar manner as for +the $`\pi`$-model. diff --git a/src/Model/PhasorDynamics/Bus/Bus.cpp b/src/Model/PhasorDynamics/Bus/Bus.cpp new file mode 100644 index 000000000..f8005b2b9 --- /dev/null +++ b/src/Model/PhasorDynamics/Bus/Bus.cpp @@ -0,0 +1,220 @@ + +#include "Bus.hpp" + +#include +#include + +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + + /*! + * @brief Constructor for a phasor dynamics bus. + * + * The model is using current balance in Cartesian coordinates. + * + * @todo Arguments that should be passed to ModelEvaluatorImpl constructor: + * - Number of equations = 2 (size_) + * - Number of variables = 2 (size_) + * - Number of quadratures = 0 + * - Number of optimization parameters = 0 + */ + template + Bus::Bus() + : Vr0_(0.0), Vi0_(0.0) + { + // std::cout << "Create Bus..." << std::endl; + // std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 2; + } + + /*! + * @brief Bus constructor. + * + * This constructor sets initial values for active and reactive voltage. + * + * @todo Arguments that should be passed to ModelEvaluatorImpl constructor: + * - Number of equations = 2 (size_) + * - Number of variables = 2 (size_) + * - Number of quadratures = 0 + * - Number of optimization parameters = 0 + */ + template + Bus::Bus(ScalarT Vr, ScalarT Vi) + : Vr0_(Vr), Vi0_(Vi) + { + // std::cout << "Create Bus..." << std::endl; + // std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 2; + } + + /** + * @brief Construct a new Bus + * + * @tparam ScalarT - type of scalar variables + * @tparam IdxT - type for vector/matrix indices + * @param[in] data - structure with bus data + */ + template + Bus::Bus(BusData& data) + : 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; + + size_ = 2; + } + + template + Bus::~Bus() + { + // std::cout << "Destroy PQ bus ..." << std::endl; + } + + /*! + * @brief allocate method resizes local solution and residual vectors. + */ + template + int Bus::allocate() + { + // Temporary while we use std::vector in the code + size_t size = static_cast(size_); + + // Resize component model data + f_.resize(size); + y_.resize(size); + yp_.resize(size); + tag_.resize(size); + + fB_.resize(size); + yB_.resize(size); + ypB_.resize(size); + + return 0; + } + + /*! + * @brief Bus variables are algebraic. + */ + template + int Bus::tagDifferentiable() + { + tag_[0] = false; + tag_[1] = false; + return 0; + } + + /*! + * @brief initialize method sets bus variables to stored initial values. + */ + template + int Bus::initialize() + { + // std::cout << "Initialize Bus..." << std::endl; + y_[0] = Vr0_; + y_[1] = Vi0_; + yp_[0] = 0.0; + yp_[1] = 0.0; + + return 0; + } + + /*! + * @brief PQ bus does not compute residuals, so here we just reset residual values. + * + * @warning This implementation assumes bus residuals are always evaluated + * _before_ component model residuals. + * + */ + template + int Bus::evaluateResidual() + { + // std::cout << "Evaluating residual of a PQ bus ...\n"; + f_[0] = 0.0; + f_[1] = 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 Bus::evaluateJacobian() + { + return 0; + } + + /*! + * @brief initialize method sets bus variables to stored initial values. + */ + template + int Bus::initializeAdjoint() + { + // std::cout << "Initialize Bus..." << std::endl; + yB_[0] = 0.0; + yB_[1] = 0.0; + ypB_[0] = 0.0; + ypB_[1] = 0.0; + + 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() + { + fB_[0] = 0.0; + fB_[1] = 0.0; + + 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; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/Bus/Bus.hpp b/src/Model/PhasorDynamics/Bus/Bus.hpp new file mode 100644 index 000000000..aedaa2a82 --- /dev/null +++ b/src/Model/PhasorDynamics/Bus/Bus.hpp @@ -0,0 +1,150 @@ + +#pragma once + +#include + +// Forward declaration of BusData structure +namespace GridKit +{ + namespace PowerSystemData + { + template + struct BusData; + } +} // namespace GridKit + +namespace GridKit +{ + namespace PhasorDynamics + { + /*! + * @brief Implementation of a PQ bus. + * + * Voltage _V_ and phase _theta_ are variables in PQ bus model. + * Active and reactive power, _P_ and _Q_, are residual components. + * + * + */ + template + class Bus : 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; + + Bus(); + Bus(ScalarT Vr, ScalarT Vi); + Bus(BusData& data); + virtual ~Bus(); + + 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::DEFAULT; + } + + virtual ScalarT& Vr() override + { + return y_[0]; + } + + virtual const ScalarT& Vr() const override + { + return y_[0]; + } + + virtual ScalarT& Vi() override + { + return y_[1]; + } + + virtual const ScalarT& Vi() const override + { + return y_[1]; + } + + virtual ScalarT& Ir() override + { + return f_[0]; + } + + virtual const ScalarT& Ir() const override + { + return f_[0]; + } + + virtual ScalarT& Ii() override + { + return f_[1]; + } + + virtual const ScalarT& Ii() const override + { + return f_[1]; + } + + // virtual ScalarT& VrB() override + // { + // return yB_[0]; + // } + + // virtual const ScalarT& VrB() const override + // { + // return yB_[0]; + // } + + // virtual ScalarT& ViB() override + // { + // return yB_[1]; + // } + + // virtual const ScalarT& ViB() const override + // { + // return yB_[1]; + // } + + // virtual ScalarT& IrB() override + // { + // return fB_[0]; + // } + + // virtual const ScalarT& IrB() const override + // { + // return fB_[0]; + // } + + // virtual ScalarT& IiB() override + // { + // return fB_[1]; + // } + + // virtual const ScalarT& IiB() const override + // { + // return fB_[1]; + // } + + private: + ScalarT Vr0_{0.0}; + ScalarT Vi0_{0.0}; + }; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/Bus/BusInfinite.cpp b/src/Model/PhasorDynamics/Bus/BusInfinite.cpp new file mode 100644 index 000000000..6206813d7 --- /dev/null +++ b/src/Model/PhasorDynamics/Bus/BusInfinite.cpp @@ -0,0 +1,200 @@ + +#include "BusInfinite.hpp" + +#include +#include + +#include + +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 PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/Bus/BusInfinite.hpp b/src/Model/PhasorDynamics/Bus/BusInfinite.hpp new file mode 100644 index 000000000..6acdd7c6a --- /dev/null +++ b/src/Model/PhasorDynamics/Bus/BusInfinite.hpp @@ -0,0 +1,155 @@ + +#pragma once + +#include + +// Forward declaration of BusData structure +namespace GridKit +{ + namespace PowerSystemData + { + template + struct BusData; + } +} // namespace GridKit + +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}; + }; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/Bus/CMakeLists.txt b/src/Model/PhasorDynamics/Bus/CMakeLists.txt new file mode 100644 index 000000000..b11fe63ac --- /dev/null +++ b/src/Model/PhasorDynamics/Bus/CMakeLists.txt @@ -0,0 +1,12 @@ +# [[ +# 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/Bus/README.md b/src/Model/PhasorDynamics/Bus/README.md new file mode 100644 index 000000000..2d61eed2f --- /dev/null +++ b/src/Model/PhasorDynamics/Bus/README.md @@ -0,0 +1,30 @@ +# Bus Model + +A bus is a point of interconnection of electrical devices. Bus component model +also plays a key role in coupling system components. Each bus $`k`$ owns two +variables -- real and imaginary voltage $`V_{rk}`$ and $`V_{ik}`$, +respectively. The bus also owns current balance residual equations for real +and imaginary currents coming into the bus $`I_{rk}`$ and $`I_{ik}`$, +respectively. While th bus model owns current residuals, it _does not compute_ +them. Instead, each component connected to the bus is adding its contribution +to the residual. The bus will merely initialize the residual to zero each time +numerical integrator requests residual evaluation. + +**Sign Convention** + +Current entering the bus has positive and current exiting the bus negative +sign. + +
+ + + Figure 1: Needs to be changed to represent current balance instead of power + balance. +
+ + + + +**Other Parameters** +Buses are uniquely defined by their ID (number or name). Besides, each bus +should have associated Nominal Voltage value. diff --git a/src/Model/PhasorDynamics/BusBase.hpp b/src/Model/PhasorDynamics/BusBase.hpp new file mode 100644 index 000000000..804cbfca4 --- /dev/null +++ b/src/Model/PhasorDynamics/BusBase.hpp @@ -0,0 +1,285 @@ +#pragma once + +#include + +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + /*! + * @brief BusBase model implementation base class. + * + */ + template + class BusBase : public Model::Evaluator + { + public: + using real_type = typename Model::Evaluator::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() override + { + return nnz_; + } + + virtual bool hasJacobian() override + { + 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 */) override + { + // No time to update in bus models + } + + virtual void setTolerances(real_type& rtol, real_type& atol) const override + { + rtol = rtol_; + atol = atol_; + } + + virtual void setMaxSteps(IdxT& msa) const override + { + 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() override + { + return J_; + } + + const COO_Matrix& getJacobian() const override + { + 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 PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/BusFault/BusFault.cpp b/src/Model/PhasorDynamics/BusFault/BusFault.cpp new file mode 100644 index 000000000..d2f519ee0 --- /dev/null +++ b/src/Model/PhasorDynamics/BusFault/BusFault.cpp @@ -0,0 +1,182 @@ +/** + * @file BusFault.hpp + * @author Slaven Peles (peless@ornl.gov) + * @brief Definition of a bus fault to ground model. + * + * The model uses Cartesian coordinates. + * + */ + +#include "BusFault.hpp" + +#include +#include + +#include +#include + +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 + BusFault::BusFault(bus_type* bus) + : bus_(bus), R_(0), X_(0.01), status_(0), busID_(0) + { + (void) busID_; + size_ = 0; + } + + /** + * @brief Construct a new BusFault + * + * @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 + BusFault::BusFault(bus_type* bus, real_type R, real_type X, int status) + : bus_(bus), R_(R), X_(X), status_(status), busID_(0) + { + size_ = 0; + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int BusFault::allocate() + { + // std::cout << "Allocate BusFault..." << std::endl; + return 0; + } + + /** + * Initialization of the branch model + * + */ + template + int BusFault::initialize() + { + return 0; + } + + /** + * \brief Identify differential variables. + */ + template + int BusFault::tagDifferentiable() + { + return 0; + } + + /** + * \brief Residual contribution of the branch is pushed to the + * two terminal buses. + * + */ + template + int BusFault::evaluateResidual() + { + if (status_) + { + double B = -X_ / (X_ * X_ + R_ * R_); + double G = R_ / (X_ * X_ + R_ * R_); + + Ir() += -Vr() * G + Vi() * B; + Ii() += -Vr() * B - Vi() * G; + } + 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 BusFault::evaluateJacobian() + { + std::cout << "Evaluate Jacobian for BusFault..." << 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 BusFault::evaluateIntegrand() + { + // std::cout << "Evaluate Integrand for BusFault..." << 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 BusFault::initializeAdjoint() + { + // std::cout << "Initialize adjoint for BusFault..." << 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 BusFault::evaluateAdjointResidual() + { + // std::cout << "Evaluate adjoint residual for BusFault..." << 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 BusFault::evaluateAdjointIntegrand() + { + // std::cout << "Evaluate adjoint Integrand for BusFault..." << std::endl; + return 0; + } + + // Available template instantiations + template class BusFault; + template class BusFault; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/BusFault/BusFault.hpp b/src/Model/PhasorDynamics/BusFault/BusFault.hpp new file mode 100644 index 000000000..4df93c123 --- /dev/null +++ b/src/Model/PhasorDynamics/BusFault/BusFault.hpp @@ -0,0 +1,97 @@ +/* Bus Fault Component - Adam Birchfield */ +#pragma once + +#include +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + template + class BusFault : public Component + { + using Component::alpha_; + using Component::f_; + using Component::fB_; + using Component::g_; + using Component::gB_; + using Component::nnz_; + using Component::param_; + using Component::size_; + using Component::tag_; + using Component::time_; + using Component::y_; + using Component::yB_; + using Component::yp_; + using Component::ypB_; + + using bus_type = BusBase; + using real_type = typename Component::real_type; + + public: + BusFault(bus_type* bus); + BusFault(bus_type* bus, real_type R, real_type X, int status); + ~BusFault() = default; + + int allocate() override; + int initialize() override; + int tagDifferentiable() override; + int evaluateResidual() override; + int evaluateJacobian() override; + int evaluateIntegrand() override; + int initializeAdjoint() override; + int evaluateAdjointResidual() override; + int evaluateAdjointIntegrand() override; + + void updateTime(real_type /* t */, real_type /* a */) override + { + } + + public: + void setR(real_type R) + { + R_ = R; + } + + void setX(real_type X) + { + X_ = X; + } + + void setStatus(int status) + { + status_ = status; + } + + 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_; + real_type R_; + real_type X_; + int status_; + const int busID_; + }; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/BusFault/CMakeLists.txt b/src/Model/PhasorDynamics/BusFault/CMakeLists.txt new file mode 100644 index 000000000..48d8c6d79 --- /dev/null +++ b/src/Model/PhasorDynamics/BusFault/CMakeLists.txt @@ -0,0 +1,5 @@ +gridkit_add_library(phasor_dynamics_bus_fault + SOURCES + BusFault.cpp + OUTPUT_NAME + gridkit_phasor_dynamics_bus_fault) diff --git a/src/Model/PhasorDynamics/CMakeLists.txt b/src/Model/PhasorDynamics/CMakeLists.txt new file mode 100644 index 000000000..01cd77258 --- /dev/null +++ b/src/Model/PhasorDynamics/CMakeLists.txt @@ -0,0 +1,10 @@ +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +add_subdirectory(Branch) +add_subdirectory(Bus) +add_subdirectory(BusFault) +add_subdirectory(Load) +add_subdirectory(SynchronousMachine) diff --git a/src/Model/PhasorDynamics/Component.hpp b/src/Model/PhasorDynamics/Component.hpp new file mode 100644 index 000000000..c061ff622 --- /dev/null +++ b/src/Model/PhasorDynamics/Component.hpp @@ -0,0 +1,263 @@ +#pragma once + +#include + +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + + /*! + * @brief Component model implementation base class. + * + */ + template + class Component : public Model::Evaluator + { + public: + using real_type = typename Model::Evaluator::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() override + { + return nnz_; + } + + /// @todo Remove this method. It should be part of DynamicSolver class. + virtual bool hasJacobian() override + { + 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 override + { + rtol = rel_tol_; + atol = abs_tol_; + } + + virtual void setMaxSteps(IdxT& msa) const override + { + 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() override + { + return J_; + } + + const COO_Matrix& getJacobian() const override + { + 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 rel_tol_; + real_type abs_tol_; + + IdxT max_steps_; + + IdxT component_id_; + }; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/ComponentLib/Exciter/README.md b/src/Model/PhasorDynamics/Exciter/README.md similarity index 97% rename from ComponentLib/Exciter/README.md rename to src/Model/PhasorDynamics/Exciter/README.md index e32003dff..79b743b37 100644 --- a/ComponentLib/Exciter/README.md +++ b/src/Model/PhasorDynamics/Exciter/README.md @@ -4,7 +4,7 @@ **Note: Exciter model not yet implemented**
- + Figure 1: Exciter EXDC1 model. Fifure courtesy of [PoweWorld](https://www.powerworld.com/WebHelp/). @@ -107,5 +107,3 @@ V_{F}=0 ``` ```math x_{2_{0}}=-\dfrac{K_{F}}{T_{F1}}\dfrac{E_{FD}}{\omega} - - diff --git a/ComponentLib/Governor/README.md b/src/Model/PhasorDynamics/Governor/README.md similarity index 95% rename from ComponentLib/Governor/README.md rename to src/Model/PhasorDynamics/Governor/README.md index be6be49c2..19e9dde2f 100644 --- a/ComponentLib/Governor/README.md +++ b/src/Model/PhasorDynamics/Governor/README.md @@ -8,7 +8,7 @@ Standard model of the stream turbine
- + Figure 1: Governor TGOV1 model. Figure courtesy of [PowerWorld](https://www.powerworld.com/WebHelp/) @@ -54,4 +54,4 @@ P=x+\dfrac{T2}{T3}V Output ```math P_{mech}=P-\Delta\omega D_{t} -``` \ No newline at end of file +``` diff --git a/src/Model/PhasorDynamics/Load/CMakeLists.txt b/src/Model/PhasorDynamics/Load/CMakeLists.txt new file mode 100644 index 000000000..0f1659a71 --- /dev/null +++ b/src/Model/PhasorDynamics/Load/CMakeLists.txt @@ -0,0 +1,12 @@ + + +# [[ +# 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..84763e3d0 --- /dev/null +++ b/src/Model/PhasorDynamics/Load/Load.cpp @@ -0,0 +1,178 @@ + +#include "Load.hpp" + +#include +#include + +#include +#include + +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..d85355093 --- /dev/null +++ b/src/Model/PhasorDynamics/Load/Load.hpp @@ -0,0 +1,109 @@ + + +#pragma once + +#include + +// Forward declarations. +namespace GridKit +{ + namespace PhasorDynamics + { + template + class BusBase; + } +} // namespace GridKit + +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..24d2c13ee --- /dev/null +++ b/src/Model/PhasorDynamics/Load/README.md @@ -0,0 +1,28 @@ +# 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/ComponentLib/Stabilizer/README.md b/src/Model/PhasorDynamics/Stabilizer/README.md similarity index 96% rename from ComponentLib/Stabilizer/README.md rename to src/Model/PhasorDynamics/Stabilizer/README.md index 722741dd8..8ace6bf5a 100644 --- a/ComponentLib/Stabilizer/README.md +++ b/src/Model/PhasorDynamics/Stabilizer/README.md @@ -4,7 +4,7 @@
- + Figure 1: Power system stabilizer PSS1A model. Figure courtesy of [PowerWorld](https://www.powerworld.com/WebHelp/) @@ -74,4 +74,4 @@ V_{llout} = \begin{cases} L_{SMIN} &\text{if } V_{5} +# - Slaven Peles +# ]] + +add_subdirectory(GENROUwS) diff --git a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/CMakeLists.txt b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/CMakeLists.txt new file mode 100644 index 000000000..11b1e4c58 --- /dev/null +++ b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/CMakeLists.txt @@ -0,0 +1,5 @@ +gridkit_add_library(phasor_dynamics_genrou + SOURCES + Genrou.cpp + OUTPUT_NAME + gridkit_phasor_dynamics_genrou) diff --git a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.cpp b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.cpp new file mode 100644 index 000000000..029f9e9fa --- /dev/null +++ b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.cpp @@ -0,0 +1,412 @@ +/** + * @file Genrou.cpp + * @author Adam Birchfield (abirchfield@tamu.edu) + * @author Slaven Peles (peless@ornl.gov) + * @brief Definition of a GENROU generator model. + * + * + */ + +#include "Genrou.hpp" + +#include +#include + +#include + +#define _USE_MATH_DEFINES + +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 + Genrou::Genrou(bus_type* bus, int unit_id) + : bus_(bus), + busID_(0), + unit_id_(unit_id), + p0_(0.), + q0_(0.), + H_(3.), + D_(0.), + Ra_(0.), + Tdop_(7.), + Tdopp_(.04), + Tqopp_(.05), + Tqop_(.75), + Xd_(2.1), + Xdp_(0.2), + Xdpp_(0.18), + Xq_(.5), + Xqp_(.5), + Xqpp_(.18), + Xl_(.15), + S10_(0.), + S12_(0.) + { + size_ = 21; + setDerivedParams(); + + // Temporary, to eliminate compiler warnings + (void) busID_; + (void) unit_id_; + } + + /*! + * @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 + Genrou::Genrou(bus_type* bus, + int unit_id, + ScalarT p0, + ScalarT q0, + real_type H, + real_type D, + real_type Ra, + real_type Tdop, + real_type Tdopp, + real_type Tqopp, + real_type Tqop, + real_type Xd, + real_type Xdp, + real_type Xdpp, + real_type Xq, + real_type Xqp, + real_type Xqpp, + real_type Xl, + real_type S10, + real_type S12) + : bus_(bus), + busID_(0), + unit_id_(unit_id), + p0_(p0), + q0_(q0), + H_(H), + D_(D), + Ra_(Ra), + Tdop_(Tdop), + Tdopp_(Tdopp), + Tqopp_(Tqopp), + Tqop_(Tqop), + Xd_(Xd), + Xdp_(Xdp), + Xdpp_(Xdpp), + Xq_(Xq), + Xqp_(Xqp), + Xqpp_(Xqpp), + Xl_(Xl), + S10_(S10), + S12_(S12) + { + size_ = 21; + setDerivedParams(); + } + + // /** + // * @brief Destroy the Genrou + // * + // * @tparam ScalarT + // * @tparam IdxT + // */ + // template + // Genrou::~Genrou() + // { + // // std::cout << "Destroy Genrou..." << std::endl; + // } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int Genrou::allocate() + { + f_.resize(size_); + y_.resize(size_); + yp_.resize(size_); + tag_.resize(size_); + fB_.resize(size_); + yB_.resize(size_); + ypB_.resize(size_); + return 0; + } + + /** + * Initialization of the branch model + * + */ + template + int Genrou::initialize() + { + /* Initialization tricks -- assuming NO saturation */ + ScalarT vr = Vr(); + ScalarT vi = Vi(); + ScalarT p = p0_; + ScalarT q = q0_; + ScalarT vm2 = vr * vr + vi * vi; + ScalarT Er = vr + (Ra_ * p * vr + Ra_ * q * vi - Xq_ * p * vi + Xq_ * q * vr) / vm2; + ScalarT Ei = vi + (Ra_ * p * vi - Ra_ * q * vr + Xq_ * p * vr + Xq_ * q * vi) / vm2; + ScalarT delta = atan2(Ei, Er); + ScalarT omega = 0; + ScalarT ir = (p * vr + q * vi) / vm2; + ScalarT ii = (p * vi - q * vr) / vm2; + ScalarT id = ir * sin(delta) - ii * cos(delta); + ScalarT iq = ir * cos(delta) + ii * sin(delta); + ScalarT vd = vr * sin(delta) - vi * cos(delta) + id * Ra_ - iq * Xqpp_; + ScalarT vq = vr * cos(delta) + vi * sin(delta) + id * Xqpp_ - iq * Ra_; + ScalarT psiqpp = -vd / (1 + omega); + ScalarT psidpp = vq / (1 + omega); + ScalarT Te = (psidpp - id * Xdpp_) * iq - (psiqpp - iq * Xdpp_) * id; + ScalarT psiqp = -(-(Xqp_ - Xl_) * iq + psiqpp * (Xqp_ - Xl_) / (Xqpp_ - Xl_)) + / (1 + (Xqp_ - Xqpp_) / (Xqpp_ - Xl_)); + ScalarT Edp = psiqp - (Xqp_ - Xl_) * iq; + ScalarT psidp = -((Xdp_ - Xl_) * id - psidpp * (Xdp_ - Xl_) / (Xdpp_ - Xl_)) + / (1 + (Xdp_ - Xdpp_) / (Xdpp_ - Xl_)); + ScalarT Eqp = psidp + (Xdp_ - Xl_) * id; + + /* Now we have the state variables, solve for alg. variables */ + ScalarT ksat; + ScalarT psipp; + + y_[0] = delta; //= 0.55399038; + y_[1] = omega; // = 0; + y_[2] = Eqp; // = 0.995472581; + y_[3] = psidp; // = 0.971299567; + y_[4] = psiqp; // = 0.306880069; + y_[5] = Edp; // = 0; + + y_[6] = psiqpp = -psiqp * Xq4_ - Edp * Xq5_; + y_[7] = psidpp = psidp * Xd4_ + Eqp * Xd5_; + y_[8] = psipp = sqrt(psiqpp * psiqpp + psidpp * psidpp); + y_[9] = ksat = SB_ * pow(psipp - SA_, 2); + y_[10] = vd = -psiqpp * (1 + omega); + y_[11] = vq = psidpp * (1 + omega); + y_[12] = Te = (psidpp - id * Xdpp_) * iq - (psiqpp - iq * Xdpp_) * id; + y_[13] = id; + y_[14] = iq; + y_[15] = ir; + y_[16] = ii; + y_[17] = pmech_set_ = Te; + y_[18] = efd_set_ = Eqp + Xd1_ * (id + Xd3_ * (Eqp - psidp - Xd2_ * id)) + psidpp * ksat; + y_[19] = G_ * (vd * sin(delta) + vq * cos(delta)) + - B_ * (vd * -cos(delta) + vq * sin(delta)); /* inort, real */ + y_[20] = B_ * (vd * sin(delta) + vq * cos(delta)) + + G_ * (vd * -cos(delta) + vq * sin(delta)); /* inort, imag */ + + for (IdxT i = 0; i < size_; ++i) + yp_[i] = 0.0; + + return 0; + } + + /** + * \brief Identify differential variables. + */ + template + int Genrou::tagDifferentiable() + { + for (IdxT i = 0; i < size_; ++i) + { + tag_[i] = i < 6; + } + return 0; + } + + /** + * \brief Residual contribution of the branch is pushed to the + * two terminal buses. + * + */ + template + int Genrou::evaluateResidual() + { + /* Read variables */ + ScalarT delta = y_[0]; + ScalarT omega = y_[1]; + ScalarT Eqp = y_[2]; + ScalarT psidp = y_[3]; + ScalarT psiqp = y_[4]; + ScalarT Edp = y_[5]; + ScalarT psiqpp = y_[6]; + ScalarT psidpp = y_[7]; + ScalarT psipp = y_[8]; + ScalarT ksat = y_[9]; + ScalarT vd = y_[10]; + ScalarT vq = y_[11]; + ScalarT telec = y_[12]; + ScalarT id = y_[13]; + ScalarT iq = y_[14]; + ScalarT ir = y_[15]; + ScalarT ii = y_[16]; + ScalarT pmech = y_[17]; + ScalarT efd = y_[18]; + ScalarT inr = y_[19]; + ScalarT ini = y_[20]; + ScalarT vr = Vr(); + ScalarT vi = Vi(); + + /* Read derivatives */ + ScalarT delta_dot = yp_[0]; + ScalarT omega_dot = yp_[1]; + ScalarT Eqp_dot = yp_[2]; + ScalarT psidp_dot = yp_[3]; + ScalarT psiqp_dot = yp_[4]; + ScalarT Edp_dot = yp_[5]; + + /* 6 Genrou differential equations */ + f_[0] = delta_dot - omega * (2 * M_PI * 60); + f_[1] = omega_dot - (1 / (2 * H_)) * ((pmech - D_ * omega) / (1 + omega) - telec); + f_[2] = Eqp_dot - (1 / Tdop_) * (efd - (Eqp + Xd1_ * (id + Xd3_ * (Eqp - psidp - Xd2_ * id)) + psidpp * ksat)); + f_[3] = psidp_dot - (1 / Tdopp_) * (Eqp - psidp - Xd2_ * id); + f_[4] = psiqp_dot - (1 / Tqopp_) * (Edp - psiqp + Xq2_ * iq); + f_[5] = Edp_dot - (1 / Tqop_) * (-Edp + Xqd_ * psiqpp * ksat + Xq1_ * (iq - Xq3_ * (Edp + iq * Xq2_ - psiqp))); + + /* 11 Genrou algebraic equations */ + f_[6] = psiqpp - (-psiqp * Xq4_ - Edp * Xq5_); + f_[7] = psidpp - (psidp * Xd4_ + Eqp * Xd5_); + f_[8] = psipp - sqrt(pow(psidpp, 2.0) + pow(psiqpp, 2.0)); + f_[9] = ksat - SB_ * pow(psipp - SA_, 2.0); + f_[10] = vd + psiqpp * (1 + omega); + f_[11] = vq - psidpp * (1 + omega); + f_[12] = telec - ((psidpp - id * Xdpp_) * iq - (psiqpp - iq * Xdpp_) * id); + f_[13] = id - (ir * sin(delta) - ii * cos(delta)); + f_[14] = iq - (ir * cos(delta) + ii * sin(delta)); + f_[15] = ir + G_ * vr - B_ * vi - inr; + f_[16] = ii + B_ * vr + G_ * vi - ini; + + /* 2 Genrou control inputs are set to constant for this example */ + f_[17] = pmech - pmech_set_; + f_[18] = efd - efd_set_; + + /* 2 Genrou current source definitions */ + f_[19] = inr - (G_ * (sin(delta) * vd + cos(delta) * vq) - B_ * (-cos(delta) * vd + sin(delta) * vq)); + f_[20] = ini - (B_ * (sin(delta) * vd + cos(delta) * vq) + G_ * (-cos(delta) * vd + sin(delta) * vq)); + + /* Current balance */ + Ir() += inr - Vr() * G_ + Vi() * B_; + Ii() += ini - Vr() * B_ - Vi() * G_; + + 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 Genrou::evaluateJacobian() + { + std::cout << "Evaluate Jacobian for Genrou..." << 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 Genrou::evaluateIntegrand() + { + // std::cout << "Evaluate Integrand for Genrou..." << 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 Genrou::initializeAdjoint() + { + // std::cout << "Initialize adjoint for Genrou..." << 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 Genrou::evaluateAdjointResidual() + { + // std::cout << "Evaluate adjoint residual for Genrou..." << 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 Genrou::evaluateAdjointIntegrand() + { + // std::cout << "Evaluate adjoint Integrand for Genrou..." << std::endl; + return 0; + } + + template + void Genrou::setDerivedParams() + { + SA_ = 0; + SB_ = 0; + if (S12_ != 0) + { + real_type s112 = sqrt(S10_ / S12_); + + SA_ = (1.2 * s112 + 1) / (s112 + 1); + SB_ = (1.2 * s112 - 1) / (s112 - 1); + if (SB_ < SA_) + SA_ = SB_; + SB_ = S12_ / pow(SA_ - 1.2, 2); + } + Xd1_ = Xd_ - Xdp_; + Xd2_ = Xdp_ - Xl_; + Xd3_ = (Xdp_ - Xdpp_) / (Xd2_ * Xd2_); + Xd4_ = (Xdp_ - Xdpp_) / Xd2_; + Xd5_ = (Xdpp_ - Xl_) / Xd2_; + Xq1_ = Xq_ - Xqp_; + Xq2_ = Xqp_ - Xl_; + Xq3_ = (Xqp_ - Xqpp_) / (Xq2_ * Xq2_); + Xq4_ = (Xqp_ - Xqpp_) / Xq2_; + Xq5_ = (Xqpp_ - Xl_) / Xq2_; + Xqd_ = (Xq_ - Xl_) / (Xd_ - Xl_); + G_ = Ra_ / (Ra_ * Ra_ + Xqpp_ * Xqpp_); + B_ = -Xqpp_ / (Ra_ * Ra_ + Xqpp_ * Xqpp_); + } + + // Available template instantiations + template class Genrou; + template class Genrou; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp new file mode 100644 index 000000000..1f05fc876 --- /dev/null +++ b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp @@ -0,0 +1,163 @@ +/** + * @file Genrou.cpp + * @author Adam Birchfield (abirchfield@tamu.edu) + * @author Slaven Peles (peless@ornl.gov) + * @brief Declaration of a GENROU generator model. + * + */ + +#pragma once + +#include + +// Forward declarations. +namespace GridKit +{ + namespace PhasorDynamics + { + template + class BusBase; + } +} // namespace GridKit + +namespace GridKit +{ + namespace PhasorDynamics + { + + template + class Genrou : public Component + { + using Component::alpha_; + using Component::f_; + using Component::fB_; + using Component::g_; + using Component::gB_; + using Component::nnz_; + using Component::param_; + using Component::size_; + using Component::tag_; + using Component::time_; + using Component::y_; + using Component::yB_; + using Component::yp_; + using Component::ypB_; + + using bus_type = BusBase; + using real_type = typename Component::real_type; + + public: + Genrou(bus_type* bus, int unit_id); + Genrou(bus_type* bus, + int unit_id, + ScalarT p0, + ScalarT q0, + real_type H, + real_type D, + real_type Ra, + real_type Tdop, + real_type Tdopp, + real_type Tqopp, + real_type Tqop, + real_type Xd, + real_type Xdp, + real_type Xdpp, + real_type Xq, + real_type Xqp, + real_type Xqpp, + real_type Xl, + real_type S10, + real_type S12); + ~Genrou() = default; + + int allocate() override; + int initialize() override; + int tagDifferentiable() override; + int evaluateResidual() override; + + // Still to be implemented + int evaluateJacobian() override; + int evaluateIntegrand() override; + int initializeAdjoint() override; + int evaluateAdjointResidual() override; + int evaluateAdjointIntegrand() override; + + void updateTime(real_type /* t */, real_type /* a */) override + { + } + + private: + void setDerivedParams(); + + ScalarT& Vr() + { + return bus_->Vr(); + } + + ScalarT& Vi() + { + return bus_->Vi(); + } + + ScalarT& Ir() + { + return bus_->Ir(); + } + + ScalarT& Ii() + { + return bus_->Ii(); + } + + private: + /* Identification */ + bus_type* bus_; + const int busID_; + int unit_id_; + + /* Initial terminal conditions */ + ScalarT p0_; + ScalarT q0_; + + /* Input parameters */ + real_type H_; + real_type D_; + real_type Ra_; + real_type Tdop_; + real_type Tdopp_; + real_type Tqopp_; + real_type Tqop_; + real_type Xd_; + real_type Xdp_; + real_type Xdpp_; + real_type Xq_; + real_type Xqp_; + real_type Xqpp_; + real_type Xl_; + real_type S10_; + real_type S12_; + + /* Derivied parameters */ + real_type SA_; + real_type SB_; + real_type Xd1_; + real_type Xd2_; + real_type Xd3_; + real_type Xd4_; + real_type Xd5_; + real_type Xq1_; + real_type Xq2_; + real_type Xq3_; + real_type Xq4_; + real_type Xq5_; + real_type Xqd_; + real_type G_; + real_type B_; + + /* Setpoints for control variables (determined at initialization) */ + real_type pmech_set_; + real_type efd_set_; + }; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/ComponentLib/SynchronousMachine/GENROUwS/README.md b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/README.md similarity index 83% rename from ComponentLib/SynchronousMachine/GENROUwS/README.md rename to src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/README.md index ea9a20da5..fec362fec 100644 --- a/ComponentLib/SynchronousMachine/GENROUwS/README.md +++ b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/README.md @@ -6,7 +6,7 @@ - same relative amount of saturation occurs on both $`d`$ and $`q`$ axis
- + Figure 2: GENROU. Figure courtesy of [PowerWorld](https://www.powerworld.com/WebHelp/) @@ -93,9 +93,14 @@ then Sat(\psi'')=Sat(\vert V_{r}+jV_{i} \vert) ``` -It is important to point out that finding the initial value of $`\delta`$ for the model without saturation direct method can be used. In case when saturation is considered some "claver" math is needed. Key insight for determining initial $`\delta`$ is that the magnitude of the saturation depends upon the magnitude of $`\psi''`$, which is independent of $`\delta`$. +It is important to point out that finding the initial value of $`\delta`$ for +the model without saturation direct method can be used. In case when saturation +is considered some "claver" math is needed. Key insight for determining initial +$`\delta`$ is that the magnitude of the saturation depends upon the magnitude +of $`\psi''`$, which is independent of $`\delta`$. ```math -\delta=tan^{-1}(\dfrac{K_{sat}V_{iterm}+K_{sat}R_{a}I_{i}+(K_{sat}X''_{d}+X_{q}-X''_{q})I_{r}}{K_{sat}V_{rterm}+K_{sat}R_{a}I_{r}-(K_{sat}X''_{d}+X_{q}-X''_{q})I_{i}}) +\delta=\tan^{-1}\left(\dfrac{K_{sat}V_{iterm}+K_{sat}R_{a}I_{i}+(K_{sat}X''_{d}+X_{q}-X''_{q})I_{r}} + {K_{sat}V_{rterm}+K_{sat}R_{a}I_{r}-(K_{sat}X''_{d}+X_{q}-X''_{q})I_{i}} \right) ``` where ```math diff --git a/ComponentLib/SynchronousMachine/GENSALwS/README.md b/src/Model/PhasorDynamics/SynchronousMachine/GENSALwS/README.md similarity index 93% rename from ComponentLib/SynchronousMachine/GENSALwS/README.md rename to src/Model/PhasorDynamics/SynchronousMachine/GENSALwS/README.md index 9c5b8978c..4d4c87900 100644 --- a/ComponentLib/SynchronousMachine/GENSALwS/README.md +++ b/src/Model/PhasorDynamics/SynchronousMachine/GENSALwS/README.md @@ -8,7 +8,7 @@ - $`T'_{q0}`$ is neglected
- + Figure 2: GENSAL. Figure courtesy of [PowerWorld](https://www.powerworld.com/WebHelp/) @@ -60,33 +60,3 @@ T''_{d0}\dfrac{d\psi'_{d}}{dt}=-\psi'_{d}-(X'_{d}-X_{l})I_{d}+E'_{q} ```math T''_{q0}\dfrac{d\psi''_{q}}{dt}=-\psi''_{q}-(X_{q}-X''_{q})I_{q} ``` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ComponentLib/SynchronousMachine/README.md b/src/Model/PhasorDynamics/SynchronousMachine/README.md similarity index 95% rename from ComponentLib/SynchronousMachine/README.md rename to src/Model/PhasorDynamics/SynchronousMachine/README.md index 66c5ccb0f..69db2c35f 100644 --- a/ComponentLib/SynchronousMachine/README.md +++ b/src/Model/PhasorDynamics/SynchronousMachine/README.md @@ -9,7 +9,7 @@
- + Figure 1: Synchronous Machine. Figure courtesy of [PowerWorld](https://www.powerworld.com/files/Synchronous-Machines.pdf) @@ -107,7 +107,7 @@ T'_{q0}\dfrac{dE'_{d}}{dt}= -E'_{d}+(X_{q}-X'_{q})(I_{q}-\dfrac{X'_{q}-X''_{q}}{ ``` Previos equations can be used to model any machine, however ***SATURATION*** is missing. -Saturation means increasingly large amounts of current are needed to increase the flux density. There are various methods to include the saturation (it is not standardized yet). We are going to use the approach implemented in PTI PSSS/E and PowerWorld Simulator (scaled quadratic). +Saturation means increasingly large amounts of current are needed to increase the flux density. There are various methods to include the saturation (it is not standardized yet). We are going to use the approach implemented in PTI PSS/E and PowerWorld Simulator (scaled quadratic). ```math Sat(x) = \begin{cases} @@ -117,6 +117,6 @@ Sat(x) = \begin{cases} ``` There are two solutions, and one where $`A<1`$ should be chosen. -Hint! +#### Hint Negative values are not allowed. diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp new file mode 100644 index 000000000..03347b224 --- /dev/null +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -0,0 +1,658 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + + /** + * @brief Prototype for a system model class + * + * This class maps component data to system data and implements + * Model::Evaluator for the system model. This is still work in + * progress and code is not optimized. + * + * @todo Address thread safety for the system model methods. + * + */ + template + class SystemModel : public PhasorDynamics::Component + { + using bus_type = PhasorDynamics::BusBase; + using component_type = PhasorDynamics::Component; + using real_type = typename Model::Evaluator::real_type; + + using PhasorDynamics::Component::size_; + using PhasorDynamics::Component::size_quad_; + using PhasorDynamics::Component::size_param_; + using PhasorDynamics::Component::nnz_; + using PhasorDynamics::Component::time_; + using PhasorDynamics::Component::alpha_; + using PhasorDynamics::Component::y_; + using PhasorDynamics::Component::yp_; + using PhasorDynamics::Component::yB_; + using PhasorDynamics::Component::ypB_; + using PhasorDynamics::Component::tag_; + using PhasorDynamics::Component::f_; + using PhasorDynamics::Component::fB_; + using PhasorDynamics::Component::g_; + using PhasorDynamics::Component::gB_; + using PhasorDynamics::Component::rel_tol_; + using PhasorDynamics::Component::abs_tol_; + using PhasorDynamics::Component::param_; + using PhasorDynamics::Component::param_up_; + using PhasorDynamics::Component::param_lo_; + + public: + /** + * @brief Constructor for the system model + */ + SystemModel() + { + // Set system model tolerances + rel_tol_ = 1e-7; + abs_tol_ = 1e-9; + this->max_steps_ = 2000; + } + + /** + * @brief Destructor for the system model + */ + virtual ~SystemModel() + { + } + + /** + * @brief Allocate buses, components, and system objects. + * + * This method first allocates bus objects, then component objects, + * and computes system size (number of unknowns). Once the size is + * computed, system global objects are allocated. + * + * @post size_quad_ == 0 or 1 + * @post size_ >= 1 + * @post size_param_ >= 0 + * + */ + int allocate() + { + size_ = 0; + size_quad_ = 0; + size_param_ = 0; + + // Allocate all buses + for (const auto& bus : buses_) + { + bus->allocate(); + size_ += bus->size(); + size_quad_ += bus->sizeQuadrature(); + size_param_ += bus->sizeParams(); + } + + // Allocate all components + for (const auto& component : components_) + { + component->allocate(); + size_ += component->size(); + size_quad_ += component->sizeQuadrature(); + size_param_ += component->sizeParams(); + } + + // Allocate global vectors + y_.resize(size_); + yp_.resize(size_); + yB_.resize(size_); + ypB_.resize(size_); + f_.resize(size_); + fB_.resize(size_); + tag_.resize(size_); + + g_.resize(size_quad_); + gB_.resize(size_quad_ * size_param_); + + param_.resize(size_param_); + param_lo_.resize(size_param_); + param_up_.resize(size_param_); + + assert(size_quad_ == 1 or size_quad_ == 0); + + return 0; + } + + /** + * @brief Assume that jacobian is not avalible + * + * @return true + * @return false + */ + bool hasJacobian() + { + return false; + } + + /** + * @brief Initialize buses first, then all the other components. + * + * @pre All buses and components must be allocated at this point. + * @pre Bus variables are written before component variables in the + * system variable vector. + * + * Buses must be initialized before other components, because other + * components may write to buses during the initialization. + * + * Also, generators may write to control devices (e.g. governors, + * exciters, etc.) during the initialization. + * + * @todo Implement writting to system vectors in a thread-safe way. + */ + int initialize() + { + // Set initial values for global solution vectors + IdxT varOffset = 0; + IdxT optOffset = 0; + + for (const auto& bus : buses_) + { + bus->initialize(); + } + + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + y_[varOffset + j] = bus->y()[j]; + yp_[varOffset + j] = bus->yp()[j]; + } + varOffset += bus->size(); + + for (IdxT j = 0; j < bus->sizeParams(); ++j) + { + param_[optOffset + j] = bus->param()[j]; + param_lo_[optOffset + j] = bus->param_lo()[j]; + param_up_[optOffset + j] = bus->param_up()[j]; + } + optOffset += bus->sizeParams(); + } + + // Initialize components + for (const auto& component : components_) + { + component->initialize(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + y_[varOffset + j] = component->y()[j]; + yp_[varOffset + j] = component->yp()[j]; + } + varOffset += component->size(); + + for (IdxT j = 0; j < component->sizeParams(); ++j) + { + param_[optOffset + j] = component->param()[j]; + param_lo_[optOffset + j] = component->param_lo()[j]; + param_up_[optOffset + j] = component->param_up()[j]; + } + optOffset += component->sizeParams(); + } + + return 0; + } + + /** + * @todo Tagging differential variables + * + * Identify what variables in the system of differential-algebraic + * equations are differential variables, i.e. their derivatives + * appear in the equations. + */ + int tagDifferentiable() + { + // Set initial values for global solution vectors + IdxT offset = 0; + for (const auto& bus : buses_) + { + bus->tagDifferentiable(); + for (IdxT j = 0; j < bus->size(); ++j) + { + tag_[offset + j] = bus->tag()[j]; + } + offset += bus->size(); + } + + for (const auto& component : components_) + { + component->tagDifferentiable(); + for (IdxT j = 0; j < component->size(); ++j) + { + tag_[offset + j] = component->tag()[j]; + } + offset += component->size(); + } + + return 0; + } + + /** + * @brief Compute system residual vector + * + * First, update bus and component variables from the system solution + * vector. Next, evaluate residuals in buses and components, and + * then copy values to the global residual vector. + * + * @warning Residuals must be computed for buses, before component + * residuals are computed. Buses own residuals for active and + * power P and Q, but the contributions to these residuals come + * from components. Buses assign their residual values, while components + * add to those values by in-place adition. This is why bus residuals + * need to be computed first. + * + * @todo Here, components write to local values, which are then copied + * to global system vectors. Make components write to the system + * vectors directly. + */ + int evaluateResidual() + { + // Update variables + IdxT varOffset = 0; + IdxT optOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + bus->y()[j] = y_[varOffset + j]; + bus->yp()[j] = yp_[varOffset + j]; + } + varOffset += bus->size(); + + for (IdxT j = 0; j < bus->sizeParams(); ++j) + { + bus->param()[j] = param_[optOffset + j]; + } + optOffset += bus->sizeParams(); + + bus->evaluateResidual(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + component->y()[j] = y_[varOffset + j]; + component->yp()[j] = yp_[varOffset + j]; + } + varOffset += component->size(); + + for (IdxT j = 0; j < component->sizeParams(); ++j) + { + component->param()[j] = param_[optOffset + j]; + } + optOffset += component->sizeParams(); + + component->evaluateResidual(); + } + + // Update residual vector + IdxT resOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + f_[resOffset + j] = bus->getResidual()[j]; + } + resOffset += bus->size(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + f_[resOffset + j] = component->getResidual()[j]; + } + resOffset += component->size(); + } + + return 0; + } + + /** + * @brief Evaluate system Jacobian. + * + * @todo Need to implement Jacobian. For now, using finite difference + * approximation provided by IDA. This works for dense Jacobian matrix + * only. + * + */ + int evaluateJacobian() + { + return 0; + } + + /** + * @brief Evaluate integrands for the system quadratures. + */ + int evaluateIntegrand() + { + // Update variables + IdxT varOffset = 0; + IdxT optOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + bus->y()[j] = y_[varOffset + j]; + bus->yp()[j] = yp_[varOffset + j]; + } + varOffset += bus->size(); + + for (IdxT j = 0; j < bus->sizeParams(); ++j) + { + bus->param()[j] = param_[optOffset + j]; + } + optOffset += bus->sizeParams(); + + bus->evaluateIntegrand(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + component->y()[j] = y_[varOffset + j]; + component->yp()[j] = yp_[varOffset + j]; + } + varOffset += component->size(); + + for (IdxT j = 0; j < component->sizeParams(); ++j) + { + component->param()[j] = param_[optOffset + j]; + } + optOffset += component->sizeParams(); + + component->evaluateIntegrand(); + } + + // Update integrand vector + IdxT intOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->sizeQuadrature(); ++j) + { + g_[intOffset + j] = bus->getIntegrand()[j]; + } + intOffset += bus->sizeQuadrature(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->sizeQuadrature(); ++j) + { + g_[intOffset + j] = component->getIntegrand()[j]; + } + intOffset += component->sizeQuadrature(); + } + + return 0; + } + + /** + * @brief Initialize system adjoint. + * + * Updates variables and optimization parameters, then initializes + * adjoints locally and copies them to the system adjoint vector. + */ + int initializeAdjoint() + { + IdxT offset = 0; + IdxT optOffset = 0; + + // Update bus variables and optimization parameters + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + bus->y()[j] = y_[offset + j]; + bus->yp()[j] = yp_[offset + j]; + } + offset += bus->size(); + + for (IdxT j = 0; j < bus->sizeParams(); ++j) + { + bus->param()[j] = param_[optOffset + j]; + } + optOffset += bus->sizeParams(); + } + + // Update component variables and optimization parameters + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + component->y()[j] = y_[offset + j]; + component->yp()[j] = yp_[offset + j]; + } + offset += component->size(); + + for (IdxT j = 0; j < component->sizeParams(); ++j) + { + component->param()[j] = param_[optOffset + j]; + } + optOffset += component->sizeParams(); + } + + // Reset counter + offset = 0; + + // Initialize bus adjoints + for (const auto& bus : buses_) + { + bus->initializeAdjoint(); + + for (IdxT j = 0; j < bus->size(); ++j) + { + yB_[offset + j] = bus->yB()[j]; + ypB_[offset + j] = bus->ypB()[j]; + } + offset += bus->size(); + } + + // Initialize component adjoints + for (const auto& component : components_) + { + component->initializeAdjoint(); + + for (IdxT j = 0; j < component->size(); ++j) + { + yB_[offset + j] = component->yB()[j]; + ypB_[offset + j] = component->ypB()[j]; + } + offset += component->size(); + } + + return 0; + } + + /** + * @brief Compute adjoint residual for the system model. + * + * @warning Components write to bus residuals. Do not copy bus residuals + * to system vectors before components computed their residuals. + * + */ + int evaluateAdjointResidual() + { + IdxT varOffset = 0; + IdxT optOffset = 0; + + // Update variables in component models + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + bus->y()[j] = y_[varOffset + j]; + bus->yp()[j] = yp_[varOffset + j]; + bus->yB()[j] = yB_[varOffset + j]; + bus->ypB()[j] = ypB_[varOffset + j]; + } + varOffset += bus->size(); + + for (IdxT j = 0; j < bus->sizeParams(); ++j) + { + bus->param()[j] = param_[optOffset + j]; + } + optOffset += bus->sizeParams(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + component->y()[j] = y_[varOffset + j]; + component->yp()[j] = yp_[varOffset + j]; + component->yB()[j] = yB_[varOffset + j]; + component->ypB()[j] = ypB_[varOffset + j]; + } + varOffset += component->size(); + + for (IdxT j = 0; j < component->sizeParams(); ++j) + { + component->param()[j] = param_[optOffset + j]; + } + optOffset += component->sizeParams(); + } + + for (const auto& bus : buses_) + { + bus->evaluateAdjointResidual(); + } + + for (const auto& component : components_) + { + component->evaluateAdjointResidual(); + } + + // Update residual vector + IdxT resOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + fB_[resOffset + j] = bus->getAdjointResidual()[j]; + } + resOffset += bus->size(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + fB_[resOffset + j] = component->getAdjointResidual()[j]; + } + resOffset += component->size(); + } + + return 0; + } + + // int evaluateAdjointJacobian(){return 0;} + + /** + * @brief Evaluate adjoint integrand for the system model. + * + * @pre Assumes there are no integrands in bus models. + * @pre Assumes integrand is implemented in only _one_ component. + * + */ + int evaluateAdjointIntegrand() + { + // First, update variables + IdxT varOffset = 0; + IdxT optOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + bus->y()[j] = y_[varOffset + j]; + bus->yp()[j] = yp_[varOffset + j]; + bus->yB()[j] = yB_[varOffset + j]; + bus->ypB()[j] = ypB_[varOffset + j]; + } + varOffset += bus->size(); + + for (IdxT j = 0; j < bus->sizeParams(); ++j) + { + bus->param()[j] = param_[optOffset + j]; + } + optOffset += bus->sizeParams(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + component->y()[j] = y_[varOffset + j]; + component->yp()[j] = yp_[varOffset + j]; + component->yB()[j] = yB_[varOffset + j]; + component->ypB()[j] = ypB_[varOffset + j]; + } + varOffset += component->size(); + + for (IdxT j = 0; j < component->sizeParams(); ++j) + { + component->param()[j] = param_[optOffset + j]; + } + optOffset += component->sizeParams(); + } + + // Evaluate integrand and update global vector + for (const auto& component : components_) + { + if (component->sizeQuadrature() == 1) + { + component->evaluateAdjointIntegrand(); + for (IdxT j = 0; j < size_param_; ++j) + { + gB_[j] = component->getAdjointIntegrand()[j]; + } + break; + } + } + return 0; + } + + void updateTime(real_type t, real_type a) + { + for (const auto& component : components_) + { + component->updateTime(t, a); + } + } + + void addBus(bus_type* bus) + { + buses_.push_back(bus); + } + + void addComponent(component_type* component) + { + components_.push_back(component); + } + + private: + std::vector buses_; + std::vector components_; + + }; // class SystemModel + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PowerElectronics/CMakeLists.txt b/src/Model/PowerElectronics/CMakeLists.txt new file mode 100644 index 000000000..d703d3006 --- /dev/null +++ b/src/Model/PowerElectronics/CMakeLists.txt @@ -0,0 +1,14 @@ + + +add_subdirectory(Capacitor) +add_subdirectory(Resistor) +add_subdirectory(VoltageSource) +add_subdirectory(Inductor) +add_subdirectory(LinearTransformer) +add_subdirectory(InductionMotor) +add_subdirectory(SynchronousMachine) +add_subdirectory(DistributedGenerator) +add_subdirectory(TransmissionLine) +add_subdirectory(MicrogridLoad) +add_subdirectory(MicrogridLine) +add_subdirectory(MicrogridBusDQ) diff --git a/src/Model/PowerElectronics/Capacitor/CMakeLists.txt b/src/Model/PowerElectronics/Capacitor/CMakeLists.txt new file mode 100644 index 000000000..e91fcb5ed --- /dev/null +++ b/src/Model/PowerElectronics/Capacitor/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(power_elec_capacitor + SOURCES + Capacitor.cpp + OUTPUT_NAME + gridkit_power_elec_capacitor) diff --git a/src/Model/PowerElectronics/Capacitor/Capacitor.cpp b/src/Model/PowerElectronics/Capacitor/Capacitor.cpp new file mode 100644 index 000000000..497c3b19b --- /dev/null +++ b/src/Model/PowerElectronics/Capacitor/Capacitor.cpp @@ -0,0 +1,141 @@ + + +#include "Capacitor.hpp" + +#include +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for Capacitor + * + * @todo this needs to be tested on some circuit + * + * Calls default ModelEvaluatorImpl constructor. + */ + + template + Capacitor::Capacitor(IdxT id, ScalarT C) + : C_(C) + { + size_ = 3; + n_intern_ = 1; + n_extern_ = 2; + extern_indices_ = {0, 1}; + idc_ = id; + } + + template + Capacitor::~Capacitor() + { + } + + /*! + * @brief allocate method creates memory for vectors + */ + template + int Capacitor::allocate() + { + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + + return 0; + } + + /** + * Initialization of the grid model + */ + template + int Capacitor::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int Capacitor::tagDifferentiable() + { + return 0; + } + + /** + * @brief Evaluate the resisdual of the Capcitor + * + */ + template + int Capacitor::evaluateResidual() + { + // input + f_[0] = C_ * yp_[2]; + // output + f_[1] = -C_ * yp_[2]; + + // internal + f_[2] = -C_ * yp_[2] + y_[0] - y_[1] - y_[2]; + return 0; + } + + /** + * @brief Compute the Jacobian dF/dy - a dF/dy' + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ + template + int Capacitor::evaluateJacobian() + { + jac_.zeroMatrix(); + // Create dF/dy + std::vector rcord{2, 2, 2}; + std::vector ccord{0, 1, 2}; + std::vector vals{1.0, -1.0, -1.0}; + jac_.setValues(rcord, ccord, vals); + + // Create dF/dy' + std::vector rcordder{0, 1, 2}; + std::vector ccordder{2, 2, 2}; + std::vector valsder{C_, -C_, -C_}; + COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder, 3, 3); + + // Perform dF/dy + \alpha dF/dy' + jac_.axpy(alpha_, Jacder); + + return 0; + } + + template + int Capacitor::evaluateIntegrand() + { + return 0; + } + + template + int Capacitor::initializeAdjoint() + { + return 0; + } + + template + int Capacitor::evaluateAdjointResidual() + { + return 0; + } + + template + int Capacitor::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class Capacitor; + template class Capacitor; + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/Capacitor/Capacitor.hpp b/src/Model/PowerElectronics/Capacitor/Capacitor.hpp new file mode 100644 index 000000000..b86ed9139 --- /dev/null +++ b/src/Model/PowerElectronics/Capacitor/Capacitor.hpp @@ -0,0 +1,66 @@ + + +#ifndef _CAP_HPP_ +#define _CAP_HPP_ + +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Declaration of a Capacitor class. + * + */ + template + class Capacitor : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::jac_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + using CircuitComponent::extern_indices_; + using CircuitComponent::n_extern_; + using CircuitComponent::n_intern_; + + public: + Capacitor(IdxT id, ScalarT C); + virtual ~Capacitor(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT C_; + }; +} // namespace GridKit + +#endif diff --git a/src/Model/PowerElectronics/CircuitComponent.hpp b/src/Model/PowerElectronics/CircuitComponent.hpp new file mode 100644 index 000000000..56e0d4c5a --- /dev/null +++ b/src/Model/PowerElectronics/CircuitComponent.hpp @@ -0,0 +1,287 @@ + + +#pragma once + +#include +#include + +#include +#include + +namespace GridKit +{ + /*! + * @brief Declaration of a CircuitComponent class. + * + */ + template + class CircuitComponent : public Model::Evaluator + { + public: + typedef typename Model::Evaluator::real_type real_type; + + CircuitComponent() = default; + ~CircuitComponent() = default; + + void updateTime(ScalarT t, ScalarT a) + { + this->time_ = t; + this->alpha_ = a; + } + + bool hasJacobian() + { + return true; + } + + size_t getExternSize() + { + return n_extern_; + } + + size_t getInternalSize() + { + return this->n_intern_; + } + + std::set getExternIndices() + { + return this->extern_indices_; + } + + /** + * @brief Create the mappings from local to global indices + * + * @param local_index + * @param global_index + * @return int + */ + int setExternalConnectionNodes(IdxT local_index, IdxT global_index) + { + connection_nodes_[local_index] = global_index; + return 0; + } + + /** + * @brief Given the location of value in the local vector map to global index + * + * f(local_index) = global_index + * + * @param local_index index of local value in vector + * @return IdxT Index of the same value in the global vector + */ + IdxT getNodeConnection(IdxT local_index) + { + return connection_nodes_.at(local_index); + } + + public: + virtual IdxT size() + { + return size_; + } + + virtual IdxT nnz() + { + return nnz_; + } + + virtual IdxT sizeQuadrature() + { + return size_quad_; + } + + virtual IdxT sizeParams() + { + return size_opt_; + } + + virtual void setTolerances(real_type& rel_tol, real_type& abs_tol) const + { + rel_tol = rel_tol_; + abs_tol = abs_tol_; + } + + virtual void setMaxSteps(IdxT& msa) const + { + msa = max_steps_; + } + + std::vector& y() + { + return y_; + } + + const std::vector& y() const + { + return y_; + } + + std::vector& yp() + { + return yp_; + } + + const std::vector& yp() const + { + return yp_; + } + + std::vector& tag() + { + return tag_; + } + + const std::vector& tag() const + { + return tag_; + } + + std::vector& yB() + { + return yB_; + } + + const std::vector& yB() const + { + return yB_; + } + + std::vector& ypB() + { + return ypB_; + } + + const std::vector& ypB() const + { + return ypB_; + } + + std::vector& param() + { + return param_; + } + + const std::vector& param() const + { + return param_; + } + + std::vector& param_up() + { + return param_up_; + } + + const std::vector& param_up() const + { + return param_up_; + } + + std::vector& param_lo() + { + return param_lo_; + } + + const std::vector& param_lo() const + { + return param_lo_; + } + + std::vector& getResidual() + { + return f_; + } + + const std::vector& getResidual() const + { + return f_; + } + + COO_Matrix& getJacobian() + { + return jac_; + } + + const COO_Matrix& getJacobian() const + { + return jac_; + } + + std::vector& getIntegrand() + { + return g_; + } + + const std::vector& getIntegrand() const + { + return g_; + } + + std::vector& getAdjointResidual() + { + return fB_; + } + + const std::vector& getAdjointResidual() const + { + return fB_; + } + + std::vector& getAdjointIntegrand() + { + return gB_; + } + + const std::vector& getAdjointIntegrand() const + { + return gB_; + } + + //@todo Fix ID naming + IdxT getIDcomponent() + { + return idc_; + } + + protected: + size_t n_extern_; + size_t n_intern_; + std::set extern_indices_; + ///@todo may want to replace the mapping of connection_nodes to Node objects instead of IdxT. Allows for container free setup + std::map connection_nodes_; + + protected: + IdxT size_{0}; + IdxT nnz_{0}; + IdxT size_quad_{0}; + IdxT size_opt_{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 jac_; + + std::vector param_; + std::vector param_up_; + std::vector param_lo_; + + real_type time_; + real_type alpha_; + + real_type rel_tol_; + real_type abs_tol_; + + IdxT max_steps_; + + IdxT idc_; + }; + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/DistributedGenerator/CMakeLists.txt b/src/Model/PowerElectronics/DistributedGenerator/CMakeLists.txt new file mode 100644 index 000000000..6d38d4536 --- /dev/null +++ b/src/Model/PowerElectronics/DistributedGenerator/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(power_elec_disgen + SOURCES + DistributedGenerator.cpp + OUTPUT_NAME + gridkit_power_elec_disgen) diff --git a/src/Model/PowerElectronics/DistributedGenerator/DistributedGenerator.cpp b/src/Model/PowerElectronics/DistributedGenerator/DistributedGenerator.cpp new file mode 100644 index 000000000..5be1802d6 --- /dev/null +++ b/src/Model/PowerElectronics/DistributedGenerator/DistributedGenerator.cpp @@ -0,0 +1,394 @@ + + +#include "DistributedGenerator.hpp" + +#include +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a Distributed Generator + * @todo Maybe have parameters be templated in. Variables cannot be changed + * and are unlikely to. Allows for compile time optimizations + * + * Calls default ModelEvaluatorImpl constructor. + */ + template + DistributedGenerator::DistributedGenerator(IdxT id, + DistributedGeneratorParameters parm, + bool reference_frame) + : wb_(parm.wb_), + wc_(parm.wc_), + mp_(parm.mp_), + Vn_(parm.Vn_), + nq_(parm.nq_), + F_(parm.F_), + Kiv_(parm.Kiv_), + Kpv_(parm.Kpv_), + Kic_(parm.Kic_), + Kpc_(parm.Kpc_), + Cf_(parm.Cf_), + rLf_(parm.rLf_), + Lf_(parm.Lf_), + rLc_(parm.rLc_), + Lc_(parm.Lc_), + refframe_(reference_frame) + { + // internals [\delta_i, Pi, Qi, phi_di, phi_qi, gamma_di, gamma_qi, il_di, il_qi, vo_di, vo_qi, io_di, io_qi] + // externals [\omega_ref, vba_out, vbb_out] + size_ = 16; + n_intern_ = 13; + n_extern_ = 3; + extern_indices_ = {0, 1, 2}; + idc_ = id; + } + + template + DistributedGenerator::~DistributedGenerator() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int DistributedGenerator::allocate() + { + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + + return 0; + } + + /** + * Initialization of the grid model + */ + template + int DistributedGenerator::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int DistributedGenerator::tagDifferentiable() + { + return 0; + } + + /** + * @brief Contributes to the resisdual of the Distributed Generator + * + */ + template + int DistributedGenerator::evaluateResidual() + { + // ### Externals Componenets ### + + ScalarT omega = wb_ - mp_ * y_[4]; + // ref common ref motor angle + /// @todo fix boolian conditional, unclear result + if (refframe_) + { + f_[0] = omega - y_[0]; + } + else + { + f_[0] = 0.0; + } + + // output + // current transformed to common frame + f_[1] = cos(y_[3]) * y_[14] - sin(y_[3]) * y_[15]; + f_[2] = sin(y_[3]) * y_[14] + cos(y_[3]) * y_[15]; + + // Take incoming voltages to current rotator reference frame + ScalarT vbd_in = cos(y_[3]) * y_[1] + sin(y_[3]) * y_[2]; + ScalarT vbq_in = -sin(y_[3]) * y_[1] + cos(y_[3]) * y_[2]; + + // ### Internal Componenets ## + // Rotor difference angle + f_[3] = -yp_[3] + omega - y_[0]; + + // P and Q equations + f_[4] = -yp_[4] + wc_ * (y_[12] * y_[14] + y_[13] * y_[15] - y_[4]); + f_[5] = -yp_[5] + wc_ * (-y_[12] * y_[15] + y_[13] * y_[14] - y_[5]); + + // Voltage control + ScalarT vod_star = Vn_ - nq_ * y_[5]; + ScalarT voq_star = 0.0; + + f_[6] = -yp_[6] + vod_star - y_[12]; + f_[7] = -yp_[7] + voq_star - y_[13]; + + ScalarT ild_star = F_ * y_[14] - wb_ * Cf_ * y_[13] + Kpv_ * (vod_star - y_[12]) + Kiv_ * y_[6]; + ScalarT ilq_star = F_ * y_[15] + wb_ * Cf_ * y_[12] + Kpv_ * (voq_star - y_[13]) + Kiv_ * y_[7]; + + // Current control + f_[8] = -yp_[8] + ild_star - y_[10]; + f_[9] = -yp_[9] + ilq_star - y_[11]; + + ScalarT vid_star = -wb_ * Lf_ * y_[11] + Kpc_ * (ild_star - y_[10]) + Kic_ * y_[8]; + ScalarT viq_star = wb_ * Lf_ * y_[10] + Kpc_ * (ilq_star - y_[11]) + Kic_ * y_[9]; + + // Output LC Filter + f_[10] = -yp_[10] - (rLf_ / Lf_) * y_[10] + omega * y_[11] + (vid_star - y_[12]) / Lf_; + f_[11] = -yp_[11] - (rLf_ / Lf_) * y_[11] - omega * y_[10] + (viq_star - y_[13]) / Lf_; + + f_[12] = -yp_[12] + omega * y_[13] + (y_[10] - y_[14]) / Cf_; + f_[13] = -yp_[13] - omega * y_[12] + (y_[11] - y_[15]) / Cf_; + + // Output Connector + f_[14] = -yp_[14] - (rLc_ / Lc_) * y_[14] + omega * y_[15] + (y_[12] - vbd_in) / Lc_; + f_[15] = -yp_[15] - (rLc_ / Lc_) * y_[15] - omega * y_[14] + (y_[13] - vbq_in) / Lc_; + return 0; + } + + /** + * @brief Compute the jacobian of the DistributedGenerator for iteration. dF/dy - \alpha dF/dy' + * + * The matrix dF/dy should be + * + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + [-1, 0, 0, 0, -mp, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + [ 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, 0, wc*x15, wc*x16, wc*x13, wc*x14] + [ 0, 0, 0, 0, 0, -wc, 0, 0, 0, 0, 0, 0, -wc*x16, wc*x15, wc*x14, -wc*x13] + [ 0, 0, 0, 0, 0, -nq, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0] + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0] + [ 0, 0, 0, 0, 0, -Kpv*nq, Kiv, 0, 0, 0, -1, 0, -Kpv, -Cf*wb, F, 0] + [ 0, 0, 0, 0, 0, 0, 0, Kiv, 0, 0, 0, -1, Cf*wb, -Kpv, 0, F] + [ 0, 0, 0, 0, -mp*x12, -(Kpc*Kpv*nq)/Lf, (Kiv*Kpc)/Lf, 0, Kic/Lf, 0, - Kpc/Lf - rLf/Lf, -mp*x5, -(Kpc*Kpv + 1)/Lf, -(Cf*Kpc*wb)/Lf, (F*Kpc)/Lf, 0] + [ 0, 0, 0, 0, mp*x11, 0, 0, (Kiv*Kpc)/Lf, 0, Kic/Lf, mp*x5, - Kpc/Lf - rLf/Lf, (Cf*Kpc*wb)/Lf, -(Kpc*Kpv + 1)/Lf, 0, (F*Kpc)/Lf] + [ 0, 0, 0, 0, -mp*x14, 0, 0, 0, 0, 0, 1/Cf, 0, 0, wb - mp*x5, -1/Cf, 0] + [ 0, 0, 0, 0, mp*x13, 0, 0, 0, 0, 0, 0, 1/Cf, mp*x5 - wb, 0, 0, -1/Cf] + [ 0, -cos(x4)/Lc, -sin(x4)/Lc, -(x3*cos(x4) - x2*sin(x4))/Lc, -mp*x16, 0, 0, 0, 0, 0, 0, 0, 1/Lc, 0, -rLc/Lc, wb - mp*x5] + [ 0, sin(x4)/Lc, -cos(x4)/Lc, (x2*cos(x4) + x3*sin(x4))/Lc, mp*x15, 0, 0, 0, 0, 0, 0, 0, 0, 1/Lc, mp*x5 - wb, -rLc/Lc] + * 'Generated from MATLAB symbolic' + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ + template + int DistributedGenerator::evaluateJacobian() + { + jac_.zeroMatrix(); + // Create dF/dy' + std::vector rcordder(13); + std::vector valsder(13, -1.0); + for (int i = 0; i < 13; i++) + { + rcordder[i] = i + 3; + } + COO_Matrix Jacder = COO_Matrix(rcordder, rcordder, valsder, 16, 16); + + std::vector ctemp{}; + std::vector rtemp{}; + std::vector valtemp{}; + + // Create dF/dy + // r = 1 + + ctemp = {3, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(1); + valtemp = {-sin(y_[3]) * y_[14] - cos(y_[3]) * y_[15], cos(y_[3]), -sin(y_[3])}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 2 + + ctemp = {3, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(2); + valtemp = {cos(y_[3]) * y_[14] - sin(y_[3]) * y_[15], sin(y_[3]), cos(y_[3])}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 3 + + ctemp = {0, 4}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(3); + valtemp = {-1.0, -mp_}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 0 + if (refframe_) + { + ctemp = {0, 4}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(0); + valtemp = {-1.0, -mp_}; + jac_.setValues(rtemp, ctemp, valtemp); + } + + // r = 4 + ctemp = {4, 12, 13, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(4); + valtemp = {-wc_, wc_ * y_[14], wc_ * y_[15], wc_ * y_[12], wc_ * y_[13]}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 5 + ctemp = {5, 12, 13, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(5); + valtemp = {-wc_, -wc_ * y_[15], wc_ * y_[14], wc_ * y_[13], -wc_ * y_[12]}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 6 + ctemp = {5, 12}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(6); + valtemp = {-nq_, -1.0}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 7 + ctemp = {13}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(7); + valtemp = {-1.0}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 8 + ctemp = {5, 6, 10, 12, 13, 14}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(8); + valtemp = {-Kpv_ * nq_, Kiv_, -1.0, -Kpv_, -Cf_ * wb_, F_}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 9 + ctemp = {7, 11, 12, 13, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(9); + valtemp = {Kiv_, -1.0, Cf_ * wb_, -Kpv_, F_}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 10 + ctemp = {4, 5, 6, 8, 10, 11, 12, 13, 14}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(10); + valtemp = {-mp_ * y_[11], + -(Kpc_ * Kpv_ * nq_) / Lf_, + (Kpc_ * Kiv_) / Lf_, + Kic_ / Lf_, + -(Kpc_ + rLf_) / Lf_, + -mp_ * y_[4], + -(Kpc_ * Kpv_ + 1.0) / Lf_, + -(Cf_ * Kpc_ * wb_) / Lf_, + (F_ * Kpc_) / Lf_}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 11 + ctemp = {4, 7, 9, 10, 11, 12, 13, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(11); + valtemp = {mp_ * y_[10], + (Kiv_ * Kpc_) / Lf_, + Kic_ / Lf_, + mp_ * y_[4], + -(Kpc_ + rLf_) / Lf_, + (Cf_ * Kpc_ * wb_) / Lf_, + -(Kpc_ * Kpv_ + 1.0) / Lf_, + (F_ * Kpc_) / Lf_}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 12 + ctemp = {4, 10, 13, 14}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(12); + valtemp = {-mp_ * y_[13], 1.0 / Cf_, wb_ - mp_ * y_[4], -1.0 / Cf_}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 13 + ctemp = {4, 11, 12, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(13); + valtemp = {mp_ * y_[12], 1.0 / Cf_, -wb_ + mp_ * y_[4], -1.0 / Cf_}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 14 + ctemp = {1, 2, 3, 4, 12, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(14); + valtemp = {(1.0 / Lc_) * -cos(y_[3]), + (1.0 / Lc_) * -sin(y_[3]), + (1.0 / Lc_) * (sin(y_[3]) * y_[1] - cos(y_[3]) * y_[2]), + -mp_ * y_[15], + 1.0 / Lc_, + -rLc_ / Lc_, + wb_ - mp_ * y_[4]}; + jac_.setValues(rtemp, ctemp, valtemp); + + // r = 15 + ctemp = {1, 2, 3, 4, 13, 14, 15}; + rtemp.clear(); + for (size_t i = 0; i < ctemp.size(); i++) + rtemp.push_back(15); + valtemp = {(1.0 / Lc_) * sin(y_[3]), + (1.0 / Lc_) * -cos(y_[3]), + (1.0 / Lc_) * (cos(y_[3]) * y_[1] + sin(y_[3]) * y_[2]), + mp_ * y_[14], + 1.0 / Lc_, + -wb_ + mp_ * y_[4], + -rLc_ / Lc_}; + jac_.setValues(rtemp, ctemp, valtemp); + + // Perform dF/dy + \alpha dF/dy' + + jac_.axpy(alpha_, Jacder); + + return 0; + } + + template + int DistributedGenerator::evaluateIntegrand() + { + return 0; + } + + template + int DistributedGenerator::initializeAdjoint() + { + return 0; + } + + template + int DistributedGenerator::evaluateAdjointResidual() + { + return 0; + } + + template + int DistributedGenerator::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class DistributedGenerator; + template class DistributedGenerator; + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/DistributedGenerator/DistributedGenerator.hpp b/src/Model/PowerElectronics/DistributedGenerator/DistributedGenerator.hpp new file mode 100644 index 000000000..96654cf62 --- /dev/null +++ b/src/Model/PowerElectronics/DistributedGenerator/DistributedGenerator.hpp @@ -0,0 +1,102 @@ + + +#ifndef _CAP_HPP_ +#define _CAP_HPP_ + +#include +#include + +namespace GridKit +{ + template + class BaseBus; + + template + struct DistributedGeneratorParameters + { + ScalarT wb_; + ScalarT wc_; + ScalarT mp_; + ScalarT Vn_; + ScalarT nq_; + ScalarT F_; + ScalarT Kiv_; + ScalarT Kpv_; + ScalarT Kic_; + ScalarT Kpc_; + ScalarT Cf_; + ScalarT rLf_; + ScalarT Lf_; + ScalarT rLc_; + ScalarT Lc_; + }; +} // namespace GridKit + +namespace GridKit +{ + /*! + * @brief Declaration of a DistributedGenerator class. + * + */ + template + class DistributedGenerator : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::jac_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + using CircuitComponent::extern_indices_; + using CircuitComponent::n_extern_; + using CircuitComponent::n_intern_; + + public: + DistributedGenerator(IdxT id, + DistributedGeneratorParameters parm, + bool reference_frame); + virtual ~DistributedGenerator(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT wb_; + ScalarT wc_; + ScalarT mp_; + ScalarT Vn_; + ScalarT nq_; + ScalarT F_; + ScalarT Kiv_; + ScalarT Kpv_; + ScalarT Kic_; + ScalarT Kpc_; + ScalarT Cf_; + ScalarT rLf_; + ScalarT Lf_; + ScalarT rLc_; + ScalarT Lc_; + bool refframe_; + }; +} // namespace GridKit + +#endif diff --git a/src/Model/PowerElectronics/InductionMotor/CMakeLists.txt b/src/Model/PowerElectronics/InductionMotor/CMakeLists.txt new file mode 100644 index 000000000..c9246583c --- /dev/null +++ b/src/Model/PowerElectronics/InductionMotor/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(power_elec_inductionmotor + SOURCES + InductionMotor.cpp + OUTPUT_NAME + gridkit_power_elec_inductionmotor) diff --git a/src/Model/PowerElectronics/InductionMotor/InductionMotor.cpp b/src/Model/PowerElectronics/InductionMotor/InductionMotor.cpp new file mode 100644 index 000000000..34e1f7438 --- /dev/null +++ b/src/Model/PowerElectronics/InductionMotor/InductionMotor.cpp @@ -0,0 +1,143 @@ + + +#include "InductionMotor.hpp" + +#include +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a constant InductionMotor model + * + * Calls default ModelEvaluatorImpl constructor. + * @todo create a test case utilizing the component. + * @todo create a unit test to check correctness of component + * + * @tparam ScalarT - data type for scalar variables in the model + * @tparam IdxT - integer index type for the model + * + * @param[in] id - unique identifier for the component + * @param[in] Lls - stator leakage inductance + */ + + template + InductionMotor::InductionMotor(IdxT id, ScalarT Lls, ScalarT Rs, ScalarT Llr, ScalarT Rr, ScalarT Lms, ScalarT RJ, ScalarT P) + : Lls_(Lls), + Rs_(Rs), + Llr_(Llr), + Rr_(Rr), + Lms_(Lms), + RJ_(RJ), + P_(P) + { + size_ = 10; + n_intern_ = 5; + n_extern_ = 5; + extern_indices_ = {0, 1, 2, 3, 4}; + idc_ = id; + } + + template + InductionMotor::~InductionMotor() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int InductionMotor::allocate() + { + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + return 0; + } + + /** + * Initialization of the grid model + */ + template + int InductionMotor::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int InductionMotor::tagDifferentiable() + { + return 0; + } + + /** + * @brief Contributes to the resisdual + * + */ + template + int InductionMotor::evaluateResidual() + { + + f_[0] = y_[5] + y_[7]; + f_[1] = (-1.0 / 2.0) * y_[5] - (sqrt(3.0) / 2.0) * y_[6] + y_[7]; + f_[2] = (-1.0 / 2.0) * y_[5] + (sqrt(3.0) / 2.0) * y_[6] + y_[7]; + f_[3] = RJ_ * yp_[3] - (3.0 / 4.0) * P_ * Lms_ * (y_[5] * y_[9] - y_[6] * y_[8]); + f_[4] = yp_[4] - y_[3]; + f_[5] = (1.0 / 3.0) * (2.0 * y_[0] - y_[1] - y_[2]) - Rs_ * y_[5] - (Lls_ + Lms_) * yp_[5] - Lms_ * yp_[6]; + f_[6] = (1.0 / sqrt(3.0)) * (-y_[1] + y_[2]) - Rs_ * y_[6] - (Lls_ + Lms_) * yp_[6] - Lms_ * yp_[5]; + f_[7] = (y_[0] + y_[1] + y_[2]) / 3.0 - Rs_ * y_[7] - Lls_ * yp_[7]; + f_[8] = Rr_ * y_[8] + (Llr_ + Lms_) * yp_[8] + Lms_ * yp_[5] - (P_ / 2) * y_[3] * ((Llr_ + Lms_) * y_[9] + Lms_ * y_[6]); + f_[9] = Rr_ * y_[9] + (Llr_ + Lms_) * yp_[9] + Lms_ * yp_[6] + (P_ / 2) * y_[3] * ((Llr_ + Lms_) * y_[8] + Lms_ * y_[5]); + return 0; + } + + /** + * @brief Compute component Jacobian + * + * @todo need to implement + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ + template + int InductionMotor::evaluateJacobian() + { + + return 0; + } + + template + int InductionMotor::evaluateIntegrand() + { + return 0; + } + + template + int InductionMotor::initializeAdjoint() + { + return 0; + } + + template + int InductionMotor::evaluateAdjointResidual() + { + return 0; + } + + template + int InductionMotor::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class InductionMotor; + template class InductionMotor; + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/InductionMotor/InductionMotor.hpp b/src/Model/PowerElectronics/InductionMotor/InductionMotor.hpp new file mode 100644 index 000000000..007e7fd5d --- /dev/null +++ b/src/Model/PowerElectronics/InductionMotor/InductionMotor.hpp @@ -0,0 +1,72 @@ + + +#ifndef _IMOTOR_HPP_ +#define _IMOTOR_HPP_ + +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Declaration of a InductionMotor class. + * + */ + template + class InductionMotor : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::jac_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + using CircuitComponent::extern_indices_; + using CircuitComponent::n_extern_; + using CircuitComponent::n_intern_; + + public: + InductionMotor(IdxT id, ScalarT Lls, ScalarT Rs, ScalarT Llr, ScalarT Rr, ScalarT Lms, ScalarT RJ, ScalarT P); + virtual ~InductionMotor(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT Lls_; + ScalarT Rs_; + ScalarT Llr_; + ScalarT Rr_; + ScalarT Lms_; + ScalarT RJ_; + ScalarT P_; + }; +} // namespace GridKit + +#endif diff --git a/src/Model/PowerElectronics/Inductor/CMakeLists.txt b/src/Model/PowerElectronics/Inductor/CMakeLists.txt new file mode 100644 index 000000000..980fb86f4 --- /dev/null +++ b/src/Model/PowerElectronics/Inductor/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(power_elec_inductor + SOURCES + Inductor.cpp + OUTPUT_NAME + gridkit_power_elec_inductor) diff --git a/src/Model/PowerElectronics/Inductor/Inductor.cpp b/src/Model/PowerElectronics/Inductor/Inductor.cpp new file mode 100644 index 000000000..fa9d07322 --- /dev/null +++ b/src/Model/PowerElectronics/Inductor/Inductor.cpp @@ -0,0 +1,140 @@ + + +#include "Inductor.hpp" + +#include +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a inductor + * + * Calls default ModelEvaluatorImpl constructor. + */ + + template + Inductor::Inductor(IdxT id, ScalarT L) + : L_(L) + { + size_ = 3; + n_intern_ = 1; + n_extern_ = 2; + extern_indices_ = {0, 1}; + idc_ = id; + } + + template + Inductor::~Inductor() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int Inductor::allocate() + { + + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + + return 0; + } + + /** + * Initialization of the grid model + */ + template + int Inductor::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int Inductor::tagDifferentiable() + { + return 0; + } + + /** + * @brief Compute the resisdual of the component + * + */ + template + int Inductor::evaluateResidual() + { + // input + f_[0] = -y_[2]; + // output + f_[1] = y_[2]; + // internal + f_[2] = -L_ * yp_[2] + y_[1] - y_[0]; + return 0; + } + + /** + * @brief Evaluate the jacobian of the component + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ + template + int Inductor::evaluateJacobian() + { + jac_.zeroMatrix(); + + // Create dF/dy + std::vector rcord{0, 1, 2, 2}; + std::vector ccord{2, 2, 0, 1}; + std::vector vals{-1.0, 1.0, -1.0, 1.0}; + jac_.setValues(rcord, ccord, vals); + + // Create dF/dy' + std::vector rcordder{2}; + std::vector ccordder{2}; + std::vector valsder{-L_}; + COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder, 3, 3); + + // Perform dF/dy + \alpha dF/dy' + jac_.axpy(alpha_, Jacder); + + return 0; + } + + template + int Inductor::evaluateIntegrand() + { + return 0; + } + + template + int Inductor::initializeAdjoint() + { + return 0; + } + + template + int Inductor::evaluateAdjointResidual() + { + return 0; + } + + template + int Inductor::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class Inductor; + template class Inductor; + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/Inductor/Inductor.hpp b/src/Model/PowerElectronics/Inductor/Inductor.hpp new file mode 100644 index 000000000..c40920b0f --- /dev/null +++ b/src/Model/PowerElectronics/Inductor/Inductor.hpp @@ -0,0 +1,66 @@ + + +#ifndef _IND_HPP_ +#define _IND_HPP_ + +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Declaration of a Inductor class. + * + */ + template + class Inductor : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::jac_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + using CircuitComponent::extern_indices_; + using CircuitComponent::n_extern_; + using CircuitComponent::n_intern_; + + public: + Inductor(IdxT id, ScalarT L); + virtual ~Inductor(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT L_; + }; +} // namespace GridKit + +#endif diff --git a/src/Model/PowerElectronics/LinearTransformer/CMakeLists.txt b/src/Model/PowerElectronics/LinearTransformer/CMakeLists.txt new file mode 100644 index 000000000..d3e2c7243 --- /dev/null +++ b/src/Model/PowerElectronics/LinearTransformer/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(power_elec_lineartrasnformer + SOURCES + LinearTransformer.cpp + OUTPUT_NAME + gridkit_power_elec_lineartrasnformer) diff --git a/src/Model/PowerElectronics/LinearTransformer/LinearTransformer.cpp b/src/Model/PowerElectronics/LinearTransformer/LinearTransformer.cpp new file mode 100644 index 000000000..189dc1d63 --- /dev/null +++ b/src/Model/PowerElectronics/LinearTransformer/LinearTransformer.cpp @@ -0,0 +1,128 @@ + + +#include "LinearTransformer.hpp" + +#include +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a LinearTransformer model + * + * Calls default ModelEvaluatorImpl constructor. + * @todo Not tested in any model yet. Should be + * @todo Has not been tested for correctness + * + * @tparam ScalarT - floating point type for the model + * @tparam IdxT - integer index type for the model + * + * @param[in] id - unique identifier for the component + * @param[in] L0 - inductance 0 + * @param[in] L1 - inductance 1 + * @param[in] R0 - resistance 0 + * @param[in] R1 - resistance 1 + * @param[in] M - mutual inductance + */ + + template + LinearTransformer::LinearTransformer(IdxT id, ScalarT L0, ScalarT L1, ScalarT R0, ScalarT R1, ScalarT M) + : L0_(L0), + L1_(L1), + R0_(R0), + R1_(R1), + M_(M) + { + size_ = 4; + n_intern_ = 2; + n_extern_ = 2; + extern_indices_ = {0, 1}; + idc_ = id; + } + + template + LinearTransformer::~LinearTransformer() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int LinearTransformer::allocate() + { + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + return 0; + } + + /** + * Initialization of the grid model + */ + template + int LinearTransformer::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int LinearTransformer::tagDifferentiable() + { + return 0; + } + + /** + * @brief Computes the component resisdual + * + */ + template + int LinearTransformer::evaluateResidual() + { + f_[0] = y_[2]; + f_[1] = y_[3]; + f_[2] = y_[0] - R0_ * y_[2] - L0_ * yp_[2] - M_ * yp_[3]; + f_[2] = y_[1] - R1_ * y_[3] - M_ * yp_[2] - L1_ * yp_[3]; + return 0; + } + + template + int LinearTransformer::evaluateJacobian() + { + return 0; + } + + template + int LinearTransformer::evaluateIntegrand() + { + return 0; + } + + template + int LinearTransformer::initializeAdjoint() + { + return 0; + } + + template + int LinearTransformer::evaluateAdjointResidual() + { + return 0; + } + + template + int LinearTransformer::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class LinearTransformer; + template class LinearTransformer; + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/LinearTransformer/LinearTransformer.hpp b/src/Model/PowerElectronics/LinearTransformer/LinearTransformer.hpp new file mode 100644 index 000000000..b1e9c57c2 --- /dev/null +++ b/src/Model/PowerElectronics/LinearTransformer/LinearTransformer.hpp @@ -0,0 +1,70 @@ + + +#ifndef _LTRANS_HPP_ +#define _LTRANS_HPP_ + +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Declaration of a LinearTransformer class. + * + */ + template + class LinearTransformer : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::jac_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + using CircuitComponent::extern_indices_; + using CircuitComponent::n_extern_; + using CircuitComponent::n_intern_; + + public: + LinearTransformer(IdxT id, ScalarT L0, ScalarT L1, ScalarT R0, ScalarT R1, ScalarT M); + virtual ~LinearTransformer(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT L0_; + ScalarT L1_; + ScalarT R0_; + ScalarT R1_; + ScalarT M_; + }; +} // namespace GridKit + +#endif diff --git a/src/Model/PowerElectronics/MicrogridBusDQ/CMakeLists.txt b/src/Model/PowerElectronics/MicrogridBusDQ/CMakeLists.txt new file mode 100644 index 000000000..1ad579876 --- /dev/null +++ b/src/Model/PowerElectronics/MicrogridBusDQ/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(power_elec_microbusdq + SOURCES + MicrogridBusDQ.cpp + OUTPUT_NAME + gridkit_power_elec_microbusdq) diff --git a/src/Model/PowerElectronics/MicrogridBusDQ/MicrogridBusDQ.cpp b/src/Model/PowerElectronics/MicrogridBusDQ/MicrogridBusDQ.cpp new file mode 100644 index 000000000..3de0b9e1a --- /dev/null +++ b/src/Model/PowerElectronics/MicrogridBusDQ/MicrogridBusDQ.cpp @@ -0,0 +1,137 @@ + +#include "MicrogridBusDQ.hpp" + +#include +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a constant MicrogridBusDQ model + * + * Calls default ModelEvaluatorImpl constructor. + * + * In DQ space + * Each microgrid line has a virtual resistance RN + * Model is from paper: "Modeling, Analysis and Testing of Autonomous Operation + * of an Inverter-Based Microgrid", Nagaraju Pogaku, Milan Prodanovic, and + * Timothy C. Green, Section E + */ + template + MicrogridBusDQ::MicrogridBusDQ(IdxT id, ScalarT RN) + : RN_(RN) + { + // externals [vbus_d, vbus_q] + size_ = 2; + n_intern_ = 0; + n_extern_ = 2; + extern_indices_ = {0, 1}; + idc_ = id; + } + + template + MicrogridBusDQ::~MicrogridBusDQ() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int MicrogridBusDQ::allocate() + { + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + + return 0; + } + + /** + * Initialization of the grid model + */ + template + int MicrogridBusDQ::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int MicrogridBusDQ::tagDifferentiable() + { + return 0; + } + + /** + * @brief Evaluate residual of microgrid line + * This model has "Virtual resistors". The voltage of the bus divided by its virtual resistance. + * The components are external to allow for outside components to add inductances to the terms. + * + * refernce to equations in class header + * + */ + template + int MicrogridBusDQ::evaluateResidual() + { + // bus voltage + f_[0] = -y_[0] / RN_; + f_[1] = -y_[1] / RN_; + + return 0; + } + + /** + * @brief Generate Jacobian + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ + template + int MicrogridBusDQ::evaluateJacobian() + { + jac_.zeroMatrix(); + + // Create dF/dy + std::vector rtemp{0, 1}; + std::vector ctemp{0, 1}; + std::vector vals{-1.0 / RN_, -1.0 / RN_}; + jac_.setValues(rtemp, ctemp, vals); + + return 0; + } + + template + int MicrogridBusDQ::evaluateIntegrand() + { + return 0; + } + + template + int MicrogridBusDQ::initializeAdjoint() + { + return 0; + } + + template + int MicrogridBusDQ::evaluateAdjointResidual() + { + return 0; + } + + template + int MicrogridBusDQ::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class MicrogridBusDQ; + template class MicrogridBusDQ; + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/MicrogridBusDQ/MicrogridBusDQ.hpp b/src/Model/PowerElectronics/MicrogridBusDQ/MicrogridBusDQ.hpp new file mode 100644 index 000000000..46173c5ab --- /dev/null +++ b/src/Model/PowerElectronics/MicrogridBusDQ/MicrogridBusDQ.hpp @@ -0,0 +1,66 @@ + + +#ifndef _VIRBUSDQ_HPP_ +#define _VIRBUSDQ_HPP_ + +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Declaration of a MicrogridBusDQ class. + * + */ + template + class MicrogridBusDQ : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::jac_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + using CircuitComponent::extern_indices_; + using CircuitComponent::n_extern_; + using CircuitComponent::n_intern_; + + public: + MicrogridBusDQ(IdxT id, ScalarT RN); + virtual ~MicrogridBusDQ(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT RN_; + }; +} // namespace GridKit + +#endif diff --git a/src/Model/PowerElectronics/MicrogridLine/CMakeLists.txt b/src/Model/PowerElectronics/MicrogridLine/CMakeLists.txt new file mode 100644 index 000000000..2f4457855 --- /dev/null +++ b/src/Model/PowerElectronics/MicrogridLine/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(power_elec_microline + SOURCES + MicrogridLine.cpp + OUTPUT_NAME + gridkit_power_elec_microline) diff --git a/src/Model/PowerElectronics/MicrogridLine/MicrogridLine.cpp b/src/Model/PowerElectronics/MicrogridLine/MicrogridLine.cpp new file mode 100644 index 000000000..030668ea0 --- /dev/null +++ b/src/Model/PowerElectronics/MicrogridLine/MicrogridLine.cpp @@ -0,0 +1,168 @@ + +#include "MicrogridLine.hpp" + +#include +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a constant MicrogridLine model + * + * Calls default ModelEvaluatorImpl constructor. + * + * + * Model is from paper: "Modeling, Analysis and Testing of Autonomous Operation + * of an Inverter-Based Microgrid", Nagaraju Pogaku, Milan Prodanovic, and + * Timothy C. Green, Section C + * + * @todo Consider having \omegaref as a global constant, not a node variable. + */ + + template + MicrogridLine::MicrogridLine(IdxT id, ScalarT R, ScalarT L) + : R_(R), + L_(L) + { + // internals [id, iq] + // externals [\omegaref, vbd_in, vbq_in, vbd_out, vbq_out] + size_ = 7; + n_intern_ = 2; + n_extern_ = 5; + extern_indices_ = {0, 1, 2, 3, 4}; + idc_ = id; + } + + template + MicrogridLine::~MicrogridLine() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int MicrogridLine::allocate() + { + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + + return 0; + } + + /** + * Initialization of the grid model + */ + template + int MicrogridLine::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int MicrogridLine::tagDifferentiable() + { + return 0; + } + + /** + * @brief Evaluate residual of microgrid line + * + */ + template + int MicrogridLine::evaluateResidual() + { + // ref motor + f_[0] = 0.0; + + // input + f_[1] = -y_[5]; + f_[2] = -y_[6]; + + // output + f_[3] = y_[5]; + f_[4] = y_[6]; + + // Internal variables + f_[5] = -yp_[5] - (R_ / L_) * y_[5] + y_[0] * y_[6] + (y_[1] - y_[3]) / L_; + f_[6] = -yp_[6] - (R_ / L_) * y_[6] - y_[0] * y_[5] + (y_[2] - y_[4]) / L_; + + return 0; + } + + /** + * @brief Generate Jacobian for Microgrid Line + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ + template + int MicrogridLine::evaluateJacobian() + { + jac_.zeroMatrix(); + + // Create dF/dy + std::vector rtemp{1, 2, 3, 4}; + std::vector ctemp{5, 6, 5, 6}; + std::vector vals{-1.0, -1.0, 1.0, 1.0}; + jac_.setValues(rtemp, ctemp, vals); + + std::vector ccord{0, 1, 3, 5, 6}; + + std::vector rcord(ccord.size(), 5); + vals = {y_[6], (1.0 / L_), -(1.0 / L_), -(R_ / L_), y_[0]}; + jac_.setValues(rcord, ccord, vals); + + std::vector ccor2{0, 2, 4, 5, 6}; + std::fill(rcord.begin(), rcord.end(), 6); + vals = {-y_[5], (1.0 / L_), -(1.0 / L_), -y_[0], -(R_ / L_)}; + jac_.setValues(rcord, ccor2, vals); + + // Create -dF/dy' + std::vector rcordder{5, 6}; + std::vector ccordder{5, 6}; + std::vector valsder{-1.0, -1.0}; + COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder, 7, 7); + + // Perform dF/dy + \alpha dF/dy' + jac_.axpy(alpha_, Jacder); + + return 0; + } + + template + int MicrogridLine::evaluateIntegrand() + { + return 0; + } + + template + int MicrogridLine::initializeAdjoint() + { + return 0; + } + + template + int MicrogridLine::evaluateAdjointResidual() + { + return 0; + } + + template + int MicrogridLine::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class MicrogridLine; + template class MicrogridLine; + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/MicrogridLine/MicrogridLine.hpp b/src/Model/PowerElectronics/MicrogridLine/MicrogridLine.hpp new file mode 100644 index 000000000..14d29b85d --- /dev/null +++ b/src/Model/PowerElectronics/MicrogridLine/MicrogridLine.hpp @@ -0,0 +1,67 @@ + + +#ifndef _TRANLINE_HPP_ +#define _TRANLINE_HPP_ + +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Declaration of a MicrogridLine class. + * + */ + template + class MicrogridLine : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::jac_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + using CircuitComponent::extern_indices_; + using CircuitComponent::n_extern_; + using CircuitComponent::n_intern_; + + public: + MicrogridLine(IdxT id, ScalarT R, ScalarT L); + virtual ~MicrogridLine(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT R_; + ScalarT L_; + }; +} // namespace GridKit + +#endif diff --git a/src/Model/PowerElectronics/MicrogridLoad/CMakeLists.txt b/src/Model/PowerElectronics/MicrogridLoad/CMakeLists.txt new file mode 100644 index 000000000..b17a875cb --- /dev/null +++ b/src/Model/PowerElectronics/MicrogridLoad/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(power_elec_microload + SOURCES + MicrogridLoad.cpp + OUTPUT_NAME + gridkit_power_elec_microload) diff --git a/src/Model/PowerElectronics/MicrogridLoad/MicrogridLoad.cpp b/src/Model/PowerElectronics/MicrogridLoad/MicrogridLoad.cpp new file mode 100644 index 000000000..f36dd8895 --- /dev/null +++ b/src/Model/PowerElectronics/MicrogridLoad/MicrogridLoad.cpp @@ -0,0 +1,163 @@ + +#include "MicrogridLoad.hpp" + +#include +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a constant MicrogridLoad model + * + * Calls default ModelEvaluatorImpl constructor. + * + * + * Model is from paper: " + "Modeling, Analysis and Testing of Autonomous Operation of an Inverter-Based Microgrid" Nagaraju Pogaku, Milan Prodanovic, and Timothy C. Green" + * Section D + */ + + template + MicrogridLoad::MicrogridLoad(IdxT id, ScalarT R, ScalarT L) + : R_(R), + L_(L) + { + // internals [id, iq] + // externals [\omegaref, vbd_out, vbq_out] + size_ = 5; + n_intern_ = 2; + n_extern_ = 3; + extern_indices_ = {0, 1, 2}; + idc_ = id; + } + + template + MicrogridLoad::~MicrogridLoad() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int MicrogridLoad::allocate() + { + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + + return 0; + } + + /** + * Initialization of the grid model + */ + template + int MicrogridLoad::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int MicrogridLoad::tagDifferentiable() + { + return 0; + } + + /** + * @brief Eval Micro Load + */ + template + int MicrogridLoad::evaluateResidual() + { + // ref motor + f_[0] = 0.0; + + // only input for loads + + // input + f_[1] = -y_[3]; + f_[2] = -y_[4]; + + // Internal variables + f_[3] = -yp_[3] - (R_ / L_) * y_[3] + y_[0] * y_[4] + y_[1] / L_; + f_[4] = -yp_[4] - (R_ / L_) * y_[4] - y_[0] * y_[3] + y_[2] / L_; + + return 0; + } + + /** + * @brief Generate Jacobian for Micro Load + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ + template + int MicrogridLoad::evaluateJacobian() + { + jac_.zeroMatrix(); + + // Create dF/dy + std::vector rtemp{1, 2}; + std::vector ctemp{3, 4}; + std::vector vals{-1.0, -1.0}; + jac_.setValues(rtemp, ctemp, vals); + + std::vector ccord{0, 1, 3, 4}; + + std::vector rcord(ccord.size(), 3); + vals = {y_[4], (1.0 / L_), -(R_ / L_), y_[0]}; + jac_.setValues(rcord, ccord, vals); + + std::vector ccor2{0, 2, 3, 4}; + std::fill(rcord.begin(), rcord.end(), 4); + vals = {-y_[3], (1.0 / L_), -y_[0], -(R_ / L_)}; + jac_.setValues(rcord, ccor2, vals); + + // Create -dF/dy' + std::vector rcordder{3, 4}; + std::vector ccordder{3, 4}; + std::vector valsder{-1.0, -1.0}; + COO_Matrix Jacder = COO_Matrix(rcordder, ccordder, valsder, 5, 5); + + // Perform dF/dy + \alpha dF/dy' + jac_.axpy(alpha_, Jacder); + + return 0; + } + + template + int MicrogridLoad::evaluateIntegrand() + { + return 0; + } + + template + int MicrogridLoad::initializeAdjoint() + { + return 0; + } + + template + int MicrogridLoad::evaluateAdjointResidual() + { + return 0; + } + + template + int MicrogridLoad::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class MicrogridLoad; + template class MicrogridLoad; + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/MicrogridLoad/MicrogridLoad.hpp b/src/Model/PowerElectronics/MicrogridLoad/MicrogridLoad.hpp new file mode 100644 index 000000000..685a05044 --- /dev/null +++ b/src/Model/PowerElectronics/MicrogridLoad/MicrogridLoad.hpp @@ -0,0 +1,67 @@ + + +#ifndef _TRANLOAD_HPP_ +#define _TRANLOAD_HPP_ + +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Declaration of a passive MicrogridLoad class. + * + */ + template + class MicrogridLoad : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::jac_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + using CircuitComponent::extern_indices_; + using CircuitComponent::n_extern_; + using CircuitComponent::n_intern_; + + public: + MicrogridLoad(IdxT id, ScalarT R, ScalarT L); + virtual ~MicrogridLoad(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT R_; + ScalarT L_; + }; +} // namespace GridKit + +#endif diff --git a/src/Model/PowerElectronics/Resistor/CMakeLists.txt b/src/Model/PowerElectronics/Resistor/CMakeLists.txt new file mode 100644 index 000000000..3721b387e --- /dev/null +++ b/src/Model/PowerElectronics/Resistor/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(power_elec_resistor + SOURCES + Resistor.cpp + OUTPUT_NAME + gridkit_power_elec_resistor) diff --git a/src/Model/PowerElectronics/Resistor/Resistor.cpp b/src/Model/PowerElectronics/Resistor/Resistor.cpp new file mode 100644 index 000000000..6549ec123 --- /dev/null +++ b/src/Model/PowerElectronics/Resistor/Resistor.cpp @@ -0,0 +1,121 @@ + + +#include "Resistor.hpp" + +#include +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a resistor model + * + * Calls default ModelEvaluatorImpl constructor. + */ + + template + Resistor::Resistor(IdxT id, ScalarT R) + : R_(R) + { + size_ = 2; + n_intern_ = 0; + n_extern_ = 2; + extern_indices_ = {0, 1}; + idc_ = id; + } + + template + Resistor::~Resistor() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int Resistor::allocate() + { + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + + return 0; + } + + /** + * Initialization of the grid model + */ + template + int Resistor::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int Resistor::tagDifferentiable() + { + return 0; + } + + /** + * @brief Computes the resistors resisdual + * + */ + template + int Resistor::evaluateResidual() + { + // input + f_[0] = (y_[0] - y_[1]) / R_; + // ouput + f_[1] = (y_[1] - y_[0]) / R_; + return 0; + } + + template + int Resistor::evaluateJacobian() + { + + // Create dF/dy + // does compiler make constant??? + std::vector rcord{0, 0, 1, 1}; + std::vector ccord{0, 1, 0, 1}; + std::vector vals{1.0 / R_, -1.0 / R_, -1.0 / R_, 1.0 / R_}; + jac_.setValues(rcord, ccord, vals); + + return 0; + } + + template + int Resistor::evaluateIntegrand() + { + return 0; + } + + template + int Resistor::initializeAdjoint() + { + return 0; + } + + template + int Resistor::evaluateAdjointResidual() + { + return 0; + } + + template + int Resistor::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class Resistor; + template class Resistor; + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/Resistor/Resistor.hpp b/src/Model/PowerElectronics/Resistor/Resistor.hpp new file mode 100644 index 000000000..0821b992e --- /dev/null +++ b/src/Model/PowerElectronics/Resistor/Resistor.hpp @@ -0,0 +1,66 @@ + + +#ifndef _RES_HPP_ +#define _RES_HPP_ + +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Declaration of a Resistor class. + * + */ + template + class Resistor : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::jac_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + using CircuitComponent::extern_indices_; + using CircuitComponent::n_extern_; + using CircuitComponent::n_intern_; + + public: + Resistor(IdxT id, ScalarT R); + virtual ~Resistor(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT R_; + }; +} // namespace GridKit + +#endif diff --git a/src/Model/PowerElectronics/SynchronousMachine/CMakeLists.txt b/src/Model/PowerElectronics/SynchronousMachine/CMakeLists.txt new file mode 100644 index 000000000..ff492047e --- /dev/null +++ b/src/Model/PowerElectronics/SynchronousMachine/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(power_elec_synmachine + SOURCES + SynchronousMachine.cpp + OUTPUT_NAME + gridkit_power_elec_synmachine) diff --git a/src/Model/PowerElectronics/SynchronousMachine/SynchronousMachine.cpp b/src/Model/PowerElectronics/SynchronousMachine/SynchronousMachine.cpp new file mode 100644 index 000000000..c34db3b9f --- /dev/null +++ b/src/Model/PowerElectronics/SynchronousMachine/SynchronousMachine.cpp @@ -0,0 +1,161 @@ +#include "SynchronousMachine.hpp" + +#include +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a constant SynchronousMachine model + * + * Calls default ModelEvaluatorImpl constructor. + * @todo This model's equations are not finished + * @todo needs to be tested for correctness + * + * @tparam ScalarT - floating point type for the model + * @tparam IdxT - integer index type for the model + * + * @param[in] id - unique identifier for the component + * @param[in] Lls - stator leakage inductance + * @param[in] Llkq - tuple of damper leakage reactances + * @param[in] Llfd - field leakage reactance + * @param[in] Llkd - damper leakage reactance + * @param[in] Lmq - quadrature axis magnetizing reactance + * @param[in] Lmd - direct axis magnetizing reactance + * @param[in] Rs - stator resistance + * @param[in] Rkq - tuple of damper resistances + * @param[in] Rfd - field resistance + * @param[in] Rkd - damper resistance + * @param[in] RJ - rotor moment of inertia + * @param[in] P - number of poles + * @param[in] mub - rated frequency + */ + + template + SynchronousMachine::SynchronousMachine(IdxT id, ScalarT Lls, std::tuple Llkq, ScalarT Llfd, ScalarT Llkd, ScalarT Lmq, ScalarT Lmd, ScalarT Rs, std::tuple Rkq, ScalarT Rfd, ScalarT Rkd, ScalarT RJ, ScalarT P, ScalarT mub) + : Lls_(Lls), + Llkq_(Llkq), + Llfd_(Llfd), + Llkd_(Llkd), + Lmq_(Lmq), + Lmd_(Lmd), + Rs_(Rs), + Rkq_(Rkq), + Rfd_(Rfd), + Rkd_(Rkd), + RJ_(RJ), + P_(P), + mub_(mub) + { + size_ = 13; + n_intern_ = 6; + n_extern_ = 7; + extern_indices_ = {0, 1, 2, 3, 4}; + idc_ = id; + } + + template + SynchronousMachine::~SynchronousMachine() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int SynchronousMachine::allocate() + { + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + return 0; + } + + /** + * Initialization of the grid model + */ + template + int SynchronousMachine::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int SynchronousMachine::tagDifferentiable() + { + return 0; + } + + /** + * @brief Compute the resisdual of the component. + * + * @todo not finished + */ + template + int SynchronousMachine::evaluateResidual() + { + ScalarT rkq1 = std::get<0>(Rkq_); + ScalarT rkq2 = std::get<1>(Rkq_); + ScalarT llkq1 = std::get<0>(Llkq_); + ScalarT llkq2 = std::get<1>(Llkq_); + + ScalarT cos1 = cos((P_ / 2.0) * y_[5]); + ScalarT sin1 = sin((P_ / 2.0) * y_[5]); + ScalarT cos23m = cos((P_ / 2.0) * y_[5] - (2.0 / 3.0) * M_PI); + ScalarT sin23m = sin((P_ / 2.0) * y_[5] - (2.0 / 3.0) * M_PI); + ScalarT cos23p = cos((P_ / 2.0) * y_[5] + (2.0 / 3.0) * M_PI); + ScalarT sin23p = sin((P_ / 2.0) * y_[5] + (2.0 / 3.0) * M_PI); + + f_[0] = y_[6] * cos1 + y_[7] * sin1 + y_[8]; + f_[1] = y_[6] * cos23m + y_[7] * sin23m + y_[8]; + f_[2] = y_[6] * cos23p + y_[7] * sin23p + y_[8]; + f_[3] = RJ_ * yp_[4] - (3.0 / 4.0) * P_ * (Lmd_ * y_[6] * (y_[7] + y_[11] + y_[12]) - Lmq_ * y_[7] * (y_[6] + y_[9] + y_[0])); + f_[4] = yp_[5] - y_[4]; + f_[5] = (-2.0 / 3.0) * (y_[0] * cos1 + y_[1] * cos23m + y_[2] * cos23p) + Rs_ * y_[6] + (Lls_ + Lmq_) * yp_[6] + Lmq_ * yp_[9] + Lmq_ * yp_[10] + y_[4] * (P_ / 2.0) * ((Lls_ + Lmd_) * y_[7] + Lmd_ * y_[11] + Lmd_ * y_[12]); + f_[6] = (-2.0 / 3.0) * (y_[0] * sin1 - y_[1] * sin23m - y_[2] * sin23p) + Rs_ * y_[7] + (Lls_ + Lmd_) * yp_[7] + Lmd_ * yp_[11] + Lmd_ * yp_[12] - y_[4] * (P_ / 2.0) * ((Lls_ + Lmq_) * y_[6] + Lmq_ * y_[9] + Lmq_ * y_[10]); + f_[7] = (-1.0 / 3.0) * (y_[0] + y_[1] + y_[2]) + Rs_ * y_[8] + Lls_ * yp_[8]; + f_[8] = rkq1 * y_[9] + (llkq1 + Lmq_) * yp_[9] + Lmq_ * yp_[6] + Lmq_ * yp_[10]; + f_[9] = rkq1 * y_[9] + (llkq1 + Lmq_) * yp_[9] + Lmq_ * yp_[6] + Lmq_ * yp_[10]; + return 0; + } + + template + int SynchronousMachine::evaluateJacobian() + { + return 0; + } + + template + int SynchronousMachine::evaluateIntegrand() + { + return 0; + } + + template + int SynchronousMachine::initializeAdjoint() + { + return 0; + } + + template + int SynchronousMachine::evaluateAdjointResidual() + { + return 0; + } + + template + int SynchronousMachine::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class SynchronousMachine; + template class SynchronousMachine; + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/SynchronousMachine/SynchronousMachine.hpp b/src/Model/PowerElectronics/SynchronousMachine/SynchronousMachine.hpp new file mode 100644 index 000000000..74766d155 --- /dev/null +++ b/src/Model/PowerElectronics/SynchronousMachine/SynchronousMachine.hpp @@ -0,0 +1,80 @@ + + +#ifndef _SYNMACH_HPP_ +#define _SYNMACH_HPP_ + +#include + +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Declaration of a SynchronousMachine class. + * + */ + template + class SynchronousMachine : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::jac_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + using CircuitComponent::extern_indices_; + using CircuitComponent::n_extern_; + using CircuitComponent::n_intern_; + + public: + SynchronousMachine(IdxT id, ScalarT Lls, std::tuple Llkq, ScalarT Llfd, ScalarT Llkd, ScalarT Lmq, ScalarT Lmd, ScalarT Rs, std::tuple Rkq, ScalarT Rfd, ScalarT Rkd, ScalarT RJ, ScalarT P, ScalarT mub); + virtual ~SynchronousMachine(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT Lls_; + std::tuple Llkq_; + ScalarT Llfd_; + ScalarT Llkd_; + ScalarT Lmq_; + ScalarT Lmd_; + ScalarT Rs_; + std::tuple Rkq_; + ScalarT Rfd_; + ScalarT Rkd_; + ScalarT RJ_; + ScalarT P_; + ScalarT mub_; + }; +} // namespace GridKit + +#endif diff --git a/src/Model/PowerElectronics/SystemModelPowerElectronics.hpp b/src/Model/PowerElectronics/SystemModelPowerElectronics.hpp new file mode 100644 index 000000000..105483094 --- /dev/null +++ b/src/Model/PowerElectronics/SystemModelPowerElectronics.hpp @@ -0,0 +1,340 @@ + + +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace GridKit +{ + + template + class PowerElectronicsModel : public CircuitComponent + { + typedef CircuitComponent component_type; + + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::f_; + using CircuitComponent::jac_; + using CircuitComponent::rel_tol_; + using CircuitComponent::abs_tol_; + + public: + /** + * @brief Default constructor for the system model + * + * @post System model parameters set as default + */ + PowerElectronicsModel() + { + // Set system model parameters as default + rel_tol_ = 1e-4; + abs_tol_ = 1e-4; + this->max_steps_ = 2000; + // By default don't use the jacobian + use_jac_ = false; + } + + /** + * @brief Constructor for the system model + * + * @param[in] rel_tol Relative tolerance for the system model + * @param[in] abs_tol Absolute tolerance for the system model + * @param[in] use_jac Boolean to choose if to use jacobian + * @param[in] max_steps Maximum number of steps for the system model + * + * @post System model parameters set as input + */ + PowerElectronicsModel(double rel_tol = 1e-4, + double abs_tol = 1e-4, + bool use_jac = false, + IdxT max_steps = 2000) + { + // Set system model tolerances from input + rel_tol_ = rel_tol; + abs_tol_ = abs_tol; + this->max_steps_ = max_steps; + // Can choose if to use jacobian + use_jac_ = use_jac; + } + + /** + * @brief Destructor for the system model + * + * @pre System components are allocated + * + * @post System components are deallocated + * + */ + virtual ~PowerElectronicsModel() + { + for (auto comp : this->components_) + delete comp; + } + + /** + * @brief allocator default + * + * @todo this should throw an exception as no allocation without a graph is allowed. + * Or needs to be removed from the base class + * + * @return int + */ + int allocate() + { + return 1; + } + + /** + * @brief Will check if each component has jacobian avalible. If one doesn't have it, return false. + * + * + * @return true if all components have jacobian + * @return false otherwise + */ + bool hasJacobian() + { + if (!this->use_jac_) + return false; + + for (const auto& component : components_) + { + if (!component->hasJacobian()) + { + return false; + } + } + return true; + } + + /** + * @brief Allocate the vector data with size amount + * @todo Add capability to go through component model connection to get the size of the actual vector + * + * @param[in] s size of the vector + * + * @post System model vectors allocated with size s + * + * @return int 0 if successful, positive if there's a recoverable error, negative if unrecoverable + */ + int allocate(IdxT s) + { + // Allocate all components + size_ = s; + for (const auto& component : components_) + { + component->allocate(); + } + + // Allocate global vectors + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + + return 0; + } + + /** + * @brief Set intial y and y' of each component + * + * @return int 0 if successful, positive if there's a recoverable error, negative if unrecoverable + */ + int initialize() + { + // Initialize components + for (const auto& component : components_) + { + component->initialize(); + } + this->distributeVectors(); + + return 0; + } + + /** + * @brief Distribute y and y' to each component based of node connection graph + * + * @post Each component has y and y' set + * + * @return int 0 if successful, positive if there's a recoverable error, negative if unrecoverable + */ + int distributeVectors() + { + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + if (component->getNodeConnection(j) != neg1_) + { + component->y()[j] = y_[component->getNodeConnection(j)]; + component->yp()[j] = yp_[component->getNodeConnection(j)]; + } + else + { + component->y()[j] = 0.0; + component->yp()[j] = 0.0; + } + } + } + return 0; + } + + int tagDifferentiable() + { + return 0; + } + + /** + * @brief Evaluate Residuals at each component then collect them + * + * @return int 0 if successful, positive if there's a recoverable error, negative if unrecoverable + */ + int evaluateResidual() + { + for (IdxT i = 0; i < this->f_.size(); i++) + { + f_[i] = 0.0; + } + + this->distributeVectors(); + + // Update system residual vector + + for (const auto& component : components_) + { + // TODO:check return type + component->evaluateResidual(); + for (IdxT j = 0; j < component->size(); ++j) + { + //@todo should do a different grounding check + if (component->getNodeConnection(j) != neg1_) + { + f_[component->getNodeConnection(j)] += component->getResidual()[j]; + } + } + } + + return 0; + } + + /** + * @brief Creates the Sparse COO Jacobian representing \alpha dF/dy' + dF/dy + * + * @return int 0 if successful, positive if there's a recoverable error, negative if unrecoverable + */ + int evaluateJacobian() + { + jac_.zeroMatrix(); + distributeVectors(); + + // Evaluate component jacs + for (const auto& component : components_) + { + component->evaluateJacobian(); + + // get references to local jacobian + std::tuple&, std::vector&, std::vector&> tpm = component->getJacobian().getEntries(); + const auto& [r, c, v] = tpm; + + // Create copies of data to handle groundings + std::vector rgr; + std::vector cgr; + std::vector vgr; + for (IdxT i = 0; i < static_cast(r.size()); i++) + { + if (component->getNodeConnection(r[i]) != neg1_ && component->getNodeConnection(c[i]) != neg1_) + { + rgr.push_back(component->getNodeConnection(r[i])); + cgr.push_back(component->getNodeConnection(c[i])); + vgr.push_back(v[i]); + } + } + + // AXPY to Global Jacobian + // elementwise jac_(rgr, cgr) += vgr + jac_.axpy(1.0, rgr, cgr, vgr); + } + + return 0; + } + + /** + * @brief Evaluate integrands for the system quadratures. + */ + int evaluateIntegrand() + { + + return 0; + } + + /** + * @brief Initialize system adjoint. + * + * Updates variables and optimization parameters, then initializes + * adjoints locally and copies them to the system adjoint vector. + */ + int initializeAdjoint() + { + return 0; + } + + /** + * @brief Compute adjoint residual for the system model. + * + * + */ + int evaluateAdjointResidual() + { + return 0; + } + + /** + * @brief Evaluate adjoint integrand for the system model. + * + * + */ + int evaluateAdjointIntegrand() + { + return 0; + } + + /** + * @brief Distribute time and time scaling for each component + * + * @param t + * @param a + */ + void updateTime(ScalarT t, ScalarT a) + { + for (const auto& component : components_) + { + component->updateTime(t, a); + } + time_ = t; + alpha_ = a; + } + + void addComponent(component_type* component) + { + components_.push_back(component); + } + + private: + static constexpr IdxT neg1_ = static_cast(-1); + + std::vector components_; + bool use_jac_; + + }; // class PowerElectronicsModel + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/TransmissionLine/CMakeLists.txt b/src/Model/PowerElectronics/TransmissionLine/CMakeLists.txt new file mode 100644 index 000000000..f8e76a1dc --- /dev/null +++ b/src/Model/PowerElectronics/TransmissionLine/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(power_elec_tranline + SOURCES + TransmissionLine.cpp + OUTPUT_NAME + gridkit_power_elec_tranline) diff --git a/src/Model/PowerElectronics/TransmissionLine/TransmissionLine.cpp b/src/Model/PowerElectronics/TransmissionLine/TransmissionLine.cpp new file mode 100644 index 000000000..85ec9151a --- /dev/null +++ b/src/Model/PowerElectronics/TransmissionLine/TransmissionLine.cpp @@ -0,0 +1,196 @@ + +#include "TransmissionLine.hpp" + +#include +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a TransmissionLine model + * + * Calls default ModelEvaluatorImpl constructor. + * + * This is the Medium distance form with the use of the admittance matrix. + * Since the line is of medium length then there is no real part for shunt admittance + * @todo needs to used in a model + * @todo test for correctness + */ + + template + TransmissionLine::TransmissionLine(IdxT id, ScalarT R, ScalarT X, ScalarT B) + : R_(R), + X_(X), + B_(B) + { + // internals [Iret1, Iimt1, Iret2, Iimt2] + // externals [Vre11, Vim11, Vre12, Vim12, Vre21, Vim21, Vre22, Vim22] + size_ = 12; + n_intern_ = 4; + n_extern_ = 8; + extern_indices_ = {0, 1, 2, 3, 4, 5, 6, 7}; + idc_ = id; + + ScalarT magImpendence = 1 / (R_ * R_ + X_ * X_); + YReMat_ = magImpendence * R_; + YImMatOff_ = magImpendence * X_; + YImMatDi_ = B_ / (2.0) - YImMatOff_; + } + + template + TransmissionLine::~TransmissionLine() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int TransmissionLine::allocate() + { + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + + return 0; + } + + /** + * Initialization of the grid model + */ + template + int TransmissionLine::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int TransmissionLine::tagDifferentiable() + { + return 0; + } + + /** + * @brief Evaluate residual of transmission line + * + * The complex admittance matrix is: + * [[ Y/2 + 1/Z, -1/Z]; + * [ -1/Z, Y/2 + 1/Z]] = + * [[R/|Z|, -R/|Z|]; + * [-R/|Z|, R/|Z|]] + + * i [[B/2 - X/|Z|, X/|Z|]; + * [X/|Z|, B/2 - X/|Z|]] + * = Dre + i Dim + * + * Then + * Ire = Dre Vre - Dim Vim + * Iim = Dre Vim + Dim Vre + * + * To express this for Modified Nodal Analysis the Voltages of the admittance matrix are put into voltage drops + */ + template + int TransmissionLine::evaluateResidual() + { + // input + f_[0] = y_[8]; + f_[1] = y_[9]; + + f_[2] = y_[10]; + f_[3] = y_[11]; + // ouput + f_[4] = -y_[8]; + f_[5] = -y_[9]; + + f_[6] = -y_[10]; + f_[7] = -y_[11]; + + // Voltage drop accross terminals + ScalarT V1re = y_[0] - y_[4]; + ScalarT V1im = y_[1] - y_[5]; + ScalarT V2re = y_[2] - y_[6]; + ScalarT V2im = y_[3] - y_[7]; + + // Internal variables + // row 1 + f_[8] = YReMat_ * (V1re - V2re) - (YImMatDi_ * V1im + YImMatOff_ * V2im) - y_[8]; + f_[9] = YReMat_ * (V1im - V2im) + (YImMatDi_ * V1re + YImMatOff_ * V2re) - y_[9]; + + // row2 + f_[10] = YReMat_ * (V2re - V1re) - (YImMatOff_ * V1im + YImMatDi_ * V2im) - y_[10]; + f_[11] = YReMat_ * (V2im - V1im) + (YImMatOff_ * V1re + YImMatDi_ * V2re) - y_[11]; + + return 0; + } + + /** + * @brief Generate Jacobian for Transmission Line + * + * @tparam ScalarT + * @tparam IdxT + * @return int + */ + template + int TransmissionLine::evaluateJacobian() + { + + // Create dF/dy + std::vector rtemp{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + std::vector ctemp{8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11}; + std::vector vals{1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}; + jac_.setValues(rtemp, ctemp, vals); + + std::vector ccord{0, 1, 2, 3, 4, 5, 6, 7}; + + std::vector rcord(ccord.size(), 8); + vals = {YReMat_, -YImMatDi_, -YReMat_, -YImMatOff_, -YReMat_, YImMatDi_, YReMat_, YImMatOff_}; + jac_.setValues(rtemp, ctemp, vals); + + std::fill(rcord.begin(), rcord.end(), 9); + vals = {YImMatDi_, YReMat_, YImMatOff_, -YReMat_, -YImMatDi_, -YReMat_, -YImMatOff_, YReMat_}; + jac_.setValues(rtemp, ctemp, vals); + + std::fill(rcord.begin(), rcord.end(), 10); + vals = {-YReMat_, -YImMatDi_, YReMat_, -YImMatOff_, YReMat_, YImMatDi_, -YReMat_, YImMatOff_}; + jac_.setValues(rtemp, ctemp, vals); + + std::fill(rcord.begin(), rcord.end(), 11); + vals = {YImMatDi_, -YReMat_, YImMatOff_, YReMat_, -YImMatDi_, YReMat_, -YImMatOff_, -YReMat_}; + jac_.setValues(rtemp, ctemp, vals); + + return 0; + } + + template + int TransmissionLine::evaluateIntegrand() + { + return 0; + } + + template + int TransmissionLine::initializeAdjoint() + { + return 0; + } + + template + int TransmissionLine::evaluateAdjointResidual() + { + return 0; + } + + template + int TransmissionLine::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class TransmissionLine; + template class TransmissionLine; + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/TransmissionLine/TransmissionLine.hpp b/src/Model/PowerElectronics/TransmissionLine/TransmissionLine.hpp new file mode 100644 index 000000000..badd0cf9d --- /dev/null +++ b/src/Model/PowerElectronics/TransmissionLine/TransmissionLine.hpp @@ -0,0 +1,75 @@ + + +#ifndef _TRANLINE_HPP_ +#define _TRANLINE_HPP_ + +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Declaration of a TransmissionLine class. + * + * Model from Adam Birchfield paper (medium distances < 2km). + * See also textbooks "Power System Analysis" by Grainger and "Power System Dynamics and Stability" by Sauer & Pai + * + * @note Not used in the Microgrid model. + */ + template + class TransmissionLine : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::jac_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + using CircuitComponent::extern_indices_; + using CircuitComponent::n_extern_; + using CircuitComponent::n_intern_; + + public: + TransmissionLine(IdxT id, ScalarT R, ScalarT X, ScalarT B); + virtual ~TransmissionLine(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT R_; + ScalarT X_; + ScalarT B_; + ScalarT YReMat_; + ScalarT YImMatDi_; + ScalarT YImMatOff_; + }; +} // namespace GridKit + +#endif diff --git a/src/Model/PowerElectronics/VoltageSource/CMakeLists.txt b/src/Model/PowerElectronics/VoltageSource/CMakeLists.txt new file mode 100644 index 000000000..129da3bb5 --- /dev/null +++ b/src/Model/PowerElectronics/VoltageSource/CMakeLists.txt @@ -0,0 +1,8 @@ + + + +gridkit_add_library(power_elec_voltagesource + SOURCES + VoltageSource.cpp + OUTPUT_NAME + gridkit_power_elec_voltagesource) diff --git a/src/Model/PowerElectronics/VoltageSource/VoltageSource.cpp b/src/Model/PowerElectronics/VoltageSource/VoltageSource.cpp new file mode 100644 index 000000000..8a2adaeb1 --- /dev/null +++ b/src/Model/PowerElectronics/VoltageSource/VoltageSource.cpp @@ -0,0 +1,120 @@ + + +#include "VoltageSource.hpp" + +#include +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a constant VoltageSource model + * + * Calls default ModelEvaluatorImpl constructor. + */ + + template + VoltageSource::VoltageSource(IdxT id, ScalarT V) + : V_(V) + { + size_ = 3; + n_intern_ = 1; + n_extern_ = 2; + extern_indices_ = {0, 1}; + idc_ = id; + } + + template + VoltageSource::~VoltageSource() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int VoltageSource::allocate() + { + y_.resize(size_); + yp_.resize(size_); + f_.resize(size_); + + return 0; + } + + /** + * Initialization of the grid model + */ + template + int VoltageSource::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int VoltageSource::tagDifferentiable() + { + return 0; + } + + /** + * @brief Evaluate resisdual of component + */ + template + int VoltageSource::evaluateResidual() + { + // input + f_[0] = -y_[2]; + // ouput + f_[1] = y_[2]; + // internal + f_[2] = y_[1] - y_[0] - V_; + return 0; + } + + template + int VoltageSource::evaluateJacobian() + { + // Create dF/dy + std::vector rcord{0, 1, 2, 2}; + std::vector ccord{2, 2, 0, 1}; + std::vector vals{-1.0, 1.0, -1.0, 1.0}; + jac_.setValues(rcord, ccord, vals); + + return 0; + } + + template + int VoltageSource::evaluateIntegrand() + { + return 0; + } + + template + int VoltageSource::initializeAdjoint() + { + return 0; + } + + template + int VoltageSource::evaluateAdjointResidual() + { + return 0; + } + + template + int VoltageSource::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class VoltageSource; + template class VoltageSource; + +} // namespace GridKit diff --git a/src/Model/PowerElectronics/VoltageSource/VoltageSource.hpp b/src/Model/PowerElectronics/VoltageSource/VoltageSource.hpp new file mode 100644 index 000000000..d3b630a07 --- /dev/null +++ b/src/Model/PowerElectronics/VoltageSource/VoltageSource.hpp @@ -0,0 +1,66 @@ + + +#ifndef _VOSO_HPP_ +#define _VOSO_HPP_ + +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Declaration of a VoltageSource class. + * + */ + template + class VoltageSource : public CircuitComponent + { + using CircuitComponent::size_; + using CircuitComponent::nnz_; + using CircuitComponent::time_; + using CircuitComponent::alpha_; + using CircuitComponent::y_; + using CircuitComponent::yp_; + using CircuitComponent::tag_; + using CircuitComponent::f_; + using CircuitComponent::g_; + using CircuitComponent::yB_; + using CircuitComponent::ypB_; + using CircuitComponent::fB_; + using CircuitComponent::gB_; + using CircuitComponent::jac_; + using CircuitComponent::param_; + using CircuitComponent::idc_; + + using CircuitComponent::extern_indices_; + using CircuitComponent::n_extern_; + using CircuitComponent::n_intern_; + + public: + VoltageSource(IdxT id, ScalarT V); + virtual ~VoltageSource(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + private: + ScalarT V_; + }; +} // namespace GridKit + +#endif diff --git a/src/Model/PowerFlow/Branch/Branch.cpp b/src/Model/PowerFlow/Branch/Branch.cpp new file mode 100644 index 000000000..08b943264 --- /dev/null +++ b/src/Model/PowerFlow/Branch/Branch.cpp @@ -0,0 +1,161 @@ + +#include "Branch.hpp" + +#include +#include + +#include +#include + +namespace GridKit +{ + + /*! + * @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), + fbusID_(0), + tbusID_(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), + fbusID_(0), + tbusID_(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), + fbusID_(data.fbus), + tbusID_(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() + { + // std::cout << "Evaluating branch residual ...\n"; + real_type b = -X_ / (R_ * R_ + X_ * X_); + real_type g = R_ / (R_ * R_ + X_ * X_); + ScalarT dtheta = theta1() - theta2(); + + P1() -= (g + 0.5 * G_) * V1() * V1() + V1() * V2() * (-g * cos(dtheta) - b * sin(dtheta)); + Q1() -= (-b - 0.5 * B_) * V1() * V1() + V1() * V2() * (-g * sin(dtheta) + b * cos(dtheta)); + P2() -= (g + 0.5 * G_) * V2() * V2() + V1() * V2() * (-g * cos(dtheta) + b * sin(dtheta)); + Q2() -= (-b - 0.5 * B_) * V2() * V2() + V1() * V2() * (g * sin(dtheta) + b * cos(dtheta)); + + return 0; + } + + template + int Branch::evaluateJacobian() + { + 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; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Branch/Branch.hpp b/src/Model/PowerFlow/Branch/Branch.hpp new file mode 100644 index 000000000..d6500bddf --- /dev/null +++ b/src/Model/PowerFlow/Branch/Branch.hpp @@ -0,0 +1,145 @@ + +#ifndef _BRANCH_H_ +#define _BRANCH_H_ + +#include + +// Forward declarations. +namespace GridKit +{ + template + class BaseBus; + + namespace PowerSystemData + { + template + struct BranchData; + } +} // namespace GridKit + +namespace GridKit +{ + /*! + * @brief Implementation of a pi-model branch between two buses. + * + */ + template + class Branch : public ModelEvaluatorImpl + { + 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 = BaseBus; + using real_type = typename ModelEvaluatorImpl::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, BranchData& data); + virtual ~Branch(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + void updateTime(real_type t, real_type a) + { + } + + public: + void setR(real_type R) + { + R_ = R; + } + + void setX(real_type X) + { + // std::cout << "Setting X ...\n"; + X_ = X; + } + + void setG(real_type G) + { + G_ = G; + } + + void setB(real_type B) + { + B_ = B; + } + + private: + ScalarT& V1() + { + return bus1_->V(); + } + + ScalarT& theta1() + { + return bus1_->theta(); + } + + ScalarT& P1() + { + return bus1_->P(); + } + + ScalarT& Q1() + { + return bus1_->Q(); + } + + ScalarT& V2() + { + return bus2_->V(); + } + + ScalarT& theta2() + { + return bus2_->theta(); + } + + ScalarT& P2() + { + return bus2_->P(); + } + + ScalarT& Q2() + { + return bus2_->Q(); + } + + private: + real_type R_; + real_type X_; + real_type G_; + real_type B_; + const IdxT fbusID_; + const IdxT tbusID_; + bus_type* bus1_; + bus_type* bus2_; + }; +} // namespace GridKit + +#endif // _BRANCH_H diff --git a/src/Model/PowerFlow/Branch/CMakeLists.txt b/src/Model/PowerFlow/Branch/CMakeLists.txt new file mode 100644 index 000000000..0b1076390 --- /dev/null +++ b/src/Model/PowerFlow/Branch/CMakeLists.txt @@ -0,0 +1,10 @@ +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +gridkit_add_library(branch + SOURCES + Branch.cpp + OUTPUT_NAME + gridkit_branch) diff --git a/ComponentLib/Branch/README.md b/src/Model/PowerFlow/Branch/README.md similarity index 96% rename from ComponentLib/Branch/README.md rename to src/Model/PowerFlow/Branch/README.md index ecfc61a34..3440da3eb 100644 --- a/ComponentLib/Branch/README.md +++ b/src/Model/PowerFlow/Branch/README.md @@ -7,7 +7,7 @@ Transmission lines and different types of transformers (traditional, Load Tap-Ch The most common circuit that is used to represent the transmission line model is $`\pi`$ circuit as shown in Figure 1. The nominal flow direction is from sending bus _s_ to receiving bus _r_.
- + Figure 1: Transmission line $`\pi`$ equivalent circuit @@ -108,7 +108,7 @@ These quantities are treated as _loads_ and are substracted from $`P`$ and $`Q`$ The branch model can be created by adding the ideal transformer in series with the $`\pi`$ circuit as shown in Figure 2 where $`\tau`$ is a tap ratio magnitude and $`\theta_{shift}`$is the phase shift angle.
- + Figure 2: Branch equivalent circuit diff --git a/src/Model/PowerFlow/Bus/BaseBus.hpp b/src/Model/PowerFlow/Bus/BaseBus.hpp new file mode 100644 index 000000000..6f682dcd5 --- /dev/null +++ b/src/Model/PowerFlow/Bus/BaseBus.hpp @@ -0,0 +1,147 @@ + +#ifndef _BASE_BUS_HPP_ +#define _BASE_BUS_HPP_ + +#include + +namespace GridKit +{ + /*! + * @brief Base class for all power flow buses. + * + * Derived bus types: + * 0 - swing bus (V and theta are constants) + * 1 - PV bus (P and V are constants) + * 2 - PQ bus (P and Q are constants) + * + * @todo Consider static instead of dynamic polymorphism for + * bus types. Create Bus class that takes template parameter + * BusType. + */ + template + class BaseBus : public ModelEvaluatorImpl + { + protected: + using ModelEvaluatorImpl::size_; + using ModelEvaluatorImpl::nnz_; + using ModelEvaluatorImpl::time_; + using ModelEvaluatorImpl::alpha_; + using ModelEvaluatorImpl::rel_tol_; + using ModelEvaluatorImpl::abs_tol_; + 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 ModelEvaluatorImpl::param_up_; + using ModelEvaluatorImpl::param_lo_; + + public: + typedef typename ModelEvaluatorImpl::real_type real_type; + + enum BusType + { + PQ = 1, + PV, + Slack, + Isolated + }; + + BaseBus(IdxT id) + : busID_(id) + { + } + + virtual ~BaseBus() + { + } + + // Set defaults for ModelEvaluator methods + virtual int allocate() + { + return 0; + } + + virtual int initialize() + { + return 0; + } + + virtual int tagDifferentiable() + { + return 0; + } + + virtual int evaluateResidual() + { + return 0; + } + + virtual int evaluateJacobian() + { + return 0; + } + + virtual int evaluateIntegrand() + { + return 0; + } + + virtual int initializeAdjoint() + { + return 0; + } + + virtual int evaluateAdjointResidual() + { + return 0; + } + + // virtual int evaluateAdjointJacobian() { return 0;} + virtual int evaluateAdjointIntegrand() + { + return 0; + } + + virtual void updateTime(real_type, real_type) + { + } // <- throw exception here + + // Pure virtual methods specific to Bus types + virtual ScalarT& V() = 0; + virtual const ScalarT& V() const = 0; + virtual ScalarT& theta() = 0; + virtual const ScalarT& theta() const = 0; + virtual ScalarT& P() = 0; + virtual const ScalarT& P() const = 0; + virtual ScalarT& Q() = 0; + virtual const ScalarT& Q() const = 0; + + virtual ScalarT& lambdaP() = 0; + virtual const ScalarT& lambdaP() const = 0; + virtual ScalarT& lambdaQ() = 0; + virtual const ScalarT& lambdaQ() const = 0; + virtual ScalarT& PB() = 0; + virtual const ScalarT& PB() const = 0; + virtual ScalarT& QB() = 0; + virtual const ScalarT& QB() const = 0; + + virtual int BusType() const = 0; + + virtual const IdxT BusID() const + { + return busID_; + } + + protected: + const IdxT busID_; + }; // class BaseBus + +} // namespace GridKit + +#endif // _BASE_BUS_HPP_ diff --git a/src/Model/PowerFlow/Bus/BusFactory.hpp b/src/Model/PowerFlow/Bus/BusFactory.hpp new file mode 100644 index 000000000..5a1c6e95b --- /dev/null +++ b/src/Model/PowerFlow/Bus/BusFactory.hpp @@ -0,0 +1,43 @@ + +#pragma once + +#include +#include +#include +#include + +namespace GridKit +{ + + template + class BusFactory + { + public: + using real_type = typename ModelEvaluatorImpl::real_type; + using BusData = GridKit::PowerSystemData::BusData; + + BusFactory() = delete; + + static BaseBus* create(BusData& data) + { + BaseBus* bus = nullptr; + switch (data.type) + { + case 1: + bus = new BusPQ(data); + break; + case 2: + bus = new BusPV(data); + break; + case 3: + bus = new BusSlack(data); + break; + default: + // Throw exception + std::cout << "Bus type " << data.type << " unrecognized.\n"; + } + return bus; + } + }; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Bus/BusPQ.cpp b/src/Model/PowerFlow/Bus/BusPQ.cpp new file mode 100644 index 000000000..207c304df --- /dev/null +++ b/src/Model/PowerFlow/Bus/BusPQ.cpp @@ -0,0 +1,152 @@ + +#include "BusPQ.hpp" + +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a PQ bus + * + * @todo Arguments that should be passed to ModelEvaluatorImpl constructor: + * - Number of equations = 2 (size_) + * - Number of variables = 2 (size_) + * - Number of quadratures = 0 + * - Number of optimization parameters = 0 + */ + template + BusPQ::BusPQ() + : BaseBus(0), V0_(0.0), theta0_(0.0) + { + // std::cout << "Create BusPQ..." << std::endl; + // std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 2; + } + + /*! + * @brief BusPQ constructor. + * + * This constructor sets initial values for voltage and phase angle. + * + * @todo Arguments that should be passed to ModelEvaluatorImpl constructor: + * - Number of equations = 2 (size_) + * - Number of variables = 2 (size_) + * - Number of quadratures = 0 + * - Number of optimization parameters = 0 + */ + template + BusPQ::BusPQ(ScalarT V, ScalarT theta) + : BaseBus(0), V0_(V), theta0_(theta) + { + // std::cout << "Create BusPQ..." << std::endl; + // std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 2; + } + + template + BusPQ::BusPQ(BusData& data) + : BaseBus(data.bus_i), V0_(data.Vm), theta0_(data.Va) + { + // std::cout << "Create BusPQ..." << std::endl; + // std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 2; + } + + template + BusPQ::~BusPQ() + { + // std::cout << "Destroy PQ bus ..." << std::endl; + } + + /*! + * @brief allocate method resizes local solution and residual vectors. + */ + template + int BusPQ::allocate() + { + // std::cout << "Allocate PQ bus ..." << std::endl; + f_.resize(size_); + y_.resize(size_); + yp_.resize(size_); + tag_.resize(size_); + + fB_.resize(size_); + yB_.resize(size_); + ypB_.resize(size_); + + return 0; + } + + template + int BusPQ::tagDifferentiable() + { + tag_[0] = false; + tag_[1] = false; + return 0; + } + + /*! + * @brief initialize method sets bus variables to stored initial values. + */ + template + int BusPQ::initialize() + { + // std::cout << "Initialize BusPQ..." << std::endl; + y_[0] = V0_; + y_[1] = theta0_; + yp_[0] = 0.0; + yp_[1] = 0.0; + + return 0; + } + + /*! + * @brief PQ bus does not compute residuals, so here we just reset residual values. + * + * @warning This implementation assumes bus residuals are always evaluated + * _before_ component model residuals. + * + */ + template + int BusPQ::evaluateResidual() + { + // std::cout << "Evaluating residual of a PQ bus ...\n"; + f_[0] = 0.0; + f_[1] = 0.0; + return 0; + } + + /*! + * @brief initialize method sets bus variables to stored initial values. + */ + template + int BusPQ::initializeAdjoint() + { + // std::cout << "Initialize BusPQ..." << std::endl; + yB_[0] = 0.0; + yB_[1] = 0.0; + ypB_[0] = 0.0; + ypB_[1] = 0.0; + + return 0; + } + + template + int BusPQ::evaluateAdjointResidual() + { + fB_[0] = 0.0; + fB_[1] = 0.0; + + return 0; + } + + // Available template instantiations + template class BusPQ; + template class BusPQ; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Bus/BusPQ.hpp b/src/Model/PowerFlow/Bus/BusPQ.hpp new file mode 100644 index 000000000..fd96ca396 --- /dev/null +++ b/src/Model/PowerFlow/Bus/BusPQ.hpp @@ -0,0 +1,139 @@ + +#ifndef _BUS_PQ_HPP_ +#define _BUS_PQ_HPP_ + +#include "BaseBus.hpp" +#include + +namespace GridKit +{ + /*! + * @brief Implementation of a PQ bus. + * + * Voltage _V_ and phase _theta_ are variables in PQ bus model. + * Active and reactive power, _P_ and _Q_, are residual components. + * + * + */ + template + class BusPQ : public BaseBus + { + using BaseBus::size_; + using BaseBus::y_; + using BaseBus::yp_; + using BaseBus::yB_; + using BaseBus::ypB_; + using BaseBus::f_; + using BaseBus::fB_; + using BaseBus::tag_; + + public: + using real_type = typename ModelEvaluatorImpl::real_type; + using BusData = GridKit::PowerSystemData::BusData; + + BusPQ(); + BusPQ(ScalarT V, ScalarT theta); + BusPQ(BusData& data); + virtual ~BusPQ(); + + virtual int allocate(); + virtual int tagDifferentiable(); + virtual int initialize(); + virtual int evaluateResidual(); + virtual int initializeAdjoint(); + virtual int evaluateAdjointResidual(); + + virtual ScalarT& V() + { + return y_[0]; + } + + virtual const ScalarT& V() const + { + return y_[0]; + } + + virtual ScalarT& theta() + { + return y_[1]; + } + + virtual const ScalarT& theta() const + { + return y_[1]; + } + + virtual ScalarT& P() + { + return f_[0]; + } + + virtual const ScalarT& P() const + { + return f_[0]; + } + + virtual ScalarT& Q() + { + return f_[1]; + } + + virtual const ScalarT& Q() const + { + return f_[1]; + } + + virtual ScalarT& lambdaP() + { + return yB_[0]; + } + + virtual const ScalarT& lambdaP() const + { + return yB_[0]; + } + + virtual ScalarT& lambdaQ() + { + return yB_[1]; + } + + virtual const ScalarT& lambdaQ() const + { + return yB_[1]; + } + + virtual ScalarT& PB() + { + return fB_[0]; + } + + virtual const ScalarT& PB() const + { + return fB_[0]; + } + + virtual ScalarT& QB() + { + return fB_[1]; + } + + virtual const ScalarT& QB() const + { + return fB_[1]; + } + + virtual int BusType() const + { + return BaseBus::BusType::PQ; + } + + private: + // Default initial values for voltage and phase on PQ bus + ScalarT V0_; + ScalarT theta0_; + }; + +} // namespace GridKit + +#endif // _BUS_PQ_HPP_ diff --git a/src/Model/PowerFlow/Bus/BusPV.cpp b/src/Model/PowerFlow/Bus/BusPV.cpp new file mode 100644 index 000000000..1552fb06d --- /dev/null +++ b/src/Model/PowerFlow/Bus/BusPV.cpp @@ -0,0 +1,145 @@ + +#include "BusPV.hpp" + +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a PV bus + * + * @todo Arguments that should be passed to ModelEvaluatorImpl constructor: + * - Number of equations = 1 (size_) + * - Number of variables = 1 (size_) + * - Number of quadratures = 0 + * - Number of optimization parameters = 0 + */ + template + BusPV::BusPV() + : BaseBus(0), V_(0.0), theta0_(0.0) + { + // std::cout << "Create BusPV..." << std::endl; + // std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 1; + } + + /*! + * @brief Constructor for a PV bus + * + * @todo Arguments that should be passed to ModelEvaluatorImpl constructor: + * - Number of equations = 1 (size_) + * - Number of variables = 1 (size_) + * - Number of quadratures = 0 + * - Number of optimization parameters = 0 + */ + template + BusPV::BusPV(ScalarT V, ScalarT theta0) + : BaseBus(0), V_(V), theta0_(theta0) + { + // std::cout << "Create BusPV..." << std::endl; + // std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 1; + } + + template + BusPV::BusPV(BusData& data) + : BaseBus(data.bus_i), V_(data.Vm), theta0_(data.Va) + { + // std::cout << "Create BusPV ..." << std::endl; + // std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 1; + } + + template + BusPV::~BusPV() + { + // std::cout << "Destroy Gen2..." << std::endl; + } + + /*! + * @brief allocate method resizes local solution and residual vectors. + */ + template + int BusPV::allocate() + { + // std::cout << "Allocate PV bus ..." << std::endl; + f_.resize(size_); + y_.resize(size_); + yp_.resize(size_); + tag_.resize(size_); + + fB_.resize(size_); + yB_.resize(size_); + ypB_.resize(size_); + + return 0; + } + + template + int BusPV::tagDifferentiable() + { + tag_[0] = false; + return 0; + } + + /*! + * @brief initialize method sets bus variables to stored initial values. + */ + template + int BusPV::initialize() + { + // std::cout << "Initialize BusPV..." << std::endl; + theta() = theta0_; + yp_[0] = 0.0; + + return 0; + } + + /*! + * @brief PV bus does not compute residuals, so here we just reset residual values. + * + * @warning This implementation assumes bus residuals are always evaluated + * _before_ component model residuals. + * + */ + template + int BusPV::evaluateResidual() + { + // std::cout << "Evaluating residual of a PV bus ...\n"; + P() = 0.0; // <-- Residual P + Q() = 0.0; // <-- Output Qg, the reactive power generator needs to supply + + return 0; + } + + /*! + * @brief initialize method sets bus variables to stored initial values. + */ + template + int BusPV::initializeAdjoint() + { + // std::cout << "Initialize BusPV..." << std::endl; + yB_[0] = 0.0; + ypB_[0] = 0.0; + + return 0; + } + + template + int BusPV::evaluateAdjointResidual() + { + fB_[0] = 0.0; + + return 0; + } + + // Available template instantiations + template class BusPV; + template class BusPV; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Bus/BusPV.hpp b/src/Model/PowerFlow/Bus/BusPV.hpp new file mode 100644 index 000000000..ac180e926 --- /dev/null +++ b/src/Model/PowerFlow/Bus/BusPV.hpp @@ -0,0 +1,154 @@ + +#ifndef _BUS_PV_HPP_ +#define _BUS_PV_HPP_ + +#include + +#include "BaseBus.hpp" +#include + +namespace GridKit +{ + /*! + * @brief Implementation of a PV bus. + * + * Voltage _V_ and phase _theta_ are variables in PV bus model. + * Active and reactive power, _P_ and _Q_, are residual components. + * + * + */ + template + class BusPV : public BaseBus + { + using BaseBus::size_; + using BaseBus::y_; + using BaseBus::yp_; + using BaseBus::yB_; + using BaseBus::ypB_; + using BaseBus::f_; + using BaseBus::fB_; + using BaseBus::tag_; + + public: + using real_type = typename ModelEvaluatorImpl::real_type; + using BusData = GridKit::PowerSystemData::BusData; + + BusPV(); + BusPV(ScalarT V, ScalarT theta0); + BusPV(BusData& data); + virtual ~BusPV(); + + virtual int allocate(); + virtual int tagDifferentiable(); + virtual int initialize(); + virtual int evaluateResidual(); + virtual int initializeAdjoint(); + virtual int evaluateAdjointResidual(); + + virtual ScalarT& V() + { + return V_; + } + + virtual const ScalarT& V() const + { + return V_; + } + + virtual ScalarT& theta() + { + return y_[0]; + } + + virtual const ScalarT& theta() const + { + return y_[0]; + } + + virtual ScalarT& P() + { + return f_[0]; + } + + virtual const ScalarT& P() const + { + return f_[0]; + } + + virtual ScalarT& Q() + { + return Q_; + } + + virtual const ScalarT& Q() const + { + return Q_; + } + + virtual ScalarT& lambdaP() + { + assert(false); + return thetaB_; + } + + virtual const ScalarT& lambdaP() const + { + assert(false); + return thetaB_; + } + + virtual ScalarT& lambdaQ() + { + assert(false); + return VB_; + } + + virtual const ScalarT& lambdaQ() const + { + assert(false); + return VB_; + } + + virtual ScalarT& PB() + { + assert(false); + return PB_; + } + + virtual const ScalarT& PB() const + { + assert(false); + return PB_; + } + + virtual ScalarT& QB() + { + assert(false); + return QB_; + } + + virtual const ScalarT& QB() const + { + assert(false); + return QB_; + } + + virtual int BusType() const + { + return BaseBus::BusType::PV; + } + + private: + ScalarT V_; ///< Bus voltage magnitude + ScalarT theta0_; ///< Default initial value for phase + ScalarT Q_; ///< Reactive power that generator needs to provide + + ScalarT VB_; + ScalarT thetaB_; + ScalarT PB_; + ScalarT QB_; + }; + +} // namespace GridKit + +#endif // _BUS_PV_HPP_ diff --git a/src/Model/PowerFlow/Bus/BusSlack.cpp b/src/Model/PowerFlow/Bus/BusSlack.cpp new file mode 100644 index 000000000..dab1ec0a7 --- /dev/null +++ b/src/Model/PowerFlow/Bus/BusSlack.cpp @@ -0,0 +1,86 @@ + +#include "BusSlack.hpp" + +#include +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a slack bus + * + * Arguments passed to ModelEvaluatorImpl: + * - Number of equations = 0 (size_) + * - Number of variables = 0 (size_) + * - Number of quadratures = 0 + * - Number of optimization parameters = 0 + */ + template + BusSlack::BusSlack() + : BaseBus(0), V_(0.0), theta_(0.0), P_(0.0), Q_(0.0), PB_(0.0), QB_(0.0) + { + // std::cout << "Create BusSlack..." << std::endl; + // std::cout << "Number of equations is " << size_ << std::endl; + + size_ = 0; + } + + /*! + * @brief BusSlack constructor. + * + * Arguments passed to ModelEvaluatorImpl: + * - Number of equations = 0 (size_) + * - Number of variables = 0 (size_) + * - Number of quadratures = 0 + * - Number of optimization parameters = 0 + */ + template + BusSlack::BusSlack(ScalarT V, ScalarT theta) + : BaseBus(0), V_(V), theta_(theta), P_(0.0), Q_(0.0), PB_(0.0), QB_(0.0) + { + // std::cout << "Create BusSlack..." << std::endl; + // std::cout << "Number of equations is " << size_ << std::endl; + P() = 0.0; + Q() = 0.0; + size_ = 0; + } + + template + BusSlack::BusSlack(BusData& data) + : BaseBus(data.bus_i), V_(data.Vm), theta_(data.Va) + { + // std::cout << "Create BusSlack..." << std::endl; + // std::cout << "Number of equations is " << size_ << std::endl; + P() = 0.0; + Q() = 0.0; + size_ = 0; + } + + template + BusSlack::~BusSlack() + { + } + + template + int BusSlack::evaluateResidual() + { + // std::cout << "Evaluating residual of a slack bus ...\n"; + P() = 0.0; + Q() = 0.0; + return 0; + } + + template + int BusSlack::evaluateAdjointResidual() + { + PB() = 0.0; + QB() = 0.0; + return 0; + } + + // Available template instantiations + template class BusSlack; + template class BusSlack; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Bus/BusSlack.hpp b/src/Model/PowerFlow/Bus/BusSlack.hpp new file mode 100644 index 000000000..96d2ba66c --- /dev/null +++ b/src/Model/PowerFlow/Bus/BusSlack.hpp @@ -0,0 +1,145 @@ + +#ifndef _BUS_SLACK_HPP_ +#define _BUS_SLACK_HPP_ + +#include "BaseBus.hpp" +#include + +namespace GridKit +{ + /*! + * @brief Implementation of a slack bus. + * + * Slack bus sets voltage _V_ and phase _theta_ as constants. + * Active and reactive power, _P_ and _Q_, are component model outputs, + * but are computed outside the BusSlack class. + * + * + */ + template + class BusSlack : public BaseBus + { + using BaseBus::size_; + using BaseBus::y_; + using BaseBus::yp_; + using BaseBus::f_; + using BaseBus::g_; + using BaseBus::abs_tol_; + using BaseBus::rel_tol_; + + public: + using real_type = typename ModelEvaluatorImpl::real_type; + using BusData = GridKit::PowerSystemData::BusData; + + BusSlack(); + BusSlack(ScalarT V, ScalarT theta); + BusSlack(BusData& data); + virtual ~BusSlack(); + virtual int evaluateResidual(); + virtual int evaluateAdjointResidual(); + + /// @todo Should slack bus allow changing voltage? + virtual ScalarT& V() + { + return V_; + } + + virtual const ScalarT& V() const + { + return V_; + } + + /// @todo Should slack bus allow changing phase? + virtual ScalarT& theta() + { + return theta_; + } + + virtual const ScalarT& theta() const + { + return theta_; + } + + virtual ScalarT& P() + { + return P_; + } + + virtual const ScalarT& P() const + { + return P_; + } + + virtual ScalarT& Q() + { + return Q_; + } + + virtual const ScalarT& Q() const + { + return Q_; + } + + /// @todo Should slack bus allow changing voltage? + virtual ScalarT& lambdaP() + { + return thetaB_; + } + + virtual const ScalarT& lambdaP() const + { + return thetaB_; + } + + /// @todo Should slack bus allow changing phase? + virtual ScalarT& lambdaQ() + { + return VB_; + } + + virtual const ScalarT& lambdaQ() const + { + return VB_; + } + + virtual ScalarT& PB() + { + return PB_; + } + + virtual const ScalarT& PB() const + { + return PB_; + } + + virtual ScalarT& QB() + { + return QB_; + } + + virtual const ScalarT& QB() const + { + return QB_; + } + + virtual int BusType() const + { + return BaseBus::BusType::Slack; + } + + private: + ScalarT V_; + ScalarT theta_; + ScalarT P_; + ScalarT Q_; + + ScalarT VB_; + ScalarT thetaB_; + ScalarT PB_; + ScalarT QB_; + + }; // class BusSlack + +} // namespace GridKit + +#endif // _BUS_SLACK_HPP_ diff --git a/src/Model/PowerFlow/Bus/CMakeLists.txt b/src/Model/PowerFlow/Bus/CMakeLists.txt new file mode 100644 index 000000000..0cc86c9a4 --- /dev/null +++ b/src/Model/PowerFlow/Bus/CMakeLists.txt @@ -0,0 +1,14 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +gridkit_add_library(bus + SOURCES + BusPQ.cpp + BusPV.cpp + BusSlack.cpp + OUTPUT_NAME + gridkit_bus) diff --git a/ComponentLib/Bus/README.md b/src/Model/PowerFlow/Bus/README.md similarity index 95% rename from ComponentLib/Bus/README.md rename to src/Model/PowerFlow/Bus/README.md index 0e48e5186..c67f718cc 100644 --- a/ComponentLib/Bus/README.md +++ b/src/Model/PowerFlow/Bus/README.md @@ -28,7 +28,7 @@ There exist two:
- + Figure 1: Sign convention for the power flow at the bus $`i`$ @@ -46,4 +46,4 @@ Q_{i}=Q_{Gi}-Q_{Li} ``` **Other Parameters** -Buses are uniquely defined by their ID (number or name). Besides, each bus should have associated Nominal Voltage value. \ No newline at end of file +Buses are uniquely defined by their ID (number or name). Besides, each bus should have associated Nominal Voltage value. diff --git a/src/Model/PowerFlow/CMakeLists.txt b/src/Model/PowerFlow/CMakeLists.txt new file mode 100644 index 000000000..6d5c15728 --- /dev/null +++ b/src/Model/PowerFlow/CMakeLists.txt @@ -0,0 +1,14 @@ +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +add_subdirectory(Branch) +add_subdirectory(Bus) +add_subdirectory(Generator) +add_subdirectory(Generator2) +add_subdirectory(Generator4) +add_subdirectory(Generator4Governor) +add_subdirectory(Generator4Param) +add_subdirectory(Load) +add_subdirectory(MiniGrid) diff --git a/src/Model/PowerFlow/Generator/CMakeLists.txt b/src/Model/PowerFlow/Generator/CMakeLists.txt new file mode 100644 index 000000000..737ba95be --- /dev/null +++ b/src/Model/PowerFlow/Generator/CMakeLists.txt @@ -0,0 +1,12 @@ +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +gridkit_add_library(generator + SOURCES + GeneratorSlack.cpp + GeneratorPV.cpp + GeneratorPQ.cpp + OUTPUT_NAME + gridkit_generator) diff --git a/src/Model/PowerFlow/Generator/GeneratorBase.hpp b/src/Model/PowerFlow/Generator/GeneratorBase.hpp new file mode 100644 index 000000000..90138c7c1 --- /dev/null +++ b/src/Model/PowerFlow/Generator/GeneratorBase.hpp @@ -0,0 +1,108 @@ + +#pragma once + +#include + +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /** + * @brief Generator base class template + * + * @tparam ScalarT - Scalar type + * @tparam IdxT - Matrix and vector index type + */ + template + class GeneratorBase : public ModelEvaluatorImpl + { + protected: + 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 = BaseBus; + using real_type = typename ModelEvaluatorImpl::real_type; + + public: + GeneratorBase() + { + } + + virtual ~GeneratorBase() + { + } + + virtual int allocate() + { + return 0; + } + + virtual int initialize() + { + return 0; + } + + virtual int tagDifferentiable() + { + return 0; + } + + virtual int evaluateResidual() + { + return 0; + } + + virtual int evaluateJacobian() + { + return 0; + } + + virtual int evaluateIntegrand() + { + return 0; + } + + virtual int initializeAdjoint() + { + return 0; + } + + virtual int evaluateAdjointResidual() + { + return 0; + } + + // virtual int evaluateAdjointJacobian(); + virtual int evaluateAdjointIntegrand() + { + return 0; + } + + void updateTime(real_type, real_type) + { + } + + virtual ScalarT& P() = 0; + virtual const ScalarT& P() const = 0; + virtual ScalarT& Q() = 0; + virtual const ScalarT& Q() const = 0; + }; +} // namespace GridKit diff --git a/src/Model/PowerFlow/Generator/GeneratorFactory.hpp b/src/Model/PowerFlow/Generator/GeneratorFactory.hpp new file mode 100644 index 000000000..07d1ac4c8 --- /dev/null +++ b/src/Model/PowerFlow/Generator/GeneratorFactory.hpp @@ -0,0 +1,44 @@ + +#pragma once + +#include +#include +#include +#include +#include + +namespace GridKit +{ + + template + class GeneratorFactory + { + public: + using real_type = typename ModelEvaluatorImpl::real_type; + using GenData = GridKit::PowerSystemData::GenData; + + GeneratorFactory() = delete; + + static GeneratorBase* create(BaseBus* bus, GenData& data) + { + GeneratorBase* gen = nullptr; + switch (bus->BusType()) + { + case 1: + gen = new GeneratorPQ(bus, data); + break; + case 2: + gen = new GeneratorPV(bus, data); + break; + case 3: + gen = new GeneratorSlack(bus, data); + break; + default: + // Throw exception + std::cout << "Generator type " << bus->BusType() << " unrecognized.\n"; + } + return gen; + } + }; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Generator/GeneratorPQ.cpp b/src/Model/PowerFlow/Generator/GeneratorPQ.cpp new file mode 100644 index 000000000..e216b7fff --- /dev/null +++ b/src/Model/PowerFlow/Generator/GeneratorPQ.cpp @@ -0,0 +1,109 @@ + +#include "GeneratorPQ.hpp" + +#include +#include +#include + +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a constant load model + * + * Calls default ModelEvaluatorImpl constructor. + */ + + template + GeneratorPQ::GeneratorPQ(bus_type* bus, GenData& data) + : P_(data.Pg), + Q_(data.Qg), + bus_(bus) + { + // std::cout << "Create a load model with " << size_ << " variables ...\n"; + size_ = 0; + } + + template + GeneratorPQ::~GeneratorPQ() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int GeneratorPQ::allocate() + { + return 0; + } + + /** + * Initialization of the grid model + */ + template + int GeneratorPQ::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int GeneratorPQ::tagDifferentiable() + { + return 0; + } + + /** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ + template + int GeneratorPQ::evaluateResidual() + { + // std::cout << "Evaluating load residual ...\n"; + bus_->P() += P_; + bus_->Q() += Q_; + return 0; + } + + template + int GeneratorPQ::evaluateJacobian() + { + return 0; + } + + template + int GeneratorPQ::evaluateIntegrand() + { + return 0; + } + + template + int GeneratorPQ::initializeAdjoint() + { + return 0; + } + + template + int GeneratorPQ::evaluateAdjointResidual() + { + return 0; + } + + template + int GeneratorPQ::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class GeneratorPQ; + template class GeneratorPQ; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Generator/GeneratorPQ.hpp b/src/Model/PowerFlow/Generator/GeneratorPQ.hpp new file mode 100644 index 000000000..1561c61be --- /dev/null +++ b/src/Model/PowerFlow/Generator/GeneratorPQ.hpp @@ -0,0 +1,85 @@ + +#pragma once + +#include + +#include "GeneratorBase.hpp" +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Implementation of a PV generator. + * + */ + template + class GeneratorPQ : public GeneratorBase + { + using GeneratorBase::size_; + using GeneratorBase::nnz_; + using GeneratorBase::time_; + using GeneratorBase::alpha_; + using GeneratorBase::y_; + using GeneratorBase::yp_; + using GeneratorBase::tag_; + using GeneratorBase::f_; + using GeneratorBase::g_; + using GeneratorBase::yB_; + using GeneratorBase::ypB_; + using GeneratorBase::fB_; + using GeneratorBase::gB_; + using GeneratorBase::param_; + + using bus_type = BaseBus; + using real_type = typename ModelEvaluatorImpl::real_type; + using GenData = GridKit::PowerSystemData::GenData; + + public: + GeneratorPQ(bus_type* bus, GenData& data); + virtual ~GeneratorPQ(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + virtual ScalarT& P() + { + return P_; + } + + virtual const ScalarT& P() const + { + return P_; + } + + virtual ScalarT& Q() + { + return Q_; + } + + virtual const ScalarT& Q() const + { + return Q_; + } + + private: + ScalarT P_; + ScalarT Q_; + bus_type* bus_; + }; +} // namespace GridKit diff --git a/src/Model/PowerFlow/Generator/GeneratorPV.cpp b/src/Model/PowerFlow/Generator/GeneratorPV.cpp new file mode 100644 index 000000000..dfd7f48c0 --- /dev/null +++ b/src/Model/PowerFlow/Generator/GeneratorPV.cpp @@ -0,0 +1,109 @@ + +#include "GeneratorPV.hpp" + +#include +#include +#include + +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a constant load model + * + * Calls default ModelEvaluatorImpl constructor. + */ + + template + GeneratorPV::GeneratorPV(bus_type* bus, GenData& data) + : P_(data.Pg), + // Q_(data.Qg), + bus_(bus) + { + // std::cout << "Create a load model with " << size_ << " variables ...\n"; + size_ = 0; + } + + template + GeneratorPV::~GeneratorPV() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int GeneratorPV::allocate() + { + return 0; + } + + /** + * Initialization of the grid model + */ + template + int GeneratorPV::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int GeneratorPV::tagDifferentiable() + { + return 0; + } + + /** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ + template + int GeneratorPV::evaluateResidual() + { + // std::cout << "Evaluating load residual ...\n"; + bus_->P() += P_; + // bus_->Q() += Q_; + return 0; + } + + template + int GeneratorPV::evaluateJacobian() + { + return 0; + } + + template + int GeneratorPV::evaluateIntegrand() + { + return 0; + } + + template + int GeneratorPV::initializeAdjoint() + { + return 0; + } + + template + int GeneratorPV::evaluateAdjointResidual() + { + return 0; + } + + template + int GeneratorPV::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class GeneratorPV; + template class GeneratorPV; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Generator/GeneratorPV.hpp b/src/Model/PowerFlow/Generator/GeneratorPV.hpp new file mode 100644 index 000000000..7882114e1 --- /dev/null +++ b/src/Model/PowerFlow/Generator/GeneratorPV.hpp @@ -0,0 +1,88 @@ + +#pragma once + +#include + +#include "GeneratorBase.hpp" +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Implementation of a PV generator. + * + */ + template + class GeneratorPV : public GeneratorBase + { + using GeneratorBase::size_; + using GeneratorBase::nnz_; + using GeneratorBase::time_; + using GeneratorBase::alpha_; + using GeneratorBase::y_; + using GeneratorBase::yp_; + using GeneratorBase::tag_; + using GeneratorBase::f_; + using GeneratorBase::g_; + using GeneratorBase::yB_; + using GeneratorBase::ypB_; + using GeneratorBase::fB_; + using GeneratorBase::gB_; + using GeneratorBase::param_; + + using bus_type = BaseBus; + using real_type = typename ModelEvaluatorImpl::real_type; + using GenData = GridKit::PowerSystemData::GenData; + + public: + GeneratorPV(bus_type* bus, GenData& data); + virtual ~GeneratorPV(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + virtual ScalarT& P() + { + return P_; + } + + virtual const ScalarT& P() const + { + return P_; + } + + /// @brief Reactive power excess on PV bus + /// @return reference to negative PV generator reactive power + virtual ScalarT& Q() + { + return (bus_->Q()); + } + + /// @brief Reactive power excess on PV bus + /// @return const reference to negative PV generator reactive power + virtual const ScalarT& Q() const + { + return (bus_->Q()); + } + + private: + ScalarT P_; + bus_type* bus_; + }; +} // namespace GridKit diff --git a/src/Model/PowerFlow/Generator/GeneratorSlack.cpp b/src/Model/PowerFlow/Generator/GeneratorSlack.cpp new file mode 100644 index 000000000..ec1d588ac --- /dev/null +++ b/src/Model/PowerFlow/Generator/GeneratorSlack.cpp @@ -0,0 +1,107 @@ + +#include "GeneratorSlack.hpp" + +#include +#include +#include + +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a constant load model + * + * Calls default ModelEvaluatorImpl constructor. + */ + + template + GeneratorSlack::GeneratorSlack(bus_type* bus, GenData& data) + : bus_(bus) + { + // std::cout << "Create a load model with " << size_ << " variables ...\n"; + size_ = 0; + } + + template + GeneratorSlack::~GeneratorSlack() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int GeneratorSlack::allocate() + { + return 0; + } + + /** + * Initialization of the grid model + */ + template + int GeneratorSlack::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int GeneratorSlack::tagDifferentiable() + { + return 0; + } + + /** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ + template + int GeneratorSlack::evaluateResidual() + { + // std::cout << "Evaluating load residual ...\n"; + // bus_->P() += P_; + // bus_->Q() += Q_; + return 0; + } + + template + int GeneratorSlack::evaluateJacobian() + { + return 0; + } + + template + int GeneratorSlack::evaluateIntegrand() + { + return 0; + } + + template + int GeneratorSlack::initializeAdjoint() + { + return 0; + } + + template + int GeneratorSlack::evaluateAdjointResidual() + { + return 0; + } + + template + int GeneratorSlack::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class GeneratorSlack; + template class GeneratorSlack; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Generator/GeneratorSlack.hpp b/src/Model/PowerFlow/Generator/GeneratorSlack.hpp new file mode 100644 index 000000000..fa5b1beff --- /dev/null +++ b/src/Model/PowerFlow/Generator/GeneratorSlack.hpp @@ -0,0 +1,85 @@ + +#pragma once + +// #include +#include + +#include "GeneratorBase.hpp" +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Implementation of a power grid. + * + */ + template + class GeneratorSlack : public GeneratorBase + { + using GeneratorBase::size_; + using GeneratorBase::nnz_; + using GeneratorBase::time_; + using GeneratorBase::alpha_; + using GeneratorBase::y_; + using GeneratorBase::yp_; + using GeneratorBase::tag_; + using GeneratorBase::f_; + using GeneratorBase::g_; + using GeneratorBase::yB_; + using GeneratorBase::ypB_; + using GeneratorBase::fB_; + using GeneratorBase::gB_; + using GeneratorBase::param_; + + using bus_type = BaseBus; + using real_type = typename ModelEvaluatorImpl::real_type; + using GenData = GridKit::PowerSystemData::GenData; + // typedef typename ModelEvaluatorImpl::real_type real_type; + // typedef BaseBus bus_type; + + public: + GeneratorSlack(bus_type* bus, GenData& data); + virtual ~GeneratorSlack(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + virtual ScalarT& P() + { + return bus_->P(); + } + + virtual const ScalarT& P() const + { + return bus_->P(); + } + + virtual ScalarT& Q() + { + return bus_->Q(); + } + + virtual const ScalarT& Q() const + { + return bus_->Q(); + } + + private: + bus_type* bus_; + }; +} // namespace GridKit diff --git a/src/Model/PowerFlow/Generator2/CMakeLists.txt b/src/Model/PowerFlow/Generator2/CMakeLists.txt new file mode 100644 index 000000000..2ee1678be --- /dev/null +++ b/src/Model/PowerFlow/Generator2/CMakeLists.txt @@ -0,0 +1,10 @@ +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +gridkit_add_library(generator2 + SOURCES + Generator2.cpp + OUTPUT_NAME + gridkit_generator2) diff --git a/src/Model/PowerFlow/Generator2/Generator2.cpp b/src/Model/PowerFlow/Generator2/Generator2.cpp new file mode 100644 index 000000000..8a5c2d6cb --- /dev/null +++ b/src/Model/PowerFlow/Generator2/Generator2.cpp @@ -0,0 +1,174 @@ + +#include "Generator2.hpp" + +#include +#include + +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a simple generator model + * + * Arguments passed to ModelEvaluatorImpl: + * - Number of equations = 2 + * - Number of quadratures = 1 + * - Number of optimization parameters = 1 + */ + template + Generator2::Generator2(bus_type* bus) + : ModelEvaluatorImpl(2, 1, 1), + H_(5.0), + D_(0.005), + Pm_(0.7), + Xdp_(0.5), + Eqp_(0.93), + omega_s_(1.0), + omega_b_(2.0 * 60.0 * M_PI), + omega_up_(omega_s_ + 0.0002), + omega_lo_(omega_s_ - 0.0002), + theta_s_(1.0), + c_(10000.0), + beta_(2), + bus_(bus) + { + } + + template + Generator2::~Generator2() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int Generator2::allocate() + { + tag_.resize(size_); + return 0; + } + + template + int Generator2::tagDifferentiable() + { + tag_[0] = true; + tag_[1] = true; + return 0; + } + + template + int Generator2::initialize() + { + // Set optimization parameter value and bounds + param_[0] = Pm_; + param_up_[0] = 1.5; + param_lo_[0] = 0.5; + + y_[0] = asin((Pm_ * Xdp_) / (Eqp_ * V())) + theta(); // <~ asin(Pm/Pmax) + y_[1] = omega_s_; + yp_[0] = 0.0; + yp_[1] = 0.0; + + return 0; + } + + template + int Generator2::evaluateResidual() + { + f_[0] = -yp_[0] + omega_b_ * (y_[1] - omega_s_); + f_[1] = -yp_[1] + omega_s_ / (2.0 * H_) * (param_[0] - Eqp_ / Xdp_ * V() * sin(y_[0] - theta()) - D_ * (y_[1] - omega_s_)); + return 0; + } + + template + int Generator2::evaluateJacobian() + { + std::cout << "Evaluate Jacobian for Gen2..." << std::endl; + std::cout << "Jacobian evaluation not implemented!" << std::endl; + return 0; + } + + template + int Generator2::evaluateIntegrand() + { + g_[0] = frequencyPenalty(y_[1]); + return 0; + } + + template + int Generator2::initializeAdjoint() + { + yB_[0] = 0.0; + yB_[1] = 0.0; + ypB_[0] = 0.0; + ypB_[1] = frequencyPenaltyDer(y_[1]); + + return 0; + } + + template + int Generator2::evaluateAdjointResidual() + { + fB_[0] = -ypB_[0] + omega_s_ / (2.0 * H_) * Eqp_ / Xdp_ * V() * cos(y_[0] - theta()) * yB_[1]; + fB_[1] = -ypB_[1] + omega_s_ / (2.0 * H_) * D_ * yB_[1] - omega_b_ * yB_[0] + frequencyPenaltyDer(y_[1]); + return 0; + } + + // template + // int Generator2::evaluateAdjointJacobian() + // { + // std::cout << "Evaluate adjoint Jacobian for Gen2..." << std::endl; + // std::cout << "Adjoint Jacobian evaluation not implemented!" << std::endl; + // return 0; + // } + + template + int Generator2::evaluateAdjointIntegrand() + { + // std::cout << "Evaluate adjoint Integrand for Gen2..." << std::endl; + gB_[0] = -omega_s_ / (2.0 * H_) * yB_[1]; + return 0; + } + + // + // Private functions + // + + /** + * Frequency penalty is used as the objective function for the generator model. + */ + template + ScalarT Generator2::frequencyPenalty(ScalarT omega) + { + return c_ * pow(std::max(0.0, std::max(omega - omega_up_, omega_lo_ - omega)), beta_); + } + + /** + * Derivative of frequency penalty cannot be written in terms of min/max functions. + * Need to expand conditional statements instead. + */ + template + ScalarT Generator2::frequencyPenaltyDer(ScalarT omega) + { + if (omega > omega_up_) + { + return beta_ * c_ * pow(omega - omega_up_, beta_ - 1.0); + } + else if (omega < omega_lo_) + { + return beta_ * c_ * pow(omega - omega_lo_, beta_ - 1.0); + } + else + { + return 0.0; + } + } + + // Available template instantiations + template class Generator2; + template class Generator2; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Generator2/Generator2.hpp b/src/Model/PowerFlow/Generator2/Generator2.hpp new file mode 100644 index 000000000..1f6aed3b1 --- /dev/null +++ b/src/Model/PowerFlow/Generator2/Generator2.hpp @@ -0,0 +1,102 @@ + +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Implementation of a second order generator model. + * + */ + template + class Generator2 : public ModelEvaluatorImpl + { + 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 ModelEvaluatorImpl::param_up_; + using ModelEvaluatorImpl::param_lo_; + + typedef typename ModelEvaluatorImpl::real_type real_type; + typedef BaseBus bus_type; + + public: + Generator2(bus_type* bus); + virtual ~Generator2(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + void updateTime(real_type t, real_type a) + { + time_ = t; + alpha_ = a; + } + + const ScalarT& V() const + { + return bus_->V(); + } + + ScalarT& V() + { + return bus_->V(); + } + + const ScalarT& theta() const + { + return bus_->theta(); + } + + ScalarT& theta() + { + return bus_->theta(); + } + + private: + inline ScalarT frequencyPenalty(ScalarT omega); + inline ScalarT frequencyPenaltyDer(ScalarT omega); + + private: + real_type H_; + real_type D_; + real_type Pm_; + real_type Xdp_; + real_type Eqp_; + real_type omega_s_; + real_type omega_b_; + real_type omega_up_; + real_type omega_lo_; + real_type theta_s_; + real_type c_; + real_type beta_; + + bus_type* bus_; + }; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Generator4/CMakeLists.txt b/src/Model/PowerFlow/Generator4/CMakeLists.txt new file mode 100644 index 000000000..30c220813 --- /dev/null +++ b/src/Model/PowerFlow/Generator4/CMakeLists.txt @@ -0,0 +1,12 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +gridkit_add_library(generator4 + SOURCES + Generator4.cpp + OUTPUT_NAME + gridkit_generator4) diff --git a/src/Model/PowerFlow/Generator4/Generator4.cpp b/src/Model/PowerFlow/Generator4/Generator4.cpp new file mode 100644 index 000000000..a6dc68424 --- /dev/null +++ b/src/Model/PowerFlow/Generator4/Generator4.cpp @@ -0,0 +1,338 @@ + +#include "Generator4.hpp" + +#include +#include + +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a simple generator model + * + * Arguments passed to ModelEvaluatorImpl: + * - Number of equations = 4 differential + 2 algebraic = 6 + * - Number of quadratures = 1 + * - Number of optimization parameters = 2 + */ + template + Generator4::Generator4(bus_type* bus, ScalarT P0, ScalarT Q0) + : ModelEvaluatorImpl(6, 1, 2), + H_(5.0), + D_(0.04), + Xq_(0.85), + Xd_(1.05), + Xqp_(0.35), + Xdp_(0.35), + Rs_(0.01), + Tq0p_(1.0), // [s] + Td0p_(8.0), // [s] + Ef_(1.45), + Pm_(1.0), + omega_s_(1.0), + omega_b_(2.0 * 60.0 * M_PI), + omega_up_(omega_s_ + 0.0001), + omega_lo_(omega_s_ - 0.0001), + c_(10000.0), + beta_(2), + P0_(P0), + Q0_(Q0), + bus_(bus) + { + } + + template + Generator4::~Generator4() + { + } + + /*! + * @brief This function will be used to allocate sparse Jacobian matrices. + * + */ + template + int Generator4::allocate() + { + // std::cout << "Allocate Generator4..." << std::endl; + tag_.resize(size_); + + return 0; + } + + /** + * @brief Initialization of the generator model + * + * Initialization equations are derived from example 9.2 in Power System + * Modeling and Scripting, Federico Milano, Chapter 9, p. 225: + * \f{eqnarray*}{ + * &~& \omega_0 = 0, \\ + * &~& \delta_0 = \tan^{-1} \left(\frac{X_q P_0 - R_s Q_0}{V_0^2 + R_s P_0 + X_q Q_0} \right) + \theta_0, \\ + * &~& \phi_0 = \delta_0 - \theta_0 + \tan^{-1} \left( \frac{Q_0}{P_0} \right), \\ + * &~& I_{d0} = \frac{\sqrt{P_0^2 + Q_0^2}}{V_0} \sin(\phi_0), \\ + * &~& I_{q0} = \frac{\sqrt{P_0^2 + Q_0^2}}{V_0} \cos(\phi_0), \\ + * &~& E_{d0}' = V_0 \sin(\delta_0 - \theta_0) + R_s I_{d0} - X_q' I_{q0}, \\ + * &~& E_{q0}' = V_0 \cos(\delta_0 - \theta_0) + R_s I_{q0} + X_d' I_{d0} + * \f} + * + * The input from exciter and governor is set to the steady state value: + * \f{eqnarray*}{ + * &~& E_{f0} = E_{q0}' + (X_d - X_d') I_{d0}, \\ + * &~& P_{m0} = E_{d0}' I_{d0} + E_{q0}' I_{q0} + ( X_q' - X_d') I_{d0} I_{q0} + * \f} + * + */ + template + int Generator4::initialize() + { + // std::cout << "Initialize Generator4..." << std::endl; + + // Compute initial guess for the generator voltage phase + const ScalarT delta = atan((Xq_ * P0_ - Rs_ * Q0_) / (V() * V() + Rs_ * P0_ + Xq_ * Q0_)) + theta(); + + // Compute initial guess for the generator current phase + const ScalarT phi = theta() - delta - atan(Q0_ / P0_); + + // Compute initial gueses for generator currents and potentials in d-q frame + const ScalarT Id = std::sqrt(P0_ * P0_ + Q0_ * Q0_) / V() * sin(phi); + const ScalarT Iq = std::sqrt(P0_ * P0_ + Q0_ * Q0_) / V() * cos(phi); + const ScalarT Ed = V() * sin(theta() - delta) + Rs_ * Id + Xqp_ * Iq; + const ScalarT Eq = V() * cos(theta() - delta) + Rs_ * Iq - Xdp_ * Id; + + y_[0] = delta; + y_[1] = omega_s_; + y_[2] = Ed; + y_[3] = Eq; + y_[4] = Id; + y_[5] = Iq; + yp_[0] = 0.0; + yp_[1] = 0.0; + yp_[2] = 0.0; + yp_[3] = 0.0; + yp_[4] = 0.0; + yp_[5] = 0.0; + + // Set control parameter values here. + Ef_ = Eq - (Xd_ - Xdp_) * Id; // <~ set to steady state value + Pm_ = Ed * Id + Eq * Iq + (Xdp_ - Xqp_) * Id * Iq; // <~ set to steady state value + + // Initialize optimization parameters + param_[0] = Pm_; + param_up_[0] = 1.5; + param_lo_[0] = 0.0; + + param_[1] = Ef_; + param_up_[1] = 1.7; + param_lo_[1] = 0.0; + + return 0; + } + + /** + * \brief Identify differential variables. + */ + template + int Generator4::tagDifferentiable() + { + tag_[0] = true; + tag_[1] = true; + tag_[2] = true; + tag_[3] = true; + + for (IdxT i = 4; i < size_; ++i) + { + tag_[i] = false; + } + + return 0; + } + + /** + * @brief Computes residual vector for the generator model. + * + * Residual equations are given per model in Power System Modeling and + * Scripting, Federico Milano, Chapter 15, p. 334: + * \f{eqnarray*}{ + * f_0: &~& \dot{\delta} -\omega_b (\omega - \omega_s), \\ + * f_1: &~& 2H/\omega_s \dot{\omega} - L_m(P_m) + E_q' I_q + E_d' I_d + (X_q' - X_d')I_d I_q + D (\omega - \omega_s), \\ + * f_2: &~& T_{q0}' \dot{E}_d' + E_d' - (X_q - X_q')I_q, \\ + * f_3: &~& T_{d0}' \dot{E}_q' + E_q' + (X_d - X_d')I_d - E_f, \\ + * f_4: &~& R_s I_d - X_q' I_q + V \sin(\delta - \theta) - E_d', \\ + * f_5: &~& R_s I_q + X_d' I_d + V \cos(\delta - \theta) - E_q', + * \f} + * where \f$ \Omega_b \f$ is the synchronous frequency in [rad/s], and + * overdot denotes time derivative. + * + * Generator injection active and reactive power are + * \f{eqnarray*}{ + * P_g &=& E_d' I_d + E_q' I_q + (X_q' - X_d') I_d I_q - R_s (I_d^2 + I_q^2), \\ + * Q_q &=& E_q' I_d - E_d' I_q - X_q' I_q^2 - X_d' I_d^2, \\ + * \f} + * respectively. + * + * State variables are: + * \f$ y_0 = \omega \f$, \f$ y_1 = \delta \f$, \f$ y_2 = E_d' \f$, \f$ y_3 = E_q' \f$, + * \f$ y_4 = I_d \f$, \f$ y_5 = I_q \f$. + * + */ + template + int Generator4::evaluateResidual() + { + // std::cout << "Evaluate residual for Generator4..." << std::endl; + f_[0] = dotDelta() - omega_b_ * (omega() - omega_s_); + f_[1] = (2.0 * H_) / omega_s_ * dotOmega() - Pm() + Eqp() * Iq() + Edp() * Id() + (-Xdp_ + Xqp_) * Id() * Iq() + D_ * (omega() - omega_s_); + f_[2] = Tq0p_ * dotEdp() + Edp() - (Xq_ - Xqp_) * Iq(); + f_[3] = Td0p_ * dotEqp() + Eqp() + (Xd_ - Xdp_) * Id() - Ef(); + f_[4] = Rs_ * Id() - Xqp_ * Iq() + V() * sin(delta() - theta()) - Edp(); + f_[5] = Xdp_ * Id() + Rs_ * Iq() + V() * cos(delta() - theta()) - Eqp(); + + // Compute active and reactive load provided by the infinite bus. + P() += Pg(); + Q() += Qg(); + + return 0; + } + + template + int Generator4::evaluateJacobian() + { + std::cerr << "Evaluate Jacobian for Generator4..." << std::endl; + std::cerr << "Jacobian evaluation not implemented!" << std::endl; + return 0; + } + + template + int Generator4::evaluateIntegrand() + { + // std::cout << "Evaluate Integrand for Generator4..." << std::endl; + g_[0] = frequencyPenalty(y_[1]); + return 0; + } + + template + int Generator4::initializeAdjoint() + { + // std::cout << "Initialize adjoint for Generator4..." << std::endl; + for (IdxT i = 0; i < size_; ++i) + { + yB_[i] = 0.0; + ypB_[i] = 0.0; + } + ypB_[1] = frequencyPenaltyDer(y_[1]); + + return 0; + } + + /** + * @brief Computes adjoint residual vector for the generator model. + * + * Adjoint residual equations are given as: + * \f{eqnarray*}{ + * f_{B0}: &~& \dot{y}_{B0} - y_{B4} V \cos(\delta - \theta) + y_{B5} V \sin(\delta - \theta), \\ + * f_{B1}: &~& 2H/\omega_s \dot{y}_{B1} + y_{B0} \omega_b - y_{B1} D + y_{B9} (1 - T_2/T_1) - y_{B10} K T_2/T_1 + g_{\omega}(\omega), \\ + * f_{B2}: &~& T_{q0}' \dot{y}_{B2} - y_{B1} I_d - y_{B2} + y_{B4} + y_{B6} I_d - y_{B7} I_q, \\ + * f_{B3}: &~& T_{d0}' \dot{y}_{B3} - y_{B1} I_q - y_{B3} + y_{B5} + y_{B6} I_q + y_{B7} I_d, \\ + * f_{B4}: &~& -y_{B1} (E_d' + (-X_d'+X_q') I_q) - y_{B3} (X_d - X_d') - y_{B4} R_s - y_{B5} X_d' + y_{B6} (E_d' + (X_q' - X_d') I_q - 2 R_s I_d) + y_{B7} (E_q' - 2 X_d' I_d), \\ + * f_{B5}: &~& -y_{B1} (E_q' + (-X_d'+X_q') I_d) + y_{B2} (X_q - X_q') + y_{B4} X_q' - y_{B5} R_s + y_{B6} (E_q' + (X_q' - X_d') I_d - 2 R_s I_q) - y_{B7} (E_d' + 2 X_q' I_q). \\ + * \f} + * + */ + template + int Generator4::evaluateAdjointResidual() + { + // std::cout << "Evaluate adjoint residual for Generator4..." << std::endl; + ScalarT sinPhi = sin(delta() - theta()); + ScalarT cosPhi = cos(delta() - theta()); + + // Generator adjoint + fB_[0] = ypB_[0] - yB_[4] * V() * cosPhi + yB_[5] * V() * sinPhi; + fB_[1] = 2.0 * H_ / omega_s_ * ypB_[1] + yB_[0] * omega_b_ - yB_[1] * D_ + frequencyPenaltyDer(omega()); + fB_[2] = Tq0p_ * ypB_[2] - yB_[1] * Id() - yB_[2] + yB_[4]; + fB_[3] = Td0p_ * ypB_[3] - yB_[1] * Iq() - yB_[3] + yB_[5]; + fB_[4] = -yB_[1] * (Edp() + (Xqp_ - Xdp_) * Iq()) - yB_[3] * (Xd_ - Xdp_) - yB_[4] * Rs_ - yB_[5] * Xdp_; + fB_[5] = -yB_[1] * (Eqp() + (Xqp_ - Xdp_) * Id()) + yB_[2] * (Xq_ - Xqp_) + yB_[4] * Xqp_ - yB_[5] * Rs_; + + return 0; + } + + // template + // int Generator4::evaluateAdjointJacobian() + // { + // std::cout << "Evaluate adjoint Jacobian for Generator4..." << std::endl; + // std::cout << "Adjoint Jacobian evaluation not implemented!" << std::endl; + // return 0; + // } + + template + int Generator4::evaluateAdjointIntegrand() + { + // std::cout << "Evaluate adjoint Integrand for Generator4..." << std::endl; + gB_[0] = yB_[1]; + gB_[1] = yB_[3]; + + return 0; + } + + // + // Private functions + // + + /** + * Generator active power Pg. + * + * \f[ P_g = E_q' I_q + E_d' I_d + (X_q' - X_d') I_q I_d - R_a (I_d^2 + I_q^2) \f] + * + */ + template + ScalarT Generator4::Pg() + { + return y_[5] * V() * cos(theta() - y_[0]) + y_[4] * V() * sin(theta() - y_[0]); + } + + /** + * Generator reactive power Qg. + * + * \f[ Q_g = E_q' I_d - E_d' I_q - X_d' I_d^2 - X_q' I_q^2 \f] + */ + template + ScalarT Generator4::Qg() + { + return y_[5] * V() * sin(theta() - y_[0]) - y_[4] * V() * cos(theta() - y_[0]); + } + + /** + * Frequency penalty is used as the objective function for the generator model. + */ + template + ScalarT Generator4::frequencyPenalty(ScalarT omega) + { + return c_ * pow(std::max(0.0, std::max(omega - omega_up_, omega_lo_ - omega)), beta_); + } + + /** + * Derivative of frequency penalty cannot be written in terms of min/max functions. + * Need to expand conditional statements instead. + */ + template + ScalarT Generator4::frequencyPenaltyDer(ScalarT omega) + { + if (omega > omega_up_) + { + return beta_ * c_ * pow(omega - omega_up_, beta_ - 1.0); + } + else if (omega < omega_lo_) + { + return beta_ * c_ * pow(omega - omega_lo_, beta_ - 1.0); + } + else + { + return 0.0; + } + } + + // Available template instantiations + template class Generator4; + template class Generator4; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Generator4/Generator4.hpp b/src/Model/PowerFlow/Generator4/Generator4.hpp new file mode 100644 index 000000000..2b534fb97 --- /dev/null +++ b/src/Model/PowerFlow/Generator4/Generator4.hpp @@ -0,0 +1,203 @@ + +#ifndef _GENERATOR_4_H_ +#define _GENERATOR_4_H_ + +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Implementation of a fourth order generator model. + * + */ + template + class Generator4 : public ModelEvaluatorImpl + { + 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 ModelEvaluatorImpl::param_up_; + using ModelEvaluatorImpl::param_lo_; + + typedef typename ModelEvaluatorImpl::real_type real_type; + typedef BaseBus bus_type; + + public: + Generator4(BaseBus* bus, ScalarT P0 = 1.0, ScalarT Q0 = 0.0); + virtual ~Generator4(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + void updateTime(real_type t, real_type a) + { + time_ = t; + alpha_ = a; + } + + // Inline accesor functions + ScalarT& V() + { + return bus_->V(); + } + + const ScalarT& V() const + { + return bus_->V(); + } + + ScalarT& theta() + { + return bus_->theta(); + } + + const ScalarT& theta() const + { + return bus_->theta(); + } + + ScalarT& P() + { + return bus_->P(); + } + + const ScalarT& P() const + { + return bus_->P(); + } + + ScalarT& Q() + { + return bus_->Q(); + } + + const ScalarT& Q() const + { + return bus_->Q(); + } + + private: + const ScalarT& Pm() const + { + return param_[0]; + } + + const ScalarT& Ef() const + { + return param_[1]; + } + + ScalarT Pg(); + ScalarT Qg(); + ScalarT frequencyPenalty(ScalarT omega); + ScalarT frequencyPenaltyDer(ScalarT omega); + + private: + // + // Private inlined accessor methods + // + + const ScalarT dotDelta() const + { + return yp_[0]; + } + + const ScalarT dotOmega() const + { + return yp_[1]; + } + + const ScalarT dotEdp() const + { + return yp_[2]; + } + + const ScalarT dotEqp() const + { + return yp_[3]; + } + + const ScalarT delta() const + { + return y_[0]; + } + + const ScalarT omega() const + { + return y_[1]; + } + + const ScalarT Edp() const + { + return y_[2]; + } + + const ScalarT Eqp() const + { + return y_[3]; + } + + const ScalarT Id() const + { + return y_[4]; + } + + const ScalarT Iq() const + { + return y_[5]; + } + + private: + real_type H_; ///< Inertia constant [s] + real_type D_; ///< Damping constant [pu] + real_type Xq_; ///< q-axis synchronous reactance [pu] + real_type Xd_; ///< d-axis synchronous reactance [pu] + real_type Xqp_; ///< q-axis transient reactance [pu] + real_type Xdp_; ///< d-axis transient reactance [pu] + real_type Rs_; ///< stator armature resistance [pu] + real_type Tq0p_; ///< q-axis open circuit transient time constant [s] + real_type Td0p_; ///< d-axis open circuit transient time constant [s] + real_type Ef_; + real_type Pm_; + real_type omega_s_; + real_type omega_b_; + real_type omega_up_; + real_type omega_lo_; + real_type c_; + real_type beta_; + + ScalarT P0_; + ScalarT Q0_; + + bus_type* bus_; + }; + +} // namespace GridKit + +#endif // _GENERATOR_4_H_ diff --git a/src/Model/PowerFlow/Generator4Governor/CMakeLists.txt b/src/Model/PowerFlow/Generator4Governor/CMakeLists.txt new file mode 100644 index 000000000..80c3aadd7 --- /dev/null +++ b/src/Model/PowerFlow/Generator4Governor/CMakeLists.txt @@ -0,0 +1,12 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +gridkit_add_library(generator4governor + SOURCES + Generator4Governor.cpp + OUTPUT_NAME + gridkit_generator4governor) diff --git a/src/Model/PowerFlow/Generator4Governor/Generator4Governor.cpp b/src/Model/PowerFlow/Generator4Governor/Generator4Governor.cpp new file mode 100644 index 000000000..47c73be8d --- /dev/null +++ b/src/Model/PowerFlow/Generator4Governor/Generator4Governor.cpp @@ -0,0 +1,435 @@ + +#include "Generator4Governor.hpp" + +#include +#include + +#include "Model/PowerFlow/Bus/BaseBus.hpp" + +namespace GridKit +{ + + /*! + * @brief Constructor for a model of generator with governor + * + * Arguments passed to ModelEvaluatorImpl: + * - Number of equations = 6 differential + 3 algebraic = 9 + * - Number of quadratures = 1 + * - Number of optimization parameters = 2 + * + */ + template + Generator4Governor::Generator4Governor(bus_type* bus, ScalarT P0, ScalarT Q0) + : ModelEvaluatorImpl(9, 1, 2), + H_(5.0), + D_(0.04), + Xq_(0.85), + Xd_(1.05), + Xqp_(0.35), + Xdp_(0.35), + Rs_(0.01), + Tq0p_(1.0), // [s] + Td0p_(8.0), // [s] + Ef0_(1.45), + Pm0_(1.0), + deltaPm_(0.5), // 0.5 + deltaPn_(1.0), // 1.0 + omega_s_(1.0), + omega_b_(2.0 * 60.0 * M_PI), // [rad/s] + omega_up_(omega_s_ + 0.0001), + omega_lo_(omega_s_ - 0.0001), + c_(10000.0), + beta_(2), + T1_(0.1), + T2_(0.15), + T3_(0.05), + K_(16.67), + offsetGen_(0), + offsetGov_(6), + P0_(P0), + Q0_(Q0), + bus_(bus) + { + } + + template + Generator4Governor::~Generator4Governor() + { + // std::cout << "Destroy Gen2..." << std::endl; + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int Generator4Governor::allocate() + { + // std::cout << "Allocate Gen2..." << std::endl; + tag_.resize(size_); + + return 0; + } + + /** + * @brief Initialization of the generator model + * + * Initialization equations are derived from example 9.2 in Power System + * Modeling and Scripting, Federico Milano, Chapter 9, p. 225: + * \f{eqnarray*}{ + * \omega_0 &=& 0, \\ + * \delta_0 &=& \tan^{-1} \left(\frac{X_q P_0 - R_s Q_0}{V_0^2 + R_s P_0 + X_q Q_0} \right) + \theta_0, \\ + * \phi_0 &=& \delta_0 - \theta_0 + \tan^{-1} \left( \frac{Q_0}{P_0} \right), \\ + * I_{d0} &=& \frac{\sqrt{P_0^2 + Q_0^2}}{V_0} \sin(\phi_0), \\ + * I_{q0} &=& \frac{\sqrt{P_0^2 + Q_0^2}}{V_0} \cos(\phi_0), \\ + * E_{d0}' &=& V_0 \sin(\delta_0 - \theta_0) + R_s I_{d0} - X_q' I_{q0}, \\ + * E_{q0}' &=& V_0 \cos(\delta_0 - \theta_0) + R_s I_{q0} + X_d' I_{d0} + * \f} + * + * The input from exciter and governor is set to the steady state value: + * \f{eqnarray*}{ + * E_{f0} &=& E_{q0}' + (X_d - X_d') I_{d0}, \\ + * P_{m0} &=& E_{d0}' I_{d0} + E_{q0}' I_{q0} + ( X_q' - X_d') I_{d0} I_{q0} + * \f} + * + */ + template + int Generator4Governor::initialize() + { + // std::cout << "Initialize Generator4Governor..." << std::endl; + + // Compute generator voltage phase + const ScalarT delta = atan((Xq_ * P0_ - Rs_ * Q0_) / (V() * V() + Rs_ * P0_ + Xq_ * Q0_)) + theta(); + + // Compute generator current phase + const ScalarT phi = delta - theta() + atan(Q0_ / P0_); + + // Compute generator currents and potentials in d-q frame + const ScalarT Id = std::sqrt(P0_ * P0_ + Q0_ * Q0_) / V() * sin(phi); + const ScalarT Iq = std::sqrt(P0_ * P0_ + Q0_ * Q0_) / V() * cos(phi); + const ScalarT Edp = V() * sin(delta - theta()) + Rs_ * Id - Xqp_ * Iq; + const ScalarT Eqp = V() * cos(delta - theta()) + Rs_ * Iq + Xdp_ * Id; + + // Initialize generator + y_[offsetGen_ + 0] = delta; + y_[offsetGen_ + 1] = omega_s_ + 0.2; // <~ this is hack to perturb omega + y_[offsetGen_ + 2] = Edp; + y_[offsetGen_ + 3] = Eqp; + y_[offsetGen_ + 4] = Id; + y_[offsetGen_ + 5] = Iq; + yp_[offsetGen_ + 0] = 0.0; + yp_[offsetGen_ + 1] = 0.0; + yp_[offsetGen_ + 2] = 0.0; + yp_[offsetGen_ + 3] = 0.0; + yp_[offsetGen_ + 4] = 0.0; + yp_[offsetGen_ + 5] = 0.0; + + Pm0_ = Edp * Id + Eqp * Iq + (Xqp_ - Xdp_) * Id * Iq; // <~ set to steady state value + Ef0_ = Eqp + (Xd_ - Xdp_) * Id; // <~ set to steady state value + + // Initialize governor + y_[offsetGov_ + 0] = Pm0_; + y_[offsetGov_ + 1] = 0.0; + y_[offsetGov_ + 2] = 0.0; + yp_[offsetGov_ + 0] = 0.0; + yp_[offsetGov_ + 1] = 0.0; + yp_[offsetGov_ + 2] = 0.0; + + param_[1] = K_; + param_up_[1] = 20.0; + param_lo_[1] = 0.0; + + param_[0] = T2_; + param_up_[0] = 5.5; + param_lo_[0] = 0.1; + + return 0; + } + + /** + * \brief Identify differential variables. + */ + template + int Generator4Governor::tagDifferentiable() + { + // std::cout << "size of tag vector is " << tag_.size() << "\n"; + tag_[offsetGen_ + 0] = true; + tag_[offsetGen_ + 1] = true; + tag_[offsetGen_ + 2] = true; + tag_[offsetGen_ + 3] = true; + tag_[offsetGen_ + 4] = false; + tag_[offsetGen_ + 5] = false; + + tag_[offsetGov_ + 0] = true; + tag_[offsetGov_ + 1] = true; + tag_[offsetGov_ + 2] = false; + + return 0; + } + + /** + * @brief Computes residual vector for the generator model. + * + * Residual equations are given as: + * \f{eqnarray*}{ + * f_0: &~& \dot{\delta} -\omega_b (\omega - \omega_s), \\ + * f_1: &~& 2H/\omega_s \dot{\omega} - L_m(P_m) + E_q' I_q + E_d' I_d + (X_q' - X_d')I_d I_q + D (\omega - \omega_s), \\ + * f_2: &~& T_{q0}' \dot{E}_d' + E_d' - (X_q - X_q')I_q, \\ + * f_3: &~& T_{d0}' \dot{E}_q' + E_q' + (X_d - X_d')I_d - E_f, \\ + * f_4: &~& R_s I_d - X_q' I_q + V \sin(\delta - \theta) - E_d', \\ + * f_5: &~& R_s I_q + X_d' I_d + V \cos(\delta - \theta) - E_q', \\ + * f_6: &~& \dot{P}_m - L_n(P_n), \\ + * f_7: &~& T_1 \dot{X} + X - (1 - T_2 / T_1) (\omega - \omega_s), \\ + * f_8: &~& T_3 P_n - P_{m0} + L_m(P_m) + K X + K T_2 / T_1 (\omega - \omega_s) + * \f} + * where \f$ \Omega_b \f$ is the synchronous frequency in [rad/s], and + * overdot denotes time derivative. + * \f$ \omega \f$ is machine frequency in [p.u.]. + * \f$ L_m() \f$ and \f$ L_n() \f$ are limiter functions, their derivatives will be + * denoted as \f$ dL_m() \f$ and \f$ dL_n() \f$ + * + * Generator injection active and reactive power are + * \f{eqnarray*}{ + * P_g &=& E_d' I_d + E_q' I_q + (X_q' - X_d') I_d I_q - R_s (I_d^2 + I_q^2), \\ + * Q_g &=& E_q' I_d - E_d' I_q - X_q' I_q^2 - X_d' I_d^2, \\ + * \f} + * respectively. + * + * State variables for the generator are: + * \f$ y_0 = \omega \f$, \f$ y_1 = \delta \f$, \f$ y_2 = E_d' \f$, \f$ y_3 = E_q' \f$, + * \f$ y_4 = I_d \f$, \f$ y_5 = I_q \f$, + * \f$ y_6 = P_m \f$, \f$ y_7 = X \f$, \f$ y_{8} = P_n \f$ + * Bus voltage \f$ V \f$ and bus phase \f$ \theta \f$ are bus state variable. + * + */ + + template + int Generator4Governor::evaluateResidual() + { + // Generator equations + f_[offsetGen_ + 0] = dotDelta() - omega_b_ * (omega() - omega_s_); + f_[offsetGen_ + 1] = (2.0 * H_) / omega_s_ * dotOmega() - Lm(y_[offsetGov_ + 0]) + Eqp() * Iq() + Edp() * Id() + (-Xdp_ + Xqp_) * Id() * Iq() + D_ * (omega() - omega_s_); + f_[offsetGen_ + 2] = Tq0p_ * dotEdp() + Edp() - (Xq_ - Xqp_) * Iq(); + f_[offsetGen_ + 3] = Td0p_ * dotEqp() + Eqp() + (Xd_ - Xdp_) * Id() - Ef0_; + f_[offsetGen_ + 4] = Rs_ * Id() - Xqp_ * Iq() + V() * sin(delta() - theta()) - Edp(); + f_[offsetGen_ + 5] = Xdp_ * Id() + Rs_ * Iq() + V() * cos(delta() - theta()) - Eqp(); + + // Bus equations + P() += Pg(); + Q() += Qg(); + + // Governor equations + f_[offsetGov_ + 0] = yp_[offsetGov_ + 0] - Ln(y_[offsetGov_ + 2]); + f_[offsetGov_ + 1] = T1() * yp_[offsetGov_ + 1] + y_[offsetGov_ + 1] - (1.0 - T2() / T1()) * (omega() - omega_s_); + f_[offsetGov_ + 2] = T3() * y_[offsetGov_ + 2] - Pm0_ + Lm(y_[offsetGov_ + 0]) + K() * y_[offsetGov_ + 1] + K() * T2() / T1() * (omega() - omega_s_); + + return 0; + } + + /* + * @brief Jacobian for the order 4 generator model (not implemented yet). + * + * + */ + template + int Generator4Governor::evaluateJacobian() + { + std::cout << "Evaluate Jacobian for Gen2..." << std::endl; + std::cout << "Jacobian evaluation not implemented!" << std::endl; + return 0; + } + + template + int Generator4Governor::evaluateIntegrand() + { + // std::cout << "Evaluate Integrand for Gen2..." << std::endl; + g_[0] = frequencyPenalty(omega()); + return 0; + } + + template + int Generator4Governor::initializeAdjoint() + { + // std::cout << "Initialize adjoint for Generator4Governor..." << std::endl; + for (IdxT i = 0; i < size_; ++i) + { + yB_[i] = 0.0; + ypB_[i] = 0.0; + } + ypB_[offsetGen_ + 1] = frequencyPenaltyDer(omega()); + + return 0; + } + + /** + * @brief Computes adjoint residual vector for the generator model. + * + * Adjoint residual equations are given as: + * \f{eqnarray*}{ + * f_{B0}: &~& \dot{y}_{B0} - y_{B4} V \cos(\delta - \theta) + y_{B5} V \sin(\delta - \theta), \\ + * f_{B1}: &~& 2H/\omega_s \dot{y}_{B1} + y_{B0} \omega_b - y_{B1} D + y_{B7} (1 - T_2/T_1) - y_{B8} K T_2/T_1 + g_{\omega}(\omega), \\ + * f_{B2}: &~& T_{q0}' \dot{y}_{B2} - y_{B1} I_d - y_{B2} + y_{B4} + \lambda_P I_d - \lambda_Q I_q, \\ + * f_{B3}: &~& T_{d0}' \dot{y}_{B3} - y_{B1} I_q - y_{B3} + y_{B5} + \lambda_P I_q + \lambda_Q I_d, \\ + * f_{B4}: &~& -y_{B1} (E_d' + (-X_d'+X_q') I_q) - y_{B3} (X_d - X_d') - y_{B4} R_s - y_{B5} X_d' + * + \lambda_P (E_d' + (X_q' - X_d') I_q - 2 R_s I_d) + \lambda_Q (E_q' - 2 X_d' I_d), \\ + * f_{B5}: &~& -y_{B1} (E_q' + (-X_d'+X_q') I_d) + y_{B2} (X_q - X_q') + y_{B4} X_q' - y_{B5} R_s + * + \lambda_P (E_q' + (X_q' - X_d') I_d - 2 R_s I_q) - \lambda_Q (E_d' + 2 X_q' I_q), \\ + * f_{B6}: &~& \dot{y}_{B6} + y_{B1} dL_m(P_m) - y_{B10} dL_m(P_m), \\ + * f_{B7}: &~& T_1 \dot{y}_{B7} - y_{B7} - y_{B8} K, \\ + * f_{B8}: &~& y_{B6} dL_n(P_n) - y_{B8} T_3 + * \f} + * + * Generator adjoint injections are + * \f{eqnarray*}{ + * P_g &=& -\lambda_P \sin(\delta - \theta) - \lambda_Q \cos(\delta - \theta), \\ + * Q_g &=& \lambda_P V \cos(\delta - \theta) - \lambda_Q V \sin(\delta - \theta), \\ + * \f} + * respectively. + * + * + */ + template + int Generator4Governor::evaluateAdjointResidual() + { + // std::cout << "Evaluate adjoint residual for Gen2..." << std::endl; + ScalarT sinPhi = sin(delta() - theta()); + ScalarT cosPhi = cos(delta() - theta()); + + // Generator adjoint + fB_[offsetGen_ + 0] = ypB_[offsetGen_ + 0] - yB_[offsetGen_ + 4] * V() * cosPhi + yB_[offsetGen_ + 5] * V() * sinPhi; + fB_[offsetGen_ + 1] = 2.0 * H_ / omega_s_ * ypB_[offsetGen_ + 1] + yB_[offsetGen_ + 0] * omega_b_ - yB_[offsetGen_ + 1] * D_ + frequencyPenaltyDer(omega()) + + yB_[offsetGov_ + 1] * (1.0 - T2() / T1()) - yB_[offsetGov_ + 2] * K() * T2() / T1(); + fB_[offsetGen_ + 2] = Tq0p_ * ypB_[offsetGen_ + 2] - yB_[offsetGen_ + 1] * Id() - yB_[offsetGen_ + 2] + yB_[offsetGen_ + 4] + + lambdaP() * Id() - lambdaQ() * Iq(); + fB_[offsetGen_ + 3] = Td0p_ * ypB_[offsetGen_ + 3] - yB_[offsetGen_ + 1] * Iq() - yB_[offsetGen_ + 3] + yB_[offsetGen_ + 5] + + lambdaP() * Iq() + lambdaQ() * Id(); + fB_[offsetGen_ + 4] = -yB_[offsetGen_ + 1] * (Edp() + (Xqp_ - Xdp_) * Iq()) - yB_[offsetGen_ + 3] * (Xd_ - Xdp_) - yB_[offsetGen_ + 4] * Rs_ - yB_[offsetGen_ + 5] * Xdp_ + + lambdaP() * (Edp() + (Xqp_ - Xdp_) * Iq() - 2.0 * Rs_ * Id()) + lambdaQ() * (Eqp() - 2.0 * Xdp_ * Id()); + fB_[offsetGen_ + 5] = -yB_[offsetGen_ + 1] * (Eqp() + (Xqp_ - Xdp_) * Id()) + yB_[offsetGen_ + 2] * (Xq_ - Xqp_) + yB_[offsetGen_ + 4] * Xqp_ - yB_[offsetGen_ + 5] * Rs_ + + lambdaP() * (Eqp() + (Xqp_ - Xdp_) * Id() - 2.0 * Rs_ * Iq()) - lambdaQ() * (Edp() + 2.0 * Xqp_ * Iq()); + + // Bus adjoint + PB() += (-yB_[offsetGen_ + 4] * sinPhi - yB_[offsetGen_ + 5] * cosPhi); + QB() += (yB_[offsetGen_ + 4] * V() * cosPhi - yB_[offsetGen_ + 5] * V() * sinPhi); + + // Governor adjoint + fB_[offsetGov_ + 0] = ypB_[offsetGov_ + 0] - yB_[offsetGov_ + 2] * dLm(y_[offsetGov_ + 0]) + yB_[offsetGen_ + 1] * dLm(y_[offsetGov_ + 0]); + fB_[offsetGov_ + 1] = ypB_[offsetGov_ + 1] * T1() - yB_[offsetGov_ + 1] - yB_[offsetGov_ + 2] * K(); + fB_[offsetGov_ + 2] = yB_[offsetGov_ + 0] * dLn(y_[offsetGov_ + 2]) - yB_[offsetGov_ + 2] * T3(); + + return 0; + } + + // template + // int Generator4Governor::evaluateAdjointJacobian() + // { + // std::cout << "Evaluate adjoint Jacobian for Gen2..." << std::endl; + // std::cout << "Adjoint Jacobian evaluation not implemented!" << std::endl; + // return 0; + // } + + template + int Generator4Governor::evaluateAdjointIntegrand() + { + // std::cout << "Evaluate adjoint Integrand for Gen2..." << std::endl; + + // K adjoint + gB_[1] = -yB_[offsetGov_ + 2] * (y_[offsetGov_ + 1] + T2() / T1() * (omega() - omega_s_)); + + // T2 adjoint + gB_[0] = -yB_[offsetGov_ + 1] * (omega() - omega_s_) / T1() - yB_[offsetGov_ + 2] * K() / T1() * (omega() - omega_s_); + + return 0; + } + + // + // Private functions + // + + /** + * Generator active power Pg. + * + * \f[ P_g = E_q' I_q + E_d' I_d + (X_q' - X_d') I_q I_d - R_a (I_d^2 + I_q^2) \f] + * + */ + template + ScalarT Generator4Governor::Pg() + { + return Iq() * Eqp() + Id() * Edp() + (Xqp_ - Xdp_) * Id() * Iq() - Rs_ * (Id() * Id() + Iq() * Iq()); + } + + /** + * Generator reactive power Qg. + * + * \f[ Q_g = E_q' I_d - E_d' I_q - X_d' I_d^2 - X_q' I_q^2 \f] + */ + template + ScalarT Generator4Governor::Qg() + { + return -Iq() * Edp() + Id() * Eqp() - Xdp_ * Id() * Id() - Xqp_ * Iq() * Iq(); + } + + /** + * Frequency penalty is used as the objective function for the generator model. + * + * @todo Use smooth penalty function! + * + */ + template + ScalarT Generator4Governor::frequencyPenalty(ScalarT omega) + { + return c_ * pow(std::max(0.0, std::max(omega - omega_up_, omega_lo_ - omega)), beta_); + } + + /** + * Derivative of frequency penalty cannot be written in terms of min/max functions. + * Need to expand conditional statements instead. + * + * @todo Use smooth penalty function! + * + */ + template + ScalarT Generator4Governor::frequencyPenaltyDer(ScalarT omega) + { + if (omega > omega_up_) + { + return beta_ * c_ * pow(omega - omega_up_, beta_ - 1.0); + } + else if (omega < omega_lo_) + { + return beta_ * c_ * pow(omega - omega_lo_, beta_ - 1.0); + } + else + { + return 0.0; + } + } + + template + ScalarT Generator4Governor::Lm(ScalarT Pm) + { + return Pm0_ + deltaPm_ * std::tanh(Pm); + } + + template + ScalarT Generator4Governor::dLm(ScalarT Pm) + { + return deltaPm_ / (std::cosh(Pm) * std::cosh(Pm)); + } + + template + ScalarT Generator4Governor::Ln(ScalarT Pn) + { + return deltaPn_ * std::tanh(Pn); + } + + template + ScalarT Generator4Governor::dLn(ScalarT Pn) + { + return deltaPn_ / (std::cosh(Pn) * std::cosh(Pn)); + } + + // Available template instantiations + template class Generator4Governor; + template class Generator4Governor; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Generator4Governor/Generator4Governor.hpp b/src/Model/PowerFlow/Generator4Governor/Generator4Governor.hpp new file mode 100644 index 000000000..948f6f67b --- /dev/null +++ b/src/Model/PowerFlow/Generator4Governor/Generator4Governor.hpp @@ -0,0 +1,264 @@ + +#ifndef _GENERATOR_4_GOVERNOR_B_HPP_ +#define _GENERATOR_4_GOVERNOR_B_HPP_ + +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Implementation of a fourth order generator model with + * a simple governor. + * + */ + template + class Generator4Governor : public ModelEvaluatorImpl + { + 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 ModelEvaluatorImpl::param_up_; + using ModelEvaluatorImpl::param_lo_; + + public: + typedef typename ModelEvaluatorImpl::real_type real_type; + typedef BaseBus bus_type; + + Generator4Governor(bus_type* bus, ScalarT P0, ScalarT Q0); + virtual ~Generator4Governor(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + void updateTime(real_type t, real_type a) + { + time_ = t; + alpha_ = a; + } + + private: + // + // Private model methods + // + + ScalarT Pg(); + ScalarT Qg(); + + inline ScalarT frequencyPenalty(ScalarT omega); + inline ScalarT frequencyPenaltyDer(ScalarT omega); + + inline ScalarT Lm(ScalarT Pm); + inline ScalarT dLm(ScalarT Pm); + + inline ScalarT Ln(ScalarT Pn); + inline ScalarT dLn(ScalarT Pn); + + public: + // + // Public inline accesor functions + // + + ScalarT& V() + { + return bus_->V(); + } + + const ScalarT& V() const + { + return bus_->V(); + } + + ScalarT& theta() + { + return bus_->theta(); + } + + const ScalarT& theta() const + { + return bus_->theta(); + } + + ScalarT& P() + { + return bus_->P(); + } + + const ScalarT& P() const + { + return bus_->P(); + } + + ScalarT& Q() + { + return bus_->Q(); + } + + const ScalarT& Q() const + { + return bus_->Q(); + } + + const ScalarT& lambdaP() const + { + return bus_->lambdaP(); + } + + const ScalarT& lambdaQ() const + { + return bus_->lambdaQ(); + } + + ScalarT& PB() + { + return bus_->PB(); + } + + ScalarT& QB() + { + return bus_->QB(); + } + + private: + // + // Private inlined accessor methods + // + + const ScalarT dotDelta() const + { + return yp_[offsetGen_ + 0]; + } + + const ScalarT dotOmega() const + { + return yp_[offsetGen_ + 1]; + } + + const ScalarT dotEdp() const + { + return yp_[offsetGen_ + 2]; + } + + const ScalarT dotEqp() const + { + return yp_[offsetGen_ + 3]; + } + + const ScalarT delta() const + { + return y_[offsetGen_ + 0]; + } + + const ScalarT omega() const + { + return y_[offsetGen_ + 1]; + } + + const ScalarT Edp() const + { + return y_[offsetGen_ + 2]; + } + + const ScalarT Eqp() const + { + return y_[offsetGen_ + 3]; + } + + const ScalarT Id() const + { + return y_[offsetGen_ + 4]; + } + + const ScalarT Iq() const + { + return y_[offsetGen_ + 5]; + } + + const ScalarT K() const + { + return param_[1]; + } + + const ScalarT T1() const + { + return T1_; + } + + const ScalarT T2() const + { + return param_[0]; + } + + const ScalarT T3() const + { + return T3_; + } + + private: + // Generator parameters + real_type H_; + real_type D_; + real_type Xq_; + real_type Xd_; + real_type Xqp_; + real_type Xdp_; + real_type Rs_; + real_type Tq0p_; + real_type Td0p_; + real_type Ef0_; + real_type Pm0_; + real_type deltaPm_; + real_type deltaPn_; + real_type omega_s_; + real_type omega_b_; + real_type omega_up_; + real_type omega_lo_; + real_type c_; + real_type beta_; + + // Governor parameters + real_type T1_; + real_type T2_; + real_type T3_; + real_type K_; + + // Index offsets + const IdxT offsetGen_; + const IdxT offsetGov_; + + // Initial power flow values + ScalarT P0_; + ScalarT Q0_; + + // Bus to which the generator is connected + bus_type* bus_; + }; + +} // namespace GridKit + +#endif // _GENERATOR_4_GOVERNOR_B_HPP_ diff --git a/src/Model/PowerFlow/Generator4Param/CMakeLists.txt b/src/Model/PowerFlow/Generator4Param/CMakeLists.txt new file mode 100644 index 000000000..b9a780cbb --- /dev/null +++ b/src/Model/PowerFlow/Generator4Param/CMakeLists.txt @@ -0,0 +1,12 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +gridkit_add_library(generator4param + SOURCES + Generator4Param.cpp + OUTPUT_NAME + gridkit_generator4param) diff --git a/src/Model/PowerFlow/Generator4Param/Generator4Param.cpp b/src/Model/PowerFlow/Generator4Param/Generator4Param.cpp new file mode 100644 index 000000000..e68ca368e --- /dev/null +++ b/src/Model/PowerFlow/Generator4Param/Generator4Param.cpp @@ -0,0 +1,415 @@ + +#include "Generator4Param.hpp" + +#include +#include + +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a simple generator model + * + * Arguments passed to ModelEvaluatorImpl: + * - Number of equations = 4 differential + 2 algebraic = 6 + * - Number of quadratures = 1 + * - Number of optimization parameters = 1 + */ + template + Generator4Param::Generator4Param(bus_type* bus, ScalarT P0, ScalarT Q0) + : ModelEvaluatorImpl(6, 1, 1), + H_(5.0), + D_(0.04), + Xq_(0.85), + Xd_(1.05), + Xqp_(0.35), + Xdp_(0.35), + Rs_(0.01), + Tq0p_(1.0), // [s] + Td0p_(8.0), // [s] + Ef_(1.45), + Pm_(1.0), + omega_s_(1.0), + omega_b_(2.0 * 60.0 * M_PI), + P0_(P0), + Q0_(Q0), + bus_(bus) + { + } + + template + Generator4Param::~Generator4Param() + { + } + + /*! + * @brief This function will be used to allocate sparse Jacobian matrices. + * + */ + template + int Generator4Param::allocate() + { + // std::cout << "Allocate Generator4Param..." << std::endl; + tag_.resize(size_); + + return 0; + } + + /** + * @brief Initialization of the generator model + * + * Initialization equations are derived from example 9.2 in Power System + * Modeling and Scripting, Federico Milano, Chapter 9, p. 225: + * \f{eqnarray*}{ + * &~& \omega_0 = 0, \\ + * &~& \delta_0 = \tan^{-1} \left(\frac{X_q P_0 - R_s Q_0}{V_0^2 + R_s P_0 + X_q Q_0} \right) + \theta_0, \\ + * &~& \phi_0 = \delta_0 - \theta_0 + \tan^{-1} \left( \frac{Q_0}{P_0} \right), \\ + * &~& I_{d0} = \frac{\sqrt{P_0^2 + Q_0^2}}{V_0} \sin(\phi_0), \\ + * &~& I_{q0} = \frac{\sqrt{P_0^2 + Q_0^2}}{V_0} \cos(\phi_0), \\ + * &~& E_{d0}' = V_0 \sin(\delta_0 - \theta_0) + R_s I_{d0} - X_q' I_{q0}, \\ + * &~& E_{q0}' = V_0 \cos(\delta_0 - \theta_0) + R_s I_{q0} + X_d' I_{d0} + * \f} + * + * The input from exciter and governor is set to the steady state value: + * \f{eqnarray*}{ + * &~& E_{f0} = E_{q0}' + (X_d - X_d') I_{d0}, \\ + * &~& P_{m0} = E_{d0}' I_{d0} + E_{q0}' I_{q0} + ( X_q' - X_d') I_{d0} I_{q0} + * \f} + * + */ + template + int Generator4Param::initialize() + { + // std::cout << "Initialize Generator4Param..." << std::endl; + + // Compute initial guess for the generator voltage phase + const ScalarT delta = atan((Xq_ * P0_ - Rs_ * Q0_) / (V() * V() + Rs_ * P0_ + Xq_ * Q0_)) + theta(); + + // Compute initial guess for the generator current phase + const ScalarT phi = theta() - delta - atan(Q0_ / P0_); + + // Compute initial gueses for generator currents and potentials in d-q frame + const ScalarT Id = std::sqrt(P0_ * P0_ + Q0_ * Q0_) / V() * sin(phi); + const ScalarT Iq = std::sqrt(P0_ * P0_ + Q0_ * Q0_) / V() * cos(phi); + const ScalarT Ed = V() * sin(theta() - delta) + Rs_ * Id + Xqp_ * Iq; + const ScalarT Eq = V() * cos(theta() - delta) + Rs_ * Iq - Xdp_ * Id; + + y_[0] = delta; + y_[1] = omega_s_; + y_[2] = Ed; + y_[3] = Eq; + y_[4] = Id; + y_[5] = Iq; + yp_[0] = 0.0; + yp_[1] = 0.0; + yp_[2] = 0.0; + yp_[3] = 0.0; + yp_[4] = 0.0; + yp_[5] = 0.0; + + // Set control parameter values here. + Ef_ = Eq - (Xd_ - Xdp_) * Id; // <~ set to steady state value + Pm_ = Ed * Id + Eq * Iq + (Xdp_ - Xqp_) * Id * Iq; // <~ set to steady state value + + // Initialize optimization parameters + param_[0] = H_; + param_up_[0] = 10.0; + param_lo_[0] = 2.0; + + // param_[0] = Pm_; + // param_up_[0] = 1.5; + // param_lo_[0] = 0.0; + + // param_[1] = Ef_; + // param_up_[1] = 1.7; + // param_lo_[1] = 0.0; + + return 0; + } + + /** + * \brief Identify differential variables. + */ + template + int Generator4Param::tagDifferentiable() + { + tag_[0] = true; + tag_[1] = true; + tag_[2] = true; + tag_[3] = true; + + for (IdxT i = 4; i < size_; ++i) + { + tag_[i] = false; + } + + return 0; + } + + /** + * @brief Computes residual vector for the generator model. + * + * Residual equations are given per model in Power System Modeling and + * Scripting, Federico Milano, Chapter 15, p. 334: + * \f{eqnarray*}{ + * f_0: &~& \dot{\delta} -\omega_b (\omega - \omega_s), \\ + * f_1: &~& 2H/\omega_s \dot{\omega} - L_m(P_m) + E_q' I_q + E_d' I_d + (X_q' - X_d')I_d I_q + D (\omega - \omega_s), \\ + * f_2: &~& T_{q0}' \dot{E}_d' + E_d' - (X_q - X_q')I_q, \\ + * f_3: &~& T_{d0}' \dot{E}_q' + E_q' + (X_d - X_d')I_d - E_f, \\ + * f_4: &~& R_s I_d - X_q' I_q + V \sin(\delta - \theta) - E_d', \\ + * f_5: &~& R_s I_q + X_d' I_d + V \cos(\delta - \theta) - E_q', + * \f} + * where \f$ \Omega_b \f$ is the synchronous frequency in [rad/s], and + * overdot denotes time derivative. + * + * Generator injection active and reactive power are + * \f{eqnarray*}{ + * P_g &=& E_d' I_d + E_q' I_q + (X_q' - X_d') I_d I_q - R_s (I_d^2 + I_q^2), \\ + * Q_q &=& E_q' I_d - E_d' I_q - X_q' I_q^2 - X_d' I_d^2, \\ + * \f} + * respectively. + * + * State variables are: + * \f$ y_0 = \omega \f$, \f$ y_1 = \delta \f$, \f$ y_2 = E_d' \f$, \f$ y_3 = E_q' \f$, + * \f$ y_4 = I_d \f$, \f$ y_5 = I_q \f$. + * + */ + template + int Generator4Param::evaluateResidual() + { + // std::cout << "Evaluate residual for Generator4Param..." << std::endl; + f_[0] = dotDelta() - omega_b_ * (omega() - omega_s_); + f_[1] = (2.0 * H()) / omega_s_ * dotOmega() - Pm() + Eqp() * Iq() + Edp() * Id() + (-Xdp_ + Xqp_) * Id() * Iq() + D_ * (omega() - omega_s_); + f_[2] = Tq0p_ * dotEdp() + Edp() - (Xq_ - Xqp_) * Iq(); + f_[3] = Td0p_ * dotEqp() + Eqp() + (Xd_ - Xdp_) * Id() - Ef(); + f_[4] = Rs_ * Id() - Xqp_ * Iq() + V() * sin(delta() - theta()) - Edp(); + f_[5] = Xdp_ * Id() + Rs_ * Iq() + V() * cos(delta() - theta()) - Eqp(); + + // Compute active and reactive load provided by the infinite bus. + P() += Pg(); + Q() += Qg(); + + // std::cout << "Residual: t = " << time_ << std::endl; + + return 0; + } + + template + int Generator4Param::evaluateJacobian() + { + std::cerr << "Evaluate Jacobian for Generator4Param..." << std::endl; + std::cerr << "Jacobian evaluation not implemented!" << std::endl; + return 0; + } + + template + int Generator4Param::evaluateIntegrand() + { + // std::cout << "Evaluate Integrand for Generator4Param..." << std::endl; + g_[0] = trajectoryPenalty(time_); + return 0; + } + + template + int Generator4Param::initializeAdjoint() + { + // std::cout << "Initialize adjoint for Generator4Param..." << std::endl; + for (IdxT i = 0; i < size_; ++i) + { + yB_[i] = 0.0; + ypB_[i] = 0.0; + } + // ypB_[1] = frequencyPenaltyDer(y_[1]); + ypB_[2] = -trajectoryPenaltyDerEdp(time_) / Tq0p_; + ypB_[3] = -trajectoryPenaltyDerEqp(time_) / Td0p_; + + return 0; + } + + /** + * @brief Computes adjoint residual vector for the generator model. + * + * Adjoint residual equations are given as: + * \f{eqnarray*}{ + * f_{B0}: &~& \dot{y}_{B0} - y_{B4} V \cos(\delta - \theta) + y_{B5} V \sin(\delta - \theta), \\ + * f_{B1}: &~& 2H/\omega_s \dot{y}_{B1} + y_{B0} \omega_b - y_{B1} D + y_{B9} (1 - T_2/T_1) - y_{B10} K T_2/T_1 + g_{\omega}(\omega), \\ + * f_{B2}: &~& T_{q0}' \dot{y}_{B2} - y_{B1} I_d - y_{B2} + y_{B4} + y_{B6} I_d - y_{B7} I_q, \\ + * f_{B3}: &~& T_{d0}' \dot{y}_{B3} - y_{B1} I_q - y_{B3} + y_{B5} + y_{B6} I_q + y_{B7} I_d, \\ + * f_{B4}: &~& -y_{B1} (E_d' + (-X_d'+X_q') I_q) - y_{B3} (X_d - X_d') - y_{B4} R_s - y_{B5} X_d' + y_{B6} (E_d' + (X_q' - X_d') I_q - 2 R_s I_d) + y_{B7} (E_q' - 2 X_d' I_d), \\ + * f_{B5}: &~& -y_{B1} (E_q' + (-X_d'+X_q') I_d) + y_{B2} (X_q - X_q') + y_{B4} X_q' - y_{B5} R_s + y_{B6} (E_q' + (X_q' - X_d') I_d - 2 R_s I_q) - y_{B7} (E_d' + 2 X_q' I_q). \\ + * \f} + * + */ + template + int Generator4Param::evaluateAdjointResidual() + { + // std::cout << "Evaluate adjoint residual for Generator4Param..." << std::endl; + ScalarT sinPhi = sin(delta() - theta()); + ScalarT cosPhi = cos(delta() - theta()); + + // Generator adjoint + fB_[0] = ypB_[0] - yB_[4] * V() * cosPhi + yB_[5] * V() * sinPhi; + fB_[1] = 2.0 * H() / omega_s_ * ypB_[1] + yB_[0] * omega_b_ - yB_[1] * D_; //+ frequencyPenaltyDer(omega()); + fB_[2] = Tq0p_ * ypB_[2] - yB_[1] * Id() - yB_[2] + yB_[4] + trajectoryPenaltyDerEdp(time_); + fB_[3] = Td0p_ * ypB_[3] - yB_[1] * Iq() - yB_[3] + yB_[5] + trajectoryPenaltyDerEqp(time_); + fB_[4] = -yB_[1] * (Edp() + (Xqp_ - Xdp_) * Iq()) - yB_[3] * (Xd_ - Xdp_) - yB_[4] * Rs_ - yB_[5] * Xdp_; + fB_[5] = -yB_[1] * (Eqp() + (Xqp_ - Xdp_) * Id()) + yB_[2] * (Xq_ - Xqp_) + yB_[4] * Xqp_ - yB_[5] * Rs_; + + return 0; + } + + // template + // int Generator4Param::evaluateAdjointJacobian() + // { + // std::cout << "Evaluate adjoint Jacobian for Generator4Param..." << std::endl; + // std::cout << "Adjoint Jacobian evaluation not implemented!" << std::endl; + // return 0; + // } + + template + int Generator4Param::evaluateAdjointIntegrand() + { + // std::cout << "Evaluate adjoint Integrand for Generator4Param..." << std::endl; + gB_[0] = -2.0 * yB_[1] * dotOmega() / omega_s_; + + return 0; + } + + // + // Private functions + // + + /** + * Generator active power Pg. + * + * \f[ P_g = E_q' I_q + E_d' I_d + (X_q' - X_d') I_q I_d - R_a (I_d^2 + I_q^2) \f] + * + */ + template + ScalarT Generator4Param::Pg() + { + return y_[5] * V() * cos(theta() - y_[0]) + y_[4] * V() * sin(theta() - y_[0]); + } + + /** + * Generator reactive power Qg. + * + * \f[ Q_g = E_q' I_d - E_d' I_q - X_d' I_d^2 - X_q' I_q^2 \f] + */ + template + ScalarT Generator4Param::Qg() + { + return y_[5] * V() * sin(theta() - y_[0]) - y_[4] * V() * cos(theta() - y_[0]); + } + + /** + * @brief Difference between computed system state and look-up table value. + * + * @todo Look-up table should probably live outside the generator model. + */ + template + ScalarT Generator4Param::trajectoryPenalty(ScalarT t) const + { + size_t N = table_.size(); + double ti = table_[0][0]; + double tf = table_[N - 1][0]; + double dt = (tf - ti) / (N - 1); + int n = std::trunc(t / tf * (N - 1.0)); + + double Edp_est = 0.0; + double Eqp_est = 0.0; + + if (t >= ti && t < tf) + { + // Interpolate from look-up table + Edp_est = (table_[n + 1][3] - table_[n][3]) / (table_[n + 1][0] - table_[n][0]) * (t - table_[n][0]) + table_[n][3]; + Eqp_est = (table_[n + 1][4] - table_[n][4]) / (table_[n + 1][0] - table_[n][0]) * (t - table_[n][0]) + table_[n][4]; + } + else + { + if (tf <= t && t < tf + dt) + { + // Extrapolate from look-up table + Edp_est = (table_[n][3] - table_[n - 1][3]) / (table_[n][0] - table_[n - 1][0]) * (t - table_[n - 1][0]) + table_[n - 1][3]; + Eqp_est = (table_[n][4] - table_[n - 1][4]) / (table_[n][0] - table_[n - 1][0]) * (t - table_[n - 1][0]) + table_[n - 1][4]; + } + else + { + // Too far away to extrapolate + std::cerr << "Trajectory penalty: Out of time bounds at time " << t << "\n"; + return -1.0; + } + } + double d = (Edp() - Edp_est); + double q = (Eqp() - Eqp_est); + return (d * d + q * q); + } + + template + ScalarT Generator4Param::trajectoryPenaltyDerEdp(ScalarT t) const + { + size_t N = table_.size(); + double ti = table_[0][0]; + double tf = table_[N - 1][0]; + double dt = (tf - ti) / (N - 1); + int n = std::trunc(t / tf * (N - 1.0)); + double Edp_est = 0.0; + + if (t >= ti && t < tf) + { + Edp_est = (table_[n + 1][3] - table_[n][3]) / (table_[n + 1][0] - table_[n][0]) * (t - table_[n][0]) + table_[n][3]; + } + else + { + if (tf <= t && t < tf + dt) + { + Edp_est = (table_[n][3] - table_[n - 1][3]) / (table_[n][0] - table_[n - 1][0]) * (t - table_[n - 1][0]) + table_[n - 1][3]; + } + else + { + std::cerr << "Trajectory penalty: Out of time bounds at time " << t << "\n"; + return -1.0; + } + } + double d = (Edp() - Edp_est); + + return 2.0 * d; + } + + template + ScalarT Generator4Param::trajectoryPenaltyDerEqp(ScalarT t) const + { + size_t N = table_.size(); + double ti = table_[0][0]; + double tf = table_[N - 1][0]; + double dt = (tf - ti) / (N - 1); + int n = std::trunc(t / tf * (N - 1.0)); + double Eqp_est = 0.0; + + if (t >= ti && t < tf) + { + Eqp_est = (table_[n + 1][4] - table_[n][4]) / (table_[n + 1][0] - table_[n][0]) * (t - table_[n][0]) + table_[n][4]; + } + else + { + if (tf <= t && t < tf + dt) + { + Eqp_est = (table_[n][4] - table_[n - 1][4]) / (table_[n][0] - table_[n - 1][0]) * (t - table_[n - 1][0]) + table_[n - 1][4]; + } + else + { + std::cerr << "Trajectory penalty: Out of time bounds at time " << t << "\n"; + return -1.0; + } + } + double q = (Eqp() - Eqp_est); + + return 2.0 * q; + } + + template class Generator4Param; + template class Generator4Param; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Generator4Param/Generator4Param.hpp b/src/Model/PowerFlow/Generator4Param/Generator4Param.hpp new file mode 100644 index 000000000..cc250995d --- /dev/null +++ b/src/Model/PowerFlow/Generator4Param/Generator4Param.hpp @@ -0,0 +1,221 @@ + +#ifndef _GENERATOR_4_H_ +#define _GENERATOR_4_H_ + +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Implementation of a fourth order generator model. + * + */ + template + class Generator4Param : public ModelEvaluatorImpl + { + 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 ModelEvaluatorImpl::param_up_; + using ModelEvaluatorImpl::param_lo_; + + typedef typename ModelEvaluatorImpl::real_type real_type; + typedef BaseBus bus_type; + + public: + Generator4Param(BaseBus* bus, ScalarT P0 = 1.0, ScalarT Q0 = 0.0); + virtual ~Generator4Param(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + void updateTime(real_type t, real_type a) + { + time_ = t; + alpha_ = a; + } + + // Inline accesor functions + ScalarT& V() + { + return bus_->V(); + } + + const ScalarT& V() const + { + return bus_->V(); + } + + ScalarT& theta() + { + return bus_->theta(); + } + + const ScalarT& theta() const + { + return bus_->theta(); + } + + ScalarT& P() + { + return bus_->P(); + } + + const ScalarT& P() const + { + return bus_->P(); + } + + ScalarT& Q() + { + return bus_->Q(); + } + + const ScalarT& Q() const + { + return bus_->Q(); + } + + ScalarT trajectoryPenalty(ScalarT t) const; + ScalarT trajectoryPenaltyDerEqp(ScalarT t) const; + ScalarT trajectoryPenaltyDerEdp(ScalarT t) const; + + std::vector>& getLookupTable() + { + return table_; + } + + std::vector> const& getLookupTable() const + { + return table_; + } + + private: + const ScalarT& H() const + { + return param_[0]; + } + + const ScalarT& Pm() const + { + return Pm_; + // return param_[0]; + } + + const ScalarT& Ef() const + { + return Ef_; + // return param_[1]; + } + + ScalarT Pg(); + ScalarT Qg(); + + private: + // + // Private inlined accessor methods + // + + const ScalarT dotDelta() const + { + return yp_[0]; + } + + const ScalarT dotOmega() const + { + return yp_[1]; + } + + const ScalarT dotEdp() const + { + return yp_[2]; + } + + const ScalarT dotEqp() const + { + return yp_[3]; + } + + const ScalarT delta() const + { + return y_[0]; + } + + const ScalarT omega() const + { + return y_[1]; + } + + const ScalarT Edp() const + { + return y_[2]; + } + + const ScalarT Eqp() const + { + return y_[3]; + } + + const ScalarT Id() const + { + return y_[4]; + } + + const ScalarT Iq() const + { + return y_[5]; + } + + private: + real_type H_; ///< Inertia constant [s] + real_type D_; ///< Damping constant [pu] + real_type Xq_; ///< q-axis synchronous reactance [pu] + real_type Xd_; ///< d-axis synchronous reactance [pu] + real_type Xqp_; ///< q-axis transient reactance [pu] + real_type Xdp_; ///< d-axis transient reactance [pu] + real_type Rs_; ///< stator armature resistance [pu] + real_type Tq0p_; ///< q-axis open circuit transient time constant [s] + real_type Td0p_; ///< d-axis open circuit transient time constant [s] + real_type Ef_; + real_type Pm_; + real_type omega_s_; + real_type omega_b_; + + ScalarT P0_; + ScalarT Q0_; + + bus_type* bus_; + + /// Look-up table data. @todo This should be part of a separate model. + std::vector> table_; + }; + +} // namespace GridKit + +#endif // _GENERATOR_4_H_ diff --git a/src/Model/PowerFlow/Load/CMakeLists.txt b/src/Model/PowerFlow/Load/CMakeLists.txt new file mode 100644 index 000000000..a17731b31 --- /dev/null +++ b/src/Model/PowerFlow/Load/CMakeLists.txt @@ -0,0 +1,10 @@ +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +gridkit_add_library(load + SOURCES + Load.cpp + OUTPUT_NAME + gridkit_load) diff --git a/src/Model/PowerFlow/Load/Load.cpp b/src/Model/PowerFlow/Load/Load.cpp new file mode 100644 index 000000000..9b5565181 --- /dev/null +++ b/src/Model/PowerFlow/Load/Load.cpp @@ -0,0 +1,121 @@ + +#include "Load.hpp" + +#include +#include +#include + +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a constant load model + * + * Calls default ModelEvaluatorImpl constructor. + */ + + template + Load::Load(bus_type* bus, ScalarT P, ScalarT Q) + : P_(P), + Q_(Q), + busID_(0), + bus_(bus) + { + // std::cout << "Create a load model with " << size_ << " variables ...\n"; + size_ = 0; + } + + template + Load::Load(bus_type* bus, LoadData& data) + : P_(data.Pd), + Q_(data.Qd), + busID_(data.bus_i), + bus_(bus) + { + // std::cout << "Create a load model with " << size_ << " variables ...\n"; + size_ = 0; + } + + template + Load::~Load() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int Load::allocate() + { + return 0; + } + + /** + * Initialization of the grid model + */ + template + int Load::initialize() + { + return 0; + } + + /* + * \brief Identify differential variables + */ + template + int Load::tagDifferentiable() + { + return 0; + } + + /** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ + template + int Load::evaluateResidual() + { + // std::cout << "Evaluating load residual ...\n"; + bus_->P() -= P_; + bus_->Q() -= Q_; + return 0; + } + + template + int Load::evaluateJacobian() + { + return 0; + } + + template + int Load::evaluateIntegrand() + { + return 0; + } + + template + int Load::initializeAdjoint() + { + return 0; + } + + template + int Load::evaluateAdjointResidual() + { + return 0; + } + + template + int Load::evaluateAdjointIntegrand() + { + return 0; + } + + // Available template instantiations + template class Load; + template class Load; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/Load/Load.hpp b/src/Model/PowerFlow/Load/Load.hpp new file mode 100644 index 000000000..a9c17eb0e --- /dev/null +++ b/src/Model/PowerFlow/Load/Load.hpp @@ -0,0 +1,75 @@ + +#ifndef _LOAD_HPP_ +#define _LOAD_HPP_ + +#include +#include + +namespace GridKit +{ + template + class BaseBus; +} + +namespace GridKit +{ + /*! + * @brief Declaration of a passive load class. + * + */ + template + class Load : public ModelEvaluatorImpl + { + 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_; + + // typedef typename ModelEvaluatorImpl::real_type real_type; + // typedef BaseBus bus_type; + using bus_type = BaseBus; + using real_type = typename ModelEvaluatorImpl::real_type; + using LoadData = GridKit::PowerSystemData::LoadData; + + public: + Load(bus_type* bus, ScalarT P, ScalarT Q); + Load(bus_type* bus, LoadData& data); + virtual ~Load(); + + int allocate(); + int initialize(); + int tagDifferentiable(); + int evaluateResidual(); + int evaluateJacobian(); + int evaluateIntegrand(); + + int initializeAdjoint(); + int evaluateAdjointResidual(); + // int evaluateAdjointJacobian(); + int evaluateAdjointIntegrand(); + + void updateTime(real_type t, real_type a) + { + time_ = t; + alpha_ = a; + } + + private: + ScalarT P_; + ScalarT Q_; + const IdxT busID_; + bus_type* bus_; + }; +} // namespace GridKit + +#endif // _LOAD_HPP_ diff --git a/ComponentLib/Load/README.md b/src/Model/PowerFlow/Load/README.md similarity index 99% rename from ComponentLib/Load/README.md rename to src/Model/PowerFlow/Load/README.md index fa10a0888..caa43996f 100644 --- a/ComponentLib/Load/README.md +++ b/src/Model/PowerFlow/Load/README.md @@ -29,4 +29,4 @@ Y_{SH}=G_{SH}+jB_{SH} ## Active -to be added \ No newline at end of file +to be added diff --git a/src/Model/PowerFlow/MiniGrid/CMakeLists.txt b/src/Model/PowerFlow/MiniGrid/CMakeLists.txt new file mode 100644 index 000000000..8487f8001 --- /dev/null +++ b/src/Model/PowerFlow/MiniGrid/CMakeLists.txt @@ -0,0 +1,10 @@ +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +gridkit_add_library(minigrid + SOURCES + MiniGrid.cpp + OUTPUT_NAME + gridkit_minigrid) diff --git a/src/Model/PowerFlow/MiniGrid/MiniGrid.cpp b/src/Model/PowerFlow/MiniGrid/MiniGrid.cpp new file mode 100644 index 000000000..eb03c9a13 --- /dev/null +++ b/src/Model/PowerFlow/MiniGrid/MiniGrid.cpp @@ -0,0 +1,89 @@ + +#include "MiniGrid.hpp" + +#include +#include +#include + +#include + +namespace GridKit +{ + + /*! + * @brief Constructor for a constant load model + * + * Calls default ModelEvaluatorImpl constructor. + */ + + template + MiniGrid::MiniGrid() + : ModelEvaluatorImpl(3, 0, 0), + Pl2_(2.5), + Ql2_(-0.8), + Pg3_(2.0), + V1_(1.0), + th1_(0.0), + V3_(1.1), + B12_(10.0), + B13_(15.0), + B22_(-22.0), + B23_(12.0) + { + // std::cout << "Create a load model with " << size_ << " variables ...\n"; + rel_tol_ = 1e-5; + abs_tol_ = 1e-5; + } + + template + MiniGrid::~MiniGrid() + { + } + + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int MiniGrid::allocate() + { + return 0; + } + + /** + * Initialization of the grid model + */ + template + int MiniGrid::initialize() + { + th2() = 0.0; // th2 + V2() = 1.0; // V2 + th3() = 0.0; // th3 + return 0; + } + + /** + * @brief Contributes to the bus residual. + * + * Must be connected to a PQ bus. + */ + template + int MiniGrid::evaluateResidual() + { + f_[0] = -Pl2_ - V2() * (V1_ * B12_ * sin(th2() - th1_) + V3_ * B23_ * sin(th2() - th3())); + f_[1] = -Ql2_ + V2() * (V1_ * B12_ * cos(th2() - th1_) + B22_ * V2() + V3_ * B23_ * cos(th2() - th3())); + f_[2] = Pg3_ - V3_ * (V1_ * B13_ * sin(th3() - th1_) + V2() * B23_ * sin(th3() - th2())); + + return 0; + } + + template + int MiniGrid::evaluateJacobian() + { + return 0; + } + + // Available template instantiations + template class MiniGrid; + template class MiniGrid; + +} // namespace GridKit diff --git a/src/Model/PowerFlow/MiniGrid/MiniGrid.hpp b/src/Model/PowerFlow/MiniGrid/MiniGrid.hpp new file mode 100644 index 000000000..eebb9f821 --- /dev/null +++ b/src/Model/PowerFlow/MiniGrid/MiniGrid.hpp @@ -0,0 +1,109 @@ +#pragma once + +#include + +#include + +namespace GridKit +{ + /*! + * @brief Implementation of a power grid. + * + */ + template + class MiniGrid : public ModelEvaluatorImpl + { + using ModelEvaluatorImpl::size_; + using ModelEvaluatorImpl::nnz_; + using ModelEvaluatorImpl::time_; + using ModelEvaluatorImpl::y_; + using ModelEvaluatorImpl::f_; + using ModelEvaluatorImpl::rel_tol_; + using ModelEvaluatorImpl::abs_tol_; + + typedef typename ModelEvaluatorImpl::real_type real_type; + + public: + MiniGrid(); + virtual ~MiniGrid(); + + int allocate(); + int initialize(); + + int tagDifferentiable() + { + return -1; + } + + int evaluateResidual(); + int evaluateJacobian(); + + int evaluateIntegrand() + { + return -1; + } + + int initializeAdjoint() + { + return -1; + } + + int evaluateAdjointResidual() + { + return -1; + } + + // int evaluateAdjointJacobian() {return -1;} + int evaluateAdjointIntegrand() + { + return -1; + } + + void updateTime(real_type t, real_type a) + { + } + + // const accessors are public + ScalarT const& th2() const + { + return y_[0]; + } + + ScalarT const& V2() const + { + return y_[1]; + } + + ScalarT const& th3() const + { + return y_[2]; + } + + ScalarT& th2() + { + return y_[0]; + } + + ScalarT& V2() + { + return y_[1]; + } + + ScalarT& th3() + { + return y_[2]; + } + + private: + ScalarT Pl2_; + ScalarT Ql2_; + ScalarT Pg3_; + ScalarT V1_; + ScalarT th1_; + ScalarT V3_; + ScalarT B12_; + ScalarT B13_; + ScalarT B22_; + ScalarT B23_; + }; +} // namespace GridKit diff --git a/src/Model/PowerFlow/ModelEvaluatorImpl.hpp b/src/Model/PowerFlow/ModelEvaluatorImpl.hpp new file mode 100644 index 000000000..3b7bb4825 --- /dev/null +++ b/src/Model/PowerFlow/ModelEvaluatorImpl.hpp @@ -0,0 +1,263 @@ + +#ifndef _MODEL_EVALUATOR_IMPL_HPP_ +#define _MODEL_EVALUATOR_IMPL_HPP_ + +#include + +#include + +namespace GridKit +{ + + /*! + * @brief Model implementation base class. + * + */ + template + class ModelEvaluatorImpl : public Model::Evaluator + { + public: + typedef typename Model::Evaluator::real_type real_type; + + ModelEvaluatorImpl() + : size_(0), + size_quad_(0), + size_opt_(0) + { + } + + ModelEvaluatorImpl(IdxT size, IdxT size_quad, IdxT size_opt) + : size_(size), + size_quad_(size_quad), + size_opt_(size_opt), + y_(size_), + yp_(size_), + f_(size_), + g_(size_quad_), + yB_(size_), + ypB_(size_), + fB_(size_), + gB_(size_opt_), + jac_(COO_Matrix()), + param_(size_opt_), + param_up_(size_opt_), + param_lo_(size_opt_) + { + } + + virtual IdxT size() + { + return size_; + } + + virtual IdxT nnz() + { + return nnz_; + } + + virtual bool hasJacobian() + { + return false; + } + + virtual IdxT sizeQuadrature() + { + return size_quad_; + } + + virtual IdxT sizeParams() + { + return size_opt_; + } + + // virtual void updateTime(real_type t, real_type a) + // { + // time_ = t; + // alpha_ = a; + // std::cout << "updateTime: t = " << time_ << "\n"; + // } + + virtual void setTolerances(real_type& rel_tol, real_type& abs_tol) const + { + rel_tol = rel_tol_; + abs_tol = abs_tol_; + } + + virtual void setMaxSteps(IdxT& msa) const + { + msa = max_steps_; + } + + std::vector& y() + { + return y_; + } + + const std::vector& y() const + { + return y_; + } + + std::vector& yp() + { + return yp_; + } + + const std::vector& yp() const + { + return yp_; + } + + std::vector& tag() + { + return tag_; + } + + const std::vector& tag() const + { + return tag_; + } + + std::vector& yB() + { + return yB_; + } + + const std::vector& yB() const + { + return yB_; + } + + std::vector& ypB() + { + return ypB_; + } + + const std::vector& ypB() const + { + return ypB_; + } + + std::vector& param() + { + return param_; + } + + const std::vector& param() const + { + return param_; + } + + std::vector& param_up() + { + return param_up_; + } + + const std::vector& param_up() const + { + return param_up_; + } + + std::vector& param_lo() + { + return param_lo_; + } + + const std::vector& param_lo() const + { + return param_lo_; + } + + std::vector& getResidual() + { + return f_; + } + + const std::vector& getResidual() const + { + return f_; + } + + COO_Matrix& getJacobian() + { + return jac_; + } + + const COO_Matrix& getJacobian() const + { + return jac_; + } + + std::vector& getIntegrand() + { + return g_; + } + + const std::vector& getIntegrand() const + { + return g_; + } + + std::vector& getAdjointResidual() + { + return fB_; + } + + const std::vector& getAdjointResidual() const + { + return fB_; + } + + std::vector& getAdjointIntegrand() + { + return gB_; + } + + const std::vector& getAdjointIntegrand() const + { + return gB_; + } + + //@todo Fix ID naming + IdxT getIDcomponent() + { + return idc_; + } + + protected: + IdxT size_; + IdxT nnz_; + IdxT size_quad_; + IdxT size_opt_; + + 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 jac_; + + std::vector param_; + std::vector param_up_; + std::vector param_lo_; + + real_type time_; + real_type alpha_; + + real_type rel_tol_; + real_type abs_tol_; + + IdxT max_steps_; + + IdxT idc_; + }; + +} // namespace GridKit + +#endif // _MODEL_EVALUATOR_IMPL_HPP_ diff --git a/ComponentLib/README.md b/src/Model/PowerFlow/README.md similarity index 99% rename from ComponentLib/README.md rename to src/Model/PowerFlow/README.md index 93c2bc349..7162738fc 100644 --- a/ComponentLib/README.md +++ b/src/Model/PowerFlow/README.md @@ -1,6 +1,7 @@ ## Component Models GridKit™ provides component models for power flow and electromechanical transient simulations, as well as experimental component models for dynamic constrained optimal power flow analysis. GridKit™ assembles components into a grid model using power flow equations. + ## Network Equations The relation between all the bus current injections and bus voltage is given by the following node equation: diff --git a/src/Model/PowerFlow/SystemModel.hpp b/src/Model/PowerFlow/SystemModel.hpp new file mode 100644 index 000000000..ceb197b87 --- /dev/null +++ b/src/Model/PowerFlow/SystemModel.hpp @@ -0,0 +1,659 @@ + +#ifndef _SYSTEM_MODEL_HPP_ +#define _SYSTEM_MODEL_HPP_ + +#include +#include +#include + +#include +#include + +namespace GridKit +{ + + /** + * @brief Prototype for a system model class + * + * This class maps component data to system data and implements + * Model::Evaluator for the system model. This is still work in + * progress and code is not optimized. + * + * @todo Address thread safety for the system model methods. + * + */ + template + class SystemModel : public ModelEvaluatorImpl + { + using bus_type = Model::Evaluator; + using component_type = Model::Evaluator; + using real_type = typename ModelEvaluatorImpl::real_type; + + using ModelEvaluatorImpl::size_; + using ModelEvaluatorImpl::size_quad_; + using ModelEvaluatorImpl::size_opt_; + using ModelEvaluatorImpl::nnz_; + using ModelEvaluatorImpl::time_; + using ModelEvaluatorImpl::alpha_; + using ModelEvaluatorImpl::y_; + using ModelEvaluatorImpl::yp_; + using ModelEvaluatorImpl::yB_; + using ModelEvaluatorImpl::ypB_; + using ModelEvaluatorImpl::tag_; + using ModelEvaluatorImpl::f_; + using ModelEvaluatorImpl::fB_; + using ModelEvaluatorImpl::g_; + using ModelEvaluatorImpl::gB_; + using ModelEvaluatorImpl::rel_tol_; + using ModelEvaluatorImpl::abs_tol_; + using ModelEvaluatorImpl::param_; + using ModelEvaluatorImpl::param_up_; + using ModelEvaluatorImpl::param_lo_; + + public: + /** + * @brief Constructor for the system model + */ + SystemModel() + : ModelEvaluatorImpl(0, 0, 0) + { + // Set system model tolerances + rel_tol_ = 1e-7; + abs_tol_ = 1e-9; + this->max_steps_ = 2000; + } + + /** + * @brief Destructor for the system model + */ + virtual ~SystemModel() + { + } + + /** + * @brief Allocate buses, components, and system objects. + * + * This method first allocates bus objects, then component objects, + * and computes system size (number of unknowns). Once the size is + * computed, system global objects are allocated. + * + * @post size_quad_ == 0 or 1 + * @post size_ >= 1 + * @post size_opt_ >= 0 + * + */ + int allocate() + { + size_ = 0; + size_quad_ = 0; + size_opt_ = 0; + + // Allocate all buses + for (const auto& bus : buses_) + { + bus->allocate(); + size_ += bus->size(); + size_quad_ += bus->sizeQuadrature(); + size_opt_ += bus->sizeParams(); + } + + // Allocate all components + for (const auto& component : components_) + { + component->allocate(); + size_ += component->size(); + size_quad_ += component->sizeQuadrature(); + size_opt_ += component->sizeParams(); + } + + // Allocate global vectors + y_.resize(size_); + yp_.resize(size_); + yB_.resize(size_); + ypB_.resize(size_); + f_.resize(size_); + fB_.resize(size_); + tag_.resize(size_); + + g_.resize(size_quad_); + gB_.resize(size_quad_ * size_opt_); + + param_.resize(size_opt_); + param_lo_.resize(size_opt_); + param_up_.resize(size_opt_); + + assert(size_quad_ == 1 or size_quad_ == 0); + + return 0; + } + + /** + * @brief Assume that jacobian is not avalible + * + * @return true + * @return false + */ + bool hasJacobian() + { + return false; + } + + /** + * @brief Initialize buses first, then all the other components. + * + * @pre All buses and components must be allocated at this point. + * @pre Bus variables are written before component variables in the + * system variable vector. + * + * Buses must be initialized before other components, because other + * components may write to buses during the initialization. + * + * Also, generators may write to control devices (e.g. governors, + * exciters, etc.) during the initialization. + * + * @todo Implement writting to system vectors in a thread-safe way. + */ + int initialize() + { + // Set initial values for global solution vectors + IdxT varOffset = 0; + IdxT optOffset = 0; + + for (const auto& bus : buses_) + { + bus->initialize(); + } + + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + y_[varOffset + j] = bus->y()[j]; + yp_[varOffset + j] = bus->yp()[j]; + } + varOffset += bus->size(); + + for (IdxT j = 0; j < bus->sizeParams(); ++j) + { + param_[optOffset + j] = bus->param()[j]; + param_lo_[optOffset + j] = bus->param_lo()[j]; + param_up_[optOffset + j] = bus->param_up()[j]; + } + optOffset += bus->sizeParams(); + } + + // Initialize components + for (const auto& component : components_) + { + component->initialize(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + y_[varOffset + j] = component->y()[j]; + yp_[varOffset + j] = component->yp()[j]; + } + varOffset += component->size(); + + for (IdxT j = 0; j < component->sizeParams(); ++j) + { + param_[optOffset + j] = component->param()[j]; + param_lo_[optOffset + j] = component->param_lo()[j]; + param_up_[optOffset + j] = component->param_up()[j]; + } + optOffset += component->sizeParams(); + } + + return 0; + } + + /** + * @todo Tagging differential variables + * + * Identify what variables in the system of differential-algebraic + * equations are differential variables, i.e. their derivatives + * appear in the equations. + */ + int tagDifferentiable() + { + // Set initial values for global solution vectors + IdxT offset = 0; + for (const auto& bus : buses_) + { + bus->tagDifferentiable(); + for (IdxT j = 0; j < bus->size(); ++j) + { + tag_[offset + j] = bus->tag()[j]; + } + offset += bus->size(); + } + + for (const auto& component : components_) + { + component->tagDifferentiable(); + for (IdxT j = 0; j < component->size(); ++j) + { + tag_[offset + j] = component->tag()[j]; + } + offset += component->size(); + } + + return 0; + } + + /** + * @brief Compute system residual vector + * + * First, update bus and component variables from the system solution + * vector. Next, evaluate residuals in buses and components, and + * then copy values to the global residual vector. + * + * @warning Residuals must be computed for buses, before component + * residuals are computed. Buses own residuals for active and + * power P and Q, but the contributions to these residuals come + * from components. Buses assign their residual values, while components + * add to those values by in-place adition. This is why bus residuals + * need to be computed first. + * + * @todo Here, components write to local values, which are then copied + * to global system vectors. Make components write to the system + * vectors directly. + */ + int evaluateResidual() + { + // Update variables + IdxT varOffset = 0; + IdxT optOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + bus->y()[j] = y_[varOffset + j]; + bus->yp()[j] = yp_[varOffset + j]; + } + varOffset += bus->size(); + + for (IdxT j = 0; j < bus->sizeParams(); ++j) + { + bus->param()[j] = param_[optOffset + j]; + } + optOffset += bus->sizeParams(); + + bus->evaluateResidual(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + component->y()[j] = y_[varOffset + j]; + component->yp()[j] = yp_[varOffset + j]; + } + varOffset += component->size(); + + for (IdxT j = 0; j < component->sizeParams(); ++j) + { + component->param()[j] = param_[optOffset + j]; + } + optOffset += component->sizeParams(); + + component->evaluateResidual(); + } + + // Update residual vector + IdxT resOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + f_[resOffset + j] = bus->getResidual()[j]; + } + resOffset += bus->size(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + f_[resOffset + j] = component->getResidual()[j]; + } + resOffset += component->size(); + } + + return 0; + } + + /** + * @brief Evaluate system Jacobian. + * + * @todo Need to implement Jacobian. For now, using finite difference + * approximation provided by IDA. This works for dense Jacobian matrix + * only. + * + */ + int evaluateJacobian() + { + return 0; + } + + /** + * @brief Evaluate integrands for the system quadratures. + */ + int evaluateIntegrand() + { + // Update variables + IdxT varOffset = 0; + IdxT optOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + bus->y()[j] = y_[varOffset + j]; + bus->yp()[j] = yp_[varOffset + j]; + } + varOffset += bus->size(); + + for (IdxT j = 0; j < bus->sizeParams(); ++j) + { + bus->param()[j] = param_[optOffset + j]; + } + optOffset += bus->sizeParams(); + + bus->evaluateIntegrand(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + component->y()[j] = y_[varOffset + j]; + component->yp()[j] = yp_[varOffset + j]; + } + varOffset += component->size(); + + for (IdxT j = 0; j < component->sizeParams(); ++j) + { + component->param()[j] = param_[optOffset + j]; + } + optOffset += component->sizeParams(); + + component->evaluateIntegrand(); + } + + // Update integrand vector + IdxT intOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->sizeQuadrature(); ++j) + { + g_[intOffset + j] = bus->getIntegrand()[j]; + } + intOffset += bus->sizeQuadrature(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->sizeQuadrature(); ++j) + { + g_[intOffset + j] = component->getIntegrand()[j]; + } + intOffset += component->sizeQuadrature(); + } + + return 0; + } + + /** + * @brief Initialize system adjoint. + * + * Updates variables and optimization parameters, then initializes + * adjoints locally and copies them to the system adjoint vector. + */ + int initializeAdjoint() + { + IdxT offset = 0; + IdxT optOffset = 0; + + // Update bus variables and optimization parameters + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + bus->y()[j] = y_[offset + j]; + bus->yp()[j] = yp_[offset + j]; + } + offset += bus->size(); + + for (IdxT j = 0; j < bus->sizeParams(); ++j) + { + bus->param()[j] = param_[optOffset + j]; + } + optOffset += bus->sizeParams(); + } + + // Update component variables and optimization parameters + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + component->y()[j] = y_[offset + j]; + component->yp()[j] = yp_[offset + j]; + } + offset += component->size(); + + for (IdxT j = 0; j < component->sizeParams(); ++j) + { + component->param()[j] = param_[optOffset + j]; + } + optOffset += component->sizeParams(); + } + + // Reset counter + offset = 0; + + // Initialize bus adjoints + for (const auto& bus : buses_) + { + bus->initializeAdjoint(); + + for (IdxT j = 0; j < bus->size(); ++j) + { + yB_[offset + j] = bus->yB()[j]; + ypB_[offset + j] = bus->ypB()[j]; + } + offset += bus->size(); + } + + // Initialize component adjoints + for (const auto& component : components_) + { + component->initializeAdjoint(); + + for (IdxT j = 0; j < component->size(); ++j) + { + yB_[offset + j] = component->yB()[j]; + ypB_[offset + j] = component->ypB()[j]; + } + offset += component->size(); + } + + return 0; + } + + /** + * @brief Compute adjoint residual for the system model. + * + * @warning Components write to bus residuals. Do not copy bus residuals + * to system vectors before components computed their residuals. + * + */ + int evaluateAdjointResidual() + { + IdxT varOffset = 0; + IdxT optOffset = 0; + + // Update variables in component models + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + bus->y()[j] = y_[varOffset + j]; + bus->yp()[j] = yp_[varOffset + j]; + bus->yB()[j] = yB_[varOffset + j]; + bus->ypB()[j] = ypB_[varOffset + j]; + } + varOffset += bus->size(); + + for (IdxT j = 0; j < bus->sizeParams(); ++j) + { + bus->param()[j] = param_[optOffset + j]; + } + optOffset += bus->sizeParams(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + component->y()[j] = y_[varOffset + j]; + component->yp()[j] = yp_[varOffset + j]; + component->yB()[j] = yB_[varOffset + j]; + component->ypB()[j] = ypB_[varOffset + j]; + } + varOffset += component->size(); + + for (IdxT j = 0; j < component->sizeParams(); ++j) + { + component->param()[j] = param_[optOffset + j]; + } + optOffset += component->sizeParams(); + } + + for (const auto& bus : buses_) + { + bus->evaluateAdjointResidual(); + } + + for (const auto& component : components_) + { + component->evaluateAdjointResidual(); + } + + // Update residual vector + IdxT resOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + fB_[resOffset + j] = bus->getAdjointResidual()[j]; + } + resOffset += bus->size(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + fB_[resOffset + j] = component->getAdjointResidual()[j]; + } + resOffset += component->size(); + } + + return 0; + } + + // int evaluateAdjointJacobian(){return 0;} + + /** + * @brief Evaluate adjoint integrand for the system model. + * + * @pre Assumes there are no integrands in bus models. + * @pre Assumes integrand is implemented in only _one_ component. + * + */ + int evaluateAdjointIntegrand() + { + // First, update variables + IdxT varOffset = 0; + IdxT optOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + bus->y()[j] = y_[varOffset + j]; + bus->yp()[j] = yp_[varOffset + j]; + bus->yB()[j] = yB_[varOffset + j]; + bus->ypB()[j] = ypB_[varOffset + j]; + } + varOffset += bus->size(); + + for (IdxT j = 0; j < bus->sizeParams(); ++j) + { + bus->param()[j] = param_[optOffset + j]; + } + optOffset += bus->sizeParams(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + component->y()[j] = y_[varOffset + j]; + component->yp()[j] = yp_[varOffset + j]; + component->yB()[j] = yB_[varOffset + j]; + component->ypB()[j] = ypB_[varOffset + j]; + } + varOffset += component->size(); + + for (IdxT j = 0; j < component->sizeParams(); ++j) + { + component->param()[j] = param_[optOffset + j]; + } + optOffset += component->sizeParams(); + } + + // Evaluate integrand and update global vector + for (const auto& component : components_) + { + if (component->sizeQuadrature() == 1) + { + component->evaluateAdjointIntegrand(); + for (IdxT j = 0; j < size_opt_; ++j) + { + gB_[j] = component->getAdjointIntegrand()[j]; + } + break; + } + } + return 0; + } + + void updateTime(real_type t, real_type a) + { + for (const auto& component : components_) + { + component->updateTime(t, a); + } + } + + void addBus(bus_type* bus) + { + buses_.push_back(bus); + } + + void addComponent(component_type* component) + { + components_.push_back(component); + } + + private: + std::vector buses_; + std::vector components_; + + }; // class SystemModel + +} // namespace GridKit + +#endif // _SYSTEM_MODEL_HPP_ diff --git a/src/Model/PowerFlow/SystemModelPowerFlow.hpp b/src/Model/PowerFlow/SystemModelPowerFlow.hpp new file mode 100644 index 000000000..d47f08992 --- /dev/null +++ b/src/Model/PowerFlow/SystemModelPowerFlow.hpp @@ -0,0 +1,378 @@ + +/** + * @file SystemSteadyStaeModel.hpp + * @author Slaven Peles + * + * Contains definition of power flow analysis class. + * + */ +#pragma once + +#include +#include +#include + +#include +#include + +namespace GridKit +{ + + /** + * @brief Prototype for a system model class + * + * This class maps component data to system data and implements + * ModelEvaluator for the system model. This is still work in + * progress and code is not optimized. + * + * @todo Address thread safety for the system model methods. + * + * @todo Tolerance management needs to be reconsidered. + * + */ + template + class SystemSteadyStateModel : public ModelEvaluatorImpl + { + typedef BaseBus bus_type; + typedef ModelEvaluatorImpl component_type; + using real_type = typename ModelEvaluatorImpl::real_type; + + using ModelEvaluatorImpl::size_; + // using ModelEvaluatorImpl::size_quad_; + // using ModelEvaluatorImpl::size_opt_; + using ModelEvaluatorImpl::nnz_; + // using ModelEvaluatorImpl::time_; + // using ModelEvaluatorImpl::alpha_; + using ModelEvaluatorImpl::y_; + // using ModelEvaluatorImpl::yp_; + // using ModelEvaluatorImpl::yB_; + // using ModelEvaluatorImpl::ypB_; + // using ModelEvaluatorImpl::tag_; + using ModelEvaluatorImpl::f_; + // using ModelEvaluatorImpl::fB_; + // using ModelEvaluatorImpl::g_; + // using ModelEvaluatorImpl::gB_; + using ModelEvaluatorImpl::rel_tol_; + using ModelEvaluatorImpl::abs_tol_; + // using ModelEvaluatorImpl::param_; + // using ModelEvaluatorImpl::param_up_; + // using ModelEvaluatorImpl::param_lo_; + + public: + /** + * @brief Constructor for the system model + */ + SystemSteadyStateModel() + : ModelEvaluatorImpl(0, 0, 0) + { + // Set system model tolerances + rel_tol_ = 1e-5; + abs_tol_ = 1e-5; + } + + /** + * @brief Construct a new System Steady State Model object. Allows for simple allocation. + * + * @param mp model data + */ + SystemSteadyStateModel(GridKit::PowerSystemData::SystemModelData mp) + : ModelEvaluatorImpl(0, 0, 0) + { + rel_tol_ = 1e-5; + abs_tol_ = 1e-5; + + // add buses + for (auto busdata : mp.bus) + { + auto* bus = BusFactory::create(busdata); + this->addBus(bus); + } + + // add generators + for (auto gendata : mp.gen) + { + auto* gen = GeneratorFactory::create(this->getBus(gendata.bus), gendata); + this->addComponent(gen); + } + + // add branches + for (auto branchdata : mp.branch) + { + auto* branch = new Branch(this->getBus(branchdata.fbus), this->getBus(branchdata.tbus), branchdata); + this->addComponent(branch); + } + + // add loads + for (auto loaddata : mp.load) + { + auto* loadm = new Load(this->getBus(loaddata.bus_i), loaddata); + this->addComponent(loadm); + } + + // There is no Generator Cost Object + // TODO: Implment for GenCost + } + + /** + * @brief Destructor for the system model + */ + virtual ~SystemSteadyStateModel() + { + for (auto comp : this->components_) + delete comp; + for (auto bus : this->buses_) + delete bus; + } + + /** + * @brief Allocate buses, components, and system objects. + * + * This method first allocates bus objects, then component objects, + * and computes system size (number of unknowns). Once the size is + * computed, system global objects are allocated. + * + * @post size_quad_ == 0 or 1 + * @post size_ >= 1 + * @post size_opt_ >= 0 + * + */ + int allocate() + { + size_ = 0; + + // Allocate all buses + for (const auto& bus : buses_) + { + bus->allocate(); + size_ += bus->size(); + } + + // Allocate all components + for (const auto& component : components_) + { + component->allocate(); + size_ += component->size(); + } + + // Allocate global vectors + y_.resize(size_); + f_.resize(size_); + + return 0; + } + + /** + * @brief Initialize buses first, then all the other components. + * + * @pre All buses and components must be allocated at this point. + * @pre Bus variables are written before component variables in the + * system variable vector. + * + * Buses must be initialized before other components, because other + * components may write to buses during the initialization. + * + * Also, generators may write to control devices (e.g. governors, + * exciters, etc.) during the initialization. + * + * @todo Implement writting to system vectors in a thread-safe way. + */ + int initialize() + { + // Set initial values for global solution vectors + IdxT varOffset = 0; + + for (const auto& bus : buses_) + { + bus->initialize(); + } + + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + y_[varOffset + j] = bus->y()[j]; + } + varOffset += bus->size(); + } + + // Initialize components + for (const auto& component : components_) + { + component->initialize(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + y_[varOffset + j] = component->y()[j]; + } + varOffset += component->size(); + } + return 0; + } + + /** + * @todo Tagging differential variables + * + * Identify what variables in the system of differential-algebraic + * equations are differential variables, i.e. their derivatives + * appear in the equations. + */ + int tagDifferentiable() + { + return 0; + } + + /** + * @brief Compute system residual vector + * + * First, update bus and component variables from the system solution + * vector. Next, evaluate residuals in buses and components, and + * then copy values to the global residual vector. + * + * @warning Residuals must be computed for buses, before component + * residuals are computed. Buses own residuals for active and + * power P and Q, but the contributions to these residuals come + * from components. Buses assign their residual values, while components + * add to those values by in-place adition. This is why bus residuals + * need to be computed first. + * + * @todo Here, components write to local values, which are then copied + * to global system vectors. Make components write to the system + * vectors directly. + */ + int evaluateResidual() + { + // Update variables + IdxT varOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + bus->y()[j] = y_[varOffset + j]; + } + varOffset += bus->size(); + bus->evaluateResidual(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + component->y()[j] = y_[varOffset + j]; + } + varOffset += component->size(); + component->evaluateResidual(); + } + + // Update system residual vector + IdxT resOffset = 0; + for (const auto& bus : buses_) + { + for (IdxT j = 0; j < bus->size(); ++j) + { + f_[resOffset + j] = bus->getResidual()[j]; + } + resOffset += bus->size(); + } + + for (const auto& component : components_) + { + for (IdxT j = 0; j < component->size(); ++j) + { + f_[resOffset + j] = component->getResidual()[j]; + } + resOffset += component->size(); + } + + return 0; + } + + /** + * @brief Evaluate system Jacobian. + * + * @todo Need to implement Jacobian. For now, using finite difference + * approximation provided by IDA. This works for dense Jacobian matrix + * only. + * + */ + int evaluateJacobian() + { + return 0; + } + + /** + * @brief Evaluate integrands for the system quadratures. + */ + int evaluateIntegrand() + { + + return 0; + } + + /** + * @brief Initialize system adjoint. + * + * Updates variables and optimization parameters, then initializes + * adjoints locally and copies them to the system adjoint vector. + */ + int initializeAdjoint() + { + return 0; + } + + /** + * @brief Compute adjoint residual for the system model. + * + * @warning Components write to bus residuals. Do not copy bus residuals + * to system vectors before components computed their residuals. + * + */ + int evaluateAdjointResidual() + { + return 0; + } + + // int evaluateAdjointJacobian(){return 0;} + + /** + * @brief Evaluate adjoint integrand for the system model. + * + * @pre Assumes there are no integrands in bus models. + * @pre Assumes integrand is implemented in only _one_ component. + * + */ + int evaluateAdjointIntegrand() + { + return 0; + } + + void updateTime(real_type t, real_type a) + { + } + + void addBus(bus_type* bus) + { + buses_.push_back(bus); + } + + void addComponent(component_type* component) + { + components_.push_back(component); + } + + bus_type* getBus(IdxT busid) + { + // Need to implement mapping of bus IDs to buses in the system model + assert((buses_[busid - 1])->BusID() == busid); + return buses_[busid - 1]; + } + + private: + std::vector buses_; + std::vector components_; + + }; // class SystemSteadyStateModel + +} // namespace GridKit diff --git a/src/PowerSystemData.hpp b/src/PowerSystemData.hpp new file mode 100644 index 000000000..a7b7dfb18 --- /dev/null +++ b/src/PowerSystemData.hpp @@ -0,0 +1,242 @@ +#pragma once +#include +#include +#include +#include + +/** + * + * @file PowerSystemData.hpp + * @author Asher Mancinelli + * + * @remark `std::stringstream` is preferred over `operator+(std::string, ...)` + * since stringstream does not reallocate on append. + * + */ + +namespace GridKit +{ + + namespace PowerSystemData + { + + template + struct BusData + { + IdxT bus_i; ///< Bus ID + IdxT type; ///< Bus type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated + RealT Gs; ///< Shunt conductance (MW demanded at V = 1.0 p.u.) + RealT Bs; ///< Shunt susceptance (MVAr injected at V = 1.0 p.u.) + IdxT area; ///< Area number (>0) + RealT Vm; ///< Voltage magnitude (p.u.) + RealT Va; ///< Voltage phase (deg) + RealT baseKV; ///< Base voltage [kV] + IdxT zone; ///< Loss zone number (>0) + RealT Vmax; ///< Maximum voltage magnitude (p.u.) + RealT Vmin; ///< Minimum voltage magnitude (p.u.) + + inline std::string str() const + { + std::stringstream ss; + std::cerr << std::setw(10) << bus_i + << std::setw(10) << type + << std::setw(10) << Gs + << std::setw(10) << Bs + << std::setw(10) << area + << std::setw(10) << Vm + << std::setw(10) << Va + << std::setw(10) << baseKV + << std::setw(10) << zone + << std::setw(10) << Vmax + << std::setw(10) << Vmin; + ss << "\n"; + return ss.str(); + } + }; + + template + struct LoadData + { + IdxT bus_i; ///< Bus ID + RealT Pd; ///< Active power demand [MW] + RealT Qd; ///< Reactive power demand [MVAr] + + inline std::string str() const + { + std::stringstream ss; + std::cerr << std::setw(10) << bus_i + << std::setw(10) << Pd + << std::setw(10) << Qd; + ss << "\n"; + return ss.str(); + } + }; + + template + struct GenData + { + IdxT bus; ///< Bus ID + RealT Pg; ///< Active power output [MW] + RealT Qg; ///< Reactive power output [MVAr] + RealT Qmax; ///< Maximum reactive power output [MVAr] + RealT Qmin; ///< Minimum reactive power output [MVAr] + RealT Vg; ///< + RealT mBase; ///< Total MVA base of machine + IdxT status; ///< Service status (>0 in service, <=0 out of service) + RealT Pmax; ///< Maximum active power output [MVAr] + RealT Pmin; ///< Minimum active power output [MVAr] + RealT Pc1; ///< + RealT Pc2; ///< + RealT Qc1min; ///< + RealT Qc1max; ///< + RealT Qc2min; ///< + RealT Qc2max; ///< + RealT ramp_agc; ///< + RealT ramp_10; ///< + RealT ramp_30; ///< + RealT ramp_q; ///< + RealT apf; ///< + + inline std::string str() const + { + std::stringstream ss; + ss << std::setw(10) << bus + << std::setw(10) << Pg + << std::setw(10) << Qg + << std::setw(10) << Qmax + << std::setw(10) << Qmin + << std::setw(10) << Vg + << std::setw(10) << mBase + << std::setw(10) << status + << std::setw(10) << Pmax + << std::setw(10) << Pmin + << std::setw(10) << Pc1 + << std::setw(10) << Pc2 + << std::setw(10) << Qc1min + << std::setw(10) << Qc1max + << std::setw(10) << Qc2min + << std::setw(10) << Qc2max + << std::setw(10) << ramp_agc + << std::setw(10) << ramp_10 + << std::setw(10) << ramp_30 + << std::setw(10) << ramp_q + << std::setw(10) << apf; + ss << "\n"; + return ss.str(); + } + }; + + template + struct BranchData + { + IdxT fbus; ///< "From" bus ID + IdxT tbus; ///< "To" bus ID + RealT r; ///< Resistance (p.u.) + RealT x; ///< Reactance (p.u.) + RealT b; ///< Total line charging susceptance (p.u.) + RealT rateA; ///< MVA rating A (long term rating), 0=unlimited + RealT rateB; ///< MVA rating B (short term rating), 0=unlimited + RealT rateC; ///< MVA rating C (emergency rating), 0=unlimited + RealT ratio; ///< Transformer off nominal turns ratio + RealT angle; ///< Transformer phase shift angle [deg], positive ⇒ delay + IdxT status; ///< Initial service status: 1=in-service, 0=out-of-service + RealT angmin; ///< Minimum anngle difference af - at [deg] + RealT angmax; ///< Maximum anngle difference af - at [deg] + + inline std::string str() const + { + std::stringstream ss; + ss << std::setw(10) << fbus + << std::setw(10) << tbus + << std::setw(10) << r + << std::setw(10) << x + << std::setw(10) << b + << std::setw(10) << rateA + << std::setw(10) << rateB + << std::setw(10) << rateC + << std::setw(10) << ratio + << std::setw(10) << angle + << std::setw(10) << status + << std::setw(10) << angmin + << std::setw(10) << angmax; + ss << "\n"; + return ss.str(); + } + }; + + template + struct GenCostData + { + IdxT kind; + IdxT startup; + IdxT shutdown; + IdxT n; + std::vector rest; + + inline std::string str() const + { + std::stringstream ss; + ss << std::setw(10) << kind + << std::setw(10) << startup + << std::setw(10) << shutdown + << std::setw(10) << n; + for (const auto& val : rest) + ss << std::setw(10) << val; + ss << "\n"; + return ss.str(); + } + }; + + template + struct SystemModelData + { + using BusDataT = BusData; + using GenDataT = GenData; + using BranchDataT = BranchData; + using GenCostDataT = GenCostData; + using LoadDataT = LoadData; + + std::string version; + IdxT baseMVA; + std::vector bus; + std::vector gen; + std::vector branch; + std::vector gencost; + std::vector load; + + // Not sure if these should be in this struct... Not all matpower files + // I found contained them. + // + // std::string name; + // std::vector bus_name; + + inline std::string str() const + { + std::stringstream ss; + ss << "Version: " << version << "\n" + << "Base MVA: " << baseMVA << "\n"; + + ss << "Bus:\n"; + for (const auto& v : bus) + ss << bus.str() << "\n"; + + ss << "Gen:\n"; + for (const auto& v : gen) + ss << gen.str(); + + ss << "Branch:\n"; + for (const auto& v : branch) + ss << branch.str(); + + ss << "GenCost:\n"; + for (const auto& v : gencost) + ss << gencost.str(); + + ss << "\n"; + + return ss.str(); + } + }; // struct SystemModelData + + } // namespace PowerSystemData +} // namespace GridKit diff --git a/src/ScalarTraits.hpp b/src/ScalarTraits.hpp new file mode 100644 index 000000000..e7cf77b8d --- /dev/null +++ b/src/ScalarTraits.hpp @@ -0,0 +1,23 @@ + +#ifndef _SCALAR_TRAITS_HPP_ +#define _SCALAR_TRAITS_HPP_ + +namespace GridKit +{ + template + class ScalarTraits + { + }; + + template <> + class ScalarTraits + { + public: + typedef double real_type; + typedef double norm_type; + typedef double scalar_type; + }; + +} // namespace GridKit + +#endif // _SCALAR_TRAITS_HPP_ diff --git a/src/Solver/CMakeLists.txt b/src/Solver/CMakeLists.txt new file mode 100644 index 000000000..f783ce34e --- /dev/null +++ b/src/Solver/CMakeLists.txt @@ -0,0 +1,16 @@ +# [[ +# Author(s): +# - Cameron Rutherford +# - Slaven Peles +#]] + +if(TARGET SUNDIALS::kinsol) + add_subdirectory(SteadyState) +endif() + +if(TARGET SUNDIALS::idas) + add_subdirectory(Dynamic) + if(GRIDKIT_ENABLE_IPOPT) + add_subdirectory(Optimization) + endif() +endif() diff --git a/src/Solver/Dynamic/CMakeLists.txt b/src/Solver/Dynamic/CMakeLists.txt new file mode 100644 index 000000000..be45aefa5 --- /dev/null +++ b/src/Solver/Dynamic/CMakeLists.txt @@ -0,0 +1,16 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +gridkit_add_library(solvers_dyn + SOURCES + Ida.cpp + LINK_LIBRARIES + PUBLIC SUNDIALS::nvecserial + PUBLIC SUNDIALS::idas + PUBLIC SUNDIALS::sunlinsolklu + OUTPUT_NAME + gridkit_solvers_dyn) diff --git a/src/Solver/Dynamic/DynamicSolver.hpp b/src/Solver/Dynamic/DynamicSolver.hpp new file mode 100644 index 000000000..81223e9fd --- /dev/null +++ b/src/Solver/Dynamic/DynamicSolver.hpp @@ -0,0 +1,33 @@ + +#ifndef _DYNAMIC_SOLVER_HPP_ +#define _DYNAMIC_SOLVER_HPP_ + +#include "Model/Evaluator.hpp" + +namespace AnalysisManager +{ + template + class DynamicSolver + { + public: + DynamicSolver(GridKit::Model::Evaluator* model) + : model_(model) + { + } + + virtual ~DynamicSolver() + { + } + + GridKit::Model::Evaluator* getModel() + { + return model_; + } + + protected: + GridKit::Model::Evaluator* model_; + }; + +} // namespace AnalysisManager + +#endif // _DYNAMIC_SOLVER_HPP_ diff --git a/src/Solver/Dynamic/Ida.cpp b/src/Solver/Dynamic/Ida.cpp new file mode 100644 index 000000000..8a4b07ac9 --- /dev/null +++ b/src/Solver/Dynamic/Ida.cpp @@ -0,0 +1,802 @@ + +#include "Ida.hpp" + +#include +#include + +#include +#include + +#include "Model/Evaluator.hpp" + +namespace AnalysisManager +{ + + namespace Sundials + { + + template + Ida::Ida(GridKit::Model::Evaluator* model) + : DynamicSolver(model) + { + int retval = 0; + + // Create the SUNDIALS context that all SUNDIALS objects require + retval = SUNContext_Create(SUN_COMM_NULL, &context_); + checkOutput(retval, "SUNContext"); + solver_ = IDACreate(context_); + tag_ = NULL; + } + + /** + * @brief Destroy the Ida< Scalar T, Idx T>:: Ida object + * + * @note if sysmodel is freed before this will fail. May want something agnostic to this + * + * @tparam ScalarT + * @tparam IdxT + */ + template + Ida::~Ida() + { + N_VDestroy(yy_); + N_VDestroy(yp_); + N_VDestroy(yy0_); + N_VDestroy(yp0_); + if (model_->hasJacobian()) + { + SUNLinSolFree_KLU(linearSolver_); + SUNMatDestroy_Sparse(JacobianMat_); + } + else + { + SUNLinSolFree_Dense(linearSolver_); + SUNMatDestroy_Dense(JacobianMat_); + } + ///@todo this free is needed but on geninfbus this seg faults + // IDAFree(&solver_); + SUNContext_Free(&context_); + } + + template + int Ida::configureSimulation() + { + int retval = 0; + + // Allocate solution vectors + yy_ = N_VNew_Serial(model_->size(), context_); + checkAllocation((void*) yy_, "N_VNew_Serial"); + yp_ = N_VClone(yy_); + checkAllocation((void*) yp_, "N_VClone"); + + // get intial conditions + this->getDefaultInitialCondition(); + + // Create vectors to store restart initial condition + yy0_ = N_VClone(yy_); + checkAllocation((void*) yy0_, "N_VClone"); + yp0_ = N_VClone(yp_); + checkAllocation((void*) yp0_, "N_VClone"); + + // Dummy initial time; will be overridden. + const sunrealtype t0 = SUN_RCONST(0.0); + + // Allocate and initialize IDA workspace + retval = IDAInit(solver_, this->Residual, t0, yy_, yp_); + checkOutput(retval, "IDAInit"); + + // Set pointer to model data + retval = IDASetUserData(solver_, model_); + checkOutput(retval, "IDASetUserData"); + + // Set tolerances + sunrealtype rel_tol; + sunrealtype abs_tol; + + model_->setTolerances(rel_tol, abs_tol); ///< \todo Function name should be "getTolerances"! + retval = IDASStolerances(solver_, rel_tol, abs_tol); + checkOutput(retval, "IDASStolerances"); + + IdxT msa; + model_->setMaxSteps(msa); + + /// \todo Need to set max number of steps based on user input! + retval = IDASetMaxNumSteps(solver_, msa); + checkOutput(retval, "IDASetMaxNumSteps"); + + // Tag differential variables + std::vector& tag = model_->tag(); + if (static_cast(tag.size()) == model_->size()) + { + tag_ = N_VClone(yy_); + checkAllocation((void*) tag_, "N_VClone"); + model_->tagDifferentiable(); + copyVec(tag, tag_); + + retval = IDASetId(solver_, tag_); + checkOutput(retval, "IDASetId"); + retval = IDASetSuppressAlg(solver_, SUNTRUE); + checkOutput(retval, "IDASetSuppressAlg"); + } + + // Set up linear solver + this->configureLinearSolver(); + + return retval; + } + + template + int Ida::configureLinearSolver() + { + int retval = 0; + if (model_->hasJacobian()) + { + JacobianMat_ = SUNSparseMatrix(model_->size(), model_->size(), model_->size() * model_->size(), CSR_MAT, context_); + checkAllocation((void*) JacobianMat_, "SUNSparseMatrix"); + + linearSolver_ = SUNLinSol_KLU(yy_, JacobianMat_, context_); + checkAllocation((void*) linearSolver_, "SUNLinSol_KLU"); + + retval = IDASetLinearSolver(solver_, linearSolver_, JacobianMat_); + checkOutput(retval, "IDASetLinearSolver"); + + retval = IDASetJacFn(solver_, this->Jac); + checkOutput(retval, "IDASetJacFn"); + } + else + { + JacobianMat_ = SUNDenseMatrix(model_->size(), model_->size(), context_); + checkAllocation((void*) JacobianMat_, "SUNDenseMatrix"); + + linearSolver_ = SUNLinSol_Dense(yy_, JacobianMat_, context_); + checkAllocation((void*) linearSolver_, "SUNLinSol_Dense"); + + retval = IDASetLinearSolver(solver_, linearSolver_, JacobianMat_); + checkOutput(retval, "IDASetLinearSolver"); + } + + return retval; + } + + template + int Ida::getDefaultInitialCondition() + { + model_->initialize(); + + copyVec(model_->y(), yy_); + copyVec(model_->yp(), yp_); + + return 0; + } + + template + int Ida::setIntegrationTime(real_type t_init, real_type t_final, int nout) + { + t_init_ = t_init; + t_final_ = t_final; + nout_ = nout; + return 0; + } + + template + int Ida::initializeSimulation(real_type t0, bool findConsistent) + { + int retval = 0; + + // Need to reinitialize IDA to set to get correct initial conditions + retval = IDAReInit(solver_, t0, yy_, yp_); + checkOutput(retval, "IDAReInit"); + + // Find a consistent set of initial conditions for DAE + if (findConsistent) + { + int initType = IDA_Y_INIT; + + if (tag_) + initType = IDA_YA_YDP_INIT; + + retval = IDACalcIC(solver_, initType, 0.1); + checkOutput(retval, "IDACalcIC"); + + copyVec(yy_, model_->y()); + copyVec(yp_, model_->yp()); + } + + return retval; + } + + template + int Ida::runSimulationFixed(real_type t0, real_type dt, real_type tmax, std::ostream& buffer) + { + int retval = 0; + int iout = 0; + real_type t, tret; + + for (t = t0 + dt; t <= tmax; t += dt) + { + retval = IDASolve(solver_, t, &tret, yy_, yp_, IDA_NORMAL); + checkOutput(retval, "IDASolve"); + printOutputF(t, retval, buffer); + + if (retval != IDA_SUCCESS) + { + std::cout << "IDA Failure! " << retval; + break; + } + } + + model_->updateTime(t, 0.0); + copyVec(yy_, model_->y()); + copyVec(yp_, model_->yp()); + + return retval; + } + + template + int Ida::runSimulation(real_type tf, int nout) + { + int retval = 0; + int iout = 0; + real_type tret; + real_type dt = tf / static_cast(nout); + real_type tout = dt; + + /* In loop, call IDASolve, print results, and test for error. + * Break out of loop when NOUT preset output times have been reached. */ + // printOutput(0.0); + while (nout > iout) + { + retval = IDASolve(solver_, tout, &tret, yy_, yp_, IDA_NORMAL); + checkOutput(retval, "IDASolve"); + // printOutput(tout); + + if (retval == IDA_SUCCESS) + { + ++iout; + tout += dt; + } + } + + // Final copy out. No gaurentee last residual evaluation is final step. + model_->updateTime(tf, 0.0); + copyVec(yy_, model_->y()); + copyVec(yp_, model_->yp()); + + // std::cout << "\n"; + return retval; + } + + template + int Ida::deleteSimulation() + { + IDAFree(&solver_); + SUNLinSolFree(linearSolver_); + N_VDestroy(yy_); + N_VDestroy(yp_); + return 0; + } + + template + int Ida::configureQuadrature() + { + int retval = 0; + + // Create and initialize quadratures + q_ = N_VNew_Serial(model_->sizeQuadrature(), context_); + checkAllocation((void*) q_, "N_VNew_Serial"); + + // Set integrand function and allocate quadrature workspace + retval = IDAQuadInit(solver_, this->Integrand, q_); + checkOutput(retval, "IDAQuadInit"); + + // Set tolerances and error control for quadratures + real_type rel_tol, abs_tol; + model_->setTolerances(rel_tol, abs_tol); + + // Set tolerances for quadrature stricter than for integration + retval = IDAQuadSStolerances(solver_, rel_tol * 0.1, abs_tol * 0.1); + checkOutput(retval, "IDAQuadSStolerances"); + + // Include quadrature in eror checking + retval = IDASetQuadErrCon(solver_, SUNTRUE); + checkOutput(retval, "IDASetQuadErrCon"); + + return retval; + } + + template + int Ida::initializeQuadrature() + { + int retval = 0; + + // Set all quadratures to zero + N_VConst(SUN_RCONST(0.0), q_); + + // Initialize quadratures + retval = IDAQuadReInit(solver_, q_); + checkOutput(retval, "IDAQuadInit"); + + return retval; + } + + template + int Ida::runSimulationQuadrature(real_type tf, int nout) + { + int retval = 0; + real_type tret; + + // std::cout << "Forward integration for initial value problem ... \n"; + + real_type dt = tf / static_cast(nout); + real_type tout = dt; + // printOutput(0.0); + // printSpecial(0.0, yy_); + for (int i = 0; i < nout; ++i) + { + retval = IDASolve(solver_, tout, &tret, yy_, yp_, IDA_NORMAL); + checkOutput(retval, "IDASolve"); + // printSpecial(tout, yy_); + // printOutput(tout); + + if (retval == IDA_SUCCESS) + { + tout += dt; + } + + retval = IDAGetQuad(solver_, &tret, q_); + checkOutput(retval, "IDAGetQuad"); + } + + // Final copy out. No gaurentee last residual evaluation is final step. + model_->updateTime(tf, 0.0); + copyVec(yy_, model_->y()); + copyVec(yp_, model_->yp()); + + return retval; + } + + template + int Ida::deleteQuadrature() + { + IDAQuadFree(solver_); + N_VDestroy(q_); + + return 0; + } + + template + int Ida::configureAdjoint() + { + // Allocate adjoint vector, derivatives and quadrature + yyB_ = N_VNew_Serial(model_->size(), context_); + checkAllocation((void*) yyB_, "N_VNew_Serial"); + + ypB_ = N_VClone(yyB_); + checkAllocation((void*) ypB_, "N_VClone"); + + qB_ = N_VNew_Serial(model_->sizeParams(), context_); + checkAllocation((void*) qB_, "N_VNew_Serial"); + + return 0; + } + + template + int Ida::initializeAdjoint(IdxT steps) + { + int retval = 0; + + // Create adjoint workspace + retval = IDAAdjInit(solver_, steps, IDA_HERMITE); + checkOutput(retval, "IDAAdjInit"); + + return retval; + } + + template + int Ida::initializeBackwardSimulation(real_type tf) + { + int retval = 0; + sunrealtype rel_tol; + sunrealtype abs_tol; + + model_->initializeAdjoint(); + + copyVec(model_->yB(), yyB_); + copyVec(model_->ypB(), ypB_); + N_VConst(0.0, qB_); + + retval = IDACreateB(solver_, &backwardID_); + checkOutput(retval, "IDACreateB"); + + // IDAInitB must be called after forward simulation run. + retval = IDAInitB(solver_, backwardID_, this->adjointResidual, tf, yyB_, ypB_); + checkOutput(retval, "IDAInitB"); + + model_->setTolerances(rel_tol, abs_tol); + retval = IDASStolerancesB(solver_, backwardID_, rel_tol, abs_tol); + checkOutput(retval, "IDASStolerancesB"); + + retval = IDASetUserDataB(solver_, backwardID_, model_); + checkOutput(retval, "IDASetUserDataB"); + + /// \todo Need to set max number of steps based on user input! + retval = IDASetMaxNumStepsB(solver_, backwardID_, 2000); + checkOutput(retval, "IDASetMaxNumSteps"); + + // Set up linear solver + JacobianMatB_ = SUNDenseMatrix(model_->size(), model_->size(), context_); + checkAllocation((void*) JacobianMatB_, "SUNDenseMatrix"); + + linearSolverB_ = SUNLinSol_Dense(yyB_, JacobianMatB_, context_); + checkAllocation((void*) linearSolverB_, "SUNLinSol_Dense"); + + retval = IDASetLinearSolverB(solver_, backwardID_, linearSolverB_, JacobianMatB_); + checkOutput(retval, "IDASetLinearSolverB"); + + // Also reinitialize quadratures. + retval = IDAQuadInitB(solver_, backwardID_, this->adjointIntegrand, qB_); + checkOutput(retval, "IDAQuadInitB"); + + // retval = IDAQuadSStolerancesB(solver_, backwardID_, rel_tol*1.1, abs_tol*1.1); + retval = IDAQuadSStolerancesB(solver_, backwardID_, rel_tol * 0.1, abs_tol * 0.1); + checkOutput(retval, "IDAQuadSStolerancesB"); + + // Include quadratures in error control + retval = IDASetQuadErrConB(solver_, backwardID_, SUNTRUE); + checkOutput(retval, "IDASetQuadErrConB"); + + return retval; + } + + template + int Ida::configureLinearSolverBackward() + { + int retval = 0; + + // Create Jacobian matrix + JacobianMatB_ = SUNDenseMatrix(model_->size(), model_->size(), context_); + checkAllocation((void*) JacobianMatB_, "SUNDenseMatrix"); + + // Create linear solver + linearSolverB_ = SUNLinSol_Dense(yyB_, JacobianMatB_, context_); + checkAllocation((void*) linearSolverB_, "SUNLinSol_Dense"); + + // Attach linear solver to IDA + retval = IDASetLinearSolverB(solver_, backwardID_, linearSolverB_, JacobianMatB_); + checkOutput(retval, "IDASetLinearSolverB"); + + return retval; + } + + template + int Ida::runForwardSimulation(real_type tf, int nout) + { + int retval = 0; + int ncheck; + real_type time; + + // std::cout << "Forward integration for adjoint analysis ... \n"; + + real_type dt = tf / static_cast(nout); + real_type tout = dt; + for (int i = 0; i < nout; ++i) + { + retval = IDASolveF(solver_, tout, &time, yy_, yp_, IDA_NORMAL, &ncheck); + checkOutput(retval, "IDASolveF"); + + if (retval == IDA_SUCCESS) + { + tout += dt; + } + + retval = IDAGetQuad(solver_, &time, q_); + checkOutput(retval, "IDASolve"); + } + + // Final copy out. No gaurentee last residual evaluation is final step. + model_->updateTime(tf, 0.0); + copyVec(yy_, model_->y()); + copyVec(yp_, model_->yp()); + + return retval; + } + + template + int Ida::runBackwardSimulation(real_type t_init) + { + int retval = 0; + long int nstB; + real_type time; + + // std::cout << "Backward integration for adjoint analysis ... "; + + retval = IDASolveB(solver_, t_init, IDA_NORMAL); + checkOutput(retval, "IDASolveB"); + + IDAGetNumSteps(IDAGetAdjIDABmem(solver_, backwardID_), &nstB); + // std::cout << "done ( nst = " << nstB << " )\n"; + + retval = IDAGetB(solver_, backwardID_, &time, yyB_, ypB_); + checkOutput(retval, "IDAGetB"); + + // Copy back into model + copyVec(yyB_, model_->yB()); + copyVec(ypB_, model_->ypB()); + + retval = IDAGetQuadB(solver_, backwardID_, &time, qB_); + checkOutput(retval, "IDAGetQuadB"); + + return retval; + } + + template + int Ida::deleteAdjoint() + { + IDAAdjFree(solver_); + return 0; + } + + template + int Ida::Residual(sunrealtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void* user_data) + { + GridKit::Model::Evaluator* model = static_cast*>(user_data); + + model->updateTime(tres, 0.0); + copyVec(yy, model->y()); + copyVec(yp, model->yp()); + + model->evaluateResidual(); + const std::vector& f = model->getResidual(); + copyVec(f, rr); + + return 0; + } + + template + int Ida::Jac(sunrealtype t, sunrealtype cj, N_Vector yy, N_Vector yp, N_Vector resvec, SUNMatrix J, void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) + { + + GridKit::Model::Evaluator* model = static_cast*>(user_data); + + model->updateTime(t, cj); + copyVec(yy, model->y()); + copyVec(yp, model->yp()); + + model->evaluateJacobian(); + COO_Matrix Jac = model->getJacobian(); + + // Get reference to the jacobian entries + std::tuple&, std::vector&, std::vector&> tpm = Jac.getEntries(); + const auto [r, c, val] = tpm; + + // get the CSR row pointers from COO matrix + std::vector csrrowdata = Jac.getCSRRowData(); + + SUNMatZero(J); + + // Set row pointers + sunindextype* rowptrs = SUNSparseMatrix_IndexPointers(J); + for (unsigned int i = 0; i < csrrowdata.size(); i++) + { + rowptrs[i] = csrrowdata[i]; + } + + sunindextype* colvals = SUNSparseMatrix_IndexValues(J); + sunrealtype* data = SUNSparseMatrix_Data(J); + // Copy data from model jac to sundials + for (unsigned int i = 0; i < c.size(); i++) + { + colvals[i] = c[i]; + data[i] = val[i]; + } + + return 0; + } + + template + int Ida::Integrand(sunrealtype tt, N_Vector yy, N_Vector yp, N_Vector rhsQ, void* user_data) + { + GridKit::Model::Evaluator* model = static_cast*>(user_data); + + model->updateTime(tt, 0.0); + copyVec(yy, model->y()); + copyVec(yp, model->yp()); + + model->evaluateIntegrand(); + const std::vector& g = model->getIntegrand(); + copyVec(g, rhsQ); + + return 0; + } + + template + int Ida::adjointResidual(sunrealtype tt, N_Vector yy, N_Vector yp, N_Vector yyB, N_Vector ypB, N_Vector rrB, void* user_data) + { + GridKit::Model::Evaluator* model = static_cast*>(user_data); + + model->updateTime(tt, 0.0); + copyVec(yy, model->y()); + copyVec(yp, model->yp()); + copyVec(yyB, model->yB()); + copyVec(ypB, model->ypB()); + + model->evaluateAdjointResidual(); + const std::vector& fB = model->getAdjointResidual(); + copyVec(fB, rrB); + + return 0; + } + + template + int Ida::adjointIntegrand(sunrealtype tt, N_Vector yy, N_Vector yp, N_Vector yyB, N_Vector ypB, N_Vector rhsQB, void* user_data) + { + GridKit::Model::Evaluator* model = static_cast*>(user_data); + + model->updateTime(tt, 0.0); + copyVec(yy, model->y()); + copyVec(yp, model->yp()); + copyVec(yyB, model->yB()); + copyVec(ypB, model->ypB()); + + model->evaluateAdjointIntegrand(); + const std::vector& gB = model->getAdjointIntegrand(); + copyVec(gB, rhsQB); + + return 0; + } + + template + void Ida::copyVec(const N_Vector x, std::vector& y) + { + const ScalarT* xdata = NV_DATA_S(x); + for (unsigned int i = 0; i < y.size(); ++i) + { + y[i] = xdata[i]; + } + } + + template + void Ida::copyVec(const std::vector& x, N_Vector y) + { + ScalarT* ydata = NV_DATA_S(y); + for (unsigned int i = 0; i < x.size(); ++i) + { + ydata[i] = x[i]; + } + } + + template + void Ida::copyVec(const std::vector& x, N_Vector y) + { + ScalarT* ydata = NV_DATA_S(y); + for (unsigned int i = 0; i < x.size(); ++i) + { + if (x[i]) + ydata[i] = 1.0; + else + ydata[i] = 0.0; + } + } + + template + void Ida::printOutputF(sunrealtype t, int res, std::ostream& buffer) + { + sunrealtype* yval = N_VGetArrayPointer_Serial(yy_); + sunrealtype* ypval = N_VGetArrayPointer_Serial(yp_); + + buffer << t << " " << res; + for (IdxT i = 0; i < model_->size(); ++i) + { + buffer << " " << yval[i]; + } + for (IdxT i = 0; i < model_->size(); ++i) + { + buffer << " " << ypval[i]; + } + buffer << std::endl; + + // fprintf(f, "%g,%d", t, res); + // for (IdxT i = 0; i < model_->size(); ++i) + // { + // fprintf(f, ",%g", yval[i]); + // } + // for (IdxT i = 0; i < model_->size(); ++i) + // { + // fprintf(f, ",%g", ypval[i]); + // } + // fprintf(f, "\n"); + } + + template + void Ida::printOutput(sunrealtype t) + { + sunrealtype* yval = N_VGetArrayPointer_Serial(yy_); + sunrealtype* ypval = N_VGetArrayPointer_Serial(yp_); + + std::cout << std::setprecision(5) << std::setw(7) << t << " "; + for (IdxT i = 0; i < model_->size(); ++i) + { + std::cout << yval[i] << " "; + } + for (IdxT i = 0; i < model_->size(); ++i) + { + std::cout << ypval[i] << " "; + } + std::cout << "\n"; + } + + template + void Ida::printSpecial(sunrealtype t, N_Vector y) + { + sunrealtype* yval = N_VGetArrayPointer_Serial(y); + IdxT N = static_cast(N_VGetLength_Serial(y)); + std::cout << "{"; + std::cout << std::setprecision(5) << std::setw(7) << t; + for (IdxT i = 0; i < N; ++i) + { + std::cout << ", " << yval[i]; + } + std::cout << "},\n"; + } + + template + void Ida::printFinalStats() + { + int retval = 0; + void* mem = solver_; + long int nst; + long int nre; + long int nje; + long int nni; + long int netf; + long int ncfn; + + retval = IDAGetNumSteps(mem, &nst); + checkOutput(retval, "IDAGetNumSteps"); + retval = IDAGetNumResEvals(mem, &nre); + checkOutput(retval, "IDAGetNumResEvals"); + retval = IDAGetNumJacEvals(mem, &nje); + checkOutput(retval, "IDAGetNumJacEvals"); + retval = IDAGetNumNonlinSolvIters(mem, &nni); + checkOutput(retval, "IDAGetNumNonlinSolvIters"); + retval = IDAGetNumErrTestFails(mem, &netf); + checkOutput(retval, "IDAGetNumErrTestFails"); + retval = IDAGetNumNonlinSolvConvFails(mem, &ncfn); + checkOutput(retval, "IDAGetNumNonlinSolvConvFails"); + + // std::cout << "\nFinal Run Statistics: \n\n"; + std::cout << "Number of steps = " << nst << "\n"; + std::cout << "Number of residual evaluations = " << nre << "\n"; + // std::cout << "Number of Jacobian evaluations = " << nje << "\n"; + std::cout << "Number of nonlinear iterations = " << nni << "\n"; + std::cout << "Number of error test failures = " << netf << "\n"; + std::cout << "Number of nonlinear conv. failures = " << ncfn << "\n"; + } + + template + void Ida::checkAllocation(void* v, const char* functionName) + { + if (v == NULL) + { + std::cerr << "\nERROR: Function " << functionName << " failed -- returned NULL pointer!\n\n"; + throw SundialsException(); + } + } + + template + void Ida::checkOutput(int retval, const char* functionName) + { + if (retval < 0) + { + std::cerr << "\nERROR: Function " << functionName << " failed with flag " << retval << "!\n\n"; + throw SundialsException(); + } + } + + // Compiler will prevent building modules with data type incompatible with sunrealtype + template class Ida; + template class Ida; + template class Ida; + + } // namespace Sundials +} // namespace AnalysisManager diff --git a/src/Solver/Dynamic/Ida.hpp b/src/Solver/Dynamic/Ida.hpp new file mode 100644 index 000000000..1fcbbca09 --- /dev/null +++ b/src/Solver/Dynamic/Ida.hpp @@ -0,0 +1,199 @@ + +#ifndef _IDA_HPP_ +#define _IDA_HPP_ + +#include +#include + +#include +#include /* access to dense linear solver */ +#include /* access to KLU linear solver */ +#include /* access to sparse SUNMatrix */ + +#include "DynamicSolver.hpp" +#include "Model/Evaluator.hpp" + +namespace AnalysisManager +{ + namespace Sundials + { + template + class Ida : public DynamicSolver + { + using DynamicSolver::model_; + + typedef typename GridKit::ScalarTraits::real_type real_type; + + public: + Ida(GridKit::Model::Evaluator* model); + ~Ida(); + + int configureSimulation(); + int configureLinearSolver(); + int getDefaultInitialCondition(); + int setIntegrationTime(real_type t_init, real_type t_final, int nout); + int initializeSimulation(real_type t0, bool findConsistent = false); + int runSimulation(real_type tf, int nout = 1); + int deleteSimulation(); + + // TODO: Temporary + int runSimulationFixed(real_type t0, real_type dt, real_type tmax, std::ostream& buffer); + + int configureQuadrature(); + int initializeQuadrature(); + int runSimulationQuadrature(real_type tf, int nout = 1); + int deleteQuadrature(); + + int configureAdjoint(); + int configureLinearSolverBackward(); + int initializeAdjoint(IdxT steps = 100); + int initializeBackwardSimulation(real_type tf); + int runForwardSimulation(real_type tf, int nout = 1); + int runBackwardSimulation(real_type t0); + int deleteAdjoint(); + + int saveInitialCondition() + { + N_VScale(1.0, yy_, yy0_); + N_VScale(1.0, yp_, yp0_); + return 0; + } + + int getSavedInitialCondition() + { + N_VScale(1.0, yy0_, yy_); + N_VScale(1.0, yp0_, yp_); + return 0; + } + + real_type getInitialTime() + { + return t_init_; + } + + real_type getFinalTime() + { + return t_final_; + } + + int getNumberOutputTimes() + { + return nout_; + } + + const real_type* getIntegral() const + { + return NV_DATA_S(q_); + } + + real_type* getIntegral() + { + return NV_DATA_S(q_); + } + + const real_type* getAdjointIntegral() const + { + return NV_DATA_S(qB_); + } + + real_type* getAdjointIntegral() + { + return NV_DATA_S(qB_); + } + + void printOutput(sunrealtype t); + void printSpecial(sunrealtype t, N_Vector x); + void printFinalStats(); + void printOutputF(sunrealtype t, int res, std::ostream& buffer); + + private: + static int Residual(sunrealtype t, + N_Vector yy, + N_Vector yp, + N_Vector rr, + void* user_data); + + static int Jac(sunrealtype t, + sunrealtype cj, + N_Vector yy, + N_Vector yp, + N_Vector resvec, + SUNMatrix J, + void* user_data, + N_Vector tmp1, + N_Vector tmp2, + N_Vector tmp3); + + static int Integrand(sunrealtype t, + N_Vector yy, + N_Vector yp, + N_Vector rhsQ, + void* user_data); + + static int adjointResidual(sunrealtype t, + N_Vector yy, + N_Vector yp, + N_Vector yyB, + N_Vector ypB, + N_Vector rrB, + void* user_data); + + static int adjointIntegrand(sunrealtype t, + N_Vector yy, + N_Vector yp, + N_Vector yyB, + N_Vector ypB, + N_Vector rhsQB, + void* user_data); + + private: + void* solver_; + SUNContext context_; + SUNMatrix JacobianMat_; + SUNMatrix JacobianMatB_; + SUNLinearSolver linearSolver_; + SUNLinearSolver linearSolverB_; + + real_type t_init_; + real_type t_final_; + int nout_; ///< Number of integration outputs + + N_Vector yy_; ///< Solution vector + N_Vector yp_; ///< Solution derivatives vector + N_Vector tag_; ///< Tags differential variables + N_Vector q_; ///< Integrand vector + + N_Vector yy0_; ///< Storage for initial values + N_Vector yp0_; ///< Storage for initial derivatives + + N_Vector yyB_; ///< Adjoint solution vector + N_Vector ypB_; ///< Adjoint solution derivatives vector + N_Vector qB_; ///< Backward integrand vector + + int backwardID_; + + private: + // static void copyMat(Model::Evaluator::Mat& J, SlsMat Jida); + static void copyVec(const N_Vector x, std::vector& y); + static void copyVec(const std::vector& x, N_Vector y); + static void copyVec(const std::vector& x, N_Vector y); + + // int check_flag(void *flagvalue, const char *funcname, int opt); + inline void checkAllocation(void* v, const char* functionName); + inline void checkOutput(int retval, const char* functionName); + }; + + /// Simple exception to use within Ida class. + class SundialsException : public std::exception + { + virtual const char* what() const throw() + { + return "Method in Ida class failed!\n"; + } + }; + + } // namespace Sundials + +} // namespace AnalysisManager + +#endif // _IDA_HPP_ diff --git a/src/Solver/Optimization/CMakeLists.txt b/src/Solver/Optimization/CMakeLists.txt new file mode 100644 index 000000000..7f3b4828f --- /dev/null +++ b/src/Solver/Optimization/CMakeLists.txt @@ -0,0 +1,16 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +gridkit_add_library(solvers_opt + SOURCES + DynamicObjective.cpp + DynamicConstraint.cpp + LINK_LIBRARIES + PUBLIC IPOPT + PUBLIC GRIDKIT::solvers_dyn + OUTPUT_NAME + gridkit_solvers_opt) diff --git a/src/Solver/Optimization/DynamicConstraint.cpp b/src/Solver/Optimization/DynamicConstraint.cpp new file mode 100644 index 000000000..5d2e04582 --- /dev/null +++ b/src/Solver/Optimization/DynamicConstraint.cpp @@ -0,0 +1,229 @@ + +#include "DynamicConstraint.hpp" + +#include +#include + +namespace AnalysisManager +{ + namespace IpoptInterface + { + + template + DynamicConstraint::DynamicConstraint(Sundials::Ida* integrator) + : OptimizationSolver(integrator), + t_init_(integrator_->getInitialTime()), + t_final_(integrator_->getFinalTime()), + nout_(integrator_->getNumberOutputTimes()) + { + model_ = integrator_->getModel(); + } + + template + DynamicConstraint::~DynamicConstraint() + { + } + + template + bool DynamicConstraint::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g, Index& nnz_h_lag, IndexStyleEnum& index_style) + { + // This code handles one objective function + assert(model_->size_quad() == 1); + + // Number of parameters is size of the system plus 1 fictitious parameter + // to store the objective value. + n = model_->sizeParams() + 1; + + // There is one constraint + m = 1; + + // Jacobian is a dense row matrix of length n+1. + nnz_jac_g = model_->sizeParams() + 1; + + // Using numerical Hessian. + nnz_h_lag = 0; + + // Use the C index style (0-based) for row/column entries + index_style = C_STYLE; + + return true; + } + + template + bool DynamicConstraint::get_bounds_info(Index n, Number* x_l, Number* x_u, Index m, Number* g_l, Number* g_u) + { + // Check if sizes are set correctly + assert(n == (Index) (model_->sizeParams() + 1)); + assert(m == 1); + + // Get boundaries for the optimization parameters + for (IdxT i = 0; i < model_->sizeParams(); ++i) + { + x_l[i] = model_->param_lo()[i]; + x_u[i] = model_->param_up()[i]; + } + + // No boundaries for fictitious parameter x[n] + x_l[model_->sizeParams()] = -1e20; + x_u[model_->sizeParams()] = +1e20; + + // Set constraint g[0] to be equality constraint g[0] = 0 + g_l[0] = 0.0; + g_u[0] = 0.0; + + return true; + } + + template + bool DynamicConstraint::get_starting_point(Index n, bool init_x, Number* x, bool init_z, Number* z_L, Number* z_U, Index m, bool init_lambda, Number* lambda) + { + // Only initial values for x provided. + assert(init_x == true); + assert(init_z == false); + assert(init_lambda == false); + + // Initialize optimization parameters x + for (IdxT i = 0; i < model_->sizeParams(); ++i) + x[i] = model_->param()[i]; + + // Initialize fictitious parameter x[n-1] to zero + x[model_->sizeParams()] = 0.0; + + return true; + } + + template + bool DynamicConstraint::eval_f(Index n, const Number* x, bool new_x, Number& obj_value) + { + // Set objective to fictitious optimization parameter x[n-1] + obj_value = x[model_->sizeParams()]; + + return true; + } + + template + bool DynamicConstraint::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f) + { + // Objective function equals to the fictitious parameter x[n-1]. + // Gradient, then assumes the simple form: + for (IdxT i = 0; i < model_->sizeParams(); ++i) + grad_f[i] = 0.0; + grad_f[model_->sizeParams()] = 1.0; + + return true; + } + + template + bool DynamicConstraint::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g) + { + // Update optimization parameters + for (IdxT i = 0; i < model_->sizeParams(); ++i) + { + model_->param()[i] = x[i]; + // std::cout << "x[" << i << "] = " << x[i] << "\n"; + } + + // Evaluate objective function + integrator_->getSavedInitialCondition(); + integrator_->initializeSimulation(t_init_); + integrator_->initializeQuadrature(); + + int status = 0; + status = integrator_->runSimulationQuadrature(t_final_, nout_); + if (status) + { + std::cerr << "Integration failed when using Pm = " << x[0] << "\n"; + return false; + } + + // For now assumes only one forward integrand and multiple optimization parameters. + g[0] = (integrator_->getIntegral())[0] - x[model_->sizeParams()]; + // std::cout << "constraint:" << g[0] << std::endl; + return true; + } + + template + bool DynamicConstraint::eval_jac_g(Index n, const Number* x, bool new_x, Index m, Index nele_jac, Index* iRow, Index* jCol, Number* values) + { + // Set Jacobian sparsity pattern ... + if (!values) + { + for (IdxT i = 0; i < model_->sizeParams(); ++i) + { + iRow[i] = 0; + jCol[i] = i; + } + iRow[model_->sizeParams()] = 0; + jCol[model_->sizeParams()] = model_->sizeParams(); + } + // ... or compute Jacobian derivatives + else + { + // Update optimization parameters + for (IdxT i = 0; i < model_->sizeParams(); ++i) + model_->param()[i] = x[i]; + + // evaluate the gradient of the objective function grad_{x} f(x) + // This is creating and deleting adjoint system for each iteration! + // Currently there is no more efficient solution. + integrator_->initializeAdjoint(); + + integrator_->getSavedInitialCondition(); + integrator_->initializeSimulation(t_init_); + integrator_->initializeQuadrature(); + + int status = 0; + status = integrator_->runForwardSimulation(t_final_, nout_); + if (status) + { + std::cerr << "Forward integration for adjoint solution failed when using Pm = " << x[0] << "\n"; + return false; + } + + integrator_->initializeBackwardSimulation(t_final_); + + status = integrator_->runBackwardSimulation(t_init_); + if (status) + { + std::cerr << "Backward integration for adjoint solution failed when using Pm = " << x[0] << "\n"; + return false; + } + + // For now assumes only one forward integrand and multiple optimization parameters. + for (IdxT i = 0; i < model_->sizeParams(); ++i) + { + values[i] = -((integrator_->getAdjointIntegral())[i]); + } + values[model_->sizeParams()] = -1.0; + + integrator_->deleteAdjoint(); + } + return true; + } + + template + bool DynamicConstraint::eval_h(Index n, const Number* x, bool new_x, Number obj_factor, Index m, const Number* lambda, bool new_lambda, Index nele_hess, Index* iRow, Index* jCol, Number* values) + { + return true; + } + + template + void DynamicConstraint::finalize_solution(SolverReturn status, + Index n, + const Number* x, + const Number* z_L, + const Number* z_U, + Index m, + const Number* g, + const Number* lambda, + Number obj_value, + const IpoptData* ip_data, + IpoptCalculatedQuantities* ip_cq) + { + } + + template class DynamicConstraint; + template class DynamicConstraint; + + } // namespace IpoptInterface +} // namespace AnalysisManager diff --git a/src/Solver/Optimization/DynamicConstraint.hpp b/src/Solver/Optimization/DynamicConstraint.hpp new file mode 100644 index 000000000..66fd79d8f --- /dev/null +++ b/src/Solver/Optimization/DynamicConstraint.hpp @@ -0,0 +1,91 @@ + +#ifndef _IPOPT_DYNAMIC_CONSTRAINT_HPP_ +#define _IPOPT_DYNAMIC_CONSTRAINT_HPP_ + +#include "OptimizationSolver.hpp" +#include + +namespace AnalysisManager +{ + + namespace IpoptInterface + { + + /** + * Implementation of Ipopt's pure virtual TNLP class. + * + * TNLP defines Ipopt's interface to the model. This is in fact + * the model evaluator interface to Ipopt. In this case however, + * the model evaluator calls dynamic solver to compute the objective + * and the gradient. + * + * \note This clas is based on Cosmin's reformulation of the dynamic + * constrained optimization problem. For now it is hard-wired to + * 1-parameter optimization problems. + * + */ + template + class DynamicConstraint : public Ipopt::TNLP, public OptimizationSolver + { + using OptimizationSolver::integrator_; + using OptimizationSolver::model_; + + typedef typename GridKit::ScalarTraits::real_type real_type; + + typedef Ipopt::Index Index; + typedef Ipopt::Number Number; + typedef Ipopt::SolverReturn SolverReturn; + typedef Ipopt::IpoptCalculatedQuantities IpoptCalculatedQuantities; + typedef Ipopt::IpoptData IpoptData; + + public: + DynamicConstraint(Sundials::Ida* integrator); + virtual ~DynamicConstraint(); + + /// Returns sizes of the model components + virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g, Index& nnz_h_lag, IndexStyleEnum& index_style); + + /// Returns problem bounds + virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u, Index m, Number* g_l, Number* g_u); + + /// Initialize optimization + virtual bool get_starting_point(Index n, bool init_x, Number* x, bool init_z, Number* z_L, Number* z_U, Index m, bool init_lambda, Number* lambda); + + /// Evaluate objective + virtual bool eval_f(Index n, const Number* x, bool new_x, Number& obj_value); + + /// Evaluate objective gradient + virtual bool eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f); + + /// Evaluate constraint residuals (not used here) + virtual bool eval_g(Index n, const Number* x, bool new_x, Index m, Number* g); + + /// Evaluate Jacobian (not used here) + virtual bool eval_jac_g(Index n, const Number* x, bool new_x, Index m, Index nele_jac, Index* iRow, Index* jCol, Number* values); + + /// Evaluate Hessian (have Ipopt estimate Hessian) + virtual bool eval_h(Index n, const Number* x, bool new_x, Number obj_factor, Index m, const Number* lambda, bool new_lambda, Index nele_hess, Index* iRow, Index* jCol, Number* values); + + /// Postprocessing of the results (not used here) + virtual void finalize_solution(SolverReturn status, + Index n, + const Number* x, + const Number* z_L, + const Number* z_U, + Index m, + const Number* g, + const Number* lambda, + Number obj_value, + const IpoptData* ip_data, + IpoptCalculatedQuantities* ip_cq); + + private: + real_type t_init_; + real_type t_final_; + int nout_; + }; + + } // namespace IpoptInterface +} // namespace AnalysisManager + +#endif // _IPOPT_DYNAMIC_CONSTRAINT_HPP_ diff --git a/src/Solver/Optimization/DynamicObjective.cpp b/src/Solver/Optimization/DynamicObjective.cpp new file mode 100644 index 000000000..0b76d82e0 --- /dev/null +++ b/src/Solver/Optimization/DynamicObjective.cpp @@ -0,0 +1,169 @@ + +#include "DynamicObjective.hpp" + +#include +#include + +namespace AnalysisManager +{ + namespace IpoptInterface + { + + template + DynamicObjective::DynamicObjective(Sundials::Ida* integrator) + : OptimizationSolver(integrator), + t_init_(integrator_->getInitialTime()), + t_final_(integrator_->getFinalTime()), + nout_(integrator_->getNumberOutputTimes()) + { + model_ = integrator_->getModel(); + } + + template + DynamicObjective::~DynamicObjective() + { + } + + template + bool DynamicObjective::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g, Index& nnz_h_lag, IndexStyleEnum& index_style) + { + // This code handles one objective function + assert(model_->size_quad() == 1); + + // Number of optimization variables. + n = model_->sizeParams(); + + // There are no constraints + m = 0; + + // No constraints, empty Jacobian. This is only temporary. + nnz_jac_g = 0; + + // Using numerical Hessian. + nnz_h_lag = 0; + + // Use the C index style (0-based) for row/column entries + index_style = C_STYLE; + + return true; + } + + template + bool DynamicObjective::get_bounds_info(Index n, Number* x_l, Number* x_u, Index m, Number* g_l, Number* g_u) + { + // Check if sizes are set correctly + assert(n == (Index) model_->sizeParams()); + assert(m == 0); + + // Get boundaries for the optimization parameters + for (IdxT i = 0; i < model_->sizeParams(); ++i) + { + x_l[i] = model_->param_lo()[i]; + x_u[i] = model_->param_up()[i]; + } + + return true; + } + + template + bool DynamicObjective::get_starting_point(Index n, bool init_x, Number* x, bool init_z, Number* z_L, Number* z_U, Index m, bool init_lambda, Number* lambda) + { + // Only initial values for x provided. + assert(init_x == true); + assert(init_z == false); + assert(init_lambda == false); + + // Initialize optimization parameters x + for (IdxT i = 0; i < model_->sizeParams(); ++i) + x[i] = model_->param()[i]; + + return true; + } + + template + bool DynamicObjective::eval_f(Index n, const Number* x, bool new_x, Number& obj_value) + { + // Update optimization parameters + for (IdxT i = 0; i < model_->sizeParams(); ++i) + model_->param()[i] = x[i]; + + // Evaluate objective function + integrator_->getSavedInitialCondition(); + integrator_->initializeSimulation(t_init_); + integrator_->initializeQuadrature(); + integrator_->runSimulationQuadrature(t_final_, nout_); + + // Assuming objective function is given as the integral (quadrature) 0 + obj_value = (integrator_->getIntegral())[0]; + + return true; + } + + template + bool DynamicObjective::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f) + { + assert(model_->sizeParams() == static_cast(n)); + // Update optimization parameters + for (IdxT i = 0; i < model_->sizeParams(); ++i) + model_->param()[i] = x[i]; + + // evaluate the gradient of the objective function grad_{x} f(x) + // This is creating and deleting adjoint system for each iteration! + // Currently there is no more efficient solution. + integrator_->initializeAdjoint(); + + integrator_->getSavedInitialCondition(); + integrator_->initializeSimulation(t_init_); + integrator_->initializeQuadrature(); + integrator_->runForwardSimulation(t_final_, nout_); + + integrator_->initializeBackwardSimulation(t_final_); + integrator_->runBackwardSimulation(t_init_); + + // For now assumes only one forward integrand and multiple optimization parameters. + for (IdxT i = 0; i < model_->sizeParams(); ++i) + grad_f[i] = -((integrator_->getAdjointIntegral())[i]); + + integrator_->deleteAdjoint(); + + return true; + } + + template + bool DynamicObjective::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g) + { + return true; + } + + template + bool DynamicObjective::eval_jac_g(Index n, const Number* x, bool new_x, Index m, Index nele_jac, Index* iRow, Index* jCol, Number* values) + { + return true; + } + + template + bool DynamicObjective::eval_h(Index n, const Number* x, bool new_x, Number obj_factor, Index m, const Number* lambda, bool new_lambda, Index nele_hess, Index* iRow, Index* jCol, Number* values) + { + return true; + } + + template + void DynamicObjective::finalize_solution(SolverReturn status, + Index n, + const Number* x, + const Number* z_L, + const Number* z_U, + Index m, + const Number* g, + const Number* lambda, + Number obj_value, + const IpoptData* ip_data, + IpoptCalculatedQuantities* ip_cq) + { + } + + template class DynamicObjective; + template class DynamicObjective; + + } // namespace IpoptInterface +} // namespace AnalysisManager diff --git a/src/Solver/Optimization/DynamicObjective.hpp b/src/Solver/Optimization/DynamicObjective.hpp new file mode 100644 index 000000000..b7a8d9ad0 --- /dev/null +++ b/src/Solver/Optimization/DynamicObjective.hpp @@ -0,0 +1,87 @@ + +#ifndef _IPOPT_DYNAMIC_OBJECTIVE_HPP_ +#define _IPOPT_DYNAMIC_OBJECTIVE_HPP_ + +#include "OptimizationSolver.hpp" +#include + +namespace AnalysisManager +{ + + namespace IpoptInterface + { + + /** + * Implementation of Ipopt's pure virtual TNLP class. + * + * TNLP defines Ipopt's interface to the model. This is in fact + * the model evaluator interface to Ipopt. In this case however, + * the model evaluator calls dynamic solver to compute the objective + * and the gradient. + * + */ + template + class DynamicObjective : public Ipopt::TNLP, public OptimizationSolver + { + using OptimizationSolver::integrator_; + using OptimizationSolver::model_; + + typedef typename GridKit::ScalarTraits::real_type real_type; + + typedef Ipopt::Index Index; + typedef Ipopt::Number Number; + typedef Ipopt::SolverReturn SolverReturn; + typedef Ipopt::IpoptCalculatedQuantities IpoptCalculatedQuantities; + typedef Ipopt::IpoptData IpoptData; + + public: + DynamicObjective(Sundials::Ida* integrator); + virtual ~DynamicObjective(); + + /// Returns sizes of the model components + virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g, Index& nnz_h_lag, IndexStyleEnum& index_style); + + /// Returns problem bounds + virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u, Index m, Number* g_l, Number* g_u); + + /// Initialize optimization + virtual bool get_starting_point(Index n, bool init_x, Number* x, bool init_z, Number* z_L, Number* z_U, Index m, bool init_lambda, Number* lambda); + + /// Evaluate objective + virtual bool eval_f(Index n, const Number* x, bool new_x, Number& obj_value); + + /// Evaluate objective gradient + virtual bool eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f); + + /// Evaluate constraint residuals (not used here) + virtual bool eval_g(Index n, const Number* x, bool new_x, Index m, Number* g); + + /// Evaluate Jacobian (not used here) + virtual bool eval_jac_g(Index n, const Number* x, bool new_x, Index m, Index nele_jac, Index* iRow, Index* jCol, Number* values); + + /// Evaluate Hessian (have Ipopt estimate Hessian) + virtual bool eval_h(Index n, const Number* x, bool new_x, Number obj_factor, Index m, const Number* lambda, bool new_lambda, Index nele_hess, Index* iRow, Index* jCol, Number* values); + + /// Postprocessing of the results (not used here) + virtual void finalize_solution(SolverReturn status, + Index n, + const Number* x, + const Number* z_L, + const Number* z_U, + Index m, + const Number* g, + const Number* lambda, + Number obj_value, + const IpoptData* ip_data, + IpoptCalculatedQuantities* ip_cq); + + private: + real_type t_init_; + real_type t_final_; + int nout_; + }; + + } // namespace IpoptInterface +} // namespace AnalysisManager + +#endif // _IPOPT_DYNAMIC_OBJECTIVE_HPP_ diff --git a/src/Solver/Optimization/OptimizationSolver.hpp b/src/Solver/Optimization/OptimizationSolver.hpp new file mode 100644 index 000000000..6203b4fb9 --- /dev/null +++ b/src/Solver/Optimization/OptimizationSolver.hpp @@ -0,0 +1,37 @@ + +#ifndef _OPTIMIZATION_SOLVER_HPP_ +#define _OPTIMIZATION_SOLVER_HPP_ + +#include "Model/Evaluator.hpp" +#include + +namespace AnalysisManager +{ + template + class DynamicSolver; + + template + class OptimizationSolver + { + public: + OptimizationSolver() + { + } + + OptimizationSolver(Sundials::Ida* integrator) + : integrator_(integrator) + { + } + + virtual ~OptimizationSolver() + { + } + + protected: + GridKit::Model::Evaluator* model_; + Sundials::Ida* integrator_; + }; + +} // namespace AnalysisManager + +#endif // _OPTIMIZATION_SOLVER_HPP_ diff --git a/src/Solver/SteadyState/CMakeLists.txt b/src/Solver/SteadyState/CMakeLists.txt new file mode 100644 index 000000000..164a46e2b --- /dev/null +++ b/src/Solver/SteadyState/CMakeLists.txt @@ -0,0 +1,14 @@ +# + +# [[ +# Author(s): +# - Cameron Rutherford +#]] + +gridkit_add_library(solvers_steady + SOURCES + Kinsol.cpp + LINK_LIBRARIES + PUBLIC SUNDIALS::kinsol + OUTPUT_NAME + gridkit_solvers_steady) diff --git a/src/Solver/SteadyState/Kinsol.cpp b/src/Solver/SteadyState/Kinsol.cpp new file mode 100644 index 000000000..ef39bf04e --- /dev/null +++ b/src/Solver/SteadyState/Kinsol.cpp @@ -0,0 +1,287 @@ + +/** + * @file Kinsol.cpp + * @author Slaven Peles + * + * Contains definition of interface to KINSOL nonlinear solver from + * SUNDIALS library. + * + */ + +#include "Kinsol.hpp" + +#include +#include + +#include // access to KINSOL func., consts. +#include // access to serial N_Vector +#include // access to dense SUNLinearSolver +#include // access to dense SUNMatrix + +#include "Model/Evaluator.hpp" + +namespace AnalysisManager +{ + + namespace Sundials + { + + template + Kinsol::Kinsol(GridKit::Model::Evaluator* model) + : SteadyStateSolver(model) + { + int retval = 0; + + // Create the SUNDIALS context that all SUNDIALS objects require + retval = SUNContext_Create(SUN_COMM_NULL, &context_); + checkOutput(retval, "SUNContext"); + + solver_ = KINCreate(context_); + tag_ = NULL; + } + + template + Kinsol::~Kinsol() + { + SUNContext_Free(&context_); + KINFree(&solver_); + + N_VDestroy_Serial(this->yy_); + N_VDestroy_Serial(this->yy0_); + N_VDestroy_Serial(this->scale_); + + SUNMatDestroy(this->JacobianMat_); + SUNLinSolFree_Dense(this->linearSolver_); + + solver_ = 0; + } + + template + int Kinsol::configureSimulation() + { + int retval = 0; + + // Allocate solution vectors + yy_ = N_VNew_Serial(model_->size(), context_); + checkAllocation((void*) yy_, "N_VNew_Serial"); + + // Allocate scaling vector + scale_ = N_VClone(yy_); + checkAllocation((void*) scale_, "N_VClone"); + + // Create vectors to store restart initial condition + yy0_ = N_VClone(yy_); + checkAllocation((void*) yy0_, "N_VClone"); + + // Allocate and initialize KIN workspace + retval = KINInit(solver_, this->Residual, yy_); + checkOutput(retval, "KINInit"); + + // Set pointer to model data + retval = KINSetUserData(solver_, model_); + checkOutput(retval, "KINSetUserData"); + + // Set tolerances + sunrealtype fnormtol; ///< Residual tolerance + sunrealtype scsteptol; ///< Scaled step tolerance + + model_->setTolerances(fnormtol, scsteptol); ///< \todo Function name should be "getTolerances"! + retval = KINSetFuncNormTol(solver_, fnormtol); + checkOutput(retval, "KINSetFuncNormTol"); + + retval = KINSetScaledStepTol(solver_, scsteptol); + checkOutput(retval, "KINSetScaledStepTol"); + + // Set up linear solver + JacobianMat_ = SUNDenseMatrix(model_->size(), model_->size(), context_); + checkAllocation((void*) JacobianMat_, "SUNDenseMatrix"); + + linearSolver_ = SUNLinSol_Dense(yy_, JacobianMat_, context_); + checkAllocation((void*) linearSolver_, "SUNLinSol_Dense"); + + retval = KINSetLinearSolver(solver_, linearSolver_, JacobianMat_); + checkOutput(retval, "KINSetLinearSolver"); + + return retval; + } + + template + int Kinsol::configureLinearSolver() + { + int retval = 0; + + // Set up linear solver + JacobianMat_ = SUNDenseMatrix(model_->size(), model_->size(), context_); + checkAllocation((void*) JacobianMat_, "SUNDenseMatrix"); + + linearSolver_ = SUNLinSol_Dense(yy_, JacobianMat_, context_); + checkAllocation((void*) linearSolver_, "SUNLinSol_Dense"); + + retval = KINSetLinearSolver(solver_, linearSolver_, JacobianMat_); + checkOutput(retval, "KINSetLinearSolver"); + + return retval; + } + + template + int Kinsol::getDefaultInitialCondition() + { + model_->initialize(); + + copyVec(model_->y(), yy_); + + return 0; + } + + template + int Kinsol::runSimulation() + { + int retval = 0; + N_VConst(1.0, scale_); + retval = KINSol(solver_, yy_, KIN_LINESEARCH, scale_, scale_); + checkOutput(retval, "KINSol"); + // printOutput(tout); + // std::cout << "\n"; + return retval; + } + + template + int Kinsol::deleteSimulation() + { + SUNLinSolFree(linearSolver_); + KINFree(&solver_); + N_VDestroy(yy_); + N_VDestroy(scale_); + return 0; + } + + template + int Kinsol::Residual(N_Vector yy, N_Vector rr, void* user_data) + { + GridKit::Model::Evaluator* model = + static_cast*>(user_data); + + copyVec(yy, model->y()); + + model->evaluateResidual(); + const std::vector& f = model->getResidual(); + copyVec(f, rr); + + return 0; + } + + template + void Kinsol::copyVec(const N_Vector x, std::vector& y) + { + const ScalarT* xdata = NV_DATA_S(x); + for (unsigned int i = 0; i < y.size(); ++i) + { + y[i] = xdata[i]; + } + } + + template + void Kinsol::copyVec(const std::vector& x, N_Vector y) + { + ScalarT* ydata = NV_DATA_S(y); + for (unsigned int i = 0; i < x.size(); ++i) + { + ydata[i] = x[i]; + } + } + + template + void Kinsol::copyVec(const std::vector& x, N_Vector y) + { + ScalarT* ydata = NV_DATA_S(y); + for (unsigned int i = 0; i < x.size(); ++i) + { + if (x[i]) + ydata[i] = 1.0; + else + ydata[i] = 0.0; + } + } + + template + void Kinsol::printOutput() + { + sunrealtype* yval = N_VGetArrayPointer_Serial(yy_); + + std::cout << std::setprecision(5) << std::setw(7); + for (IdxT i = 0; i < model_->size(); ++i) + { + std::cout << yval[i] << " "; + } + std::cout << "\n"; + } + + template + void Kinsol::printSpecial(sunrealtype t, N_Vector y) + { + sunrealtype* yval = N_VGetArrayPointer_Serial(y); + IdxT N = N_VGetLength_Serial(y); + std::cout << "{"; + std::cout << std::setprecision(5) << std::setw(7) << t; + for (IdxT i = 0; i < N; ++i) + { + std::cout << ", " << yval[i]; + } + std::cout << "},\n"; + } + + template + void Kinsol::printFinalStats() + { + int retval = 0; + void* mem = solver_; + long int nni; + long int nfe; + long int nje; + long int nlfe; + + // retval = KINGetNumSteps(mem, &nst); + // checkOutput(retval, "KINGetNumSteps"); + retval = KINGetNumNonlinSolvIters(mem, &nni); + checkOutput(retval, "KINGetNumNonlinSolvIters"); + retval = KINGetNumFuncEvals(mem, &nfe); + checkOutput(retval, "KINGetNumFuncEvals"); + retval = KINGetNumJacEvals(mem, &nje); + checkOutput(retval, "KINGetNumJacEvals"); + retval = KINGetNumLinFuncEvals(mem, &nlfe); + checkOutput(retval, "KINGetNumLinFuncEvals"); + + // std::cout << "\nFinal Run Statistics: \n\n"; + std::cout << "Number of nonlinear iterations = " << nni << "\n"; + std::cout << "Number of function evaluations = " << nfe << "\n"; + std::cout << "Number of Jacobian evaluations = " << nje << "\n"; + std::cout << "Number of linear function evals. = " << nlfe << "\n"; + } + + template + void Kinsol::checkAllocation(void* v, const char* functionName) + { + if (v == NULL) + { + std::cerr << "\nERROR: Function " << functionName << " failed -- returned NULL pointer!\n\n"; + throw SundialsException(); + } + } + + template + void Kinsol::checkOutput(int retval, const char* functionName) + { + if (retval < 0) + { + std::cerr << "\nERROR: Function " << functionName << " failed with flag " << retval << "!\n\n"; + throw SundialsException(); + } + } + + // Compiler will prevent building modules with data type incompatible with sunrealtype + template class Kinsol; + template class Kinsol; + template class Kinsol; + + } // namespace Sundials +} // namespace AnalysisManager diff --git a/src/Solver/SteadyState/Kinsol.hpp b/src/Solver/SteadyState/Kinsol.hpp new file mode 100644 index 000000000..b4cb190a2 --- /dev/null +++ b/src/Solver/SteadyState/Kinsol.hpp @@ -0,0 +1,162 @@ + +/** + * @file Kinsol.hpp + * @author Slaven Peles + * + * Contains declaration of interface to KINSOL nonlinear solver from + * SUNDIALS library. + * + */ +#pragma once + +#include +#include + +#include +#include /* access to sparse SUNMatrix */ +// #include /* access to KLU linear solver */ +#include /* access to dense linear solver */ + +#include "Model/Evaluator.hpp" +#include "SteadyStateSolver.hpp" + +namespace AnalysisManager +{ + namespace Sundials + { + template + class Kinsol : public SteadyStateSolver + { + using SteadyStateSolver::model_; + + typedef typename GridKit::ScalarTraits::real_type real_type; + + public: + Kinsol(GridKit::Model::Evaluator* model); + ~Kinsol(); + + int configureSimulation(); + int configureLinearSolver(); + int getDefaultInitialCondition(); + // int setIntegrationTime(real_type t_init, real_type t_final, int nout); + // int initializeSimulation(); + int runSimulation(); + int deleteSimulation(); + + // int configureQuadrature(); + // int initializeQuadrature(); + // int runSimulationQuadrature(real_type tf, int nout=1); + // int deleteQuadrature(); + + // int configureAdjoint(); + // int configureLinearSolverBackward(); + // int initializeAdjoint(IdxT steps = 100); + // int initializeBackwardSimulation(real_type tf); + // int runForwardSimulation(real_type tf, int nout=1); + // int runBackwardSimulation(real_type t0); + // int deleteAdjoint(); + + int saveInitialCondition() + { + N_VScale(1.0, yy_, yy0_); + return 0; + } + + int getSavedInitialCondition() + { + N_VScale(1.0, yy0_, yy_); + return 0; + } + + // real_type getInitialTime() + // { + // return t_init_; + // } + + // real_type getFinalTime() + // { + // return t_final_; + // } + + // int getNumberOutputTimes() + // { + // return nout_; + // } + + // const real_type* getIntegral() const + // { + // return NV_DATA_S(q_); + // } + + // real_type* getIntegral() + // { + // return NV_DATA_S(q_); + // } + + // const real_type* getAdjointIntegral() const + // { + // return NV_DATA_S(qB_); + // } + + // real_type* getAdjointIntegral() + // { + // return NV_DATA_S(qB_); + // } + + void printOutput(); + void printSpecial(sunrealtype t, N_Vector x); + void printFinalStats(); + + private: + static int Residual(N_Vector yy, N_Vector rr, void* user_data); + + // static int Integrand(sunrealtype t, + // N_Vector yy, N_Vector yp, + // N_Vector rhsQ, void *user_data); + + // static int adjointResidual(sunrealtype t, + // N_Vector yy, N_Vector yp, + // N_Vector yyB, N_Vector ypB, + // N_Vector rrB, void *user_data); + + // static int adjointIntegrand(sunrealtype t, + // N_Vector yy, N_Vector yp, + // N_Vector yyB, N_Vector ypB, + // N_Vector rhsQB, void *user_data); + + private: + void* solver_; + SUNContext context_; + SUNMatrix JacobianMat_; + SUNLinearSolver linearSolver_; + + N_Vector yy_; ///< Solution vector + N_Vector scale_; ///< Scaling vector + N_Vector tag_; ///< Tags differential variables + N_Vector q_; ///< Integrand vector + + N_Vector yy0_; ///< Storage for initial values + + private: + // static void copyMat(Model::Evaluator::Mat& J, SlsMat Jida); + static void copyVec(const N_Vector x, std::vector& y); + static void copyVec(const std::vector& x, N_Vector y); + static void copyVec(const std::vector& x, N_Vector y); + + // int check_flag(void *flagvalue, const char *funcname, int opt); + inline void checkAllocation(void* v, const char* functionName); + inline void checkOutput(int retval, const char* functionName); + }; + + /// Simple exception to use within Kinsol class. + class SundialsException : public std::exception + { + virtual const char* what() const throw() + { + return "Method in Kinsol class failed!\n"; + } + }; + + } // namespace Sundials + +} // namespace AnalysisManager diff --git a/src/Solver/SteadyState/SteadyStateSolver.hpp b/src/Solver/SteadyState/SteadyStateSolver.hpp new file mode 100644 index 000000000..1ab27edc3 --- /dev/null +++ b/src/Solver/SteadyState/SteadyStateSolver.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "Model/Evaluator.hpp" + +namespace AnalysisManager +{ + template + class SteadyStateSolver + { + public: + SteadyStateSolver(GridKit::Model::Evaluator* model) + : model_(model) + { + } + + virtual ~SteadyStateSolver() + { + } + + GridKit::Model::Evaluator* getModel() + { + return model_; + } + + protected: + GridKit::Model::Evaluator* model_; + }; + +} // namespace AnalysisManager diff --git a/Utilities/CMakeLists.txt b/src/Utilities/CMakeLists.txt similarity index 99% rename from Utilities/CMakeLists.txt rename to src/Utilities/CMakeLists.txt index aba0c614f..3bd96fc96 100644 --- a/Utilities/CMakeLists.txt +++ b/src/Utilities/CMakeLists.txt @@ -2,4 +2,3 @@ add_library(Utilities INTERFACE) target_include_directories(Utilities INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) add_library(GRIDKIT::Utilities ALIAS Utilities) - diff --git a/src/Utilities/FileIO.hpp b/src/Utilities/FileIO.hpp new file mode 100644 index 000000000..217c93fa6 --- /dev/null +++ b/src/Utilities/FileIO.hpp @@ -0,0 +1,385 @@ + +/** + * @file FileIO.hpp + * @author Slaven Peles + * + * Contains definition of a utility for reading lookup tables. + * + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace +{ + + using namespace GridKit; + using namespace GridKit::PowerSystemData; + + static const std::string matlab_syntax_error{ + "Only a subset of Matlab syntax is supported." + "\n\t'=' for assignment must be on the same line as the field, eg " + "`mpc.version = '2'`." + "\n\tOpen brace ('[') must be on the same line as the field for matrix " + "initialization." + "\n\tEach row of a matrix must be terminated by a semicolon."}; + + std::ostream& logs() + { +#ifndef NDEBUG + std::cerr << "[FileIO.hpp]: "; + return std::cerr; +#else + static std::ofstream ofs; + ofs.setstate(std::ios_base::badbit); + return ofs; +#endif + } + + void ltrim(std::string& s) + { + const std::string nothing = ""; + s = std::regex_replace(s, std::regex("^\\s+"), nothing); + } + + void rtrim(std::string& s) + { + const std::string nothing = ""; + s = std::regex_replace(s, std::regex("\\s+$"), nothing); + } + + void trim_matlab_comments(std::string& s) + { + const std::string nothing = ""; + s = std::regex_replace(s, std::regex("%.+"), nothing); + } + + // Retrive MATPOWER component from assignment line. + // + // For example, the string " mpc.bus = [ ... ] % Some comment" will + // return the value "bus". + std::string getMatPowerComponent(const std::string& line) + { + logs() << "Getting matpower component from line\n"; + std::regex pat("mpc.([a-zA-Z]+)\\s*=.+"); + std::smatch matches; + std::string component; + if (std::regex_match(line, matches, pat)) + { + component = matches[1].str(); + } + else + { + throw std::runtime_error(matlab_syntax_error + "\nGot line " + line); + } + ltrim(component); + rtrim(component); + return component; + } + + // Ensure that all of the given line has been consumed, and that the only + // remaining non-whitespace character left in the line is a semicolon. + void checkEndOfMatrixRow(std::istream& is) + { + std::string rest; + is >> rest; + ltrim(rest); + rtrim(rest); + if (rest != ";") + throw std::runtime_error(matlab_syntax_error); + } + + template + void readMatPowerBusRow(const std::string& row, BusData& br, LoadData& lr) + { + logs() << "Parsing MATPOWER bus row\n"; + std::stringstream is(row); + is >> br.bus_i // Bus ID + >> br.type // Bus type: 1 = PQ, 2 = PV, 3 = ref, 4 = isolated + >> lr.Pd // Active power demand [MW] + >> lr.Qd // Reactive power demand [MVAr] + >> br.Gs // Shunt conductance (MW demanded at V = 1.0 p.u.) + >> br.Bs // Shunt susceptance (MVAr injected at V = 1.0 p.u.) + >> br.area // Area number (>0) + >> br.Vm // Voltage magnitude (p.u.) + >> br.Va // Voltage phase (deg) + >> br.baseKV // Base voltage [kV] + >> br.zone // Loss zone number (>0) + >> br.Vmax // Maximum voltage magnitude (p.u.) + >> br.Vmin; // Minimum voltage magnitude (p.u.) + + lr.bus_i = br.bus_i; + + // std::cout << br.str(); + // logs() << "Read BusData with the following values:\n" << br.str(); + // return br; + } + + template + void readMatPowerGenRow(GenData& gr, std::string& row) + { + logs() << "Parsing MATPOWER gen row\n"; + std::stringstream is(row); + is >> gr.bus >> gr.Pg >> gr.Qg >> gr.Qmax >> gr.Qmin >> gr.Vg >> gr.mBase + >> gr.status >> gr.Pmax >> gr.Pmin >> gr.Pc1 >> gr.Pc2 >> gr.Qc1min + >> gr.Qc1max >> gr.Qc2min >> gr.Qc2max >> gr.ramp_agc >> gr.ramp_10 + >> gr.ramp_30 >> gr.ramp_q >> gr.apf; + checkEndOfMatrixRow(is); + } + + template + void readMatPowerBranchRow(BranchData& br, std::string& row) + { + logs() << "Parsing MATPOWER branch row\n"; + std::stringstream is(row); + is >> br.fbus >> br.tbus >> br.r >> br.x >> br.b >> br.rateA >> br.rateB + >> br.rateC >> br.ratio >> br.angle >> br.status >> br.angmin + >> br.angmax; + checkEndOfMatrixRow(is); + } + + template + void readMatPowerGenCostRow(GenCostData& gcr, std::string& row) + { + logs() << "Parsing MATPOWER gen cost row\n"; + // Ensure last character is semicolon. + rtrim(row); + if (row[row.size() - 1] != ';') + throw std::runtime_error(matlab_syntax_error + "\nGot line " + row); + + std::stringstream is(row); + is >> gcr.kind >> gcr.startup >> gcr.shutdown >> gcr.n; + + for (RealT r; is >> r;) + { + gcr.rest.push_back(r); + } + } + + template + void readMatPowerVersion(SystemModelData& mp, std::string& line) + { + logs() << "Parsing matpower version\n"; + std::regex pat("mpc\\.version\\s*=\\s*'([0-9])';"); + std::smatch matches; + if (std::regex_match(line, matches, pat)) + { + mp.version = matches[1].str(); + } + else + { + throw std::runtime_error(matlab_syntax_error + "\nGot line '" + line + "'"); + } + } + + template + void readMatPowerBaseMVA(SystemModelData& mp, std::string& line) + { + std::regex pat("mpc\\.baseMVA\\s*=\\s*([0-9]+);"); + std::smatch matches; + if (std::regex_match(line, matches, pat)) + { + std::string s = matches[1]; + mp.baseMVA = std::atoi(s.c_str()); + } + else + { + throw std::runtime_error(matlab_syntax_error + "\nGot line '" + line + "'"); + } + } + +} // namespace + +namespace GridKit +{ + + /** + * @brief Reads in an input stream of tabulated data + * + * @todo needs to return int for file error codes + * + * @tparam ScalarT + * @param[out] table object in memory where the data from the input stream is + * @param[in] filename input stream to space and newline separated data + * @param[out] ti initial time returned + * @param[out] tf final time returned + * + * @pre Input stream should read space separated data. Rows are separated + * by new line. Each row od data must have the same number of entries. The + * first column of the data represents time and other columns time dependent + * variables. + */ + template + void setLookupTable(std::vector>& table, + std::istream& idata, + ScalarT& ti, + ScalarT& tf) + { + std::string line; + int oldwordcount = -1; + while (std::getline(idata, line)) + { + std::istringstream iss(line); + double word; + int wordcount = 0; + std::vector row; + while (iss >> word) + { + row.push_back(word); + ++wordcount; + } + table.push_back(std::move(row)); + if (oldwordcount != -1) + { + if (oldwordcount != wordcount) + { + std::cerr << "Corrupted input data!\n"; + return; + } + } + else + { + oldwordcount = wordcount; + } + } + + size_t N = table.size(); + if (N == 0) + { + // do nothing + } + else if (N == 1) + { + ti = table[0][0]; + tf = table[0][0]; + } + else + { + ti = table[0][0]; + tf = table[N - 1][0]; + } + } + + template + void printLookupTable(std::vector> const& table) + { + for (size_t i = 0; i < table.size(); ++i) + { + for (size_t j = 0; j < table[i].size(); ++j) + { + std::cout << table[i][j] << " "; + } + std::cout << "\n"; + } + } + + template + void readMatPowerFile(SystemModelData& mp, std::string& filename) + { + std::ifstream ifs{filename}; + readMatPower(mp, ifs); + } + + template + void readMatPower(SystemModelData& mp, std::istream& is) + { + using BusDataT = BusData; + using GenDataT = GenData; + using BranchDataT = BranchData; + using GenCostDataT = GenCostData; + using LoadDataT = LoadData; + + for (std::string line; std::getline(is, line);) + { + // Trim whitespace and remove comments + ltrim(line); + rtrim(line); + logs() << line << "\n"; + trim_matlab_comments(line); + + // Skip empty lines and comment-only lines + if (line.size() == 0) + continue; + + // Skip the matlab function declaration + if (line.find("function") != std::string::npos) + continue; + + // Check for MATPOWER component definitions + if (line.find("mpc") != std::string::npos) + { + const std::string component = getMatPowerComponent(line); + logs() << "Got component: '" << component << "'\n"; + // First, parse matrix components + if (component == "bus") + { + while (std::getline(is, line)) + { + if (line.find("];") != std::string::npos) + break; + BusDataT br; + LoadDataT lr; + readMatPowerBusRow(line, br, lr); + mp.bus.push_back(std::move(br)); + mp.load.push_back(std::move(lr)); + } + } + else if (component == "gen") + { + while (std::getline(is, line)) + { + if (line.find("];") != std::string::npos) + break; + GenDataT gr; + readMatPowerGenRow(gr, line); + mp.gen.push_back(gr); + } + } + else if (component == "branch") + { + while (std::getline(is, line)) + { + if (line.find("];") != std::string::npos) + break; + BranchDataT br; + readMatPowerBranchRow(br, line); + mp.branch.push_back(br); + } + } + else if (component == "gencost") + { + while (std::getline(is, line)) + { + if (line.find("];") != std::string::npos) + break; + GenCostDataT gcr; + readMatPowerGenCostRow(gcr, line); + mp.gencost.push_back(gcr); + } + } + + // Next, parse scalar components + else if (component == "version") + { + readMatPowerVersion(mp, line); + } + else if (component == "baseMVA") + { + readMatPowerBaseMVA(mp, line); + } + } + } + } + +} // namespace GridKit diff --git a/src/Utilities/TestHelpers.hpp b/src/Utilities/TestHelpers.hpp new file mode 100644 index 000000000..d8e876c04 --- /dev/null +++ b/src/Utilities/TestHelpers.hpp @@ -0,0 +1,270 @@ + +/** + * @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 Colors + + 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 new file mode 100644 index 000000000..ce57d2c5f --- /dev/null +++ b/src/Utilities/Testing.hpp @@ -0,0 +1,225 @@ +/** + * @file Testing.hpp + * @author Slaven Peles + * + * Contains utilies for testing. + * + */ +#pragma once + +#include +#include +#include + +#include + +namespace +{ + + static constexpr double tol_ = 1e-8; + + inline std::ostream& errs() + { + std::cerr << "[Utils/Testing.hpp]: "; + return std::cerr; + } + +} // namespace + +namespace GridKit +{ + namespace Testing + { + + 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, + PowerSystemData::GenCostData b, + RealT tol = tol_) + { + (void) tol; // suppress warning + int fail = 0; + fail += a.kind != b.kind; + fail += a.startup != b.startup; + fail += a.shutdown != b.shutdown; + fail += a.n != b.n; + if (fail) + { + errs() << "Got failure!\na=" << a.str() << "\nb=" << b.str(); + } + return fail == 0; + } + + template + inline bool isEqual(PowerSystemData::GenData a, + PowerSystemData::GenData b, + RealT tol = tol_) + { + int fail = 0; + + fail += a.bus != b.bus; + fail += !isEqual(a.Pg, b.Pg, tol); + fail += !isEqual(a.Qg, b.Qg, tol); + fail += !isEqual(a.Qmax, b.Qmax, tol); + fail += !isEqual(a.Qmin, b.Qmin, tol); + fail += !isEqual(a.Vg, b.Vg, tol); + fail += a.mBase != b.mBase; + fail += a.status != b.status; + fail += a.Pmax != b.Pmax; + fail += a.Pmin != b.Pmin; + fail += a.Pc1 != b.Pc1; + fail += a.Pc2 != b.Pc2; + fail += a.Qc1min != b.Qc1min; + fail += a.Qc1max != b.Qc1max; + fail += a.Qc2min != b.Qc2min; + fail += a.Qc2max != b.Qc2max; + fail += a.ramp_agc != b.ramp_agc; + fail += a.ramp_10 != b.ramp_10; + fail += a.ramp_30 != b.ramp_30; + fail += a.ramp_q != b.ramp_q; + fail += a.apf != b.apf; + + if (fail) + { + errs() << "Got failure!\na=" << a.str() << "\nb=" << b.str(); + } + return fail == 0; + } + + template + inline bool isEqual(PowerSystemData::BusData a, + PowerSystemData::BusData b, + RealT tol = tol_) + { + int fail = 0; + + fail += a.bus_i != b.bus_i; + fail += a.type != b.type; + fail += a.Gs != b.Gs; + fail += a.Bs != b.Bs; + fail += a.area != b.area; + fail += !isEqual(a.Vm, b.Vm, tol); + fail += !isEqual(a.Va, b.Va, tol); + fail += a.baseKV != b.baseKV; + fail += a.zone != b.zone; + fail += !isEqual(a.Vmax, b.Vmax, tol); + fail += !isEqual(a.Vmin, b.Vmin, tol); + + if (fail) + { + errs() << "bus_i: a=" << a.bus_i << ", b=" << b.bus_i << "\n" + << "type: a=" << a.type << ", b=" << b.type << "\n" + << "Gs: a=" << a.Gs << ", b=" << b.Gs << "\n" + << "Bs: a=" << a.Bs << ", b=" << b.Bs << "\n" + << "area: a=" << a.area << ", b=" << b.area << "\n" + << "Vm: a=" << a.Vm << ", b=" << b.Vm << "\n" + << "Va: a=" << a.Va << ", b=" << b.Va << "\n" + << "baseKV: a=" << a.baseKV << ", b=" << b.baseKV << "\n" + << "zone: a=" << a.zone << ", b=" << b.zone << "\n" + << "Vmax: a=" << a.Vmax << ", b=" << b.Vmax << "\n" + << "Vmin: a=" << a.Vmin << ", b=" << b.Vmin << "\n"; + } + return fail == 0; + } + + template + inline bool isEqual(PowerSystemData::LoadData a, + PowerSystemData::LoadData b, + RealT tol = tol_) + { + int fail = 0; + + fail += a.bus_i != b.bus_i; + fail += !isEqual(a.Pd, b.Pd, tol); + fail += !isEqual(a.Qd, b.Qd, tol); + + if (fail) + { + errs() << "bus_i: a=" << a.bus_i << ", b=" << b.bus_i << "\n" + << "Pd: a=" << a.Pd << ", b=" << b.Pd << "\n" + << "Qd: a=" << a.Qd << ", b=" << b.Qd << "\n"; + } + return fail == 0; + } + + template + inline bool isEqual(PowerSystemData::BranchData a, + PowerSystemData::BranchData b, + RealT tol = tol_) + { + int fail = 0; + + fail += a.fbus != b.fbus; + fail += a.tbus != b.tbus; + fail += !isEqual(a.r, b.r, tol); + fail += !isEqual(a.x, b.x, tol); + fail += !isEqual(a.b, b.b, tol); + fail += a.rateA != b.rateA; + fail += a.rateB != b.rateB; + fail += a.rateC != b.rateC; + fail += a.ratio != b.ratio; + fail += a.angle != b.angle; + fail += a.status != b.status; + fail += a.angmin != b.angmin; + fail += a.angmax != b.angmax; + + if (fail) + { + errs() << "Got failure!\na=" << a.str() << "\nb=" << b.str(); + } + return fail == 0; + } + + template + inline bool isEqual(std::vector a, std::vector b, double tol = tol_) + { + if (a.size() != b.size()) + throw std::runtime_error([&] + { + std::stringstream errs; + errs << "Containers do not have the same size!\n" + << "\tGot a.size() == " << a.size() << "\n" + << "\tGot b.size() == " << b.size() << "\n"; + return errs.str(); }()); + + int fail = 0; + for (std::size_t i = 0; i < a.size(); i++) + { + if (!isEqual(a[i], b[i], tol)) + { + fail++; + errs() << "[isEqual>]: Got failure with i=" << i << ".\n"; + } + } + + return fail == 0; + } + + template + inline bool isEqual(PowerSystemData::SystemModelData a, + PowerSystemData::SystemModelData b) + { + int fail = 0; + + fail += a.version != b.version; + fail += a.baseMVA != b.baseMVA; + fail += !isEqual(a.bus, b.bus); + fail += !isEqual(a.gen, b.gen); + fail += !isEqual(a.gencost, b.gencost); + fail += !isEqual(a.branch, b.branch); + fail += !isEqual(a.load, b.load); + + return fail == 0; + } + + } // namespace Testing + +} // namespace GridKit 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..034023832 --- /dev/null +++ b/tests/UnitTests/CMakeLists.txt @@ -0,0 +1,3 @@ +# +add_subdirectory(PhasorDynamics) +add_subdirectory(SparsityPattern) diff --git a/tests/UnitTests/PhasorDynamics/BranchTests.hpp b/tests/UnitTests/PhasorDynamics/BranchTests.hpp new file mode 100644 index 000000000..81e2c48eb --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/BranchTests.hpp @@ -0,0 +1,145 @@ +#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..0ba50587c --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/BusTests.hpp @@ -0,0 +1,101 @@ +#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..18876a998 --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/CMakeLists.txt @@ -0,0 +1,38 @@ +# [[ +# 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_executable(test_phasor_genrou runGenrouTests.cpp) +target_link_libraries(test_phasor_genrou GRIDKIT::phasor_dynamics_genrou + GRIDKIT::phasor_dynamics_bus) + + +add_executable(test_phasor_system runSystemTests.cpp) +target_link_libraries(test_phasor_system GRIDKIT::phasor_dynamics_load + GRIDKIT::phasor_dynamics_branch + GRIDKIT::phasor_dynamics_bus) + +add_test(NAME PhasorDynamicsBusTest COMMAND $) +add_test(NAME PhasorDynamicsBranchTest COMMAND $) +add_test(NAME PhasorDynamicsGenrouTest COMMAND $) +add_test(NAME PhasorDynamicsLoadTest COMMAND $) +add_test(NAME PhasorDynamicsSystemTest COMMAND $) + +install(TARGETS test_phasor_bus + test_phasor_branch + test_phasor_load + test_phasor_genrou + test_phasor_system RUNTIME DESTINATION bin) diff --git a/tests/UnitTests/PhasorDynamics/GenrouTests.hpp b/tests/UnitTests/PhasorDynamics/GenrouTests.hpp new file mode 100644 index 000000000..40e9feda4 --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/GenrouTests.hpp @@ -0,0 +1,63 @@ +#include +#include + +#include +#include +#include +#include +#include + +namespace GridKit +{ + namespace Testing + { + + template + class GenrouTests + { + private: + using real_type = typename PhasorDynamics::Component::real_type; + + public: + GenrouTests() = default; + ~GenrouTests() = default; + + TestOutcome constructor() + { + TestStatus success = true; + + auto* bus = new PhasorDynamics::Bus(1.0, 0.0); + + PhasorDynamics::Component* machine = + new PhasorDynamics::Genrou(bus, 1); + + success *= (machine != nullptr); + + if (machine) + { + delete machine; + } + delete bus; + + return success.report(__func__); + } + + TestOutcome residual() + { + TestStatus success = true; + success.skipTest(); + + return success.report(__func__); + } + + TestOutcome accessors() + { + TestStatus success = true; + success.skipTest(); + + return success.report(__func__); + } + }; // class GenrouTest + + } // namespace Testing +} // namespace GridKit diff --git a/tests/UnitTests/PhasorDynamics/LoadTests.hpp b/tests/UnitTests/PhasorDynamics/LoadTests.hpp new file mode 100644 index 000000000..7a9688bc8 --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/LoadTests.hpp @@ -0,0 +1,71 @@ +#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/SystemTests.hpp b/tests/UnitTests/PhasorDynamics/SystemTests.hpp new file mode 100644 index 000000000..ea1cf7f29 --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/SystemTests.hpp @@ -0,0 +1,97 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace GridKit +{ + namespace Testing + { + template + class SystemTests + { + private: + using real_type = typename PhasorDynamics::Component::real_type; + + public: + SystemTests() = default; + ~SystemTests() = default; + + /// Constructor, allocation, and initialization checks + TestOutcome constructor() + { + TestStatus success = true; + + // ScalarT Vr{1.0}; + // ScalarT Vi{2.0}; + + PhasorDynamics::SystemModel* system = nullptr; + + // Create an empty system + system = new PhasorDynamics::SystemModel(); + + success *= (system != nullptr); + + if (system) + { + delete system; + } + + return success.report(__func__); + } + + TestOutcome composer() + { + 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 + + // Create an empty system model + PhasorDynamics::SystemModel system; + + // Add a bus + PhasorDynamics::BusInfinite bus1(Vr1, Vi1); + system.addBus(&bus1); + + // Add a bus + PhasorDynamics::BusInfinite bus2(Vr2, Vi2); + system.addBus(&bus1); + + PhasorDynamics::Branch branch(&bus1, &bus2, R, X, G, B); + system.addComponent(&branch); + + system.allocate(); + system.initialize(); + system.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__); + } + }; + + } // namespace Testing +} // namespace GridKit diff --git a/tests/UnitTests/PhasorDynamics/runBranchTests.cpp b/tests/UnitTests/PhasorDynamics/runBranchTests.cpp new file mode 100644 index 000000000..b70a39ff1 --- /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(); +} diff --git a/tests/UnitTests/PhasorDynamics/runBusTests.cpp b/tests/UnitTests/PhasorDynamics/runBusTests.cpp new file mode 100644 index 000000000..c7063318d --- /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(); +} diff --git a/tests/UnitTests/PhasorDynamics/runGenrouTests.cpp b/tests/UnitTests/PhasorDynamics/runGenrouTests.cpp new file mode 100644 index 000000000..0570a73c8 --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/runGenrouTests.cpp @@ -0,0 +1,14 @@ +#include "GenrouTests.hpp" + +int main() +{ + GridKit::Testing::TestingResults result; + + GridKit::Testing::GenrouTests test; + + result += test.constructor(); + result += test.accessors(); + result += test.residual(); + + return result.summary(); +} diff --git a/tests/UnitTests/PhasorDynamics/runLoadTests.cpp b/tests/UnitTests/PhasorDynamics/runLoadTests.cpp new file mode 100644 index 000000000..7ad3daf0b --- /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(); +} diff --git a/tests/UnitTests/PhasorDynamics/runSystemTests.cpp b/tests/UnitTests/PhasorDynamics/runSystemTests.cpp new file mode 100644 index 000000000..25519f618 --- /dev/null +++ b/tests/UnitTests/PhasorDynamics/runSystemTests.cpp @@ -0,0 +1,15 @@ +#include "SystemTests.hpp" + +int main() +{ + using namespace GridKit; + using namespace GridKit::Testing; + + GridKit::Testing::TestingResults result; + GridKit::Testing::SystemTests test; + + result += test.constructor(); + result += test.composer(); + + return result.summary(); +} diff --git a/tests/UnitTests/SparsityPattern/CMakeLists.txt b/tests/UnitTests/SparsityPattern/CMakeLists.txt new file mode 100644 index 000000000..c4c9cc854 --- /dev/null +++ b/tests/UnitTests/SparsityPattern/CMakeLists.txt @@ -0,0 +1,14 @@ +# [[ +# Author(s): +# - Slaven Peles +#]] + + +add_executable(test_sparsity_pattern runSparsityPatternTests.cpp) +target_link_libraries(test_sparsity_pattern GRIDKIT::phasor_dynamics_bus) + + +add_test(NAME SparsityPatternTest COMMAND $) + +install(TARGETS test_sparsity_pattern + RUNTIME DESTINATION bin) diff --git a/tests/UnitTests/SparsityPattern/SparsityPatternTests.hpp b/tests/UnitTests/SparsityPattern/SparsityPatternTests.hpp new file mode 100644 index 000000000..c836f961b --- /dev/null +++ b/tests/UnitTests/SparsityPattern/SparsityPatternTests.hpp @@ -0,0 +1,88 @@ +#include +#include + +#include +#include +#include + +namespace GridKit +{ + namespace Testing + { + template + class SparsityPatternTests + { + public: + SparsityPatternTests() = default; + ~SparsityPatternTests() = default; + + /// Constructor, allocation, and initialization checks + TestOutcome variable() + { + TestStatus success = true; + + const size_t n = 3; + std::vector x(n), p(n), f(n); + + // decide x, y, and z are variables + for (size_t i = 0; i < n; ++i) + x[i].setVariableNumber(i); + + // ...and sigma, rho, and beta are constant parameters + for (size_t i = 0; i < n; ++i) + p[i].setFixed(true); + + // initialize independent variables + x[0]() = 8.0; + x[1]() = 20.0; + x[2]() = 2.0 / 3.0; + + // set constant parameter values + p[0] = 10.0; + p[1] = 8.0 / 3.0; + p[2] = 28.0; + + // The residualFunction computes f + residualFunction(f, x, p); + + // Check dependenices of f[0] (depends on x[0] and x[1]) + { + const Sparse::Variable::DependencyMap& dependencies = + (f[0]).getDependencies(); + + success *= (dependencies.size() == 2); + success *= (dependencies.find(0) != dependencies.end()); + success *= (dependencies.find(1) != dependencies.end()); + success *= (dependencies.find(2) == dependencies.end()); + } + + // Check dependencies of f[2] (depends on x[0], x[1], x[2]) + { + const Sparse::Variable::DependencyMap& dependencies = + (f[2]).getDependencies(); + + success *= (dependencies.size() == 3); + success *= (dependencies.find(0) != dependencies.end()); + success *= (dependencies.find(1) != dependencies.end()); + success *= (dependencies.find(2) != dependencies.end()); + } + + return success.report(__func__); + } + + private: + template + void residualFunction(std::vector& f, + const std::vector& x, + const std::vector& p) + { + const T u = x[0] * x[1]; + + f[0] = p[0] * (x[1] - x[0]); // sigma*(y - x) + f[1] = x[0] * (p[1] - x[2]) - x[1]; // x*(rho - z) - y + f[2] = u - p[2] * x[2]; // x*y - beta*z + } + }; + + } // namespace Testing +} // namespace GridKit diff --git a/tests/UnitTests/SparsityPattern/runSparsityPatternTests.cpp b/tests/UnitTests/SparsityPattern/runSparsityPatternTests.cpp new file mode 100644 index 000000000..782148f2c --- /dev/null +++ b/tests/UnitTests/SparsityPattern/runSparsityPatternTests.cpp @@ -0,0 +1,14 @@ +#include "SparsityPatternTests.hpp" + +int main() +{ + using namespace GridKit; + using namespace GridKit::Testing; + + GridKit::Testing::TestingResults result; + GridKit::Testing::SparsityPatternTests test; + + result += test.variable(); + + return result.summary(); +}