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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-14-large, macos-latest]
os: [macos-14-large]

steps:
- name: Setup cmake
Expand Down
450 changes: 340 additions & 110 deletions ssc/cmod_mhk_costs.cpp

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions ssc/cmod_mhk_wave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,9 +444,13 @@ class cm_mhk_wave : public compute_module
for (size_t j = 0; j < (size_t)wave_power_matrix.ncols(); j++) {

//Calculate and allocate annual_energy_distribution:
if (j == 0 || i == 0) //Where (i = 0) is the row header, and (j = 0) is the column header.
p_annual_energy_dist[k] = (ssc_number_t) wave_resource_matrix.at(i, j); //Don't do anything with top left corner of matrix as this value is always 0 and not part of the grid
else {
if (j == 0 || i == 0) { //Where (i = 0) is the row header, and (j = 0) is the column header.
if (wave_resource_matrix.at(i, j) != wave_power_matrix.at(i, j)) {
throw exec_error("mhk_wave", "Resource matrix and Power matrix bins do not match.");
}
p_annual_energy_dist[k] = (ssc_number_t)wave_resource_matrix.at(i, j); //Don't do anything with top left corner of matrix as this value is always 0 and not part of the grid
}
else {
//Find annual probability (as a %) of wave at height i and period j, multiply by 8760/100 to find fractional hours per year that wave(i,j) is achieved;
//Mult. by number of devices and total loss multiplier to find energy for certain wave type in grid
p_annual_energy_dist[k] = (ssc_number_t)(wave_resource_matrix.at(i,j) * wave_power_matrix.at(i,j) * 8760.0 / 100.0) * (1-total_loss/100) * number_devices;
Expand Down
157 changes: 115 additions & 42 deletions ssc/cmod_tidalfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,17 +125,22 @@ class cm_tidal_file_reader : public compute_module
void exec()
{

if (as_integer("tidal_resource_model_choice") == 0) return;
if (as_integer("tidal_resource_model_choice") == 0) return; //Nothing to do

std::string file;
if (is_assigned("tidal_resource_filename") && as_integer("tidal_resource_model_choice")==1)
{
file = as_string("tidal_resource_filename");
}
else if (is_assigned("tidal_resource_filename_dist") && as_integer("tidal_resource_model_choice") == 0)
{
file = as_string("tidal_resource_filename_dist");
}
else
{
throw exec_error("tidal_file_reader", "Model choice and tidal resource file do not match");
}

if (file.empty())
{
throw exec_error("tidal_file_reader", "File name missing.");
Expand Down Expand Up @@ -168,41 +173,98 @@ class cm_tidal_file_reader : public compute_module
throw exec_error("tidal_file_reader", "Number of header column labels does not match number of values. There are " + std::to_string(ncols) + "keys and " + std::to_string(ncols1) + "values.");
}
if (as_integer("tidal_resource_model_choice") == 0) {
assign("name", var_data(values[0]));
assign("city", var_data(values[1]));
assign("state", var_data(values[2]));
assign("country", var_data(values[3]));
// lat with S is negative
ssc_number_t dlat = std::numeric_limits<double>::quiet_NaN();
std::vector<std::string> slat = split(values[4], ' ');
if (slat.size() > 0)
//assign("name", var_data(values[0]));
//assign("city", var_data(values[1]));
//assign("state", var_data(values[2]));
//assign("country", var_data(values[3]));
//// lat with S is negative
//ssc_number_t dlat = std::numeric_limits<double>::quiet_NaN();
//std::vector<std::string> slat = split(values[4], ' ');
//if (slat.size() > 0)
//{
// dlat = std::stod(slat[0]);
// if (slat.size() > 1)
// {
// if (slat[1] == "S") dlat = 0.0 - dlat;
// }
//}
//assign("lat", var_data(dlat));
//// lon with W is negative
//ssc_number_t dlon = std::numeric_limits<double>::quiet_NaN();
//std::vector<std::string> slon = split(values[5], ' ');
//if (slon.size() > 0)
//{
// dlon = std::stod(slon[0]);
// if (slon.size() > 1)
// {
// if (slon[1] == "W") dlon = 0.0 - dlon;
// }
//}
//assign("lon", var_data(dlon));
//assign("nearby_buoy_number", var_data(values[6]));
//assign("average_power_flux", var_data(std::stod(values[7])));
//assign("bathymetry", var_data(values[8]));
//assign("sea_bed", var_data(values[9]));
//assign("tz", var_data(std::stod(values[10])));
//assign("data_source", var_data(values[11]));
//assign("notes", var_data(values[12]));

// allow metadata rows to have different lengths as long as required data is included
ncols = std::min(ncols, ncols1);

std::string name, value;

for (size_t i = 0; (int)i < ncols; i++)
{
dlat = std::stod(slat[0]);
if (slat.size() > 1)

name = "";
if (!keys[i].empty())
name = util::lower_case(trimboth(keys[i]));

value = "";
if (!values[i].empty())
value = trimboth(values[i]);

// required metadata (see checks below)
if (name == "lat" || name == "latitude")
{
if (slat[1] == "S") dlat = 0.0 - dlat;
assign("lat", var_data(std::stod(value)));
}
}
assign("lat", var_data(dlat));
// lon with W is negative
ssc_number_t dlon = std::numeric_limits<double>::quiet_NaN();
std::vector<std::string> slon = split(values[5], ' ');
if (slon.size() > 0)
{
dlon = std::stod(slon[0]);
if (slon.size() > 1)
else if (name == "lon" || name == "long" || name == "longitude" || name == "lng")
{
assign("lon", var_data(std::stod(value)));
}
else if (name == "tz" || name == "timezone" || name == "time zone") // require "time zone" and "local time zone" columns in NSRDB files are the same
{
if (slon[1] == "W") dlon = 0.0 - dlon;
assign("tz", var_data(std::stod(value)));
}
else if (name == "distance to shore" || name == "shore distance" || name == "distance") // require "time zone" and "local time zone" columns in NSRDB files are the same
{
assign("distance_to_shore_file", var_data(std::stod(value)));
}
else if (name == "water depth" || name == "depth") // require "time zone" and "local time zone" columns in NSRDB files are the same
{
assign("water_depth_file", var_data(std::stod(value)));
}
else if (name == "id" || name == "jurisdiction" || name == "station id" || name == "wban" || name == "wban#" || name == "site")
{
assign("location", var_data(value));
}
else if (name == "location" || name == "location id")
{
assign("location_id", var_data(value));
}


else if (name == "source" || name == "src" || name == "data source")
{
assign("data_source", var_data(value));
}
else if (name == "notes" || name == "source notes")
{
assign("notes", var_data(value));
}
}
assign("lon", var_data(dlon));
assign("nearby_buoy_number", var_data(values[6]));
assign("average_power_flux", var_data(std::stod(values[7])));
assign("bathymetry", var_data(values[8]));
assign("sea_bed", var_data(values[9]));
assign("tz", var_data(std::stod(values[10])));
assign("data_source", var_data(values[11]));
assign("notes", var_data(values[12]));
}
else {
/*
Expand Down Expand Up @@ -416,28 +478,39 @@ class cm_tidal_file_reader : public compute_module
assign("number_hours", int(numberRecords * hourdiff));
}
else if (as_integer("tidal_resource_model_choice") == 0) {
ssc_number_t* mat = allocate("wave_resource_matrix", 21, 22);
for (size_t r = 0; r < 21; r++)
getline(ifs, buf); //Skip past column labels for record counting
size_t numberRecords = 0;
while (getline(ifs, buf)) {
numberRecords++;

}

ifs.clear();
ifs.seekg(0);
for (size_t i = 0; i < 3; i++)
getline(ifs, buf);
if (ifs.eof())
{
throw exec_error("tidal_file_reader", "Could not read column names");
}
ssc_number_t* mat = allocate("tidal_resource", numberRecords, 2);
for (size_t r = 0; r < numberRecords; r++)
{
getline(ifs, buf);
values.clear();
values = split(buf);
if (values.size() != 22)
{
throw exec_error("tidal_file_reader", "Wave period columns must span 0.5s to 20.5s with increments of 1s. Incorrect number of wave period (s) columns: " + std::to_string(values.size()));
}
for (size_t c = 0; c < 22; c++)
if (values.size() != 2)
{
if (r == 0 && c == 0)
mat[r * 22 + c] = 0.0;
else
mat[r * 22 + c] = std::stod(values[c]);
throw exec_error("tidal_file_reader", "Tidal resource probability must contain 2 columns: tidal velocity and probability of occurence");
}
mat[r * 2] = std::stod(values[0]);
mat[r * 2 + 1] = std::stod(values[1]);

}

}
else {
throw exec_error("tidal_file_reader", "Resource data type needs to be defined ");
throw exec_error("tidal_file_reader", "Resource data type needs to be defined. ");
}

return;
Expand Down
1 change: 1 addition & 0 deletions ssc/cmod_wavefile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ class cm_wave_file_reader : public compute_module
value = "";
if (!values[i].empty())
value = trimboth(values[i]);
if (value == "") continue;

// required metadata (see checks below)
if (name == "lat" || name == "latitude")
Expand Down
117 changes: 117 additions & 0 deletions test/input_cases/mhk/mhk_cost_inputs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
BSD 3-Clause License

Copyright (c) Alliance for Sustainable Energy, LLC. See also https://github.com/NREL/ssc/blob/develop/LICENSE
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef MHK_COST_INPUTS_H_
#define MHK_COST_INPUTS_H_

#include <stdio.h>
#include "../test/input_cases/code_generator_utilities.h"

void mhk_cost_inputs(ssc_data_t &data) {

ssc_data_set_number(data, "device_rated_power", 286);
ssc_data_set_number(data, "system_capacity", 28600);
ssc_data_set_number(data, "devices_per_row", 10);
ssc_data_set_number(data, "marine_energy_tech", 0);
ssc_data_set_number(data, "library_or_input_wec", 0);
ssc_data_set_string(data, "lib_wave_device", "RM3");
ssc_data_set_string(data, "lib_tidal_device", "RM1");
ssc_data_set_number(data, "structural_assembly_cost_method", 2);
ssc_data_set_number(data, "structural_assembly_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "structural_assembly_cost_total", 1000000);
ssc_data_set_number(data, "structural_assembly_cost_rvalue", 0.1);
ssc_data_set_number(data, "power_takeoff_system_cost_method", 2);
ssc_data_set_number(data, "power_takeoff_system_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "power_takeoff_system_cost_total", 1000000);
ssc_data_set_number(data, "power_takeoff_system_cost_rvalue", 0.1);
ssc_data_set_number(data, "mooring_found_substruc_cost_method", 2);
ssc_data_set_number(data, "mooring_found_substruc_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "mooring_found_substruc_cost_total", 1000000);
ssc_data_set_number(data, "mooring_found_substruc_cost_rvalue", 0.1);
ssc_data_set_number(data, "development_cost_method", 2);
ssc_data_set_number(data, "development_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "development_cost_total", 1000000);
ssc_data_set_number(data, "development_cost_rvalue", 0.1);
ssc_data_set_number(data, "eng_and_mgmt_cost_method", 2);
ssc_data_set_number(data, "eng_and_mgmt_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "eng_and_mgmt_cost_total", 1000000);
ssc_data_set_number(data, "eng_and_mgmt_cost_rvalue", 0.1);
ssc_data_set_number(data, "assembly_and_install_cost_method", 2);
ssc_data_set_number(data, "assembly_and_install_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "assembly_and_install_cost_total", 1000000);
ssc_data_set_number(data, "assembly_and_install_cost_rvalue", 0.1);
ssc_data_set_number(data, "other_infrastructure_cost_method", 2);
ssc_data_set_number(data, "other_infrastructure_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "other_infrastructure_cost_total", 1000000);
ssc_data_set_number(data, "other_infrastructure_cost_rvalue", 0.1);
ssc_data_set_number(data, "elec_infras_cost_method", 2);
ssc_data_set_number(data, "elec_infras_cost_modeled", 0);
ssc_data_set_number(data, "elec_infras_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "elec_infras_cost_total", 1000000);
ssc_data_set_number(data, "elec_infras_cost_rvalue", 0.1);
ssc_data_set_number(data, "plant_commissioning_cost_method", 2);
ssc_data_set_number(data, "plant_commissioning_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "plant_commissioning_cost_total", 1000000);
ssc_data_set_number(data, "plant_commissioning_cost_rvalue", 0.1);
ssc_data_set_number(data, "site_access_port_staging_cost_method", 2);
ssc_data_set_number(data, "site_access_port_staging_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "site_access_port_staging_cost_total", 1000000);
ssc_data_set_number(data, "site_access_port_staging_cost_rvalue", 0.1);
ssc_data_set_number(data, "project_contingency_cost_method", 2);
ssc_data_set_number(data, "project_contingency_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "project_contingency_cost_total", 1000000);
ssc_data_set_number(data, "project_contingency_cost_rvalue", 0.1);
ssc_data_set_number(data, "insurance_during_construction_cost_method", 2);
ssc_data_set_number(data, "insurance_during_construction_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "insurance_during_construction_cost_total", 1000000);
ssc_data_set_number(data, "insurance_during_construction_cost_rvalue", 0.1);
ssc_data_set_number(data, "reserve_accounts_cost_method", 2);
ssc_data_set_number(data, "reserve_accounts_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "reserve_accounts_cost_total", 1000000);
ssc_data_set_number(data, "reserve_accounts_cost_rvalue", 0.1);
ssc_data_set_number(data, "other_financial_cost_method", 2);
ssc_data_set_number(data, "other_financial_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "other_financial_cost_total", 1000000);
ssc_data_set_number(data, "other_financial_cost_rvalue", 0.1);
ssc_data_set_number(data, "operations_cost_method", 2);
ssc_data_set_number(data, "operations_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "operations_cost_total", 1000000);
ssc_data_set_number(data, "operations_cost_rvalue", 0.1);
ssc_data_set_number(data, "maintenance_cost_method", 2);
ssc_data_set_number(data, "maintenance_cost_input", 100); //$ or $/kW
ssc_data_set_number(data, "maintenance_cost_total", 1000000);
ssc_data_set_number(data, "maintenance_cost_rvalue", 0.1);


}

#endif
Loading