├── .github └── pull_request_template.md ├── .gitignore ├── .travis.yml ├── .travis └── key.enc ├── COPYING ├── README.md ├── dependencyCheck.m ├── docs ├── _static │ ├── WecOptToolFlowChart.svg │ ├── WecOptToolFlowChartCode.svg │ ├── WecOptTool_algorithmDiagram.svg │ ├── WecOptTool_webinar_2020_09_29.pdf │ ├── example_meshes.svg │ ├── example_optimplotfval.svg │ ├── example_rm3Parametric.svg │ ├── example_spectra.svg │ ├── example_spectralPowerPlot.svg │ └── theme_overrides.css ├── conf.py ├── contents.rst ├── index.rst └── user │ ├── 1setup.rst │ ├── 2optimization.rst │ ├── 3model.rst │ ├── 4cite.rst │ ├── 5resources.rst │ ├── 6api.rst │ ├── 7license.rst │ ├── 8references.rst │ └── WecOptTool_refs.bib ├── examples ├── RM3 │ ├── RM3_BEM.mat │ ├── basic.m │ ├── designDevice.m │ ├── optimization.m │ └── simulateDevice.m └── WaveBot │ ├── Performance.m │ ├── README.md │ ├── WaveBot_caseA.m │ ├── WaveBot_caseB.m │ ├── WaveBot_caseC.m │ ├── designDevice.m │ └── simulateDevice.m ├── installNemoh.m ├── runTests.m ├── tests ├── AutoFolderMule.m ├── AutoFolderTest.m ├── PlotsTest.m ├── SeaStateTest.m ├── base │ └── TempFolderTest.m ├── examples │ ├── RM3 │ │ ├── ExamplesTest.m │ │ ├── ParametricTest.m │ │ ├── optionsTest.m │ │ └── parametricBugTest.m │ └── WaveBot │ │ └── ExamplesTest.m ├── math │ └── bisectionTest.m ├── meshes.mat ├── meshsolver │ ├── getNemohCylinderTest.m │ ├── getNemohSphereTest.m │ └── getNemohTest.m ├── scriptsTest.m ├── system │ ├── getFoldersTest.m │ ├── hasToolboxTest.m │ ├── isParallelTest.m │ ├── readConfigTest.m │ └── writeConfigTest.m ├── testHydrodynamics.m └── validation │ ├── mustBeEqualLengthTest.m │ └── mustBeFunctionHandleTest.m └── toolbox └── +WecOptTool ├── +base ├── Mesher.m ├── NEMOH.m ├── Solver.m └── TempFolder.m ├── +geometry └── existingNEMOH.m ├── +math ├── bisection.m └── isClose.m ├── +mesh └── AxiMesh.m ├── +plot ├── plotMesh.m └── powerPerFreq.m ├── +solver ├── NEMOH.m ├── nemohcalbody.txt ├── nemohcalfooter.txt └── nemohcalheader.txt ├── +system ├── getFolders.m ├── getSrcRootPath.m ├── getUserPath.m ├── hasToolbox.m ├── isParallel.m ├── readConfig.m ├── rmdirRetry.m └── writeConfig.m ├── +validation ├── mustBeEqualLength.m └── mustBeFunctionHandle.m ├── +vendor └── +WEC_Sim │ ├── LICENSE │ ├── NOTICE │ ├── Normalize.m │ └── Read_NEMOH.m ├── AutoFolder.m ├── Hydrodynamics.m ├── SeaState.m ├── data ├── 8spectra.mat └── spectrum.mat ├── mesh.m └── solver.m /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Please include a summary of the change and which (if any) issue is fixed. 4 | 5 | Fixes # (issue) 6 | 7 | ## Checklist: 8 | 9 | - [ ] All new files contain the GPL header 10 | - [ ] If `examples/RM3/optimization.m` has been modified, the content / line 11 | numbers in `docs/user/optimization.rst` are still valid or have been fixed 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.aux 2 | *.fls 3 | *.lof 4 | *.log 5 | *.out 6 | *.synctex.gz 7 | *.synctex 8 | *.blg 9 | *.lot 10 | *.bbl 11 | *.fdb_latexmk 12 | Thumbs.db 13 | *.DS_Store 14 | *.dvi 15 | *.tiw 16 | *.toc 17 | *.dmp 18 | *.bak 19 | *.tps 20 | *.tcp 21 | *.asv 22 | *.m~ 23 | *.spl 24 | *.orig 25 | 26 | # NEMOH 27 | ~nemoh_runs/ 28 | 29 | # Tests 30 | test_results/ 31 | test_results.pdf 32 | 33 | # local sphinx build folder 34 | docs/_build 35 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: minimal 3 | 4 | stages: 5 | - test 6 | - pages 7 | 8 | jobs: 9 | include: 10 | - stage: test 11 | language: matlab 12 | before_install: 13 | - sudo apt-get -y install gfortran 14 | install: 15 | - git clone --depth 1 https://github.com/LHEEA/Nemoh.git NEMOH 16 | - cd NEMOH 17 | - make 18 | - cd .. 19 | - matlab -batch "addpath(genpath('toolbox')), savepath pathdef.m;" 20 | - matlab -batch "installNemoh('$TRAVIS_BUILD_DIR/NEMOH/bin'), dependencyCheck;" 21 | script: 22 | - matlab -batch "results = runTests('reportHTML', false, 'reportPDF', false), assertSuccess(results);" 23 | if: branch = master 24 | - stage: pages 25 | language: python 26 | install: 27 | - pip install click colorama colorclass future "sphinx==1.8.5" "sphinxcontrib-bibtex==0.4.2" 28 | sphinx_rtd_theme sphinxcontrib-matlabdomain 29 | - pip install git+git://github.com/SuperKogito/sphinxcontrib-pdfembed 30 | - pip install https://github.com/H0R5E/sphinxcontrib-versioning/archive/v1.8.5_support.zip 31 | script: 32 | - eval "$(ssh-agent -s)"; touch .travis/key; chmod 0600 .travis/key 33 | - openssl aes-256-cbc -d -K $encrypted_c97e05834f48_key -iv $encrypted_c97e05834f48_iv < .travis/key.enc > .travis/key 34 | && ssh-add .travis/key # Use && to prevent ssh-add from prompting during pull requests. 35 | - git config --global user.email "builds@travis-ci.com" 36 | - git config --global user.name "Travis CI" 37 | - git remote set-url --push origin "git@github.com:$TRAVIS_REPO_SLUG" 38 | - sphinx-versioning push -abt -e .nojekyll -e README.md docs gh-pages . 39 | if: (branch = master AND type = push) OR tag IS present 40 | -------------------------------------------------------------------------------- /.travis/key.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SNL-WaterPower/WecOptTool-MATLAB/0a9faa189f8570444fac5ebe0da2a9fcd94958eb/.travis/key.enc -------------------------------------------------------------------------------- /dependencyCheck.m: -------------------------------------------------------------------------------- 1 | function dependencyCheck() 2 | % Check that all dependencies are licensed and installed 3 | 4 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 5 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 6 | % U.S. Government retains certain rights in this software. 7 | % 8 | % This file is part of WecOptTool. 9 | % 10 | % WecOptTool is free software: you can redistribute it and/or 11 | % modify it under the terms of the GNU General Public License as 12 | % published by the Free Software Foundation, either version 3 of 13 | % the License, or (at your option) any later version. 14 | % 15 | % WecOptTool is distributed in the hope that it will be useful, 16 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | % GNU General Public License for more details. 19 | % 20 | % You should have received a copy of the GNU General Public 21 | % License along with WecOptTool. If not, see 22 | % . 23 | 24 | import WecOptTool.system.hasToolbox 25 | 26 | allfoundflag = true; 27 | 28 | fprintf('\nWecOptTool Dependency Checker\n'); 29 | fprintf('-------------------------------\n'); 30 | 31 | %% Required Products 32 | 33 | fprintf('\n'); 34 | fprintf('Required\n'); 35 | fprintf('--------\n'); 36 | 37 | %% Optimisation Toolbox 38 | 39 | [optimBoxFound, ... 40 | optimBoxLicensed, ... 41 | optimBoxInstalled] = hasToolbox("Optimization_Toolbox", ... 42 | "Optimization Toolbox"); 43 | 44 | print_dependency("Optimization Toolbox", ... 45 | optimBoxInstalled, ... 46 | optimBoxLicensed); 47 | 48 | allfoundflag = allfoundflag && optimBoxFound; 49 | 50 | %% Nemoh 51 | 52 | nemohExistFlag = WecOptTool.base.NEMOH.isNemohInPath(); 53 | print_dependency("NEMOH", nemohExistFlag); 54 | 55 | %% Optional Products 56 | 57 | fprintf('\n'); 58 | fprintf('Optional\n'); 59 | fprintf('--------\n'); 60 | 61 | %% Parallel Computing Toolbox 62 | 63 | [~, ... 64 | parallelBoxLicensed, ... 65 | parallelBoxInstalled] = hasToolbox("Distrib_Computing_Toolbox", ... 66 | "Parallel Computing Toolbox"); 67 | 68 | print_dependency("Parallel Toolbox", ... 69 | parallelBoxInstalled, ... 70 | parallelBoxLicensed); 71 | 72 | %% Global Optimization Toolbox 73 | 74 | [~, ... 75 | globOptBoxLicensed, ... 76 | globOptBoxInstalled] = hasToolbox("GADS_Toolbox", ... 77 | "Global Optimization Toolbox"); 78 | 79 | print_dependency("Global Optimization Toolbox", ... 80 | globOptBoxInstalled, ... 81 | globOptBoxLicensed); 82 | 83 | %% WAFO 84 | 85 | wafoFunction = 'bretschneider'; 86 | wafoPath = fullfile('wafo', 'spec','bretschneider.m'); 87 | 88 | wafoCheck = lower(which(wafoFunction)); 89 | wafoInstalled = contains(wafoCheck, wafoPath) && ... 90 | (exist(wafoCheck, 'file') == 2); 91 | 92 | print_dependency("WAFO", wafoInstalled); 93 | 94 | %% End matter 95 | 96 | fprintf('\n') 97 | 98 | % Warn if execution not possible 99 | if ~allfoundflag 100 | warning("Mandatory dependencies are missing!") 101 | end 102 | 103 | end 104 | 105 | function print_dependency(name, installed, licensed, options) 106 | 107 | arguments 108 | name 109 | installed 110 | licensed = true 111 | options.columns = 45 112 | end 113 | 114 | name = name + ":"; 115 | 116 | if licensed && installed 117 | nChars = options.columns - 6; 118 | fprintf('%-*s Found\n', nChars, name); 119 | elseif ~licensed && installed 120 | nChars = options.columns - 11; 121 | fprintf('%-*s Unlicensed\n', nChars, name); 122 | else 123 | nChars = options.columns - 14; 124 | fprintf('%-*s Not Installed\n', nChars, name); 125 | end 126 | 127 | end 128 | -------------------------------------------------------------------------------- /docs/_static/WecOptTool_webinar_2020_09_29.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SNL-WaterPower/WecOptTool-MATLAB/0a9faa189f8570444fac5ebe0da2a9fcd94958eb/docs/_static/WecOptTool_webinar_2020_09_29.pdf -------------------------------------------------------------------------------- /docs/_static/theme_overrides.css: -------------------------------------------------------------------------------- 1 | /* override table width restrictions */ 2 | @media screen and (min-width: 767px) { 3 | 4 | .wy-table-responsive table td { 5 | /* !important prevents the common CSS stylesheets from overriding 6 | this as on RTD they are loaded after this stylesheet */ 7 | white-space: normal !important; 8 | } 9 | 10 | .wy-table-responsive { 11 | overflow: visible !important; 12 | } 13 | } 14 | 15 | li { 16 | text-align:left; 17 | } 18 | 19 | body { 20 | text-align:justify; 21 | } 22 | 23 | clickme { 24 | color: #2980b9; 25 | text-decoration: none; 26 | cursor: pointer; 27 | } 28 | -------------------------------------------------------------------------------- /docs/contents.rst: -------------------------------------------------------------------------------- 1 | .. toctree:: 2 | :maxdepth: 1 3 | :numbered: 4 | :caption: User Guide 5 | 6 | user/1setup 7 | user/2optimization 8 | user/3model 9 | user/4cite 10 | user/5resources 11 | user/6api 12 | user/7license 13 | user/8references 14 | 15 | .. toctree:: 16 | :hidden: 17 | :caption: External 18 | 19 | GitHub Repository 20 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ########## 2 | WecOptTool 3 | ########## 4 | 5 | The WEC Design Optimization MATLAB Toolbox (WecOptTool) allows users to perform wave energy converter (WEC) device design optimization studies while including different control strategies. 6 | In particular, this tool's key feature is the usage of a pseudo spectral solution method capable of dealing with both constraints and nonlinear dynamics. 7 | This allows for the optimization study to find the best possible power capture performance within the system constraints (e.g., maximum power take-off force). 8 | 9 | Applications of WecOptTool include design optimization studies of the `WaveBot`_ point absorber and `RM3`_ point absorber (see the :ref:`optimization` section for further details). 10 | These examples illustrate how WecOptTool can be applied to arbitrary devices of the user's choosing (see the :ref:`model` section). 11 | 12 | Developers 13 | ========== 14 | 15 | WecOptTool is developed by `Sandia National Laboratories`_, with support from `Data Only Greater`_. 16 | The developers would also like to acknowledge benefit from past collaborations with the `Oregon State University Design Engineering Lab`_. 17 | 18 | .. include:: contents.rst 19 | 20 | Sandia National Laboratories is a multi-mission laboratory managed and operated 21 | by National Technology and Engineering Solutions of Sandia, LLC., a wholly 22 | owned subsidiary of Honeywell International, Inc., for the U.S. Department of 23 | Energy's National Nuclear Security Administration under contract DE-NA0003525. 24 | 25 | .. _Data Only Greater: https://www.dataonlygreater.com 26 | .. _Oregon State University Design Engineering Lab: https://design.engr.oregonstate.edu 27 | .. _RM3: https://tethys-engineering.pnnl.gov/signature-projects/rm3-wave-point-absorber 28 | .. _Sandia National Laboratories: https://www.sandia.gov 29 | .. _WaveBot: https://tethys-engineering.pnnl.gov/signature-projects/advanced-wec-dynamics-controls -------------------------------------------------------------------------------- /docs/user/1setup.rst: -------------------------------------------------------------------------------- 1 | ***** 2 | Setup 3 | ***** 4 | 5 | Dependencies 6 | ============ 7 | 8 | The following table displays the required and optional dependencies for 9 | WecOptTool. 10 | 11 | .. table:: 12 | :widths: 35, 55, 10 13 | 14 | +----------------------+-------------------------------------------------------------+--------------+ 15 | | Dependency | Website | Required?\* | 16 | +======================+=============================================================+==============+ 17 | | MATLAB | https://www.mathworks.com/products/matlab.html | yes [#f1]_ | 18 | +----------------------+-------------------------------------------------------------+--------------+ 19 | | MATLAB Optimization | https://www.mathworks.com/products/optimization.html | yes | 20 | | Toolbox | | | 21 | +----------------------+-------------------------------------------------------------+--------------+ 22 | | NEMOH | https://github.com/LHEEA/Nemoh | yes | 23 | +----------------------+-------------------------------------------------------------+--------------+ 24 | | WAFO | https://github.com/wafo-project/wafo | optional | 25 | +----------------------+-------------------------------------------------------------+--------------+ 26 | | MATLAB Parallel | https://www.mathworks.com/products/parallel-computing.html | optional | 27 | | Computing Toolbox | | | 28 | +----------------------+-------------------------------------------------------------+--------------+ 29 | | MATLAB Global | https://www.mathworks.com/products/global-optimization.html | optional | 30 | | Optimization Toolbox | | | 31 | +----------------------+-------------------------------------------------------------+--------------+ 32 | 33 | \* The values in the Required column have the following meanings: 34 | * **yes** indicates dependencies that must be installed to use the 35 | WecOptTool toolbox 36 | * **optional** indicates dependencies that are used on a case by case basis, 37 | in the examples 38 | 39 | .. _user-setup-download: 40 | 41 | Download 42 | ======== 43 | 44 | .. raw:: html 45 | 46 |
Get the stable version
47 | 48 | The latest stable version of WecOptTool can be downloaded by clicking `HERE `__. 49 | 50 | Details of this and previous stable releases can be found in the `Releases `__ section of the GitHub repository. 51 | 52 | .. raw:: html 53 | 54 |

55 | 56 | .. raw:: html 57 | 58 |
Get the development version
59 | 60 | To get the latest development version of WecOptTool, clone or download the WecOptTool GitHub repository using the '`Clone or download `__' button. 61 | 62 | Note that, although the developers endeavor to ensure that the development version is not broken, bugs or unexpected behavior may occur, so please beware. 63 | 64 | Please see the "Contributing" section of the source code's `README.md`_ file for details on how to contribute to the code development. 65 | 66 | .. raw:: html 67 | 68 |

69 | 70 | Install 71 | ======= 72 | 73 | .. note:: 74 | Unexpected behavior may occur if multiple versions of the toolbox are installed. Please following the :ref:`user-setup-uninstall` instructions to uninstall any previous versions of WecOptTool first. 75 | 76 | #. **Download the WecOptTool software**: See the :ref:`user-setup-download` section. If required, unzip the archive to a path of your choosing (i.e. ``/path/to/WecOptTool``). |br| |br| 77 | 78 | #. **Add WecOptTool to your MATLAB path**: Add the WecOptTool toolbox to your MATLAB path using the MATLAB command prompt: 79 | 80 | .. code:: matlab 81 | 82 | >> addpath(genpath('/path/to/WecOptTool/toolbox')); 83 | >> savepath; 84 | 85 | Alternatively the "Set Path" graphical tool can be used to add the toolbox. 86 | |br| |br| 87 | 88 | #. **Prepare Nemoh**: Follow the OS dependent instructions for setting up 89 | NEMOH: 90 | 91 | .. raw:: html 92 | 93 |
Windows
94 | 95 | Executables are provided in the ‘Release’ directory of the NEMOH source code. 96 | These are installed into WecOptTool using the ``installNemoh.m`` MATLAB script, run from the WecOptTool root directory, using the MATLAB command prompt as follows: 97 | 98 | .. code:: matlab 99 | 100 | >> cd /path/to/WecOptTool 101 | >> installNemoh('/path/to/NEMOH/Release'); 102 | 103 | .. raw:: html 104 | 105 |

106 | 107 | .. raw:: html 108 | 109 |
Linux
110 | 111 | To set up NEMOH for Linux, first, use a command window to compile the executables (you will need gfortran or the Intel FORTRAN compiler): 112 | 113 | :: 114 | 115 | $ cd /path/to/NEMOH 116 | $ make 117 | 118 | Executables will be created a new directory called ‘bin’, which must then be installed into WecOptTool using the ``installNemoh.m`` MATLAB script, run from the WecOptTool root directory using the MATLAB command prompt: 119 | 120 | .. code:: matlab 121 | 122 | >> cd /path/to/WecOptTool 123 | >> installNemoh('/path/to/NEMOH/bin'); 124 | 125 | .. raw:: html 126 | 127 |

128 | 129 | #. **Verify dependencies installation:** You can verify that the dependencies have been installed correctly by running the 130 | ``dependencyCheck.m`` script provided in the root directory of the WecOptTool source code. 131 | The script is called as follows using the MATLAB command prompt: 132 | 133 | .. code:: matlab 134 | 135 | >> cd /path/to/WecOptTool 136 | >> dependencyCheck 137 | 138 | and successful output may look like this: 139 | 140 | .. code:: 141 | 142 | WecOptTool Dependency Checker 143 | ------------------------------- 144 | 145 | Required 146 | -------- 147 | Optimization Toolbox: Found 148 | NEMOH: Found 149 | 150 | Optional 151 | -------- 152 | Parallel Toolbox: Found 153 | Global Optimization Toolbox: Not Installed 154 | WAFO: Found 155 | 156 | 157 | #. **(optional) Run functionality tests:** A test suite is available to verify that the code is operational. 158 | A script is provided in the root directory of the WecOptTool source code and is run from the MATLAB command window, as follows: 159 | 160 | .. code:: matlab 161 | 162 | >> cd /path/to/WecOptTool 163 | >> runTests; 164 | 165 | There should be no *Failed* or *Incomplete* tests at the end of the run. 166 | For example: 167 | 168 | .. code:: 169 | 170 | Totals: 171 | 91 Passed, 0 Failed, 0 Incomplete. 172 | 195.0643 seconds testing time. 173 | 174 | .. _user-setup-uninstall: 175 | 176 | Uninstall 177 | ========= 178 | 179 | Uninstall a previous version of WecOptTool using the MATLAB command prompt: 180 | 181 | .. code:: matlab 182 | 183 | >> rmpath(genpath('/path/to/WecOptTool/toolbox')); 184 | 185 | Alternatively the "Set Path" graphical tool can be used to remove the toolbox. 186 | 187 | .. _README.md: https://github.com/SNL-WaterPower/WecOptTool/blob/master/README.md 188 | 189 | .. rubric:: Footnotes 190 | 191 | .. [#f1] The WecOptTool developers are endeavoring to ensure that this 192 | software is compatible with the latest version of MATLAB (and the 193 | toolbox dependencies). Unfortunately, this may mean that backwards 194 | compatibility with older versions of MATLAB is not possible. See the 195 | `MATLAB Version Support Policy 196 | `__ 197 | page for further details. 198 | 199 | .. |br| raw:: html 200 | 201 |
202 | -------------------------------------------------------------------------------- /docs/user/3model.rst: -------------------------------------------------------------------------------- 1 | .. _model: 2 | 3 | ********************** 4 | WEC Model Architecture 5 | ********************** 6 | 7 | This section provides an overview of how a typical WecOptTool model is programmed. 8 | WecOptTool is currently structured as a set of examples, all of which follow a similar format and can thus rely on common utilities. 9 | It is envisioned that the structure of WecOptTool may some day be consolidated based on experience in developing these examples. 10 | 11 | Introduction 12 | ============ 13 | 14 | The WaveBot example :cite:`Coe2020initial` will be used to illustrate these concepts in more detail. 15 | The process for performing a study in WecOptTool can be broken into three distinct steps, which correlate to three files in the WaveBot example: 16 | 17 | * **Designing the device** - |designDevice.m|_ creates the device based on a set of design variables 18 | * **Simulating device response** - |simulateDevice.m|_ simulates device performance 19 | * **Reporting results** - |Performance.m|_ a class for storing and plotting performance data 20 | 21 | The diagram below shows the responsibilities that each of these steps take within the context of the overall work-flow. 22 | The **Designing the device** step takes user inputs regarding the configuration of the device and calculates the hydrodynamic parameters of that design. 23 | In the diagram below, the processes bounded by **rectangle 1** are encapsulated by this step. 24 | **Simulating device response** takes information about the sea state and controller type, and finds the optimal power output for the given hydrodynamic parameters, encapsulating the processes in **rectangle 2**. 25 | Finally, the processes in **rectangle 3** will use metrics that are calculated in the **Reporting results** step, e.g., to find the average power. 26 | 27 | .. image:: /_static/WecOptToolFlowChartCode.svg 28 | :alt: Steps for implementing the WecOptTool functionality 29 | 30 | Designing the device 31 | ==================== 32 | 33 | .. raw:: html 34 | 35 |
See the entire file
36 | 37 | .. literalinclude:: /../examples/WaveBot/designDevice.m 38 | :language: matlab 39 | :linenos: 40 | 41 | .. raw:: html 42 | 43 |

