Skip to content

frw: HTML/Javascript implementation of floating random walk cap extraction - #11179

Closed
QuantamHD wants to merge 1 commit into
The-OpenROAD-Project:masterfrom
QuantamHD:frw
Closed

frw: HTML/Javascript implementation of floating random walk cap extraction#11179
QuantamHD wants to merge 1 commit into
The-OpenROAD-Project:masterfrom
QuantamHD:frw

Conversation

@QuantamHD

Copy link
Copy Markdown
Collaborator

To test it open the html page with vscode and right click on the html file "View with Live Server", otherwise you will get CORS exception.

image

…ction

Signed-off-by: Ethan Mahintorabi <ethanmoon@google.com>
@QuantamHD
QuantamHD requested a review from a team as a code owner August 19, 2026 00:17
@QuantamHD
QuantamHD requested a review from maliberty August 19, 2026 00:17

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces three interactive HTML-based 2D Floating Random Walk (FRW) capacitance extractors: a rectangular simulator, a circular simulator, and an infinite-space circular simulator. While the interactive drag-and-drop features and real-time path rendering are excellent additions, several critical issues need to be addressed. In the infinite-space simulator, the relative error calculation incorrectly uses total walks instead of completed walks, and the lack of an outer boundary for the infinite domain can cause browser freezes and selection bias due to walks hitting the safety brake. Additionally, both the rectangular and circular simulators lack overlap prevention when dragging conductors, which can result in physically impossible overlapping states and incorrect capacitance calculations.

let relativeError = Infinity;

if (hitsNeighbor > 50) {
relativeError = Math.sqrt((1 - p) / (totalWalks * p));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The relative error calculation is incorrect because it uses totalWalks in the denominator. In this infinite space simulation, walks that hit the safety brake are discarded and do not increment hitsNeighbor or hitsTarget. Therefore, totalWalks is larger than the number of completed walks, leading to an underestimation of the relative error. This can cause the simulation to converge prematurely before reaching the actual target error limit. The relative error should be calculated using only the completed walks (hitsNeighbor + hitsTarget), which simplifies to Math.sqrt((1 - p) / hitsNeighbor).

Suggested change
relativeError = Math.sqrt((1 - p) / (totalWalks * p));
relativeError = Math.sqrt((1 - p) / hitsNeighbor);

let safetyBrake = 0;

// Massive safety brake for walks that go into deep space
while (isWalking && safetyBrake < 500000) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

In a 2D infinite domain without ground boundaries, a random walk is recurrent but has an infinite expected number of steps to return or hit a compact target. Consequently, a significant portion of walks will wander extremely far and hit the safety brake of 500000. Discarding these walks introduces a severe selection bias (over-representing walks that terminate quickly). Furthermore, running up to 500,000 steps per walk for 1,000 walks on the main thread in a single animation frame will completely freeze the browser UI. To resolve this, consider implementing an outer bounding boundary (e.g., a large circle) with an analytical absorption/return probability, which is the standard way to handle infinite domains in FRW.

Comment on lines +185 to +190
NEIGHBOR.x = mouseX - dragOffsetX;
NEIGHBOR.y = mouseY - dragOffsetY;

// Keep the circle inside the canvas
NEIGHBOR.x = Math.max(NEIGHBOR.r, Math.min(canvas.width - NEIGHBOR.r, NEIGHBOR.x));
NEIGHBOR.y = Math.max(NEIGHBOR.r, Math.min(canvas.height - NEIGHBOR.r, NEIGHBOR.y));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

There is no overlap prevention when dragging the neighbor circle. If the user drags the neighbor circle over the target circle, they can overlap, which results in negative distances and physically impossible/incorrect capacitance values. Consider adding the same radial overlap prevention logic that was implemented in frw_two_circles_infinite_bound.html.

Suggested change
NEIGHBOR.x = mouseX - dragOffsetX;
NEIGHBOR.y = mouseY - dragOffsetY;
// Keep the circle inside the canvas
NEIGHBOR.x = Math.max(NEIGHBOR.r, Math.min(canvas.width - NEIGHBOR.r, NEIGHBOR.x));
NEIGHBOR.y = Math.max(NEIGHBOR.r, Math.min(canvas.height - NEIGHBOR.r, NEIGHBOR.y));
NEIGHBOR.x = mouseX - dragOffsetX;
NEIGHBOR.y = mouseY - dragOffsetY;
// Ensure circles don't overlap
let distBetweenCenters = Math.sqrt(Math.pow(NEIGHBOR.x - TARGET.x, 2) + Math.pow(NEIGHBOR.y - TARGET.y, 2));
if (distBetweenCenters < (TARGET.r + NEIGHBOR.r + 5)) {
let angle = Math.atan2(NEIGHBOR.y - TARGET.y, NEIGHBOR.x - TARGET.x);
NEIGHBOR.x = TARGET.x + Math.cos(angle) * (TARGET.r + NEIGHBOR.r + 5);
NEIGHBOR.y = TARGET.y + Math.sin(angle) * (TARGET.r + NEIGHBOR.r + 5);
}
// Keep the circle inside the canvas
NEIGHBOR.x = Math.max(NEIGHBOR.r, Math.min(canvas.width - NEIGHBOR.r, NEIGHBOR.x));
NEIGHBOR.y = Math.max(NEIGHBOR.r, Math.min(canvas.height - NEIGHBOR.r, NEIGHBOR.y));

Comment on lines +190 to +195
NEIGHBOR.x = mouseX - dragOffsetX;
NEIGHBOR.y = mouseY - dragOffsetY;

// Optional: Keep the box inside the canvas
NEIGHBOR.x = Math.max(0, Math.min(canvas.width - NEIGHBOR.w, NEIGHBOR.x));
NEIGHBOR.y = Math.max(0, Math.min(canvas.height - NEIGHBOR.h, NEIGHBOR.y));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

There is no overlap prevention when dragging the neighbor rectangle. If the user drags the neighbor rectangle over the target rectangle, they can overlap, which results in immediate absorption (hits) during the simulation and incorrect capacitance values. Consider adding a simple AABB overlap check to prevent dragging the neighbor box into the target box.

Suggested change
NEIGHBOR.x = mouseX - dragOffsetX;
NEIGHBOR.y = mouseY - dragOffsetY;
// Optional: Keep the box inside the canvas
NEIGHBOR.x = Math.max(0, Math.min(canvas.width - NEIGHBOR.w, NEIGHBOR.x));
NEIGHBOR.y = Math.max(0, Math.min(canvas.height - NEIGHBOR.h, NEIGHBOR.y));
let newX = mouseX - dragOffsetX;
let newY = mouseY - dragOffsetY;
// Keep the box inside the canvas
newX = Math.max(0, Math.min(canvas.width - NEIGHBOR.w, newX));
newY = Math.max(0, Math.min(canvas.height - NEIGHBOR.h, newY));
// Prevent overlap with TARGET (with 5px padding)
const padding = 5;
const overlaps = (
newX < TARGET.x + TARGET.w + padding &&
newX + NEIGHBOR.w > TARGET.x - padding &&
newY < TARGET.y + TARGET.h + padding &&
newY + NEIGHBOR.h > TARGET.y - padding
);
if (!overlaps) {
NEIGHBOR.x = newX;
NEIGHBOR.y = newY;
}

@maliberty maliberty closed this Aug 19, 2026
@maliberty

Copy link
Copy Markdown
Member

I don't plan to merge it so I've closed it but I'll examine it further.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants