Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9a090ce
first attempt at a tariff region. nominally it works
dean-krueger Aug 6, 2025
1afed45
fixed products to look like materials
dean-krueger Aug 6, 2025
f223a9e
removed reference to old friend_regions and enemy_regions vectors
dean-krueger Aug 6, 2025
dcfba68
changelog
dean-krueger Aug 6, 2025
f5d7b56
removed friend/enemy designation and just lumped everything into a si…
dean-krueger Aug 10, 2025
7e84754
made documentation in tariffs entry more clear
dean-krueger Aug 10, 2025
5c6bf1e
changed tariff to adjustment since they can be positive or negative
dean-krueger Aug 10, 2025
9fc9c9d
reworded doc in pragma for adjustments
dean-krueger Aug 19, 2025
7583c75
removed leftover function signatures from an earlier implementation
dean-krueger Aug 19, 2025
0b7a179
templated Adjust<matl/product>bid functions to reduce code duplication
dean-krueger Aug 19, 2025
e69e482
rewrote if (var != nullptr) to if (var)
dean-krueger Aug 19, 2025
ce88ca1
changed variable pref in header to pref_multiplier to better reflect …
dean-krueger Aug 27, 2025
3545250
simplified logic using new cyclus functions from #1914
dean-krueger Aug 27, 2025
486f288
sped up region lookups with new cyclus functions GetRegionList and Ge…
dean-krueger Aug 30, 2025
0776f75
added summary table
dean-krueger Aug 30, 2025
d6b2f7a
cleaned up and simplified code greatly
dean-krueger Aug 30, 2025
7d1c71f
changed some variable names to make them easier to understand, made a…
dean-krueger Nov 12, 2025
ce232f5
refactored entirely to use new datatype from cyclus/cyclus#1922. Stil…
dean-krueger Nov 17, 2025
da1addc
added a check to the config recorder, moved template out of class def…
dean-krueger Nov 17, 2025
e34d274
Merge branch 'main' into tariff-region
dean-krueger Nov 17, 2025
eeb2873
added aliases to the xml schema to let users put in readable names fo…
dean-krueger Nov 18, 2025
bdaee88
Merge branch 'tariff-region' of github.com:dean-krueger/cycamore into…
dean-krueger Nov 18, 2025
e6d6fe3
added all options to the example file
dean-krueger Nov 18, 2025
9cf210d
updated example file to include dummy commodity since we made it so t…
dean-krueger Dec 4, 2025
db1d099
changed to . Went with adjustment instead of tariff since it can go …
dean-krueger Dec 4, 2025
72db1b8
made it so that we should have good coverage for nested tariff region…
dean-krueger Dec 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Since last release
======================

