31#include "common/implicit_conduction.hlsli"
32#include "common/multires_conduction.hlsli"
37using namespace bicameral::multires;
47 constexpr uint32_t
NOT_IN_SYSTEM = std::numeric_limits<uint32_t>::max();
51 std::vector<ImplicitCell>
cells;
52 std::vector<ImplicitFace>
faces;
59 std::vector<uint32_t>
ids;
64 const MrBlock& block = nest.
blocks[slot];
65 const bool frozenNow = !frozen.empty() && frozen[slot] != 0;
67 return slot < nest.
capacity.
worldBlocks && block.kind == MR_BLOCK_REAL && !MrIsUniform(block) && !frozenNow;
73 const size_t address = (
size_t{slot} * MR_BLOCK_CELLS) + index;
75 return system.
ids[address];
77 const MrThermal thermal = thermals.
At(slot, index);
78 if (thermal.capacityLimit == 0)
82 const MrBlock& block = nest.
blocks[slot];
84 cell.
level = block.level;
85 cell.
x = block.originX +
static_cast<int64_t
>(MrCellX(index));
86 cell.
y = block.originY +
static_cast<int64_t
>(MrCellY(index));
87 cell.
z = block.originZ +
static_cast<int64_t
>(MrCellZ(index));
88 cell.
heatCapacity = thermal.capacityLimit << IM_ENERGY_BITS_PER_LEVEL;
90 cell.
startTemperature = int64_t{thermal.temperature} << IM_TEMPERATURE_SHIFT;
94 const auto id =
static_cast<uint32_t
>(system.
cells.size());
95 system.
ids[address] = id;
96 system.
cells.push_back(cell);
97 system.
slots.push_back(slot);
98 system.
indices.push_back(index);
108 return ImWideShiftLeft(ImWide(conductance * HC_LIMIT_PER_CONDUCTANCE),
109 2 *
static_cast<uint32_t
>(fine.
level));
114 std::span<const uint8_t> frozen, uint32_t
id) {
115 const CpuTree tree{.nest = &nest};
116 const uint32_t slot = system.
slots[id];
117 const uint32_t index = system.
indices[id];
118 const MrBlock block = nest.
blocks[slot];
119 for (uint32_t face = 0; face < MR_FACES; ++face) {
120 const MrFaceNeighbor neighbor = MrFindFaceNeighbor(tree, slot, block, index, face,
122 if (neighbor.kind != MR_NEIGHBOR_SAME && neighbor.kind != MR_NEIGHBOR_COARSER)
125 if (!
CanJoin(nest, frozen, neighbor.slot))
128 const uint32_t other =
AddCell(system, nest, thermals, neighbor.slot, neighbor.index);
129 if (other ==
NOT_IN_SYSTEM || (neighbor.kind == MR_NEIGHBOR_SAME && other <
id))
132 const uint32_t gap = neighbor.kind == MR_NEIGHBOR_SAME ? 0 : neighbor.gap;
133 system.
faces.push_back({.fine = id,
142 std::span<const uint8_t> implicitBlocks) {
149 for (uint32_t index = 0; index < MR_BLOCK_CELLS; ++index) {
150 if (MrIsSteppedCell(nest.
blocks[slot], index))
151 AddCell(system, nest, thermals, slot, index);
155 const auto unknowns =
static_cast<uint32_t
>(system.
cells.size());
156 for (uint32_t
id = 0;
id < unknowns; ++id)
166 for (
size_t node = 0; node + 1 < level.
rowStarts.size(); ++node)
176 auto copy = std::make_shared<MultiresNest>(nest);
177 copy->captureImplicitNest =
false;
178 copy->implicitFrozen.clear();
179 copy->implicitGrid = {};
187 for (uint32_t index = 0; index < MR_BLOCK_CELLS; ++index) {
188 if (MrIsSteppedCell(nest.
blocks[slot], index) && thermals.
At(slot, index).capacityLimit != 0)
207 namespace nest_detail {
210 const MrBlock& block = nest.
blocks[slot];
219 return slot < implicitBlocks.size() && implicitBlocks[slot] != 0;
224 std::vector<uint8_t> marks(nest.
blocks.size(), 0);
232 uint64_t unknowns = 0;
238 const uint32_t count = CountUnknowns(nest, thermals, slot);
240 cells += ImBlockCellBound(count);
254 std::span<MrEnergyDelta> deltas) {
260 ImplicitSystem system = MakeSystem(nest, thermals, frozen, implicitBlocks);
261 if (system.faces.empty())
265 CaptureNest(nest, frozen);
276 RecordLevels(nest, grid);
277 for (
size_t id = 0;
id < grid.
cells.size(); ++id) {
279 const MrEnergyDelta change = {.whole = cell.
energy - system.startEnergies[id],
281 if (MrEnergyDeltaIsZero(change))
284 const MrBlock& block = nest.
blocks[system.slots[id]];
285 MrEnergyDelta& entry = deltas[
PageCellAddress(nest, block.page, system.indices[
id])];
286 entry = MrAddEnergyDelta(entry, change);
multires::MrThermal At(uint32_t slot, uint32_t index)
void AddCellFaces(ImplicitSystem &system, const MultiresNest &nest, CellThermals &thermals, std::span< const uint8_t > frozen, uint32_t id)
uint32_t AddCell(ImplicitSystem &system, const MultiresNest &nest, CellThermals &thermals, uint32_t slot, uint32_t index)
void CaptureNest(MultiresNest &nest, std::span< const uint8_t > frozen)
fx::FxU128 FaceCoefficient(const ImplicitCell &fine, const ImplicitCell &coarse)
constexpr uint32_t NOT_IN_SYSTEM
void RecordLevels(MultiresNest &nest, const ImplicitGrid &grid)
ImplicitSystem MakeSystem(const MultiresNest &nest, CellThermals &thermals, std::span< const uint8_t > frozen, std::span< const uint8_t > implicitBlocks)
ImplicitOptions MakeImplicitOptions(const MultiresStepOptions &options)
uint32_t CountUnknowns(const MultiresNest &nest, CellThermals &thermals, uint32_t slot)
bool CanJoin(const MultiresNest &nest, std::span< const uint8_t > frozen, uint32_t slot)
size_t PageCellAddress(const MultiresNest &nest, uint32_t page, uint32_t index)
std::vector< uint8_t > MarkImplicitBlocks(MultiresNest &nest, CellThermals &thermals, std::span< const uint8_t > frozen, const MultiresStepOptions &options)
bool InImplicitConduction(const MultiresNest &nest, uint32_t slot, const MultiresStepOptions &options)
bool IsImplicitBlock(std::span< const uint8_t > implicitBlocks, uint32_t slot)
void AddImplicitConduction(MultiresNest &nest, CellThermals &thermals, std::span< const uint8_t > frozen, std::span< const uint8_t > implicitBlocks, const MultiresStepOptions &options, std::span< MrEnergyDelta > deltas)
ImplicitCost StepImplicit(ImplicitGrid &grid, const ImplicitOptions &options)
ImplicitGrid BuildImplicitGrid(std::vector< ImplicitCell > cells, bool galerkin)
constexpr MultiresImplicitBudget MakeMultiresImplicitBudget(const MultiresImplicitLimits &limits)
int64_t ImplicitEnergyFor(uint64_t heatCapacity, int64_t millikelvin)
std::vector< int32_t > levels
std::vector< uint32_t > rowStarts
std::vector< ImplicitGridLevel > levels
std::vector< ImplicitCell > cells
uint32_t toleranceMillikelvin
ImplicitCost implicitCost
std::vector< uint8_t > implicitFrozen
std::shared_ptr< const MultiresNest > implicitNest
MultiresCapacity capacity
ImplicitGrid implicitGrid
std::vector< multires::MrBlock > blocks
std::vector< std::array< uint32_t, 2 > > implicitLevels
uint32_t implicitDeferredBlocks
uint32_t implicitMaxCycles
int32_t subcycleBaseLevel
MultiresImplicitLimits implicitLimits
ImplicitOverflow implicitOverflow
std::vector< ImplicitCell > cells
std::vector< uint32_t > ids
std::vector< uint32_t > indices
std::vector< ImplicitFace > faces
std::vector< int64_t > startEnergies
std::vector< uint32_t > slots