44 | 45 | The **Designing the device** step codifies the user inputs for the **Geometry**, **Power take off**, and **Kinematics** of the WEC. 46 | With some important caveats, this step can be seen as analogous to building the physical device. 47 | This step can include [#f1]_ generating a panelized representation of the WEC's hull and calling a BEM code (e.g., NEMOH) to estimate the hydrodynamic coefficients. 48 | We can see from the signature of |designDevice.m|_ that it will return a :mat:class:`~+WecOptTool.Hydrodynamics` object. 49 | 50 | .. code:: matlab 51 | 52 | hydro = designDevice(type, varargin) 53 | 54 | Simulating device response 55 | ========================== 56 | 57 | .. raw:: html 58 | 59 |
See the entire file
60 | 61 | .. literalinclude:: /../examples/WaveBot/simulateDevice.m 62 | :language: matlab 63 | :linenos: 64 | 65 | .. raw:: html 66 | 67 |

68 | 69 | To find the performance of a device, a separate step (**Simulating device response**) is used. 70 | For WaveBot, this is codified in the |simulateDevice.m|_, function, which has the following signature: 71 | 72 | .. code:: matlab 73 | 74 | performance = simulateDevice(hydro, seastate, controlType, options) 75 | 76 | The arguments for |simulateDevice.m|_ are: 77 | 78 | * ``hydro`` - a :mat:class:`~+WecOptTool.Hydrodynamics` object containing hydrodynamic coefficients produced by |designDevice.m|_ 79 | * ``seastate`` - a :mat:class:`~+WecOptTool.SeaState` object (see :ref:`seastate`) 80 | * ``controlType`` - string specifying the control type (see :ref:`controlledPerformance`) 81 | * ``options`` - name-value pair arguments for additional settings 82 | 83 | The ``options`` argument can be used to define device properties that are not directly related to the hydrodynamics. 84 | For example, in the WaveBot example the user can set the maximum displacement (``Zmax``) and maximum PTO force (``Fmax``) at this point. 85 | Additionally, solver settings such as the linear interpolation method (``interMethod``) can be defined. 86 | 87 | Reporting results 88 | ================= 89 | 90 | .. raw:: html 91 | 92 |
See the entire file
93 | 94 | .. literalinclude:: /../examples/WaveBot/Performance.m 95 | :language: matlab 96 | :linenos: 97 | 98 | .. raw:: html 99 | 100 |

101 | 102 | The WaveBot example includes the |Performance.m|_ class for storing and reporting results. 103 | As a final step after simulations are completed, |simulateDevice.m|_ populates the fields of this object for return to the user. 104 | In addition to storing the results in a systematic structure, this class also provides some basic plotting functionality. 105 | 106 | .. rubric:: Footnotes 107 | 108 | .. [#f1] Note that since the hydrodynamics are linear, global scalings of the device can be analyzed without rerunning a BEM calculation. 109 | 110 | .. |designDevice.m| replace:: ``designDevice.m`` 111 | .. _designDevice.m: https://github.com/SNL-WaterPower/WecOptTool/blob/master/examples/WaveBot/designDevice.m 112 | .. |simulateDevice.m| replace:: ``simulateDevice.m`` 113 | .. _simulateDevice.m: https://github.com/SNL-WaterPower/WecOptTool/blob/master/examples/WaveBot/simulateDevice.m 114 | .. |Performance.m| replace:: ``Performance.m`` 115 | .. _Performance.m: https://github.com/SNL-WaterPower/WecOptTool/blob/master/examples/WaveBot/Performance.m 116 | -------------------------------------------------------------------------------- /docs/user/4cite.rst: -------------------------------------------------------------------------------- 1 | ***************** 2 | Citing WecOptTool 3 | ***************** 4 | 5 | If WecOptTool has been significant in your research, and you would like to acknowledge the project in your academic publication, we suggest citing the following paper: 6 | 7 | * Coe, R.G., Bacelli, G., Olson, S. *et al.* Initial conceptual demonstration of control co-design for WEC optimization. 8 | J. Ocean Eng. Mar. Energy **6**, 441–449 (2020). `https://doi.org/10.1007/s40722-020-00181-9 `__. 9 | 10 | *In BibTeX format*:: 11 | 12 | @article{ Coe2020initial, 13 | author = {Ryan G. Coe and Giorgio Bacelli and Sterling Olson and Vincent S. Neary 14 | and Mathew B. R. Topper}, 15 | doi = {10.1007/s40722-020-00181-9}, 16 | journal = {Journal of Ocean Engineering and Marine Energy}, 17 | month = {November}, 18 | number = {4}, 19 | pages = {441-449}, 20 | title = {Initial conceptual demonstration of control co-design for {WEC} optimization}, 21 | volume = {6}, 22 | year = {2020} 23 | } 24 | -------------------------------------------------------------------------------- /docs/user/5resources.rst: -------------------------------------------------------------------------------- 1 | ********* 2 | Resources 3 | ********* 4 | 5 | This page provides additional resources for users of WecOptTool. 6 | 7 | Webinar 8 | ======= 9 | 10 | A one hour webinar :cite:`coe2020webinar` was presented on September 29th 2020. This webinar provides interested users with a tutorial and background. 11 | 12 | :pdfembed:`src:../_static/WecOptTool_webinar_2020_09_29.pdf#view=fitH&zoom=scale&toolbar=1, height:450, width:100%, align:middle` 13 | 14 | Additional Reading 15 | ================== 16 | 17 | The following references specifically focusing on WecOptTool are available: 18 | 19 | * **Optimal control of wave energy converters** :cite:`Bacelli2014` - While written years before the development of WecOptTool, Giorgio Bacelli's doctoral thesis provides much of the framework upon which WecOptTool is based. 20 | * **Initial conceptual demonstration of control co-design for WEC optimization** :cite:`Coe2020initial` - This paper presents the basic framework of WecOptTool along with a series of examples using the Sandia WaveBot. 21 | -------------------------------------------------------------------------------- /docs/user/6api.rst: -------------------------------------------------------------------------------- 1 | .. _api: 2 | 3 | *** 4 | API 5 | *** 6 | 7 | WecOptTool 8 | ---------- 9 | 10 | .. mat:autoclass:: +WecOptTool.AutoFolder 11 | :members: 12 | 13 | .. mat:autoclass:: +WecOptTool.Hydrodynamics 14 | :members: 15 | 16 | .. mat:autoclass:: +WecOptTool.SeaState 17 | :members: 18 | 19 | .. mat:autofunction:: +WecOptTool.mesh 20 | 21 | .. mat:autofunction:: +WecOptTool.solver 22 | 23 | WecOptTool.geometry 24 | ------------------- 25 | 26 | The geometry package provides predefined geometry generation functions. 27 | 28 | .. mat:automodule:: +WecOptTool.+geometry 29 | :members: 30 | 31 | WecOptTool.plot 32 | --------------- 33 | 34 | .. mat:automodule:: +WecOptTool.+plot 35 | :members: 36 | 37 | WecOptTool.math 38 | --------------- 39 | 40 | .. mat:automodule:: +WecOptTool.+math 41 | :members: 42 | 43 | WecOptTool.mesh 44 | --------------- 45 | 46 | The mesh subpackage provides mesh generation classes, that provide the standard method ``makeMesh``. 47 | 48 | .. mat:automodule:: +WecOptTool.+mesh 49 | :members: 50 | 51 | WecOptTool.solver 52 | ----------------- 53 | 54 | The solver subpackage provides hydrodynamic solver classes, that provide the standard method ``getHydro``. 55 | 56 | .. mat:automodule:: +WecOptTool.+solver 57 | :members: 58 | 59 | WecOptTool.base 60 | --------------- 61 | 62 | The base subpackage provides base classes used in other classes. 63 | 64 | .. mat:automodule:: +WecOptTool.+base 65 | :members: 66 | -------------------------------------------------------------------------------- /docs/user/7license.rst: -------------------------------------------------------------------------------- 1 | ******* 2 | License 3 | ******* 4 | 5 | Copyright |copy| |year| National Technology & Engineering Solutions of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government retains certain rights in this software. 6 | 7 | WecOptTool is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 8 | 9 | WecOptTool is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 10 | 11 | You should have received a copy of the GNU General Public License along with WecOptTool. 12 | If not, see . 13 | 14 | .. |copy| unicode:: U+000A9 .. COPYRIGHT SIGN 15 | .. |year| date:: %Y 16 | -------------------------------------------------------------------------------- /docs/user/8references.rst: -------------------------------------------------------------------------------- 1 | ********** 2 | References 3 | ********** 4 | 5 | This page list supporting references for WecOptTool. 6 | 7 | .. bibliography:: WecOptTool_refs.bib 8 | :style: unsrt 9 | -------------------------------------------------------------------------------- /docs/user/WecOptTool_refs.bib: -------------------------------------------------------------------------------- 1 | 2 | @phdthesis{Bacelli2014, 3 | Address = {Maynooth, Ireland}, 4 | Author = {Bacelli, Giorgio}, 5 | School = {National University of Ireland, Maynooth}, 6 | Title = {Optimal control of wave energy converters}, 7 | Type = {{PhD}}, 8 | Url = {http://mural.maynoothuniversity.ie/6753/}, 9 | Year = {2014}} 10 | 11 | @misc{coe2020webinar, 12 | Author = {Ryan G. Coe and Giorgio Bacelli and Sterling Olson and Vincent S. Neary and Mathew B. R. Topper}, 13 | Doi = {10.13140/RG.2.2.16353.94564}, 14 | Howpublished = {Online}, 15 | Month = {September}, 16 | Title = {{WecOptTool Sept. 2020 Webinar}}, 17 | Year = {2020}} 18 | 19 | @article{Coe2020initial, 20 | Author = {Ryan G. Coe and Giorgio Bacelli and Sterling Olson and Vincent S. Neary and Mathew B. R. Topper}, 21 | Doi = {10.1007/s40722-020-00181-9}, 22 | Journal = {Journal of Ocean Engineering and Marine Energy}, 23 | Title = {{Initial conceptual demonstration of control co-design for WEC optimization}}, 24 | month = {November}, 25 | number = {4}, 26 | pages = {441-449}, 27 | volume = {6}, 28 | Year = {2020}} 29 | 30 | @book{Falnes2002, 31 | Address = {Cambridge; New York}, 32 | Author = {Johannes Falnes}, 33 | Doi = {10.1017/CBO9780511754630}, 34 | Publisher = {Cambridge University Press}, 35 | Title = {Ocean Waves and Oscillating Systems}, 36 | Year = {2002}} 37 | 38 | @article{Bacelli2014a, 39 | Author = {Bacelli, Giorgio and Ringwood, John V}, 40 | Doi = {10.1109/TSTE.2014.2371536}, 41 | Journal = {IEEE Transactions on Sustainable Energy}, 42 | Number = {2}, 43 | Pages = {294--302}, 44 | Publisher = {IEEE}, 45 | Title = {Numerical optimal control of wave energy converters}, 46 | Volume = {6}, 47 | Year = {2014}} 48 | -------------------------------------------------------------------------------- /examples/RM3/RM3_BEM.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SNL-WaterPower/WecOptTool-MATLAB/0a9faa189f8570444fac5ebe0da2a9fcd94958eb/examples/RM3/RM3_BEM.mat -------------------------------------------------------------------------------- /examples/RM3/basic.m: -------------------------------------------------------------------------------- 1 | 2 | clear controlParams performances r 3 | 4 | % Create an example SeaState object 5 | SS = WecOptTool.SeaState.exampleSpectrum("resampleByError", 0.1); 6 | 7 | controlParams.type = 'CC'; 8 | controlParams(2).type = 'P'; 9 | controlParams(3).type = 'PS'; 10 | controlParams(3).params = {10 1e9}; 11 | 12 | deviceHydro = designDevice('scalar', 1); 13 | 14 | for i = 1:length(controlParams) 15 | 16 | disp("Simulation " + (i) + " of " + length(controlParams)) 17 | 18 | for j = 1:length(SS) 19 | 20 | if ~isempty(controlParams(i).params) 21 | performances(j) = simulateDevice(deviceHydro, ... 22 | SS(j), ... 23 | controlParams(i).type, ... 24 | controlParams(i).params{:}); 25 | else 26 | performances(j) = simulateDevice(deviceHydro, ... 27 | SS(j), ... 28 | controlParams(i).type); 29 | end 30 | 31 | end 32 | 33 | r(i) = sum(aggregateSeaStates(SS, performances)); 34 | 35 | end 36 | 37 | function out = aggregateSeaStates(seastate, performances) 38 | pow = sum(performances.powPerFreq); 39 | out = dot(pow, [seastate.mu]) / sum([seastate.mu]); 40 | end 41 | 42 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 43 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 44 | % U.S. Government retains certain rights in this software. 45 | % 46 | % This file is part of WecOptTool. 47 | % 48 | % WecOptTool is free software: you can redistribute it and/or modify 49 | % it under the terms of the GNU General Public License as published by 50 | % the Free Software Foundation, either version 3 of the License, or 51 | % (at your option) any later version. 52 | % 53 | % WecOptTool is distributed in the hope that it will be useful, 54 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 55 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 56 | % GNU General Public License for more details. 57 | % 58 | % You should have received a copy of the GNU General Public License 59 | % along with WecOptTool. If not, see . 60 | -------------------------------------------------------------------------------- /examples/RM3/designDevice.m: -------------------------------------------------------------------------------- 1 | function [hydro, meshes] = designDevice(type, varargin) 2 | 3 | meshes = []; 4 | 5 | switch type 6 | 7 | case 'existing' 8 | hydro = WecOptTool.geometry.existingNEMOH(varargin{:}); 9 | case 'scalar' 10 | hydro = getHydroScalar(varargin{:}); 11 | case 'parametric' 12 | [hydro, meshes] = getHydroParametric(varargin{:}); 13 | 14 | end 15 | 16 | end 17 | 18 | function hydro = getHydroScalar(lambda) 19 | 20 | % Get data file path 21 | p = mfilename('fullpath'); 22 | [filepath, ~, ~] = fileparts(p); 23 | dataPath = fullfile(filepath, 'RM3_BEM.mat'); 24 | 25 | mf = matfile(dataPath); 26 | hydro = mf.hydro; 27 | 28 | % dimensionalize w/ WEC-Sim built-in function 29 | hydro.rho = 1025; 30 | hydro.g = 9.81; 31 | % hydro = Normalize(hydro); % TODO - this doesn't work for our data 32 | % that was produced w/ WAMIT... 33 | 34 | % scale by scaling factor lambda 35 | hydro.Vo = hydro.Vo .* lambda^3; 36 | hydro.C = hydro.C .* lambda^2; 37 | hydro.B = hydro.B .* lambda^2.5; 38 | hydro.A = hydro.A .* lambda^3; 39 | hydro.ex = complex(hydro.ex_re,hydro.ex_im) .* lambda^2; 40 | hydro = rmfield(hydro,{'ex_re','ex_im'}); 41 | end 42 | 43 | 44 | function [hydro, meshes] = getHydroParametric(folder, r1, r2, d1, d2, w) 45 | 46 | % Float 47 | 48 | rf = [0 r1 r1 0]; 49 | zf = [0 0 -d1 -d1]; 50 | 51 | % Heave plate 52 | 53 | thk = 1; 54 | rs = [0 r2 r2 0]; 55 | zs = [-d2 -d2 -d2-thk -d2-thk]; 56 | 57 | % Mesh 58 | ntheta = 20; 59 | nfobj = 200; 60 | zG = 0; 61 | 62 | meshes = WecOptTool.mesh("AxiMesh", ... 63 | folder, ... 64 | rf, ... 65 | zf, ... 66 | ntheta, ... 67 | nfobj, ... 68 | zG, ... 69 | 1); 70 | meshes(2) = WecOptTool.mesh("AxiMesh", ... 71 | folder, ... 72 | rs, ... 73 | zs, ... 74 | ntheta, ... 75 | nfobj, ... 76 | zG, ... 77 | 2); 78 | 79 | hydro = WecOptTool.solver("NEMOH", folder, meshes, w); 80 | 81 | end 82 | 83 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 84 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 85 | % U.S. Government retains certain rights in this software. 86 | % 87 | % This file is part of WecOptTool. 88 | % 89 | % WecOptTool is free software: you can redistribute it and/or modify 90 | % it under the terms of the GNU General Public License as published by 91 | % the Free Software Foundation, either version 3 of the License, or 92 | % (at your option) any later version. 93 | % 94 | % WecOptTool is distributed in the hope that it will be useful, 95 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 96 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 97 | % GNU General Public License for more details. 98 | % 99 | % You should have received a copy of the GNU General Public License 100 | % along with WecOptTool. If not, see . 101 | -------------------------------------------------------------------------------- /examples/RM3/optimization.m: -------------------------------------------------------------------------------- 1 | %% optimization.m 2 | % Example of an optimization study 3 | 4 | %% Define and store sea state of interest 5 | 6 | % Create Bretschnider spectrum from WAFO and trim off frequencies that 7 | % have less that 1% of the max spectral density 8 | % S = bretschneider([],[8,10],0); 9 | % SS = WecOptTool.SeaState(S, "trimFrequencies", 0.01) 10 | 11 | % Load an example with multiple sea-states (8 differing spectra) and trim 12 | % off frequencies that have less that 1% of the max spectral density 13 | SS = WecOptTool.SeaState.example8Spectra("trimFrequencies", 0.01); 14 | 15 | %% Create a folder for storing intermediate files 16 | folder = WecOptTool.AutoFolder(); 17 | 18 | %% Optimization Setup 19 | 20 | % Add geometry design variables (parametric) 21 | x0 = [5, 7.5, 1.125, 42]; 22 | lb = [4.5, 7, 1.00, 41]; 23 | ub = [5.5, 8, 1.25, 43]; 24 | 25 | % Define optimisation options 26 | opts = optimoptions('fmincon'); 27 | opts.FiniteDifferenceType = 'central'; 28 | opts.UseParallel = true; 29 | opts.MaxFunctionEvaluations = 5; % set artificial low for fast running 30 | opts.Display = 'iter'; 31 | 32 | % Enable dynamic plotting 33 | % opts.PlotFcn = {@optimplotx,@optimplotfval}; 34 | 35 | % Define unused parameters 36 | A = []; 37 | B = []; 38 | Aeq = []; 39 | Beq = []; 40 | NONLCON = []; 41 | 42 | %% Optimization Execution 43 | 44 | % Create simple objective function handle 45 | objFun = @(x) myWaveBotObjFun(x, SS, folder); 46 | 47 | % Call the solver 48 | [x, fval] = fmincon(objFun, x0, A, B, Aeq, Beq, lb, ub, NONLCON, opts); 49 | 50 | %% Recover device object of best simulation and plot its power per freq 51 | %% and mesh 52 | performances = folder.recoverVar("performances"); 53 | 54 | for i = 1:length(performances) 55 | test = performances{i}; 56 | if isequal(test(1).x, x) 57 | bestPerformances = test; 58 | break 59 | end 60 | end 61 | 62 | WecOptTool.plot.powerPerFreq(bestPerformances); 63 | WecOptTool.plot.plotMesh(bestPerformances(1).meshes); 64 | 65 | %% Define objective function 66 | % This can take any form that complies with the requirements of the MATLAB 67 | % optimization functions 68 | 69 | function fval = myWaveBotObjFun(x, seastate, folder) 70 | 71 | w = seastate.getRegularFrequencies(0.5); 72 | geomParams = [folder.path num2cell(x) w]; 73 | 74 | [deviceHydro, meshes] = designDevice('parametric', geomParams{:}); 75 | 76 | for j = 1:length(seastate) 77 | performances(j) = simulateDevice(deviceHydro, ... 78 | seastate(j), ... 79 | 'CC'); 80 | end 81 | 82 | fval = -1 * weightedPower(seastate, performances); 83 | 84 | [performances(:).w] = seastate.w; 85 | performances(1).x = x; 86 | performances(1).meshes = meshes; 87 | 88 | folder.stashVar(performances); 89 | 90 | end 91 | 92 | function out = weightedPower(seastate, performances) 93 | pow = sum([performances.powPerFreq]); 94 | out = dot(pow, [seastate.mu]) / sum([seastate.mu]); 95 | end 96 | 97 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 98 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 99 | % U.S. Government retains certain rights in this software. 100 | % 101 | % This file is part of WecOptTool. 102 | % 103 | % WecOptTool is free software: you can redistribute it and/or modify 104 | % it under the terms of the GNU General Public License as published by 105 | % the Free Software Foundation, either version 3 of the License, or 106 | % (at your option) any later version. 107 | % 108 | % WecOptTool is distributed in the hope that it will be useful, 109 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 110 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 111 | % GNU General Public License for more details. 112 | % 113 | % You should have received a copy of the GNU General Public License 114 | % along with WecOptTool. If not, see . 115 | -------------------------------------------------------------------------------- /examples/WaveBot/Performance.m: -------------------------------------------------------------------------------- 1 | classdef Performance < handle 2 | 3 | properties 4 | w (:,:) double {mustBeFinite,mustBeReal,mustBePositive} 5 | ph (:,:) double {mustBeFinite,mustBeReal} 6 | eta (:,:) double {mustBeFinite} 7 | F0 (:,:) double {mustBeFinite} 8 | u (:,:) double {mustBeFinite} 9 | pos (:,:) double {mustBeFinite} 10 | Zpto (:,:) double {} 11 | Fpto (:,:) double {mustBeFinite} 12 | pow (:,:) double {mustBeFinite} 13 | name (1,:) char = 'tmp' 14 | date (1,1) double {mustBeFinite,mustBePositive} = now 15 | end 16 | 17 | methods 18 | 19 | function plotTime(obj, t, options) 20 | 21 | arguments 22 | obj 23 | t = 0:0.05:obj(1).getRepeatPer() 24 | options.Interpreter = 'none' 25 | options.FontSize = 11 26 | end 27 | 28 | fig = figure('Name','Performance.plotTime'); 29 | fig.Position = fig.Position .* [1 1 1 1.5]; 30 | movegui(fig, 'onscreen'); 31 | 32 | % fields for plotting 33 | fns = {'eta','F0','pos','u','Fpto','pow'}; 34 | 35 | for ii = 1:length(fns) 36 | ax(ii) = subplot(length(fns), 1, ii); 37 | hold on 38 | grid on 39 | end 40 | 41 | for jj = 1:length(obj) 42 | 43 | for ii = 1:length(fns) 44 | timeRes.(fns{ii}) = getTimeRes(obj(jj),fns{ii}, t); 45 | plot(ax(ii),t,timeRes.(fns{ii})) 46 | ylabel(ax(ii), ... 47 | fns{ii}, ... 48 | 'Interpreter', options.Interpreter, ... 49 | 'FontSize', options.FontSize) 50 | end 51 | 52 | for ii = 1:length(ax) - 1 53 | set(ax(ii),'XTickLabel',[]) 54 | end 55 | 56 | linkaxes(ax,'x') 57 | xlabel(ax(end), ... 58 | 'Time [s]', ... 59 | 'Interpreter', options.Interpreter, ... 60 | 'FontSize', options.FontSize) 61 | 62 | end 63 | 64 | xlim([t(1), t(end)]) 65 | 66 | if length(obj) > 1 67 | l1 = legend(ax(1), ... 68 | {obj.name}, ... 69 | 'Interpreter', options.Interpreter, ... 70 | 'FontSize', options.FontSize); 71 | set(l1, 'NumColumns', length(obj)) 72 | end 73 | 74 | end 75 | 76 | function plotFreq(obj, fig, options) 77 | 78 | arguments 79 | obj 80 | fig = figure; 81 | options.Interpreter = 'none' 82 | options.FontSize = 11 83 | end 84 | 85 | set(fig,'Name','Performance.plotFreq'); 86 | 87 | fns = {'F0','u','Fpto'}; 88 | mrks = {'o','.','+','s'}; 89 | 90 | n = length(obj); 91 | for jj = 1:n 92 | for ii = 1:length(fns) 93 | 94 | fv = obj(jj).(fns{ii})(:,1); % use the first column if this is PS 95 | 96 | % mag plot 97 | ax(jj,1) = subplot(2,n,sub2ind([n,2],jj,1)); 98 | title(obj(jj).name, ... 99 | 'Interpreter', options.Interpreter, ... 100 | 'FontSize', options.FontSize) 101 | hold on 102 | grid on 103 | 104 | stem(ax(jj,1), ... 105 | obj(jj).w, ... 106 | mag2db(abs(fv)), ... 107 | mrks{ii}, ... 108 | 'DisplayName', fns{ii}, ... 109 | 'MarkerSize', 8, ... 110 | 'Color', 'b') 111 | 112 | % phase plot 113 | ax(jj,2) = subplot(2,n,sub2ind([n,2],jj,2)); 114 | hold on 115 | grid on 116 | 117 | stem(ax(jj,2), ... 118 | obj(jj).w, ... 119 | angle(fv), ... 120 | mrks{ii}, ... 121 | 'DisplayName', fns{ii}, ... 122 | 'MarkerSize', 8, ... 123 | 'Color', 'b') 124 | 125 | ylim(ax(jj,2),[-pi,pi]) 126 | 127 | end 128 | 129 | xlabel(ax(jj,2), ... 130 | 'Frequency [rad/s]', ... 131 | 'Interpreter', options.Interpreter, ... 132 | 'FontSize', options.FontSize) 133 | 134 | end 135 | 136 | ylabel(ax(1,1), ... 137 | 'Magnitude [dB]', ... 138 | 'Interpreter', options.Interpreter, ... 139 | 'FontSize', options.FontSize) 140 | ylabel(ax(1,2), ... 141 | 'Angle [rad]', ... 142 | 'Interpreter', options.Interpreter, ... 143 | 'FontSize', options.FontSize) 144 | legend(ax(n,1), ... 145 | 'Interpreter', options.Interpreter, ... 146 | 'FontSize', options.FontSize) 147 | linkaxes(ax, 'x') 148 | linkaxes(ax(:,1), 'y') 149 | 150 | end 151 | 152 | function T = summary(obj) 153 | 154 | if length(obj) > 1 155 | for ii = 1:length(obj) 156 | Tr(ii,:) = summary(obj(ii)); 157 | end 158 | 159 | % augment names if they are the same 160 | if any(strcmp(obj(1).name, {obj(2:end).name})) 161 | for ii = 1:length(obj) 162 | rnames{ii} = [obj(ii).name, '_', num2str(ii)]; 163 | end 164 | else 165 | rnames = {obj.name}; 166 | end 167 | 168 | Tr.Properties.RowNames = rnames; 169 | mT = Tr; 170 | 171 | if nargout 172 | T = mT; 173 | else 174 | disp(mT) 175 | end 176 | 177 | return 178 | 179 | else 180 | rnames = {obj.name}; 181 | end 182 | 183 | trep = obj.getRepeatPer(); 184 | t = linspace(0,trep,1e3); 185 | 186 | for jj = 1:size(obj.ph,2) % for each phase in PS cases 187 | 188 | tmp.pow_avg(jj) = sum(real(obj.pow(:,jj))); 189 | 190 | pow_t = getTimeRes(obj, 'pow', t, jj); 191 | tmp.pow_max(jj) = max(abs(pow_t)); 192 | 193 | try 194 | tmp.pow_thd(jj) = thd(pow_t); 195 | catch ME 196 | warning(ME.message) 197 | tmp.pow_thd(jj) = NaN; 198 | end 199 | 200 | pos_t = getTimeRes(obj, 'pos', t, jj); 201 | tmp.pos_max(jj) = max(abs(pos_t)); 202 | 203 | vel_t = getTimeRes(obj, 'u', t, jj); 204 | tmp.vel_max(jj) = max(abs(vel_t)); 205 | 206 | Fpto_t = getTimeRes(obj, 'Fpto', t, jj); 207 | tmp.Fpto_max(jj) = max(abs(Fpto_t)); 208 | end 209 | 210 | fn = fieldnames(tmp); 211 | for kk = 1:length(fn) 212 | out.(fn{kk}) = mean(tmp.(fn{kk}), 2); 213 | end 214 | 215 | rnames = reshape(rnames,[],1); 216 | 217 | mT = table(out.pow_avg(:),out.pow_max(:),out.pow_thd(:),... 218 | out.pos_max(:),out.vel_max(:),out.Fpto_max(:),... 219 | 'VariableNames',... 220 | {'AvgPow','|MaxPow|','PowTHD_dBc','MaxPos','MaxVel','MaxPTO'},... 221 | 'RowNames',rnames); 222 | 223 | if nargout 224 | T = mT; 225 | else 226 | disp(mT) 227 | end 228 | 229 | end 230 | 231 | end 232 | 233 | methods (Access=protected) 234 | 235 | function [tRep] = getRepeatPer(obj) 236 | tRep = 2*pi/(obj.w(2) - obj.w(1)); 237 | end 238 | 239 | function [timeRes] = getTimeRes(obj, fn, t_vec, ph_idx) 240 | if nargin < 4 241 | ph_idx = 1; 242 | end 243 | 244 | if strcmp(fn,'pow') 245 | vel = obj.getTimeRes('u',t_vec); 246 | f = obj.getTimeRes('Fpto',t_vec); 247 | timeRes = vel .* f; 248 | else 249 | timeRes = zeros(size(t_vec)); 250 | fv = obj.(fn)(:,ph_idx); % use the first column if this is PS 251 | for ii = 1:length(obj.w) % for each freq. TODO - use IFFT 252 | timeRes = timeRes ... 253 | + real(fv(ii) * exp(1i * obj.w(ii) * t_vec)); 254 | end 255 | end 256 | end 257 | 258 | % function checkSizes(varargin) % TODO 259 | % n = length(varargin); 260 | % for ii = 1:n 261 | % if ~isequal(varargin(varargin{ii}),size(varargin{1})) 262 | % error('Frequency vectors must have same size') 263 | % end 264 | % end 265 | % end 266 | 267 | end 268 | end 269 | 270 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 271 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 272 | % U.S. Government retains certain rights in this software. 273 | % 274 | % This file is part of WecOptTool. 275 | % 276 | % WecOptTool is free software: you can redistribute it and/or 277 | % modify it under the terms of the GNU General Public License as 278 | % published by the Free Software Foundation, either version 3 of 279 | % the License, or (at your option) any later version. 280 | % 281 | % WecOptTool is distributed in the hope that it will be useful, 282 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 283 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 284 | % GNU General Public License for more details. 285 | % 286 | % You should have received a copy of the GNU General Public 287 | % License along with WecOptTool. If not, see 288 | % . 289 | -------------------------------------------------------------------------------- /examples/WaveBot/README.md: -------------------------------------------------------------------------------- 1 | # WaveBot 2 | 3 | This example was developed in conjuction with the following journal paper, which is avaialable at . 4 | 5 | ``` 6 | @Article{WecDesignOptimizationTool, 7 | author = "Ryan G. Coe and Giorgio Bacelli and Sterling Olson and Vincent S. Neary and Mathew B. R. Topper", 8 | title = {Initial conceptual demonstration of control co-design for {WEC} optimization}, 9 | year = {2020}, 10 | journal= {Journal of Ocean Engineering and Marine Energy}, 11 | month = {November}, 12 | volume = {6}, 13 | number = {4}, 14 | pages = {441-449}, 15 | doi = {10.1007/s40722-020-00181-9} 16 | } 17 | ``` 18 | -------------------------------------------------------------------------------- /examples/WaveBot/WaveBot_caseA.m: -------------------------------------------------------------------------------- 1 | % Case A 2 | % This case study shows a comparison between the different controllers 3 | % currently available in WecOptTool. This is NOT an optimization study. 4 | % Instead, a single device design is simulated in a sea state using each of 5 | % the three controllers. The purpose of this study is to demonstrate some 6 | % of the basic differences between these three controller types: 7 | % 8 | % CC complex conjugate control 9 | % P proportional damping 10 | % PS pseudo-spectral numerical optimal control 11 | 12 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, LLC 13 | % (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. 14 | % Government retains certain rights in this software. 15 | % 16 | % This file is part of WecOptTool. 17 | % 18 | % WecOptTool is free software: you can redistribute it and/or modify it 19 | % under the terms of the GNU General Public License as published by the 20 | % Free Software Foundation, either version 3 of the License, or (at 21 | % your option) any later version. 22 | % 23 | % WecOptTool is distributed in the hope that it will be useful, but 24 | % WITHOUT ANY WARRANTY; without even the implied warranty of 25 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 26 | % General Public License for more details. 27 | % 28 | % You should have received a copy of the GNU General Public License 29 | % along with WecOptTool. If not, see . 30 | 31 | %% define sea state of interest 32 | 33 | dw = 0.3142; 34 | nf = 50; 35 | w = dw * (1:nf)'; 36 | A = 0.125/2; 37 | wp = w(6); 38 | fp = wp/(2*pi); 39 | Tp = 1/fp; 40 | SS = WecOptTool.SeaState.regularWave(w,[A,Tp]); 41 | 42 | %% Create device and define controllers 43 | 44 | controlType{1} = 'CC'; 45 | controlType{2} = 'P'; 46 | controlType{3} = 'PS'; 47 | 48 | % constraints for PS, zmax: max stroke (inactive); fmax: max PTO force 49 | zmax = 1e10; 50 | fmax = 2e3; 51 | 52 | % make a WaveBot using the 'base' dimensions 53 | designType = 'scalar'; 54 | scalarVal = 1; 55 | folder = WecOptTool.AutoFolder(); 56 | deviceHydro = designDevice(designType, folder.path, scalarVal, w); 57 | 58 | %% Run simulations 59 | 60 | clear r 61 | for ii = 1:length(controlType) 62 | disp("Simulation " + (ii) + " of " + length(controlType)) 63 | rng(3) % run same wave phasing for each case 64 | r(ii) = simulateDevice(deviceHydro,SS,controlType{ii}, ... 65 | 'interpMethod', 'nearest', ... 66 | 'Zmax', zmax, ... 67 | 'Fmax', fmax); 68 | r(ii).name = controlType{ii}; 69 | end 70 | 71 | %% plot freq. domain results 72 | 73 | r.plotFreq('Interpreter', 'latex') 74 | 75 | fig = gcf; 76 | fig.Position = fig.Position .* [1 1 1.5 0.5]; 77 | delete(findobj(fig, 'Type', 'Legend')) 78 | 79 | % Rewrite legend 80 | ax = findobj(gcf, 'Type', 'axes'); 81 | l1 = legend(ax(end), '$F_e$', '$u$', '$F_u$'); 82 | set(l1, 'Interpreter', 'latex') 83 | 84 | % label x-axis with integer multiples of fundamental freq. 85 | intf = 1:2:8; 86 | xt = [0 (1:2:8) * 2 * pi / Tp]; 87 | xtl{1} = 0; 88 | xtl{2} = sprintf('$\\omega_0$'); 89 | 90 | for ii = 1:length(intf) - 1 91 | xtl{ii+2} = sprintf('%i $\\omega_0$', intf(ii+1)); 92 | end 93 | 94 | for ii = 1:length(ax) 95 | set(ax(ii), 'XTick', xt) 96 | set(ax(ii), 'XTickLabel', xtl) 97 | set(ax(ii), 'TickLabelInterpreter', 'latex'); 98 | end 99 | 100 | for ii = [2,4,6] 101 | set(ax(ii), 'XTickLabel', []) 102 | end 103 | 104 | % export_fig('WaveBot_caseA_freq.pdf','-transparent') 105 | 106 | %% plot time domain results 107 | 108 | fs = 15; 109 | r.plotTime(0:0.01:10, 'Interpreter', 'latex', 'FontSize', fs); 110 | fig = gcf; 111 | ax = findall(fig, 'type', 'axes'); 112 | 113 | % thicker lines 114 | lh = findobj(fig, 'Type', 'line'); 115 | for ii = 1:numel(lh) 116 | lh(ii).LineWidth=2; 117 | end 118 | 119 | % plot PTO force limits and add annotations 120 | hp(1) = plot(ax(2), xlim, fmax * ones(2,1), 'k--'); 121 | hp(2) = plot(ax(2), xlim, -1 * fmax * ones(2,1), 'k--'); 122 | uistack(hp,'bottom'); 123 | annotation(fig, ... 124 | 'textarrow', ... 125 | [0.648214285714286 0.573214285714286], ... 126 | [0.361904761904762 0.328571428571429], ... 127 | 'String', '$F_u^{\textrm{{max}}}$', ... 128 | 'Interpreter', 'latex', ... 129 | 'FontSize', 18); 130 | annotation(fig, ... 131 | 'arrow', ... 132 | [0.648214285714286 0.528571428571429], ... 133 | [0.36031746031746 0.288888888888889]); 134 | 135 | % Rewrite y-axis labels 136 | ylabel(ax(1), '$P$ [W]', 'Interpreter', 'latex', 'FontSize', fs) 137 | ylabel(ax(2), '$F_u$ [N]', 'Interpreter', 'latex', 'FontSize', fs) 138 | ylabel(ax(3), '$u$ [m/s]', 'Interpreter', 'latex', 'FontSize', fs) 139 | ylabel(ax(4), '$z$ [m]', 'Interpreter', 'latex', 'FontSize', fs) 140 | ylabel(ax(5), '$F_e$ [N]', 'Interpreter', 'latex', 'FontSize', fs) 141 | ylabel(ax(6), '$\eta$ [m]', 'Interpreter', 'latex', 'FontSize', fs) 142 | 143 | % export_fig('WaveBot_caseA_time.pdf','-transparent') 144 | 145 | %% report results in a table 146 | 147 | summary(r) 148 | -------------------------------------------------------------------------------- /examples/WaveBot/WaveBot_caseB.m: -------------------------------------------------------------------------------- 1 | % Case B 2 | % This case performs three optimization studies (one using each of the 3 | % three control types: P, CC, and PS). The objective function is a simple 4 | % ratio of average power and a polynomial of submerged hull volume. The 5 | % goal behind this study is to illustrate how the different control types 6 | % result in different optimal designs. 7 | 8 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, LLC 9 | % (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. 10 | % Government retains certain rights in this software. 11 | % 12 | % This file is part of WecOptTool. 13 | % 14 | % WecOptTool is free software: you can redistribute it and/or modify it 15 | % under the terms of the GNU General Public License as published by the 16 | % Free Software Foundation, either version 3 of the License, or (at 17 | % your option) any later version. 18 | % 19 | % WecOptTool is distributed in the hope that it will be useful, but 20 | % WITHOUT ANY WARRANTY; without even the implied warranty of 21 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 | % General Public License for more details. 23 | % 24 | % You should have received a copy of the GNU General Public License 25 | % along with WecOptTool. If not, see . 26 | 27 | %% define sea state of interest 28 | 29 | dw = 0.3142; 30 | nf = 50; 31 | w = dw * (1:nf)'; 32 | A = 0.125/2; 33 | wp = w(6); 34 | fp = wp/(2*pi); 35 | Tp = 1/fp; 36 | SS = WecOptTool.SeaState.regularWave(w,[A,Tp]); 37 | 38 | %% set up device types 39 | 40 | controlType{1} = 'CC'; 41 | controlType{2} = 'P'; 42 | controlType{3} = 'PS'; 43 | 44 | % constraints for PS, zmax: max stroke; fmax: max PTO force (inactive) 45 | zmax = 0.6; 46 | fmax = 1e10; 47 | 48 | folder = WecOptTool.AutoFolder(); 49 | 50 | %% create set of devices (run hydrodynamics) 51 | 52 | % outer radius of WaveBot 53 | rmin = 0.25; 54 | rmax = 2; 55 | r0 = 0.88; % nominal radius 56 | radii = sort([linspace(rmin,rmax,19), r0]); 57 | 58 | clear deviceHydro 59 | for idx = 1:length(radii) 60 | radius = radii(idx); 61 | disp("Running BEM for case " + (idx) + " of " + length(radii)) 62 | deviceHydro(idx) = designDevice('parametric', folder.path, ... 63 | radius, 0.35, 0.16, 0.53, w); 64 | end 65 | 66 | %% simulate performance 67 | 68 | clear r 69 | for ii = 1:length(controlType) 70 | for jj = 1:length(radii) 71 | rng(3) % run same wave phasing for each case 72 | disp("Monte-carlo for " + controlType{ii} + ", case " + (jj) + " of " + length(radii)) 73 | r(jj,ii) = simulateDevice(deviceHydro(jj),SS,controlType{ii},... 74 | 'interpMethod','nearest','Zmax',zmax,... 75 | 'Fmax',fmax); 76 | r(jj,ii).name = [controlType{ii}, '_', num2str(radii(jj))]; 77 | end 78 | end 79 | 80 | %% set up optimization problems 81 | 82 | x0 = 2; 83 | A = []; 84 | B = []; 85 | Aeq = []; 86 | Beq = []; 87 | LB = min(radii); 88 | UB = max(radii); 89 | NONLCON = []; 90 | opts = optimset('fminbnd'); 91 | opts.UseParallel = true; 92 | opts.Display = 'iter'; 93 | opts.PlotFcn = {@optimplotx,@optimplotfval}; 94 | 95 | %% run optimization solver (for each control type) 96 | 97 | clear fval x_opt exitflag output optSimres 98 | for ii = 1:length(controlType) 99 | disp("fminbnd for " + controlType{ii}) 100 | 101 | % find optimal geometry for each control type 102 | [x_opt(ii), fval(ii), exitflag(ii), output(ii)] = ... 103 | fminbnd(@(x) myWaveBotObjFun(x,w,SS,controlType{ii},zmax,fmax,... 104 | folder.path),LB,UB,opts); 105 | 106 | % get full results for optimal geometry 107 | [~, optSimres(ii), optHydro(ii)] = ... 108 | myWaveBotObjFun(x_opt(ii),w,SS,controlType{ii},zmax,fmax,folder.path); 109 | end 110 | 111 | %% plot results 112 | 113 | fig = figure('Name','WaveBot_caseB'); 114 | fig.Position = fig.Position .* [1, 1, 1, 1.5]; 115 | 116 | mys = {'log','linear','log','log'}; 117 | for ii = 1:4 118 | ax(ii) = subplot(4,1,ii); 119 | set(ax(ii),'yscale',mys{ii}) 120 | grid on 121 | hold on 122 | end 123 | 124 | mkrs = {'^','o','s'}; 125 | 126 | % plot Monte-Carlo results 127 | for ii = 1:size(r,2) 128 | 129 | SMRY = summary(r(:,ii)); 130 | pow = abs(SMRY.AvgPow); 131 | vol = arrayfun(@(x) deviceHydro(x).Vo, 1:length(radii))'; 132 | pos = SMRY.MaxPos; 133 | obfn = pow ./ (0.88 + radii(:)).^3; 134 | 135 | semilogy(ax(1), radii, pow, 'Marker', mkrs{ii},'LineWidth',1.5) 136 | plot(ax(2), radii, vol, 'Marker', mkrs{ii},'LineWidth',1.5) 137 | semilogy(ax(3), radii, pos, 'Marker', mkrs{ii},'LineWidth',1.5) 138 | semilogy(ax(4), radii, obfn, 'Marker', mkrs{ii},'LineWidth',1.5) 139 | end 140 | 141 | 142 | for jj = 1:length(ax) 143 | set(ax(jj),'ColorOrderIndex',1) 144 | end 145 | 146 | % plot optimal solutions 147 | for ii = 1:length(optSimres) 148 | 149 | SMRY = summary(optSimres(ii)); 150 | pow = abs(SMRY.AvgPow); 151 | vol = optHydro(ii).Vo; 152 | pos = SMRY.MaxPos; 153 | obfn = -1*fval(ii); 154 | 155 | stem(ax(1), x_opt(ii), pow, 'Marker', mkrs{ii},... 156 | 'LineWidth',2,'MarkerSize',10) 157 | stem(ax(2), x_opt(ii), vol, 'Marker', mkrs{ii},... 158 | 'LineWidth',2,'MarkerSize',10) 159 | stem(ax(3), x_opt(ii), pos, 'Marker', mkrs{ii},... 160 | 'LineWidth',2,'MarkerSize',10) 161 | stem(ax(4), x_opt(ii), obfn, 'Marker', mkrs{ii},... 162 | 'LineWidth',2,'MarkerSize',10) 163 | end 164 | 165 | fs = 15; 166 | 167 | ylabel(ax(1),'Avg. pow [W]','interpreter','latex','FontSize',fs) 168 | ylabel(ax(2),'Vol. [m$^3$]','interpreter','latex','FontSize',fs) 169 | ylabel(ax(3),'Pos. amp. [m]','interpreter','latex','FontSize',fs) 170 | ylabel(ax(4),'$-1\cdot{}$Obj. fun. [W/m$^3$]','interpreter','latex','FontSize',fs) 171 | 172 | set(ax(1:3),'XTickLabel',[]) 173 | 174 | l1 = legend(ax(1),'CC','P','PS'); 175 | set(l1,'location','southeast') 176 | xlabel('Outer radius, $r_1$ [m]','interpreter','latex','FontSize',fs) 177 | linkaxes(ax,'x') 178 | xlim([0.25, max(radii)]) 179 | 180 | annotation(gcf,'textarrow',[0.808928571428571 0.728571428571429],... 181 | [0.49047619047619 0.434920634920635],'String','$z^{\textrm{{max}}}$',... 182 | 'Interpreter','latex',... 183 | 'FontSize',18); 184 | h = plot(ax(3),[0,1e10],zmax * ones(2,1),'k--'); 185 | uistack(h,'bottom'); 186 | 187 | % export_fig('WaveBot_caseB_results.pdf','-transparent') 188 | 189 | %% Plot geometries cross sections 190 | 191 | fig = figure('name','WaveBot_caseB_geometrities'); 192 | fig.Position = fig.Position .*[1,1,1.5,0.75]; 193 | hold on 194 | grid on 195 | ax = gca; 196 | 197 | % Plot optimal solutions 198 | for ii = 1:length(controlType) 199 | radiusOpt = x_opt(ii); 200 | xCoords = [0, radiusOpt, radiusOpt, 0.35, 0]; 201 | yCoords = [0.2, 0.2, -0.16, -0.53, -0.53]; 202 | p(ii) = plot(ax, xCoords, yCoords, 'Marker', mkrs{ii},... 203 | 'LineWidth',2,'MarkerSize',10,... 204 | 'DisplayName', controlType{ii}); 205 | end 206 | 207 | % Plot all solutions 208 | for ii = 1:length(radii) 209 | baseN = length(controlType); 210 | radius = radii(ii); 211 | xCoords = [0, radius, radius, 0.35, 0]; 212 | yCoords = [0.2, 0.2, -0.16, -0.53, -0.53]; 213 | if ii+baseN == 8+baseN 214 | p(ii+baseN) = plot(ax,xCoords, yCoords, 'ks-',... 215 | 'DisplayName','Original'); 216 | else 217 | p(ii+baseN) = plot(ax,xCoords, yCoords, 'bo-', ... 218 | 'DisplayName',num2str(ii)); 219 | end 220 | end 221 | 222 | l1 = legend([p(1), p(2), p(3), p(4), p(8+baseN)],... 223 | 'CC','P','PS', ... 224 | 'WecOptTool study geometries', 'Original geometry (Coe et al. 2016)'); 225 | set(l1,'location','southeast') 226 | 227 | xlabel('$r$ [m]','interpreter','latex') 228 | ylabel('$z$ [m]','interpreter','latex') 229 | axis equal 230 | ylim([-0.6, 0]) 231 | xlim([0, rmax]) 232 | 233 | % export_fig('WaveBot_caseB_geometries.pdf','-transparent') 234 | 235 | %% objective function 236 | 237 | function [fval, simRes, deviceHydro] = myWaveBotObjFun(x,w,SS,controlType,zmax,fmax,folderPath) 238 | 239 | % create device and simulate performance the parametric input is 240 | % [r1, r2, d1, d2] (all positive); here we specify only r1 241 | deviceHydro = designDevice('parametric', folderPath, ... 242 | x, 0.35, 0.16, 0.53, w); 243 | 244 | simRes = simulateDevice(deviceHydro, ... 245 | SS, ... 246 | controlType, ... 247 | 'interpMethod','nearest', ... 248 | 'Zmax',zmax, ... 249 | 'Fmax',fmax); 250 | if strcmp(controlType,'PS') 251 | pow =simRes.pow(:,1); 252 | else 253 | pow = simRes.pow; 254 | end 255 | 256 | % objective function value 257 | p_bar = sum(real(pow)); % average power 258 | fval = 1 * p_bar ./ (0.88 + x).^3; % r1 = 0.88 is as-built WaveBot 259 | end 260 | -------------------------------------------------------------------------------- /examples/WaveBot/WaveBot_caseC.m: -------------------------------------------------------------------------------- 1 | % Case C 2 | % This case performs a single multiobjective optimization study using a PS 3 | % controller with a constrained maximum force. The free design variables 4 | % are: 5 | % 6 | % r outer radius of the hull 7 | % FuMax maximum PTO force 8 | % 9 | % The multi-objective study finds the Pareto front for the following 10 | % responses: 11 | % 12 | % Pbar average absorbed power 13 | % volFun (r_0 + r)^3, where r_0 = 0.88 14 | % zMax maximum displacement 15 | 16 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, LLC 17 | % (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. 18 | % Government retains certain rights in this software. 19 | % 20 | % This file is part of WecOptTool. 21 | % 22 | % WecOptTool is free software: you can redistribute it and/or modify it 23 | % under the terms of the GNU General Public License as published by the 24 | % Free Software Foundation, either version 3 of the License, or (at 25 | % your option) any later version. 26 | % 27 | % WecOptTool is distributed in the hope that it will be useful, but 28 | % WITHOUT ANY WARRANTY; without even the implied warranty of 29 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 30 | % General Public License for more details. 31 | % 32 | % You should have received a copy of the GNU General Public License 33 | % along with WecOptTool. If not, see . 34 | 35 | %% define sea state of interest 36 | 37 | dw = 0.3142; 38 | nf = 50; 39 | w = dw * (1:nf)'; 40 | A = 0.125/2; 41 | wp = w(6); 42 | fp = wp/(2*pi); 43 | Tp = 1/fp; 44 | SS = WecOptTool.SeaState.regularWave(w,[A,Tp]); 45 | 46 | %% set up optimization problem 47 | 48 | rmin = 0.25; 49 | rmax = 2; 50 | r0 = 0.88; 51 | zlim = 1e4; % (inactive) 52 | 53 | nvars = 2; 54 | A = []; 55 | B = []; 56 | Aeq = []; 57 | Beq = []; 58 | LB = [rmin, 1e2]; 59 | UB = [rmax, 1e3]; 60 | NONLCON = []; 61 | opts = optimoptions('paretosearch'); 62 | opts.UseParallel = true; 63 | opts.Display = 'iter'; 64 | opts.PlotFcn = @psplotparetof; 65 | % opts.MaxFunctionEvaluations = 10; % for debugging 66 | 67 | %% run optimization solver 68 | 69 | folder = WecOptTool.AutoFolder(); 70 | 71 | rng(3) 72 | [x,fval,exitflag,output,residuals] = ... 73 | paretosearch(@(x) myWaveBotObjFun(x,w,SS, zlim,folder.path),nvars,... 74 | A,B,Aeq,Beq,LB,UB,NONLCON,opts); 75 | 76 | % Optimized values 77 | radiiOpt = x(:,1); 78 | fmaxOpt = x(:,2); 79 | % Optimized results 80 | pBar = fval(:,1); 81 | vol = fval(:,2); 82 | zmax = fval(:,3); 83 | 84 | %% Plot 3D 85 | 86 | knee_idx = 36; % a potential single solution on the Pareto front 87 | 88 | figure('color','white') 89 | hold on 90 | grid on 91 | 92 | % Pareto front 93 | scatter3(-pBar, vol, zmax, 75, zmax, 'filled','LineWidth',0.5,... 94 | 'MarkerEdgeColor','k','MarkerFaceAlpha',0.5); 95 | 96 | % potential single solution 97 | scatter3(-pBar(knee_idx), vol(knee_idx), zmax(knee_idx),150,... 98 | 'marker','+','MarkerEdgeColor','k','LineWidth',2); 99 | 100 | view([13, 18]) 101 | 102 | cb = colorbar; 103 | cb.Label.Interpreter = 'latex'; 104 | cb.Label.String = ('Max. PTO stroke, $z^{\textrm{max}}$ [m]'); 105 | xlabel('Neg. avg. power, $ - \bar{P}$ [W]', 'interpreter','latex') 106 | ylabel('Vol. fun, $(r_0 + r)^3$ [m$^3$]', 'interpreter','latex') 107 | zlabel('Max. PTO stroke, $z^{\textrm{max}}$ [m]', 'interpreter','latex') 108 | 109 | %% Plot 2D 110 | 111 | fig = figure(); 112 | fig.Position = fig.Position .* [1 1 1.5 1]*1; 113 | 114 | tiledlayout(3,4,'TileSpacing','compact','Padding','compact') 115 | axb = nexttile([3,2]); 116 | 117 | hold on 118 | grid on 119 | scatter(axb, pBar,vol,75,zmax,... 120 | 'filled',... 121 | 'MarkerEdgeColor','k',... 122 | 'MarkerFaceAlpha',0.5); 123 | 124 | scatter(axb, pBar(knee_idx),vol(knee_idx),200,... 125 | 'marker','+','MarkerEdgeColor','k','LineWidth',1.5); 126 | 127 | 128 | xlabel('Avg. power, $ \bar{P}$ [W]', 'interpreter','latex') 129 | ylabel('Vol. fun, $(r_0 + r)^3$ [m$^3$]', 'interpreter','latex') 130 | 131 | cb = colorbar; 132 | cb.Label.Interpreter = 'latex'; 133 | cb.Label.String = ('Max. PTO stroke, $z^{\textrm{max}}$ [m]'); 134 | cb.Location = 'northoutside'; 135 | 136 | set(gca,'Yscale','log') 137 | 138 | ylim([min(vol), Inf]) 139 | 140 | % annotations 141 | annotation(fig,'textarrow',[0.0813492063492065 0.113095238095238],... 142 | [0.81825396825397 0.554761904761905],'TextEdgeColor',[0 0 0],... 143 | 'TextBackgroundColor',[1 1 1],... 144 | 'String',{'Smaller stroke,','larger vol.'},... 145 | 'HorizontalAlignment','center'); 146 | annotation(fig,'textarrow',[0.0726190476190479 0.0821428571428572],... 147 | [0.276984126984128 0.104761904761905],'TextEdgeColor',[0 0 0],... 148 | 'TextBackgroundColor',[1 1 1],... 149 | 'String',{'Larger stroke,','smaller vol.'},... 150 | 'HorizontalAlignment','center'); 151 | 152 | rlbs = {'$\bar{P}$','$(r_0 + r)^3$','$z^{\textrm{max}}$'}; 153 | xlbs = {'Outer radius, $r$ [m]','Max. PTO force, $F_u^{max}$ [N]'}; 154 | 155 | for kk = 1:2*3 156 | ax(kk) = nexttile(); 157 | end 158 | ax = reshape(ax,[2,3]); 159 | 160 | for ii = 1:size(x,2) 161 | for jj = 1:size(fval,2) 162 | hold(ax(ii,jj),'on') 163 | scatter(ax(ii,jj),x(:,ii),fval(:,jj),[],zmax,... 164 | 'filled',... 165 | 'MarkerEdgeColor','k',... 166 | 'MarkerFaceAlpha',0.25); 167 | 168 | scatter(ax(ii,jj),x(knee_idx,ii),fval(knee_idx,jj),200,... 169 | 'marker','+',... 170 | 'MarkerEdgeColor','k',... 171 | 'LineWidth',1.5); 172 | 173 | if jj ~= size(fval,2) 174 | set(ax(ii,jj),'XTickLabel',[]) 175 | end 176 | 177 | if ii == 1 178 | ylabel(ax(ii,jj),rlbs{jj}, 'interpreter','latex') 179 | end 180 | end 181 | xlabel(ax(ii,jj),xlbs{ii}, 'interpreter','latex') 182 | end 183 | 184 | % exportgraphics(fig, 'WaveBot_caseC_results.pdf','ContentType','vector') 185 | 186 | %% objective function 187 | 188 | function [fval] = myWaveBotObjFun(x,w,SS,zmax,folderPath) 189 | 190 | r1 =x(1); 191 | fmax =x(2); 192 | 193 | % create device and simulate performance the parametric input is 194 | % [r1, r2, d1, d2] (all positive); here we specify only r1 195 | 196 | deviceHydro = designDevice('parametric', folderPath, ... 197 | r1, 0.35, 0.16, 0.53, w); 198 | 199 | simRes = simulateDevice(deviceHydro, ... 200 | SS, ... 201 | 'PS', ... 202 | 'interpMethod','nearest', ... 203 | 'Zmax',zmax, ... 204 | 'Fmax',fmax); 205 | % objective function value 206 | SMRY = summary(simRes); 207 | 208 | pow =simRes.pow(:,1); 209 | p_bar = sum(real(pow)); % average power 210 | 211 | fval(1) = 1 * p_bar; 212 | fval(2) = (0.88 + r1).^3;% r1 = 0.88 is the as-built WaveBot 213 | fval(3) = SMRY.MaxPos; 214 | 215 | end 216 | -------------------------------------------------------------------------------- /examples/WaveBot/designDevice.m: -------------------------------------------------------------------------------- 1 | function hydro = designDevice(type, varargin) 2 | % WaveBot WEC based on the Sandia "WaveBot" device. 3 | % 4 | % The WaveBot is a model-scale wave energy converter (WEC) tested in 5 | % the Navy's Manuevering and Sea Keeping (MASK) basin. Reports and 6 | % papers about the WaveBot are available at advweccntrls.sandia.gov. 7 | 8 | switch type 9 | 10 | case 'existing' 11 | hydro = WecOptTool.geometry.existingNEMOH(varargin{:}); 12 | case 'scalar' 13 | hydro = getHydroScalar(varargin{:}); 14 | case 'parametric' 15 | hydro = getHydroParametric(varargin{:}); 16 | otherwise 17 | error('WecOptTool:UnknownGeometryType',... 18 | 'Invalid geometry type') 19 | end 20 | 21 | end 22 | 23 | function hydro = getHydroScalar(folder, lambda, w) 24 | 25 | if w(1) == 0 26 | error('WecOptTool:UnknownGeometryType',... 27 | 'Invalid frequency vector') % TODO - more checks 28 | end 29 | 30 | r = lambda * [0, 0.88, 0.88, 0.35, 0]; 31 | z = lambda * [0.2, 0.2, -0.16, -0.53, -0.53]; 32 | 33 | % Mesh 34 | ntheta = 20; 35 | nfobj = 200; 36 | zG = 0; 37 | 38 | meshes = WecOptTool.mesh("AxiMesh", ... 39 | folder, ... 40 | r, ... 41 | z, ... 42 | ntheta, ... 43 | nfobj, ... 44 | zG, ... 45 | 1); 46 | 47 | hydro = WecOptTool.solver("NEMOH", folder, meshes, w); 48 | 49 | end 50 | 51 | function hydro = getHydroParametric(folder, r1, r2, d1, d2, w) 52 | 53 | if w(1) == 0 54 | w = w(2:end); 55 | end 56 | 57 | r = [0, r1, r1, r2, 0]; 58 | z = [0.2, 0.2, -d1, -d2, -d2]; 59 | 60 | % Mesh 61 | ntheta = 20; 62 | nfobj = 200; 63 | zG = 0; 64 | 65 | meshes = WecOptTool.mesh("AxiMesh", ... 66 | folder, ... 67 | r, ... 68 | z, ... 69 | ntheta, ... 70 | nfobj, ... 71 | zG, ... 72 | 1); 73 | 74 | hydro = WecOptTool.solver("NEMOH", folder, meshes, w); 75 | 76 | end 77 | 78 | 79 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 80 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 81 | % U.S. Government retains certain rights in this software. 82 | % 83 | % This file is part of WecOptTool. 84 | % 85 | % WecOptTool is free software: you can redistribute it and/or modify 86 | % it under the terms of the GNU General Public License as published by 87 | % the Free Software Foundation, either version 3 of the License, or 88 | % (at your option) any later version. 89 | % 90 | % WecOptTool is distributed in the hope that it will be useful, 91 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 92 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 93 | % GNU General Public License for more details. 94 | % 95 | % You should have received a copy of the GNU General Public License 96 | % along with WecOptTool. If not, see . 97 | -------------------------------------------------------------------------------- /installNemoh.m: -------------------------------------------------------------------------------- 1 | function installNemoh(nemohPath) 2 | % Adds Nemoh executables path to WecOptTool 3 | % 4 | % Args: 5 | % nemohPath (string): 6 | % path to (platform dependent) NEMOH executables 7 | % 8 | 9 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 10 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 11 | % U.S. Government retains certain rights in this software. 12 | % 13 | % This file is part of WecOptTool. 14 | % 15 | % WecOptTool is free software: you can redistribute it and/or 16 | % modify it under the terms of the GNU General Public License as 17 | % published by the Free Software Foundation, either version 3 of 18 | % the License, or (at your option) any later version. 19 | % 20 | % WecOptTool is distributed in the hope that it will be useful, 21 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | % GNU General Public License for more details. 24 | % 25 | % You should have received a copy of the GNU General Public 26 | % License along with WecOptTool. If not, see 27 | % . 28 | 29 | % Check if the a current path is set 30 | try 31 | oldNemohPath = WecOptTool.system.readConfig('nemohPath'); 32 | catch 33 | oldNemohPath = ""; 34 | end 35 | 36 | % Update the config file 37 | WecOptTool.system.writeConfig('nemohPath', nemohPath) 38 | 39 | % Check installation 40 | nemohExistFlag = WecOptTool.base.NEMOH.isNemohInPath(); 41 | 42 | if nemohExistFlag 43 | 44 | fprintf('Successfully Installed Nemoh\n'); 45 | 46 | else 47 | 48 | msg = ['Nemoh not found. Please check the specified path ' ... 49 | 'and try again. \n']; 50 | fprintf(msg); 51 | 52 | % Revert back to the old config 53 | WecOptTool.system.writeConfig('nemohPath', oldNemohPath) 54 | 55 | end 56 | 57 | end 58 | 59 | -------------------------------------------------------------------------------- /runTests.m: -------------------------------------------------------------------------------- 1 | function results = runTests(options) 2 | 3 | arguments 4 | options.reportHTML = true 5 | options.reportPDF = true 6 | end 7 | 8 | import matlab.unittest.TestRunner; 9 | import matlab.unittest.TestSuite; 10 | import matlab.unittest.plugins.TestReportPlugin; 11 | 12 | % Define test suite 13 | suite = TestSuite.fromFolder('tests', ... 14 | 'IncludingSubfolders', true); 15 | 16 | % Build the runner 17 | runner = TestRunner.withTextOutput; 18 | 19 | p = mfilename('fullpath'); 20 | [filepath, ~, ~] = fileparts(p); 21 | 22 | % Add HTML plugin 23 | if options.reportHTML 24 | htmlFolder = fullfile(filepath,'test_results'); 25 | plugin = TestReportPlugin.producingHTML(htmlFolder); 26 | runner.addPlugin(plugin); 27 | end 28 | 29 | % Add PDF plugin 30 | if options.reportPDF 31 | pdfFile = fullfile(filepath,'test_results.pdf'); 32 | plugin = TestReportPlugin.producingPDF(pdfFile); 33 | runner.addPlugin(plugin); 34 | end 35 | 36 | % Run the tests 37 | results = runner.run(suite); 38 | 39 | end 40 | 41 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 42 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 43 | % U.S. Government retains certain rights in this software. 44 | % 45 | % This file is part of WecOptTool. 46 | % 47 | % WecOptTool is free software: you can redistribute it and/or modify 48 | % it under the terms of the GNU General Public License as published by 49 | % the Free Software Foundation, either version 3 of the License, or 50 | % (at your option) any later version. 51 | % 52 | % WecOptTool is distributed in the hope that it will be useful, 53 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 54 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 55 | % GNU General Public License for more details. 56 | % 57 | % You should have received a copy of the GNU General Public License 58 | % along with WecOptTool. If not, see . 59 | 60 | -------------------------------------------------------------------------------- /tests/AutoFolderMule.m: -------------------------------------------------------------------------------- 1 | classdef AutoFolderMule < WecOptTool.AutoFolder 2 | 3 | properties 4 | varsPathPublic 5 | end 6 | 7 | methods 8 | function value = get.varsPathPublic(obj) 9 | value = obj.varsPath; 10 | end 11 | end 12 | 13 | end 14 | 15 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 16 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 17 | % U.S. Government retains certain rights in this software. 18 | % 19 | % This file is part of WecOptTool. 20 | % 21 | % WecOptTool is free software: you can redistribute it and/or modify 22 | % it under the terms of the GNU General Public License as published by 23 | % the Free Software Foundation, either version 3 of the License, or 24 | % (at your option) any later version. 25 | % 26 | % WecOptTool is distributed in the hope that it will be useful, 27 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 28 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 | % GNU General Public License for more details. 30 | % 31 | % You should have received a copy of the GNU General Public License 32 | % along with WecOptTool. If not, see . 33 | -------------------------------------------------------------------------------- /tests/AutoFolderTest.m: -------------------------------------------------------------------------------- 1 | function tests = AutoFolderTest() 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testPathDestructor(testCase) 6 | 7 | % Directory build 8 | autoFolder = WecOptTool.AutoFolder(); 9 | assertTrue(testCase, isfolder(autoFolder.path)) 10 | testDir = autoFolder.path; 11 | 12 | % Trigger destructor 13 | clear autoFolder 14 | 15 | verifyEqual(testCase, isfolder(testDir), false) 16 | 17 | end 18 | 19 | function testVarsPathExists(testCase) 20 | 21 | % Directory build 22 | autoFolder = AutoFolderMule(); 23 | verifyTrue(testCase, isfolder(autoFolder.varsPathPublic)) 24 | 25 | end 26 | 27 | function testVarsPathDestructor(testCase) 28 | 29 | % Directory build 30 | autoFolder = AutoFolderMule(); 31 | assertTrue(testCase, isfolder(autoFolder.varsPathPublic)) 32 | testDir = autoFolder.varsPathPublic; 33 | 34 | % Trigger destructor 35 | clear autoFolder 36 | 37 | verifyEqual(testCase, isfolder(testDir), false) 38 | 39 | end 40 | 41 | function testStashVar(testCase) 42 | 43 | autoFolder = AutoFolderMule(); 44 | myData.value = "Test"; 45 | autoFolder.stashVar(myData) 46 | folders = WecOptTool.system.getFolders(autoFolder.varsPathPublic, ... 47 | "absPath", true); 48 | files = dir(fullfile(folders{1}, '*.mat')); 49 | verifySubstring(testCase, files.name, "myData.mat") 50 | 51 | end 52 | 53 | function testRecoverVar(testCase) 54 | 55 | autoFolder = AutoFolderMule(); 56 | myData.value = "Test"; 57 | autoFolder.stashVar(myData) 58 | test = autoFolder.recoverVar("myData"); 59 | verifyEqual(testCase, test{1}, myData) 60 | 61 | end 62 | 63 | function testArchive(testCase) 64 | 65 | import matlab.unittest.fixtures.TemporaryFolderFixture 66 | 67 | tempFixture = testCase.applyFixture( ... 68 | TemporaryFolderFixture('PreservingOnFailure', true, ... 69 | 'WithSuffix', 'testStudySaveNEMOH')); 70 | 71 | autoFolder = WecOptTool.AutoFolder(); 72 | 73 | filePath = fullfile(autoFolder.path, 'changing.txt'); 74 | fileID = fopen(filePath,'w'); 75 | fmt = '%5d %5d %5d %5d\n'; 76 | fprintf(fileID,fmt, magic(4)); 77 | fclose(fileID); 78 | 79 | % Copy data 80 | testDir = fullfile(tempFixture.Folder, "test"); 81 | autoFolder.archive(testDir); 82 | 83 | verifyTrue(testCase, isfolder(testDir)) 84 | rmdir(testDir, 's') 85 | 86 | end 87 | 88 | function testArchiveNoCopy(testCase) 89 | 90 | import matlab.unittest.fixtures.TemporaryFolderFixture 91 | 92 | tempFixture = testCase.applyFixture( ... 93 | TemporaryFolderFixture('PreservingOnFailure', true, ... 94 | 'WithSuffix', 'testStudyNoSopyNEMOH')); 95 | 96 | autoFolder = WecOptTool.AutoFolder(); 97 | 98 | % Attempt to copy data 99 | testDir = fullfile(tempFixture.Folder, "test"); 100 | autoFolder.archive(testDir); 101 | 102 | verifyFalse(testCase, isfolder(testDir)) 103 | 104 | end 105 | 106 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 107 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 108 | % U.S. Government retains certain rights in this software. 109 | % 110 | % This file is part of WecOptTool. 111 | % 112 | % WecOptTool is free software: you can redistribute it and/or modify 113 | % it under the terms of the GNU General Public License as published by 114 | % the Free Software Foundation, either version 3 of the License, or 115 | % (at your option) any later version. 116 | % 117 | % WecOptTool is distributed in the hope that it will be useful, 118 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 119 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 120 | % GNU General Public License for more details. 121 | % 122 | % You should have received a copy of the GNU General Public License 123 | % along with WecOptTool. If not, see . 124 | -------------------------------------------------------------------------------- /tests/PlotsTest.m: -------------------------------------------------------------------------------- 1 | classdef PlotsTest < matlab.unittest.TestCase 2 | 3 | properties 4 | OriginalDefault 5 | end 6 | 7 | methods (TestMethodSetup) 8 | function killPlots (~) 9 | set(0,'DefaultFigureVisible','off'); 10 | end 11 | end 12 | 13 | methods (TestMethodTeardown) 14 | function loadPlots (~) 15 | set(0,'DefaultFigureVisible','on'); 16 | end 17 | end 18 | 19 | methods(TestClassSetup) 20 | function captureVisibility(testCase) 21 | testCase.OriginalDefault = get(0,'DefaultFigureVisible'); 22 | end 23 | end 24 | 25 | methods(TestClassTeardown) 26 | function checkVisibilityRestored(testCase) 27 | testCase.assertEqual(get(0,'DefaultFigureVisible'), ... 28 | testCase.OriginalDefault); 29 | end 30 | end 31 | 32 | methods(Test) 33 | 34 | function testPowerPerFreqSingleSpectrum(testCase) 35 | 36 | % Fake some inputs 37 | spectrum = WecOptTool.SeaState.exampleSpectrum(); 38 | input.w = spectrum.w; 39 | input.powPerFreq = spectrum.S; 40 | 41 | WecOptTool.plot.powerPerFreq(input); 42 | 43 | end 44 | 45 | function testPowerPerFreqMultiSpectra(testCase) 46 | 47 | % Fake some inputs 48 | spectra = WecOptTool.SeaState.example8Spectra(); 49 | NSS = length(spectra); 50 | 51 | for i = 1:NSS 52 | spectrum = spectra(i); 53 | input(i).w = spectrum.w; 54 | input(i).powPerFreq = spectrum.S(2:end); 55 | end 56 | 57 | WecOptTool.plot.powerPerFreq(input); 58 | 59 | end 60 | 61 | function testPlotMesh(testCase) 62 | 63 | meshes = load('meshes.mat'); 64 | WecOptTool.plot.plotMesh(meshes.meshes); 65 | 66 | end 67 | 68 | function testPlotMeshEmpty(testCase) 69 | WecOptTool.plot.plotMesh([]); 70 | end 71 | 72 | end 73 | 74 | end 75 | 76 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 77 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 78 | % U.S. Government retains certain rights in this software. 79 | % 80 | % This file is part of WecOptTool. 81 | % 82 | % WecOptTool is free software: you can redistribute it and/or modify 83 | % it under the terms of the GNU General Public License as published by 84 | % the Free Software Foundation, either version 3 of the License, or 85 | % (at your option) any later version. 86 | % 87 | % WecOptTool is distributed in the hope that it will be useful, 88 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 89 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 90 | % GNU General Public License for more details. 91 | % 92 | % You should have received a copy of the GNU General Public License 93 | % along with WecOptTool. If not, see . 94 | -------------------------------------------------------------------------------- /tests/base/TempFolderTest.m: -------------------------------------------------------------------------------- 1 | function tests = TempFolderTest() 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testFolderExists(testCase) 6 | 7 | tempFolder = WecOptTool.base.TempFolder(); 8 | verifyTrue(testCase, isfolder(tempFolder.path)) 9 | 10 | end 11 | 12 | function testBase(testCase) 13 | 14 | tempFolder = WecOptTool.base.TempFolder(tempdir); 15 | verifySubstring(testCase, tempFolder.path, tempdir) 16 | 17 | end 18 | 19 | 20 | function testUnique(testCase) 21 | 22 | tempFolder1 = WecOptTool.base.TempFolder(); 23 | tempFolder2 = WecOptTool.base.TempFolder(); 24 | 25 | verifyNotEqual(testCase, tempFolder1.path, tempFolder2.path) 26 | 27 | end 28 | 29 | function testBaseUnique(testCase) 30 | 31 | tempFolder1 = WecOptTool.base.TempFolder(tempdir); 32 | tempFolder2 = WecOptTool.base.TempFolder(tempdir); 33 | 34 | verifyNotEqual(testCase, tempFolder1.path, tempFolder2.path) 35 | 36 | end 37 | 38 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 39 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 40 | % U.S. Government retains certain rights in this software. 41 | % 42 | % This file is part of WecOptTool. 43 | % 44 | % WecOptTool is free software: you can redistribute it and/or modify 45 | % it under the terms of the GNU General Public License as published by 46 | % the Free Software Foundation, either version 3 of the License, or 47 | % (at your option) any later version. 48 | % 49 | % WecOptTool is distributed in the hope that it will be useful, 50 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 51 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 52 | % GNU General Public License for more details. 53 | % 54 | % You should have received a copy of the GNU General Public License 55 | % along with WecOptTool. If not, see . 56 | -------------------------------------------------------------------------------- /tests/examples/RM3/ExamplesTest.m: -------------------------------------------------------------------------------- 1 | classdef ExamplesTest < matlab.unittest.TestCase 2 | 3 | properties 4 | OriginalDefault 5 | end 6 | 7 | methods (TestMethodSetup) 8 | function killPlots (~) 9 | set(0,'DefaultFigureVisible','off'); 10 | end 11 | end 12 | 13 | methods(TestClassSetup) 14 | 15 | function captureVisibility(testCase) 16 | testCase.OriginalDefault = get(0,'DefaultFigureVisible'); 17 | end 18 | 19 | end 20 | 21 | methods(TestClassTeardown) 22 | function checkVisibilityRestored(testCase) 23 | set(0,'DefaultFigureVisible',testCase.OriginalDefault); 24 | testCase.assertEqual(get(0,'DefaultFigureVisible'), ... 25 | testCase.OriginalDefault); 26 | end 27 | end 28 | 29 | methods(Test) 30 | 31 | function testBasic(testCase) 32 | 33 | examplePath = fullfile(WecOptTool.system.getSrcRootPath(), ... 34 | "examples", ... 35 | "RM3", ... 36 | "basic.m"); 37 | 38 | % This fills the function namespace with the variables defined 39 | % in the example 40 | run(examplePath); 41 | 42 | verifyEqual(testCase, ... 43 | r(1), 4.046658023714033e+06, ... 44 | 'RelTol', 5 * eps) 45 | 46 | end 47 | 48 | function testOptimization(testCase) 49 | 50 | examplePath = fullfile(WecOptTool.system.getSrcRootPath(), ... 51 | "examples", ... 52 | "RM3", ... 53 | "optimization.m"); 54 | 55 | % This fills the function namespace with the variables defined 56 | % in the example 57 | run(examplePath); 58 | 59 | verifyEqual(testCase, ... 60 | bestPerformances(1).x, [5 7.5 1.125 42], ... 61 | 'RelTol', 5 * eps) 62 | 63 | 64 | end 65 | 66 | end 67 | 68 | end 69 | 70 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 71 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 72 | % U.S. Government retains certain rights in this software. 73 | % 74 | % This file is part of WecOptTool. 75 | % 76 | % WecOptTool is free software: you can redistribute it and/or modify 77 | % it under the terms of the GNU General Public License as published by 78 | % the Free Software Foundation, either version 3 of the License, or 79 | % (at your option) any later version. 80 | % 81 | % WecOptTool is distributed in the hope that it will be useful, 82 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 83 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 84 | % GNU General Public License for more details. 85 | % 86 | % You should have received a copy of the GNU General Public License 87 | % along with WecOptTool. If not, see . 88 | -------------------------------------------------------------------------------- /tests/examples/RM3/ParametricTest.m: -------------------------------------------------------------------------------- 1 | classdef ParametricTest < matlab.unittest.TestCase 2 | 3 | properties 4 | SS 5 | performanceCC 6 | performanceP 7 | performancePS 8 | folder 9 | rundir 10 | end 11 | 12 | methods(TestClassSetup) 13 | 14 | function getPower(testCase) 15 | 16 | import matlab.unittest.fixtures.PathFixture 17 | 18 | addFolder = fullfile(WecOptTool.system.getSrcRootPath(), ... 19 | "examples", ... 20 | "RM3"); 21 | testCase.applyFixture(PathFixture(addFolder)); 22 | 23 | testCase.SS = WecOptTool.SeaState.exampleSpectrum( ... 24 | "extendFrequencies", 2, ... 25 | "resampleByStep", 0.05); 26 | w = testCase.SS.getRegularFrequencies(0.5); 27 | testCase.folder = WecOptTool.AutoFolder(); 28 | 29 | deviceHydro = designDevice('parametric', ... 30 | testCase.folder.path, ... 31 | 10, 15, 3, 42, ... 32 | w); 33 | 34 | testCase.rundir = deviceHydro.runDirectory; 35 | 36 | testCase.performanceP = simulateDevice(deviceHydro, ... 37 | testCase.SS, ... 38 | 'P'); 39 | 40 | testCase.performanceCC = simulateDevice(deviceHydro, ... 41 | testCase.SS, ... 42 | 'CC'); 43 | 44 | delta_Zmax = 10; 45 | delta_Fmax = 1e9; 46 | 47 | testCase.performancePS = simulateDevice(deviceHydro, ... 48 | testCase.SS, ... 49 | 'PS', ... 50 | delta_Zmax, ... 51 | delta_Fmax, ... 52 | 'iter', ... 53 | 1e-4); 54 | 55 | end 56 | 57 | end 58 | 59 | methods(Test) 60 | 61 | function test_existingRunFiles(testCase) 62 | 63 | tol = 1e-12; 64 | madeFile = testCase.rundir; 65 | 66 | deviceHydro = designDevice('existing', madeFile); 67 | newPerformance = simulateDevice(deviceHydro, ... 68 | testCase.SS, ... 69 | 'CC'); 70 | 71 | verifyEqual(testCase, ... 72 | testCase.performanceCC, ... 73 | newPerformance, ... 74 | 'RelTol', tol); 75 | 76 | end 77 | 78 | function test_runParametric(testCase) 79 | 80 | expSol = 4.759798816032207e+06; 81 | pow = sum(testCase.performanceCC.powPerFreq); 82 | verifyEqual(testCase, pow, expSol, 'RelTol', 0.001) 83 | 84 | end 85 | 86 | function test_bounds(testCase) 87 | 88 | % Test that P <= CC 89 | lower = sum(testCase.performanceP.powPerFreq); 90 | upper = sum(testCase.performanceCC.powPerFreq); 91 | verifyGreaterThanOrEqual(testCase, upper, lower) 92 | 93 | end 94 | 95 | 96 | function test_lower_bound(testCase) 97 | 98 | % The P controller should be the lower bound for PS 99 | expSol = sum(testCase.performanceP.powPerFreq); 100 | pow = sum(testCase.performancePS.powPerFreq); 101 | verifyGreaterThanOrEqual(testCase, pow, expSol) 102 | 103 | end 104 | 105 | function test_upper_bound(testCase) 106 | 107 | % The CC controller should be the upper bound for PS 108 | expSol = sum(testCase.performanceCC.powPerFreq); 109 | pow = sum(testCase.performancePS.powPerFreq); 110 | verifyLessThanOrEqual(testCase, pow, expSol) 111 | 112 | end 113 | 114 | end 115 | 116 | end 117 | 118 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 119 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 120 | % U.S. Government retains certain rights in this software. 121 | % 122 | % This file is part of WecOptTool. 123 | % 124 | % WecOptTool is free software: you can redistribute it and/or modify 125 | % it under the terms of the GNU General Public License as published by 126 | % the Free Software Foundation, either version 3 of the License, or 127 | % (at your option) any later version. 128 | % 129 | % WecOptTool is distributed in the hope that it will be useful, 130 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 131 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 132 | % GNU General Public License for more details. 133 | % 134 | % You should have received a copy of the GNU General Public License 135 | % along with WecOptTool. If not, see . 136 | -------------------------------------------------------------------------------- /tests/examples/RM3/optionsTest.m: -------------------------------------------------------------------------------- 1 | function tests = optionsTest() 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testVerify_CC(testCase) 6 | 7 | import matlab.unittest.fixtures.PathFixture 8 | 9 | addFolder = fullfile(WecOptTool.system.getSrcRootPath(), ... 10 | "examples", ... 11 | "RM3"); 12 | testCase.applyFixture(PathFixture(addFolder)); 13 | 14 | SS = WecOptTool.SeaState.exampleSpectrum(); 15 | 16 | deviceHydro = designDevice('scalar', 1); 17 | performance = simulateDevice(deviceHydro, SS, 'CC'); 18 | pow = sum(performance.powPerFreq); 19 | 20 | expSol = 4.072835515358689e+06; 21 | verifyEqual(testCase, pow, expSol, 'RelTol', 0.001) 22 | 23 | end 24 | 25 | function testVerify_damping(testCase) 26 | 27 | import matlab.unittest.fixtures.PathFixture 28 | 29 | addFolder = fullfile(WecOptTool.system.getSrcRootPath(), ... 30 | "examples", ... 31 | "RM3"); 32 | testCase.applyFixture(PathFixture(addFolder)); 33 | 34 | SS = WecOptTool.SeaState.exampleSpectrum(); 35 | 36 | deviceHydro = designDevice('scalar', 1); 37 | performance = simulateDevice(deviceHydro, SS, 'P'); 38 | pow = sum(performance.powPerFreq); 39 | 40 | expSol = 2.144693683724375e+06; 41 | verifyEqual(testCase, pow, expSol, 'RelTol', 0.001) 42 | 43 | end 44 | 45 | % function testVerify_SeaStates(testCase) 46 | % % Load Sea States 47 | % SS = load('Y:\WecOptTool\toolbox\+WecOptLib\+tests\+data\sea-states.mat'); 48 | % 49 | % %S.ph = rand(length(S.w),1)* 2 * pi; 50 | % RM3Device = WecOptLib.models.RM3DeviceModel(); 51 | % WECpow = RM3Device.getPower(S,'P','scalar',1); 52 | % expSol = -1.349990052717686e+06; 53 | % verifyEqual(testCase, WECpow, expSol, 'RelTol', 0.001) 54 | % end 55 | 56 | function testVerify_PS(testCase) 57 | 58 | import matlab.unittest.fixtures.PathFixture 59 | 60 | addFolder = fullfile(WecOptTool.system.getSrcRootPath(), ... 61 | "examples", ... 62 | "RM3"); 63 | testCase.applyFixture(PathFixture(addFolder)); 64 | 65 | SS = WecOptTool.SeaState.exampleSpectrum("resampleByError", 0.08); 66 | 67 | deviceHydro = designDevice('scalar', 1); 68 | performance = simulateDevice(deviceHydro, SS, 'PS', 10, 1e9); 69 | pow = sum(performance.powPerFreq); 70 | 71 | expSol = 4.072812570315526e+06; 72 | verifyEqual(testCase, pow, expSol, 'RelTol', 0.001) 73 | 74 | end 75 | 76 | function test_RM3_mass(testCase) 77 | 78 | import matlab.unittest.fixtures.PathFixture 79 | 80 | addFolder = fullfile(WecOptTool.system.getSrcRootPath(), ... 81 | "examples", ... 82 | "RM3"); 83 | testCase.applyFixture(PathFixture(addFolder)); 84 | 85 | deviceHydro = designDevice('scalar', 1); 86 | mass = sum(deviceHydro.Vo * deviceHydro.rho); 87 | 88 | expSol = 1.652838125000000e6; 89 | verifyEqual(testCase, mass, expSol, 'RelTol', 0.001) 90 | 91 | end 92 | 93 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 94 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 95 | % U.S. Government retains certain rights in this software. 96 | % 97 | % This file is part of WecOptTool. 98 | % 99 | % WecOptTool is free software: you can redistribute it and/or modify 100 | % it under the terms of the GNU General Public License as published by 101 | % the Free Software Foundation, either version 3 of the License, or 102 | % (at your option) any later version. 103 | % 104 | % WecOptTool is distributed in the hope that it will be useful, 105 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 106 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 107 | % GNU General Public License for more details. 108 | % 109 | % You should have received a copy of the GNU General Public License 110 | % along with WecOptTool. If not, see . 111 | -------------------------------------------------------------------------------- /tests/examples/RM3/parametricBugTest.m: -------------------------------------------------------------------------------- 1 | function tests = parametricBugTest() 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function test_damping_warning(testCase) 6 | 7 | import matlab.unittest.fixtures.PathFixture 8 | 9 | addFolder = fullfile(WecOptTool.system.getSrcRootPath(), ... 10 | "examples", ... 11 | "RM3"); 12 | testCase.applyFixture(PathFixture(addFolder)); 13 | 14 | SS = WecOptTool.SeaState.exampleSpectrum("extendFrequencies", 2, ... 15 | "resampleByStep", 0.05); 16 | 17 | w = SS.getRegularFrequencies(0.5); 18 | folder = WecOptTool.AutoFolder(); 19 | 20 | deviceHydro = designDevice('parametric', ... 21 | folder.path, ... 22 | 14.76, 15.71, 2.58, 37.27, ... 23 | w); 24 | 25 | testf = @() simulateDevice(deviceHydro, ... 26 | SS, ... 27 | 'P'); 28 | verifyWarning(testCase, testf, 'WecOptTool:RM3:BadDamping'); 29 | 30 | end 31 | 32 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 33 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 34 | % U.S. Government retains certain rights in this software. 35 | % 36 | % This file is part of WecOptTool. 37 | % 38 | % WecOptTool is free software: you can redistribute it and/or modify 39 | % it under the terms of the GNU General Public License as published by 40 | % the Free Software Foundation, either version 3 of the License, or 41 | % (at your option) any later version. 42 | % 43 | % WecOptTool is distributed in the hope that it will be useful, 44 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 45 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 46 | % GNU General Public License for more details. 47 | % 48 | % You should have received a copy of the GNU General Public License 49 | % along with WecOptTool. If not, see . 50 | -------------------------------------------------------------------------------- /tests/examples/WaveBot/ExamplesTest.m: -------------------------------------------------------------------------------- 1 | classdef ExamplesTest < matlab.unittest.TestCase 2 | 3 | properties 4 | OriginalDefault 5 | end 6 | 7 | methods (TestMethodSetup) 8 | function killPlots (~) 9 | set(0,'DefaultFigureVisible','off'); 10 | end 11 | end 12 | 13 | methods(TestClassSetup) 14 | 15 | function captureVisibility(testCase) 16 | testCase.OriginalDefault = get(0,'DefaultFigureVisible'); 17 | end 18 | 19 | end 20 | 21 | methods(TestClassTeardown) 22 | function checkVisibilityRestored(testCase) 23 | set(0,'DefaultFigureVisible',testCase.OriginalDefault); 24 | testCase.assertEqual(get(0,'DefaultFigureVisible'), ... 25 | testCase.OriginalDefault); 26 | end 27 | end 28 | 29 | methods(Test) 30 | 31 | function testWaveBot_caseA(testCase) 32 | 33 | examplePath = fullfile(WecOptTool.system.getSrcRootPath(), ... 34 | "examples", ... 35 | "WaveBot", ... 36 | "WaveBot_caseA.m"); 37 | 38 | % This fills the function namespace with the variables defined 39 | % in the example 40 | run(examplePath); 41 | 42 | verifyEqual(testCase, length(r), 3) 43 | 44 | end 45 | 46 | end 47 | 48 | end 49 | 50 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 51 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 52 | % U.S. Government retains certain rights in this software. 53 | % 54 | % This file is part of WecOptTool. 55 | % 56 | % WecOptTool is free software: you can redistribute it and/or modify 57 | % it under the terms of the GNU General Public License as published by 58 | % the Free Software Foundation, either version 3 of the License, or 59 | % (at your option) any later version. 60 | % 61 | % WecOptTool is distributed in the hope that it will be useful, 62 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 63 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 64 | % GNU General Public License for more details. 65 | % 66 | % You should have received a copy of the GNU General Public License 67 | % along with WecOptTool. If not, see . 68 | -------------------------------------------------------------------------------- /tests/math/bisectionTest.m: -------------------------------------------------------------------------------- 1 | function tests = bisectionTest() 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testIdentity(testCase) 6 | 7 | import matlab.unittest.constraints.IsEqualTo 8 | import matlab.unittest.constraints.AbsoluteTolerance 9 | 10 | f = @(x) x; 11 | result = WecOptTool.math.bisection(f, -1, 1); 12 | 13 | testCase.assertThat(result, ... 14 | IsEqualTo(0, 'Within', AbsoluteTolerance(1e-10))) 15 | 16 | end 17 | 18 | function testParabola(testCase) 19 | 20 | import matlab.unittest.constraints.IsEqualTo 21 | import matlab.unittest.constraints.AbsoluteTolerance 22 | 23 | f = @(x) x^2 - 1; 24 | result = WecOptTool.math.bisection(f, 0, 10); 25 | 26 | testCase.assertThat(result, ... 27 | IsEqualTo(1, 'Within', AbsoluteTolerance(1e-10))) 28 | 29 | end 30 | 31 | function testBadInterval(testCase) 32 | 33 | f = @(x) x; 34 | eID = "WecOptTool:bisection:badInterval"; 35 | verifyError(testCase, ... 36 | @() WecOptTool.math.bisection(f, 0.5, 1), ... 37 | eID) 38 | 39 | end 40 | 41 | function testSearchSpaceClosed(testCase) 42 | 43 | function f = step(x) 44 | if x > 0 45 | f = 1; 46 | else 47 | f = -1; 48 | end 49 | end 50 | 51 | eID = "WecOptTool:bisection:searchSpaceClosed"; 52 | verifyError(testCase, ... 53 | @() WecOptTool.math.bisection(@step, -1, 1), ... 54 | eID) 55 | 56 | end 57 | 58 | function testTooManyIterations(testCase) 59 | 60 | function f = step(x) 61 | if x > 0 62 | f = 1; 63 | else 64 | f = -1; 65 | end 66 | end 67 | 68 | eID = "WecOptTool:bisection:tooManyIterations"; 69 | verifyError(testCase, ... 70 | @() WecOptTool.math.bisection(@step, -1, 1, ... 71 | "nmax", 2), ... 72 | eID) 73 | 74 | end 75 | 76 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 77 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 78 | % U.S. Government retains certain rights in this software. 79 | % 80 | % This file is part of WecOptTool. 81 | % 82 | % WecOptTool is free software: you can redistribute it and/or modify 83 | % it under the terms of the GNU General Public License as published by 84 | % the Free Software Foundation, either version 3 of the License, or 85 | % (at your option) any later version. 86 | % 87 | % WecOptTool is distributed in the hope that it will be useful, 88 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 89 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 90 | % GNU General Public License for more details. 91 | % 92 | % You should have received a copy of the GNU General Public License 93 | % along with WecOptTool. If not, see . 94 | -------------------------------------------------------------------------------- /tests/meshes.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SNL-WaterPower/WecOptTool-MATLAB/0a9faa189f8570444fac5ebe0da2a9fcd94958eb/tests/meshes.mat -------------------------------------------------------------------------------- /tests/meshsolver/getNemohCylinderTest.m: -------------------------------------------------------------------------------- 1 | classdef getNemohCylinderTest < matlab.unittest.TestCase 2 | % Notes: 3 | % 4 | % Tests cylinder shaped geometries 5 | % 6 | % All test functions use a relative tolerance. to adjust the tolerance, 7 | % modify the `tol` property of the class. 8 | % 9 | % Currently all verifications are based off of run data from a working 10 | % version. A more analytic approach may be taken at a later date. 11 | 12 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 13 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 14 | % U.S. Government retains certain rights in this software. 15 | % 16 | % This file is part of WecOptTool. 17 | % 18 | % WecOptTool is free software: you can redistribute it and/or 19 | % modify it under the terms of the GNU General Public License as 20 | % published by the Free Software Foundation, either version 3 of 21 | % the License, or (at your option) any later version. 22 | % 23 | % WecOptTool is distributed in the hope that it will be useful, 24 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 | % GNU General Public License for more details. 27 | % 28 | % You should have received a copy of the GNU General Public 29 | % License along with WecOptTool. If not, see 30 | % . 31 | 32 | properties 33 | tol = .001 34 | w = linspace(0.1,1,10) 35 | hydro 36 | end 37 | 38 | methods(TestClassSetup) 39 | 40 | function runNEMOH(testCase) 41 | 42 | import matlab.unittest.fixtures.TemporaryFolderFixture 43 | tempFixture = testCase.applyFixture( ... 44 | TemporaryFolderFixture('PreservingOnFailure', true, ... 45 | 'WithSuffix', 'testCylinderM')); 46 | 47 | r = [0 1 1 0]; 48 | z = [.5 .5 -.5 -.5]; 49 | ntheta = 20; 50 | nfobj = 200; 51 | zG = 0; 52 | 53 | meshes = WecOptTool.mesh("AxiMesh", ... 54 | tempFixture.Folder, ... 55 | r, ... 56 | z, ... 57 | ntheta, ... 58 | nfobj, ... 59 | zG, ... 60 | 1); 61 | 62 | testCase.hydro = WecOptTool.solver("NEMOH", ... 63 | tempFixture.Folder, ... 64 | meshes, ... 65 | testCase.w); 66 | 67 | end 68 | 69 | end 70 | 71 | methods(Test) 72 | 73 | function testCylinderM(testCase) 74 | 75 | mAct = testCase.hydro.Vo * testCase.hydro.rho; 76 | mExp = 1602.74022500000; 77 | 78 | verifyEqual(testCase, mAct, mExp, 'RelTol', testCase.tol) 79 | 80 | end 81 | 82 | 83 | function testCylinderA(testCase) 84 | 85 | AAct = squeeze(testCase.hydro.A(3,3,:)) * testCase.hydro.rho; 86 | 87 | %expected value off of previous runs 88 | AExp = [2.449950000000000e+03;... 89 | 2.466340000000000e+03;... 90 | 2.479139000000000e+03;... 91 | 2.502448000000000e+03;... 92 | 2.518107000000000e+03;... 93 | 2.526768000000000e+03;... 94 | 2.530628000000000e+03;... 95 | 2.526432000000000e+03;... 96 | 2.514688000000000e+03;... 97 | 2.496468000000000e+03]; 98 | 99 | verifyEqual(testCase, AAct, AExp, 'RelTol', testCase.tol) 100 | 101 | end 102 | 103 | function testCylinderAinf(testCase) 104 | 105 | AinfAct = testCase.hydro.Ainf(3,3) * testCase.hydro.rho; 106 | AinfExp = 2.496468000000000e+03; 107 | 108 | verifyEqual(testCase, AinfAct, AinfExp, 'RelTol', testCase.tol) 109 | 110 | end 111 | 112 | function testCylinderB(testCase) 113 | 114 | BAct = squeeze(testCase.hydro.B(3,3,:)).*testCase.w' * ... 115 | testCase.hydro.rho; 116 | BExp = [0.509248900000000;... 117 | 4.04226400000000;... 118 | 13.4646100000000;... 119 | 31.3241400000000;... 120 | 59.7084300000000;... 121 | 100.121500000000;... 122 | 153.377200000000;... 123 | 219.584900000000;... 124 | 298.097900000000;... 125 | 387.615300000000]; 126 | 127 | verifyEqual(testCase, BAct, BExp, 'RelTol', testCase.tol) 128 | 129 | end 130 | 131 | function testCylinderEx(testCase) 132 | 133 | ExAct = squeeze(testCase.hydro.ex(3,1,:)) * ... 134 | testCase.hydro.rho * ... 135 | testCase.hydro.g; 136 | ExExp = [31405.2399999587 + 0.0509254181638977i;... 137 | 31283.0899895515 + 0.808531169306684i;... 138 | 31078.8897373919 + 4.04019042295150i;... 139 | 30790.5674486798 + 12.5344804511268i;... 140 | 30419.5153310345 + 29.8738322913427i;... 141 | 29967.3696654497 + 60.1343427919986i;... 142 | 29435.7036000245 + 107.528514833500i;... 143 | 28829.1224344311 + 176.055037363224i;... 144 | 28152.4237611598 + 269.115469988388i;... 145 | 27410.4363488219 + 389.247231437354i]; 146 | 147 | verifyEqual(testCase, ExAct, ExExp, 'RelTol', testCase.tol); 148 | 149 | end 150 | 151 | function testCylinderC(testCase) 152 | 153 | CAct = testCase.hydro.C(3,3) * testCase.hydro.rho * ... 154 | testCase.hydro.g; 155 | CExp = 3.144575000000000e+04; 156 | verifyEqual(testCase, CAct, CExp, 'RelTol', testCase.tol); 157 | 158 | end 159 | 160 | end 161 | 162 | end 163 | 164 | 165 | -------------------------------------------------------------------------------- /tests/meshsolver/getNemohSphereTest.m: -------------------------------------------------------------------------------- 1 | classdef getNemohSphereTest < matlab.unittest.TestCase 2 | % Notes: 3 | % 4 | % Tests sphere shaped geometries. 5 | % 6 | % All test functions use a relative tolerance. to adjust the tolerance, 7 | % modify the `tol` property of the class. 8 | % 9 | % Currently all verifications are based off of run data from a working 10 | % version. A more analytic approach may be taken at a later date. 11 | 12 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 13 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 14 | % U.S. Government retains certain rights in this software. 15 | % 16 | % This file is part of WecOptTool. 17 | % 18 | % WecOptTool is free software: you can redistribute it and/or 19 | % modify it under the terms of the GNU General Public License as 20 | % published by the Free Software Foundation, either version 3 of 21 | % the License, or (at your option) any later version. 22 | % 23 | % WecOptTool is distributed in the hope that it will be useful, 24 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 | % GNU General Public License for more details. 27 | % 28 | % You should have received a copy of the GNU General Public 29 | % License along with WecOptTool. If not, see 30 | % . 31 | 32 | properties 33 | tol = .001 34 | w = linspace(0.1,1,10) 35 | hydro 36 | end 37 | 38 | methods(TestClassSetup) 39 | 40 | function runNEMOH(testCase) 41 | 42 | import matlab.unittest.fixtures.TemporaryFolderFixture 43 | tempFixture = testCase.applyFixture( ... 44 | TemporaryFolderFixture('PreservingOnFailure', true, ... 45 | 'WithSuffix', 'testCylinderM')); 46 | 47 | n = 40; 48 | 49 | % using n points, preallocating space for speed. 50 | z = 1:n; 51 | r = 1:n; 52 | 53 | % want the top and bottom of sphere to be accounted for 54 | z(1) = 1; 55 | z(n) = -1; 56 | r(1) = 0; 57 | r(n) = 0; 58 | 59 | %chebyshev node formula: 60 | %for k in 1..n 61 | %zk = cos((2k-1)/2n*pi) 62 | 63 | %using n-2 chebyshev nodes, to round out the array of size n 64 | 65 | for k = 1:(n-2) 66 | zk = cos((2*k-1)/(2*(n-2)) * pi); 67 | z(k+1) = zk; 68 | r(k+1) = sqrt(1 - zk^2); 69 | end 70 | 71 | ntheta = 20; 72 | nfobj = 200; 73 | zG = 0; 74 | 75 | meshes = WecOptTool.mesh("AxiMesh", ... 76 | tempFixture.Folder, ... 77 | r, ... 78 | z, ... 79 | ntheta, ... 80 | nfobj, ... 81 | zG, ... 82 | 1); 83 | 84 | testCase.hydro = WecOptTool.solver("NEMOH", ... 85 | tempFixture.Folder, ... 86 | meshes, ... 87 | testCase.w); 88 | 89 | end 90 | 91 | end 92 | 93 | methods(Test) 94 | 95 | function testSphereA(testCase) 96 | 97 | AAct = squeeze(testCase.hydro.A(3,3,:)) * testCase.hydro.rho; 98 | AExp = [1.805080000000000e+03;... 99 | 1.822259000000000e+03;... 100 | 1.846489000000000e+03;... 101 | 1.866336000000000e+03;... 102 | 1.882618000000000e+03;... 103 | 1.893489000000000e+03;... 104 | 1.897963000000000e+03;... 105 | 1.895358000000000e+03;... 106 | 1.884580000000000e+03;... 107 | 1.866094000000000e+03]; 108 | 109 | verifyEqual(testCase, AAct, AExp, 'RelTol', testCase.tol) 110 | 111 | end 112 | 113 | function testSphereAinf(testCase) 114 | 115 | AinfAct = testCase.hydro.Ainf(3,3) * testCase.hydro.rho; 116 | AinfExp = 1.866094000000000e+03; 117 | 118 | verifyEqual(testCase, AinfAct, AinfExp, 'RelTol', testCase.tol) 119 | 120 | end 121 | 122 | function testSphereB(testCase) 123 | 124 | BAct = squeeze(testCase.hydro.B(3,3,:)).*testCase.w' * ... 125 | testCase.hydro.rho; 126 | BExp = [0.517412700000000;... 127 | 4.108027000000001;... 128 | 13.687960000000000;... 129 | 31.861250000000002;... 130 | 60.774350000000000;... 131 | 1.019905000000000e+02;... 132 | 1.564007000000000e+02;... 133 | 2.241753000000000e+02;... 134 | 3.047622000000000e+02;... 135 | 3.969600000000000e+02]; 136 | 137 | verifyEqual(testCase, BAct, BExp, 'RelTol', testCase.tol); 138 | 139 | end 140 | 141 | function testSphereEx(testCase) 142 | 143 | ExAct = squeeze(testCase.hydro.ex(3,1,:)) * ... 144 | testCase.hydro.rho * testCase.hydro.g; 145 | ExExp = [3.135264999995731e+04 + 5.174237563772652e-02i;... 146 | 3.123397998919338e+04 + 8.216251484554422e-01i;... 147 | 3.103439972829488e+04 + 4.106630071455531e+00i;... 148 | 3.075387735867814e+04 + 1.274604976429039e+01i;... 149 | 3.039233480194188e+04 + 3.039422925936637e+01i;... 150 | 2.995119743334907e+04 + 6.122006325009694e+01i;... 151 | 2.943299609927892e+04 + 1.095575640094596e+02i;... 152 | 2.884138117499728e+04 + 1.795407533474796e+02i;... 153 | 2.818175074881988e+04 + 2.747483930624004e+02i;... 154 | 2.745981680392228e+04 + 3.979351517871062e+02i]; 155 | 156 | verifyEqual(testCase, ExAct, ExExp, 'RelTol', testCase.tol) 157 | 158 | end 159 | 160 | function testSphereC(testCase) 161 | 162 | CAct = testCase.hydro.C(3,3) * testCase.hydro.rho * ... 163 | testCase.hydro.g; 164 | CExp = 3.139205000000000e+04; 165 | 166 | verifyEqual(testCase, CAct, CExp, 'RelTol', testCase.tol) 167 | 168 | end 169 | 170 | end 171 | 172 | end 173 | 174 | 175 | -------------------------------------------------------------------------------- /tests/meshsolver/getNemohTest.m: -------------------------------------------------------------------------------- 1 | function tests = getNemohTest 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testNoExtraFigures(testCase) 6 | 7 | import matlab.unittest.fixtures.TemporaryFolderFixture 8 | 9 | tempFixture = testCase.applyFixture( ... 10 | TemporaryFolderFixture('PreservingOnFailure', true, ... 11 | 'WithSuffix', 'testNoExtraFigures')); 12 | 13 | h = findobj('type','figure'); 14 | nExpected = length(h); 15 | 16 | w = 0.1; 17 | r=[0 1 1 0]; 18 | z=[.5 .5 -.5 -.5]; 19 | 20 | ntheta = 20; 21 | nfobj = 200; 22 | zG = 0; 23 | 24 | meshes = WecOptTool.mesh("AxiMesh", ... 25 | tempFixture.Folder, ... 26 | r, ... 27 | z, ... 28 | ntheta, ... 29 | nfobj, ... 30 | zG, ... 31 | 1); 32 | 33 | WecOptTool.solver("NEMOH", ... 34 | tempFixture.Folder, ... 35 | meshes, ... 36 | w); 37 | 38 | h = findobj('type','figure'); 39 | nActual = length(h); 40 | 41 | verifyEqual(testCase, nActual, nExpected) 42 | 43 | end 44 | 45 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 46 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 47 | % U.S. Government retains certain rights in this software. 48 | % 49 | % This file is part of WecOptTool. 50 | % 51 | % WecOptTool is free software: you can redistribute it and/or modify 52 | % it under the terms of the GNU General Public License as published by 53 | % the Free Software Foundation, either version 3 of the License, or 54 | % (at your option) any later version. 55 | % 56 | % WecOptTool is distributed in the hope that it will be useful, 57 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 58 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 59 | % GNU General Public License for more details. 60 | % 61 | % You should have received a copy of the GNU General Public License 62 | % along with WecOptTool. If not, see . 63 | -------------------------------------------------------------------------------- /tests/scriptsTest.m: -------------------------------------------------------------------------------- 1 | function tests = scriptsTest() 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testDependencyCheck(testCase) 6 | 7 | srcRootPath = WecOptTool.system.getSrcRootPath(); 8 | cd(srcRootPath); 9 | verifyWarningFree(testCase, @dependencyCheck); 10 | 11 | end 12 | 13 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 14 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 15 | % U.S. Government retains certain rights in this software. 16 | % 17 | % This file is part of WecOptTool. 18 | % 19 | % WecOptTool is free software: you can redistribute it and/or modify 20 | % it under the terms of the GNU General Public License as published by 21 | % the Free Software Foundation, either version 3 of the License, or 22 | % (at your option) any later version. 23 | % 24 | % WecOptTool is distributed in the hope that it will be useful, 25 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | % GNU General Public License for more details. 28 | % 29 | % You should have received a copy of the GNU General Public License 30 | % along with WecOptTool. If not, see . 31 | -------------------------------------------------------------------------------- /tests/system/getFoldersTest.m: -------------------------------------------------------------------------------- 1 | function tests = getFoldersTest() 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testNotFolder(testCase) 6 | 7 | import matlab.unittest.fixtures.TemporaryFolderFixture 8 | tempFixture = testCase.applyFixture( ... 9 | TemporaryFolderFixture('PreservingOnFailure', true, ... 10 | 'WithSuffix', 'testNotFolder')); 11 | 12 | dummyFile = fullfile(tempFixture.Folder, "dummy.txt"); 13 | fclose(fopen(dummyFile, 'w')); 14 | assertTrue(testCase, isfile(dummyFile)) 15 | 16 | folderNames = WecOptTool.system.getFolders(dummyFile); 17 | verifyEmpty(testCase, folderNames) 18 | 19 | end 20 | 21 | function testEmptyFolder(testCase) 22 | 23 | import matlab.unittest.fixtures.TemporaryFolderFixture 24 | tempFixture = testCase.applyFixture( ... 25 | TemporaryFolderFixture('PreservingOnFailure', true, ... 26 | 'WithSuffix', 'testNotFolder')); 27 | 28 | dummyFile = fullfile(tempFixture.Folder, "dummy.txt"); 29 | fclose(fopen(dummyFile, 'w')); 30 | assertTrue(testCase, isfile(dummyFile)) 31 | 32 | folderNames = WecOptTool.system.getFolders(tempFixture.Folder); 33 | verifyEmpty(testCase, folderNames) 34 | 35 | end 36 | 37 | function testRelativePaths(testCase) 38 | 39 | import matlab.unittest.fixtures.TemporaryFolderFixture 40 | tempFixture = testCase.applyFixture( ... 41 | TemporaryFolderFixture('PreservingOnFailure', true, ... 42 | 'WithSuffix', 'testNotFolder')); 43 | 44 | % Make some folders to test 45 | nFolders = 5; 46 | expected = cell(1, nFolders); 47 | 48 | for i = 1:nFolders 49 | 50 | folderName = sprintf('dummy%d', i); 51 | absFolderPath = fullfile(tempFixture.Folder, folderName); 52 | mkdir(absFolderPath); 53 | 54 | assertTrue(testCase, isfolder(absFolderPath)) 55 | expected{i} = folderName; 56 | 57 | end 58 | 59 | folderNames = WecOptTool.system.getFolders(tempFixture.Folder); 60 | verifyEqual(testCase, folderNames, expected) 61 | 62 | end 63 | 64 | 65 | function testAbsolutePaths(testCase) 66 | 67 | import matlab.unittest.fixtures.TemporaryFolderFixture 68 | tempFixture = testCase.applyFixture( ... 69 | TemporaryFolderFixture('PreservingOnFailure', true, ... 70 | 'WithSuffix', 'testNotFolder')); 71 | 72 | % Make some folders to test 73 | nFolders = 5; 74 | expected = cell(1, nFolders); 75 | 76 | for i = 1:nFolders 77 | 78 | folderName = sprintf('dummy%d', i); 79 | absFolderPath = fullfile(tempFixture.Folder, folderName); 80 | mkdir(absFolderPath); 81 | 82 | assertTrue(testCase, isfolder(absFolderPath)) 83 | expected{i} = absFolderPath; 84 | 85 | end 86 | 87 | folderNames = WecOptTool.system.getFolders(tempFixture.Folder, ... 88 | "absPath", true); 89 | verifyEqual(testCase, folderNames, expected) 90 | 91 | end 92 | 93 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 94 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 95 | % U.S. Government retains certain rights in this software. 96 | % 97 | % This file is part of WecOptTool. 98 | % 99 | % WecOptTool is free software: you can redistribute it and/or modify 100 | % it under the terms of the GNU General Public License as published by 101 | % the Free Software Foundation, either version 3 of the License, or 102 | % (at your option) any later version. 103 | % 104 | % WecOptTool is distributed in the hope that it will be useful, 105 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 106 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 107 | % GNU General Public License for more details. 108 | % 109 | % You should have received a copy of the GNU General Public License 110 | % along with WecOptTool. If not, see . 111 | -------------------------------------------------------------------------------- /tests/system/hasToolboxTest.m: -------------------------------------------------------------------------------- 1 | function tests = hasToolboxTest() 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testhasParallelToolbox(testCase) 6 | 7 | import matlab.unittest.constraints.IsSubsetOf 8 | import WecOptTool.system.hasToolbox 9 | 10 | [combined, ... 11 | licensed, ... 12 | installed] = hasToolbox("Distrib_Computing_Toolbox", ... 13 | "Parallel Computing Toolbox"); 14 | 15 | testCase.verifyThat(combined, IsSubsetOf(logical([0;1]))); 16 | testCase.verifyThat(licensed, IsSubsetOf(logical([0;1]))); 17 | testCase.verifyThat(installed, IsSubsetOf(logical([0;1]))); 18 | 19 | end 20 | 21 | % Copyright 2020 Sandia National Labs 22 | % 23 | % This file is part of WecOptTool. 24 | % 25 | % WecOptTool is free software: you can redistribute it and/or modify 26 | % it under the terms of the GNU General Public License as published by 27 | % the Free Software Foundation, either version 3 of the License, or 28 | % (at your option) any later version. 29 | % 30 | % WecOptTool is distributed in the hope that it will be useful, 31 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 32 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 33 | % GNU General Public License for more details. 34 | % 35 | % You should have received a copy of the GNU General Public License 36 | % along with Foobar. If not, see . 37 | -------------------------------------------------------------------------------- /tests/system/isParallelTest.m: -------------------------------------------------------------------------------- 1 | function tests = isParallelTest() 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testIsParallelTrue(testCase) 6 | 7 | import WecOptTool.system.hasToolbox 8 | 9 | installed = hasToolbox("Distrib_Computing_Toolbox", ... 10 | "Parallel Computing Toolbox"); 11 | testCase.assumeTrue(installed, 'Parallel toolbox not available') 12 | 13 | tests = zeros(1, 2); 14 | 15 | parfor i = 1:length(tests) 16 | 17 | % Check if the pool is working. If not, assume that the test passes. 18 | p = gcp('nocreate') 19 | 20 | if isempty(p) 21 | tests(i) = true; 22 | else 23 | tests(i) = WecOptTool.system.isParallel(); 24 | end 25 | 26 | end 27 | 28 | verifyEqual(testCase, all(tests), true) 29 | 30 | end 31 | 32 | function testIsParallelFalse(testCase) 33 | 34 | tests = zeros(1, 2); 35 | 36 | for i = 1:length(tests) 37 | tests(i) = WecOptTool.system.isParallel(); 38 | end 39 | 40 | verifyEqual(testCase, any(tests), false) 41 | 42 | end 43 | 44 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 45 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 46 | % U.S. Government retains certain rights in this software. 47 | % 48 | % This file is part of WecOptTool. 49 | % 50 | % WecOptTool is free software: you can redistribute it and/or modify 51 | % it under the terms of the GNU General Public License as published by 52 | % the Free Software Foundation, either version 3 of the License, or 53 | % (at your option) any later version. 54 | % 55 | % WecOptTool is distributed in the hope that it will be useful, 56 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 57 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 58 | % GNU General Public License for more details. 59 | % 60 | % You should have received a copy of the GNU General Public License 61 | % along with WecOptTool. If not, see . 62 | -------------------------------------------------------------------------------- /tests/system/readConfigTest.m: -------------------------------------------------------------------------------- 1 | function tests = readConfigTest 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testReadConfigNoDir(testCase) 6 | 7 | func = @() WecOptTool.system.readConfig("test", 'configDir', ""); 8 | eID = 'WecOptTool:readConfig:missingDirectory'; 9 | verifyError(testCase, func, eID) 10 | 11 | end 12 | 13 | function testReadConfigNoFile(testCase) 14 | 15 | import matlab.unittest.fixtures.TemporaryFolderFixture 16 | 17 | tempFixture = testCase.applyFixture( ... 18 | TemporaryFolderFixture('PreservingOnFailure', true, ... 19 | 'WithSuffix', 'testReadConfigNoFile')); 20 | 21 | func = @() WecOptTool.system.readConfig( ... 22 | "test", ... 23 | 'configDir', tempFixture.Folder); 24 | eID = 'WecOptTool:readConfig:missingFile'; 25 | verifyError(testCase, func, eID) 26 | 27 | end 28 | 29 | function testReadConfigNoKey(testCase) 30 | 31 | import matlab.unittest.fixtures.TemporaryFolderFixture 32 | import matlab.unittest.constraints.IsFile 33 | 34 | tempFixture = testCase.applyFixture( ... 35 | TemporaryFolderFixture('PreservingOnFailure', true, ... 36 | 'WithSuffix', 'testReadConfigNoKey')); 37 | 38 | WecOptTool.system.writeConfig("test", 1, ... 39 | 'configDir', tempFixture.Folder) 40 | 41 | filePath = fullfile(tempFixture.Folder, 'config.json'); 42 | testCase.verifyThat(filePath, IsFile) 43 | 44 | func = @() WecOptTool.system.readConfig( ... 45 | "wrongkey", ... 46 | 'configDir', tempFixture.Folder); 47 | eID = 'WecOptTool:readConfig:missingKey'; 48 | verifyError(testCase, func, eID) 49 | 50 | end 51 | 52 | function testReadConfig(testCase) 53 | 54 | import matlab.unittest.fixtures.TemporaryFolderFixture 55 | import matlab.unittest.constraints.IsFile 56 | import matlab.unittest.constraints.IsEqualTo 57 | 58 | tempFixture = testCase.applyFixture( ... 59 | TemporaryFolderFixture('PreservingOnFailure', true, ... 60 | 'WithSuffix', 'testReadConfig')); 61 | 62 | expected = 1; 63 | WecOptTool.system.writeConfig("test", expected, ... 64 | 'configDir', tempFixture.Folder) 65 | 66 | filePath = fullfile(tempFixture.Folder, 'config.json'); 67 | testCase.verifyThat(filePath, IsFile) 68 | 69 | actual = WecOptTool.system.readConfig( ... 70 | "test", ... 71 | 'configDir', tempFixture.Folder); 72 | 73 | testCase.verifyThat(actual, IsEqualTo(expected)) 74 | 75 | end 76 | 77 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 78 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 79 | % U.S. Government retains certain rights in this software. 80 | % 81 | % This file is part of WecOptTool. 82 | % 83 | % WecOptTool is free software: you can redistribute it and/or modify 84 | % it under the terms of the GNU General Public License as published by 85 | % the Free Software Foundation, either version 3 of the License, or 86 | % (at your option) any later version. 87 | % 88 | % WecOptTool is distributed in the hope that it will be useful, 89 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 90 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 91 | % GNU General Public License for more details. 92 | % 93 | % You should have received a copy of the GNU General Public License 94 | % along with WecOptTool. If not, see . 95 | -------------------------------------------------------------------------------- /tests/system/writeConfigTest.m: -------------------------------------------------------------------------------- 1 | function tests = writeConfigTest 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testWriteConfigNew(testCase) 6 | 7 | import matlab.unittest.fixtures.TemporaryFolderFixture 8 | import matlab.unittest.constraints.IsFile 9 | import matlab.unittest.constraints.IsEqualTo 10 | 11 | tempFixture = testCase.applyFixture( ... 12 | TemporaryFolderFixture('PreservingOnFailure', true, ... 13 | 'WithSuffix', 'testWriteConfigNew')); 14 | 15 | WecOptTool.system.writeConfig("test", 1, ... 16 | 'configDir', tempFixture.Folder) 17 | 18 | filePath = fullfile(tempFixture.Folder, 'config.json'); 19 | testCase.verifyThat(filePath, IsFile) 20 | 21 | fileID = fopen(filePath); 22 | tline = fgetl(fileID); 23 | fclose(fileID); 24 | 25 | expVal = '{"test":1}'; 26 | testCase.verifyThat(tline, IsEqualTo(expVal)) 27 | 28 | end 29 | 30 | function testWriteConfigExists(testCase) 31 | 32 | import matlab.unittest.fixtures.TemporaryFolderFixture 33 | import matlab.unittest.constraints.IsFile 34 | import matlab.unittest.constraints.IsEqualTo 35 | 36 | tempFixture = testCase.applyFixture( ... 37 | TemporaryFolderFixture('PreservingOnFailure', true, ... 38 | 'WithSuffix', 'testWriteConfigExists')); 39 | 40 | WecOptTool.system.writeConfig("test", 1, ... 41 | 'configDir', tempFixture.Folder) 42 | 43 | filePath = fullfile(tempFixture.Folder, 'config.json'); 44 | testCase.verifyThat(filePath, IsFile) 45 | 46 | fileID = fopen(filePath); 47 | tline = fgetl(fileID); 48 | fclose(fileID); 49 | 50 | expVal = '{"test":1}'; 51 | testCase.verifyThat(tline, IsEqualTo(expVal)) 52 | 53 | WecOptTool.system.writeConfig("new", 2, ... 54 | 'configDir', tempFixture.Folder) 55 | 56 | filePath = fullfile(tempFixture.Folder, 'config.json'); 57 | testCase.verifyThat(filePath, IsFile) 58 | 59 | fileID = fopen(filePath); 60 | tline = fgetl(fileID); 61 | fclose(fileID); 62 | 63 | expVal = '{"test":1,"new":2}'; 64 | testCase.verifyThat(tline, IsEqualTo(expVal)) 65 | 66 | end 67 | 68 | function testWriteConfigRemove(testCase) 69 | 70 | import matlab.unittest.fixtures.TemporaryFolderFixture 71 | import matlab.unittest.constraints.IsFile 72 | import matlab.unittest.constraints.IsEqualTo 73 | 74 | tempFixture = testCase.applyFixture( ... 75 | TemporaryFolderFixture('PreservingOnFailure', true, ... 76 | 'WithSuffix', 'testWriteConfigRemove')); 77 | 78 | WecOptTool.system.writeConfig("test", 1, ... 79 | 'configDir', tempFixture.Folder) 80 | 81 | filePath = fullfile(tempFixture.Folder, 'config.json'); 82 | testCase.verifyThat(filePath, IsFile) 83 | 84 | fileID = fopen(filePath); 85 | tline = fgetl(fileID); 86 | fclose(fileID); 87 | 88 | expVal = '{"test":1}'; 89 | testCase.verifyThat(tline, IsEqualTo(expVal)) 90 | 91 | WecOptTool.system.writeConfig("test", "", ... 92 | 'configDir', tempFixture.Folder) 93 | 94 | filePath = fullfile(tempFixture.Folder, 'config.json'); 95 | testCase.verifyThat(filePath, IsFile) 96 | 97 | fileID = fopen(filePath); 98 | tline = fgetl(fileID); 99 | fclose(fileID); 100 | 101 | expVal = '{}'; 102 | testCase.verifyThat(tline, IsEqualTo(expVal)) 103 | 104 | end 105 | 106 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 107 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 108 | % U.S. Government retains certain rights in this software. 109 | % 110 | % This file is part of WecOptTool. 111 | % 112 | % WecOptTool is free software: you can redistribute it and/or modify 113 | % it under the terms of the GNU General Public License as published by 114 | % the Free Software Foundation, either version 3 of the License, or 115 | % (at your option) any later version. 116 | % 117 | % WecOptTool is distributed in the hope that it will be useful, 118 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 119 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 120 | % GNU General Public License for more details. 121 | % 122 | % You should have received a copy of the GNU General Public License 123 | % along with WecOptTool. If not, see . 124 | -------------------------------------------------------------------------------- /tests/testHydrodynamics.m: -------------------------------------------------------------------------------- 1 | function tests = testHydrodynamics 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testNegativeRadDamping(testCase) 6 | % this case is known to produce radiation values in the diagonal terms less 7 | % than zero 8 | 9 | import matlab.unittest.fixtures.TemporaryFolderFixture 10 | 11 | tempFixture = testCase.applyFixture( ... 12 | TemporaryFolderFixture( ... 13 | 'PreservingOnFailure', true, ... 14 | 'WithSuffix', 'testNegativeRadDampingKnownBad')); 15 | 16 | w = [0.5:0.5:5.5]; 17 | rf = [0, 5, 5, 0]; 18 | rs = [0, 7.5, 7.5, 0]; 19 | zf = [0, 0, -1.1250, -1.1250]; 20 | zs = [-42, -42, -43, -43]; 21 | 22 | % Mesh 23 | ntheta = 20; 24 | nfobj = 200; 25 | zG = 0; 26 | 27 | meshes = WecOptTool.mesh("AxiMesh", ... 28 | tempFixture.Folder, ... 29 | rf, ... 30 | zf, ... 31 | ntheta, ... 32 | nfobj, ... 33 | zG, ... 34 | 1); 35 | meshes(2) = WecOptTool.mesh("AxiMesh", ... 36 | tempFixture.Folder, ... 37 | rs, ... 38 | zs, ... 39 | ntheta, ... 40 | nfobj, ... 41 | zG, ... 42 | 2); 43 | 44 | hydro = WecOptTool.solver("NEMOH", tempFixture.Folder, meshes, w); 45 | 46 | data = struct(); 47 | data = WecOptTool.vendor.WEC_Sim.Read_NEMOH(data, ... 48 | hydro.runDirectory); 49 | 50 | rawBdiag = cell2mat(arrayfun(@(x) diag(data.B(:,:,x)), ... 51 | 1:size(data.B,3), ... 52 | 'UniformOutput', false)); 53 | 54 | hydroBdiag = cell2mat(arrayfun(@(x) diag(hydro.B(:,:,x)), ... 55 | 1:size(data.B,3), ... 56 | 'UniformOutput', false)); 57 | 58 | verifyTrue(testCase, any(any(rawBdiag < 0))); 59 | verifyGreaterThanOrEqual(testCase, hydroBdiag, 0); 60 | 61 | end 62 | 63 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 64 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 65 | % U.S. Government retains certain rights in this software. 66 | % 67 | % This file is part of WecOptTool. 68 | % 69 | % WecOptTool is free software: you can redistribute it and/or modify 70 | % it under the terms of the GNU General Public License as published by 71 | % the Free Software Foundation, either version 3 of the License, or 72 | % (at your option) any later version. 73 | % 74 | % WecOptTool is distributed in the hope that it will be useful, 75 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 76 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 77 | % GNU General Public License for more details. 78 | % 79 | % You should have received a copy of the GNU General Public License 80 | % along with WecOptTool. If not, see . 81 | % 82 | -------------------------------------------------------------------------------- /tests/validation/mustBeEqualLengthTest.m: -------------------------------------------------------------------------------- 1 | function tests = mustBeEqualLengthTest() 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function test_mustBeEqualLength_scalar(testCase) 6 | x=1.0; 7 | y=2.0; 8 | verifyWarningFree(testCase, ... 9 | @() WecOptTool.validation.mustBeEqualLength(x,y)) 10 | end 11 | 12 | function test_mustBeEqualLength_array(testCase) 13 | x=ones(1,5); 14 | y=zeros(1,5); 15 | verifyWarningFree(testCase, ... 16 | @() WecOptTool.validation.mustBeEqualLength(x,y)) 17 | end 18 | 19 | function test_mustBeEqualLength_mixed(testCase) 20 | x = WecOptTool.SeaState.example8Spectra(); 21 | y = zeros(length(x),1); 22 | verifyWarningFree(testCase, ... 23 | @() WecOptTool.validation.mustBeEqualLength(x,y)) 24 | end 25 | 26 | function test_mustBeEqualLength_error(testCase) 27 | x=1.0; 28 | y=[2, 3]; 29 | eID = 'WecOptTool:Validation:NotEqualLength'; 30 | verifyError(testCase, ... 31 | @() WecOptTool.validation.mustBeEqualLength(x,y), ... 32 | eID) 33 | end 34 | 35 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 36 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 37 | % U.S. Government retains certain rights in this software. 38 | % 39 | % This file is part of WecOptTool. 40 | % 41 | % WecOptTool is free software: you can redistribute it and/or modify 42 | % it under the terms of the GNU General Public License as published by 43 | % the Free Software Foundation, either version 3 of the License, or 44 | % (at your option) any later version. 45 | % 46 | % WecOptTool is distributed in the hope that it will be useful, 47 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 48 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 49 | % GNU General Public License for more details. 50 | % 51 | % You should have received a copy of the GNU General Public License 52 | % along with WecOptTool. If not, see . 53 | -------------------------------------------------------------------------------- /tests/validation/mustBeFunctionHandleTest.m: -------------------------------------------------------------------------------- 1 | function tests = mustBeFunctionHandleTest() 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testIsFunctionHandle(~) 6 | a = @(x) x^2; 7 | WecOptTool.validation.mustBeFunctionHandle(a) 8 | end 9 | 10 | function testIsNotFunctionHandle(testCase) 11 | a = 1; 12 | eID = 'WecOptTool:Validation:NotFunctionHandle'; 13 | verifyError(testCase, ... 14 | @() WecOptTool.validation.mustBeFunctionHandle(a), ... 15 | eID) 16 | end 17 | 18 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 19 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 20 | % U.S. Government retains certain rights in this software. 21 | % 22 | % This file is part of WecOptTool. 23 | % 24 | % WecOptTool is free software: you can redistribute it and/or modify 25 | % it under the terms of the GNU General Public License as published by 26 | % the Free Software Foundation, either version 3 of the License, or 27 | % (at your option) any later version. 28 | % 29 | % WecOptTool is distributed in the hope that it will be useful, 30 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 31 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32 | % GNU General Public License for more details. 33 | % 34 | % You should have received a copy of the GNU General Public License 35 | % along with WecOptTool. If not, see . 36 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+base/Mesher.m: -------------------------------------------------------------------------------- 1 | classdef (Abstract) Mesher < WecOptTool.base.TempFolder 2 | % Abstract class for creating new mesher classes 3 | % 4 | % A single method should be implemented, called ``makeMesh`` that 5 | % creates a mesh using any particular external tool 6 | % 7 | % -- 8 | % 9 | % See also WecOptTool.mesh 10 | % 11 | % -- 12 | 13 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 14 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 15 | % U.S. Government retains certain rights in this software. 16 | % 17 | % This file is part of WecOptTool. 18 | % 19 | % WecOptTool is free software: you can redistribute it and/or 20 | % modify it under the terms of the GNU General Public License as 21 | % published by the Free Software Foundation, either version 3 of 22 | % the License, or (at your option) any later version. 23 | % 24 | % WecOptTool is distributed in the hope that it will be useful, 25 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | % GNU General Public License for more details. 28 | % 29 | % You should have received a copy of the GNU General Public 30 | % License along with WecOptTool. If not, see 31 | % . 32 | 33 | methods (Abstract) 34 | mesh = makeMesh(obj, varagin) 35 | end 36 | 37 | end 38 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+base/NEMOH.m: -------------------------------------------------------------------------------- 1 | classdef NEMOH < handle 2 | % Base class containing NEMOH helpers 3 | % 4 | % -- 5 | % 6 | % NEMOH Methods: 7 | % isNemohInPath - Determine if the NEMOH executables can be found. 8 | % 9 | % See also WecOptTool.mesh.AxiMesh, WecOptTool.solver.NEMOH 10 | % 11 | % -- 12 | 13 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 14 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 15 | % U.S. Government retains certain rights in this software. 16 | % 17 | % This file is part of WecOptTool. 18 | % 19 | % WecOptTool is free software: you can redistribute it and/or 20 | % modify it under the terms of the GNU General Public License as 21 | % published by the Free Software Foundation, either version 3 of 22 | % the License, or (at your option) any later version. 23 | % 24 | % WecOptTool is distributed in the hope that it will be useful, 25 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | % GNU General Public License for more details. 28 | % 29 | % You should have received a copy of the GNU General Public 30 | % License along with WecOptTool. If not, see 31 | % . 32 | 33 | methods (Static) 34 | 35 | function inpath = isNemohInPath() 36 | % Determine if the NEMOH executables can be found. 37 | % 38 | % Returns: 39 | % logical: true if executables found, otherwise false. 40 | % 41 | 42 | startdir = pwd; 43 | inpath = 1; 44 | 45 | try 46 | nemohPath = WecOptTool.system.readConfig('nemohPath'); 47 | catch 48 | inpath = 0; 49 | cd(startdir); 50 | return 51 | end 52 | 53 | rundir = tempname; 54 | [status, ~, message] = mkdir(rundir); 55 | 56 | if ~status || strcmp(message, 'MATLAB:MKDIR:DirectoryExists') 57 | errStr = "Failed to create unique folder"; 58 | error('WecOptTool:AutoFolder:NoUniqueFolder', errStr) 59 | end 60 | 61 | cd(rundir); 62 | 63 | windows_exes = ["Mesh", "postProcessor", "preProcessor", "Solver"]; 64 | unix_exes = ["mesh", "postProc", "preProc", "solver"]; 65 | 66 | if ispc 67 | 68 | for exe = windows_exes 69 | 70 | exePath = fullfile(nemohPath, exe); 71 | [status, result] = system(exePath); 72 | 73 | if ~(status == 0 || contains(result, 'ID.dat')) 74 | inpath = 0; 75 | cd(startdir); 76 | return 77 | end 78 | 79 | end 80 | 81 | else 82 | 83 | for exe = unix_exes 84 | 85 | exePath = fullfile(nemohPath, exe); 86 | [status, result] = system(exePath); 87 | 88 | if ~(status == 0 || contains(result, 'ID.dat')) 89 | inpath = 0; 90 | cd(startdir); 91 | return 92 | end 93 | 94 | end 95 | 96 | end 97 | 98 | cd(startdir); 99 | WecOptTool.system.rmdirRetry(rundir); 100 | 101 | end 102 | 103 | end 104 | 105 | end 106 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+base/Solver.m: -------------------------------------------------------------------------------- 1 | classdef (Abstract) Solver < WecOptTool.base.TempFolder 2 | % Abstract class for creating new solver classes 3 | % 4 | % A single method should be implemented, called ``getHydro`` that 5 | % solves the hydrodynamics for a given mesh using any particular 6 | % external tool 7 | % 8 | % -- 9 | % 10 | % See also WecOptTool.mesh 11 | % 12 | % -- 13 | 14 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 15 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 16 | % U.S. Government retains certain rights in this software. 17 | % 18 | % This file is part of WecOptTool. 19 | % 20 | % WecOptTool is free software: you can redistribute it and/or 21 | % modify it under the terms of the GNU General Public License as 22 | % published by the Free Software Foundation, either version 3 of 23 | % the License, or (at your option) any later version. 24 | % 25 | % WecOptTool is distributed in the hope that it will be useful, 26 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | % GNU General Public License for more details. 29 | % 30 | % You should have received a copy of the GNU General Public 31 | % License along with WecOptTool. If not, see 32 | % . 33 | 34 | methods (Abstract) 35 | hydro = getHydro(obj, meshes, varagin) 36 | end 37 | 38 | end 39 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+base/TempFolder.m: -------------------------------------------------------------------------------- 1 | classdef TempFolder < handle 2 | % Superclass for classes requiring temporary storage 3 | % 4 | % Arguments: 5 | % base (string, optional): 6 | % Parent for temporary folder, default is tempdir 7 | % 8 | % Attributes: 9 | % path (string): path to temporary folder 10 | % 11 | 12 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 13 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 14 | % U.S. Government retains certain rights in this software. 15 | % 16 | % This file is part of WecOptTool. 17 | % 18 | % WecOptTool is free software: you can redistribute it and/or 19 | % modify it under the terms of the GNU General Public License as 20 | % published by the Free Software Foundation, either version 3 of 21 | % the License, or (at your option) any later version. 22 | % 23 | % WecOptTool is distributed in the hope that it will be useful, 24 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 | % GNU General Public License for more details. 27 | % 28 | % You should have received a copy of the GNU General Public 29 | % License along with WecOptTool. If not, see 30 | % . 31 | properties 32 | path 33 | end 34 | 35 | methods 36 | 37 | function obj = TempFolder(base) 38 | 39 | arguments 40 | base string = ""; 41 | end 42 | 43 | if (base == "") 44 | obj.path = tempname; 45 | else 46 | obj.path = tempname(base); 47 | end 48 | 49 | obj.mkdirSafe(obj.path); 50 | 51 | end 52 | 53 | end 54 | 55 | methods (Static, Access=protected) 56 | 57 | function mkdirSafe(path) 58 | 59 | [status, ~, message] = mkdir(path); 60 | 61 | if ~status || strcmp(message, 'MATLAB:MKDIR:DirectoryExists') 62 | errStr = "Failed to create unique folder"; 63 | error('WecOptTool:TempFolder:NoUniqueFolder', errStr) 64 | end 65 | 66 | end 67 | 68 | end 69 | 70 | end 71 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+geometry/existingNEMOH.m: -------------------------------------------------------------------------------- 1 | function hydro = existingNEMOH(nemohFolder) 2 | % A predefined geometry callback for reading an existing NEMOH 3 | % solution. 4 | % 5 | % Arguments: 6 | % nemohFolder (string): 7 | % Path to the folder containing existing NEMOH output files 8 | % 9 | % Returns: 10 | % :mat:class:`+WecOptTool.Hydrodynamics`: Hydrodynamics object 11 | % 12 | % -- 13 | % See also WecOptTool.Hydrodynamics 14 | % -- 15 | 16 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 17 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 18 | % U.S. Government retains certain rights in this software. 19 | % 20 | % This file is part of WecOptTool. 21 | % 22 | % WecOptTool is free software: you can redistribute it and/or 23 | % modify it under the terms of the GNU General Public License as 24 | % published by the Free Software Foundation, either version 3 of 25 | % the License, or (at your option) any later version. 26 | % 27 | % WecOptTool is distributed in the hope that it will be useful, 28 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 29 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 | % GNU General Public License for more details. 31 | % 32 | % You should have received a copy of the GNU General Public 33 | % License along with WecOptTool. If not, see 34 | % . 35 | 36 | data = struct(); 37 | data = WecOptTool.vendor.WEC_Sim.Read_NEMOH(data, ... 38 | nemohFolder); 39 | hydro = WecOptTool.Hydrodynamics(data, ... 40 | "solverName", "NEMOH", ... 41 | "runDirectory", nemohFolder); 42 | 43 | end 44 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+math/bisection.m: -------------------------------------------------------------------------------- 1 | function c = bisection(f, a, b, options) 2 | % Bisection method 3 | % 4 | % Args: 5 | % f (double): real valued function 6 | % a (double): search space lower boundary 7 | % b (double): search space upper boundary 8 | % tol (optional, double): solution tolerance, default = 1e-10 9 | % nmax (optional, int): maximum number of operations, default = 1e4 10 | % 11 | % Returns: 12 | % double: root of f 13 | % 14 | % Note: 15 | % The given interval boundaries must satisfy f(a) * f(b) <= 0 16 | % 17 | 18 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 19 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 20 | % U.S. Government retains certain rights in this software. 21 | % 22 | % This file is part of WecOptTool. 23 | % 24 | % WecOptTool is free software: you can redistribute it and/or 25 | % modify it under the terms of the GNU General Public License as 26 | % published by the Free Software Foundation, either version 3 of 27 | % the License, or (at your option) any later version. 28 | % 29 | % WecOptTool is distributed in the hope that it will be useful, 30 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 31 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32 | % GNU General Public License for more details. 33 | % 34 | % You should have received a copy of the GNU General Public 35 | % License along with WecOptTool. If not, see 36 | % . 37 | 38 | arguments 39 | f {WecOptTool.validation.mustBeFunctionHandle}; 40 | a {mustBeNumeric, mustBeFinite}; 41 | b {mustBeNumeric, mustBeFinite, mustBeGreaterThan(b, a)}; 42 | options.tol {mustBeNumeric, ... 43 | mustBePositive, ... 44 | mustBeFinite, ... 45 | mustBeNonzero} = 1e-10; 46 | options.nmax {mustBeInteger, ... 47 | mustBePositive, ... 48 | mustBeFinite, ... 49 | mustBeNonzero} = 1e4; 50 | end 51 | 52 | if f(a) * f(b) > 0 53 | eID = "WecOptTool:bisection:badInterval"; 54 | error(eID, "Incorrect initial interval [a, b]") 55 | end 56 | 57 | n = 1; 58 | 59 | while n < options.nmax 60 | 61 | c = (a + b) / 2; 62 | 63 | if abs(f(c)) < options.tol 64 | return 65 | elseif (b - a) / 2 < eps 66 | eID = "WecOptTool:bisection:searchSpaceClosed"; 67 | error(eID, 'Search space closed before finding a solution') 68 | end 69 | 70 | n = n + 1; 71 | 72 | if sign(f(c)) == sign(f(a)) 73 | a = c; 74 | else 75 | b = c; 76 | end 77 | 78 | end 79 | 80 | eID = "WecOptTool:bisection:tooManyIterations"; 81 | error(eID, 'Number of iterations exceeded') 82 | 83 | end 84 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+math/isClose.m: -------------------------------------------------------------------------------- 1 | function result = isClose(a, b, varargin) 2 | % Determine if two values are numerically close (but perhaps not 3 | % exactly equal). 4 | % 5 | % Args: 6 | % a (double): first value to compare 7 | % b (double): second value to compare 8 | % rtol (double, optional): relative tolerence, default = 1e-05 9 | % atol (double, optional): absolute tolerance, default = 1e-08 10 | % 11 | % Returns: 12 | % logical: true if a is within given tolerances of b 13 | % 14 | % Note: 15 | % Derived from the similar named `numpy routine 16 | % `_ 17 | % 18 | 19 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 20 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 21 | % U.S. Government retains certain rights in this software. 22 | % 23 | % This file is part of WecOptTool. 24 | % 25 | % WecOptTool is free software: you can redistribute it and/or 26 | % modify it under the terms of the GNU General Public License as 27 | % published by the Free Software Foundation, either version 3 of 28 | % the License, or (at your option) any later version. 29 | % 30 | % WecOptTool is distributed in the hope that it will be useful, 31 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 32 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 33 | % GNU General Public License for more details. 34 | % 35 | % You should have received a copy of the GNU General Public 36 | % License along with WecOptTool. If not, see 37 | % . 38 | % 39 | % Copyright (C) 2005-2020, NumPy Developers. 40 | % All rights reserved. 41 | % 42 | % Redistribution and use in source and binary forms, with or without 43 | % modification, are permitted provided that the following conditions 44 | % are met: 45 | % 46 | % * Redistributions of source code must retain the above copyright 47 | % notice, this list of conditions and the following disclaimer. 48 | % 49 | % * Redistributions in binary form must reproduce the above copyright 50 | % notice, this list of conditions and the following disclaimer in the 51 | % documentation and/or other materials provided with the distribution. 52 | % 53 | % * Neither the name of the NumPy Developers nor the names of any 54 | % contributors may be used to endorse or promote products derived from 55 | % this software without specific prior written permission. 56 | % 57 | % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 58 | % "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 59 | % LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 60 | % FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 61 | % COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 62 | % INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 63 | % BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 64 | % LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 65 | % CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 | % LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 67 | % ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 68 | % POSSIBILITY OF SUCH DAMAGE. 69 | 70 | defaultAtol = 1e-08; 71 | defaultRtol = 1e-05; 72 | 73 | p = inputParser; 74 | 75 | addParameter(p, 'rtol', defaultRtol); 76 | addParameter(p, 'atol', defaultAtol); 77 | parse(p, varargin{:}); 78 | 79 | result = abs(a - b) <= (p.Results.atol + p.Results.rtol * abs(b)); 80 | 81 | end 82 | 83 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+plot/plotMesh.m: -------------------------------------------------------------------------------- 1 | function plotMesh(meshses, newFig) 2 | % Plot the given meshes on a single 3D axis. 3 | % 4 | % Arguments: 5 | % meshses (struct): 6 | % Struct array containing mesh description with fields as 7 | % described below 8 | % newFig (logical): 9 | % If true a new figure is created 10 | % 11 | % The meshes struct must contain the following fields: 12 | % 13 | % ============ ================ ====================================== 14 | % **Variable** **Format** **Description** 15 | % bodyNum int32 body number 16 | % name char array name of the mesh 17 | % nodes Nx4 table table of N node positions with columns ID, x, y, z 18 | % panels Mx4 int32 array array of M panels where each row contains the 4 connected node IDs 19 | % xzSymmetric logical body is symmetric in xz plane (half mesh) 20 | % zG double z-coordinate of the bodies centre of gravity 21 | % ============ ================ ====================================== 22 | % 23 | 24 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 25 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 26 | % U.S. Government retains certain rights in this software. 27 | % 28 | % This file is part of WecOptTool. 29 | % 30 | % WecOptTool is free software: you can redistribute it and/or 31 | % modify it under the terms of the GNU General Public License as 32 | % published by the Free Software Foundation, either version 3 of 33 | % the License, or (at your option) any later version. 34 | % 35 | % WecOptTool is distributed in the hope that it will be useful, 36 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 37 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 38 | % GNU General Public License for more details. 39 | % 40 | % You should have received a copy of the GNU General Public 41 | % License along with WecOptTool. If not, see 42 | % . 43 | 44 | arguments 45 | meshses 46 | newFig = true 47 | end 48 | 49 | if isempty(meshses) 50 | return 51 | end 52 | 53 | if newFig 54 | figure 55 | ax1 = axes; 56 | view(ax1, 3) 57 | end 58 | 59 | hold on 60 | 61 | for mesh = meshses 62 | plotSingleMesh(ax1, mesh); 63 | end 64 | 65 | xlabel("x") 66 | ylabel("y") 67 | zlabel("z") 68 | 69 | axis image 70 | 71 | hold off 72 | 73 | end 74 | 75 | function plotSingleMesh(ax, mesh) 76 | 77 | n = size(mesh.panels, 1); 78 | 79 | X = zeros(4, n); 80 | Y = zeros(4, n); 81 | Z = zeros(4, n); 82 | 83 | for i = 1:n 84 | X(:, i) = mesh.nodes(mesh.panels(i, :), :).x; 85 | Y(:, i) = mesh.nodes(mesh.panels(i, :), :).y; 86 | Z(:, i) = mesh.nodes(mesh.panels(i, :), :).z; 87 | end 88 | 89 | fill3(ax, X, Y, Z, 'r') 90 | 91 | if ~mesh.xzSymmetric 92 | return 93 | end 94 | 95 | for i = 1:n 96 | Y(:, i) = -mesh.nodes(mesh.panels(i, :), :).y; 97 | end 98 | 99 | fill3(ax, X, Y, Z, 'r') 100 | 101 | end 102 | 103 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+plot/powerPerFreq.m: -------------------------------------------------------------------------------- 1 | function powerPerFreq(input) 2 | % Plots power per frequency for a simulated device. 3 | % 4 | % Arguments: 5 | % input (struct): 6 | % A struct array with fields defined in the table below 7 | % 8 | % ============ ================ ===================================== 9 | % **Variable** **Format** **Description** 10 | % w Nx1 double array N sea-state frequencie 11 | % powPerFreq Nx1 double array Power production per frequency 12 | % ============ ================ ===================================== 13 | % 14 | 15 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 16 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 17 | % U.S. Government retains certain rights in this software. 18 | % 19 | % This file is part of WecOptTool. 20 | % 21 | % WecOptTool is free software: you can redistribute it and/or 22 | % modify it under the terms of the GNU General Public License as 23 | % published by the Free Software Foundation, either version 3 of 24 | % the License, or (at your option) any later version. 25 | % 26 | % WecOptTool is distributed in the hope that it will be useful, 27 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 28 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 | % GNU General Public License for more details. 30 | % 31 | % You should have received a copy of the GNU General Public 32 | % License along with WecOptTool. If not, see 33 | % . 34 | 35 | % Number of Sea-States 36 | NSS = length(input); 37 | 38 | multiSeaState = false; 39 | if NSS>1 40 | multiSeaState = true; 41 | end 42 | 43 | figure 44 | 45 | if multiSeaState 46 | 47 | hold on 48 | 49 | for i = 1 : NSS 50 | 51 | freq = input(i).w; 52 | 53 | % Trim off zero frequencies 54 | if abs(freq(1)) <= eps 55 | freq = freq(2:end); 56 | end 57 | 58 | powPerFreq = input(i).powPerFreq; 59 | plot(freq, powPerFreq,'DisplayName',int2str(i)) 60 | 61 | end 62 | 63 | legend() 64 | 65 | else 66 | 67 | freq = input(1).w; 68 | powPerFreq = input(1).powPerFreq; 69 | plot(freq, powPerFreq) 70 | 71 | end 72 | 73 | xlabel('Frequency [$\omega$]','Interpreter','latex') 74 | ylabel('Power [$W]$','Interpreter','latex') 75 | grid 76 | 77 | end 78 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+solver/nemohcalbody.txt: -------------------------------------------------------------------------------- 1 | --- Body %i ------------------------------------------------------------------ 2 | '%s' ! Name of mesh file 3 | %-12i %-12i ! Number of points and number of panels 4 | 6 ! Number of degrees of freedom 5 | 1 1. 0. 0. 0. 0. 0. ! Surge 6 | 1 0. 1. 0. 0. 0. 0. ! Sway 7 | 1 0. 0. 1. 0. 0. 0. ! Heave 8 | 2 1. 0. 0. 0. 0. %-9.4f ! Roll about a point 9 | 2 0. 1. 0. 0. 0. %-9.4f ! Pitch about a point 10 | 2 0. 0. 1. 0. 0. %-9.4f ! Yaw about a point 11 | 6 ! Number of resulting generalised forces 12 | 1 1. 0. 0. 0. 0. 0. ! Force in x direction 13 | 1 0. 1. 0. 0. 0. 0. ! Force in y direction 14 | 1 0. 0. 1. 0. 0. 0. ! Force in z direction 15 | 2 1. 0. 0. 0. 0. %-9.4f ! Moment force in x direction about a point 16 | 2 0. 1. 0. 0. 0. %-9.4f ! Moment force in y direction about a point 17 | 2 0. 0. 1. 0. 0. %-9.4f ! Moment force in z direction about a point 18 | 0 ! Number of lines of additional information 19 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+solver/nemohcalfooter.txt: -------------------------------------------------------------------------------- 1 | --- Load cases to be solved -------------------------------------------------- 2 | %-4i %-11.4f %-11.4f ! Number of wave frequencies, Min, and Max (rad/s) 3 | 1 0. 0. ! Number of wave directions, Min and Max (degrees) 4 | --- Post processing ---------------------------------------------------------- 5 | 0 0.1 10. ! IRF ! IRF calculation (0 for no calculation), time step and duration 6 | 0 ! Show pressure 7 | 0 0. 180. ! Kochin function ! Number of directions of calculation (0 for no calculations), Min and Max (degrees) 8 | 0 50 400. 400. ! Free surface elevation ! Number of points in x direction (0 for no calcutions) and y direction and dimensions of domain in x and y direction 9 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+solver/nemohcalheader.txt: -------------------------------------------------------------------------------- 1 | --- Environment -------------------------------------------------------------- 2 | %-15.4f ! RHO ! KG/M**3 ! Fluid specific volume 3 | %-15.4f ! G ! M/S**2 ! Gravity 4 | 0. ! DEPTH ! M ! Water depth 5 | 0. 0. ! XEFF YEFF ! M ! Wave measurement point 6 | --- Description of floating bodies ------------------------------------------- 7 | %d ! Number of bodies 8 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+system/getFolders.m: -------------------------------------------------------------------------------- 1 | function folderNames = getFolders(baseFolder, varargin) 2 | % Returns folder names found at a given folder path (excludes '.' 3 | % and '..') 4 | % 5 | % Args: 6 | % baseFolder (character vector | string scalar): 7 | % folder path used for search 8 | % varargin: name-value pair options. See below. 9 | % 10 | % The following options are supported: 11 | % 12 | % absPath (logical): 13 | % If true, the absolute path to the folders is returned. Defaults 14 | % to false. 15 | % 16 | % Returns: 17 | % cell array: Discovered folder names 18 | % 19 | 20 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 21 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 22 | % U.S. Government retains certain rights in this software. 23 | % 24 | % This file is part of WecOptTool. 25 | % 26 | % WecOptTool is free software: you can redistribute it and/or 27 | % modify it under the terms of the GNU General Public License as 28 | % published by the Free Software Foundation, either version 3 of 29 | % the License, or (at your option) any later version. 30 | % 31 | % WecOptTool is distributed in the hope that it will be useful, 32 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 33 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 34 | % GNU General Public License for more details. 35 | % 36 | % You should have received a copy of the GNU General Public 37 | % License along with WecOptTool. If not, see 38 | % . 39 | 40 | p = inputParser; 41 | 42 | defaultAbsPath = false; 43 | validCharString = @(x) ischar(x) | isstring(x); 44 | 45 | addRequired(p, 'baseFolder', validCharString); 46 | addParameter(p, 'absPath', defaultAbsPath, @islogical); 47 | 48 | parse(p, baseFolder, varargin{:}); 49 | 50 | validBaseFolder = p.Results.baseFolder; 51 | 52 | if ~isfolder(validBaseFolder) 53 | folderNames = {}; 54 | return 55 | end 56 | 57 | d = dir(validBaseFolder); 58 | dfolders = d([d(:).isdir] == 1); 59 | dfolders = dfolders(~ismember({dfolders(:).name}, {'.', '..'})); 60 | 61 | relativeFolderNames = {dfolders(:).name}; 62 | 63 | if ~p.Results.absPath 64 | folderNames = relativeFolderNames; 65 | return 66 | end 67 | 68 | folderNames = cell(1, length(relativeFolderNames)); 69 | 70 | for i = 1:length(relativeFolderNames) 71 | folderNames{i} = fullfile(validBaseFolder, relativeFolderNames{i}); 72 | end 73 | 74 | end 75 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+system/getSrcRootPath.m: -------------------------------------------------------------------------------- 1 | function [srcRootPath] = getSrcRootPath() 2 | % Return path to WecOptTool src code root directory 3 | 4 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 5 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 6 | % U.S. Government retains certain rights in this software. 7 | % 8 | % This file is part of WecOptTool. 9 | % 10 | % WecOptTool is free software: you can redistribute it and/or 11 | % modify it under the terms of the GNU General Public License as 12 | % published by the Free Software Foundation, either version 3 of 13 | % the License, or (at your option) any later version. 14 | % 15 | % WecOptTool is distributed in the hope that it will be useful, 16 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | % GNU General Public License for more details. 19 | % 20 | % You should have received a copy of the GNU General Public 21 | % License along with WecOptTool. If not, see 22 | % . 23 | 24 | p = mfilename('fullpath'); 25 | [pDir, ~, ~] = fileparts(p); 26 | parts = strsplit(pDir, filesep); 27 | srcRootPath = fullfile(parts{1:end-3}); 28 | 29 | % Linux requires a leading slash 30 | if ~ispc 31 | srcRootPath = [filesep, srcRootPath]; 32 | end 33 | 34 | end 35 | 36 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+system/getUserPath.m: -------------------------------------------------------------------------------- 1 | function [WOTDataPath] = getUserPath() 2 | % Return path to WecOptTool user data directory 3 | 4 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 5 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 6 | % U.S. Government retains certain rights in this software. 7 | % 8 | % This file is part of WecOptTool. 9 | % 10 | % WecOptTool is free software: you can redistribute it and/or 11 | % modify it under the terms of the GNU General Public License as 12 | % published by the Free Software Foundation, either version 3 of 13 | % the License, or (at your option) any later version. 14 | % 15 | % WecOptTool is distributed in the hope that it will be useful, 16 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | % GNU General Public License for more details. 19 | % 20 | % You should have received a copy of the GNU General Public 21 | % License along with WecOptTool. If not, see 22 | % . 23 | 24 | if ispc 25 | appDataPath = getenv('APPDATA'); 26 | WOTDataPath = fullfile(appDataPath, 'WecOptTool'); 27 | else 28 | appDataPath = getenv('HOME'); 29 | WOTDataPath = fullfile(appDataPath, '.wecopttool'); 30 | end 31 | end 32 | 33 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+system/hasToolbox.m: -------------------------------------------------------------------------------- 1 | function [combined, licensed, installed] = hasToolbox(licenseName, ... 2 | installedName) 3 | % Check if an extension toolbox is installed 4 | % 5 | % Arguments: 6 | % licenseName (string): 7 | % the licence name (normally with underscores) 8 | % installedName (string): 9 | % the toolbox name (as given by the ver command) 10 | % 11 | % Returns: 12 | % (): outputs are: 13 | % 14 | % combined (logical): true if toolbox is licensed and installed 15 | % licensed (logical): true is toolbox is licensed 16 | % installed (logical): true is toolbox is installed 17 | % 18 | 19 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 20 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 21 | % U.S. Government retains certain rights in this software. 22 | % 23 | % This file is part of WecOptTool. 24 | % 25 | % WecOptTool is free software: you can redistribute it and/or 26 | % modify it under the terms of the GNU General Public License as 27 | % published by the Free Software Foundation, either version 3 of 28 | % the License, or (at your option) any later version. 29 | % 30 | % WecOptTool is distributed in the hope that it will be useful, 31 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 32 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 33 | % GNU General Public License for more details. 34 | % 35 | % You should have received a copy of the GNU General Public 36 | % License along with WecOptTool. If not, see 37 | % . 38 | 39 | licensed = logical(license('test', licenseName)); 40 | 41 | installedProducts = ver; 42 | installedNames = {installedProducts(:).Name}; 43 | installed = false; 44 | 45 | for name = installedNames 46 | if contains(name, installedName) 47 | installed = true; 48 | break 49 | end 50 | end 51 | 52 | combined = licensed && installed; 53 | 54 | end 55 | 56 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+system/isParallel.m: -------------------------------------------------------------------------------- 1 | function result = isParallel() 2 | % Determine if the current process is being run in parallel 3 | 4 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 5 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 6 | % U.S. Government retains certain rights in this software. 7 | % 8 | % This file is part of WecOptTool. 9 | % 10 | % WecOptTool is free software: you can redistribute it and/or 11 | % modify it under the terms of the GNU General Public License as 12 | % published by the Free Software Foundation, either version 3 of 13 | % the License, or (at your option) any later version. 14 | % 15 | % WecOptTool is distributed in the hope that it will be useful, 16 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | % GNU General Public License for more details. 19 | % 20 | % You should have received a copy of the GNU General Public 21 | % License along with WecOptTool. If not, see 22 | % . 23 | 24 | import WecOptTool.system.hasToolbox 25 | 26 | hasParallelToolbox = hasToolbox("Distrib_Computing_Toolbox", ... 27 | "Parallel Computing Toolbox"); 28 | 29 | if ~hasParallelToolbox 30 | result = false; 31 | return 32 | end 33 | 34 | result = ~isempty(getCurrentTask()); 35 | 36 | end 37 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+system/readConfig.m: -------------------------------------------------------------------------------- 1 | function value = readConfig(key, varargin) 2 | % Read the value for the given key in the config file 3 | 4 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 5 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 6 | % U.S. Government retains certain rights in this software. 7 | % 8 | % This file is part of WecOptTool. 9 | % 10 | % WecOptTool is free software: you can redistribute it and/or 11 | % modify it under the terms of the GNU General Public License as 12 | % published by the Free Software Foundation, either version 3 of 13 | % the License, or (at your option) any later version. 14 | % 15 | % WecOptTool is distributed in the hope that it will be useful, 16 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | % GNU General Public License for more details. 19 | % 20 | % You should have received a copy of the GNU General Public 21 | % License along with WecOptTool. If not, see 22 | % . 23 | 24 | % Default directory for config 25 | WOTDataPath = WecOptTool.system.getUserPath(); 26 | 27 | p = inputParser; 28 | validText = @(x) isstring(x) || ischar(x); 29 | addRequired(p, 'key', validText); 30 | addParameter(p, 'configDir', WOTDataPath, validText); 31 | parse(p, key, varargin{:}); 32 | 33 | if ~exist(p.Results.configDir, 'dir') 34 | errStr = "Config directory '" + p.Results.configDir + ... 35 | "' does not exist"; 36 | errStr = strrep(errStr, '\', '\\'); 37 | error('WecOptTool:readConfig:missingDirectory', errStr) 38 | end 39 | 40 | configPath = fullfile(p.Results.configDir, 'config.json'); 41 | 42 | if ~exist(configPath, 'file') 43 | errStr = "Config file 'config.json' does not exist"; 44 | error('WecOptTool:readConfig:missingFile', errStr) 45 | end 46 | 47 | config = jsondecode(fileread(configPath)); 48 | 49 | if ~isfield(config, p.Results.key) 50 | errStr = "Config file does contain key: " + p.Results.key; 51 | error('WecOptTool:readConfig:missingKey', errStr) 52 | end 53 | 54 | value = config.(p.Results.key); 55 | 56 | end 57 | 58 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+system/rmdirRetry.m: -------------------------------------------------------------------------------- 1 | function rmdirRetry(dirPath) 2 | % Calls rmdir with 's' option in a retry loop 3 | 4 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 5 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 6 | % U.S. Government retains certain rights in this software. 7 | % 8 | % This file is part of WecOptTool. 9 | % 10 | % WecOptTool is free software: you can redistribute it and/or 11 | % modify it under the terms of the GNU General Public License as 12 | % published by the Free Software Foundation, either version 3 of 13 | % the License, or (at your option) any later version. 14 | % 15 | % WecOptTool is distributed in the hope that it will be useful, 16 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | % GNU General Public License for more details. 19 | % 20 | % You should have received a copy of the GNU General Public 21 | % License along with WecOptTool. If not, see 22 | % . 23 | 24 | maxRetries = 59; 25 | nRetries = 0; 26 | 27 | while nRetries < maxRetries 28 | try 29 | rmdir(dirPath, 's'); 30 | return 31 | catch 32 | pause(1) 33 | nRetries = nRetries + 1; 34 | end 35 | end 36 | 37 | rmdir(dirPath, 's'); 38 | 39 | end 40 | 41 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+system/writeConfig.m: -------------------------------------------------------------------------------- 1 | function writeConfig(key, value, varargin) 2 | % Add given key with given value to config file 3 | 4 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 5 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 6 | % U.S. Government retains certain rights in this software. 7 | % 8 | % This file is part of WecOptTool. 9 | % 10 | % WecOptTool is free software: you can redistribute it and/or 11 | % modify it under the terms of the GNU General Public License as 12 | % published by the Free Software Foundation, either version 3 of 13 | % the License, or (at your option) any later version. 14 | % 15 | % WecOptTool is distributed in the hope that it will be useful, 16 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | % GNU General Public License for more details. 19 | % 20 | % You should have received a copy of the GNU General Public 21 | % License along with WecOptTool. If not, see 22 | % . 23 | 24 | % Default directory for config 25 | WOTDataPath = WecOptTool.system.getUserPath(); 26 | 27 | p = inputParser; 28 | validText = @(x) isstring(x) || ischar(x); 29 | addRequired(p, 'key', validText); 30 | addRequired(p, 'value'); 31 | addParameter(p, 'configDir', WOTDataPath, validText); 32 | parse(p, key, value, varargin{:}); 33 | 34 | % Check if the user data directory exists and make if necessary 35 | if ~exist(p.Results.configDir, 'dir') 36 | mkdir(p.Results.configDir) 37 | end 38 | 39 | % Check if the config file exists and read 40 | configPath = fullfile(p.Results.configDir, 'config.json'); 41 | 42 | if exist(configPath, 'file') 43 | config = jsondecode(fileread(configPath)); 44 | else 45 | config = struct(char(p.Results.key), p.Results.value); 46 | end 47 | 48 | if strcmp(p.Results.value, "") 49 | config = rmfield(config, p.Results.key); 50 | else 51 | config.(p.Results.key) = p.Results.value; 52 | end 53 | 54 | % Convert to JSON text and save 55 | jsonConfig = jsonencode(config); 56 | fid = fopen(configPath, 'w'); 57 | fprintf(fid, '%s', jsonConfig); 58 | fclose(fid); 59 | 60 | end 61 | 62 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+validation/mustBeEqualLength.m: -------------------------------------------------------------------------------- 1 | function mustBeEqualLength(x, y) 2 | % Returns an error if x and y are not of equal lengths 3 | 4 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 5 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 6 | % U.S. Government retains certain rights in this software. 7 | % 8 | % This file is part of WecOptTool. 9 | % 10 | % WecOptTool is free software: you can redistribute it and/or 11 | % modify it under the terms of the GNU General Public License as 12 | % published by the Free Software Foundation, either version 3 of 13 | % the License, or (at your option) any later version. 14 | % 15 | % WecOptTool is distributed in the hope that it will be useful, 16 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | % GNU General Public License for more details. 19 | % 20 | % You should have received a copy of the GNU General Public 21 | % License along with WecOptTool. If not, see 22 | % . 23 | 24 | msg = 'Inputs must be of equal length'; 25 | ID = 'WecOptTool:Validation:NotEqualLength'; 26 | assert(length(x)==length(y),ID,msg); 27 | 28 | end 29 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+validation/mustBeFunctionHandle.m: -------------------------------------------------------------------------------- 1 | function mustBeFunctionHandle(input) 2 | % Returns an error if input is not a function handle 3 | 4 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 5 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 6 | % U.S. Government retains certain rights in this software. 7 | % 8 | % This file is part of WecOptTool. 9 | % 10 | % WecOptTool is free software: you can redistribute it and/or 11 | % modify it under the terms of the GNU General Public License as 12 | % published by the Free Software Foundation, either version 3 of 13 | % the License, or (at your option) any later version. 14 | % 15 | % WecOptTool is distributed in the hope that it will be useful, 16 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | % GNU General Public License for more details. 19 | % 20 | % You should have received a copy of the GNU General Public 21 | % License along with WecOptTool. If not, see 22 | % . 23 | 24 | if ~isa(input, 'function_handle') 25 | error('WecOptTool:Validation:NotFunctionHandle', ... 26 | 'Input must be a function handle') 27 | end 28 | 29 | end 30 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+vendor/+WEC_Sim/NOTICE: -------------------------------------------------------------------------------- 1 | WEC-Sim (Wave Energy Converter SIMulator) 2 | Copyright 2014 the National Renewable Energy Laboratory and Sandia Corporation 3 | 4 | Sandia and NREL Developers: 5 | Yi-Hsiang Yu (National Renewable Energy Laboratory) 6 | Kelley Ruehl (Sandia National Laboratories) 7 | Michael Lawson (National Renewable Energy Laboratory) 8 | Carlos Michelen (Sandia National Laboratories) 9 | Jennifer Van Rij (National Renewable Energy Laboratory) 10 | Nathan Tom (National Renewable Energy Laboratory) 11 | 12 | See list of external contributors on the WEC-Sim webite. 13 | 14 | Several libraries developed by external parties are used by WEC-Sim. License information for these libraries is as follows: 15 | source/functions/import_stl_fast/import_stl_fast.m - see license in import_stl_fast.m 16 | 17 | Modifications March 2020 18 | National Technology & Engineering Solutions of Sandia, LLC (NTESS) 19 | -------------------------------------------------------------------------- 20 | + Read_NEMOH.m and Normalize.m packaged within WecOptTool 21 | + Minor modification was made to Read_NEMOH.m to access package namespace 22 | + Remove waitbar call in Read_NEMOH.m 23 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/+vendor/+WEC_Sim/Normalize.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SNL-WaterPower/WecOptTool-MATLAB/0a9faa189f8570444fac5ebe0da2a9fcd94958eb/toolbox/+WecOptTool/+vendor/+WEC_Sim/Normalize.m -------------------------------------------------------------------------------- /toolbox/+WecOptTool/AutoFolder.m: -------------------------------------------------------------------------------- 1 | classdef AutoFolder < WecOptTool.base.TempFolder 2 | % Class that creates unique temporary folders, which are deleted 3 | % upon object destruction. 4 | % 5 | % Attributes: 6 | % path (string): path to unique folder for storage 7 | % 8 | % -- 9 | % 10 | % AutoFolder Methods: 11 | % stashVar - store a variable for recovery later 12 | % recoverVar - retrieve stashed variable 13 | % archive - Save the folder and contents 14 | % 15 | % -- 16 | 17 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 18 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 19 | % U.S. Government retains certain rights in this software. 20 | % 21 | % This file is part of WecOptTool. 22 | % 23 | % WecOptTool is free software: you can redistribute it and/or 24 | % modify it under the terms of the GNU General Public License as 25 | % published by the Free Software Foundation, either version 3 of 26 | % the License, or (at your option) any later version. 27 | % 28 | % WecOptTool is distributed in the hope that it will be useful, 29 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 | % GNU General Public License for more details. 32 | % 33 | % You should have received a copy of the GNU General Public 34 | % License along with WecOptTool. If not, see 35 | % . 36 | 37 | properties (Access = protected) 38 | varsPath 39 | end 40 | 41 | methods 42 | 43 | function obj = AutoFolder() 44 | 45 | obj = obj@WecOptTool.base.TempFolder(); 46 | obj.varsPath = tempname; 47 | obj.mkdirSafe(obj.varsPath); 48 | 49 | end 50 | 51 | function stashVar(obj, variable) 52 | % Store a variable for recovery later. 53 | % 54 | % Arguments: 55 | % variable: variable to store 56 | % 57 | % Note: 58 | % A new stash is created every time a variable is stored, 59 | % so multiple values may be returned by 60 | % :mat:meth:`.recoverVar` 61 | % 62 | 63 | arguments 64 | obj 65 | variable {mustBeNonempty} 66 | end 67 | 68 | resultsFolder = tempname(obj.varsPath); 69 | mkdir(resultsFolder); 70 | etcPath = fullfile(resultsFolder, inputname(2) + ".mat"); 71 | save(etcPath, "variable"); 72 | 73 | end 74 | 75 | function result = recoverVar(obj, variableName) 76 | % Recover stashed variable 77 | % 78 | % Arguments: 79 | % variableName (string): variable to recover 80 | % 81 | % Returns: 82 | % cell array: 83 | % cell array containing all stored version of given 84 | % variable name 85 | % 86 | 87 | arguments 88 | obj 89 | variableName string {mustBeNonempty} 90 | end 91 | 92 | pDirs = WecOptTool.system.getFolders(obj.varsPath, ... 93 | "absPath", true); 94 | nDirs = length(pDirs); 95 | result = {}; 96 | 97 | for i = 1:nDirs 98 | dir = pDirs{i}; 99 | fileName = fullfile(dir, variableName + ".mat"); 100 | if isfile(fileName) 101 | result = [result, {load(fileName).variable}]; 102 | end 103 | end 104 | 105 | end 106 | 107 | function archive(obj, targetPath) 108 | % Save the folder and contents 109 | % 110 | % Args: 111 | % targetPath (string): Path to destination folder 112 | % 113 | % Note: 114 | % If there are no files to copy this function will not 115 | % make the destination folder 116 | % 117 | 118 | arguments 119 | obj 120 | targetPath string 121 | end 122 | 123 | if length(dir(obj.path)) == 2 124 | return 125 | end 126 | 127 | copyfile(obj.path, targetPath); 128 | 129 | end 130 | 131 | end 132 | 133 | methods (Access = protected) 134 | 135 | function obj = rmFolders(obj) 136 | if isfolder(obj.path) 137 | WecOptTool.system.rmdirRetry(obj.path); 138 | end 139 | if isfolder(obj.varsPath) 140 | WecOptTool.system.rmdirRetry(obj.varsPath); 141 | end 142 | end 143 | 144 | function delete(obj) 145 | if ~WecOptTool.system.isParallel() 146 | obj.rmFolders(); 147 | end 148 | end 149 | 150 | end 151 | 152 | end 153 | 154 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/Hydrodynamics.m: -------------------------------------------------------------------------------- 1 | classdef Hydrodynamics 2 | % Data type for storage of solver hydrodynamics output. 3 | % 4 | % This data type defines a set of parameters that are common to the 5 | % description of wave device hydrodynamics parameters, such as in 6 | % `WEC-Sim's BEMIO `_. 7 | % 8 | % The following parameters must be provided within the input struct, 9 | % which map directly to class attributes (see below): 10 | % 11 | % * ex 12 | % * g 13 | % * rho 14 | % * w 15 | % * A 16 | % * Ainf 17 | % * B 18 | % * C 19 | % * Nb 20 | % * Nh 21 | % * Nf 22 | % * Vo 23 | % 24 | % Note: 25 | % Any negative radiation damping coefficients detected for 26 | % individual bodies will be set to zero, automatically. 27 | % 28 | % Arguments: 29 | % hydroData (struct): 30 | % A struct containing the required fields 31 | % options: name-value pair options. See below. 32 | % 33 | % The following options are supported: 34 | % 35 | % solverName (string): 36 | % The name of the solver used to generate the data 37 | % runDirectory (string): 38 | % Path to the directory containing the solver's output files 39 | % 40 | % Attributes: 41 | % base (struct): 42 | % copy of the input struct 43 | % ex (array of double): 44 | % complex excitation force or torque ([6*Nb,Nh,Nf]) 45 | % g (double): 46 | % gravitational acceleration 47 | % rho (double): 48 | % water density 49 | % w (array of double): 50 | % simulated wave frequencies ([1,Nf]) 51 | % A (array of double): 52 | % radiation added mass ([6*Nb,6*Nb,Nf]) 53 | % Ainf (array of double): 54 | % infinite frequency added mass ([6*Nb,6*Nb]) 55 | % B (array of double): 56 | % radiation wave damping ([6*Nb,6*Nb,Nf]) 57 | % C (array of double): 58 | % hydrostatic restoring stiffness ([6,6,Nb]) 59 | % Nb (int32): 60 | % number of bodies 61 | % Nh (int32): 62 | % number of wave headings 63 | % Nf (int32): 64 | % number of wave frequencies 65 | % Vo (array of double): 66 | % displaced volume ([1,Nb]) 67 | % solverName (string): 68 | % name of solver used to generate hydrodyamic parameters. 69 | % Default is "Unknown". 70 | % runDirectory (string): 71 | % path to folder containing output files of the hydrodynamic 72 | % solver. Defaults to "". 73 | % 74 | % -- 75 | % 76 | % Hydrodynamics Properties: 77 | % S - spectral density 78 | % base - copy of the input struct 79 | % ex - complex component of excitation force or torque ([6*Nb,Nh,Nf]) 80 | % g - gravitational acceleration 81 | % rho - water density 82 | % w - simulated wave frequencies ([1,Nf]) 83 | % A - radiation added mass ([6*Nb,6*Nb,Nf]) 84 | % Ainf - infinite frequency added mass ([6*Nb,6*Nb]) 85 | % B - radiation wave damping ([6*Nb,6*Nb,Nf]) 86 | % C - hydrostatic restoring stiffness ([6,6,Nb]) 87 | % Nb - number of bodies 88 | % Nh - number of wave headings 89 | % Nf - number of wave frequencies 90 | % Vo - displaced volume ([1,Nb]) 91 | % solverName - name of solver used to generate hydrodyamic parameters. Default is "Unknown". 92 | % runDirectory - Path to folder containing output files of the hydrodynamic solver. Defaults to "". 93 | % 94 | % -- 95 | 96 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 97 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 98 | % U.S. Government retains certain rights in this software. 99 | % 100 | % This file is part of WecOptTool. 101 | % 102 | % WecOptTool is free software: you can redistribute it and/or 103 | % modify it under the terms of the GNU General Public License as 104 | % published by the Free Software Foundation, either version 3 of 105 | % the License, or (at your option) any later version. 106 | % 107 | % WecOptTool is distributed in the hope that it will be useful, 108 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 109 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 110 | % GNU General Public License for more details. 111 | % 112 | % You should have received a copy of the GNU General Public 113 | % License along with WecOptTool. If not, see 114 | % . 115 | 116 | properties 117 | base 118 | ex 119 | g 120 | rho 121 | w 122 | A 123 | Ainf 124 | B 125 | C 126 | Nb 127 | Nh 128 | Nf 129 | Vo 130 | solverName 131 | runDirectory 132 | end 133 | 134 | methods 135 | 136 | function obj = Hydrodynamics(hydroData, options) 137 | 138 | arguments 139 | hydroData 140 | options.solverName = "Unknown" 141 | options.runDirectory = "" 142 | end 143 | 144 | obj.base = hydroData; 145 | obj.ex = complex(hydroData.ex_re, hydroData.ex_im); 146 | obj.g = hydroData.g; 147 | obj.rho = hydroData.rho; 148 | obj.w = hydroData.w; 149 | obj.A = hydroData.A; 150 | obj.Ainf = hydroData.Ainf; 151 | obj.B = obj.checkDamping(hydroData.B); 152 | obj.C = hydroData.C; 153 | obj.Nb = hydroData.Nb; 154 | obj.Nh = hydroData.Nh; 155 | obj.Nf = hydroData.Nf; 156 | obj.Vo = hydroData.Vo; 157 | obj.solverName = options.solverName; 158 | obj.runDirectory = options.runDirectory; 159 | 160 | end 161 | 162 | end 163 | 164 | methods (Static, Access=private) 165 | 166 | function newB = checkDamping(B) 167 | % Checks that diagonal radiation damping always positive 168 | 169 | newB = B; 170 | 171 | for ii = 1:size(B, 1) 172 | Bdiag = squeeze(B(ii,ii,:)); 173 | Bdiag(Bdiag < 0) = 0; 174 | newB(ii,ii,:) = Bdiag; 175 | end 176 | 177 | end 178 | 179 | end 180 | 181 | end 182 | 183 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/data/8spectra.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SNL-WaterPower/WecOptTool-MATLAB/0a9faa189f8570444fac5ebe0da2a9fcd94958eb/toolbox/+WecOptTool/data/8spectra.mat -------------------------------------------------------------------------------- /toolbox/+WecOptTool/data/spectrum.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SNL-WaterPower/WecOptTool-MATLAB/0a9faa189f8570444fac5ebe0da2a9fcd94958eb/toolbox/+WecOptTool/data/spectrum.mat -------------------------------------------------------------------------------- /toolbox/+WecOptTool/mesh.m: -------------------------------------------------------------------------------- 1 | function mesh = mesh(meshName, folder, varargin) 2 | % Make a mesh using shortcuts to the ``makeMesh`` method of the 3 | % defined Mesher concrete classes in the :mat:mod:`+WecOptTool.+mesh` 4 | % package. 5 | % 6 | % Arguments: 7 | % meshName (string): 8 | % Meshing routine to use. Current options are: 9 | % 10 | % * AxiMesh (:mat:class:`+WecOptTool.+mesh.AxiMesh`) 11 | % 12 | % folder (string): 13 | % Path to the folder to store output files 14 | % varargin: 15 | % Arguments to pass to the meshing routine. See the 16 | % ``makeMesh`` method of the chosen mesher class for details. 17 | % 18 | % Returns: 19 | % struct: 20 | % A mesh description with fields as described below 21 | % 22 | % ============ ================ ====================================== 23 | % **Variable** **Format** **Description** 24 | % bodyNum int32 body number 25 | % name char array name of the mesh 26 | % nodes Nx4 table table of N node positions with columns ID, x, y, z 27 | % panels Mx4 int32 array array of M panels where each row contains the 4 connected node IDs 28 | % xzSymmetric logical body is symmetric in xz plane (half mesh) 29 | % zG double z-coordinate of the bodies centre of gravity 30 | % ============ ================ ====================================== 31 | % 32 | % -- 33 | % 34 | % See also WecOptTool.mesh.AxiMesh 35 | % 36 | % -- 37 | 38 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 39 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 40 | % U.S. Government retains certain rights in this software. 41 | % 42 | % This file is part of WecOptTool. 43 | % 44 | % WecOptTool is free software: you can redistribute it and/or 45 | % modify it under the terms of the GNU General Public License as 46 | % published by the Free Software Foundation, either version 3 of 47 | % the License, or (at your option) any later version. 48 | % 49 | % WecOptTool is distributed in the hope that it will be useful, 50 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 51 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 52 | % GNU General Public License for more details. 53 | % 54 | % You should have received a copy of the GNU General Public 55 | % License along with WecOptTool. If not, see 56 | % . 57 | 58 | fullQName = "WecOptTool.mesh." + meshName; 59 | meshHandle = str2func(fullQName); 60 | mesher = meshHandle(folder); 61 | mesh = mesher.makeMesh(varargin{:}); 62 | 63 | end 64 | -------------------------------------------------------------------------------- /toolbox/+WecOptTool/solver.m: -------------------------------------------------------------------------------- 1 | function hydro = solver(solverName, folder, varargin) 2 | % Solve a mesh using shortcuts to the ``getHydro`` method of the 3 | % defined Solver concrete classes in the :mat:mod:`+WecOptTool.+solver` 4 | % package. 5 | % 6 | % Arguments: 7 | % solverName (string): 8 | % Solver routine to use. Current options are: 9 | % 10 | % * NEMOH (:mat:class:`+WecOptTool.+solver.NEMOH`) 11 | % 12 | % folder (string): 13 | % Path to the folder to store output files 14 | % varargin: 15 | % Arguments to pass to the solver routine. See the ``getHydro`` 16 | % method of the chosen solver class for details. 17 | % 18 | % Returns: 19 | % struct: Output struct from chosen solver 20 | % 21 | % -- 22 | % 23 | % See also WecOptTool.solver.NEMOH 24 | % 25 | % -- 26 | 27 | % Copyright 2020 National Technology & Engineering Solutions of Sandia, 28 | % LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the 29 | % U.S. Government retains certain rights in this software. 30 | % 31 | % This file is part of WecOptTool. 32 | % 33 | % WecOptTool is free software: you can redistribute it and/or 34 | % modify it under the terms of the GNU General Public License as 35 | % published by the Free Software Foundation, either version 3 of 36 | % the License, or (at your option) any later version. 37 | % 38 | % WecOptTool is distributed in the hope that it will be useful, 39 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 40 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 41 | % GNU General Public License for more details. 42 | % 43 | % You should have received a copy of the GNU General Public 44 | % License along with WecOptTool. If not, see 45 | % . 46 | 47 | fullQName = "WecOptTool.solver." + solverName; 48 | solverHandle = str2func(fullQName); 49 | solver = solverHandle(folder); 50 | hydro = solver.getHydro(varargin{:}); 51 | 52 | end 53 | --------------------------------------------------------------------------------