Presentation for CharmCityJS Meetup Feb 1, 2017

Link.

Posted in Software | Tagged , , | Leave a comment

A Simple Discrete-Event Simulation: Part 80

I was working on other things today so the only thing I added to this project was the grid. It’s at a y-elevation of zero. More interestingly, it’s generation is automated, with the relevant code being shown below. Because floating-point numbers can be notoriously touchy after numerous operations I added in the smidge factor to ensure that end lines are always drawn and that the center lines can be found reliably. The center lines can be drawn in a different color if the number of divisions across the total width or length of the grid is even, meaning there will be an odd number of lines.

The grid fits to the layout so well because I make use of the fact that I had the boundary locations available since they’d been calculated to identify the center about which the camera flies and at which it looks. I extended the grid exactly one block in each direction. I wanted the blocks to be (roughly) square so I created more of them in the z-direction than in the x-direction. Last but not least the function can and should be parameterized instead of hard-coded like I’ve done here, but that’s a trivial matter.

I put the following scene together as part of preparations for a presentation. The code for generating the grid is a bit more primitive but this exercise drove me to learn how to modify the endpoints of existing lines as well as their color. In define3DLine we specify the endpoints as a pair of vector objects pushed into an array called vertices. If we want to modify those endpoints we simply dereference them in the other direction. The trick in this case is knowing you need to set the flag which lets the framework know the change needs to be processed internally. Some operation are straightforward — you just change and value and it takes effect (the line’s color works this way as we’ve already seen). In other cases you have to set the flag because the framework has to do something extra in response to the changes that wouldn’t happen naturally.

Always be on the lookout for such gotchas if the first thing you try doesn’t work the way you think it should. As it happens I found the verticesNeedUpdate property when I was using the Firefox debugger to inspect the line I was trying to change. A quick search in the documentation told me that my hunch was correct. You know what they say: RTFM.

You can see the results here, in the lines showing where the camera is located as it orbits the scene. The camera does the same thing in the simulation code demos up to this point as well.

Posted in Simulation | Tagged , , , | Leave a comment

A Simple Discrete-Event Simulation: Part 79

The direct link to the latest version is here. Open this in a new window and try resizing it.

While preparing to give a presentation at the CharmCityJS Meetup this Wednesday I spent quite a bit of time investigating the setup of the 3D display, particularly in full screen mode. The first thing I had to do was make the full screen 3D display work again, since I inadvertently broke it when I updated the base HTML last week. Once that was done I set about making it work the way I want even as the user resizes the browser window.

Here’s the base HTML. In full screen 3D mode the normal components are all set to not display and a renderer canvas element is assigned to fill the entire window. Therefore a single wrapper is used to enclose all of the other elements.

Here’s the code that sets up the 3D display. I originally controlled this with a single variable, virtual3DViewOnly, but realized that making the display 3D and making it stereo/VR could easily be controlled with a separate setting. The stereoVR setting is only used in three places, as it turns out.

If fullScreen3D is set to true the script hides the standard components and attaches a dedicated, full-screen canvas to the window as described. If it is set to false is creates a renderer canvas of a fixed size and attaches it to the target div element. If the stereoVR flag is set then the renderer’s output is piped through an additional transform to produce the stereo display. There are a few other mechanics in place to support changing the size of the window interactively. These are mostly not necessary when not in full screen 3D mode.

The other part of the setup involves adding a camera, which defines the viewing frustum. This is the transform that maps the internal 3D representation of objects to the 2D screen. It requires a field of view angle, an aspect ratio, and settings to clip near and far distances from the viewing point. There’s the relevant Three.js documentation. When the size of the window changes the aspect ratio and field of view angle have to change accordingly.

Here’s how changes to the window size are detected and how the camera parameters are updated. I included links to the pages where I found these methods.

