Public
Edited
Feb 9, 2023
1 fork
6 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function vecField(x, y){
let vec={}
if (field=="Position Vec"){
vec.x = x;
vec.y = y;
}
if (field=="Field 1"){
vec.x = Math.cos(x);
vec.y = Math.cos(y);
}
if (field=="Solenoidal 1"){
vec.x = -y;
vec.y = x;
}
if (field=="Solenoidal 2"){
vec.x = Math.sin(y);
vec.y = Math.cos(x);
}
return vec
}
Insert cell
Insert cell
Insert cell
mutable yBox=0 // top left corner of the box (pixels)
Insert cell
mutable xBox=0 // top left corner of the box (pixels)
Insert cell
xStart=x.invert(xBox)
Insert cell
yStart=y.invert(yBox)
Insert cell
boxSizePix=x(boxSize)-x(0)
Insert cell
// x and y coordinates of each corner of the box
boxLine=[{x:xStart+boxSize,y:yStart-boxSize}, {x:xStart+boxSize,y:yStart}, {x:xStart,y:yStart}, {x:xStart,y:yStart-boxSize},{x:xStart+boxSize, y:yStart-boxSize}]
Insert cell
// flux through each face
fluxInt = {
let nElem=20;
let fluxInt=[];
for (let nSide = 0; nSide < 4; ++nSide) {
let x0 = boxLine[nSide].x;
let x1 = boxLine[nSide+1].x;
let y0 = boxLine[nSide].y;
let y1 = boxLine[nSide+1].y;
let dx=(x1-x0)/nElem
let dy=(y1-y0)/nElem
let fluxNow=0;
for (let n = 0; n < nElem; ++n) {
let xNow = x0 + n*dx + dx/2;
let yNow = y0 + n*dy + dy/2;
let vecNow = vecField(xNow,yNow);
fluxNow = fluxNow + dy * vecNow.x - dx * vecNow.y;
}
fluxInt.push(fluxNow/(boxSize*boxSize));
}
return fluxInt
}

Insert cell
fluxSum = fluxInt.reduce( (a, b) => a + b, 0 )
Insert cell
contWidth = width*0.5
Insert cell
contHeight=contWidth
Insert cell
xDomain=[-2 , 2]
Insert cell
yDomain = [-2,2]
Insert cell
vectors = {
const dx = (xDomain[1] - xDomain[0])/width;
const dy = (yDomain[1] - yDomain[0])/height;
const n = Math.ceil((grid.x1 - grid.x0) / vecQ);
const m = Math.ceil((grid.y1 - grid.y0) / vecQ);
const vector = new Array(n*m);
for (let j = 0; j < m; ++j) {
for (let i = 0; i < n; ++i) {
const xnow = x.invert(i*vecQ + grid.x0);
const ynow = y.invert(j*vecQ + grid.y0);
const delx = vecField(xnow,ynow).x;
const dely = vecField(xnow,ynow).y;
vector[j*n+i] = {x:xnow, y:ynow, dx:delx, dy:dely};
}
}
return vector;
}

Insert cell
color = d3.scaleLinear()
.domain(d3.extent(thresholds))
.interpolate(d => d3.interpolateViridis)
Insert cell
thresholds=d3.range(d3.min(grid),d3.max(grid),(d3.max(grid)-d3.min(grid))/21)
Insert cell
grid = {
const q = 4; // The level of detail, e.g., sample every 4 pixels in x and y.
const x0 = -q / 2, x1 = contWidth + q;
const y0 = -q / 2, y1 = contHeight + q;
const n = Math.ceil((x1 - x0) / q);
const m = Math.ceil((y1 - y0) / q);
const grid = new Array(n * m)
for (let j = 0; j < m; ++j) {
for (let i = 0; i < n; ++i) {
let xNow = x.invert(i * q + x0);
let yNow = y.invert(j * q + y0);
let vecNow=vecField(xNow,yNow);
let Vx = vecNow.x;
let Vy = vecNow.y;
grid[j * n + i] = Math.sqrt(Vx*Vx + Vy*Vy)
}
}
grid.x = -q;
grid.y = -q;
grid.k = q;
grid.n = n;
grid.m = m;
grid.x0 = x0;
grid.x1 = x1;
grid.y0 = y0;
grid.y1 = y1;
return grid;
}
Insert cell
// Converts from grid coordinates (indexes) to screen coordinates (pixels).
transform = ({type, value, coordinates}) => {
return {type, value, coordinates: coordinates.map(rings => {
return rings.map(points => {
return points.map(([x, y]) => ([
grid.x + grid.k * x,
grid.y + grid.k * y
]));
});
})};
}
Insert cell
contours = d3.contours()
.size([grid.n, grid.m])
.thresholds(thresholds)
(grid)
.map(transform)
Insert cell
function dragged(event, d) {
mutable xBox += event.dx;
mutable yBox += event.dy;
}

Insert cell
x = d3.scaleLinear().domain(xDomain).range([0, contWidth ])
Insert cell
y = d3.scaleLinear().domain(yDomain).range([contHeight, 0])
Insert cell
barData=[{label:"E",value:fluxInt[0],color:"steelBlue"},{label:"N",value:fluxInt[1],color:"steelBlue"},{label:"W",value:fluxInt[2],color:"steelBlue"},{label:"S",value:fluxInt[3],color:"steelBlue"},{label:"sum", value:fluxSum,color:"green"}]
Insert cell
xBar = d3.scaleBand()
.domain(barData.map(d => d.label))
.range([contWidth+50, width])
.padding(0.1)
Insert cell
yBar = d3.scaleLinear()
.domain([-2., 2.])
.range([height-50,50])
Insert cell
line = d3.line()
.x( d => x(d.x) )
.y( d => y(d.y) )
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height})`)
.call(d3.axisTop(x).ticks(width / height * 10))
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick").filter(d => x.domain().includes(d)).remove())
Insert cell
yAxis = g => g
.attr("transform", "translate(-1,0)")
.call(d3.axisRight(y))
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick").filter(d => y.domain().includes(d)).remove())
Insert cell
yAxisBar = g => g
.attr("transform", `translate(${contWidth+50},0)`)
.call(d3.axisLeft(yBar))
Insert cell
xAxisBar = g => g
.attr("transform", `translate(0,${yBar(0)})`)
.call(d3.axisBottom(xBar)
.tickSizeOuter(0))
Insert cell
height = contHeight
Insert cell
import {select, slider} from "@jashkenas/inputs"
Insert cell
d3 = require("d3@7")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more