diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 22325dcd..d5d1b804 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -7,14 +7,39 @@ env:
BUILD_TYPE: Release
jobs:
- build:
+ windows:
+ name: ${{ matrix.os }}-${{ matrix.arch }}
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [windows-2019, windows-2022]
+ arch: [x86, x64]
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Configure CMake
+ # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
+ # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
+ run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
+
+ - name: Build
+ # Build your program with the given configuration
+ run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
+
+ - name: Test
+ working-directory: ${{github.workspace}}/build
+ run: ctest -C RELEASE -V
+
+ mac:
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
- os: [windows-2019, windows-2022, macos-12, macos-14, ubuntu-latest]
- # arch: [x86, x64]
+ os: [macos-13, macos-latest]
steps:
- name: Checkout repository
@@ -29,6 +54,40 @@ jobs:
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
+ - name: Test
+ working-directory: ${{github.workspace}}/build
+ run: ctest -C RELEASE -V
+
+ linux:
+ name: ${{ matrix.os }}-${{ matrix.arch }}
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ ubuntu-24.04]
+ arch: [x86_64, aarch64]
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Install QEMU for aarch64 emulation
+ uses: docker/setup-qemu-action@v2
+ with:
+ platforms: all
+
+ - name: Upgrade gcc
+ run: sudo apt-get install -y gcc g++
+
+ - name: Configure CMake
+ # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
+ # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
+ run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
+
+ - name: Build
+ # Build your program with the given configuration
+ run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
+
- name: Test
working-directory: ${{github.workspace}}/build
run: ctest -C RELEASE -V
\ No newline at end of file
diff --git a/CMakeLists-OpticalMeasurementParser.txt.in b/CMakeLists-OpticalMeasurementParser.txt.in
index 2ab026a7..1f6e46b9 100644
--- a/CMakeLists-OpticalMeasurementParser.txt.in
+++ b/CMakeLists-OpticalMeasurementParser.txt.in
@@ -4,7 +4,7 @@ include(ExternalProject)
ExternalProject_Add(OpticalMeasurementParser
GIT_REPOSITORY https://github.com/LBNL-ETA/OpticalMeasurementParser.git
- GIT_TAG "v2.3.0"
+ GIT_TAG "dec_2024_parsing"
UPDATE_COMMAND ""
PATCH_COMMAND ""
diff --git a/CMakeLists-THMXParser.txt.in b/CMakeLists-THMXParser.txt.in
index 12a624a2..4e2c39ab 100644
--- a/CMakeLists-THMXParser.txt.in
+++ b/CMakeLists-THMXParser.txt.in
@@ -4,7 +4,7 @@ include(ExternalProject)
ExternalProject_Add(THMXParser
GIT_REPOSITORY https://github.com/LBNL-ETA/THMXParser.git
- GIT_TAG "v1.1.1"
+ GIT_TAG "v1.1.2"
UPDATE_COMMAND ""
PATCH_COMMAND ""
diff --git a/CMakeLists-Windows-CalcEngine.txt.in b/CMakeLists-Windows-CalcEngine.txt.in
index beac13b2..d4b15647 100644
--- a/CMakeLists-Windows-CalcEngine.txt.in
+++ b/CMakeLists-Windows-CalcEngine.txt.in
@@ -4,7 +4,7 @@ include(ExternalProject)
ExternalProject_Add(Windows-CalcEngine
GIT_REPOSITORY https://github.com/LBNL-ETA/Windows-CalcEngine.git
- GIT_TAG "Version_1.0.48"
+ GIT_TAG "Version_1.0.50"
UPDATE_COMMAND ""
PATCH_COMMAND ""
diff --git a/doc/WinCalc.md b/doc/WinCalc.md
new file mode 100644
index 00000000..c6177934
--- /dev/null
+++ b/doc/WinCalc.md
@@ -0,0 +1,21 @@
+```mermaid
+graph TD
+ %% Package definitions
+ xmlParser[xmlParser
v1.0.2]
+ OpticalMeasurementParser[OpticalMeasurementParser
v2.3.2]
+ nlohmann[nlohmann
v3.11.3]
+ BSDFXMLParser[BSDFXMLParser
Version_0.0.2]
+ THMXParser[THMXParser
v1.1.2]
+ WindowsCalcEngine[WindowsCalcEngine
Version_1.0.50]
+ Windows-CalcStandards[Windows-CalcStandards
v1.2.1]
+ WinCalc[WinCalc
dec_2024_test_fix]
+
+ %% Package relations
+ WinCalc --> OpticalMeasurementParser
+ OpticalMeasurementParser --> nlohmann
+ OpticalMeasurementParser --> BSDFXMLParser
+ BSDFXMLParser --> xmlParser
+ THMXParser --> xmlParser
+ WinCalc --> THMXParser
+ WinCalc --> Windows-CalcStandards
+ WinCalc --> WindowsCalcEngine
diff --git a/readme.md b/readme.md
index 54f8f8c1..e59063bb 100644
--- a/readme.md
+++ b/readme.md
@@ -1,4 +1,4 @@
-Berkeley Lab WINDOW Calc Engine (CalcEngine) Copyright (c) 2016 - 2024, The
+Berkeley Lab WINDOW Calc Engine (CalcEngine) Copyright (c) 2016 - 2025, The
Regents of the University of California, through Lawrence Berkeley National
Laboratory (subject to receipt of any required approvals from the U.S.
Dept. of Energy). All rights reserved.
@@ -14,4 +14,7 @@ its behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
Software to reproduce, distribute copies to the public, prepare derivative
works, and perform publicly and display publicly, and to permit other to do
so.
+
+## Detailed package relation diagram
+[Located here](./doc/WinCalc.md)
diff --git a/src/convert_optics_parser.cpp b/src/convert_optics_parser.cpp
index ee3ed1d7..afbbebb5 100644
--- a/src/convert_optics_parser.cpp
+++ b/src/convert_optics_parser.cpp
@@ -97,6 +97,32 @@ namespace wincalc
return length_conversion;
}
+ double get_wavelength_unit_conversion_factor(OpticsParser::ProductData const & product)
+ {
+ // Seems like most wavelengths are in microns so default to that.
+ double wavelength_conversion = 1.0;
+ if(product.wavelengthUnit.has_value())
+ {
+ auto wavelength_unit = to_lower(product.wavelengthUnit.value());
+ if(wavelength_unit == "micron" || wavelength_unit == "microns")
+ {
+ // Default case, do nothing
+ }
+ else if(wavelength_unit == "nanometer" || wavelength_unit == "nanometers")
+ {
+ wavelength_conversion = 1.0 / 1000.0;
+ }
+ else
+ {
+ std::stringstream msg;
+ msg << "Unsupported wlvelength unit: " << product.wavelengthUnit.value()
+ << " Currently only micron and nanometer are supported.";
+ throw std::runtime_error(msg.str());
+ }
+ }
+ return wavelength_conversion;
+ }
+
std::shared_ptr convert_optical(OpticsParser::ProductData const & product)
{
auto length_conversion = get_length_unit_conversion_factor(product);
@@ -199,10 +225,23 @@ namespace wincalc
coated_side = convert_coated_side(product.coatedSide.value());
}
+ auto wl_values =
+ std::get>(wavelength_measured_values);
+
+ auto wl_unit_conversion_factor = get_wavelength_unit_conversion_factor(product);
+
+ if (wl_unit_conversion_factor != 1.0)
+ {
+ for (auto& val : wl_values)
+ {
+ val.wavelength *= wl_unit_conversion_factor;
+ }
+ }
+
converted.reset(new Product_Data_N_Band_Optical(
material_type,
product.thickness.value() * length_conversion,
- std::get>(wavelength_measured_values),
+ wl_values,
coated_side,
product.IRTransmittance,
product.IRTransmittance,
diff --git a/src/create_wce_objects.cpp b/src/create_wce_objects.cpp
index fd3f784b..f4be2f9f 100644
--- a/src/create_wce_objects.cpp
+++ b/src/create_wce_objects.cpp
@@ -101,33 +101,55 @@ namespace wincalc
return integration_types[integration_rule_type];
}
-
double get_minimum_wavelength(window_standards::Optical_Standard_Method const & method,
double product_data_min_wavelength,
FenestrationCommon::CSeries const & source_spectrum)
{
+ LOGMSG(
+ "begin get_minimum_wavelength for method " + method.name
+ + " with product_data_min_wavelength = " + std::to_string(product_data_min_wavelength));
double result = std::numeric_limits::quiet_NaN();
if(method.min_wavelength.type == window_standards::Wavelength_Boundary_Type::WAVELENGTH_SET)
{
+ LOGMSG("in if(method.min_wavelength.type == "
+ "window_standards::Wavelength_Boundary_Type::WAVELENGTH_SET)");
if(method.wavelength_set.type == window_standards::Wavelength_Set_Type::FILE)
{
+ LOGMSG(
+ "in if(method.wavelength_set.type == "
+ "window_standards::Wavelength_Set_Type::FILE) with "
+ "method.wavelength_set.values.size = " + std::to_string(method.wavelength_set.values.size()));
result = method.wavelength_set.values[0];
}
else if(method.wavelength_set.type == window_standards::Wavelength_Set_Type::SOURCE)
{
+ LOGMSG("in else if(method.wavelength_set.type == "
+ "window_standards::Wavelength_Set_Type::SOURCE) with "
+ "source_spectrum.getXArray().size() = "
+ + std::to_string(source_spectrum.getXArray().size()));
result = source_spectrum.getXArray().front();
}
if(method.wavelength_set.type == window_standards::Wavelength_Set_Type::DATA)
{
+ LOGMSG("method.wavelength_set.type == window_standards::Wavelength_Set_Type::DATA");
result = product_data_min_wavelength;
}
}
else if(method.min_wavelength.type == window_standards::Wavelength_Boundary_Type::NUMBER)
{
+ LOGMSG("in else if(method.min_wavelength.type == "
+ "window_standards::Wavelength_Boundary_Type::NUMBER) with "
+ "method.min_wavelength.value = "
+ + std::to_string(method.min_wavelength.value));
result = method.min_wavelength.value;
}
+ LOGMSG("end get_minimum_wavelength for method " + method.name
+ + " with product_data_min_wavelength = "
+ + std::to_string(product_data_min_wavelength)
+ + " result = " + std::to_string(result));
+
return result;
}
@@ -136,28 +158,51 @@ namespace wincalc
double product_data_max_wavelength,
FenestrationCommon::CSeries const & source_spectrum)
{
+ LOGMSG("begin get_maximum_wavelength for method " + method.name
+ + " with product_data_max_wavelength = "
+ + std::to_string(product_data_max_wavelength));
+
double result = std::numeric_limits::quiet_NaN();
if(method.max_wavelength.type == window_standards::Wavelength_Boundary_Type::WAVELENGTH_SET)
{
+ LOGMSG("in if(method.max_wavelength.type == window_standards::Wavelength_Boundary_Type::WAVELENGTH_SET)");
if(method.wavelength_set.type == window_standards::Wavelength_Set_Type::FILE)
{
+ LOGMSG("in if(method.wavelength_set.type == "
+ "window_standards::Wavelength_Set_Type::FILE) with "
+ "method.wavelength_set.values.size = "
+ + std::to_string(method.wavelength_set.values.size()));
+
result = method.wavelength_set.values.back();
}
else if(method.wavelength_set.type == window_standards::Wavelength_Set_Type::SOURCE)
{
+ LOGMSG("in else if(method.wavelength_set.type == "
+ "window_standards::Wavelength_Set_Type::SOURCE) with "
+ "source_spectrum.getXArray().size() = "
+ + std::to_string(source_spectrum.getXArray().size()));
result = source_spectrum.getXArray().back();
}
if(method.wavelength_set.type == window_standards::Wavelength_Set_Type::DATA)
{
+ LOGMSG("method.wavelength_set.type == window_standards::Wavelength_Set_Type::DATA");
result = product_data_max_wavelength;
}
}
else if(method.max_wavelength.type == window_standards::Wavelength_Boundary_Type::NUMBER)
{
+ LOGMSG("in else if(method.max_wavelength.type == "
+ "window_standards::Wavelength_Boundary_Type::NUMBER) with "
+ "method.max_wavelength.value = "
+ + std::to_string(method.max_wavelength.value));
result = method.max_wavelength.value;
}
+ LOGMSG("end get_maximum_wavelength for method " + method.name
+ + " with product_data_max_wavelength = "
+ + std::to_string(product_data_max_wavelength)
+ + " result = " + std::to_string(result));
return result;
}
@@ -389,21 +434,27 @@ namespace wincalc
Lambda_Range get_lambda_range(std::vector> const & products_wavelengths,
window_standards::Optical_Standard_Method const & method)
{
+ LOGMSG("begin get_lambda_range");
auto source_spectrum =
get_spectum_values(method.source_spectrum, method, products_wavelengths);
std::vector min_wavelengths;
std::vector max_wavelengths;
for(auto product_wavelengths : products_wavelengths)
{
+ LOGMSG("in for(auto product_wavelengths : products_wavelengths)");
min_wavelengths.push_back(
get_minimum_wavelength(method, product_wavelengths[0], source_spectrum));
+ LOGMSG("before max_wavelengths.push_back");
max_wavelengths.push_back(
get_maximum_wavelength(method, product_wavelengths.back(), source_spectrum));
}
// The min and max lambda should be the tighest boundary not the loosest
// So it should be the largest minimum and smallest maximum
+ LOGMSG("before min_wavelength = with min_wavelengths.size = " + std::to_string(min_wavelengths.size()));
double min_wavelength = *std::max_element(min_wavelengths.begin(), min_wavelengths.end());
+ LOGMSG("before max_wavelength = with max_wavelengths.size = " + std::to_string(max_wavelengths.size()));
double max_wavelength = *std::min_element(max_wavelengths.begin(), max_wavelengths.end());
+ LOGMSG("end get_lambda_range");
return Lambda_Range{min_wavelength, max_wavelength};
}
@@ -714,29 +765,37 @@ namespace wincalc
int number_visible_bands,
int number_solar_bands)
{
+ LOGMSG("begin create_multi_pane_specular(product_data, " + method.name + ")");
std::vector> layers;
+ LOGMSG("before number_of_layers = product_data.size()");
auto number_of_layers = product_data.size();
for(std::shared_ptr const & product : product_data)
{
+ LOGMSG("in for(std::shared_ptr const & product : "
+ "product_data)");
layers.push_back(create_specular_layer(product, method, number_of_layers));
}
+ LOGMSG("before wavelengths = get_wavelengths");
std::vector> wavelengths = get_wavelengths(product_data);
+ LOGMSG("before source_spectrum = get_spectum_values");
auto source_spectrum = get_spectum_values(method.source_spectrum, method, wavelengths);
+ LOGMSG("before detector_spectrum = get_spectum_values");
auto detector_spectrum = get_spectum_values(method.detector_spectrum, method, wavelengths);
-
+ LOGMSG("before combined_layer_wavelengths = combined_layer_wavelength_range_factory");
auto combined_layer_wavelengths = combined_layer_wavelength_range_factory(
wavelengths, type, number_visible_bands, number_solar_bands);
-
+ LOGMSG("before MultiLayerOptics::CMultiPaneSpecular::create");
auto layer =
MultiLayerOptics::CMultiPaneSpecular::create(layers, combined_layer_wavelengths);
-
+ LOGMSG("before standard_wavelengths = optical_standard_wavelength_set");
auto standard_wavelengths = optical_standard_wavelength_set(method, wavelengths);
-
+ LOGMSG("before SingleLayerOptics::CalculationProperties input");
const SingleLayerOptics::CalculationProperties input{
source_spectrum, standard_wavelengths, detector_spectrum};
+ LOGMSG("before layer->setCalculationProperties");
layer->setCalculationProperties(input);
-
+ LOGMSG("end create_multi_pane_specular(product_data, " + method.name + ")");
return layer;
}
@@ -746,9 +805,12 @@ namespace wincalc
size_t number_of_layers,
SingleLayerOptics::BSDFHemisphere const & bsdf_hemisphere)
{
+ LOGMSG("begin create_bsdf_layer_specular(product_data, " + method.name + ")");
auto material = create_material(product_data, method, number_of_layers);
+ LOGMSG("before SingleLayerOptics::CBSDFLayerMaker::getSpecularLayer");
auto layer =
SingleLayerOptics::CBSDFLayerMaker::getSpecularLayer(material, bsdf_hemisphere);
+ LOGMSG("begin create_bsdf_layer_specular(product_data, " + method.name + ")");
return layer;
}
@@ -758,9 +820,27 @@ namespace wincalc
size_t number_of_layers,
SingleLayerOptics::BSDFHemisphere const & bsdf_hemisphere)
{
+ LOGMSG("begin create_bsdf_layer_perfectly_diffuse(product_data, " + method.name + ")");
auto material = create_material(product_data, method, number_of_layers);
+ LOGMSG("before SingleLayerOptics::CBSDFLayerMaker::getPerfectlyDiffuseLayer");
auto layer =
SingleLayerOptics::CBSDFLayerMaker::getPerfectlyDiffuseLayer(material, bsdf_hemisphere);
+ LOGMSG("end create_bsdf_layer_perfectly_diffuse(product_data, " + method.name + ")");
+ return layer;
+ }
+
+ std::shared_ptr create_bsdf_layer_homogeneous_diffuse(
+ std::shared_ptr const & product_data,
+ window_standards::Optical_Standard_Method const & method,
+ size_t number_of_layers,
+ SingleLayerOptics::BSDFHemisphere const & bsdf_hemisphere)
+ {
+ LOGMSG("begin create_bsdf_layer_homogeneous_diffuse(product_data, " + method.name + ")");
+ auto material = create_material(product_data, method, number_of_layers);
+ LOGMSG("before SingleLayerOptics::CBSDFLayerMaker::getHomogeneousDiffuseLayer");
+ auto layer =
+ SingleLayerOptics::CBSDFLayerMaker::getHomogeneousDiffuseLayer(material, bsdf_hemisphere);
+ LOGMSG("end create_bsdf_layer_homogeneous_diffuse(product_data, " + method.name + ")");
return layer;
}
@@ -770,9 +850,12 @@ namespace wincalc
size_t number_of_layers,
SingleLayerOptics::BSDFHemisphere const & bsdf_hemisphere)
{
+ LOGMSG("begin create_bsdf_layer_preloaded_matrices(product_data, " + method.name + ")");
auto material = create_material(product_data, method, number_of_layers);
+ LOGMSG("before SingleLayerOptics::CBSDFLayerMaker::getPreLoadedBSDFLayer");
auto layer =
SingleLayerOptics::CBSDFLayerMaker::getPreLoadedBSDFLayer(material, bsdf_hemisphere);
+ LOGMSG("end create_bsdf_layer_preloaded_matrices(product_data, " + method.name + ")");
return layer;
}
@@ -782,8 +865,10 @@ namespace wincalc
size_t number_of_layers,
SingleLayerOptics::BSDFHemisphere const & bsdf_hemisphere)
{
+ LOGMSG("begin create_bsdf_layer_venetian(product_data, " + method.name + ")");
auto material =
create_material(product_data->material_optical_data, method, number_of_layers);
+ LOGMSG("before SingleLayerOptics::CBSDFLayerMaker::getVenetianLayer");
auto layer = SingleLayerOptics::CBSDFLayerMaker::getVenetianLayer(
material,
bsdf_hemisphere,
@@ -794,6 +879,7 @@ namespace wincalc
product_data->geometry.number_slat_segments,
product_data->geometry.distribution_method,
product_data->geometry.is_horizontal);
+ LOGMSG("end create_bsdf_layer_venetian(product_data, " + method.name + ")");
return layer;
}
@@ -803,13 +889,16 @@ namespace wincalc
size_t number_of_layers,
SingleLayerOptics::BSDFHemisphere const & bsdf_hemisphere)
{
+ LOGMSG("begin create_bsdf_layer_woven_shade(product_data, " + method.name + ")");
auto material =
create_material(product_data->material_optical_data, method, number_of_layers);
+ LOGMSG("before SingleLayerOptics::CBSDFLayerMaker::getWovenLayer");
auto layer =
SingleLayerOptics::CBSDFLayerMaker::getWovenLayer(material,
bsdf_hemisphere,
product_data->geometry.thread_diameter,
product_data->geometry.thread_spacing);
+ LOGMSG("end create_bsdf_layer_woven_shade(product_data, " + method.name + ")");
return layer;
}
@@ -819,10 +908,13 @@ namespace wincalc
size_t number_of_layers,
SingleLayerOptics::BSDFHemisphere const & bsdf_hemisphere)
{
+ LOGMSG("begin create_bsdf_layer_perforated_screen(product_data, " + method.name + ")");
auto material =
create_material(product_data->material_optical_data, method, number_of_layers);
+ LOGMSG("before if in create_bsdf_layer_perforated_screen");
if(product_data->geometry.perforation_type == wincalc::Perforated_Geometry::Type::CIRCULAR)
{
+ LOGMSG("in circular in create_bsdf_layer_perforated_screen");
return SingleLayerOptics::CBSDFLayerMaker::getCircularPerforatedLayer(
material,
bsdf_hemisphere,
@@ -834,6 +926,7 @@ namespace wincalc
else if(product_data->geometry.perforation_type
== wincalc::Perforated_Geometry::Type::RECTANGULAR)
{
+ LOGMSG("in rectangular in create_bsdf_layer_perforated_screen");
return SingleLayerOptics::CBSDFLayerMaker::getRectangularPerforatedLayer(
material,
bsdf_hemisphere,
@@ -846,6 +939,7 @@ namespace wincalc
else if(product_data->geometry.perforation_type
== wincalc::Perforated_Geometry::Type::SQUARE)
{
+ LOGMSG("in square in create_bsdf_layer_perforated_screen");
return SingleLayerOptics::CBSDFLayerMaker::getRectangularPerforatedLayer(
material,
bsdf_hemisphere,
@@ -857,6 +951,7 @@ namespace wincalc
}
else
{
+ LOGMSG("in else of create_bsdf_layer_perforated_screen");
std::stringstream msg;
msg << "Unsupported perforation type for optical bsdf layer: "
<< static_cast::type>(
@@ -872,6 +967,7 @@ namespace wincalc
size_t number_of_layers,
SingleLayerOptics::BSDFHemisphere const & bsdf_hemisphere)
{
+ LOGMSG("begin create_bsdf_layer(product_data, " + method.name + ")");
std::shared_ptr layer;
if(std::dynamic_pointer_cast(product_data))
{
@@ -883,6 +979,17 @@ namespace wincalc
number_of_layers,
bsdf_hemisphere);
}
+ else if(std::dynamic_pointer_cast(
+ product_data))
+ {
+ layer = create_bsdf_layer_homogeneous_diffuse(
+ std::dynamic_pointer_cast(
+ product_data)
+ ->material_optical_data,
+ method,
+ number_of_layers,
+ bsdf_hemisphere);
+ }
else if(std::dynamic_pointer_cast(product_data))
{
layer = create_bsdf_layer_venetian(
@@ -922,8 +1029,10 @@ namespace wincalc
else if(std::dynamic_pointer_cast(
product_data))
{
+ LOGMSG("in dual band in if in create_bsdf_layer");
if(method.name == "THERMAL IR")
{
+ LOGMSG("in if(method.name == THERMAL IR)");
// Thermal IR is a special case that can be calculated despite a lack of
// BSDF data. Since there is no BSDF for the IR range yet the IR range
// is instead modeled as a perfectly diffusing shade
@@ -932,6 +1041,7 @@ namespace wincalc
}
else
{
+ LOGMSG("in else of if(method.name == THERMAL IR)");
layer = create_bsdf_layer_preloaded_matrices(
std::dynamic_pointer_cast(
product_data),
@@ -942,11 +1052,12 @@ namespace wincalc
}
else
{
+ LOGMSG("in else in create_bsdf_layer");
layer =
create_bsdf_layer_specular(product_data, method, number_of_layers, bsdf_hemisphere);
}
-
+ LOGMSG("end create_bsdf_layer(product_data, " + method.name + ")");
return layer;
}
@@ -958,30 +1069,38 @@ namespace wincalc
int number_visible_bands,
int number_solar_bands)
{
+ LOGMSG("begin create_multi_pane_bsdf(products, " + method.name + ")");
std::vector> layers;
std::vector> wavelengths;
+ LOGMSG("before number_of_layers");
auto number_of_layers = products.size();
for(auto const & product : products)
{
+ LOGMSG("in for(auto const & product : products)");
layers.push_back(create_bsdf_layer(product, method, number_of_layers, bsdf_hemisphere));
+ LOGMSG("before wavelengths.push_back(product->wavelengths());");
wavelengths.push_back(product->wavelengths());
}
+ LOGMSG("before source_spectrum");
auto source_spectrum = get_spectum_values(method.source_spectrum, method, wavelengths);
-
+ LOGMSG("before detector_spectrum");
auto detector_spectrum = get_spectum_values(method.detector_spectrum, method, wavelengths);
-
+ LOGMSG("before combined_layer_wavelength_range_factory");
auto combined_layer_wavelengths = combined_layer_wavelength_range_factory(
wavelengths, type, number_visible_bands, number_solar_bands);
+ LOGMSG("before MultiLayerOptics::CMultiPaneBSDF::create");
auto layer = MultiLayerOptics::CMultiPaneBSDF::create(layers, combined_layer_wavelengths);
-
+ LOGMSG("before standard_wavelengths = optical_standard_wavelength_set");
auto standard_wavelengths = optical_standard_wavelength_set(method, wavelengths);
-
+ LOGMSG("before SingleLayerOptics::CalculationProperties input");
const SingleLayerOptics::CalculationProperties input{
source_spectrum, standard_wavelengths, detector_spectrum};
+ LOGMSG("before layer->setCalculationProperties");
layer->setCalculationProperties(input);
+ LOGMSG("end create_multi_pane_bsdf(products, " + method.name + ")");
return layer;
}
@@ -993,9 +1112,11 @@ namespace wincalc
int number_visible_bands,
int number_solar_bands)
{
+ LOGMSG("begin create_multi_pane(product_data, " + method.name + ")");
bool as_bsdf = false;
for(auto product : product_data)
{
+ LOGMSG("in for(auto product : product_data)");
if(std::dynamic_pointer_cast(product)
|| std::dynamic_pointer_cast(product))
{
@@ -1003,8 +1124,11 @@ namespace wincalc
break;
}
}
+
+ LOGMSG("before if(as_bsdf && !bsdf_hemisphere.has_value())");
if(as_bsdf && !bsdf_hemisphere.has_value())
{
+ LOGMSG("in if(as_bsdf && !bsdf_hemisphere.has_value())");
throw std::runtime_error(
"No BSDF hemisphere provided for a system with at least one bsdf type.");
}
@@ -1015,6 +1139,7 @@ namespace wincalc
if(as_bsdf)
{
+ LOGMSG("in if(as_bsdf)");
return create_multi_pane_bsdf(product_data,
method,
bsdf_hemisphere.value(),
@@ -1024,6 +1149,7 @@ namespace wincalc
}
else
{
+ LOGMSG("in else of if(as_bsdf)");
return create_multi_pane_specular(
product_data, method, type, number_visible_bands, number_solar_bands);
}
diff --git a/src/glazing_system.cpp b/src/glazing_system.cpp
index 238580a7..dcbd37ec 100644
--- a/src/glazing_system.cpp
+++ b/src/glazing_system.cpp
@@ -12,6 +12,9 @@ namespace wincalc
double theta,
double phi) const
{
+ LOGMSG("begin Glazing_System::optical_method_results(" + method_name + ", "
+ + std::to_string(theta) + ", " + std::to_string(phi) + ")");
+
if(method_name == "THERMAL IR")
{
throw std::runtime_error(
@@ -24,9 +27,11 @@ namespace wincalc
}
std::vector color_methods{
"COLOR_TRISTIMX", "COLOR_TRISTIMY", "COLOR_TRISTIMZ", "CRI_X", "CRI_Y", "CRI_Z"};
+ LOGMSG("before std::find");
if(std::find(color_methods.begin(), color_methods.end(), method_name)
!= color_methods.end())
{
+ LOGMSG("in std::find");
throw std::runtime_error(
"Individual tristimulus color optical methods should not be calculated using the "
"generic method for optical calculations. The color function which takes the X, Y "
@@ -35,8 +40,10 @@ namespace wincalc
"standard file but care should be taken in interpreting any results calculated this "
"way.");
}
+ LOGMSG("before get_method");
auto method = get_method(method_name);
- return calc_all(get_optical_layers(product_data),
+ LOGMSG("before calc_all");
+ auto result = calc_all(get_optical_layers(product_data),
method,
theta,
phi,
@@ -44,6 +51,9 @@ namespace wincalc
spectral_data_wavelength_range_method,
number_visible_bands,
number_solar_bands);
+ LOGMSG("end Glazing_System::optical_method_results(" + method_name + ", "
+ + std::to_string(theta) + ", " + std::to_string(phi) + ")");
+ return result;
}
WCE_Color_Results Glazing_System::color(double theta,
@@ -52,10 +62,14 @@ namespace wincalc
std::string const & tristimulus_y_method,
std::string const & tristimulus_z_method) const
{
+ LOGMSG("begin Glazing_System::color(" + std::to_string(theta) + ", " + std::to_string(phi) + ")");
window_standards::Optical_Standard_Method tristim_x = get_method(tristimulus_x_method);
+ LOGMSG("before get_method Y");
window_standards::Optical_Standard_Method tristim_y = get_method(tristimulus_y_method);
+ LOGMSG("before get_method Z");
window_standards::Optical_Standard_Method tristim_z = get_method(tristimulus_z_method);
- return calc_color(get_optical_layers(product_data),
+ LOGMSG("before calc_color");
+ auto result = calc_color(get_optical_layers(product_data),
tristim_x,
tristim_y,
tristim_z,
@@ -65,72 +79,107 @@ namespace wincalc
spectral_data_wavelength_range_method,
number_visible_bands,
number_solar_bands);
+ LOGMSG("end Glazing_System::color(" + std::to_string(theta) + ", " + std::to_string(phi)
+ + ")");
+ return result;
+
}
void Glazing_System::reset_igu()
{
+ LOGMSG("begin Glazing_System::reset_igu");
optical_system_for_thermal_calcs = nullptr;
current_igu = std::nullopt;
+ LOGMSG("before reset_system");
reset_system();
+ LOGMSG("end Glazing_System::reset_igu");
}
void Glazing_System::reset_system()
{
+ LOGMSG("begin Glazing_System::reset_system");
current_system = std::nullopt;
+ LOGMSG("end Glazing_System::reset_system");
}
window_standards::Optical_Standard_Method
Glazing_System::get_method(std::string const & method_name) const
{
+ LOGMSG("begin Glazing_System::get_method(" + method_name + ")");
auto method_itr = standard.methods.find(method_name);
+ LOGMSG("before if(method_itr == standard.methods.end())");
if(method_itr == standard.methods.end())
{
+ LOGMSG("in if(method_itr == standard.methods.end())");
std::stringstream err_msg;
err_msg << "Standard " << standard.name << " does not include a " << method_name
<< " method";
throw std::runtime_error(err_msg.str());
}
+ LOGMSG("end Glazing_System::get_method(" + method_name + ")");
return method_itr->second;
}
Tarcog::ISO15099::CIGU & Glazing_System::get_igu(double theta, double phi)
{
+ LOGMSG("begin Glazing_System::get_igu(" + std::to_string(theta) + ", " + std::to_string(phi)
+ + ")");
if(current_igu.has_value() && is_current_igu_calculated(theta, phi))
{
+ LOGMSG("in if(current_igu.has_value() && is_current_igu_calculated(theta, phi))");
return current_igu.value();
}
else
{
+ LOGMSG("in else branch of if(current_igu.has_value() && is_current_igu_calculated(theta, phi))");
current_igu = create_igu(product_data, gap_values, width, height, tilt, standard);
+ LOGMSG("before if(!applied_loads.empty())");
if(!applied_loads.empty())
{
+ LOGMSG("in if(!applied_loads.empty())");
current_igu.value().setAppliedLoad(applied_loads);
}
+ LOGMSG("end of else branch");
return current_igu.value();
}
}
Tarcog::ISO15099::CSystem & Glazing_System::get_system(double theta, double phi)
{
+ LOGMSG("begin Glazing_System::get_system(" + std::to_string(theta) + ", " + std::to_string(phi)
+ + ")");
if(current_system.has_value() && is_current_igu_calculated(theta, phi))
{
+ LOGMSG("in if(current_system.has_value() && is_current_igu_calculated(theta, phi))");
return current_system.value();
}
else
{
+ LOGMSG("in else branch of if(current_system.has_value() && is_current_igu_calculated(theta, phi))");
auto & igu = get_igu(theta, phi);
+ LOGMSG("before create_system");
current_system = create_system(igu, environment);
last_theta = theta;
last_phi = phi;
+ LOGMSG("end else branch of if(current_system.has_value() && "
+ "is_current_igu_calculated(theta, phi))");
+
return current_system.value();
}
}
double Glazing_System::u(double theta, double phi)
{
+ LOGMSG("begin Glazing_System::u(" + std::to_string(theta) + ", " + std::to_string(phi)
+ + ")");
do_updates_for_thermal(theta, phi);
+ LOGMSG("before get_system");
auto & system = get_system(theta, phi);
- return system.getUValue();
+ LOGMSG("before getUValue");
+ auto result = system.getUValue();
+ LOGMSG("end Glazing_System::u(" + std::to_string(theta) + ", " + std::to_string(phi)
+ + ")");
+ return result;
}
double Glazing_System::shgc(double theta, double phi)
@@ -140,69 +189,110 @@ namespace wincalc
// files do not have conductivity and so can be used in optical calcs but not thermal.
// Creating the system is much less expensive than doing the optical calcs so do that first
// to save time if there are any errors.
- do_updates_for_thermal(theta, phi);
+ LOGMSG("begin Glazing_System::shgc(" + std::to_string(theta) + ", " + std::to_string(phi)
+ + ")");
+
+ do_updates_for_thermal(theta, phi);
+ LOGMSG("befoe get_solar_transmittance_front");
auto solar_front_transmittance = get_solar_transmittance_front(theta, phi);
+ LOGMSG("befoe get_system");
auto & system = get_system(theta, phi);
- return system.getSHGC(solar_front_transmittance);
+ LOGMSG("befoe system.getSHGC");
+ auto result = system.getSHGC(solar_front_transmittance);
+ LOGMSG("end Glazing_System::shgc(" + std::to_string(theta) + ", " + std::to_string(phi)
+ + ")");
+ return result;
}
std::vector Glazing_System::layer_temperatures(Tarcog::ISO15099::System system_type,
double theta,
double phi)
{
+ LOGMSG("begin Glazing_System::layer_temperatures(" + std::to_string(theta) + ", " + std::to_string(phi)
+ + ")");
do_updates_for_thermal(theta, phi);
+ LOGMSG("before get_system");
auto & system = get_system(theta, phi);
-
- return system.getTemperatures(system_type);
+ LOGMSG("before system.getTemperatures");
+ auto result = system.getTemperatures(system_type);
+ LOGMSG("end Glazing_System::layer_temperatures(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
+ return result;
}
void Glazing_System::set_deflection_properties(double temperature_at_construction,
double pressure_at_construction)
{
+ LOGMSG("begin Glazing_System::set_deflection_properties("
+ + std::to_string(pressure_at_construction) + ", "
+ + std::to_string(temperature_at_construction) + ")");
deflection_properties =
Temperature_Pressure{temperature_at_construction, pressure_at_construction};
+ LOGMSG("before do_deflection_updates");
do_deflection_updates(last_theta, last_phi);
+ LOGMSG("end Glazing_System::set_deflection_properties("
+ + std::to_string(pressure_at_construction) + ", "
+ + std::to_string(temperature_at_construction) + ")");
}
void
Glazing_System::set_deflection_properties(const std::vector & measured_deflected_gaps)
{
+ LOGMSG("begin Glazing_System::set_deflection_properties");
deflection_properties = measured_deflected_gaps;
do_deflection_updates(last_theta, last_phi);
+ LOGMSG("end Glazing_System::set_deflection_properties");
}
void Glazing_System::set_applied_loads(std::vector const & loads)
{
+ LOGMSG("begin Glazing_System::set_applied_loads");
applied_loads = loads;
if(current_system)
{
+ LOGMSG("in if(current_system)");
current_system.value().setAppliedLoad(applied_loads);
}
+ LOGMSG("end Glazing_System::set_applied_loads");
}
Deflection_Results Glazing_System::calc_deflection_properties(
Tarcog::ISO15099::System system_type, double theta, double phi)
{
+ LOGMSG("begin Glazing_System::calc_deflection_properties(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
do_updates_for_thermal(theta, phi);
+ LOGMSG("before get_system");
auto & system = get_system(theta, phi);
+ LOGMSG("before getMaxLayerDeflections");
const auto layer_deflection_max = system.getMaxLayerDeflections(system_type);
+ LOGMSG("before getMeanLayerDeflections");
const auto layer_deflection_mean = system.getMeanLayerDeflections(system_type);
+ LOGMSG("before getPanesLoad");
const auto panes_load = system.getPanesLoad(system_type);
+ LOGMSG("before getMaxGapWidth");
const auto gap_deflection_max = system.getMaxGapWidth(system_type);
+ LOGMSG("before getMeanGapWidth");
const auto gap_deflection_mean = system.getMeanGapWidth(system_type);
- return {layer_deflection_max,
+ auto result = Deflection_Results{layer_deflection_max,
layer_deflection_mean,
panes_load,
gap_deflection_max,
gap_deflection_mean};
+ LOGMSG("end Glazing_System::calc_deflection_properties(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
+ return result;
}
void Glazing_System::do_deflection_updates(double theta, double phi)
{
+ LOGMSG("begin Glazing_System::do_deflection_updates(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
auto & system = get_system(theta, phi);
if(model_deflection)
{
+ LOGMSG("in if(model_deflection)");
if(auto state_ptr = std::get_if(&deflection_properties))
{
system.setDeflectionProperties(state_ptr->temperature, state_ptr->pressure);
@@ -214,8 +304,11 @@ namespace wincalc
}
else
{
+ LOGMSG("in else calling system.clearDeflection();");
system.clearDeflection();
}
+ LOGMSG("end Glazing_System::do_deflection_updates(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
}
void Glazing_System::do_deflection_updates(std::optional theta,
@@ -229,23 +322,41 @@ namespace wincalc
void Glazing_System::do_layer_absorptance_updates(double theta, double phi)
{
+ LOGMSG("begin Glazing_System::do_layer_absorptance_updates(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
auto & system = get_system(theta, phi);
+ LOGMSG("before get_solar_abs_front");
auto solar_front_absorptances = get_solar_abs_front(theta, phi);
+ LOGMSG("before system.setAbsorptances");
system.setAbsorptances(solar_front_absorptances);
+ LOGMSG("end Glazing_System::do_layer_absorptance_updates(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
}
void Glazing_System::do_updates_for_thermal(double theta, double phi)
{
+ LOGMSG("begin Glazing_System::do_updates_for_thermal(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
do_deflection_updates(theta, phi);
+ LOGMSG("before do_layer_absorptance_updates");
do_layer_absorptance_updates(theta, phi);
+ LOGMSG("end Glazing_System::do_updates_for_thermal(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
}
std::vector Glazing_System::solid_layers_effective_conductivities(
Tarcog::ISO15099::System system_type, double theta, double phi)
{
+ LOGMSG("begin Glazing_System::solid_layers_effective_conductivities(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
do_updates_for_thermal(theta, phi);
+ LOGMSG("before get_system");
auto & system = get_system(theta, phi);
- return system.getSolidEffectiveLayerConductivities(system_type);
+ LOGMSG("before getSolidEffectiveLayerConductivities");
+ auto result = system.getSolidEffectiveLayerConductivities(system_type);
+ LOGMSG("end Glazing_System::solid_layers_effective_conductivities("
+ + std::to_string(theta) + ", " + std::to_string(phi) + ")");
+ return result;
}
std::vector Glazing_System::gap_layers_effective_conductivities(
Tarcog::ISO15099::System system_type, double theta, double phi)
@@ -279,8 +390,10 @@ namespace wincalc
void Glazing_System::optical_standard(window_standards::Optical_Standard const & s)
{
+ LOGMSG("begin Glazing_System::optical_standard");
reset_igu();
standard = s;
+ LOGMSG("end Glazing_System::optical_standard");
}
window_standards::Optical_Standard Glazing_System::optical_standard() const
{
@@ -289,8 +402,10 @@ namespace wincalc
void Glazing_System::solid_layers(std::vector const & layers)
{
+ LOGMSG("begin Glazing_System::solid_layers");
reset_igu();
product_data = layers;
+ LOGMSG("end Glazing_System::solid_layers");
}
std::vector Glazing_System::solid_layers() const
@@ -301,8 +416,10 @@ namespace wincalc
void Glazing_System::gap_layers(
std::vector> const & layers)
{
+ LOGMSG("begin Glazing_System::gap_layers");
reset_igu();
gap_values = layers;
+ LOGMSG("end Glazing_System::gap_layers");
}
std::vector> Glazing_System::gap_layers() const
@@ -312,12 +429,15 @@ namespace wincalc
void Glazing_System::sort_spectral_data()
{
+ LOGMSG("begin Glazing_System::sort_spectral_data");
for(auto & product : product_data)
{
+ LOGMSG("in for(auto & product : product_data)");
auto nband_optical_data = std::dynamic_pointer_cast(
product.optical_data->optical_data());
if(nband_optical_data)
{
+ LOGMSG("in if(nband_optical_data)");
auto & measurements = nband_optical_data->wavelength_data;
std::sort(measurements.begin(),
measurements.end(),
@@ -326,6 +446,7 @@ namespace wincalc
});
}
}
+ LOGMSG("end Glazing_System::sort_spectral_data");
}
Glazing_System::Glazing_System(
@@ -386,25 +507,31 @@ namespace wincalc
std::vector> const &
product_data)
{
+ LOGMSG("begin create_solid_layers");
std::vector solid_layers;
for(auto product : product_data)
{
+ LOGMSG("in for(auto product : product_data)");
Product_Data_Optical_Thermal * solid_layer =
std::get_if(&product);
if(solid_layer)
{
+ LOGMSG("in if(solid_layer)");
// If the variant was already holding a converted object use it
solid_layers.push_back(*solid_layer);
}
else
{
+ LOGMSG("in else");
// Otherwise the variant was holding OpticsParser::ProductData
// Convert that and use it
auto converted_layer =
convert_to_solid_layer(std::get(product));
+ LOGMSG("before solid_layers.push_back");
solid_layers.push_back(converted_layer);
}
}
+ LOGMSG("end create_solid_layers");
return solid_layers;
}
@@ -443,26 +570,34 @@ namespace wincalc
void Glazing_System::environments(Environments const & environments)
{
+ LOGMSG("begin Glazing_System::environments");
environment = environments;
reset_system();
+ LOGMSG("end Glazing_System::environments");
}
void Glazing_System::set_width(double w)
{
+ LOGMSG("begin Glazing_System::set_width(" + std::to_string(w) + ")");
width = w;
if(current_system)
{
+ LOGMSG("in if(current_system)");
current_system.value().setWidth(width);
}
+ LOGMSG("end Glazing_System::set_width(" + std::to_string(w) + ")");
}
void Glazing_System::set_height(double h)
{
+ LOGMSG("begin Glazing_System::set_height(" + std::to_string(h) + ")");
height = h;
if(current_system)
{
+ LOGMSG("in if(current_system)");
current_system.value().setHeight(height);
}
+ LOGMSG("end Glazing_System::set_height(" + std::to_string(h) + ")");
}
void Glazing_System::set_tilt(double t)
@@ -485,15 +620,18 @@ namespace wincalc
void Glazing_System::set_spectral_data_wavelength_range(
Spectal_Data_Wavelength_Range_Method const & type, int visible_bands, int solar_bands)
{
+ LOGMSG("begin Glazing_System::set_spectral_data_wavelength_range");
if(this->spectral_data_wavelength_range_method != type
|| this->number_visible_bands != visible_bands
|| this->number_solar_bands != solar_bands)
{
+ LOGMSG("in if(this->spectral_data_wavelength_range_method etc...");
this->spectral_data_wavelength_range_method = type;
this->number_visible_bands = visible_bands;
this->number_solar_bands = solar_bands;
this->optical_system_for_thermal_calcs = nullptr;
}
+ LOGMSG("end Glazing_System::set_spectral_data_wavelength_range");
}
void Glazing_System::enable_deflection(bool enable)
@@ -520,19 +658,23 @@ namespace wincalc
double Glazing_System::overallThickness() const
{
+ LOGMSG("begin Glazing_System::overallThickness");
if(current_igu.has_value())
{
+ LOGMSG("in if(current_igu.has_value()) returning " + std::to_string(current_igu.value().getThickness()));
return current_igu.value().getThickness();
}
-
+ LOGMSG("not in if(current_igu.has_value()) returning 0.0");
return 0.0;
}
SingleLayerOptics::IScatteringLayer & Glazing_System::get_optical_system_for_thermal_calcs()
{
+ LOGMSG("begin Glazing_System::get_optical_system_for_thermal_calcs");
if(optical_system_for_thermal_calcs == nullptr)
{
+ LOGMSG("in if(optical_system_for_thermal_calcs == nullptr)");
optical_system_for_thermal_calcs =
optical_solar_results_system_needed_for_thermal_calcs(
product_data,
@@ -543,48 +685,100 @@ namespace wincalc
number_solar_bands);
}
+ LOGMSG("end Glazing_System::get_optical_system_for_thermal_calcs");
return *optical_system_for_thermal_calcs;
}
double Glazing_System::get_solar_transmittance_front(double theta, double phi)
{
+ LOGMSG("begin Glazing_System::get_solar_transmittance_front("
+ + std::to_string(theta) + ", " + std::to_string(phi) + ")");
auto & optical_system = get_optical_system_for_thermal_calcs();
-
+ LOGMSG("before get_optical_layers");
auto optical_layers = get_optical_layers(product_data);
+ LOGMSG("before standard.methods.at(SOLAR)");
auto solar_method = standard.methods.at("SOLAR");
+ LOGMSG("before get_wavelengths");
std::vector> wavelengths = get_wavelengths(optical_layers);
+ LOGMSG("before get_lambda_range");
auto lambda_range = get_lambda_range(wavelengths, solar_method);
-
- return optical_system.getPropertySimple(lambda_range.min_lambda,
+ LOGMSG("before optical_system.getPropertySimple");
+ auto result = optical_system.getPropertySimple(lambda_range.min_lambda,
lambda_range.max_lambda,
FenestrationCommon::PropertySimple::T,
FenestrationCommon::Side::Front,
FenestrationCommon::Scattering::DirectHemispherical,
theta,
phi);
+ LOGMSG("end Glazing_System::get_solar_transmittance_front(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
+ return result;
}
bool Glazing_System::is_current_igu_calculated(double theta, double phi)
{
- return last_theta.has_value() && FenestrationCommon::isEqual(theta, last_theta.value())
+ LOGMSG("begin Glazing_System::is_current_igu_calculated(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
+ bool result = last_theta.has_value() && FenestrationCommon::isEqual(theta, last_theta.value())
&& last_phi.has_value() && FenestrationCommon::isEqual(phi, last_phi.value());
+ LOGMSG("begin Glazing_System::is_current_igu_calculated(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")" + " returning " + std::to_string(result));
+ return result;
}
std::vector Glazing_System::get_solar_abs_front(double theta, double phi)
{
+ LOGMSG("begin Glazing_System::get_solar_abs_front(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
auto & optical_system = get_optical_system_for_thermal_calcs();
-
+ LOGMSG("before get_optical_layers");
auto optical_layers = get_optical_layers(product_data);
+ LOGMSG("before standard.methods.at(SOLAR)");
auto solar_method = standard.methods.at("SOLAR");
+ LOGMSG("before get_wavelengths");
std::vector> wavelengths = get_wavelengths(optical_layers);
+ LOGMSG("before get_lambda_range");
auto lambda_range = get_lambda_range(wavelengths, solar_method);
-
- return optical_system.getAbsorptanceLayersHeat(lambda_range.min_lambda,
+ LOGMSG("before optical_system.getAbsorptanceLayersHeat");
+ auto result = optical_system.getAbsorptanceLayersHeat(lambda_range.min_lambda,
lambda_range.max_lambda,
FenestrationCommon::Side::Front,
FenestrationCommon::ScatteringSimple::Direct,
theta,
phi);
+
+ LOGMSG("end Glazing_System::get_solar_abs_front(" + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
+ return result;
+ }
+
+ double Glazing_System::heat_flow(Tarcog::ISO15099::System system_type,
+ Tarcog::ISO15099::Environment env,
+ double theta,
+ double phi)
+ {
+ do_updates_for_thermal(theta, phi);
+ auto & system = get_system(theta, phi);
+ return system.getHeatFlow(system_type, env);
+ }
+
+ double Glazing_System::h(Tarcog::ISO15099::System system_type,
+ Tarcog::ISO15099::Environment env,
+ double theta,
+ double phi)
+ {
+ do_updates_for_thermal(theta, phi);
+ auto & system = get_system(theta, phi);
+ return system.getH(system_type, env);
+ }
+
+ std::vector Glazing_System::radiosities(Tarcog::ISO15099::System system_type,
+ double theta,
+ double phi)
+ {
+ do_updates_for_thermal(theta, phi);
+ auto & system = get_system(theta, phi);
+ return system.getRadiosities(system_type);
}
} // namespace wincalc
diff --git a/src/glazing_system.h b/src/glazing_system.h
index a5135856..232429c8 100644
--- a/src/glazing_system.h
+++ b/src/glazing_system.h
@@ -112,6 +112,21 @@ namespace wincalc
double relative_heat_gain(double theta = 0, double phi = 0);
+ double heat_flow(Tarcog::ISO15099::System system_type,
+ Tarcog::ISO15099::Environment env,
+ double theta = 0,
+ double phi = 0);
+
+ double h(Tarcog::ISO15099::System system_type,
+ Tarcog::ISO15099::Environment env,
+ double theta = 0,
+ double phi = 0);
+
+ std::vector radiosities(Tarcog::ISO15099::System system_type,
+ double theta = 0,
+ double phi = 0);
+
+
void optical_standard(window_standards::Optical_Standard const & s);
window_standards::Optical_Standard optical_standard() const;
diff --git a/src/optical_calcs.cpp b/src/optical_calcs.cpp
index b3ab0955..a99d7874 100644
--- a/src/optical_calcs.cpp
+++ b/src/optical_calcs.cpp
@@ -20,11 +20,18 @@ namespace wincalc
WCE_Optical_Result_Simple
do_calc(std::function const & f)
{
+ LOGMSG("begin do_calc(std::function "
+ "const & f)");
WCE_Optical_Result_Simple calc_result;
calc_result.direct_direct = f(FenestrationCommon::Scattering::DirectDirect);
+ LOGMSG("before DirectDiffuse");
calc_result.direct_diffuse = f(FenestrationCommon::Scattering::DirectDiffuse);
+ LOGMSG("before DiffuseDiffuse");
calc_result.diffuse_diffuse = f(FenestrationCommon::Scattering::DiffuseDiffuse);
+ LOGMSG("before DirectHemispherical");
calc_result.direct_hemispherical = f(FenestrationCommon::Scattering::DirectHemispherical);
+ LOGMSG("end do_calc(std::function "
+ "const & f)");
return calc_result;
}
@@ -35,6 +42,7 @@ namespace wincalc
const FenestrationCommon::Side side,
const FenestrationCommon::Scattering scattering)> const & f)
{
+ LOGMSG("begin do_calcs(prop, side, scattering)");
WCE_Optical_Results_Template calc_result;
calc_result.system_results.front.transmittance =
@@ -43,24 +51,28 @@ namespace wincalc
FenestrationCommon::PropertySimple::T, FenestrationCommon::Side::Front, scattering);
});
+ LOGMSG("before back transmittance");
calc_result.system_results.back.transmittance =
do_calc([&f](const FenestrationCommon::Scattering scattering) {
return f(
FenestrationCommon::PropertySimple::T, FenestrationCommon::Side::Back, scattering);
});
+ LOGMSG("before front reflectance");
calc_result.system_results.front.reflectance =
do_calc([&f](const FenestrationCommon::Scattering scattering) {
return f(
FenestrationCommon::PropertySimple::R, FenestrationCommon::Side::Front, scattering);
});
+ LOGMSG("before back reflectance");
calc_result.system_results.back.reflectance =
do_calc([&f](const FenestrationCommon::Scattering scattering) {
return f(
FenestrationCommon::PropertySimple::R, FenestrationCommon::Side::Back, scattering);
});
+ LOGMSG("end do_calcs(prop, side, scattering)");
return calc_result;
}
@@ -73,8 +85,11 @@ namespace wincalc
double theta,
double phi)
{
- return layers->getPropertySimple(
+ LOGMSG("begin calc_optical_property");
+ double result = layers->getPropertySimple(
min_lambda, max_lambda, property_choice, side_choice, scattering_choice, theta, phi);
+ LOGMSG("end calc_optical_property");
+ return result;
}
std::vector>
@@ -85,6 +100,7 @@ namespace wincalc
double theta = 0,
double phi = 0)
{
+ LOGMSG("begin get_layer_absorptances");
std::vector> absorptances;
auto direct_absorptances_total =
layers->getAbsorptanceLayers(min_lambda,
@@ -93,6 +109,7 @@ namespace wincalc
FenestrationCommon::ScatteringSimple::Direct,
theta,
phi);
+ LOGMSG("before diffuse_absorptances_total");
auto diffuse_absorptances_total =
layers->getAbsorptanceLayers(min_lambda,
max_lambda,
@@ -101,6 +118,7 @@ namespace wincalc
theta,
phi);
+ LOGMSG("before direct_absorptances_heat");
auto direct_absorptances_heat =
layers->getAbsorptanceLayersHeat(min_lambda,
max_lambda,
@@ -108,6 +126,7 @@ namespace wincalc
FenestrationCommon::ScatteringSimple::Direct,
theta,
phi);
+ LOGMSG("before diffuse_absorptances_heat");
auto diffuse_absorptances_heat =
layers->getAbsorptanceLayersHeat(min_lambda,
max_lambda,
@@ -115,7 +134,7 @@ namespace wincalc
FenestrationCommon::ScatteringSimple::Diffuse,
theta,
phi);
-
+ LOGMSG("before direct_absorptances_electricity");
auto direct_absorptances_electricity =
layers->getAbsorptanceLayersElectricity(min_lambda,
max_lambda,
@@ -123,7 +142,7 @@ namespace wincalc
FenestrationCommon::ScatteringSimple::Direct,
theta,
phi);
-
+ LOGMSG("before diffuse_absorptances_electricity");
auto diffuse_absorptances_electricity =
layers->getAbsorptanceLayersElectricity(min_lambda,
max_lambda,
@@ -132,22 +151,28 @@ namespace wincalc
theta,
phi);
+ LOGMSG("before bsdf_system");
auto bsdf_system = std::dynamic_pointer_cast(layers);
for(size_t i = 0; i < diffuse_absorptances_heat.size(); ++i)
{
+ LOGMSG("in loop iteration: " + std::to_string(i));
std::optional> angular_total;
std::optional> angular_heat;
std::optional> angular_electricity;
if(bsdf_system)
{
+ LOGMSG("in if(bsdf_system)");
angular_total = bsdf_system->Abs(min_lambda, max_lambda, side_choice, i + 1);
+ LOGMSG("before angular_heat");
angular_heat = bsdf_system->AbsHeat(min_lambda, max_lambda, side_choice, i + 1);
+ LOGMSG("before angular_electricity");
angular_electricity =
bsdf_system->AbsElectricity(min_lambda, max_lambda, side_choice, i + 1);
}
+ LOGMSG("before absorptances.push_back");
absorptances.push_back(WCE_Optical_Result_Absorptance{
direct_absorptances_total[i],
diffuse_absorptances_total[i],
@@ -161,6 +186,7 @@ namespace wincalc
});
}
+ LOGMSG("end get_layer_absorptances");
return absorptances;
}
@@ -170,20 +196,28 @@ namespace wincalc
double theta,
double phi)
{
+ LOGMSG("begin calc_all(system, " + std::to_string(min_lambda) + ", "
+ + std::to_string(max_lambda) + ", " + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
if(max_lambda < min_lambda)
{
+ LOGMSG("in if(max_lambda < min_lambda)");
max_lambda = min_lambda + 1;
}
+ LOGMSG("before calc_f = ");
auto calc_f = [=, &system](const FenestrationCommon::PropertySimple prop,
const FenestrationCommon::Side side,
const FenestrationCommon::Scattering scattering) {
return calc_optical_property(
system, prop, side, scattering, min_lambda, max_lambda, theta, phi);
};
+ LOGMSG("before optical_results");
auto optical_results = do_calcs(calc_f);
+ LOGMSG("before bsdf_system");
auto bsdf_system = std::dynamic_pointer_cast(system);
if(bsdf_system)
{
+ LOGMSG("in if(bsdf_system)");
// Include matrix results for BSDF systems
optical_results.system_results.front.transmittance.matrix =
bsdf_system
@@ -193,6 +227,7 @@ namespace wincalc
FenestrationCommon::PropertySimple::T)
.getMatrix();
+ LOGMSG("before front.reflectance.matrix");
optical_results.system_results.front.reflectance.matrix =
bsdf_system
->getMatrix(min_lambda,
@@ -201,6 +236,7 @@ namespace wincalc
FenestrationCommon::PropertySimple::R)
.getMatrix();
+ LOGMSG("before back.transmittance.matrix");
optical_results.system_results.back.transmittance.matrix =
bsdf_system
->getMatrix(min_lambda,
@@ -209,6 +245,7 @@ namespace wincalc
FenestrationCommon::PropertySimple::T)
.getMatrix();
+ LOGMSG("before back.reflectance.matrix");
optical_results.system_results.back.reflectance.matrix =
bsdf_system
->getMatrix(min_lambda,
@@ -218,19 +255,25 @@ namespace wincalc
.getMatrix();
}
+ LOGMSG("before absorptances_front");
auto absorptances_front = get_layer_absorptances(
system, FenestrationCommon::Side::Front, min_lambda, max_lambda, theta, phi);
+ LOGMSG("before absorptances_back");
auto absorptances_back = get_layer_absorptances(
system, FenestrationCommon::Side::Back, min_lambda, max_lambda, theta, phi);
for(size_t i = 0; i < absorptances_front.size(); ++i)
{
+ LOGMSG("in absorptances loop iteration: " + std::to_string(i));
optical_results.layer_results.push_back(
WCE_Optical_Result_By_Side>{
WCE_Optical_Result_Absorptance{absorptances_front[i]},
WCE_Optical_Result_Absorptance{absorptances_back[i]}});
}
+ LOGMSG("end calc_all(system, " + std::to_string(min_lambda) + ", "
+ + std::to_string(max_lambda) + ", " + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
return optical_results;
}
@@ -244,12 +287,20 @@ namespace wincalc
int number_visible_bands,
int number_solar_bands)
{
+ LOGMSG("begin calc_all(product_data, " + method.name + ", " + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
auto layers = create_multi_pane(
product_data, method, bsdf_hemisphere, type, number_visible_bands, number_solar_bands);
+ LOGMSG("before get_wavelengths");
std::vector> wavelengths = get_wavelengths(product_data);
+ LOGMSG("before get_lambda_range");
auto lambda_range = get_lambda_range(wavelengths, method);
- return calc_all(
+ LOGMSG("before result = calc_all");
+ auto result = calc_all(
std::move(layers), lambda_range.min_lambda, lambda_range.max_lambda, theta, phi);
+ LOGMSG("end calc_all(product_data, " + method.name + ", " + std::to_string(theta) + ", "
+ + std::to_string(phi) + ")");
+ return result;
}
Color_Result
@@ -260,10 +311,16 @@ namespace wincalc
double theta = 0,
double phi = 0)
{
+ LOGMSG("begin calc_color_properties");
auto trichromatic = color_props->getTrichromatic(prop, side, scattering, theta, phi);
+ LOGMSG("before getRGB");
auto rgb = color_props->getRGB(prop, side, scattering, theta, phi);
+ LOGMSG("before getCIE_Lab");
auto lab = color_props->getCIE_Lab(prop, side, scattering, theta, phi);
- return Color_Result(trichromatic, rgb, lab);
+ LOGMSG("before result = Color_Result");
+ auto result = Color_Result(trichromatic, rgb, lab);
+ LOGMSG("end calc_color_properties");
+ return result;
}
WCE_Color_Results calc_color_properties(
@@ -292,6 +349,7 @@ namespace wincalc
int number_visible_bands,
int number_solar_bands)
{
+ LOGMSG("begin calc_color");
auto layer_x = create_multi_pane(
product_data, method_x, bsdf_hemisphere, type, number_visible_bands, number_solar_bands);
// auto layer_y = create_multi_pane(
@@ -300,7 +358,7 @@ namespace wincalc
// auto layer_z = create_multi_pane(
// product_data, method_z, bsdf_hemisphere, type, number_visible_bands,
// number_solar_bands);
-
+ LOGMSG("before layer_x->getWavelengths()");
auto x_wavelengths = layer_x->getWavelengths();
// auto y_wavelengths = layer_y->getWavelengths();
// auto z_wavelengths = layer_z->getWavelengths();
@@ -319,49 +377,65 @@ namespace wincalc
/// throw std::runtime_error(err_msg.str());
///}
+ LOGMSG("before get_wavelengths");
std::vector> wavelengths = get_wavelengths(product_data);
+ LOGMSG("before get_spectum_values X");
auto detector_x = get_spectum_values(method_x.detector_spectrum, method_x, wavelengths);
+ LOGMSG("before get_spectum_values Y");
auto detector_y = get_spectum_values(method_y.detector_spectrum, method_y, wavelengths);
+ LOGMSG("before get_spectum_values Z");
auto detector_z = get_spectum_values(method_z.detector_spectrum, method_z, wavelengths);
FenestrationCommon::CCommonWavelengths wavelength_combiner;
for(auto & wavelength_set : wavelengths)
{
+ LOGMSG("in for(auto & wavelength_set : wavelengths)");
wavelength_combiner.addWavelength(wavelength_set);
}
+
+ LOGMSG("before common_wavelengths");
auto common_wavelengths =
wavelength_combiner.getCombinedWavelengths(FenestrationCommon::Combine::Interpolate);
// All methods must have the same source
// spectrum? (Should it be checked above?)
+ LOGMSG("before source_spectrum");
auto source_spectrum =
get_spectum_values(method_x.source_spectrum, method_x, common_wavelengths);
// and the same wavelength set?
+ LOGMSG("before wavelength_set");
std::vector wavelength_set = combined_layer_wavelength_range_factory(
{common_wavelengths}, type, number_visible_bands, number_solar_bands);
+ LOGMSG("before color_props");
auto color_props = std::make_shared(
std::move(layer_x), source_spectrum, detector_x, detector_y, detector_z, wavelength_set);
-
- return calc_color_properties(color_props, theta, phi);
+ LOGMSG("before calc_color_properties");
+ auto result = calc_color_properties(color_props, theta, phi);
+ LOGMSG("end calc_color");
+ return result;
}
Layer_Optical_IR_Results_Needed_For_Thermal_Calcs optical_ir_results_needed_for_thermal_calcs(
Product_Data_Optical_Thermal const & product_data,
window_standards::Optical_Standard const & standard)
{
+ LOGMSG("begin optical_ir_results_needed_for_thermal_calcs layer");
auto ir_results = calc_thermal_ir(standard, product_data);
double tf = ir_results.transmittance_front_diffuse_diffuse;
double tb = ir_results.transmittance_back_diffuse_diffuse;
double absorptance_front = ir_results.emissivity_front_hemispheric;
double absorptance_back = ir_results.emissivity_back_hemispheric;
- return Layer_Optical_IR_Results_Needed_For_Thermal_Calcs{
+
+ auto result = Layer_Optical_IR_Results_Needed_For_Thermal_Calcs{
tf, tb, absorptance_front, absorptance_back};
+ LOGMSG("end optical_ir_results_needed_for_thermal_calcs layer");
+ return result;
}
std::vector
@@ -369,15 +443,17 @@ namespace wincalc
std::vector const & product_data,
window_standards::Optical_Standard const & standard)
{
+ LOGMSG("begin optical_ir_results_needed_for_thermal_calcs");
std::vector result;
for(auto product : product_data)
{
+ LOGMSG("in for(auto product : product_data)");
result.push_back(optical_ir_results_needed_for_thermal_calcs(product, standard));
}
+ LOGMSG("end optical_ir_results_needed_for_thermal_calcs layer");
return result;
}
-#include
#if 0
Optical_Solar_Results_Needed_For_Thermal_Calcs optical_solar_results_needed_for_thermal_calcs(
std::vector const & product_data,
@@ -433,17 +509,21 @@ namespace wincalc
int number_visible_bands,
int number_solar_bands)
{
+ LOGMSG("begin optical_solar_results_system_needed_for_thermal_calcs");
auto optical_layers = get_optical_layers(product_data);
+ LOGMSG("before solar_method");
auto solar_method = standard.methods.at("SOLAR");
-
+ LOGMSG("before get_wavelengths");
std::vector> wavelengths = get_wavelengths(optical_layers);
-
- return create_multi_pane(optical_layers,
+ LOGMSG("before create_multi_pane");
+ auto result = create_multi_pane(optical_layers,
solar_method,
bsdf_hemisphere,
type,
number_visible_bands,
number_solar_bands);
+ LOGMSG("end optical_solar_results_system_needed_for_thermal_calcs");
+ return result;
}
double calc_optical_property(
@@ -459,12 +539,15 @@ namespace wincalc
int number_visible_bands,
int number_solar_bands)
{
+ LOGMSG("begin calc_optical_property");
auto layers = create_multi_pane(
product_data, method, bsdf_hemisphere, type, number_visible_bands, number_solar_bands);
+ LOGMSG("before get_wavelengths");
std::vector> wavelengths = get_wavelengths(product_data);
+ LOGMSG("before get_lambda_range");
auto lambda_range = get_lambda_range(wavelengths, method);
-
- return calc_optical_property(std::move(layers),
+ LOGMSG("before calc_optical_property");
+ auto result = calc_optical_property(std::move(layers),
property_choice,
side_choice,
scattering_choice,
@@ -472,5 +555,7 @@ namespace wincalc
lambda_range.max_lambda,
theta,
phi);
+ LOGMSG("end calc_optical_property");
+ return result;
}
} // namespace wincalc
diff --git a/src/product_data.cpp b/src/product_data.cpp
index 938cb5df..21c62f64 100644
--- a/src/product_data.cpp
+++ b/src/product_data.cpp
@@ -33,17 +33,16 @@ namespace wincalc
double gap_width_bottom,
double gap_width_left,
double gap_width_right,
- double effective_thermal_front_openness_area,
+ double,
double permeability_factor) const
{
- EffectiveLayers::ShadeOpenness openness{effective_thermal_front_openness_area,
- gap_width_left,
+ EffectiveLayers::ShadeOpenness openness{gap_width_left,
gap_width_right,
gap_width_top,
gap_width_bottom};
- return std::make_unique(
- width, height, thickness_meters, openness, permeability_factor);
+ return std::make_unique(
+ width, height, thickness_meters, permeability_factor, openness);
}
@@ -126,6 +125,11 @@ namespace wincalc
Product_Data_Optical_With_Material(material_data)
{}
+ Product_Data_Optical_Uniform_Diffuse::Product_Data_Optical_Uniform_Diffuse(
+ const std::shared_ptr & material_data) :
+ Product_Data_Optical_With_Material(material_data)
+ {}
+
Product_Data_Optical_Venetian::Product_Data_Optical_Venetian(
std::shared_ptr const & optical_data,
Venetian_Geometry const & geometry) :
@@ -143,15 +147,14 @@ namespace wincalc
double,
double ) const // Front openness is automatically calculated by the model
{
- double front_openness_venetian =
- ThermalPermeability::Venetian::frontOpenness(geometry.slat_tilt,
- geometry.slat_spacing,
- material_optical_data->thickness_meters,
- geometry.slat_curvature,
- geometry.slat_width);
-
- EffectiveLayers::ShadeOpenness openness{front_openness_venetian,
- gap_width_left,
+ //TODO: make sure units match
+ FenestrationCommon::Venetian::Geometry wce_geometry{
+ geometry.slat_width, geometry.slat_spacing, geometry.slat_tilt, geometry.slat_curvature};
+
+ //double front_openness_venetian =
+ // ThermalPermeability::Venetian::permeabilityFactor(material_optical_data->thickness_meters, wce_geometry);
+
+ EffectiveLayers::ShadeOpenness openness{gap_width_left,
gap_width_right,
gap_width_top,
gap_width_bottom};
@@ -160,9 +163,8 @@ namespace wincalc
width,
height,
material_optical_data->thickness_meters,
- openness,
- geometry.slat_tilt,
- geometry.slat_width);
+ wce_geometry,
+ openness);
}
Product_Data_Optical_Woven_Shade::Product_Data_Optical_Woven_Shade(
@@ -182,13 +184,13 @@ namespace wincalc
double,
double ) const // calculated automatically by the code
{
- double front_openness = ThermalPermeability::Woven::frontOpenness(geometry.thread_diameter,
- geometry.thread_spacing);
- EffectiveLayers::ShadeOpenness openness{
- front_openness, gap_width_left, gap_width_right, gap_width_top, gap_width_bottom};
+
+ FenestrationCommon::Woven::Geometry wce_geometry{geometry.thread_diameter,
+ geometry.thread_spacing};
+ EffectiveLayers::ShadeOpenness openness{gap_width_left, gap_width_right, gap_width_top, gap_width_bottom};
return std::make_unique(
- width, height, geometry.shade_thickness, openness);
+ width, height, geometry.shade_thickness, wce_geometry, openness);
}
Product_Data_Optical_Thermal::Product_Data_Optical_Thermal(
@@ -214,52 +216,26 @@ namespace wincalc
double,
double) const // Calculated automatically by the code
{
- std::map> front_openness_calcs;
- front_openness_calcs[Perforated_Geometry::Type::CIRCULAR] = [=]() {
- return ThermalPermeability::Perforated::frontOpenness(
- ThermalPermeability::Perforated::Type::Circular,
- geometry.spacing_x,
- geometry.spacing_y,
- geometry.dimension_x * 2,
- geometry.dimension_x * 2);
- };
-
- front_openness_calcs[Perforated_Geometry::Type::RECTANGULAR] = [=]() {
- return ThermalPermeability::Perforated::frontOpenness(
- ThermalPermeability::Perforated::Type::Rectangular,
- geometry.spacing_x,
- geometry.spacing_y,
- geometry.dimension_x,
- geometry.dimension_y);
- };
-
- front_openness_calcs[Perforated_Geometry::Type::SQUARE] = [=]() {
- return ThermalPermeability::Perforated::frontOpenness(
- ThermalPermeability::Perforated::Type::Square,
- geometry.spacing_x,
- geometry.spacing_y,
- geometry.dimension_x,
- geometry.dimension_x);
- };
-
- auto front_openness_calc = front_openness_calcs.find(geometry.perforation_type);
-
- if(front_openness_calc == front_openness_calcs.end())
- {
- std::stringstream msg;
- msg << "Unsupported perforation type: "
- << static_cast::type>(
- geometry.perforation_type);
- throw std::runtime_error(msg.str());
- }
-
- double front_openness = front_openness_calc->second();
-
- EffectiveLayers::ShadeOpenness openness{
- front_openness, gap_width_left, gap_width_right, gap_width_top, gap_width_bottom};
+ std::map wce_map{
+ {wincalc::Perforated_Geometry::Type::CIRCULAR,
+ FenestrationCommon::Perforated::Type::Circular},
+ {wincalc::Perforated_Geometry::Type::SQUARE,
+ FenestrationCommon::Perforated::Type::Square},
+ {wincalc::Perforated_Geometry::Type::RECTANGULAR,
+ FenestrationCommon::Perforated::Type::Rectangular}};
+
+ FenestrationCommon::Perforated::Geometry wce_geometry{
+ wce_map[geometry.perforation_type],
+ geometry.spacing_x,
+ geometry.spacing_y,
+ geometry.dimension_x,
+ geometry.dimension_y};
+
+
+ EffectiveLayers::ShadeOpenness openness{gap_width_left, gap_width_right, gap_width_top, gap_width_bottom};
return std::make_unique(
- width, height, material_optical_data->thickness_meters, openness);
+ width, height, material_optical_data->thickness_meters, wce_geometry, openness);
}
Product_Data_Dual_Band_Optical_BSDF::Product_Data_Dual_Band_Optical_BSDF(
@@ -304,20 +280,25 @@ namespace wincalc
double gap_width_bottom,
double gap_width_left,
double gap_width_right,
- double front_openness,
+ double effective_thermal_front_openness_area,
double permeability_factor) const
{
- EffectiveLayers::ShadeOpenness openness{
- front_openness, gap_width_left, gap_width_right, gap_width_top, gap_width_bottom};
- if(user_defined_effective_values)
+ EffectiveLayers::ShadeOpenness openness{gap_width_left, gap_width_right, gap_width_top, gap_width_bottom};
+
+ if(!user_defined_effective_values)
{
- return std::make_unique(
- width, height, thickness_meters, openness, permeability_factor);
+ return std::make_unique(
+ width, height, thickness_meters, permeability_factor, openness);
}
else
{
- return std::make_unique(
- width, height, thickness_meters, openness, permeability_factor);
+ return std::make_unique(
+ width,
+ height,
+ thickness_meters,
+ permeability_factor,
+ effective_thermal_front_openness_area,
+ openness);
}
}
diff --git a/src/product_data.h b/src/product_data.h
index 4c7a4c49..37ea9a77 100644
--- a/src/product_data.h
+++ b/src/product_data.h
@@ -166,7 +166,7 @@ namespace wincalc
double gap_width_bottom,
double gap_width_left,
double gap_width_right,
- double front_openness,
+ double effective_thermal_front_openness_area,
double permeability_factor) const override;
};
@@ -218,6 +218,12 @@ namespace wincalc
std::shared_ptr material_optical_data;
};
+ struct Product_Data_Optical_Uniform_Diffuse : Product_Data_Optical_With_Material
+ {
+ Product_Data_Optical_Uniform_Diffuse(
+ std::shared_ptr const & material_optical_data);
+ };
+
struct Product_Data_Optical_Perfectly_Diffuse : Product_Data_Optical_With_Material
{
Product_Data_Optical_Perfectly_Diffuse(
@@ -258,7 +264,7 @@ namespace wincalc
double gap_width_bottom,
double gap_width_left,
double gap_width_right,
- double front_openness,
+ double effective_thermal_front_openness_area,
double permeability_factor) const override;
Venetian_Geometry geometry;
@@ -286,7 +292,7 @@ namespace wincalc
double gap_width_bottom,
double gap_width_left,
double gap_width_right,
- double front_openness,
+ double effective_thermal_front_openness_area,
double permeability_factor) const override;
Woven_Geometry geometry;
@@ -327,7 +333,7 @@ namespace wincalc
double gap_width_bottom,
double gap_width_left,
double gap_width_right,
- double front_openness,
+ double effective_thermal_front_openness_area,
double permeability_factor) const override;
Perforated_Geometry geometry;
diff --git a/src/shade_factories.cpp b/src/shade_factories.cpp
index d524b315..2ba02085 100644
--- a/src/shade_factories.cpp
+++ b/src/shade_factories.cpp
@@ -62,4 +62,56 @@ namespace wincalc
std::make_shared(material_optical_data, geometry);
return Product_Data_Optical_Thermal(optical_data, material_thermal_data);
}
+
+ Product_Data_Optical_Thermal create_homogeneous_diffusing_shade(
+ std::shared_ptr material_optical_data,
+ std::shared_ptr material_thermal_data,
+ double permeability_factor)
+ {
+ auto optical_data =
+ std::make_shared(material_optical_data);
+ auto data = Product_Data_Optical_Thermal(optical_data, material_thermal_data);
+ data.thermal_data->permeability_factor =
+ permeability_factor;
+ return data;
+ }
+
+ Product_Data_Optical_Thermal
+ create_homogeneous_diffusing_shade(OpticsParser::ProductData const & material,
+ double permeability_factor)
+ {
+ auto converted_material = convert_to_solid_layer(material);
+ auto optical_data = std::make_shared(
+ converted_material.optical_data);
+ converted_material.thermal_data->permeability_factor =
+ permeability_factor;
+ return Product_Data_Optical_Thermal(optical_data, converted_material.thermal_data);
+ }
+
+ Product_Data_Optical_Thermal
+ create_perfectly_diffusing_shade(
+ std::shared_ptr material_optical_data,
+ std::shared_ptr material_thermal_data,
+ double permeability_factor)
+ {
+ auto optical_data =
+ std::make_shared(material_optical_data);
+ auto data = Product_Data_Optical_Thermal(optical_data, material_thermal_data);
+ data.thermal_data->permeability_factor =
+ permeability_factor;
+ return data;
+ }
+
+
+ Product_Data_Optical_Thermal
+ create_perfectly_diffusing_shade(OpticsParser::ProductData const & material,
+ double permeability_factor)
+ {
+ auto converted_material = convert_to_solid_layer(material);
+ auto optical_data =
+ std::make_shared(converted_material.optical_data);
+ converted_material.thermal_data->permeability_factor =
+ permeability_factor;
+ return Product_Data_Optical_Thermal(optical_data, converted_material.thermal_data);
+ }
} // namespace wincalc
diff --git a/src/shade_factories.h b/src/shade_factories.h
index 4d1efd52..90b2f85a 100644
--- a/src/shade_factories.h
+++ b/src/shade_factories.h
@@ -27,4 +27,22 @@ namespace wincalc
std::shared_ptr material_optical_data,
std::shared_ptr material_thermal_data);
+ Product_Data_Optical_Thermal
+ create_homogeneous_diffusing_shade(std::shared_ptr material_optical_data,
+ std::shared_ptr material_thermal_data,
+ double permeability_factor = 0);
+
+ Product_Data_Optical_Thermal
+ create_homogeneous_diffusing_shade(OpticsParser::ProductData const & material,
+ double permeability_factor = 0);
+
+ Product_Data_Optical_Thermal create_perfectly_diffusing_shade(
+ std::shared_ptr material_optical_data,
+ std::shared_ptr material_thermal_data,
+ double permeability_factor = 0);
+
+ Product_Data_Optical_Thermal
+ create_perfectly_diffusing_shade(OpticsParser::ProductData const & material,
+ double permeability_factor = 0);
+
} // namespace wincalc
diff --git a/src/util.cpp b/src/util.cpp
index 6588a855..724a398b 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -1,5 +1,6 @@
#include "util.h"
#include
+#include
#include "convert_optics_parser.h"
namespace wincalc
@@ -101,4 +102,9 @@ namespace wincalc
return res;
}
-} // namespace wincalc
+
+ void logMsg(std::string const & msg)
+ {
+ std::cerr << msg << std::endl;
+ }
+} // namespace wincalc
\ No newline at end of file
diff --git a/src/util.h b/src/util.h
index c736a062..1456f11e 100644
--- a/src/util.h
+++ b/src/util.h
@@ -41,4 +41,20 @@ namespace wincalc
std::vector> get_wavelengths(
std::vector> const & product_data);
+
+ void logMsg(std::string const & msg);
} // namespace wincalc
+
+#ifdef LOGMESSAGES
+# define LOGMSG(msg) \
+ do \
+ { \
+ wincalc::logMsg(msg); \
+ } while(0)
+#else
+ // Expand to nothing in no-logging mode
+# define LOGMSG(msg) \
+ do \
+ { \
+ } while(0)
+#endif
diff --git a/test/1_layer_applied_film_nfrc_9223.unit.cpp b/test/1_layer_applied_film_nfrc_9223.unit.cpp
new file mode 100644
index 00000000..c9cf524f
--- /dev/null
+++ b/test/1_layer_applied_film_nfrc_9223.unit.cpp
@@ -0,0 +1,58 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wincalc/wincalc.h"
+#include "optical_calcs.h"
+#include "util.h"
+#include "convert_optics_parser.h"
+#include "paths.h"
+
+
+using namespace wincalc;
+using namespace window_standards;
+
+class Test_1_layer_applied_film_nfrc_9223 : public testing::Test
+{
+protected:
+ std::shared_ptr glazing_system_u;
+ std::shared_ptr glazing_system_shgc;
+
+ virtual void SetUp()
+ {
+ std::filesystem::path product_path(test_dir);
+ product_path /= "products";
+ product_path /= "nfrc_9223.json";
+
+ std::vector products;
+ auto product = OpticsParser::parseJSONFile(product_path.string());
+ products.push_back(product);
+
+ std::vector> gaps;
+
+ std::filesystem::path standard_path(test_dir);
+ standard_path /= "standards";
+ standard_path /= "W5_NFRC_2003.std";
+ Optical_Standard standard = load_optical_standard(standard_path.string());
+ glazing_system_u = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_u_environments());
+ glazing_system_shgc = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_shgc_environments());
+ }
+};
+
+TEST_F(Test_1_layer_applied_film_nfrc_9223, Test_Thermal)
+{
+ test_thermal_results("1_layer/applied_film_nfrc_9223/default", "thermal_U_Environment", glazing_system_u, update_results);
+ test_thermal_results(
+ "1_layer/applied_film_nfrc_9223/default", "thermal_SHGC_Environment", glazing_system_shgc, update_results);
+}
+
+TEST_F(Test_1_layer_applied_film_nfrc_9223, Test_Optical)
+{
+ test_optical_results("1_layer/applied_film_nfrc_9223/default", glazing_system_u, update_results);
+}
diff --git a/test/1_layer_cellular_shade_CS03_genBSDF.unit.cpp b/test/1_layer_cellular_shade_CS03_genBSDF.unit.cpp
new file mode 100644
index 00000000..f046e536
--- /dev/null
+++ b/test/1_layer_cellular_shade_CS03_genBSDF.unit.cpp
@@ -0,0 +1,74 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wincalc/wincalc.h"
+#include "optical_calcs.h"
+#include "util.h"
+#include "convert_optics_parser.h"
+#include "paths.h"
+
+
+using namespace wincalc;
+using namespace window_standards;
+
+
+class Test_1_layer_cellular_shade_CS03_genBSDF : public testing::Test
+{
+protected:
+ std::shared_ptr glazing_system_u;
+ std::shared_ptr glazing_system_shgc;
+
+ virtual void SetUp()
+ {
+ std::filesystem::path product_path(test_dir);
+ product_path /= "products";
+ product_path /= "CS03_genBSDF.xml";
+
+ std::vector products;
+ auto shade = OpticsParser::parseBSDFXMLFile(product_path.string());
+ products.push_back(shade);
+
+ std::vector> gaps;
+
+ std::filesystem::path standard_path(test_dir);
+ standard_path /= "standards";
+ standard_path /= "W5_NFRC_2003.std";
+ Optical_Standard standard = load_optical_standard(standard_path.string());
+
+ auto bsdf_hemisphere =
+ SingleLayerOptics::BSDFHemisphere::create(SingleLayerOptics::BSDFBasis::Full);
+
+ glazing_system_u = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_u_environments(), bsdf_hemisphere);
+ glazing_system_shgc = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_shgc_environments(), bsdf_hemisphere);
+ }
+};
+
+TEST_F(Test_1_layer_cellular_shade_CS03_genBSDF, Test_Thermal)
+{
+ // The genBSDF XML files do not have conductivity and so cannot generate thermal results
+ EXPECT_THROW(glazing_system_u->gap_layers_effective_conductivities(Tarcog::ISO15099::System::Uvalue), std::runtime_error);
+ EXPECT_THROW(glazing_system_u->gap_layers_effective_conductivities(Tarcog::ISO15099::System::SHGC), std::runtime_error);
+ EXPECT_THROW(glazing_system_u->layer_temperatures(Tarcog::ISO15099::System::Uvalue), std::runtime_error);
+ EXPECT_THROW(glazing_system_u->layer_temperatures(Tarcog::ISO15099::System::SHGC), std::runtime_error);
+ EXPECT_THROW(glazing_system_u->relative_heat_gain(), std::runtime_error);
+ EXPECT_THROW(glazing_system_u->shgc(), std::runtime_error);
+ EXPECT_THROW(glazing_system_u->u(), std::runtime_error);
+ EXPECT_THROW(glazing_system_u->solid_layers_effective_conductivities(Tarcog::ISO15099::System::Uvalue), std::runtime_error);
+ EXPECT_THROW(glazing_system_u->solid_layers_effective_conductivities(Tarcog::ISO15099::System::SHGC), std::runtime_error);
+ EXPECT_THROW(glazing_system_u->system_effective_conductivity(Tarcog::ISO15099::System::Uvalue), std::runtime_error);
+ EXPECT_THROW(glazing_system_u->system_effective_conductivity(Tarcog::ISO15099::System::SHGC), std::runtime_error);
+
+
+}
+
+TEST_F(Test_1_layer_cellular_shade_CS03_genBSDF, Test_Optical)
+{
+ test_optical_results("1_layer/cellular_shade_CS03_genBSDF/full_basis", glazing_system_u, update_results);
+}
diff --git a/test/1_layer_coated_nfrc_18100.unit.cpp b/test/1_layer_coated_nfrc_18100.unit.cpp
new file mode 100644
index 00000000..d5cec8e8
--- /dev/null
+++ b/test/1_layer_coated_nfrc_18100.unit.cpp
@@ -0,0 +1,61 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wincalc/wincalc.h"
+#include "optical_calcs.h"
+#include "util.h"
+#include "convert_optics_parser.h"
+#include "paths.h"
+
+
+using namespace wincalc;
+using namespace window_standards;
+
+class Test_1_layer_coated_nfrc_18100 : public testing::Test
+{
+protected:
+ std::shared_ptr glazing_system_u;
+ std::shared_ptr glazing_system_shgc;
+
+ virtual void SetUp()
+ {
+ std::filesystem::path product_path(test_dir);
+ product_path /= "products";
+ product_path /= "nfrc_18100.json";
+
+ std::vector products;
+ OpticsParser::Parser parser;
+ auto product = parser.parseJSONFile(product_path.string());
+ products.push_back(product);
+
+ std::vector> gaps;
+
+ std::filesystem::path standard_path(test_dir);
+ standard_path /= "standards";
+ standard_path /= "W5_NFRC_2003.std";
+ Optical_Standard standard = load_optical_standard(standard_path.string());
+
+ glazing_system_u = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_u_environments());
+ glazing_system_shgc = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_shgc_environments());
+ }
+};
+
+TEST_F(Test_1_layer_coated_nfrc_18100, Test_Thermal)
+{
+ test_thermal_results("1_layer/coated_nfrc_18100/default", "thermal_U_Environment", glazing_system_u, update_results);
+ test_thermal_results(
+ "1_layer/coated_nfrc_18100/default", "thermal_SHGC_Environment", glazing_system_shgc, update_results);
+}
+
+TEST_F(Test_1_layer_coated_nfrc_18100, Test_Optical)
+{
+ WCE_Optical_Results solar_results = glazing_system_u->optical_method_results("SOLAR");
+ test_optical_results("1_layer/coated_nfrc_18100/default", glazing_system_u, update_results);
+}
diff --git a/test/1_layer_coated_nfrc_20748.unit.cpp b/test/1_layer_coated_nfrc_20748.unit.cpp
new file mode 100644
index 00000000..c7af7c16
--- /dev/null
+++ b/test/1_layer_coated_nfrc_20748.unit.cpp
@@ -0,0 +1,61 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wincalc/wincalc.h"
+#include "optical_calcs.h"
+#include "util.h"
+#include "convert_optics_parser.h"
+#include "paths.h"
+
+
+using namespace wincalc;
+using namespace window_standards;
+
+class Test_1_layer_coated_nfrc_20748 : public testing::Test
+{
+protected:
+ std::shared_ptr glazing_system_u;
+ std::shared_ptr glazing_system_shgc;
+
+ virtual void SetUp()
+ {
+ std::filesystem::path product_path(test_dir);
+ product_path /= "products";
+ product_path /= "nfrc_20748.oag";
+
+ std::vector products;
+ OpticsParser::Parser parser;
+ auto layer = parser.parseFile(product_path.string());
+ products.push_back(layer);
+
+ std::vector> gaps;
+
+ std::filesystem::path standard_path(test_dir);
+ standard_path /= "standards";
+ standard_path /= "W5_NFRC_2003.std";
+ Optical_Standard standard = load_optical_standard(standard_path.string());
+
+ glazing_system_u = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_u_environments());
+ glazing_system_shgc = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_shgc_environments());
+ }
+};
+
+TEST_F(Test_1_layer_coated_nfrc_20748, Test_Thermal)
+{
+ test_thermal_results("1_layer/coated_nfrc_20748/default", "thermal_U_Environment", glazing_system_u, update_results);
+ test_thermal_results(
+ "1_layer/coated_nfrc_20748/default", "thermal_SHGC_Environment", glazing_system_shgc, update_results);
+}
+
+
+TEST_F(Test_1_layer_coated_nfrc_20748, Test_Optical)
+{
+ test_optical_results("1_layer/coated_nfrc_20748/default", glazing_system_u, update_results);
+}
diff --git a/test/1_layer_coated_nfrc_21467.unit.cpp b/test/1_layer_coated_nfrc_21467.unit.cpp
new file mode 100644
index 00000000..1f12d004
--- /dev/null
+++ b/test/1_layer_coated_nfrc_21467.unit.cpp
@@ -0,0 +1,59 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wincalc/wincalc.h"
+#include "optical_calcs.h"
+#include "util.h"
+#include "convert_optics_parser.h"
+#include "paths.h"
+
+
+using namespace wincalc;
+using namespace window_standards;
+
+class Test_1_layer_coated_nfrc_21467 : public testing::Test
+{
+protected:
+ std::shared_ptr glazing_system_u;
+ std::shared_ptr glazing_system_shgc;
+
+ virtual void SetUp()
+ {
+ std::filesystem::path product_path(test_dir);
+ product_path /= "products";
+ product_path /= "nfrc_21467.json";
+
+ std::vector products;
+ auto product = OpticsParser::parseJSONFile(product_path.string());
+ products.push_back(product);
+
+ std::vector> gaps;
+
+ std::filesystem::path standard_path(test_dir);
+ standard_path /= "standards";
+ standard_path /= "W5_NFRC_2003.std";
+ Optical_Standard standard = load_optical_standard(standard_path.string());
+ glazing_system_u = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_u_environments());
+ glazing_system_shgc = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_shgc_environments());
+ }
+};
+
+
+TEST_F(Test_1_layer_coated_nfrc_21467, Test_Thermal)
+{
+ test_thermal_results("1_layer/coated_nfrc_21467/default", "thermal_U_Environment", glazing_system_u, update_results);
+ test_thermal_results(
+ "1_layer/coated_nfrc_21467/default", "thermal_SHGC_Environment", glazing_system_shgc, update_results);
+}
+
+TEST_F(Test_1_layer_coated_nfrc_21467, Test_Optical)
+{
+ test_optical_results("1_layer/coated_nfrc_21467/default", glazing_system_u, update_results);
+}
diff --git a/test/1_layer_coated_nfrc_6046.unit.cpp b/test/1_layer_coated_nfrc_6046.unit.cpp
new file mode 100644
index 00000000..6108e424
--- /dev/null
+++ b/test/1_layer_coated_nfrc_6046.unit.cpp
@@ -0,0 +1,58 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wincalc/wincalc.h"
+#include "optical_calcs.h"
+#include "util.h"
+#include "convert_optics_parser.h"
+#include "paths.h"
+
+
+using namespace wincalc;
+using namespace window_standards;
+
+class Test_1_layer_coated_nfrc_6046 : public testing::Test
+{
+protected:
+ std::shared_ptr glazing_system_u;
+ std::shared_ptr glazing_system_shgc;
+
+ virtual void SetUp()
+ {
+ std::filesystem::path product_path(test_dir);
+ product_path /= "products";
+ product_path /= "nfrc_6046.json";
+
+ std::vector products;
+ auto product = OpticsParser::parseJSONFile(product_path.string());
+ products.push_back(product);
+
+ std::vector> gaps;
+
+ std::filesystem::path standard_path(test_dir);
+ standard_path /= "standards";
+ standard_path /= "W5_NFRC_2003.std";
+ Optical_Standard standard = load_optical_standard(standard_path.string());
+ glazing_system_u = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_u_environments());
+ glazing_system_shgc = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_shgc_environments());
+ }
+};
+
+TEST_F(Test_1_layer_coated_nfrc_6046, Test_Thermal)
+{
+ test_thermal_results("1_layer/coated_nfrc_6046/default", "thermal_U_Environment", glazing_system_u, update_results);
+ test_thermal_results(
+ "1_layer/coated_nfrc_6046/default", "thermal_SHGC_Environment", glazing_system_shgc, update_results);
+}
+
+TEST_F(Test_1_layer_coated_nfrc_6046, Test_Optical)
+{
+ test_optical_results("1_layer/coated_nfrc_6046/default", glazing_system_u, update_results);
+}
diff --git a/test/1_layer_coated_nfrc_6400.cpp b/test/1_layer_coated_nfrc_6400.cpp
new file mode 100644
index 00000000..855d70fa
--- /dev/null
+++ b/test/1_layer_coated_nfrc_6400.cpp
@@ -0,0 +1,61 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wincalc/wincalc.h"
+#include "optical_calcs.h"
+#include "util.h"
+#include "convert_optics_parser.h"
+#include "paths.h"
+
+
+using namespace wincalc;
+using namespace window_standards;
+
+class Test_1_layer_coated_nfrc_6400 : public testing::Test
+{
+protected:
+ std::shared_ptr glazing_system_u;
+ std::shared_ptr glazing_system_shgc;
+
+ virtual void SetUp()
+ {
+ std::filesystem::path clear_3_path(test_dir);
+ clear_3_path /= "products";
+ clear_3_path /= "nfrc_6400.json";
+
+ std::vector products;
+ OpticsParser::Parser parser;
+ auto clear_3 = parser.parseJSONFile(clear_3_path.string());
+ products.push_back(clear_3);
+
+ std::vector> gaps;
+
+ std::filesystem::path standard_path(test_dir);
+ standard_path /= "standards";
+ standard_path /= "W5_NFRC_2003.std";
+ Optical_Standard standard = load_optical_standard(standard_path.string());
+
+ glazing_system_u = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_u_environments());
+ glazing_system_shgc = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_shgc_environments());
+ }
+};
+
+TEST_F(Test_1_layer_coated_nfrc_6400, Test_Thermal)
+{
+ test_thermal_results("1_layer/coated_nfrc_6400/default", "thermal_U_Environment", glazing_system_u, update_results);
+ test_thermal_results(
+ "1_layer/coated_nfrc_6400/default", "thermal_SHGC_Environment", glazing_system_shgc, update_results);
+}
+
+
+TEST_F(Test_1_layer_coated_nfrc_6400, Test_Optical)
+{
+ test_optical_results("1_layer/coated_nfrc_6400/default", glazing_system_u, update_results);
+}
diff --git a/test/1_layer_laminate_optics_nanometers.unit.cpp b/test/1_layer_laminate_optics_nanometers.unit.cpp
new file mode 100644
index 00000000..bbb92253
--- /dev/null
+++ b/test/1_layer_laminate_optics_nanometers.unit.cpp
@@ -0,0 +1,61 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wincalc/wincalc.h"
+#include "optical_calcs.h"
+#include "util.h"
+#include "convert_optics_parser.h"
+#include "paths.h"
+
+
+using namespace wincalc;
+using namespace window_standards;
+
+class Test_1_layer_laminate_optics_nanometers : public testing::Test
+{
+protected:
+ std::shared_ptr glazing_system_u;
+ std::shared_ptr glazing_system_shgc;
+
+ virtual void SetUp()
+ {
+ std::filesystem::path clear_3_path(test_dir);
+ clear_3_path /= "products";
+ clear_3_path /= "OpticsNanometers.txt";
+
+ std::vector products;
+ OpticsParser::Parser parser;
+ auto clear_3 = parser.parseFile(clear_3_path.string());
+ products.push_back(clear_3);
+
+ std::vector> gaps;
+
+ std::filesystem::path standard_path(test_dir);
+ standard_path /= "standards";
+ standard_path /= "W5_NFRC_2003.std";
+ Optical_Standard standard = load_optical_standard(standard_path.string());
+
+ glazing_system_u = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_u_environments());
+ glazing_system_shgc = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_shgc_environments());
+ }
+};
+
+TEST_F(Test_1_layer_laminate_optics_nanometers, Test_Thermal)
+{
+ test_thermal_results("1_layer/laminate_optics_nanometers/default", "thermal_U_Environment", glazing_system_u, update_results);
+ test_thermal_results(
+ "1_layer/laminate_optics_nanometers/default", "thermal_SHGC_Environment", glazing_system_shgc, update_results);
+}
+
+
+TEST_F(Test_1_layer_laminate_optics_nanometers, Test_Optical)
+{
+ test_optical_results("1_layer/laminate_optics_nanometers/default", glazing_system_u, update_results);
+}
diff --git a/test/1_layer_nfrc_102.unit.cpp b/test/1_layer_nfrc_102.unit.cpp
new file mode 100644
index 00000000..68f589b6
--- /dev/null
+++ b/test/1_layer_nfrc_102.unit.cpp
@@ -0,0 +1,61 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wincalc/wincalc.h"
+#include "optical_calcs.h"
+#include "util.h"
+#include "convert_optics_parser.h"
+#include "paths.h"
+
+
+using namespace wincalc;
+using namespace window_standards;
+
+class Test_1_layer_nfrc_102_default : public testing::Test
+{
+protected:
+ std::shared_ptr glazing_system_u;
+ std::shared_ptr glazing_system_shgc;
+
+ virtual void SetUp()
+ {
+ std::filesystem::path clear_3_path(test_dir);
+ clear_3_path /= "products";
+ clear_3_path /= "CLEAR_3.json";
+
+ std::vector products;
+ OpticsParser::Parser parser;
+ auto clear_3 = parser.parseJSONFile(clear_3_path.string());
+ products.push_back(clear_3);
+
+ std::vector> gaps;
+
+ std::filesystem::path standard_path(test_dir);
+ standard_path /= "standards";
+ standard_path /= "W5_NFRC_2003.std";
+ Optical_Standard standard = load_optical_standard(standard_path.string());
+
+ glazing_system_u = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_u_environments());
+ glazing_system_shgc = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_shgc_environments());
+ }
+};
+
+TEST_F(Test_1_layer_nfrc_102_default, Test_Thermal)
+{
+ test_thermal_results("1_layer/nfrc_102/default", "thermal_U_Environment", glazing_system_u, update_results);
+ test_thermal_results(
+ "1_layer/nfrc_102/default", "thermal_SHGC_Environment", glazing_system_shgc, update_results);
+}
+
+
+TEST_F(Test_1_layer_nfrc_102_default, Test_Optical)
+{
+ test_optical_results("1_layer/nfrc_102/default", glazing_system_u, update_results);
+}
diff --git a/test/1_layer_nfrc_102_WCE.unit.cpp b/test/1_layer_nfrc_102_WCE.unit.cpp
new file mode 100644
index 00000000..01e7843b
--- /dev/null
+++ b/test/1_layer_nfrc_102_WCE.unit.cpp
@@ -0,0 +1,57 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wincalc/wincalc.h"
+#include "optical_calcs.h"
+#include "util.h"
+#include "convert_optics_parser.h"
+#include "paths.h"
+
+
+using namespace wincalc;
+using namespace window_standards;
+
+class Test_1_layer_nfrc_102_WCE : public testing::Test
+{
+protected:
+ std::shared_ptr glazing_system;
+ virtual void SetUp()
+ {
+ std::filesystem::path clear_3_path(test_dir);
+ clear_3_path /= "products";
+ clear_3_path /= "CLEAR_3.json";
+
+ std::vector products;
+ OpticsParser::Parser parser;
+ auto clear_3 = parser.parseJSONFile(clear_3_path.string());
+ products.push_back(clear_3);
+
+ std::vector> gaps;
+
+ std::filesystem::path standard_path(test_dir);
+ standard_path /= "standards";
+ standard_path /= "W5_NFRC_2003.std";
+ Optical_Standard standard = load_optical_standard(standard_path.string());
+
+ auto env = nfrc_u_environments();
+ env.outside.air_temperature = 300.0;
+ env.outside.air_speed = 5.5;
+ env.outside.radiation_temperature = 270;
+ env.outside.direct_solar_radiation = 789;
+ env.outside.coefficient_model = Tarcog::ISO15099::BoundaryConditionsCoeffModel::CalculateH;
+
+ env.inside.air_temperature = 294.15;
+ glazing_system = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, env);
+ }
+};
+
+TEST_F(Test_1_layer_nfrc_102_WCE, Test_Thermal)
+{
+ test_thermal_results("1_layer/nfrc_102/default", "thermal_WCE_Environment", glazing_system, update_results);
+}
diff --git a/test/1_layer_nfrc_102_as_bsdf.unit.cpp b/test/1_layer_nfrc_102_as_bsdf.unit.cpp
new file mode 100644
index 00000000..31ad7d6c
--- /dev/null
+++ b/test/1_layer_nfrc_102_as_bsdf.unit.cpp
@@ -0,0 +1,64 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wincalc/wincalc.h"
+#include "optical_calcs.h"
+#include "util.h"
+#include "convert_optics_parser.h"
+#include "paths.h"
+
+
+using namespace wincalc;
+using namespace window_standards;
+
+class Test_1_layer_nfrc_102_as_bsdf : public testing::Test
+{
+protected:
+ std::shared_ptr glazing_system_u;
+ std::shared_ptr glazing_system_shgc;
+
+ virtual void SetUp()
+ {
+ std::filesystem::path layer_1_path(test_dir);
+ layer_1_path /= "products";
+ layer_1_path /= "CLEAR_3.json";
+
+ std::vector products;
+ auto layer_1 = OpticsParser::parseJSONFile(layer_1_path.string());
+ products.push_back(layer_1);
+
+ std::vector> gaps;
+
+ std::filesystem::path standard_path(test_dir);
+ standard_path /= "standards";
+ standard_path /= "W5_NFRC_2003.std";
+ Optical_Standard standard = load_optical_standard(standard_path.string());
+
+ auto bsdf_hemisphere =
+ SingleLayerOptics::BSDFHemisphere::create(SingleLayerOptics::BSDFBasis::Full);
+
+ glazing_system_u = std::make_shared(
+ standard, products, gaps, 1.0, 1.0, 90, nfrc_u_environments(), bsdf_hemisphere);
+ glazing_system_shgc = std::make_shared