Setting the aspect ratio as the window size changes is straightforward but recalculating the field of view angle was trickier, and that’s where the calcFovBaseX and calcFovAngle functions come in. The field of view angle is given an initial value (of 75 degrees) in the fovBase variable. This angle is applicable to the initial internal height of the window, in pixels. If the height of the window changes we have to back calculate the new field of view angle that keeps the display the same relative size. (Note that you might not want this behavior, but if you do you have to take steps like those I describe here.)

In order to keep the displayed scene a constant size we have to keep the viewing location the same distance from the scene. Consider the following figure:

We want to keep the distance (x) from the viewer to the scene constant as we change the height of the window (y), so we have to find the new angle (a2) to go along with a new window height (y2). In order to do that we need to find the constant distance (x) to use. Remembering that the tangent of an angle is the ratio of the height of a right triangle divided by the width of that triangle we know that:

tan( a1 / 2) = (0.5y1) / x

which means that

x = 0.5y1 / tan( a1 / 2).

We know the original values for y, and a1 so we can calculate x using the calcFovBaseX function. Given a new y2 when the screen size changes, and using our constant x, we can find the new fov angle like this:

a2 = 2 atan( 0.5y2 / x)

This calculation is done in the calcFovAngle function. Remember that we have to convert from degrees to radians and back again to do these calculations properly. A good check to make sure we get both functions right is to generate a base x value for a given field of view angle and window height, then feed that window height back into the second function to be sure it returns that same angle.

Once I got all this straightened out it worked like a charm, and it worked if we’re viewing one 3D image or doing so in stereo. Interestingly, the apparent size of the scene is determined based on the initial viewing frustum and the initial window size. The scene will appear to be different sizes based on the initial size of the window, and will not change even if the size of the window is changed. However, a scene initialized in a larger starting window will appear larger than one initialized in a smaller starting window. The apparent size of the scene is also a function of where the camera is located in the global 3D space, and we’ll experiment with that some tomorrow.

Until then, don’t let anyone tell you that trigonometry never comes up in your everyday life. đŸ™‚

Last but not least you may notice that the shape for the Combined component, (C21) is itself rotating about a y-axis drawn through its center. The locations of the components are all defined relative to their center points (on the x-z plane). If doing 3D transforms natively the procedure is to translate the object so the point you want to rotate around is at the origin of the global 3D space, perform the rotation (or scale or skew) operation, and then translate the object back to where you want it. The makers of Three.js know that’s kind of painful, so they hide all those mechanics from the user and allow the code to just say:

In this example this.component is a reference to one of the shape objects we created and rotation is the total angle of rotation from the original orientation. The y gives access to rotation about the y-axis individually.

Posted in Simulation | Tagged , , | Leave a comment

A Simple Discrete-Event Simulation: Part 78

Today I did a bunch of work behind the scenes, starting with automatically determining the exclusivity of components based on their defined capacities, where appropriate. Queue, Process, Bag, and Combined components are exclusive if their governing capacities are finite and not exclusive if they are infinite. All other component types are always non-exclusive. It could be argued that Process components should never be defined to have infinite capacities when modeling any real system, since the whole purpose is to examine its finite constraints. The same might also be true of bag components. I should probably have the system throw a warning if a user specifies an infinite capacity for a Process or Bag component. Components that can operationally handle an infinite capacity are as a practical matter limited in two ways. One is by the amount of memory that can be allocated to store entities in internal queues and the other is by the number of entities that can be individually displayed.

Next I streamlined a bunch of the initializers for the graphic display components by defining a lot of default parameter values and embedding an assignment into a constructor. This was especially germane to the graphic characteristics of Path components, whose endpoints are usually determined automatically by the non-Path components they are connected to. I also removed references to the internal DisplayGroup mechanisms in the initialization code, but the mechanics remain in place within the component objects.

