A few months ago, Ben Sitler created a guide for making Grasshopper components where, tucked in the bottom, are instructions for viewing the Grasshopper source code. Download the .Net Reflector from RedGate, point it towards the Grasshopper dll, and there it all is. Dissecting Grasshopper like this is against section 3.2.1 of the Grasshopper terms of service, however just looking at the code is unlikely to draw attention, copying the code on the other-hand is both unethical and illegal.
It is fascinating to see the inner workings of production software. I was expecting it to be overflowing with elaborate geometric algorithms, graph theory and optimisations, these are definitely there but for the most part the code is user interface. This probably should not be surprising, the interface to Grasshopper is fairly sophisticated with many different buttons and controls, while the geometry is largely handled by Rhino. The dominance of interface in code seems to be true for many other projects, I used to sell small software plugins and was always amazed by how much time I would spend not writing plugins and instead packaging software, writing instructions and providing support. Adobe seems to face a similar phenomena, about 25 minutes into this talk about Photoshop at Google, the Adobe engineer mentions that the interface of Photoshop accounts for about 1/3 of the code base, surprising when you consider how simple the interface is relative to how complex the tools are. I think as a user the output of the software gets all the attention, however under the hood of production software are elaborate algorithms, not to generate the right output, but to help the user generate the right output.
Lately I have been very focused on the output of CAD software, and whether software engineering can teach us how to make better parametric models. I wonder if I have this the wrong way around, perhaps you need to start with the interface.
Edit 3rd of August, 2010: Removed the sentence that stated: “David Rutten, the developer of Grasshopper, has mentioned that decompiling code like this is often against the terms of service, but I can not deduce if it is against the Grasshopper terms of service – I think as long as you are just looking and not taking anything, it should be fine.” And replaced it with a sentence referring to the Grasshopper terms of service, thanks to David Rutten for clarifying this in the comment below.
I have spent the past month revising this project, and have come to the conclusion: I suck at parametric design. I set off with intentions of making the entire model parametric, but four weeks later I am left with a shambolic set of simi-parametric tools linked together with long manual processes and discarded ambition for the complex parts of the project.
Everything that I wanted to do with a parametric model could be achieved with a parametric model; this claim is the origin of the rhetoric for the flexibility of parametric models. In practice however, I did very little of the project with a parametric model, I did a bit of the project manually and I modified the the rest of the project so it was achievable. The result is a design that is distorted towards the strengths and away from the weaknesses of parametric tools. An example of this is the curves along the surface (illustrated below). The the curves are an explicit list of points that are wrapped onto the surface with a UV curve passed between them. Most of the time this curve looks straight, but at the ends of the surface (shown in the illustration in red) the UV curve starts to bend. The solution is to use a geodesic curve (the green one), but this breaks the relationships to the other curves. Given enough time, it would be possible to use straight geodesic curves but, given how long it would take, it is far easier to use UV curves and modify the design to allow the bend of the curve.
Bent UV curve shown in red, straight geodesic shown in green
It is a trade off: will the 12 hours I spend fixing the parametric model be noticeable in the final design. And in some cases: is it faster to get the parametric model to conform to the real world, or is it faster to get the real world to conform to the parametric model. People mistakenly associate this decision with choice and blame the architect for being a luddite. But the decision is loaded and biases the design towards things that are easy to do parametrically and away from things that are hard to do parametrically. In this way, just like any other CAD tool, parametric designs can be read as being in the language of parametricisim – dare I quote Schumacher – biased towards the easy solutions.
So parametric flexibility is more than being able to do something, it is the ability to actually do it. For me, what I am able to do and what I actually do is quite different. I suspect the difficulty in doing some of these tasks is related using mathematics as the intermediate language between designer and parametric tool, but that is a topic for another post. Have you encountered a similar phenomena in your models?
This is part two of a series on advanced design strategies for Grasshopper definitions. Part one looked at using design patterns to structure definitions and this part will investigate ways to optimise Grasshopper definitions. While it is written for Grasshopper, the ideas are equally applicable to other parametric modelling tools.
Why and when to optimise Grasshopper
In general optimising Grasshopper is a waste of time; the optimisation will take longer than any time you gain from using it. You spend far longer constructing Grasshopper definitions compared to using them so I would favor any change that makes a definition optimally readable over a change that makes a definition computationally optimal. However, in certain cases computational optimisation may be justified, particularly when dealing with real time transformations of models. A little optimization might kick a definition from unusably sluggish to fluid.
In general optimisation should only occur once the definition is fully functional – to avoid optimising a part of the definition that is either not used in the final definition or optimising the wrong part. Once you have the fully functional definition, you can choose the correct part to optimise by measuring how long processes take using the Grasshopper profiling tool.
Profile is under the view menu, and draws little boxes under each node with the time it takes to calculate.
Despite its three-digit accuracy, the tool is only approximate, so do not take it as gospel. You will want to focus your optimisation efforts on the areas that are taking the longest time and therefore offer the most reward for optimising. The following is a list of ways to optimise your definition, starting with the most basic and working into the advanced stuff.
Break the model up / Use the place holder pattern
This one is pretty obvious but I have included it for completeness. The general idea is to break a large calculation into more manageable parts. One way to do this is to look for moments in the definition where the graph narrows to one node. For example you might have a function that gives generates the lines for a set of columns and these lines are then fed into a function that generates the columns. You could calculate the lines separately and then in another definition import the lines to generate the columns. Another way to do this is to right click a node and either disable the calculations or turn off the preview. Yet another way to do this is to use the place holder design pattern where you replace complex geometry with temporary and simple geometry. So you might replace columns with a simple pipe and once all the pipes are in the right place, draw the detailed model in place of this pipe.
Simplify curves
Simplify is under Curve>Util
Simplify curves rebuilds the curve with less control points. This can significantly increase the speed of calculations with these curves, and any objects derived from the curves – like lofts and pipes.
Don’t repeat yourself
Repeating yourself causes twice as much work writing out the two definitions, twice as much work editing the definition in two places and causes the computer twice as much work doing the calculations twice. If you need a value, calculate it in one place and link this into the places where the calculation is needed. This is said another way in the DRY principle: “Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.” Your code will be faster to write, faster to edit and faster to calculate.
Work smarter
Above: original definition. Below: Using just the z component of the vector
Grasshopper encourages us to think about problems geometrically rather than computationally. Most of the time this is a good thing, but sometimes it can result in very inefficient code. A came across a great example of this the other week when a friend wanted to get the normals of a group of points on a surface and ensure the normals are always pointing upwards. For every point, he took the positive and negative normal, placed a point at the end and took the normal that put the point the furthest from the ground plane. This method is how we think about the problem geometrically, but is computationally slow because it involves creating points, projecting them and measuring distances. He asked me how to make it more efficient. I told him to take the normal for the point, check to see if the z-axis component is positive, if it is not then take the negative normal. This may not be an intuitive approach to the problem, but it is computationally efficient. Reconsidering a problem from a mathematical perspective can sometimes be rewarding.
Write your own functions
Writing your own functions can be very fickle, on some hardware configurations I have found rewriting Grasshopper nodes into C# or VB can greatly increase their execution time (sometimes as much as 10X). Other times it runs significantly slower. The following code finds the normal of the closest point on the surface. On my laptop this reduces the execution time from 400ms to about 100ms, however on my desktop it actually runs slower.
// Returns the normal of the surface at the closest point to the passed point.
private void RunScript(On3dPoint p, OnSurface s, ref object x, ref object y, ref object z)
{
double passS = 0;
double passT = 0;
s.GetClosestPoint(p, ref passS, ref passT);
RMA.OpenNURBS.On3dVector normal = s.NormalAt(passS, passT);
x = normal.x;
y = normal.y;
z = normal.z;
}
Write your own code
Grasshopper is pretty fast, but sometimes it just is not fast enough. You can either throw better hardware at the problem or better software at the problem. Writing your own C++/C#/VBA code can generate programs that run significantly faster than Grasshopper. The work done in Grasshopper is not lost though; it can act as a guide for structuring your new program, or as a specification to give a professional programmer.
This semester I have been teaching two papers at RMIT that have involved getting students up to speed with Grasshopper. There are already some excellent tutorials on how Grasshopper works – my favorite is Zubin M Khabazi’s Generative Grasshopper Tutorials – Lift Architects and Woo Jae also have some helpful advice. However, there seems to be little advice on avoiding a big balls of tangled Grasshopper spaghetti. So I am going to share some of my thoughts on how using design patterns can help avoid tangling yourself in Grasshopper bézier curves.
Why spaghetti is bad
Unfortunately not a joke
Spaghetti is the technical name for a tangled mess of code, sometimes called The Big Ball of Mud. Often when you are producing spaghetti everything will be fine, but when it comes to editing or reusing spaghetti things can be pretty painful. Spaghetti can make it almost impossible to understand what your code does because understanding it involves following the paths of all the wildly connected data-streams. It makes editing the code difficult because you do not know what removing a node does or how to reconnect the other nodes when you do. It can also make it hard to trace problems through the code. And you will never be able to merge two balls of spaghetti together. Gah.
Functions in Grasshopper
One of the most basic strategies for avoiding Spaghetti is to break your problem down into small tasks. This is pretty much how all programming languages manage code and this was even a feature in Grasshopper until it got mysteriously dropped (I am still hoping they dropped it because they are working on something better). You want to break the problem into distinct units of work, which can be described in a short sentence. For example, in the Copenhagen project, we were distributing wooden elements onto an elliptical surface. This can be broken down into four main tasks: generating the elliptical surface, placing points on the surface, placing the wooden elements on the points, and analysing the wooden elements.
Once you have your problem broken down, you should consider what data you need to perform each task and what data each task will return. So for generating an eliptical surface, the inputs to the task are: the center of the surface and the scale of the surface in the x, y, z space. The output of the task is a surface. I like to create a column of parameters for the inputs and a column for the outputs. This both helps explain what data your task is using and it makes it easy to reuse the function in the future.
Inputs and outputs all setup
Once all that is in place all that is left to do is fill in the steps to transform the inputs into the outputs.
Final function
There are some really big advantages to this method:
Your definition becomes easier to understand. Rather than trying to follow big long tangled links, you can see the main steps of the program. Then within each task, even if you do not fully understand what is going on inside the task, you can clearly see what data the task requires and what data it returns.
You can test a project in parts. Because every task is independent of the other tasks, you can easily put data into the inputs and verify the output of the task is correct. If something goes wrong with your model you can check each task is functioning, rather than trying to test the whole project at once.
It is easier to reuse your work. When you copy a task to a new location, because the inputs and outputs are explicitly defined and clearly labeled, all you need to do is reconnect these inputs and outputs to the right data sources. Similarly, it is easy to swap tasks in and out of the model when the inputs and outputs are defined. So if we decided we no longer wanted to use an elliptical surface because the elliptical surface has an explicit output node, we could just connect a free form surface to that node. No more trying to follow a curves through the definition to link them back up when something changes.
Design patterns in Grasshopper
Once you start designing with functions for a while, you will start to see common patterns occurring. In computer science, the patterns that form code are called design patterns. In a strange instance of progress folding back in on itself, design patterns are an idea that was originally taken by computer scientists from Christopher Alexander, and now we are borrowing these ideas back to help code architecture. Robert Woodbury, Robert Aish, and Axel Kilian developed a set of design patterns for parametric architecture, displayed in this excellent website. The patterns are for Generative Components but are applicable to Grasshopper. I personally find myself frequently using The Jig, The Controller, and The Place Holder.
While over in Copenhagen I was able to attend a PhD symposium held between CITA, SIAL and the Bartlett. There was 17 PhD students presenting their research (full list of speakers and topics), and two trends stuck:
New materialism
During a question and answer session, Mark Burry pointed out that materials are back in the zeitgeist. I suspect this is probably because materials and construction techniques are rapidly being discovered by material scientists, giving architects a much broader range of materials to consider than steel, concrete and glass. To a lesser extent architects are also starting to drive the development of new materials (although this is still rare). This is unfamiliar territory for architects and much of the research is looking at how to bring the material scientist into the project team and how to design and compute with these new materials.
My favorite example is a project by Sarat Babu from the Bartlett called Microkinetics. In the video above he has printed two types of rubber to make a member. In the first half of the video all the rubber is in strands and it behaves as you would expect: as it stretches it also becomes thinner. In the second half of the video, the rubber is printed in a bow-tie shape. As the member stretches it also becomes thicker. Babu had other examples of this process being used to make things like a cylindrical rubber jug, which when picked up forms a spout. Unfortunately, I suspect due to commercial interest in his work, all the videos of this have been taken down.
The mash-up
Software mash-up was a more subtle trend at the symposium. The keywords were: “I linked software X with software Y.” This falls into a much larger trend in software engineering of script kiddies, web2.0, SDK’s and the App store. For architecture there are probably two major implications:
The first is that it is the end of CAD-as-god, or the belief that a single tool can solve all problems. Hopefully this is also the end of all the zealots who flood forums with stories about how Autocad or Revit or Archicad are better than Autocad or Revit or Archicad. Possibly it is also the end of employment for people who can only use Autocad or Revit or Archicad.
The second is that interoperability becomes a lot more important than ability. I know there are people like Arup, and I imagine other big offices, are looking at this problem, but I am not convinced that it will be solved in a top-down manner.
In the mash-up culture we are also seeing software offices shrink to the size of one person. A single person like Daniel Piker (who makes Kangaroo physics for Grasshopper) is able focus on solving one problem well, rather than building an entire CAD package. I hope that the App Store model extends to architecture, allowing a single person to make a living solving a niche problem exceptionally well, and giving us a mash-up of many well fitting solutions to a problem rather than one ill-fitting CAD package.
I have just returned from the CITA workshop in Copenhagen. One of the problems we were tackling was how to distribute elements onto a unevenly doublely curved surface. I decided to explore whether the surface could be generated from elements of the same size. The most natural solution is to draw the elements in two dimensions and try to wrap the two dimensional surface onto the three dimensional shape. However the process of wrapping a two dimensional surface onto a three dimensional shape creates so much distortion that the original properties of the surface are lost: the elements become to long or too short. To me it feels like we hit the boundary of most CAD packages, which allow you to work in Cartesian space, and provide tools to wrap/embed Cartesian space into other spaces, but they are not set up to allow you to work in the original non-Cartesian space. For a while it seemed like the easiest solution would be to lazer cut the timber to fit the computer model rather than to correct the computer model. It is interesting to witness such a high-end workshop, full of nerds, struggling to overcome the limitations of CAD and in many ways giving the design over to the limitions of the software – or at-least designing within the vocabulary of the software.
The solution I came up with to this problem was to use a swarming algorithm on the surface (seen in the video above). By creating a number of random points on the surface, and then iteratively pushing these points away from each-other until they were the desired distance apart, it was possible to generate the surface from elements of the same size. I uploaded the code to do this onto openprocessing here. In the video above you will also notice that there is a Grasshopper model on the right. The processing code saves a text file of the elements and, in real time, Grasshopper turns this text file into a Rhino model that it analyses. Due to some of the code inside that model I can not release it, but you should be able to create your own version pretty fast using the Read File element in Grasshopper.
Another project from the workshop is Anders Deleuran’s exploration of the accuracy of lightweight simulation (video above). In this case he is simulating a reciprocal joint held with the bending of timber. Both of these projects were discussed by Mark Burry at the AD magazine’s 80th Birthday durring his lecture on ‘The future of architecture.’ The lectures were filmed but I have yet to find them online.
I have joined Twitter @nzarchitecture as a way to share the links that do not quite warrant a 1000 word a blog post here. Initially I was resistant to the idea that 140 characters could add anything other than noise to the discourse, however, from inbound links to this blog, I have come to see the aggregate effect of the conversation on Twitter. My first tweet is this video, by Martin Tamke and Jacob Riiber, of self organising structures generated in Processing at CITA:
This segways into my other announcement today: the blog may be a little quiet of the next 6 weeks, not because I am lost in the world of Twitter, but because I am travelling 16,000 Km to CITA, to attend/teach a workshop with Martin and Jacob as well as Mette Thomsen and Mark Burry. So if you are in either Twitter or Copenhagen say hi, and if you have any suggestions of people to follow on Twitter or places to see in Copenhagen/Germany/France or Spain, let me know.
Computational architecture got off to a pretty bizarre start in the 1960s. Pick up a copy of Cross’s The Automated Architect (1976) to see what I mean: study after study of methods to optimize designs to reduce the distance occupants walked. Even by today’s standards, the distance occupants walk seems a pretty strange measure of design success. One can only conclude that architects in the 1960s must have lived in almost perfect buildings, where commodity, firmness and delight were taken care of, and all that remained was to minimise the distances between tasks. Unfortunately, the dream to minimise the distances between tasks ends abruptly about the same time as the publication of The Automated Architect, never again to be considered a measure of building success again.
I recently stumbled across Sean Keller’s explanation of this period in his article Fenland Tech: Architectural Science in Postwar Cambridge. Keller traces computational architecture back to the Second World War, a period when:
“The extremities of war had forced to the surface many doubts about architecture as a significant modern profession: Did architects possess special expertise? Was their expertise objective or merely based on taste? In times of real need, were architects necessary? In short, was architecture serious business?” (pg. 48)
Arising from a sense of war-time inferiority, architects attempted to legitimize the profession by turning to science and mathematics. In post-war Britain, architecture was centralised around the Ministry of Works, which enabled the funding of – what was seen as legitimising — research into environmental design. With it came the rejection of “intuitive skill,” “confusion,” “sophistical sciences,” “individual hunches,” “court jesters and acrobats,” “private pranks,” “pricey prima-donnas,” “hallucinations,” “extravagant and empty images,” “individual expression,” and “personal prejudice” that “threaten architecture and planning.”(pg. 51). This manifested itself in an attempt to generate the perfect plan though minimising distances people walked. Keller gives three reasons for the interest in distances people walked:
It was based on observed behaviour and statistics.
The architects were able to legitimise the work through the mathematics of topology and graph theory.
The result was not geometrical and did not require a (then expensive) screen.
By the mid-1970s this approach had fallen out of favor. Of the many reasons given, the most relevant are:
A functional study could not objectively translate into a formal representation of a building.
It is difficult to measure a quality of a building – the distance people walk is itself a function of the building.
A satisfactory, but not optimal, solution can be found intuitively. It is not worth giving up control of how the building looks, how much it costs and what the environment is like, in exchange for a small improvement in a fairly unimportant characteristic of a building – the distance people walk.
I would also add that telecommunication probably solved a large part of this problem. This speaks to the non-obvious nature of design, that the solution to reducing the distances people walked was the design of a protocol for exchanging information between computers, rather than the design of a perfect building layout. Tabor and Willoughby, two previous advocates of mathematical plan generation, concluded that “quantitative approaches have a limited use for certain very complex problems, and must always rely on many assumptions that cannot be quantified and on inherited typologies.”
Recently performance has been back on the architectural agenda. Optimisation in the 1960s has much to teach us about the dangers of false optimization and indifference to the resulting architecture. I think this is particularly important as optimisation becomes black-boxed and commodified. So with this warning, I welcome Galapagos, an evolutionary optimizer still in beta, developed for Grasshoppper by David Rutten. In the video below it has been linked with the physics engine Kangaroo to optimise the position of attractors.
Just finished a tool to visualise directed graphs in processing. It uses the bezier curve & box combination from Grasshopper, but since the visualisation is not a development tool, the nodes the free to float into place. I created it to expose the underlying schema of a parametric tool we are developing but it could be modified to display any directed graph /& relational graph.
In general I am not a fan of ‘theorists’ or anything else from the 80s. The exception is Neil Leach. I can still remember the first time I read The Anaesthics of Architecture, cover to cover under the afternoon sun, the whole text resonating. In the domain of digital architecture, even though it does not explicitly discuss the computer, it is significant because it establishes context for the emergence of digital architecture. This context of architecture at the end of the millennium is described by Leach as “Architectural design reduced to the superficial play of empty, seductive forms and philosophy is appropriated as an intellectual veneer to justify forms.”
It is against this Xeroxed backdrop of image based architecture that our current focus on performance emerges. I think Leach has articulated this shift better than anyone else, best summarised in his article Digital Morphogenesis, in Architectural Design, 79 (see full article here). The only critique I have is that Leach tends to downplay the role of the architect in digital morphogenesis, claiming the process is objective when in reality the architect exerts absolute control over the process – either through limiting the application of digital morphogenesis, or acting as an editor. In some cases this has lead to performance replacing philosophy as ‘an intellectual veneer to justify forms.’ Browsing the Grasshopper forum this becomes apparent, where project after project is rendered in the image of performance rather than being performative. In many ways the shift towards performance has been a fulfillment of John Frazer’s warning (issued in 1995) that computers “induce a false sense of having optimised a design which may be fundamentally ill conceived.” Whether or not the performance we are now seeing in architecture is ill conceived or intelligent, Neil Leach has been essential in exposing the trend.
A full list of all Leach’s publications can be found at http://neilleach.wordpress.com/ along with the picture used in this post.