**Added:**
* Added TariffRegion Region (#661)
* Added Conversion Facility (#657)
* Replaced manual matl_buy/sell_policy code in storage with code injection (#639)
* Added package parameter to storage (#603, #612, #616)
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ USE_CYCLUS("cycamore" "manager_inst")

USE_CYCLUS("cycamore" "growth_region")

USE_CYCLUS("cycamore" "tariff_region")

USE_CYCLUS("cycamore" "storage")

INSTALL_CYCLUS_MODULE("cycamore" "" "NONE")
Expand Down
88 changes: 88 additions & 0 deletions src/tariff_region.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#include "tariff_region.h"

namespace cycamore {

TariffRegion::TariffRegion(cyclus::Context* ctx)
: cyclus::Region(ctx) {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we check that we have the same number of entries in the two vectors of input? Is that typical of other inputs that we expect to be coordinated like this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems wise.


TariffRegion::~TariffRegion() {}

void TariffRegion::EnterNotify() {
Region::EnterNotify();

}

void TariffRegion::AdjustMatlPrefs(cyclus::PrefMap<cyclus::Material>::type& prefs) {
for (auto& req_pair : prefs) {

// Iterate over the bids in the request portfolio
for (auto& bid_pair : req_pair.second) {

// Get the bid
cyclus::Bid<cyclus::Material>* bid = bid_pair.first;

// Get the supplier - use manager() to get the Agent* from the Trader*
cyclus::Agent* supplier = bid->bidder()->manager();

// Traverse up the hierarchy to get the supplier's region
cyclus::Region* supplier_region = nullptr;
cyclus::Agent* current = supplier;
while (current != nullptr) {
supplier_region = dynamic_cast<cyclus::Region*>(current);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check Agent->kind() for "Region"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did some poking into this, and my new understanding is that if we were to do something like if (current->kind() == "Region") { we'd need to then dynamic_cast to region anyway to return the pointer to the region anyway (which is what we want in the end), so checking that way would be redundant. I'm working on converting this to a facility function and then using that in tariff_region now, so maybe it'll make sense in that context?

if (supplier_region != nullptr) {
break; // Found a region
}
current = current->parent();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a useful functionality to have somewhere in Cyclus. In most cases, this should just be parent()->parent(), but your approach allows for more complex hierarchies in the future, e.g. subfacilities, etc.

See Agent::AncestorOf(), AgentDescendentOf(), and Agent::InFamilyTree()...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I THINK Agent::AncestorOf(), etc would be really nice if we could somehow just jump to the Region, but because (at least I don't think) you can't access the list of all agents (it's a private member that RIF's don't have access to), it's hard to do something like is "this Agent" an ancestor of "that Agent". At least in a Region. I agree, though, that those functions you mentioned below (FindRegionByName) would be a nice function in Cyclus, where I think it would be possible to do something like that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try implementing some kind of GetRegion() (and GetInstitution()) for each Facility


// If the supplier is in the region list, apply the appropriate adjustment
auto it = std::find(region_names.begin(), region_names.end(),
supplier_region->prototype());
if (it != region_names.end()) {
double cost_multiplier = 1.0 + adjustments[it - region_names.begin()];
bid_pair.second *= cost_multiplier > 0.0 ? 1.0 / cost_multiplier : std::numeric_limits<double>::infinity();
}
}
}
}

void TariffRegion::AdjustProductPrefs(cyclus::PrefMap<cyclus::Product>::type& prefs) {

// Iterate over the preferences
for (auto& req_pair : prefs) {
// Iterate over the bids in the request portfolio
for (auto& bid_pair : req_pair.second) {

// Get the bid
cyclus::Bid<cyclus::Product>* bid = bid_pair.first;

// Get the supplier - use manager() to get the Agent* from the Trader*
cyclus::Agent* supplier = bid->bidder()->manager();

// Traverse up the hierarchy to get the supplier's region
cyclus::Region* supplier_region = nullptr;
cyclus::Agent* current = supplier;
while (current != nullptr) {
supplier_region = dynamic_cast<cyclus::Region*>(current);
if (supplier_region != nullptr) {
break; // Found a region
}
current = current->parent();
}

// If the supplier is in the region list, apply the appropriate adjustment
auto it = std::find(region_names.begin(), region_names.end(),
supplier_region->prototype());
if (it != region_names.end()) {
double cost_multiplier = 1.0 + adjustments[it - region_names.begin()];
bid_pair.second *= cost_multiplier > 0.0 ? 1.0 / cost_multiplier : std::numeric_limits<double>::infinity();
}
}
}
}

extern "C" cyclus::Agent* ConstructTariffRegion(cyclus::Context* ctx) {
return new TariffRegion(ctx);
}

} // namespace cycamore
43 changes: 43 additions & 0 deletions src/tariff_region.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef CYCAMORE_SRC_TARIFF_REGION_H_
#define CYCAMORE_SRC_TARIFF_REGION_H_

#include "cyclus.h"
#include <string>

namespace cycamore {

class TariffRegion : public cyclus::Region {
public:
TariffRegion(cyclus::Context* ctx);
virtual ~TariffRegion();

virtual void EnterNotify();
virtual void AdjustMatlPrefs(cyclus::PrefMap<cyclus::Material>::type& prefs);
virtual void AdjustProductPrefs(cyclus::PrefMap<cyclus::Product>::type& prefs);

#pragma cyclus

private:
cyclus::Region* FindRegionByName(const std::string& name);
cyclus::Region* FindRegionInHierarchy(cyclus::Agent* agent, const std::string& name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see these implemented anywhere... surprised that it builds....

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are probably better implemented in cyclus/cyclus anyway

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, they were leftovers from an old implementation route I was going down before I decided to switch gears. I got rid of them (though I do think a FindAgentByName(std::string name) function in Cyclus/Cyclus would be pretty nice...)


#pragma cyclus var { \
"default": [], \
"doc": "List of regions that will have a trade adjustment " \
"(subsidy)" \
}
std::vector<std::string> region_names;

#pragma cyclus var { \
"default": [], \
"doc": "Adjustments (1+val) to apply to trades from affected " \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"doc": "Adjustments (1+val) to apply to trades from affected " \
"doc": "Adjustments (multiply by (1+val)) to apply to cost of trades from affected " \

"regions (percent as decimal, must be in same order as " \
"region_names). Positive values are tariffs, negative values are subsidies." \
}
std::vector<double> adjustments;

};

} // namespace cycamore

#endif // CYCAMORE_SRC_TARIFF_REGION_H_
Loading