Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into pyml
Browse files Browse the repository at this point in the history
# Conflicts:
#	docs/algorithms/sidb_simulation.rst
#	libs/pybind11
marcelwa committed Nov 21, 2023

Unverified

The email in this signature doesn’t match the committer email.
2 parents 3a5d387 + 987ef42 commit de9dfd8
Showing 12 changed files with 938 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/clang-tidy-review-post.yml
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ jobs:
steps:
# Download the artifact uploaded by the lint action
- name: Download Clang-Tidy artifact
uses: actions/github-script@v6
uses: actions/github-script@v7
with:
script: |
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
21 changes: 21 additions & 0 deletions docs/algorithms/sidb_simulation.rst
Original file line number Diff line number Diff line change
@@ -265,3 +265,24 @@ Binary-dot Logic (BDL) Pair Detection
.. autoclass:: fiction.pyfiction.detect_bdl_pairs_params
:members:
.. autofunction:: fiction.pyfiction.detect_bdl_pairs


Assess Population Stability
^^^^^^^^^^^^^^^^^^^^^^^^^^^

**Header:** ``fiction/algorithms/simulation/sidb/assess_physical_population_stability.hpp``

.. doxygenenum:: fiction::transition_type
.. doxygenstruct:: fiction::population_stability_information
:members:
.. doxygenstruct:: fiction::assess_physical_population_stability_params
:members:
.. doxygenfunction:: fiction::assess_physical_population_stability


Convert Potential to Distance
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

**Header:** ``fiction/algorithms/simulation/sidb/convert_potential_to_distance.hpp``

.. doxygenfunction:: fiction::convert_potential_to_distance

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//
// Created by Jan Drewniok on 10.11.23.
//

#ifndef FICTION_CONVERT_POTENTIAL_TO_DISTANCE_HPP
#define FICTION_CONVERT_POTENTIAL_TO_DISTANCE_HPP

#include "fiction/algorithms/simulation/sidb/sidb_simulation_parameters.hpp"
#include "fiction/technology/physical_constants.hpp"

#include <cmath>
#include <cstdint>
#include <limits>
#include <vector>

namespace fiction
{

/**
* The electrostatic potential on hydrogen-passivated silicon is typically modeled using a screened Coulomb potential.
* This electrostatic potential is commonly employed to determine the electrostatic potential for a given distance
* (between SiDB and point under consideration) and given physical parameters. However, the function provided here
* serves the inverse purpose by calculating the distance for a given potential and given physical parameters.
*
* @note Runtime depends exponentially on the provided precision.
*
* @param params The physical parameters for a given hydrogen-passivated silicon surface.
* @param potential The electrostatic potential (unit: V) to be converted to a distance.
* @param precision The precision level for the conversion, specifying the number of decimal places.
* @return The distance (unit: nm) corresponding to the given electrostatic potential.
*/
[[nodiscard]] inline double
convert_potential_to_distance(const double potential,
const sidb_simulation_parameters& params = sidb_simulation_parameters{},
const uint64_t precision = 2) noexcept
{
// function to calculate the electrostatic potential for a given distance and given physical parameters on the H-Si
// surface
const auto calculate_potential_for_given_distance = [&params](const double distance) noexcept
{
return params.k() * params.epsilon_r / params.epsilon_r / (distance * 1e-9) *
std::exp(-distance / params.lambda_tf) * physical_constants::ELEMENTARY_CHARGE;
};

// calculate the step size based on the precision
const double step_size = std::pow(10, -static_cast<double>(precision));

// initialize distance and potential for the initial step
double distance = step_size;
double potential_for_given_distance = calculate_potential_for_given_distance(distance);

// as long as the electrostatic potential is still larger than the given potential, the distance is increased
while (potential_for_given_distance > potential)
{
distance += step_size;
potential_for_given_distance = calculate_potential_for_given_distance(distance);
}

return distance;
}

} // namespace fiction

#endif // FICTION_CONVERT_POTENTIAL_TO_DISTANCE_HPP
Original file line number Diff line number Diff line change
@@ -871,7 +871,7 @@ class operational_domain_impl
const auto decr_x = (x > 0) ? x - 1 : x;
const auto incr_x = (x + 1 < x_indices.size()) ? x + 1 : x;
const auto decr_y = (y > 0) ? y - 1 : y;
const auto incr_y = (y + 1 < x_indices.size()) ? y + 1 : y;
const auto incr_y = (y + 1 < y_indices.size()) ? y + 1 : y;

