is lately. I believe you are absolutely right to say that the type of behavior to be modelled will define if we actually need an ABM interface. If, as you say, the parameters modelled are temperature or radiation, then I imagine that a lot of studies can be done within E+, perhaps in the stepwise way you described earlier.
Additionally, and this is my main critic on ABM in general but I'll leave it for another discussion, the degree of freedom or interaction with the environment that an agent has dictates the possibilities for an ABM. In typical models this has to do with how you model innovation in agents, changes in their practices and norms (which generally isn't there in ABM models). In our case, it related to the type of environments our agents are situated in.
I can imagine two extreme cases of environments, with ofc a gradient of possible worlds between: the mechanically conditioned building and the naturally ventillated building.
In the first case, which btw is the one most encountered in my part of the world, the agents have minimal, to sometimes zero, control on their environment and no capabilities of adaptation and change. Imagine a typical building where the set points are set centrally, windows are not operable, and even the shading devices are sometimes out of their reach.
In this case, I can imagine ABM models helping only as a post processing tool. What that means is that we could potentially use them to analyze occupant behavior within this controlled environment. E+ would give us the hourly space performance and we would feed that to agents to see how they respond. Ofc, in terms of thermal comfort this is almost what your tools are doing. So, such an approach would have little value in an office building for example where people are assumed static but could be interesting in retail buildings where we could potentially model occupant movement according to building performance. The limits of this approach then is some sort of scenario testing of different settings and occupant (response) behavior to them. Here of course, you have a valid point of other building characteristics that should be modelled, apart from climate.
In the second case, that of an adaptive building, I believe ABM can be a tool that can be used in a co-simulation approach, as it has been used in the site Mostapha mentioned above. Again though, in ABM it is critical to not overdefine behavior but on the contrary to generate behavior from assigning simple rules to agents. This makes it difficult for me to find the limit of detail in the functions/statistics used to model occupant actions within the building (on windows, shading, thermostats, etc.).
Since ABM is better fitted to generate patterns that we encounter in the real world, I thought of developing a model that might do exactly that. It took me a while to think of a pattern that would be interesting, but I think I finally have it. It is a bit of a grand gesture of course, but should be worth it.
As you know better than me from your research, the adaptive comfort studies found a quite peculiar fact about the tropics. The sentence went something like this (I'm botching it probably), "people in the tropics tend to prefer environments that are below the limits of their neutral comfort". Or simpler, people just want to the space to be colder than what one calls neutral.
My simple minded explanation, after leaving in the region, is that the explanation for this is to be found in the interface between outside and inside. The temperature gradient in that interface is what makes people feel more comfortable in uncomfortable (i.e. colder) conditions.
So what if we would introduce a shaded, open, naturally ventilated space prior to a MV building's entrance and then increase your indoor temperatures in the building? Or what if we introduced a temperature gradient in the different spaces a visitor/occupant passes through as he enters the building. I feel that energy modelling cannot really understand the impact of these interventions on occupants, at least in its basic form. I think this is where ABM could be useful. Building a model that can generate the above mentioned pattern and then using it to analyze different types of strategies to occupant behavior.
I wanted to write the things above in a more structured way but I forgot my cheat-sheet at home :) I hope I made some sense.
I will try and be patient and follow the route you suggest however, understanding the E+ resources first and then moving to connecting it to ABM.
I just thought I'd describe the sort of research questions I have in mind for this, hoping someone finds it interesting as well!
Kind regards,
Theodore.
P.S.: I have left out other areas that would be suitable for ABM modeling within buildings. For example the area of health and safety. ABM is an amazing tool to model occupant behavior in extreme events, e.g. fire in a building or toxic smoke, etc. in order to analyze evacuation patterns and optimize building design. Even though this is something I am also interested, I intentionally did not go into it since we are mostly dealing with environmental design here.
…
ting at multiple geometries in the same location. I simply sorted the list of values and used the Delete Consecutive component. This potentially rearranges the order of values but I don't think that matters in your case. I also threw in an Int component which actually seems to make a difference (try sidestepping it and you will see!).
2-I flattened the output of the mesh component before sending it to union. This ensures that the original mesh is booleaned once with all the components rather than individually with each of the 86 components.
Is this what the result should look like?
One suggestion for future postings: when referencing geometry in rhino, it often helps if you attach your rhino file as well so people don't have to guess where you are starting from.
If you have further questions, just ask ;-)
cbass…
.
Things have been working swimmingly in many areas of the plugin, but one particular problem has been tough to solve. I have two components that are trying to read/write to the same memory at the same time, causing Rhino exceptions and crashes.
The conflicts appear to be happening between two components -- one is a "Layer Events Listener" that reports essentially what type of layer event just happened. The other is a "Set Layer Visibility" component that toggles the visibility of a list of layers.
The code:
public class LayerTools_LayerEventsListener : GH_Component { /// <summary> /// Initializes a new instance of the LayerTools_LayerListener class. /// </summary> public LayerTools_LayerEventsListener() : base("Layer Events Listener", "Layer Listener", "Get granular information about the layer events happening in the Rhino document.", "Squirrel", "Layer Tools") { }
/// <summary> /// Registers all the input parameters for this component. /// </summary> protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) { pManager.AddBooleanParameter("Active", "A", "Set to true to listen to layer events in the Rhino document.", GH_ParamAccess.item, false); pManager.AddTextParameter("Exclusions", "E", "Provide a list of exclusions to stop reading specific events (Added, Deleted, Moved, Renamed, Locked, Visibility, Color, Active).", GH_ParamAccess.list); pManager[1].Optional = true; }
/// <summary> /// Registers all the output parameters for this component. /// </summary> protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) { pManager.AddBooleanParameter("Initialized", "I", "Whether the listener changed from passive to active.", GH_ParamAccess.item); pManager.AddTextParameter("Document Name", "doc", "Name of the Rhino document that is changing.", GH_ParamAccess.item); pManager.AddTextParameter("Layer Path", "path", "Path of the modifed layer.", GH_ParamAccess.item); pManager.AddIntegerParameter("Layer Index", "ID", "Index of the modified layer.", GH_ParamAccess.item); pManager.AddIntegerParameter("Sort Index", "SID", "Sort index of the modified layer.", GH_ParamAccess.item); pManager.AddTextParameter("Event Type", "T", "Type of the modification.", GH_ParamAccess.item); pManager.AddBooleanParameter("Added", "A", "If the layer has been added.", GH_ParamAccess.item); pManager.AddBooleanParameter("Deleted", "D", "If the layer has been deleted.", GH_ParamAccess.item); pManager.AddBooleanParameter("Moved", "M", "If the layer has been moved.", GH_ParamAccess.item); pManager.AddBooleanParameter("Renamed", "R", "If the layer has been renamed.", GH_ParamAccess.item); pManager.AddBooleanParameter("Locked", "L", "If the layer locked setting has changed.", GH_ParamAccess.item); pManager.AddBooleanParameter("Visibility", "V", "If the layer's visibility has changed.", GH_ParamAccess.item); pManager.AddBooleanParameter("Color", "C", "If the layer's color has changed.", GH_ParamAccess.item); pManager.AddBooleanParameter("Active", "Act", "If the active layer has changed.", GH_ParamAccess.item); }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { bool active = false; List<string> exclusions = new List<string>();
DA.GetData(0, ref active); DA.GetDataList(1, exclusions);
RhinoDoc thisDoc = null;
bool initialize = false;
string dName = null; string activePath = null; int layerIndex = -1; int sortIndex = -1; string eventType = null; bool added = false; bool deleted = false; bool moved = false; bool renamed = false; bool locked = false; bool visibility = false; bool color = false; bool current = false;
if (active) { thisDoc = RhinoDoc.ActiveDoc;
initialize = (!previouslyActive) ? true : false;
RhinoDoc.LayerTableEvent -= RhinoDoc_LayerTableEvent; RhinoDoc.LayerTableEvent += RhinoDoc_LayerTableEvent; previouslyActive = true;
} else {
RhinoDoc.LayerTableEvent -= RhinoDoc_LayerTableEvent; previouslyActive = false; }
if (ev != null) { dName = ev.Document.Name; layerIndex = ev.LayerIndex; eventType = ev.EventType.ToString();
if (!exclusions.Contains("Active")) { if (ev.EventType.ToString() == "Current") { // active layer has just been changed current = true; }
}
if (!exclusions.Contains("Moved")) { if (ev.EventType.ToString() == "Sorted") { // active layer has just been changed moved = true; }
}
if (!exclusions.Contains("Added")) { if (ev.EventType.ToString() == "Added") { // layer has just been added activePath = ev.NewState.FullPath; added = true; }
}
if (!exclusions.Contains("Active")) { if (ev.EventType.ToString() == "Deleted") { // layer has just been added
deleted = true; } }
if (ev.EventType.ToString() == "Modified") { // layer has been modified activePath = ev.NewState.FullPath;
//skip sortindex eventType = ev.EventType.ToString();
if (ev.OldState != null && ev.NewState != null) { if (!exclusions.Contains("Locked")) { if (ev.OldState.IsLocked != ev.NewState.IsLocked) locked = true;
} if (!exclusions.Contains("Visibility")) { if (ev.OldState.IsVisible != ev.NewState.IsVisible) visibility = true; }
if (!exclusions.Contains("Moved")) { if (ev.OldState.ParentLayerId != ev.NewState.ParentLayerId) moved = true; }
//if (ev.OldState.SortIndex != ev.NewState.SortIndex) moved = true; if (!exclusions.Contains("Renamed")) { if (ev.OldState.Name != ev.NewState.Name) renamed = true; }
if (!exclusions.Contains("Color")) { if (ev.OldState.Color != ev.NewState.Color) color = true; } }
} }
DA.SetData(0, initialize); DA.SetData(1, dName); DA.SetData(2, activePath); DA.SetData(3, layerIndex); DA.SetData(4, sortIndex); DA.SetData(5, eventType); DA.SetData(6, added); DA.SetData(7, deleted); DA.SetData(8, moved); DA.SetData(9, renamed); DA.SetData(10, locked); DA.SetData(11, visibility); DA.SetData(12, color); DA.SetData(13, current);
}
static bool previouslyActive = false; Rhino.DocObjects.Tables.LayerTableEventArgs ev = null;
void RhinoDoc_LayerTableEvent(object sender, Rhino.DocObjects.Tables.LayerTableEventArgs e) { ev = e;this.ExpireSolution(true); }
And for the layer visibility component:
public LayerTools_SetActiveLayer() : base("Set Active Layer", "SetActiveLayer", "Set the active layer in the Rhino document.", "Squirrel", "Layer Tools") { }
/// <summary> /// Registers all the input parameters for this component. /// </summary> protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) { pManager.AddBooleanParameter("Active", "A", "Set to true to change the active layer in Rhino.", GH_ParamAccess.item, false); pManager.AddTextParameter("Path", "P", "Full path of the layer to be activated.", GH_ParamAccess.item); }
/// <summary> /// Registers all the output parameters for this component. /// </summary> protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) { pManager.AddIntegerParameter("Layer ID", "ID", "Index of layer that has been activated.", GH_ParamAccess.item); pManager.AddBooleanParameter("Status", "St", "True when the layer has been activated.", GH_ParamAccess.item); }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { bool active = false; string path = "";
if (!DA.GetData(0, ref active)) return; if (!DA.GetData(1, ref path)) return;
int layer_index = -1; bool status = false;
if (path != null) {
Rhino.RhinoDoc doc = Rhino.RhinoDoc.ActiveDoc; Rhino.DocObjects.Tables.LayerTable layertable = doc.Layers;
layer_index = layertable.FindByFullPath(path, true);
if (layer_index > 0) { // if exists RhinoDoc.ActiveDoc.Layers.SetCurrentLayerIndex(layer_index, true); status = true; } }
DA.SetData(0, layer_index); DA.SetData(1, status); }
Now originally I was getting exceptions when changing multiple layers' visibility properties, which would cause the Event Listener to fire and try to read the Visibility property before the memory has been released by the Set Layer Visibility component. That led me to add an "Exceptions" input, that would allow me to disable the reading of Visibility events at the source in the Layer Events listener. That helped me manage about 95% of the crashes I was getting, but I still get strange crashes in other event properties, even when that property shouldn't be affected. For instance, I am getting a crash here on the Name property in the event from the delegate function, even though I am only changing Visibility at any one time:
I have a few ideas but they all seem pretty hacky. One is to try to set a flag that is readable by any component in the plugin -- so that the event listener can see if a "set" component is currently running and abort before causing an exception. The other is creating a delay in the event listener, somthing like 200ms, to allow any set components to finish what they are doing before reading the event. Neither seems super ideal.
Any ideas?
Thanks,
Marc
…
currently within a fake euphoria framework - blame China/UAE) and a potential decision about doing/developing this or doing that … well …anyway … read and enjoy.
AEC matters: The good, the bad and the ugly.
The bad news: Rhino is NOT suitable for the job (although some use it … but only in the sense that people use Modo for the so called “hard modeling”). By job I mean things up to shop drawing level + specs + you and me (we call it Final level) – nothing to do with sketches and outlines of some abstract “schematic” topology.
The ugly news: The so called Design-Construct approach gains exponentially momentum especially in countries the likes of China/UAE/BRICS (95% of the whole AEC activity worldwide happens there). DeCo means: AEC engineers deliver some kind of study in a preliminary level and the main contractor splits (outsourcers) the job and assigns the study completion AND the construction to various sup-constructors. That thing appeared first – in a large scale - in Dubai 15 years ago. This means that the era of Sergio Pininfarina is over and out: welcome anonymous Toyota designer. In plain English: days of construction corporations fast replacing practices. Dead men walking.
The good news: All AEC related apps (Revit, AECOsim, Allplan and the likes) are in a lethargic state as regards the brave new world (based on the archaic level driven organization schemas etc etc). Of course they all claim the exact opposite and point that support BIM (nobody mention PLM) better than the other guy. But the 21st century – helped by 2 forthcoming unavoidable crisis (a) about shortage of water (b) about transition from carbon to hydrogen economy – isn’t about bureaucracy: think cost/resources optimization and “fitness” rather than China/UAE type of liquid trend. Days of euphoria fast approaching the Wall.
Top to bottom and visa versa.
Old days Titans (Oscar, Mies, Walter, Pierre Luigi, Frank, Eero, blah blah) outlined things (mostly using crayons) and the rest were struggling to translate these in reality in an one way vector like process : Top to bottom that is. These days the inverse gains momentum : when in the whole consider the part … validate … redo … validate … redo. This means bottom to top geared with top-to-bottom. In plain English : child imposes rules to parent and parent imposes rules to child. This means classic MCAD feature/history modeling (CATIA/NX/MS). This is something that Rhino can’t do (not to mention that Rhino is a surface modeler – a rather critical fact).
The parts that are bigger than the whole.
Go there ( http://www.behance.net/gallery/2885057/a-myriad-of-cables) are inspect the whole thing: it’s a parametric nightmare made with the other guy (Generative Components – slower than a Skoda + bugs + why bother?). But the whole (masts and membranes and the likes) means nothing here: focus to the details that are critical for connecting this with that. Complex feature driven solids that are made with internal (on a per se basis) parameters (like fillets required for casting or radius for cable anchoring) whilst they comply with external rules/parameters (cable angles, topology clash issues etc etc). So the whole outlines possibilities … and the part either can follow…or the part must change…or the whole must change. Can you do that with GH/Rhino? And if not what’s missing? (lot’s of things to be honest).
Some other "similar" things:
The narrow picture.
I agree with what others already said and with pretty much all Ola’s points – especially the visual drag-and-drop path mapper (i.e. a visual data manipulator so to speak) and the enable/disable components in groups capability.
Some other suggestions:
A multi canvas capability. As things are right now…it’s like working in Rhino in one view (rather unsuitable I guess). In fact …since overlapping views they don’t work in Rhino…well…you know, he he.
A working auto profile arrangement capability (non twisted Loft/Sweep and the likes). Worth 1Bn dollars that one.
Ability to locate components that caused this or that in the Rhino view: meaning a 2 way communication approach : GH makes things happen in Rhino and things can indicate their cause in the GH canvas.
A robust collection of components that bake stuff in nested blocks (emulating some primitive assembly/component way of thinking). Why may you ask? Well … the whole objective is to talk to CATIA (via STEP) don’t you agree? CATIA makes things happen in real-life not Rhino.
A robust collection of components that can create real-life parametric tensile membrane solutions (get some inspiration from FormFinder: useless because it’s academic but good to point the way). Membranes (and geodesics) are the future.
I could continue at infinitum but IMHO the big picture is worth 12345,67 “focused” GH improvements.
May the Force (the dark option) be with us all.
…
ld be the best UI.
I think difference is made by 'Slider = 10' vs 'Slider = 10.000' more than by simple input/component initialization so, why to stop when it could be even more powerful?
Slider = 0 To 5 --- Slider in [0, 5]
Slider = {3; 0 To 5}
Slider = {3;0;5}
Slider = 3;0;5
Slider = 3 0:5
Slider = 3,0,5
Slider = 3 0 5 --- Value and range (min max)
3 0.0 5 --- 3.0 0.0 5.0
3 0 5.0 --- 3.0 0.0 5.0
3.0 0 5 --- 3.0 0.0 5.0
-1 0 5 --- 0 0 5 (-1 -1 5)
6 0 5 --- 5 0 5 (6 0 6)
Slider = 0:2:6 --- Even numbers: 0, 2, 4, 6.
Slider = 1:2:7 --- Odd numbers: 1, 3, 5, 7.
0:2:5 --- 0:2:4 (or 0:2:6)
3:2:8 --- 3:2:7 (or 3:2:9)
3 1:2:7 --- 1 3 5 7 (value 3)
Bang! = 7 --- 7 outputs
Merge = 5 --- 5 inputs
What's your opinion about Bang! = 7? As it's setting number of inputs, should it use different format? Bang! 7? Bang! (7)? Bang! i7?
+ * - / \ % ^ & | ! = > --- Addition, Multiplication, Subtraction, Division, Integer Division, Modulus, Power, AND, OR, NOT, Larger than, &c.
= could be a problem.
\ Integer division or Set difference?
! could be NOT but also Factorial.
| could mean intersection.
& could mean concatenate.
1+ --- Addition: input A = 1
2* --- Multiplication: input A = 2
+{0,1,1} --- Addition: input B = {0,1,1}
0-, 1/, 2^, 10^, e^ have their own components
Flatten = {7} or Flatten = 7 --- Input P = {7} (off-topic: Why can’t P be a list?)
Pt = {1, 2, 3} --- Point XYZ, X = 1, Y = 2, Z = 3.
Swatch = 129,239,231 (102)
Swatch = 129 139 231 102
F2 = "x^2+y"
"List Length" and "List Insert" don't work properly: "Value List" is choosen. Why? What's the reason to this choice? Well, I'd like to know how the whole thing (search by keywords) works, David.
Name and nickname can be now used as keywords. "Larger" works for ">" but "greater" doesn't. Could it be improved? Could synonyms be used? Could a short description even be used (I know this could be a bit weird)?
more than --- >
more or less --- Similarity
more less --- Similarity
red green --- Sets.List components should be showed
lightning --- Split Tree
What about use Curve.Analysis or Math.Boolean to display those Tab.Panel components? Param, Math, Sets, Vector? Primitive, Special, Util? Tab, Panel, and Tab.Panel as keywords.
At the moment that I write this, I check that ignoring accents in keywords has almost been included (0.8.0009): p`anel, pañel, pánel --- panel (almost)
Shouldn’t 'Dom2' work for Dom²?
What about nested search? You type some keywords (say 'Params' or 'Params.Geometry', or 'red green', or 'lst') and then you make a fine-tunning search over previous results/keywords. Tab.Panel and/or nested geometry could be useful when search by plug-in is desired or when you want to search among .ghuser components (first 'ghuser' or 'Extra.MyPlugIn' or 'lst' keyword and then fine-tunning, specific, search).
Is 'list length' performing this nested search right now ('lst' > 'length')? Anyway, I am thinking about UI (graphical) changes; successive searches.
As I said, description (and even words from the help info) could be used to search. What about "some kind of tags"? I mean that if 'list l' to finally choose List Length has been used for a while, that could be learned. Eventually, an XML file could store these tags, so you could even edit them. That could implement description, name, nickname, help info, Tab.Panel, .ghuser, synonyms (lots of them), tags/shortcuts or wathever.
How could flatten/graft/reverse be used? Initialize graft+Simplify or graft+Bang! could be really useful.
What about expressions? I don't how could it be done properly: would Slider = x^2 (expression) work? I mean, aren't expressions parsed when initializing?
Is Panel somehow doing this? 'panel = wathever' always suppose that wathever is a string, so you can't use 'panel = <pi>'. Sets.Strings components also do this.
I've been about to write several paragraphs about height/width (resizable components: Panel, Graph Mapper, Slider, &c.), input/output names (Scripts, F components; or any component with editable input/output names), orientation (Scribble), type hint and access option, nickname, &c. but, to sum up: being able to set any property when initializing would be really useful. I'd like to know the best choice of syntax but I'm sure that, David, you're closer to the answer. What do you think about this?
Slider: 3 0 5 "MySlider" "Slider^2"
Panel: "This is the content" "This is the title"
VB: "N" List Integer 7 "r" Item Double
Addition: A 1 B 2
I guess that any unified syntax would be elegant and useful, but additional ad hoc syntax (per component) could be even better (cleaner).
What about use lists of values? I'm not sure about format: panel = ("Hello", "Bonjour", "Hola")? If any valid format/syntax is found, maybe more sophisticated fetaures could be achieved: panel = {0;0} ("A", "B", "C") {0;1} ("1", "2", "3") How would you like this to be implemented?
There is a much simpler and interesting feature that would be useful, in my opinion: being able to initialize more than one component. I mean say 7xSlider = 10.0 and get 7 sliders and I also mean multiline (multi-component) initialization: Ctrl+Intro when you want to start a new line and Intro (or even some Accept/Cancel buttons when you activate multiline mode) to initialize (every line/component), for example. I mean:
3 x Slider = 1
Panel
Mass addition
Panel
And the whole bunch of components that were in mind (pre-thinked definition) is initialized. It speeds up the workflow, making more dynamic to add components that are only available via the drop-down panels.
Should this multiplier be something like a text box adjacent to search field more than '7x'?
These are some of my thoughts about intitializing. Please let me know your opinion :]
…