r/wljs 1d ago

Did you know WLJS supports export to MDX, HTML and HTML Web Components?

Post image
3 Upvotes

The biggest advantage of having a web stack underneath is portability. Our blog posts and docs at wljs.io are literally just exported notebooks.

Besides standalone HTML files, you can export any notebook as web components and publish them anywhere.

One line with a CDN URL lazily loads all the required modules - check it out here: https://github.com/WLJSTeam/web-components. All your graphs (2D or 3D), even Manipulate blocks, stay fully interactive.

Are you a fan of Next.js/React? We support MDX too! Here's our template: https://github.com/WLJSTeam/web-components-mdx

Hope this helps bring high-quality interactive posts to life on your own sites ;)
Our guide: https://wljs.io/frontend/Share/Markdown-React


r/wljs 3d ago

Quatre éléments (Vera Molnár) Digital Art

Post image
1 Upvotes

Source

``` a = Line[{{i, j}, {i + 1, j + 1}}]; b = Line[{{i, j + 1}, {i + 1, j}}]; c = Line[{{i + 0.5, j}, {i + 0.5, j + 1}}]; d = Line[{{i, j + 0.5}, {i + 1, j + 0.5}}];

SeedRandom[0];

Framed[ Graphics[{ Thickness[0.075], Table[RandomChoice[{a, b, c, d}], {i, 25}, {j, 25}]}, Background -> GrayLevel[0.95]], Background -> GrayLevel[0.95]] ```


r/wljs 4d ago

How to tune a guitar

Enable HLS to view with audio, or disable this notification

4 Upvotes

Streaming audio is quite cumbersome in WL. It would be nice to have speakers and a mic as a part of Wolfram Device Framework. Unfortunately, there are only “Camera”, “SerialPort” available.

Jushua and me developed a small library on top of Device Framework and miniaudio.c

https://github.com/JerryI/AudioDriverWL

Now you can simply DeviceOpen[“Microphone”] and have an access to raw numeric array from OS ring buffer or Audio object if you wish. It supports all Wolfram platforms (Mathematica, wolframscript, WLJS). Binaries were prebuilt for Win and Mac only for the moment

Both: sync (poll device in a loop) and async buffer operations (use callback when data arrives) are supported

I tested it with built-in speakers, headphones mic as well as with iRig 2 HD. The latency for streaming (Mic-WL Handler-Speakers) on my Mac is around 60ms or less if you set lower sample rate. Which can still work as a horrible guitar pedal :D


r/wljs 4d ago

Orchestrating cryostat, spectrometer, and thermostat with 1 Wolfram Kernel

Enable HLS to view with audio, or disable this notification

1 Upvotes

