diff --git a/src/integrals/ao_integrals/coulomb_metric.cpp b/src/integrals/ao_integrals/coulomb_metric.cpp index ef724e9c..ca0760e4 100644 --- a/src/integrals/ao_integrals/coulomb_metric.cpp +++ b/src/integrals/ao_integrals/coulomb_metric.cpp @@ -32,8 +32,7 @@ struct Kernel { template simde::type::tensor operator()(const std::span I) { using clean_type = std::decay_t; - if constexpr(types::is_uncertain_v || - types::is_interval_v) { + if constexpr(types::is_uq_type_v) { throw std::runtime_error( "integrals::ao_integrals::CoulombMetric: UQ types not supported"); } else { diff --git a/src/integrals/ao_integrals/uq_atom_symm_blocked_driver.cpp b/src/integrals/ao_integrals/uq_atom_symm_blocked_driver.cpp index b1672ea4..3458b632 100644 --- a/src/integrals/ao_integrals/uq_atom_symm_blocked_driver.cpp +++ b/src/integrals/ao_integrals/uq_atom_symm_blocked_driver.cpp @@ -33,11 +33,11 @@ auto average_error(T&& strides, T&& nbf, T&& ao_i, Tensor&& error, "integrals::ao_integrals::UQAtomSymmBlockedDriver: "; #ifdef ENABLE_SIGMA - using float_type = typename UQType::value_t; - using demangler_type = ::utilities::printing::Demangler; + using float_type = typename UQType::value_t; auto n_elements = nbf[0] * nbf[1] * nbf[2] * nbf[3]; + using tensorwrapper::types::construct_uq_type; if(mean == utils::mean_type::none) { std::vector result; result.reserve(n_elements); @@ -50,16 +50,8 @@ auto average_error(T&& strides, T&& nbf, T&& ao_i, Tensor&& error, for(std::size_t l = 0; l < nbf[3]; ++l) { auto loffset = koffset + (ao_i[3] + l) * strides[3]; auto ei = std::fabs(error[loffset]); - if constexpr(types::is_interval_v) { - result.push_back(UQType{-ei, ei}); - } else if constexpr(types::is_uncertain_v) { - result.push_back(UQType{0.0, ei}); - } else { - auto type0 = demangler_type::demangle(); - throw std::runtime_error( - error_base + "Invalid UQ type " + type0 + - " for non-mean reduction"); - } + auto elem = construct_uq_type(0.0, ei); + result.push_back(elem); } } } @@ -83,15 +75,8 @@ auto average_error(T&& strides, T&& nbf, T&& ao_i, Tensor&& error, } } auto mean_value = utils::compute_mean(mean, buffer); - if constexpr(types::is_interval_v) { - return std::vector(n_elements, UQType{-mean_value, mean_value}); - } else if constexpr(types::is_uncertain_v) { - return std::vector(n_elements, UQType{0.0, mean_value}); - } else { - auto type0 = demangler_type::demangle(); - throw std::runtime_error(error_base + "Invalid UQ type " + type0 + - " for mean reduction"); - } + auto value = construct_uq_type(0.0, mean_value); + return std::vector(n_elements, value); #else throw std::runtime_error(error_base + "Sigma support not enabled!"); return std::vector{}; @@ -191,8 +176,7 @@ struct Kernel { Tensor rv; using float_type = std::decay_t; - if constexpr(types::is_uncertain_v || - types::is_interval_v) { + if constexpr(types::is_uq_type_v) { auto type0 = demangler_type::demangle(); throw std::runtime_error( m_error_base + "Expected non-UQ floating point type, but got " + @@ -348,6 +332,13 @@ MODULE_RUN(UQAtomSymmBlockedDriver) { } else if(uq_type == "interval") { Kernel k(shape, aos, mean); t_w_error = visit_contiguous_buffer(k, t_buffer, e_buffer); + } else if(uq_type == "affine") { + Kernel k(shape, aos, mean); + t_w_error = visit_contiguous_buffer(k, t_buffer, e_buffer); + } else if(uq_type == "thresholded affine") { + Kernel k(shape, aos, + mean); + t_w_error = visit_contiguous_buffer(k, t_buffer, e_buffer); } else { throw std::runtime_error( "integrals::ao_integrals::UQAtomSymmBlockedDriver: Invalid UQ type " diff --git a/src/integrals/ao_integrals/uq_driver.cpp b/src/integrals/ao_integrals/uq_driver.cpp index e0f9929d..7ceea6a7 100644 --- a/src/integrals/ao_integrals/uq_driver.cpp +++ b/src/integrals/ao_integrals/uq_driver.cpp @@ -52,15 +52,16 @@ struct Kernel { Tensor rv; using float_type = std::decay_t; - if constexpr(types::is_uncertain_v || - types::is_interval_v) { + if constexpr(types::is_uq_type_v) { auto type0 = demangler_type::demangle(); throw std::runtime_error( m_error_base + "Expected non-UQ floating point type, but got " + type0); } else { #ifdef ENABLE_SIGMA - using uq_type = UQType; + using uq_type = UQType; + using tensorwrapper::types::construct_uq_type; + using tensorwrapper::types::fabs; auto rv_buffer = buffer::make_contiguous(m_shape); auto rv_data = buffer::get_raw_data(rv_buffer); @@ -68,30 +69,13 @@ struct Kernel { if(!use_mean) { for(std::size_t i = 0; i < t.size(); ++i) { const auto elem = t[i]; - if constexpr(types::is_interval_v) { - auto ei = std::fabs(error[i]); - rv_data[i] = uq_type{elem - ei, elem + ei}; - } else if constexpr(types::is_uncertain_v) { - rv_data[i] = uq_type{elem, error[i]}; - } else { - auto type0 = demangler_type::demangle(); - throw std::runtime_error(m_error_base + - "Invalid UQ type " + type0 + - " for non-mean reduction"); - } + const auto ei = std::fabs(error[i]); + rv_data[i] = construct_uq_type(elem, ei); } } else { float_type max_error = utils::compute_mean(m_mean, error); - uq_type max_uq; - if constexpr(types::is_interval_v) { - max_uq = uq_type(-max_error, max_error); - } else if constexpr(types::is_uncertain_v) { - max_uq = uq_type(0.0, max_error); - } else { - auto type0 = demangler_type::demangle(); - throw std::runtime_error(m_error_base + "Invalid UQ type " + - type0 + " for mean reduction"); - } + auto max_uq = construct_uq_type(0.0, max_error); + for(std::size_t i = 0; i < t.size(); ++i) { const auto elem = t[i]; rv_data[i] = uq_type(elem) + max_uq; @@ -155,6 +139,12 @@ MODULE_RUN(UQDriver) { } else if(uq_type == "interval") { Kernel k(shape, mean); t_w_error = visit_contiguous_buffer(k, t_buffer, error_buffer); + } else if(uq_type == "affine") { + Kernel k(shape, mean); + t_w_error = visit_contiguous_buffer(k, t_buffer, error_buffer); + } else if(uq_type == "thresholded affine") { + Kernel k(shape, mean); + t_w_error = visit_contiguous_buffer(k, t_buffer, error_buffer); } else { throw std::runtime_error( "integrals::ao_integrals::UQDriver: Invalid UQ type name " + uq_type); diff --git a/src/integrals/libint/libint.cpp b/src/integrals/libint/libint.cpp index 729070a0..f453ddfb 100644 --- a/src/integrals/libint/libint.cpp +++ b/src/integrals/libint/libint.cpp @@ -57,6 +57,14 @@ TEMPLATED_MODULE_RUN(Libint, BraKetType) { } else if(uq_type == "interval") { using interval_type = tensorwrapper::types::interval_type; t = detail_::fill_tensor(basis_sets, op, rv, thresh); + } else if(uq_type == "affine") { + using affine_type = tensorwrapper::types::affine_type; + t = detail_::fill_tensor(basis_sets, op, rv, thresh); + } else if(uq_type == "thresholded affine") { + using thresholded_affine_type = + tensorwrapper::types::thresholded_affine_type; + t = detail_::fill_tensor(basis_sets, op, rv, + thresh); } else { throw std::runtime_error( "integrals::libint::Libint: Invalid UQ type name " + uq_type); diff --git a/src/integrals/utils/uncertainty_reductions.hpp b/src/integrals/utils/uncertainty_reductions.hpp index e74e95a4..f181a9e9 100644 --- a/src/integrals/utils/uncertainty_reductions.hpp +++ b/src/integrals/utils/uncertainty_reductions.hpp @@ -35,8 +35,8 @@ auto max_mean(const ContainerType& values) { template auto geometric_mean(const ContainerType& values) { - using float_type = std::decay_t; - float_type log_sum = 0.0; + using float_type = std::decay_t; + float_type log_sum(0.0); std::size_t non_zero_count = 0; for(const auto& val : values) { if(val == float_type{0}) continue; diff --git a/tests/cxx/unit/integrals/ao_integrals/test_uq_atom_symm_blocked_driver.cpp b/tests/cxx/unit/integrals/ao_integrals/test_uq_atom_symm_blocked_driver.cpp index a7197842..a3e0762b 100644 --- a/tests/cxx/unit/integrals/ao_integrals/test_uq_atom_symm_blocked_driver.cpp +++ b/tests/cxx/unit/integrals/ao_integrals/test_uq_atom_symm_blocked_driver.cpp @@ -22,20 +22,6 @@ using namespace tensorwrapper; namespace { -template -auto elem(FloatType value, FloatType error) { - if constexpr(tensorwrapper::types::is_uncertain_v) { - return UQType{value, error}; - } else if constexpr(tensorwrapper::types::is_interval_v) { - return UQType{value - error, value + error}; - } else { - ::utilities::printing::Demangler demangler; - auto type0 = demangler.template demangle(); - throw std::runtime_error( - "UQ Atom Symm Blocked Driver Test: Invalid UQ type " + type0); - } -} - // N.b. The "means" of the correct values are validated by comparing to Libint's // results. With the exception of the "No Mean" values, the // "standard deviations" are not validated, but seem reasonable (the "No Mean" @@ -49,34 +35,38 @@ auto corr_answer(const simde::type::tensor& T) { using value_t = typename UQType::value_t; simde::type::tensor T_corr(T); auto& corr_buffer = buffer::make_contiguous(T_corr.buffer()); - corr_buffer.set_elem({0, 0, 0, 0}, elem(0.774606, value_t(0))); - corr_buffer.set_elem({0, 0, 0, 1}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({0, 0, 1, 0}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({0, 0, 1, 1}, elem(0.446701, value_t(0))); - corr_buffer.set_elem({0, 1, 0, 0}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({0, 1, 0, 1}, - elem(0.120666, 0.0000170000000000)); - corr_buffer.set_elem({0, 1, 1, 0}, - elem(0.120666, 0.0000170000000000)); - corr_buffer.set_elem({0, 1, 1, 1}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({1, 0, 0, 0}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({1, 0, 0, 1}, - elem(0.120666, 0.0000170000000000)); - corr_buffer.set_elem({1, 0, 1, 0}, - elem(0.120666, 0.0000170000000000)); - corr_buffer.set_elem({1, 0, 1, 1}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({1, 1, 0, 0}, elem(0.446701, value_t(0))); - corr_buffer.set_elem({1, 1, 0, 1}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({1, 1, 1, 0}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({1, 1, 1, 1}, elem(0.774606, value_t(0))); + corr_buffer.set_elem( + {0, 0, 0, 0}, types::construct_uq_type(0.774606, value_t(0))); + corr_buffer.set_elem({0, 0, 0, 1}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem({0, 0, 1, 0}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem( + {0, 0, 1, 1}, types::construct_uq_type(0.446701, value_t(0))); + corr_buffer.set_elem({0, 1, 0, 0}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem({0, 1, 0, 1}, types::construct_uq_type( + 0.120666, 0.0000170000000000)); + corr_buffer.set_elem({0, 1, 1, 0}, types::construct_uq_type( + 0.120666, 0.0000170000000000)); + corr_buffer.set_elem({0, 1, 1, 1}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem({1, 0, 0, 0}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem({1, 0, 0, 1}, types::construct_uq_type( + 0.120666, 0.0000170000000000)); + corr_buffer.set_elem({1, 0, 1, 0}, types::construct_uq_type( + 0.120666, 0.0000170000000000)); + corr_buffer.set_elem({1, 0, 1, 1}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem( + {1, 1, 0, 0}, types::construct_uq_type(0.446701, value_t(0))); + corr_buffer.set_elem({1, 1, 0, 1}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem({1, 1, 1, 0}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem( + {1, 1, 1, 1}, types::construct_uq_type(0.774606, value_t(0))); return T_corr; } } @@ -112,11 +102,14 @@ auto corr_answer_no_mean(const simde::type::tensor& T, } // namespace -TEST_CASE("UQ Atom Symm Blocked Driver") { - using uncertain_type = tensorwrapper::types::udouble; - using interval_type = tensorwrapper::types::interval_type; - using test_pt = simde::ERI4; - using error_pt = integrals::property_types::Uncertainty; +using uq_types = + std::tuple, + tensorwrapper::types::affine_type, + tensorwrapper::types::thresholded_affine_type>; +TEMPLATE_LIST_TEST_CASE("UQ Atom Symm Blocked Driver", "", uq_types) { + using float_type = TestType; + using test_pt = simde::ERI4; + using error_pt = integrals::property_types::Uncertainty; using tensorwrapper::operations::approximately_equal; auto rt = std::make_unique(); @@ -141,60 +134,48 @@ TEST_CASE("UQ Atom Symm Blocked Driver") { // Make BraKet Input chemist::braket::BraKet braket(aos_squared, op, aos_squared); - if constexpr(tensorwrapper::types::is_uncertain_v) { - SECTION("No Mean") { - auto T = mod.run_as(braket); - auto tol = 1.0e-6; - auto T_eri = mm.at("ERI4").run_as(braket); - auto T_err = - mm.at("Primitive Error Model").run_as(braket, tol); - REQUIRE(corr_answer_no_mean(T, T_eri, T_err)); - } - SECTION("Max Error") { - mod.change_input("Mean Type", "max"); - auto T = mod.run_as(braket); - - auto T_corr = corr_answer(T); - REQUIRE(approximately_equal(T_corr, T, 1E-6)); + std::string uq_type = []() -> std::string { + if constexpr(tensorwrapper::types::is_uncertain_v) { + return "uncertain"; + } else if constexpr(tensorwrapper::types::is_interval_v< + float_type>) { + return "interval"; + } else if constexpr(tensorwrapper::types::is_affine_v) { + return "affine"; + } else if constexpr(tensorwrapper::types::is_thresholded_affine_v< + float_type>) { + return "thresholded affine"; + } else { + return ""; // Won't be used because of static assert below. } - SECTION("Geometric Mean") { - mod.change_input("Mean Type", "geometric"); - auto T = mod.run_as(braket); + }(); - auto T_corr = corr_answer(T); - REQUIRE(approximately_equal(T_corr, T, 1E-6)); - } - } - if constexpr(tensorwrapper::types::is_interval_v) { + if constexpr(tensorwrapper::types::is_uq_type_v) { // The errors for the integrals are on the order of 1e-5. - // Subtracting - // the intervals in approximately_equal treats the intervals as - // independent and doubles them instead of cancelling them. This in - // turn means center + radius on the difference inside - // approximately_equal will be between 1e-5 and 1e-4. + // Subtracting results in differences between 1e-5 and 1e-4. SECTION("No Mean") { - mod.change_input("UQ Type", "interval"); + mod.change_input("UQ Type", uq_type); auto T = mod.run_as(braket); auto tol = 1.0e-6; auto T_eri = mm.at("ERI4").run_as(braket); auto T_err = mm.at("Primitive Error Model").run_as(braket, tol); - REQUIRE(corr_answer_no_mean(T, T_eri, T_err)); + REQUIRE(corr_answer_no_mean(T, T_eri, T_err)); } SECTION("Max Error") { - mod.change_input("UQ Type", "interval"); + mod.change_input("UQ Type", uq_type); mod.change_input("Mean Type", "max"); auto T = mod.run_as(braket); - auto T_corr = corr_answer(T); + auto T_corr = corr_answer(T); REQUIRE(approximately_equal(T_corr, T, 1E-4)); } SECTION("Geometric Mean") { - mod.change_input("UQ Type", "interval"); + mod.change_input("UQ Type", uq_type); mod.change_input("Mean Type", "geometric"); auto T = mod.run_as(braket); - auto T_corr = corr_answer(T); + auto T_corr = corr_answer(T); REQUIRE(approximately_equal(T_corr, T, 1E-4)); } } diff --git a/tests/cxx/unit/integrals/ao_integrals/test_uq_driver.cpp b/tests/cxx/unit/integrals/ao_integrals/test_uq_driver.cpp index 5ff5e5f0..d8b66f45 100644 --- a/tests/cxx/unit/integrals/ao_integrals/test_uq_driver.cpp +++ b/tests/cxx/unit/integrals/ao_integrals/test_uq_driver.cpp @@ -27,17 +27,6 @@ namespace { // "standard deviations" are not validated, but seem reasonable (the "No Mean" // values come from the unit tests of the underlying error module). -template -auto elem(FloatType value, FloatType error) { - if constexpr(tensorwrapper::types::is_uncertain_v) { - return UQType{value, error}; - } else if constexpr(tensorwrapper::types::is_interval_v) { - return UQType{value - error, value + error}; - } else { - throw std::runtime_error("Invalid UQ type"); - } -} - template auto corr_answer(const simde::type::tensor& T) { if constexpr(std::is_same_v) { @@ -45,34 +34,38 @@ auto corr_answer(const simde::type::tensor& T) { } else { simde::type::tensor T_corr(T); auto& corr_buffer = buffer::make_contiguous(T_corr.buffer()); - corr_buffer.set_elem({0, 0, 0, 0}, elem(0.774606, 0.0)); - corr_buffer.set_elem({0, 0, 0, 1}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({0, 0, 1, 0}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({0, 0, 1, 1}, elem(0.446701, 0.0)); - corr_buffer.set_elem({0, 1, 0, 0}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({0, 1, 0, 1}, - elem(0.120666, 0.0000170000000000)); - corr_buffer.set_elem({0, 1, 1, 0}, - elem(0.120666, 0.0000170000000000)); - corr_buffer.set_elem({0, 1, 1, 1}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({1, 0, 0, 0}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({1, 0, 0, 1}, - elem(0.120666, 0.0000170000000000)); - corr_buffer.set_elem({1, 0, 1, 0}, - elem(0.120666, 0.0000170000000000)); - corr_buffer.set_elem({1, 0, 1, 1}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({1, 1, 0, 0}, elem(0.446701, 0.0)); - corr_buffer.set_elem({1, 1, 0, 1}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({1, 1, 1, 0}, - elem(0.265558, 0.0000010000000000)); - corr_buffer.set_elem({1, 1, 1, 1}, elem(0.774606, 0.0)); + corr_buffer.set_elem( + {0, 0, 0, 0}, types::construct_uq_type(0.774606, 0.0)); + corr_buffer.set_elem({0, 0, 0, 1}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem({0, 0, 1, 0}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem( + {0, 0, 1, 1}, types::construct_uq_type(0.446701, 0.0)); + corr_buffer.set_elem({0, 1, 0, 0}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem({0, 1, 0, 1}, types::construct_uq_type( + 0.120666, 0.0000170000000000)); + corr_buffer.set_elem({0, 1, 1, 0}, types::construct_uq_type( + 0.120666, 0.0000170000000000)); + corr_buffer.set_elem({0, 1, 1, 1}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem({1, 0, 0, 0}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem({1, 0, 0, 1}, types::construct_uq_type( + 0.120666, 0.0000170000000000)); + corr_buffer.set_elem({1, 0, 1, 0}, types::construct_uq_type( + 0.120666, 0.0000170000000000)); + corr_buffer.set_elem({1, 0, 1, 1}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem( + {1, 1, 0, 0}, types::construct_uq_type(0.446701, 0.0)); + corr_buffer.set_elem({1, 1, 0, 1}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem({1, 1, 1, 0}, types::construct_uq_type( + 0.265558, 0.0000010000000000)); + corr_buffer.set_elem( + {1, 1, 1, 1}, types::construct_uq_type(0.774606, 0.0)); return T_corr; } } @@ -85,38 +78,38 @@ auto corr_max_answer(const simde::type::tensor& T) { simde::type::tensor T_corr(T); auto& corr_buffer = buffer::make_contiguous(T_corr.buffer()); double max_error = 0.0000170000000000; - corr_buffer.set_elem({0, 0, 0, 0}, - elem(0.774606, max_error)); - corr_buffer.set_elem({0, 0, 0, 1}, - elem(0.265558, max_error)); - corr_buffer.set_elem({0, 0, 1, 0}, - elem(0.265558, max_error)); - corr_buffer.set_elem({0, 0, 1, 1}, - elem(0.446701, max_error)); - corr_buffer.set_elem({0, 1, 0, 0}, - elem(0.265558, max_error)); - corr_buffer.set_elem({0, 1, 0, 1}, - elem(0.120666, max_error)); - corr_buffer.set_elem({0, 1, 1, 0}, - elem(0.120666, max_error)); - corr_buffer.set_elem({0, 1, 1, 1}, - elem(0.265558, max_error)); - corr_buffer.set_elem({1, 0, 0, 0}, - elem(0.265558, max_error)); - corr_buffer.set_elem({1, 0, 0, 1}, - elem(0.120666, max_error)); - corr_buffer.set_elem({1, 0, 1, 0}, - elem(0.120666, max_error)); - corr_buffer.set_elem({1, 0, 1, 1}, - elem(0.265558, max_error)); - corr_buffer.set_elem({1, 1, 0, 0}, - elem(0.446701, max_error)); - corr_buffer.set_elem({1, 1, 0, 1}, - elem(0.265558, max_error)); - corr_buffer.set_elem({1, 1, 1, 0}, - elem(0.265558, max_error)); - corr_buffer.set_elem({1, 1, 1, 1}, - elem(0.774606, max_error)); + corr_buffer.set_elem({0, 0, 0, 0}, types::construct_uq_type( + 0.774606, max_error)); + corr_buffer.set_elem({0, 0, 0, 1}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({0, 0, 1, 0}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({0, 0, 1, 1}, types::construct_uq_type( + 0.446701, max_error)); + corr_buffer.set_elem({0, 1, 0, 0}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({0, 1, 0, 1}, types::construct_uq_type( + 0.120666, max_error)); + corr_buffer.set_elem({0, 1, 1, 0}, types::construct_uq_type( + 0.120666, max_error)); + corr_buffer.set_elem({0, 1, 1, 1}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({1, 0, 0, 0}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({1, 0, 0, 1}, types::construct_uq_type( + 0.120666, max_error)); + corr_buffer.set_elem({1, 0, 1, 0}, types::construct_uq_type( + 0.120666, max_error)); + corr_buffer.set_elem({1, 0, 1, 1}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({1, 1, 0, 0}, types::construct_uq_type( + 0.446701, max_error)); + corr_buffer.set_elem({1, 1, 0, 1}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({1, 1, 1, 0}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({1, 1, 1, 1}, types::construct_uq_type( + 0.774606, max_error)); return T_corr; } } @@ -129,45 +122,49 @@ auto corr_geometric_mean_answer(const simde::type::tensor& T) { simde::type::tensor T_corr(T); auto& corr_buffer = buffer::make_contiguous(T_corr.buffer()); double max_error = 0.0000025712815907; - corr_buffer.set_elem({0, 0, 0, 0}, - elem(0.774606, max_error)); - corr_buffer.set_elem({0, 0, 0, 1}, - elem(0.265558, max_error)); - corr_buffer.set_elem({0, 0, 1, 0}, - elem(0.265558, max_error)); - corr_buffer.set_elem({0, 0, 1, 1}, - elem(0.446701, max_error)); - corr_buffer.set_elem({0, 1, 0, 0}, - elem(0.265558, max_error)); - corr_buffer.set_elem({0, 1, 0, 1}, - elem(0.120666, max_error)); - corr_buffer.set_elem({0, 1, 1, 0}, - elem(0.120666, max_error)); - corr_buffer.set_elem({0, 1, 1, 1}, - elem(0.265558, max_error)); - corr_buffer.set_elem({1, 0, 0, 0}, - elem(0.265558, max_error)); - corr_buffer.set_elem({1, 0, 0, 1}, - elem(0.120666, max_error)); - corr_buffer.set_elem({1, 0, 1, 0}, - elem(0.120666, max_error)); - corr_buffer.set_elem({1, 0, 1, 1}, - elem(0.265558, max_error)); - corr_buffer.set_elem({1, 1, 0, 0}, - elem(0.446701, max_error)); - corr_buffer.set_elem({1, 1, 0, 1}, - elem(0.265558, max_error)); - corr_buffer.set_elem({1, 1, 1, 0}, - elem(0.265558, max_error)); - corr_buffer.set_elem({1, 1, 1, 1}, - elem(0.774606, max_error)); + corr_buffer.set_elem({0, 0, 0, 0}, types::construct_uq_type( + 0.774606, max_error)); + corr_buffer.set_elem({0, 0, 0, 1}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({0, 0, 1, 0}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({0, 0, 1, 1}, types::construct_uq_type( + 0.446701, max_error)); + corr_buffer.set_elem({0, 1, 0, 0}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({0, 1, 0, 1}, types::construct_uq_type( + 0.120666, max_error)); + corr_buffer.set_elem({0, 1, 1, 0}, types::construct_uq_type( + 0.120666, max_error)); + corr_buffer.set_elem({0, 1, 1, 1}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({1, 0, 0, 0}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({1, 0, 0, 1}, types::construct_uq_type( + 0.120666, max_error)); + corr_buffer.set_elem({1, 0, 1, 0}, types::construct_uq_type( + 0.120666, max_error)); + corr_buffer.set_elem({1, 0, 1, 1}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({1, 1, 0, 0}, types::construct_uq_type( + 0.446701, max_error)); + corr_buffer.set_elem({1, 1, 0, 1}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({1, 1, 1, 0}, types::construct_uq_type( + 0.265558, max_error)); + corr_buffer.set_elem({1, 1, 1, 1}, types::construct_uq_type( + 0.774606, max_error)); return T_corr; } } } // namespace -TEST_CASE("UQ Driver") { - using float_type = tensorwrapper::types::udouble; +using uq_types = + std::tuple, + tensorwrapper::types::thresholded_affine_type>; +TEMPLATE_LIST_TEST_CASE("UQ Driver", "", uq_types) { + using float_type = TestType; using test_pt = simde::ERI4; auto rt = std::make_unique(); @@ -192,59 +189,46 @@ TEST_CASE("UQ Driver") { chemist::braket::BraKet braket(aos_squared, op, aos_squared); using tensorwrapper::operations::approximately_equal; - if constexpr(tensorwrapper::types::is_uncertain_v) { - SECTION("No Mean") { - // Call modules - auto T = mm.at("UQ Driver").run_as(braket); - auto T_corr = corr_answer(T); - REQUIRE(approximately_equal(T_corr, T, 1E-6)); + std::string uq_type = []() -> std::string { + if constexpr(tensorwrapper::types::is_uncertain_v) { + return "uncertain"; + } else if constexpr(tensorwrapper::types::is_interval_v) { + return "interval"; + } else if constexpr(tensorwrapper::types::is_affine_v) { + return "affine"; + } else if constexpr(tensorwrapper::types::is_thresholded_affine_v< + float_type>) { + return "thresholded affine"; + } else { + return ""; // Won't be used because of static assert below. } - SECTION("Max Error") { - auto copy = mm.at("UQ Driver").unlocked_copy(); - copy.change_input("Mean Type", "max"); - auto T = copy.run_as(braket); - - auto T_corr = corr_max_answer(T); - REQUIRE(approximately_equal(T_corr, T, 1E-6)); - } - SECTION("Geometric Mean") { - auto copy = mm.at("UQ Driver").unlocked_copy(); - copy.change_input("Mean Type", "geometric"); - auto T = copy.run_as(braket); + }(); - auto T_corr = corr_geometric_mean_answer(T); - REQUIRE(approximately_equal(T_corr, T, 1E-6)); - } - } - using interval_type = tensorwrapper::types::interval_type; - if constexpr(tensorwrapper::types::is_interval_v) { - auto copy = mm.at("UQ Driver").unlocked_copy(); - copy.change_input("UQ Type", "interval"); - // The errors for the integrals are on the order of 1e-5. Subtracting - // the intervals in approximately_equal treats the intervals as - // independent and doubles them instead of cancelling them. This in turn - // means center + radius on the difference inside approximately_equal + if constexpr(tensorwrapper::types::is_uq_type_v) { + // The errors for the integrals are on the order of 1e-5. So difference // will be between 1e-5 and 1e-4. + auto copy = mm.at("UQ Driver").unlocked_copy(); + copy.change_input("UQ Type", uq_type); SECTION("No Mean") { // Call modules auto T = copy.run_as(braket); - auto T_corr = corr_answer(T); - + auto T_corr = corr_answer(T); REQUIRE(approximately_equal(T_corr, T, 1E-4)); } SECTION("Max Error") { auto copy2 = copy.unlocked_copy(); copy2.change_input("Mean Type", "max"); - auto T = copy2.run_as(braket); - auto T_corr = corr_max_answer(T); + auto T = copy2.run_as(braket); + + auto T_corr = corr_max_answer(T); REQUIRE(approximately_equal(T_corr, T, 1E-4)); } SECTION("Geometric Mean") { - auto copy2 = copy.unlocked_copy(); - copy2.change_input("Mean Type", "geometric"); - auto T = copy2.run_as(braket); + auto copy3 = copy.unlocked_copy(); + copy3.change_input("Mean Type", "geometric"); + auto T = copy3.run_as(braket); - auto T_corr = corr_geometric_mean_answer(T); + auto T_corr = corr_geometric_mean_answer(T); REQUIRE(approximately_equal(T_corr, T, 1E-4)); } }