Finally, in preparation for doing something a little cleaner with the specification of internal entity locations, I redefined the internal arrays that store those locations to be multidimensional. The code is otherwise unchanged, and all locations are saved in master array zero. The goal is to be able to specify locations for different internal entity queues (e.g., parking and exit queues in Bag components, waiting and process queues in Combined components) in their own arrays rather than having to figure out which of the latter locations apply to entities in the second queue. This should also allow for a process to represent multiple, parallel operations, possibly each with their own sub-queues, but that is an idea for later.

The only visible change in the model is that I lowered the queue capacity in the Combined component down to two so I could test to ensure it handles exclusivity properly, which it does. You may have to reset and rerun a couple of times to see enough entities back up in that component, but it happens.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 77

Today I created a combined Queue-Process component I called a Combined component. You can see it in today’s version of the model as component 50, labeled C21, having replaced queue 21 and process 21. I suspect that this will become the default Process component once I have it cleaned up and a bit more bulletproof. I started with a Queue component and then added features until I had the behaviors I wanted. The main change is that the hand-off between the queue and process parts is handled internally and instantaneously. The mechanism for pulling from the previous component had to be adjust as well, as did the code to draw the 2D and 3D graphic displays.

Here’s the code for the new component:

I see numerous opportunities for compressing and streamlining things as I continue to work with this code. One of the insights is that any Queue or Process with a finite capacity is effectively exclusive, so I can probably automate the setting of that value for each component. That will be one of the things I work on tomorrow. I’m also thinking of modifying the way the entities are drawn in the various components. The current code works but is a bit twisty and opaque, so it could stand some clarification and regularizing.

I also fixed the 3D display mechanisms for the entities in the Bag and Combined components.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 76

Today I added a series of Queue and Process components into the pathway traversed by the sub-entities leaving and returning to the Bag component. I found one change I had to make, which was adding the ability of the ReturnFromSubJourney component to return its parent component’s componentGroup value. This was necessary so entities could test to see whether they were leaving the component groups represented by the two new Queue-Process pairs.

I changed the routing to divert more entities over to the Bag component to exercise the added components. I then found that the number of entities in the system exceeded the maximum number of 3D entity objects I’d allocated (which halted the simulation), so I changed the maximum from 35 to 50.

Everything else worked perfectly, including the reporting. It added report sections for “Ped Primary” and “Ped Secondary” (short for Pedestrian Primary and Secondary, or Queue and Process 20 and Queue and Process 21, respectively). I was originally wondering if it would create new sections of reports for the spawned entities but the way I had it set up they retained the Process Speed and Residency properties of their parent entities and the Queue and Process components were set to use those properties.

It suddenly occurred to me how to make a combined Queue-Process component, and also a process component with multiple, parallel processing positions. Both of these ideas had been on my To Do list for a while, so that’s what I’ll work on tomorrow. Such a component will greatly compress and simplify the specification and layout of a simulation system.

Last but not least I seriously reworked the basic HTML and CSS configuration.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 75

Today I expanded the capability of the Bag component to allow entities to reside there, spawn new sub-entities that undergo an external process of their own, and return to the “parked” entity. Delay times can be specified that control how long it takes the spawned sub-entity to start moving once the main entity parks, and how long it takes the before main entity transfers to the exit queue once the sub-entity returns. Think of the delays like this. You drive into a parking lot and park. Then you gather up your belongings, paperwork, and do whatever else you might have to before walking in to your next activity. The activity has its own duration, at which point you walk back to your parked car. Then you put all your stuff back in the car, get settled as you need to, and you finally drive out of the parking lot. The spawned entity is, in our example, colored orange. When it is waiting at the main entity within the Bag component is is displayed on top of the main entity that spawned it, a handful of pixels up and to the right.

The value for the Bag component’s process time has no meaning in this case, though perhaps it should double as one or both of the delay times.

Two new components were created to serve as the internal “entry” into the sub-process and “exit” back out of the sub-process. They have as little of the machinery common to the other component types as possible. When entities are forwarded to them they are immediately forwarded to their next component. The source component can only connect to a single, downstream component, but multiple upstream components can be connected to the destination component.

