I spent a week trying to represent Ivanpah as data. Not the whole plant, just the part you can see from a car: three towers, three mirror fields, and a boundary fence. It turned out to be a good exercise in knowing what a model can hold and what it quietly drops.
The Only Thing the Map Gives You
I started with GenAnywhere, because it was the fastest way to get a spatial sketch. I selected a rectangle around the Ivanpah Valley site and asked it to build a model from the map. The result was a recognizable blockout: three clusters of panels, three vertical markers, a road along one edge, and the shape of the dry lakebed. For a first pass, that was useful.
The model had no idea what a heliostat is. It had shapes that looked like mirrors and towers, but no identity, no orientation, no state. That is less a flaw in the tool than a boundary. A map-based generator reproduces geometry, and geometry is the smallest part of this system.
Three Entities, One Sun
Once I stopped expecting the model to know anything, I wrote down the entities I actually needed:
• A heliostat: a mirror assembly with a position, an aim point, and a status.
• A receiver: the target on top of a tower, with a flux limit.
• A reading: a measurement at a point in time, from a sensor or a meter.
The sun is not an entity. It is an input that changes every second, and it is the reason the other three exist. The plant has 173,500 heliostats across three units, and each one is aimed independently. If you store only the field boundary, you have stored almost nothing.
A Small Model
Here is a sketch of the Python side. It is deliberately plain, because the interesting decisions are about fields, not frameworks.
The first thing this model forces you to admit is that a position is not enough. Two heliostats at the same coordinates would behave differently if one is tracking and the other is parked for maintenance. The second thing it forces is a time dimension. A reading without a timestamp is just a number.
Coordinates Are Not State
The map model gave me an x and a y on a plane. The real field sits on uneven ground, and each pedestal has its own elevation. The mirrors also have limits: they cannot tilt past a certain angle, and they stow flat when wind gets too high. None of that is visible in a generated blockout.
I also had to pick a coordinate system. Latitude and longitude are fine for a map, but a field controller works in meters from a local origin. Mixing the two is a quiet source of bugs, and a plant this size makes the error obvious: a few feet of offset at the boundary becomes a missed aim point at the tower.
I ended up treating the generated mesh as a base layer and adding attributes on top of it. That was the only way to keep the model honest. The mesh answered "where does the field start and end." The attributes answered "what is each unit doing right now." Mixing those two questions in one object is how you get a model that looks correct and answers nothing.
Flux Is the Part You Cannot Query
The receiver at each tower has a flux limit. Mirrors are assigned aim points to spread the concentrated light, and the control system adjusts those assignments as the sun moves. There is no public feed for this. I could not query it, and I would not trust a generated scene to show it.
So I left flux out of the first version and wrote down why. A data model with a documented hole is more useful than one with a guessed value. If I ever get real readings, the Reading class is already waiting for them.
What I Took Away
A map-box 3D generator is a good way to get the outline of an industrial site in a few minutes. It is a bad way to understand timing, control, or heat. Ivanpah is a plant where the interesting behavior happens between frames: mirrors move, aim points shift, and output follows the weather.
The model I built has three towers and 173,500 rows in theory. In practice I filled in a few dozen and spent the rest of the time on the schema. That felt like the right ratio. The picture is the easy part.


Top comments (0)