// add neighbors in clockwise direction

104 changes: 32 additions & 72 deletions include/fiction/algorithms/simulation/sidb/quickexact.hpp
Original file line number Diff line number Diff line change
@@ -86,7 +86,7 @@ class quickexact_impl
{
public:
quickexact_impl(const Lyt& lyt, const quickexact_params<Lyt>& parameter) :
layout{lyt},
layout{lyt.clone()},
charge_lyt{lyt},
params{parameter}
{
@@ -345,22 +345,14 @@ class quickexact_impl

if (charge_layout.is_physically_valid())
{
charge_distribution_surface<Lyt> charge_lyt_copy{charge_layout};
charge_lyt_copy.recompute_system_energy();
charge_distribution_surface<Lyt> charge_lyt_copy{charge_lyt};

// The pre-assigned negatively-charged SiDBs are added to the final layout.
for (const auto& cell : preassigned_negative_sidbs)
{
charge_lyt_copy.add_sidb(cell, sidb_charge_state::NEGATIVE);
}
charge_layout.foreach_cell(
[&charge_lyt_copy, &charge_layout](const auto& c)
{ charge_lyt_copy.assign_charge_state(c, charge_layout.get_charge_state(c)); });

if constexpr (has_get_sidb_defect_v<Lyt>)
{
for (const auto& [cell, defect] : real_placed_defects)
{
charge_lyt_copy.assign_sidb_defect(cell, defect);
}
}
charge_lyt_copy.update_after_charge_change();
charge_lyt_copy.recompute_system_energy();
result.charge_distributions.push_back(charge_lyt_copy);
}
}
@@ -398,23 +390,14 @@ class quickexact_impl
{
if (charge_layout.is_physically_valid())
{
charge_distribution_surface<Lyt> charge_lyt_copy{charge_layout};
charge_lyt_copy.recompute_system_energy();

// The pre-assigned negatively-charged SiDBs are added to the final layout.
for (const auto& cell : preassigned_negative_sidbs)
{
charge_lyt_copy.add_sidb(cell, sidb_charge_state::NEGATIVE);
}
charge_distribution_surface<Lyt> charge_lyt_copy{charge_lyt};

if constexpr (has_get_sidb_defect_v<Lyt>)
{
for (const auto& [cell, defect] : real_placed_defects)
{
charge_lyt_copy.assign_sidb_defect(cell, defect);
}
}
charge_layout.foreach_cell(
[&charge_lyt_copy, &charge_layout](const auto& c)
{ charge_lyt_copy.assign_charge_state(c, charge_layout.get_charge_state(c)); });

charge_lyt_copy.update_after_charge_change();
charge_lyt_copy.recompute_system_energy();
result.charge_distributions.push_back(charge_lyt_copy);
}

@@ -428,22 +411,14 @@ class quickexact_impl

if (charge_layout.is_physically_valid())
{
charge_distribution_surface<Lyt> charge_lyt_copy{charge_layout};
charge_lyt_copy.recompute_system_energy();
charge_distribution_surface<Lyt> charge_lyt_copy{charge_lyt};

for (const auto& cell : preassigned_negative_sidbs)
{
charge_lyt_copy.add_sidb(cell, sidb_charge_state::NEGATIVE);
}

if constexpr (has_get_sidb_defect_v<Lyt>)
{
for (const auto& [cell, defect] : real_placed_defects)
{
charge_lyt_copy.assign_sidb_defect(cell, defect);
}
}
charge_layout.foreach_cell(
[&charge_lyt_copy, &charge_layout](const auto& c)
{ charge_lyt_copy.assign_charge_state(c, charge_layout.get_charge_state(c)); });

charge_lyt_copy.update_after_charge_change();
charge_lyt_copy.recompute_system_energy();
result.charge_distributions.push_back(charge_lyt_copy);
}

@@ -465,23 +440,15 @@ class quickexact_impl
{
if (charge_layout.is_physically_valid())
{
charge_distribution_surface<Lyt> charge_lyt_copy{charge_layout};
charge_lyt_copy.recompute_system_energy();
charge_distribution_surface<Lyt> charge_lyt_copy{charge_lyt};

// The pre-assigned negatively-charged SiDBs are added to the final layout.
for (const auto& cell : preassigned_negative_sidbs)
{
charge_lyt_copy.add_sidb(cell, sidb_charge_state::NEGATIVE);
}

if constexpr (has_get_sidb_defect_v<Lyt>)
{
for (const auto& [cell, defect] : real_placed_defects)
{
charge_lyt_copy.assign_sidb_defect(cell, defect);
}
}
charge_layout.foreach_cell(
[&charge_lyt_copy, &charge_layout](const auto& c)
{ charge_lyt_copy.assign_charge_state(c, charge_layout.get_charge_state(c)); });

charge_lyt_copy.update_after_charge_change();
charge_lyt_copy.recompute_system_energy();
charge_lyt_copy.charge_distribution_to_index_general();
result.charge_distributions.push_back(charge_lyt_copy);
}

@@ -492,21 +459,14 @@ class quickexact_impl

if (charge_layout.is_physically_valid())
{
charge_distribution_surface<Lyt> charge_lyt_copy{charge_layout};
charge_distribution_surface<Lyt> charge_lyt_copy{charge_lyt};

for (const auto& cell : preassigned_negative_sidbs)
{
charge_lyt_copy.add_sidb(cell, sidb_charge_state::NEGATIVE);
}

if constexpr (has_get_sidb_defect_v<Lyt>)
{
for (const auto& [cell, defect] : real_placed_defects)
{
charge_lyt_copy.assign_sidb_defect(cell, defect);
}
}
charge_layout.foreach_cell([&charge_lyt_copy, &charge_layout](const auto& c)
{ charge_lyt_copy.assign_charge_state(c, charge_layout.get_charge_state(c)); });

charge_lyt_copy.update_after_charge_change();
charge_lyt_copy.recompute_system_energy();
charge_lyt_copy.charge_distribution_to_index_general();
result.charge_distributions.push_back(charge_lyt_copy);
}

30 changes: 25 additions & 5 deletions include/fiction/technology/charge_distribution_surface.hpp
Original file line number Diff line number Diff line change
@@ -1282,11 +1282,14 @@ class charge_distribution_surface<Lyt, false> : public Lyt
void assign_global_external_potential(const double potential_value,
dependent_cell_mode dependent_cell = dependent_cell_mode::FIXED) noexcept
{
this->foreach_cell(
[this, &potential_value](const auto& c) {
strg->local_external_pot.insert({c, potential_value});
});
this->update_after_charge_change(dependent_cell);
if (potential_value != 0.0)
{
this->foreach_cell(
[this, &potential_value](const auto& c) {
strg->local_external_pot.insert({c, potential_value});
});
this->update_after_charge_change(dependent_cell);
}
}
/**
* This function determines if given layout has to be simulated with three states since positively charged SiDBs can
@@ -1769,6 +1772,23 @@ class charge_distribution_surface<Lyt, false> : public Lyt
{
strg->cell_charge.push_back(charge);
strg->sidb_order.push_back(c);

// sort sidbs by the relation given by the coordinates and sort charge vector accordingly
std::vector<std::pair<typename Lyt::cell, sidb_charge_state>> combined_vector{};
combined_vector.reserve(strg->cell_charge.size());

for (size_t i = 0; i < strg->sidb_order.size(); i++)
{
combined_vector.emplace_back(strg->sidb_order[i], strg->cell_charge[i]);
}

std::sort(combined_vector.begin(), combined_vector.end());

for (size_t i = 0; i < combined_vector.size(); i++)
{
strg->sidb_order[i] = combined_vector[i].first;
strg->cell_charge[i] = combined_vector[i].second;
}
}

private:
2 changes: 1 addition & 1 deletion libs/Catch2
Submodule Catch2 updated 31 files
+1 −1 docs/cmake-integration.md
+4 −0 src/CMakeLists.txt
+1 −1 src/catch2/benchmark/catch_optimizer.hpp
+1 −0 src/catch2/catch_all.hpp
+115 −0 src/catch2/internal/catch_jsonwriter.cpp
+139 −0 src/catch2/internal/catch_jsonwriter.hpp
+4 −1 src/catch2/internal/catch_reporter_registry.cpp
+4 −0 src/catch2/meson.build
+395 −0 src/catch2/reporters/catch_reporter_json.cpp
+95 −0 src/catch2/reporters/catch_reporter_json.hpp
+1 −0 src/catch2/reporters/catch_reporters_all.hpp
+5 −1 tests/CMakeLists.txt
+2 −0 tests/SelfTest/Baselines/automake.sw.approved.txt
+2 −0 tests/SelfTest/Baselines/automake.sw.multi.approved.txt
+141 −2 tests/SelfTest/Baselines/compact.sw.approved.txt
+141 −2 tests/SelfTest/Baselines/compact.sw.multi.approved.txt
+2 −2 tests/SelfTest/Baselines/console.std.approved.txt
+410 −2 tests/SelfTest/Baselines/console.sw.approved.txt
+410 −2 tests/SelfTest/Baselines/console.sw.multi.approved.txt
+22 −1 tests/SelfTest/Baselines/junit.sw.approved.txt
+22 −1 tests/SelfTest/Baselines/junit.sw.multi.approved.txt
+23 −0 tests/SelfTest/Baselines/sonarqube.sw.approved.txt
+23 −0 tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt
+49 −1 tests/SelfTest/Baselines/tap.sw.approved.txt
+49 −1 tests/SelfTest/Baselines/tap.sw.multi.approved.txt
+4 −0 tests/SelfTest/Baselines/teamcity.sw.approved.txt
+4 −0 tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt
+387 −2 tests/SelfTest/Baselines/xml.sw.approved.txt
+387 −2 tests/SelfTest/Baselines/xml.sw.multi.approved.txt
+152 −0 tests/SelfTest/IntrospectiveTests/Json.tests.cpp
+3 −1 tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp
2 changes: 1 addition & 1 deletion libs/parallel-hashmap
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
//
// Created by Jan Drewniok on 02.11.23.
//

#include <catch2/catch_template_test_macros.hpp>
#include <catch2/matchers/catch_matchers_floating_point.hpp>

#include <fiction/algorithms/simulation/sidb/assess_physical_population_stability.hpp>
#include <fiction/algorithms/simulation/sidb/sidb_simulation_parameters.hpp>
#include <fiction/layouts/cell_level_layout.hpp>
#include <fiction/technology/cell_technologies.hpp>
#include <fiction/types.hpp>

using namespace fiction;

using layout = sidb_cell_clk_lyt_siqad;

TEST_CASE("Single SiDB", "[assess-physical-population-stability]")
{
layout lyt{};
lyt.assign_cell_type({1, 1, 0}, sidb_technology::cell_type::NORMAL);

SECTION("Precision of distance_corresponding_to_potential is two")
{
const auto params = assess_physical_population_stability_params{sidb_simulation_parameters{2, -0.29}, 2};
const auto result = assess_physical_population_stability(lyt, params);
REQUIRE(result.size() == 1);
const auto& population_stability_detail = result[0];
CHECK(population_stability_detail.critical_cell == siqad::coord_t{1, 1, 0});
CHECK(population_stability_detail.transition_from_to == transition_type::NEGATIVE_TO_NEUTRAL);
CHECK(population_stability_detail.minimum_potential_difference_to_transition == 0.29);
REQUIRE_THAT(population_stability_detail.distance_corresponding_to_potential,
Catch::Matchers::WithinAbs(0.77, 1e-5));
}

SECTION("Precision of distance_corresponding_to_potential is three")
{
const auto params = assess_physical_population_stability_params{sidb_simulation_parameters{2, -0.29}, 3};
const auto result = assess_physical_population_stability(lyt, params);
REQUIRE(result.size() == 1);
const auto& population_stability_detail = result[0];
CHECK(population_stability_detail.critical_cell == siqad::coord_t{1, 1, 0});
CHECK(population_stability_detail.transition_from_to == transition_type::NEGATIVE_TO_NEUTRAL);
CHECK(population_stability_detail.minimum_potential_difference_to_transition == 0.29);
REQUIRE_THAT(population_stability_detail.distance_corresponding_to_potential,
Catch::Matchers::WithinAbs(0.762, 1e-5));
}
}

TEST_CASE("Three SiDBs with positive charge states", "[assess-physical-population-stability]")
{
layout lyt{};
const auto params = assess_physical_population_stability_params{};
lyt.assign_cell_type({1, 1, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({1, 1, 1}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({2, 1, 0}, sidb_technology::cell_type::NORMAL);

const auto result = assess_physical_population_stability(lyt, params);
REQUIRE(result.size() == 3);

SECTION("Check correct energy order")
{
CHECK(result[0].system_energy < result[1].system_energy);
CHECK(result[1].system_energy < result[2].system_energy);
}

SECTION("Ground state")
{
const auto& population_stability_detail = result[0];
CHECK(population_stability_detail.critical_cell == siqad::coord_t{2, 1, 0});
CHECK(population_stability_detail.transition_from_to == transition_type::NEGATIVE_TO_NEUTRAL);
CHECK(population_stability_detail.minimum_potential_difference_to_transition < 0.43);
REQUIRE_THAT(population_stability_detail.distance_corresponding_to_potential,
Catch::Matchers::WithinAbs(0.56, 1e-5));
}
SECTION("1st excited state")
{
const auto& population_stability_detail = result[1];
CHECK(population_stability_detail.critical_cell == siqad::coord_t{2, 1, 0});
CHECK(population_stability_detail.transition_from_to == transition_type::NEGATIVE_TO_NEUTRAL);
CHECK(population_stability_detail.minimum_potential_difference_to_transition < 0.23);
REQUIRE_THAT(population_stability_detail.distance_corresponding_to_potential,
Catch::Matchers::WithinAbs(0.94, 1e-5));
}

SECTION("2nd excited state")
{
const auto& population_stability_detail = result[2];
CHECK(population_stability_detail.critical_cell == siqad::coord_t{1, 1, 1});
CHECK(population_stability_detail.transition_from_to == transition_type::NEUTRAL_TO_NEGATIVE);
CHECK(population_stability_detail.minimum_potential_difference_to_transition < 0.21);
REQUIRE_THAT(population_stability_detail.distance_corresponding_to_potential,
Catch::Matchers::WithinAbs(1.01, 1e-5));
}
}

TEST_CASE("Bestagon AND gate", "[assess-physical-population-stability]")
{
layout lyt{};
const auto params = assess_physical_population_stability_params{};
lyt.assign_cell_type({36, 1, 0}, sidb_technology::cell_type::INPUT);
lyt.assign_cell_type({2, 1, 0}, sidb_technology::cell_type::INPUT);

lyt.assign_cell_type({38, 0, 0}, sidb_technology::cell_type::INPUT);
lyt.assign_cell_type({0, 0, 0}, sidb_technology::cell_type::INPUT);

lyt.assign_cell_type({23, 9, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({18, 11, 1}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({18, 9, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({19, 8, 0}, sidb_technology::cell_type::NORMAL);

lyt.assign_cell_type({20, 14, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({19, 13, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({26, 16, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({24, 15, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({32, 2, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({30, 3, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({26, 4, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({24, 5, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({12, 4, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({14, 5, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({6, 2, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({8, 3, 0}, sidb_technology::cell_type::NORMAL);

lyt.assign_cell_type({32, 18, 0}, sidb_technology::cell_type::OUTPUT);
lyt.assign_cell_type({30, 17, 0}, sidb_technology::cell_type::OUTPUT);

lyt.assign_cell_type({36, 19, 0}, sidb_technology::cell_type::NORMAL);

SECTION("no input specified")
{
const auto result = assess_physical_population_stability(lyt, params);
REQUIRE(result.size() == 8);
const auto& population_stability_detail = result[0];
CHECK(population_stability_detail.critical_cell == siqad::coord_t{2, 1, 0});
CHECK(population_stability_detail.transition_from_to == transition_type::NEUTRAL_TO_NEGATIVE);
CHECK(population_stability_detail.minimum_potential_difference_to_transition < 0.021);
REQUIRE_THAT(population_stability_detail.distance_corresponding_to_potential,
Catch::Matchers::WithinAbs(4.79, 1e-5));
}

SECTION("input 00")
{
lyt.assign_cell_type({36, 1, 0}, sidb_technology::cell_type::EMPTY);
lyt.assign_cell_type({2, 1, 0}, sidb_technology::cell_type::EMPTY);
const auto result = assess_physical_population_stability(lyt, params);
REQUIRE(result.size() == 2);
const auto& population_stability_detail = result[0];
CHECK(population_stability_detail.critical_cell == siqad::coord_t{14, 5, 0});
CHECK(population_stability_detail.transition_from_to == transition_type::NEUTRAL_TO_NEGATIVE);
CHECK(population_stability_detail.minimum_potential_difference_to_transition < 0.026);
REQUIRE_THAT(population_stability_detail.distance_corresponding_to_potential,
Catch::Matchers::WithinAbs(4.32, 1e-5));
}

SECTION("input 01")
{
lyt.assign_cell_type({36, 1, 0}, sidb_technology::cell_type::EMPTY);
lyt.assign_cell_type({0, 0, 0}, sidb_technology::cell_type::EMPTY);

const auto result = assess_physical_population_stability(lyt, params);
REQUIRE(result.size() == 4);
const auto& population_stability_detail = result[0];
CHECK(population_stability_detail.critical_cell == siqad::coord_t{32, 18, 0});
CHECK(population_stability_detail.transition_from_to == transition_type::NEUTRAL_TO_NEGATIVE);
CHECK(population_stability_detail.minimum_potential_difference_to_transition < 0.041);
REQUIRE_THAT(population_stability_detail.distance_corresponding_to_potential,
Catch::Matchers::WithinAbs(3.3, 1e-5));
}

SECTION("input 10")
{
lyt.assign_cell_type({38, 0, 0}, sidb_technology::cell_type::EMPTY);
lyt.assign_cell_type({0, 0, 0}, sidb_technology::cell_type::EMPTY);

const auto result = assess_physical_population_stability(lyt, params);
REQUIRE(result.size() == 8);
const auto& population_stability_detail = result[0];
CHECK(population_stability_detail.critical_cell == siqad::coord_t{19, 8, 0});
CHECK(population_stability_detail.transition_from_to == transition_type::NEUTRAL_TO_NEGATIVE);
CHECK(population_stability_detail.minimum_potential_difference_to_transition < 0.02);
REQUIRE_THAT(population_stability_detail.distance_corresponding_to_potential,
Catch::Matchers::WithinAbs(4.87, 1e-5));
}

SECTION("input 11")
{
lyt.assign_cell_type({36, 1, 0}, sidb_technology::cell_type::EMPTY);
lyt.assign_cell_type({2, 1, 0}, sidb_technology::cell_type::EMPTY);

const auto result = assess_physical_population_stability(lyt, params);
REQUIRE(result.size() == 2);
const auto& population_stability_detail = result[0];
CHECK(population_stability_detail.critical_cell == siqad::coord_t{14, 5, 0});
CHECK(population_stability_detail.transition_from_to == transition_type::NEUTRAL_TO_NEGATIVE);
CHECK(population_stability_detail.minimum_potential_difference_to_transition < 0.026);
REQUIRE_THAT(population_stability_detail.distance_corresponding_to_potential,
Catch::Matchers::WithinAbs(4.32, 1e-5));
}
}

TEST_CASE("Bestagon CROSSING gate input 11", "[assess-physical-population-stability]")
{
layout lyt{};
const auto params = assess_physical_population_stability_params{};
lyt.assign_cell_type({36, 1, 0}, sidb_technology::cell_type::INPUT);
lyt.assign_cell_type({2, 1, 0}, sidb_technology::cell_type::INPUT);

lyt.assign_cell_type({6, 2, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({20, 12, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({8, 3, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({14, 5, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({14, 11, 1}, sidb_technology::cell_type::NORMAL);

lyt.assign_cell_type({12, 4, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({14, 15, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({26, 4, 0}, sidb_technology::cell_type::NORMAL);

lyt.assign_cell_type({14, 9, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({24, 15, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({12, 16, 0}, sidb_technology::cell_type::NORMAL);

lyt.assign_cell_type({18, 9, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({26, 16, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({24, 13, 1}, sidb_technology::cell_type::NORMAL);

lyt.assign_cell_type({24, 5, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({30, 3, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({16, 13, 1}, sidb_technology::cell_type::NORMAL);

lyt.assign_cell_type({32, 2, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({20, 8, 0}, sidb_technology::cell_type::NORMAL);

lyt.assign_cell_type({30, 17, 0}, sidb_technology::cell_type::OUTPUT);
lyt.assign_cell_type({6, 18, 0}, sidb_technology::cell_type::OUTPUT);

lyt.assign_cell_type({32, 18, 0}, sidb_technology::cell_type::OUTPUT);
lyt.assign_cell_type({8, 17, 0}, sidb_technology::cell_type::OUTPUT);

lyt.assign_cell_type({2, 19, 0}, sidb_technology::cell_type::NORMAL);
lyt.assign_cell_type({36, 19, 0}, sidb_technology::cell_type::NORMAL);

CHECK(lyt.num_cells() == 27);

const auto result = assess_physical_population_stability(lyt, params);
REQUIRE(result.size() == 20);
const auto& population_stability_detail = result[0];
CHECK(population_stability_detail.critical_cell == siqad::coord_t{14, 9, 0});
CHECK(population_stability_detail.transition_from_to == transition_type::NEUTRAL_TO_NEGATIVE);
CHECK(population_stability_detail.minimum_potential_difference_to_transition < 0.01);
REQUIRE_THAT(population_stability_detail.distance_corresponding_to_potential,
Catch::Matchers::WithinAbs(6.88, 1e-5));
}
78 changes: 78 additions & 0 deletions test/algorithms/simulation/sidb/convert_potential_to_distance.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//
// Created by Jan Drewniok on 10.11.23.
//

#include <catch2/catch_template_test_macros.hpp>
#include <catch2/matchers/catch_matchers_floating_point.hpp>

#include <fiction/algorithms/simulation/sidb/convert_potential_to_distance.hpp>
#include <fiction/algorithms/simulation/sidb/sidb_simulation_parameters.hpp>

#include <limits>

using namespace fiction;

TEST_CASE("Conversion of potential to distance", "[convert-potential-to-distance]")
{
auto params = sidb_simulation_parameters{};

SECTION("Valid conversion with default parameters")
{
uint64_t const precision = 1;
const double potential_value = 5.0;
const double expected_distance = 0.1;
REQUIRE_THAT(convert_potential_to_distance(potential_value, params, precision),
Catch::Matchers::WithinAbs(expected_distance, 1e-5));
}

SECTION("Valid conversion with custom parameters, precision is 1")
{
params.epsilon_r = 2.0;
params.lambda_tf = 1.0;
const uint64_t precision = 1;
const double potential_value = 0.01;
const double expected_distance = 3.2;
REQUIRE_THAT(convert_potential_to_distance(potential_value, params, precision),
Catch::Matchers::WithinAbs(expected_distance, 1e-5));
}

SECTION("Valid conversion with custom parameters, precision is 2")
{
params.epsilon_r = 2.0;
params.lambda_tf = 1.0;
const uint64_t precision = 2;
const double potential_value = 0.01;
const double expected_distance = 3.14;
REQUIRE_THAT(convert_potential_to_distance(potential_value, params, precision),
Catch::Matchers::WithinAbs(expected_distance, 1e-5));
}

SECTION("Valid conversion with custom parameters, precision is 3")
{
params.epsilon_r = 2.0;
params.lambda_tf = 1.0;
const uint64_t precision = 3;
const double potential_value = 0.01;
const double expected_distance = 3.135;
REQUIRE_THAT(convert_potential_to_distance(potential_value, params, precision),
Catch::Matchers::WithinAbs(expected_distance, 1e-5));
}

SECTION("Valid conversion with custom parameters, precision is 0")
{
const uint64_t precision = 0;
const double potential_value = 0.03;
const double expected_distance = 4;
REQUIRE_THAT(convert_potential_to_distance(potential_value, params, precision),
Catch::Matchers::WithinAbs(expected_distance, 1e-5));
}

SECTION("Conversion with infinite potential")
{
const uint64_t precision = 3;
const double potential_value = std::numeric_limits<double>::infinity();
const double expected_distance = 0.001;
REQUIRE_THAT(convert_potential_to_distance(potential_value, params, precision),
Catch::Matchers::WithinAbs(expected_distance, 1e-5));
}
}
84 changes: 83 additions & 1 deletion test/algorithms/simulation/sidb/operational_domain.cpp
Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@ TEST_CASE("BDL wire operational domain computation", "[operational-domain]")

operational_domain_stats op_domain_stats{};

SECTION("operational area")
SECTION("operational area, same number of steps in x- and y-direction")
{
op_domain_params.x_min = 5.1;
op_domain_params.x_max = 6.1;
@@ -158,6 +158,88 @@ TEST_CASE("BDL wire operational domain computation", "[operational-domain]")
}
}

SECTION("operational area, different number of steps in x- and y-direction")
{
op_domain_params.x_min = 5.1;
op_domain_params.x_max = 6.1;
op_domain_params.x_step = 0.1;

op_domain_params.y_min = 4.5;
op_domain_params.y_max = 5.0;
op_domain_params.y_step = 0.1;

SECTION("grid_search")
{
const auto op_domain = operational_domain_grid_search(lyt, std::vector<tt>{create_id_tt()},
op_domain_params, &op_domain_stats);

// check if the operational domain has the correct size (10 steps in each dimension)
CHECK(op_domain.operational_values.size() == 50);

// for the selected range, all samples should be within the parameters and operational
check_op_domain_params_and_operational_status(op_domain, op_domain_params, operational_status::OPERATIONAL);

CHECK(mockturtle::to_seconds(op_domain_stats.time_total) > 0.0);
CHECK(op_domain_stats.num_simulator_invocations == 100);
CHECK(op_domain_stats.num_evaluated_parameter_combinations == 50);
CHECK(op_domain_stats.num_operational_parameter_combinations == 50);
CHECK(op_domain_stats.num_non_operational_parameter_combinations == 0);
}
SECTION("random_sampling")
{
const auto op_domain = operational_domain_random_sampling(lyt, std::vector<tt>{create_id_tt()}, 100,
op_domain_params, &op_domain_stats);

// check if the operational domain has the correct size
CHECK(op_domain.operational_values.size() <= 100);

// for the selected range, all samples should be within the parameters and operational
check_op_domain_params_and_operational_status(op_domain, op_domain_params, operational_status::OPERATIONAL);

CHECK(mockturtle::to_seconds(op_domain_stats.time_total) > 0.0);
CHECK(op_domain_stats.num_simulator_invocations <= 200);
CHECK(op_domain_stats.num_evaluated_parameter_combinations <= 100);
CHECK(op_domain_stats.num_evaluated_parameter_combinations > 0);
CHECK(op_domain_stats.num_operational_parameter_combinations <= 100);
CHECK(op_domain_stats.num_non_operational_parameter_combinations == 0);
}

SECTION("flood_fill")
{
const auto op_domain = operational_domain_flood_fill(lyt, std::vector<tt>{create_id_tt()}, 1,
op_domain_params, &op_domain_stats);

// check if the operational domain has the correct size
CHECK(op_domain.operational_values.size() == 50);

// for the selected range, all samples should be within the parameters and operational
check_op_domain_params_and_operational_status(op_domain, op_domain_params, operational_status::OPERATIONAL);

CHECK(mockturtle::to_seconds(op_domain_stats.time_total) > 0.0);
CHECK(op_domain_stats.num_simulator_invocations == 100);
CHECK(op_domain_stats.num_evaluated_parameter_combinations == 50);
CHECK(op_domain_stats.num_operational_parameter_combinations == 50);
CHECK(op_domain_stats.num_non_operational_parameter_combinations == 0);
}
SECTION("contour_tracing")
{
const auto op_domain = operational_domain_contour_tracing(lyt, std::vector<tt>{create_id_tt()}, 1,
op_domain_params, &op_domain_stats);

// check if the operational domain has the correct size
CHECK(op_domain.operational_values.size() <= 50);

// for the selected range, all samples should be within the parameters and operational
check_op_domain_params_and_operational_status(op_domain, op_domain_params, operational_status::OPERATIONAL);

CHECK(mockturtle::to_seconds(op_domain_stats.time_total) > 0.0);
CHECK(op_domain_stats.num_simulator_invocations <= 100);
CHECK(op_domain_stats.num_evaluated_parameter_combinations <= 50);
CHECK(op_domain_stats.num_operational_parameter_combinations <= 50);
CHECK(op_domain_stats.num_non_operational_parameter_combinations == 0);
}
}

SECTION("non-operational area")
{
op_domain_params.x_min = 2.5;

0 comments on commit de9dfd8

Please sign in to comment.