The external system can be made up of any types of components (except Entry or Exit components) but I’ve included only two paths so I didn’t have to think about reporting on top of everything else I did today. That will be tomorrow’s project. The process of traversing an external system is referred to as a “sub-journey” and the new components and processes are named accordingly.

Here’s the updated code for the Bag component:

Here are the new source and destination components:

Here’s the code that defines the entire system:

Some adjustments had to be made to the DisplayElement object as well, to handle drawing the 2D and 3D versions of the new components.

I also made the background transparent so it’ll look a bit nicer in an iframe and need to do something more explicit with the 3D versions of the sub-entities.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 74

Following yesterday’s work I had three tasks to complete. The first task was to fix the reporting for cases where a Process or Bag component is not the last item in a component group. The fix was to only run the reporting process for exiting a group when the entity leaving a Process or Bag component is going to a different non-Path component that’s in a different group. This involved embedding the report function at the end of the forwardEntity function in the if statement shown below.

The getComponentGroup function in Path components had to be modified so it actually returns the component group of its next component, so it always returns the component group of the next non-Path component.

The second task was to experiment with different ways of specifying the process time for certain components in a modular way. I originally passed in an array of values and called a fixed, external function to determine the array index to use base on the relevant entity’s user-defined properties. Later I added an additional index to the process so different Process or Bag components could generate lookup indices based on different properties or combinations of properties. I then realized that I could simply pass a custom function in for each case. The code for one way of doing this is here:

If we want to retain some additional form of external modularity of parameters we could do something like this:

The possibilities are many.

The third and final task was to allow the simulation to run until it is empty if a specific flag is set. I defined a global variable called runToEmptyFlag and modified two tests that control when to stop the simulation and when to stop recording data. The logic says to run to at least the minimum time and then stop if runToEmptyFlag is false, or keep going until there are no entities left in the system if runToEmptyFlag is true. Today’s version of the model has the flag set to true, so it will run beyond 630 time units as long as there are entities still in the system. If the first run doesn’t run past that time because it clears out then reset and rerun it until you see the desired behavior. The runtimes can vary quite a bit depending on how the type and routing dice fall.

I noticed that the final time increment would not be reported properly if the systems runs to empty beyond its allotted time. The fix was to add in an extra reporting increment if the global clock is greater than the number of reporting cycles run times the number of time units per cycle.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 73

Today I added the Bag component (number 36 in the frame above), which you can think of as a parking lot. It works largely the same way as a ProcessComponent but it doesn’t store its entities in a FIFO queue internally. Rather, it defines a list of entities with one space for each possible entity up to the defined maxCapacity of the component. An entity enters the component, gets assigned to the lowest empty index in the list, and begins working off its defined process time. When the process time ends the entity is moved over to an exit queue, which is another list of entities within the Bag component. The exit queue shows which entities are waiting to leave the Bag component, which is only relevant if the next downstream component is an exclusive one that is not currently open. I added a downstream Process component to the model in order to visually demonstrate this behavior.

The procedure for drawing the entities in the linked displayElement is a bit different than for the queue or process components. The designer should specify more entityLocs spaces than the capacity of the component. The first maxCapacity spaces are used to display the entities while they are “parked”. Any additional spaces are used to display the entities waiting in the exit queue. The Bag component in today’s version of the example model has a capacity of twelve and an additional five spaces reserved to show the exit queue. If there are more entities in the internal exit queue than there are spaces left to display them then the extras do not get displayed. One trick to make this more visually interesting, if it’s appropriate to the real process being modeled, is to assign the entity locations up to the Bag’s capacity in a semi-random order. That way the entities look like they’re parking in a more naturalistic manner rather than obediently filling spaces in regimented order. The border modeling programs I worked with at Regal Decision Systems (BorderWizard, CanSim, and SimFronteras) all allowed for this, and the effect was particularly striking in situations where there were large numbers of vehicles in a parking area. The commercial parking area at Ambassador Bridge in Detroit used to fill up in a big way when many trucks needed to park so the drivers could attend to customs paperwork. (That process has since been largely obviated by automating the paperwork so it’s completed offsite before the vehicle makes the crossing.)