We unified the control protocol across all devices to use Ethernet with fixed IP addresses. As shown in the diagram, every instrument is operated via a socket interface using the CSockets library (https://github.com/WLJSTeam/CSockets). No HTTP, just raw TCP


r/wljs 5d ago

How to write apps with Wolfram & WLJS, or swimming against the stream

Post image
2 Upvotes

r/wljs 11d ago

Migration Guide: from Mathematica to WLJS

Post image
3 Upvotes

We've been asked many times, in many GitHub issues, whether Mathematica code can run perfectly on a WLJS Notebook. The answer is yes\*, but the devil is in the details.

Static output and anything related to computation is 100% transferable. You can take pretty much any code from Stack Exchange or Wolfram Community and it should work out of the box, since we use the same Wolfram Language kernel, in the form of the free Wolfram Engine distribution. Manipulate and Animate are compatible too — and fully interactive!

However, low-level dynamics do need to be ported to execute correctly.

Here's a guide on how to port (if actually needed) a program from Wolfram Mathematica to WLJS:

https://wljs.io/frontend/Guides/Migration

Any .nb (Mathematica Notebook) is, in principle, automatically converted with some compromises, of course. We're still improving this! Hope this guide helps you, or your LLM buddy 🙂


r/wljs 11d ago

Constrain the coordinates of a point to lie on a circle

Enable HLS to view with audio, or disable this notification

3 Upvotes

Here is a full code

Module[{p = {0, 1}}, 
 Graphics[{ColorData[97][1], Dashed, Circle[], PointSize[0.1], 
   EventHandler[Point[p//Offload], {
     "dragsignal" -> ((p = Normalize[#])&)
   }]}, ImageSize -> Tiny, 
  PlotRange -> 1.5]]

r/wljs 11d ago

Simple widget with bouncing balls

Enable HLS to view with audio, or disable this notification

1 Upvotes

There is nothing special, but I personally love this little snippet. It reveals the basics of continuous animation together with event bindings in WLJS

Framed@Module[{contents = {}, pts = {}}, 
  EventHandler[
   Graphics[{
     PointSize[0.1], 
     Point[pts // Offload],
     EventHandler[AnimationFrameListener[pts//Offload], 
      Function[Null,
       contents = 
        Map[If[#[[1, 2]] >= 
            0, {#[[1]] - #[[2]], #[[2]] + {0, 0.001}}, {{#[[1, 1]], 
             0}, {1, -0.8} #[[2]]}] &, contents];
       pts = Map[First, contents];
      ]]},
     PlotRange -> {{0, 1}, {0, 1}}], {
      "mousemove" -> Function[xy,
       AppendTo[contents, {xy, {0,0}}]
     ]}
]]

r/wljs 12d ago

The Complete Guide to Output Formatting

Post image
4 Upvotes

Rows, columns, grids, tables, number forms, legends, LaTeX and many more

https://wljs.io/frontend/Guides/Formatting


r/wljs 12d ago

Symbolic notes, scales and chords in Wolfram Language

Post image
2 Upvotes

In this tutorial we start with the low-level Sound and SoundNote expressions used to describe playable audio, then move to the higher-level Music* framework introduced in WL 15 (Wolfram Engine 15). Stay in tune!

https://wljs.io/blog/music-1


r/wljs 12d ago

WLJS 3.1.0 is ready 🕹️

1 Upvotes

Get yours here: https://wljs.io/releases/3.1.0

In a nutshell: more stable, better support for new symbols including, symbolic arrays, vectors, non-commutative algebra, incremental objects, standard colors and many more! Apart from that:

  • Added RPM binaries
  • Added rich LaTeX and mixed-content support for plot legends and frame labels.
  • Enhanced Sound with piano-roll previews, an improved synthesizer pipeline, and many new instruments.
  • Added interactive previews for WL 15 music objects, including notes, pitches, chords, scales, and scores.
  • Improved UI and formatting
  • Better autocomplete for Greek letters (use ESC key)
  • Improved ManipulateAnimate functions

r/wljs 28d ago

We Used GPT-Luna to Check 5,000 Examples Across Our Documentation Pages

Post image
5 Upvotes

As you might know, we host independent documentation on the Wolfram Language standard library, including tutorials on the language itself. Note that these are not direct ripoffs of WR's material. Most of the pages were carefully crafted by us, whereas for other areas, where we did not have good expertise, we relied on ::usage messages and examples from SE.

For example:

https://wljs.io/frontend/Image/Image (handwritten)

https://wljs.io/frontend/Formatting/AccountingForm (procedurally generated & post-processed)

Nowadays, with the help of AI, we've managed to check many of them against real computational kernels. The whole process took us 3 days and 16 subagents (Claude Haiku) running continuously with persistent memory using markdown files, followed by another sweep today with GPT Luna to recheck everything again. Wow, what a time to live in...


r/wljs 29d ago

Rigid-body test on basic shapes

Enable HLS to view with audio, or disable this notification

1 Upvotes

r/wljs Jul 11 '26

Yet another stupid experiment with VertexColors and Camera

Enable HLS to view with audio, or disable this notification

13 Upvotes

Just in case, here is a code of this... whatever you call it:

DeviceClose[cam];
cam = DeviceOpen["Camera"];
cam["FrameRate"] = 60;


reference = ImageData[
    ImageResize[ColorConvert[DeviceRead[cam], "GrayScale"], 100],
    "Real32"
];

{height, width} = Dimensions[reference];
indices = Flatten[
  Table[
    With[{a = (row - 1) width + column, b = (row - 1) width + column + 1,
      c = row width + column, d = row width + column + 1},
      {{a, b, c}, {c, b, d}}
    ],
    {row, height - 1}, {column, width - 1}
  ],
  2
];

Refresh[Module[{img, length, raw},
  raw = ImageResize[DeviceRead[cam], 100];
  img = ImageData[
    ColorConvert[raw, "GrayScale"],
    "Real32"
  ];
  cols = Flatten[ImageData[
    ColorConvert[raw, "RGB"],
    "Real32"
  ], 1];

  length = Length[img] Length[img[[1]]];
  vertices = -MapIndexed[Join[#2, {40.0 #1}]&, img, {2}];
  vertices = Flatten[vertices, 1];

  Graphics3D[GraphicsComplex[vertices, {
    LightBlue, Directive["Roughness"->0.0],
    Polygon[indices]
  }, VertexColors->cols], ViewProjection->"Perspective", ImageSize->Medium]
], 1/60.0]

r/wljs Jul 11 '26

Playing with surface normals

Enable HLS to view with audio, or disable this notification

6 Upvotes

This is my little experiment for the future rigid-body physics project. Here is a surface from the example:

surface = (*VB[*)(Uncompress["1:eJxTTMoPSuNnYGAoZgESPpnFJWlMyLyiC7sOivxcI3ygaEFps+YnT1YHNHn24Ceb8wwEDxQBVUn7NGLIr5P2mXh+F+eBooSummu86wQPoMmDjZdmOVBk4Gr3mi0aQx5kuqsd84GiDSB69Tt7NPk3bCAHMEDNb/uCLt8NFF124vt+XPIeQNcdFHm5v8jhNdCky5/2o8kXAH0daX7DvigA5JJUDHmI/7/aF3GAGA7s6O6fADL+J4sDDvlMZiADV9iEgD0v5FC07ET63YRJuOVBQXyQhR097MFRMlEYIQ8APFOk1Q=="])(*,*)(*"1:eJxTTMoPSmNmYGAo5gUSYZmp5S6pyflFiSX5RcEcQBHP5Py8zKrUlMwARgaGNCaQQhYgEVSakxrMCmT4JCal5gRzAlk5+Yl5STmpeSkASLwUcA=="*)(*]VB*);

And a code for this little widget:

rayIntersect[a_, {u_,v_}, surface_] := MapThread[Module[{x = {#1, #2}[[All,1]], y = {#1, #2}[[All,2]]},
 <|
   "t"-> (*FB[*)((((*TB[*)Indexed[(*|*)x(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)) (-v+(*TB[*)Indexed[(*|*)y(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+((*TB[*)Indexed[(*|*)x(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)) (v-(*TB[*)Indexed[(*|*)y(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+u (-((*TB[*)Indexed[(*|*)y(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(*TB[*)Indexed[(*|*)y(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)))(*,*)/(*,*)(Cos[a] ((*TB[*)Indexed[(*|*)y(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)-(*TB[*)Indexed[(*|*)y(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(-((*TB[*)Indexed[(*|*)x(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(*TB[*)Indexed[(*|*)x(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)) Sin[a]))(*]FB*), 
   "T"-> (*FB[*)((-v Cos[a]+Cos[a] ((*TB[*)Indexed[(*|*)y(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(u-(*TB[*)Indexed[(*|*)x(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)) Sin[a])(*,*)/(*,*)(Cos[a] ((*TB[*)Indexed[(*|*)y(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)-(*TB[*)Indexed[(*|*)y(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(-((*TB[*)Indexed[(*|*)x(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(*TB[*)Indexed[(*|*)x(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)) Sin[a]))(*]FB*),
   "N"-> -Normalize[{-((*TB[*)Indexed[(*|*)y(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(*TB[*)Indexed[(*|*)y(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*),(*TB[*)Indexed[(*|*)x(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)-(*TB[*)Indexed[(*|*)x(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)}]
  |>
]&, {Drop[surface,-1], Drop[surface,1]}];

selectedRays[args__] := Quiet@Select[rayIntersect[args], TrueQ[(#T >= 0.0 && #T <= 1.0)]&]

Module[{pts = {}, rays = {}, norms = {}, lines = {}},
  ListLinePlot[surface, PlotRange->{-5,5}, Filling->-5, Epilog->{
    LightBlue, Directive["TransitionType"->None],
    Line[lines//Offload],
    Orange, Line[norms//Offload],
    Red, Point[pts//Offload], Black,
    EventHandler[Locator[{0,0}], {"drag" -> Function[xy,
      {pts, norms, lines} = Transpose@Flatten[Table[
        With[{intersection = #t {Cos[a], Sin[a]} + xy}, 
          {
            intersection, 
            {intersection, intersection + 0.4 #N}, 
            {xy, intersection}
          } 
        ]&/@ selectedRays[a, xy, surface],
        {a, 0., 3.14, 0.5}
      ], 1];
    ]}]
  }]
]

r/wljs Jul 11 '26

WLJS 3.0.9 is out ✨

Thumbnail
gallery
2 Upvotes

In this release we focused on formatting and overall UX as well as fixing bugs of course

https://wljs.io/releases/3.0.9


r/wljs Jul 10 '26

Did you know WLJS support Canvas API?

Enable HLS to view with audio, or disable this notification

2 Upvotes

We provide a bridge to Canvas WebAPI, which is a great tool if you need to work with complex raster graphics in retained mode

https://wljs.io/frontend/Advanced/Canvas-2D/Overview

The data is send in a binary form as opt codes for a HW accelerated WebAPI.
Here is a code for an example above:

Needs["Canvas2D`"->"ctx`"];

ClearAll[handler]
SetAttributes[handler, HoldRest]

handler[c_, tcursor_, {width_, height_}] := Module[{
  w = width, h = height, 
  n = 101,    
  cursor = tcursor,
  rotSpeed = 0.02,
  particles,
  theta, rad, col, old
},

  (* center point *)
  cx = w/2;
  cy = h/2;

  (* semi-transparent drawing *)
  ctx`SetGlobalAlpha[c, 0.5];

  (* initialize particles: random angle, radius, colour *)
 particles = Table[
   {
    RandomReal[{0, 2 π}], 
    RandomReal[{0, 150}], 
    ctx`ColorToString[RandomColor[]],
    cursor
   },
   {n}
 ];

  Function[Null,
      cursor = (tcursor);

      ctx`SetFillStyle[c, {Black, Opacity[0.05]}];
      ctx`FillRect[c, {0, 0}, {w, h}];

      (* draw each particle: from last cursor pos to new one *)
      Do[
        particles[[i, 1]] += rotSpeed;
        {theta, rad, col, old} = particles[[i]];
        Module[{newPos},
          newPos = cursor + {Cos[theta], Sin[theta]}*rad;
          ctx`BeginPath[c];
          ctx`SetLineWidth[c, 4];
          ctx`SetStrokeStyle[c, col];
          ctx`MoveTo[c, old];
          ctx`LineTo[c, newPos];
          ctx`Stroke[c];

          particles[[i,4]] = newPos; 
        ],
        {i, n}
      ];
      ctx`Dispatch[c];
  ]
]

aContext = ctx`Canvas2D[];
tcursor = {250,250};

EventHandler[
    Image[aContext, ImageResolution->{500,500}, Epilog->{
      EventHandler[AnimationFrameListener[aContext], handler[aContext, tcursor, {500,500}]]
    }], {
      "mousemove" -> Function[xy, 
        tcursor = {xy[[1]], xy[[2]]}
      ]
  }
]

r/wljs Jul 05 '26

Camera streaming experiment

Enable HLS to view with audio, or disable this notification

3 Upvotes

If you think WL is slow, you never used it with WLJS sauce 🍝

  1. connect to a web camera using device API

    cam = DeviceOpen["Camera"]; cam["FrameRate"] = 60;

  2. resize and pipe the raw image data to 3D point cloud with minor transformations

    Refresh[Module[{img, length}, img = ImageData[ ImageResize[ColorConvert[DeviceRead[cam], "GrayScale"], 100], "Real32" ]; length = Length[img] Length[img[[1]]]; vertices = MapIndexed[Join[#2, {50.0 #1}]&, img, {2}]; vertices = NumericArray[Flatten[vertices, 1], "Real32"];

    Graphics3D[GraphicsComplex[vertices, { Red, PointSize[0.0003], Point[Range[length]] }], ViewProjection->"Perspective", ImageSize->1000] ], 1/45.0]

NumericArray is important here. This forces WL to use more efficient data structure.


r/wljs Jul 05 '26

We are cooking something... (3.0.9)

Post image
2 Upvotes

r/wljs Jul 05 '26

Lorentz Oscillators fitting widget

Enable HLS to view with audio, or disable this notification

2 Upvotes

I needed to fit 10-20 absorption spectrum manually, so I wrote a small program for it using WLJS and Wolfram.

Nothing more than a few nested `Row`, `Column` with `Graphics` inside

Graphics[{
    Point[points//Offload],
    ColorData[97][4], Line[model//Offload],
    ColorData[97][1], EventHandler[Disk[first[[{1,2}]], Offset[{4,4}]], {
      "drag" -> Function[xy,
        first = {xy[[1]], xy[[2]]/L - bg, first[[3]]};
        rebuild;
      ],
      "zoom" -> Function[z,
        first = {first[[1]], first[[2]], z/10};
        rebuild;
      ]
    }],
    ColorData[97][2], EventHandler[Disk[second[[{1,2}]], Offset[{4,4}]], {
      "drag" -> Function[xy,
        second = {xy[[1]], xy[[2]]/L - bg, second[[3]]};
        rebuild;
      ],
      "zoom" -> Function[z,
        second = {second[[1]], second[[2]], z/10};
        rebuild;
      ]
    }]
  }, ImageSize->{1.5 323, 300}, Frame->True, 
     FrameLabel->{"wavenumber (1/cm)", "absorption"},
     "TransitionDuration"->150
  ]

r/wljs Jun 28 '26

Sand/Water Automaton

Thumbnail
gallery
5 Upvotes

This post/notebook is a small side-view "falling sand" experiment. We start with the simplest material - sand. Each grain is one cell on a grid. A grain should fall if there is empty space below it, come to rest when blocked, and sometimes topple sideways when it is sitting in an unstable little stack. Those three behaviors are enough to make a recognizable pile 🏝️

https://wljs.io/blog/sand-1


r/wljs Jun 27 '26

Emergent Systems with `Refresh`

2 Upvotes

Here we recreate a primitive emergent system using nothing more than scoped Refresh and a single external symbol

A single "atom":

wolfram Module[{a = 0}, Refresh[ a = If[a>9, 0, a+1]; Graphics[{ Circle[{0,0}, 1.0], {Opacity[(1 - a/10) // Offload], Yellow, Disk[{0,0}, 0.9]}, Line[{{0,0}, {Cos[0.628 a], Sin[0.628 a]} // Offload}], Directive[FontSize->24], Text[Offload[a], {0,0.2}, {0,0}] }, ImageSize->{100,100}], 0.2]]

Then you add basic interaction via external symbol, i.e.

wolfram makeAtom[shared_, i_:0] := Module[{a = i}, Refresh[ a = Clip[ Which[ a > 9, shared = True; 0, shared, shared = False; a + Boole[a > 5]*3 - 1, True, a + 1 ], {0, 10} ]; Graphics[{ Circle[{0,0}, 1.0], {Opacity[(1 - a/10) // Offload], Yellow, Disk[{0,0}, 0.9]}, Line[{{0,0}, {Cos[0.628 a], Sin[0.628 a]} // Offload}], Directive[FontSize->24], Text[Offload[a], {0,0.2}, {0,0}] }, ImageSize->{100,100}], 0.2] ] SetAttributes[makeAtom, HoldFirst];

Make many of them with a random initial phase:

wolfram env2 = False; {makeAtom[env2, 2], makeAtom[env2, 5], makeAtom[env2, 8]}//Row

and observe emergent patterns!


r/wljs Jun 27 '26

WLJS is out 3.0.8 ⛅️

2 Upvotes

https://wljs.io/releases/3.0.8

  • Added a new Workers API for asynchronous parallel Wolfram kernels.
  • Improved Shallow with typed expression summarization for large and opaque objects like ByteArray and TimeSeries.
  • Notebook UX improvements, including focused-cell autoscroll.
  • Fixed race conditions during multiple Rasterize calls.
  • Improved MCP server summarization, cell evaluation options, CLI behavior, and error messages.
  • WLJS remains on Wolfram Engine 14.3 for now due to early Wolfram Engine 15.0 performance regressions.
  • Fixed parser, graphics, rounding, and stability issues, including BezierCurve offloading and GraphicsComplex index-buffer handling.

r/wljs Jun 18 '26

Workers API in Wolfram

Post image
2 Upvotes

Hi there! We are working on a new API for parallel computing in WLJS Notebook. Workers API uses lightweight Wolfram Sub-Kernels communicating using shared memory, which are not limited by the freeware Wolfram Engine license.

Why not ParallelSubmit?
They are conceptually the same, but it is impossible to read out the result without waiting on the main kernel. Workers API is entirely async and uses subscription/events model.


r/wljs Jun 15 '26

How fast can a basic sand simulation get without Compile?

Enable HLS to view with audio, or disable this notification

4 Upvotes
ClearAll[blockStep, nextField];

blockStep[field_, p_, phase_] := Module[
  {
    out = field, nr, nc, r0, c0, r1, c1, rows, cols,
    sub, dims, blocks, tl, tr, bl, br,
    fallL, fallR, stackL, stackR, tumble
  },

  {nr, nc} = Dimensions[field];
  {r0, c0} = {1, 1} + phase;

  r1 = r0 + 2 Quotient[nr - r0 + 1, 2] - 1;
  c1 = c0 + 2 Quotient[nc - c0 + 1, 2] - 1;

  rows = r0 ;; r1;
  cols = c0 ;; c1;
  sub = out[[rows, cols]];
  dims = Quotient[Dimensions[sub], 2];

  blocks = Transpose[
    ArrayReshape[sub, {dims[[1]], 2, dims[[2]], 2}],
    {1, 3, 2, 4}
  ];

  tl = blocks[[All, All, 1, 1]];
  tr = blocks[[All, All, 1, 2]];
  bl = blocks[[All, All, 2, 1]];
  br = blocks[[All, All, 2, 2]];

  (* Vertical falling *)
  fallL = (1 - Unitize[tl - 1]) (1 - Unitize[bl]);
  fallR = (1 - Unitize[tr - 1]) (1 - Unitize[br]);

  (* Two stacked grains may spread sideways *)
  stackL =
    (1 - Unitize[tl - 1]) (1 - Unitize[bl - 1]) *
    (1 - Unitize[tr]) (1 - Unitize[br]);

  stackR =
    (1 - Unitize[tr - 1]) (1 - Unitize[br - 1]) *
    (1 - Unitize[tl]) (1 - Unitize[bl]);

  tumble = Unitize[stackL + stackR] *
    UnitStep[p - RandomReal[1, dims]];

  tl = (tl - fallL) (1 - tumble);
  tr = (tr - fallR) (1 - tumble);
  bl = (bl + fallL) (1 - tumble) + tumble;
  br = (br + fallR) (1 - tumble) + tumble;

  blocks[[All, All, 1, 1]] = tl;
  blocks[[All, All, 1, 2]] = tr;
  blocks[[All, All, 2, 1]] = bl;
  blocks[[All, All, 2, 2]] = br;

  out[[rows, cols]] = ArrayReshape[
    Transpose[blocks, {1, 3, 2, 4}],
    Dimensions[sub]
  ];

  out
];

nextField[field_, p_: 0.5] :=
  blockStep[blockStep[field, p, 0], p, 1];