Having a Bag component feed directly into another component that’s exclusive should probably be rare, but the full behavior is included. I’m thinking of my time analyzing and collecting data at dozens of border crossings where vehicles and pedestrians were almost always able to leave a Process or Bag (parking lot, literally) and go someplace else. There was effectively a non-exclusive queue in front of most processes and parking lots. That said, one can easily imagine a tightly coupled manufacturing process when internal queues have been squeezed out by design or after rearrangement following a Lean analysis.

Here’s the code for the entire Bag component.

I had to add the parameter processTimeSwitch to allow different type indices to be used for determining the process time for each entity type. The process times are provided to the component as an array of values meant to apply to different types using the function entityProcessTimeIndex(entity,this.processTimeSwitch). In the primary Process components I wanted the types to be based on a combination of the entity’s residency and process speed. In the secondary group I specified the same time for all types so it didn’t matter what indices were used. I noticed the problem when I was looking at the report output for the “Parking Lot” group when there was no Process component in place after the Bag component. I had defined process times of 30, 50, and 80 units envisioning that they would apply to citizens, LPRs, and visitors, respectively, but the process times reported for those types varied in ways I didn’t expect. Then I remembered how the entityProcessTimeIndex function worked and added a switch to it to allow different indices to be generated based on an entity’s properties. That index had to be added to the component definition for both the Bag and Process components.

Since JavaScript is so modular it should be possible to supply a custom function to the processTime parameter that embodies any combination of indices and process time values. I’ll experiment with that tomorrow.

Here’s the updated code for drawing the display element.

I tested the Bag component with and without the subsequent Process component and everything worked as it should procedurally. I also assigned the Bag and Process components to a componentGroup called “Parking Lot” and the reporting mechanism picked up the new group and reported it like a champ. However, I noticed that there were negative entity counts during some time intervals in the “Parking Lot” section of the report for each entity type. I traced this down to the erroneous assumption that exiting a Process or Bag component should always trigger recording an exit from a component group. This worked fine when the groups start with a Queue component and end with a Process component, but not so well when a group contained multiple Process and Bag components in series. I therefore have to add a test to see whether an entity is truly exiting a component group before triggering the exit reporting mechanism. That will be another part of tomorrow’s work.

Last but not least I’ll update the framework so it can be allowed to run until all entities have cleared the system, after a specified minimum running time. This is not always the desired behavior for analysis or reporting, so a switch setting will have to be included as well.

Posted in Simulation | Tagged , | Leave a comment

A Simple Discrete-Event Simulation: Part 72

Following last week’s investigations I tried moving all of the functions inside the EntityPassive object (closure) to the outside, to be attached as external prototype functions. As I discovered, in keeping with what I’ve read, attaching the functions outside of the object results in a much smaller memory footprint. With internal functions the object took up 144 bytes and with external functions it consumed 480. There are other differences as well, as indicated by the before-and-after memory comparisons generated using the Memory Inspector in Firefox.

480 bytes, by the way, is a 224-byte base allocation plus a 64-byte incremental allocation plus a 128-byte allocation, as I described in my last post. You might want to keep this mechanism in the back of your mind if you’re working on a memory-intensive application, particularly when the objects are larger or there are large numbers of objects to be allocated.

Here’s the usage for internally declared functions:

Here’s the usage for externally declared functions:

The code runs without a hitch either way.

One caution about using the Memory Inspector in Firefox: you should probably take at least two snapshots of every state. I’ve found that the first pass doesn’t generate consistent information but subsequent passes seem to get a more accurate read on what’s there.

Posted in Simulation | Tagged , , | Leave a comment