Hey there everyone. Thanks for joining our session. Today we're going to be talking about pre-sale checks. Do you need a checklist before sailing to production with Istio? First off, just a quick round of introductions. My name is Simon Green and I'm a field engineer here at Solo. I'm based in Boston, Massachusetts and I'm very proud to say this is actually my first Istio con and actually I haven't been part of the Istio community for that long. In my prior life I've contributed to Apache Camel and ActiveMQ and Kafka and I've got roughly 25 years or so experience working in the app dev world. And over to you, Ron. Hey everyone. My name is Ron Venom. I'm also at Solo. I lead one of the field engineering teams called Special Operations. And what my team does is it focuses on providing mesh-based solutions for some of the more complex use cases. So I focused on like enterprise customers and some of the larger multi-tenant environments. I've been working on Istio since almost the beginning of the project. So before joining Solo almost three years ago I was at IBM also working on Istio. So yeah, glad to be here and I'm glad to continue being able to be a speaker and present to the Istio community. Happy to be here. Perfect. Thanks, Ron. So first off, for those of you that don't know me, I've been a pilot also roughly for I guess 15 or so years. And as a pilot using checklist was always something that was drummed into me back as far as my primary training. So not only things like pre-flight checklist, but checklist for all phases of flight, whether it's takeoff, cruise, descent or landing. And of course we also use them for emergencies. What we're looking at right now is my airplane. It's a highly modified 1949 Temco Swift, building Dallas, Texas. And what's unique about this is it has over 150 airframe modifications. And because of this, there was never a checklist for this unique bird. So what I had to do is go ahead and write my own. And here is the checklist I wrote. So this is a checklist that covers everything that I could possibly need to do, including what to do in an emergency. In fact, I actually had an in-flight emergency once where my landing gear wouldn't extend. So luckily I had a passenger to help me. What we call this is crew resource management, or CRM. So my passenger kindly took the checklist, read it line by line what tasks I needed to accomplish in order to troubleshoot my production outage, so he read and I verified. This resulted in a really positive outcome. I was able to help identify an electrical fault which could be resolved by cycling the flaps three to four times. And further extending CRM, I included the control tower to help me verify and check that my landing gear was in fact extended and I was cleared to land. And what does all of this mean? Checklist facilitate teamwork. So the question is why am I telling you all of this? Remember, whether it's for something like piloting an airplane or a surgeon in the operating theater who doesn't want to forget a scalpel in their patient or a platform SRE responsible for business critical workloads, we need a clearly defined checklist. A checklist is intended for the pilot though, not for the mechanic. We're focused on checking the oil, not changing it. In other words, we worry about solving the issue later in a more controlled manner. Use the checklist to help identify shortcomings or gaps, either during production readiness or an outage. Taking what I've learned as an aviator, Ram and I have embarked on drafting an Istio readiness checklist which you can see over here on the right hand side. This checklist is intended for the platform ops team. Those who are focused on day two ops, not day zero. Intention is not to go into the internals of how Istio works, but more about identifying gaps or outliers. So what we're going to do in today's session is help you build your own checklist, just like I did for my highly modified airplane. Ram and I have put together a bunch of different customer case studies where we were able to observe the problem, check and validate what was wrong and help the customer with a positive outcome. And with that, our first example is the orphan sidecar problem. So for this particular case, we had a customer come to us with a problem that some of their services were not behaving well. They were seeing random intermittent errors and this just started happening out of the blue. So as field engineers, Ram and I asked them what had changed in the system leading up to this particular event. They mentioned that they'd recently upgraded Istio but didn't think it was part of the issue because things were working fine after the upgrade. We helped narrow down the problem to just a few microservices and observed in the sidecar logs that there were endpoint and certificate related errors. So from the customer's perspective, this was difficult to troubleshoot and mostly because of the intermittent and the random nature of when it started occurring. It wasn't all of the services in the mesh. It was only a subset of them and it wasn't all destinations or all endpoints that the mesh service was trying to route to. That was also intermittent. So because of that, we started going down first thing we checked, make sure Istio D is okay and Istio D didn't have any errors. The sidecar logs showed access logs. We turned on access log and looked at the access log and most of them were working and then we're seeing errors in some of them but not all of them. There was a few warning messages but it wasn't enough for a customer to quickly debug themselves. The issue was that some of these sidecars were orphaned from Istio D. After they did the upgrade, they did a revision upgrade, installed a new control plane and took out the old one and then they didn't complete the entire process of moving all the sidecars to the new one. The way a sidecar works when it receives config from Istio D, the control plane, it is self-sufficient for a while. With that configuration, it will continue running until things like the endpoints that it's trying to get to are stale. The config gets stale because no one's updating it and then any certificates that it no longer receives from Istio D. That was the reason why the customer wasn't able to identify the problem for a while, especially because if you're not making any strong, strict MTLS communications to other sidecars, then it might be a couple of days before you notice a potential problem. The solution for all this, in your checklist, obviously make sure that you run all of the stuff that Istio tells you to do before and after an upgrade to make sure all the sidecars are moved over. To also prevent other orphaned sidecar problems, there are metrics exposed on the sidecar side. Envoy, cluster manager, cluster updated metric, for example, or there's a CDS update time and an LDS update time metric that each sidecar emits. Set up an alert, make sure that if that's going past a certain number of hours without any upgrade, you probably haven't have an outage that's about to hit your lane. Perfect. One of our Istio support customers, this is another example, recently endured a production outage during an extremely busy trading weekend. After further investigation, they determined that all of their virtual services were missing. This is really strange though, because the developers don't have access to delete all the virtual services across namespaces. They should have proper boundaries in place around their namespaces to prevent this. So how did this happen? A lot of customers that we work with have large environments where they have a platform team that's responsible for installing platform related things, things like Istio, onto the cluster, and then each individual development team or a tenant operates in their own sets of namespaces. So when they install Istio, things like the Istio control plane and maybe the Istio gateways, they protected all of those and all of those namespaces from their tenants from being able to modify. That's kind of obvious. And then they used an RBAC to make sure that every namespace and every developer that namespace can create their appropriate resources that they deem that they should be allowed to create. What they fail to protect are the cluster scope ones, things like the Istio CRDs, not the CRs, but the CRD itself. So what happens if you delete a CRD, like the Istio virtual service CRD, all of the CRs get deleted. So this is another checklist item to make sure that you have proper, if you're using a multi-tenant environment, you're using the proper Kubernetes RBAC controls to make sure that you're not only protecting the stuff that's inside the namespace and namespace scoped, etc., but you're also protecting things like the CRDs. So just make sure you lock down access as much as possible. A lot of times what we've seen is that this is not malicious. It is purely accidental. One of the tenants, they couldn't get something working. So instead of accidentally deleting a CR or CRD, they delete one or the other without actually entirely understanding what's happening, right? Because they'll try anything to try to get something working, especially in a high stress environment. So make sure that you have proper checks in place to prevent that from happening. Thanks, Ram. So the next example is traffic hijacking. So for our next case study, we worked with a platform team that in production expected traffic routing to a completely different upstream servers. There was no recent new configuration change in the cluster, but the routing behavior had changed. We simplified the problem down. The platform team had a shared gateway resource in the Istio gateways namespace to be shared across the cluster. One of the team leads, we'll call her Iris, has a virtual service that routes traffic based on prefix slash app to her holo world service. Sometime in the past, Tim from another team had decided to create a virtual service in team B namespace, which included a route, which was slash app login, routing traffic to his service. This didn't impact anything with the original application and they went to production, but somewhat randomly, the routing in production changed. So by default in Istio, the configuration is exported to all namespaces. It's not scoped. So whatever virtual service you create in one namespace is exported to the other ones, unless you explicitly scope it down. And in a multi-tenant environment, we've often seen this where for a single host, there's multiple virtual services across different namespaces that people will use to do their multi-tenancy. Istio does its best to merge all of these routing roles, these virtual services together. But for the sake of running into production, that ordering is essentially undefined. So when there is a conflict between two routes, it essentially just picks the first one based on a timestamp, whichever was created first gets higher up in the order. Same thing for catch all roles. Like whatever is created, Istio picks up first is the one that's there. So that's why you can get into really bad intermittent behavior. In this example, where team A was running fine, team B comes along, applies bad config. They don't realize that it's bad because it's not accepted by Istio. Sometime in the future, maybe in production, the original team A uninstalls and reinstalls their app. So now the timestamp has changed and that bad config or that dormant bad config is now active. So that's a place where we often see users get tripped up in the middle of production where Istio routing has just changed and they haven't essentially changed any configuration. They just changed the order of when particular resources get applied or when they scale to another cluster when timing is different. The solutions for this ideally avoid using multiple virtual services for a single host. But that's not always possible depending on how you have your environment architected. The second way is scope down all of your resources. Your gateway can scope down exactly what namespaces it's going to pick up its virtual services from. So in the host field, you can specify which namespaces that it's going to pick up, that it should be watched to bind to that gateway. Same thing for your virtual services. Make sure you have your export to fields set in all of your virtual services so that you're exporting things to the right gateway's namespace and not your devs to test staging, for example, by accident. And then Istio-Cuttle analyze might catch some of these things, but we've seen a lot of cases where it doesn't just because of the way the complexity of rules ordering. And then the last piece of advice is run Istio-Cuttle proxy config routes on your gateway. And it shows you all the various routes that are bound to that gateway. And then from there, you can see if you have multiple routes going to different destinations that you did not intend that to happen. So before going to production, run your Istio-Cuttle proxy routes to look at the configuration of your Istio-Ingress gateway and make sure that looks good. Excellent. So for our next case study, we had a customer noticing a high number in cross zone traffic charges from their cloud provider. After digging a little deeper, we noticed a lot of traffic between side cars in one zone connecting to Istio-D running in another region, zone with a lot, a lot of chatter. This is not something that people typically think about, but with Istio running in your environment, this might become a concern. The customer asked us if there was something we could do to help them reduce this cost. Yeah. If you take a step back, the premise of this problem is that, again, by default, every side car, every mesh service needs to know about every other mesh service. So if anything changes in your mesh, Istio-D has to take that updated information and blast it to every other side car. And that can be scoped down, but a lot of users don't scope it down. This is what we've seen is that it's wide open. So Istio-D is doing a lot to orchestrate everything. And this becomes costly. We know it's costly at a resource level, but it's also costly at a networking level, especially when you have these multi-zone clusters where you have side cars spanned across these availability zones. And then your Istio-D, the piece that all of these side cars are connected to, are not necessarily in the same zone. So the solutions for this, make sure that you're scaling up your Istio-D to match your environment. Make sure you're running multiple Istio-Ds. You have the proper affinity set so that they're scattered across your nodes and across your zones. You can take advantage of topology aware routing feature in Kubernetes to make sure that when side cars connect to Istio-D, they're connecting to their closest available Istio-D, so that you reduce that cross zone routing and chatter. So Istio-D is doing a lot. And you can look at what Istio-D is doing, the amount of information it's sending to every single side car, to every single one of your workloads. So from a workload perspective, just like you have metrics to observe how your application is doing, you should also observe the amount of configuration that Istio-D is sending to your workload. And if this is getting too high, or if you have a few that are really high, then you know that those are the ones you should probably tackle first and create your Istio side car resources to scope things down properly, so that Istio-D is not sending that much data to every one of your side cars. So that's how much data. So next, you should also monitor how often and how long it's taking for Istio-D to push this information to the side cars. Typically, a lot of users monitor Pilot XD as push time metric to see how long it's taking for metrics to get from the control plane to side car. But it's worthwhile in production to understand that there's actually more that goes into the Istio-D XDS pushes. And the Airbnb did a great blog, and this diagram is straight from that blog. And I put that link to that at the bottom. But essentially, whenever there's any change in the environment, know that change gets created, a push request gets created. And that push request stays in a debounce time period for a little while to make sure it gets all of the right information, and we're waiting for all the merges. And then once that period is passed, then Istio-D will pick up that push request, it gets added to the push queue, and then XDS is calculated, and then it's being sent. So there's multiple steps in this process. And when you're running Istio in production, make sure you're graphing every single one of those metrics so that you can tune things properly. All of those various periods and the number of concurrent pushes, etc., they're all configurable with an environment variable. And in production, you might tune it differently than in your dev environment. For example, in production, there's not as much configuration changes that's happening. You're not constantly applying new config. But what might change are endpoint information, the IPs as your pods come up and down. That information you want to get to the other services as fast as possible, because you don't want any downtime in production, even the slightest. So for that, you are going to reduce the debounce period to make sure that any update gets sent quickly to the other sidecars. And you can also increase your push throttle. You don't want to do that in your dev environment where you have a lot of configurations happening because you'll just bottleneck Istio-D trying to keep up with all of these config changes that are happening. So for that, you might set a higher debounce period, maybe 10 seconds instead of for production, you might do 100 milliseconds. Thanks, Rom. So the next example is what we call the bypass sidecar. And this example comes from a large consulting company that we were working with who had already built a highly secure app on top of Istio. So they asked us, as the Istio experts, to help them with production readiness before go live. So after looking at their installation, we noticed a lot of unencrypted traffic between workloads and also that auth policies were ineffective. They asked us if we could help identify what the root cause might be. Yeah. So this is a case where a platform team installed Istio. They thought they installed the right restriction policies and they just expected everything to be secure. That was not the case because developers found a way to go around the sidecar. I don't know if it's malicious or they were just trying to get something working and they forgot about it. But developers can add annotations to their pods, like exclude outbound IP ports or IP ranges, or they can add annotations to not even have the sidecar come up. There's various things that they can do to bypass the Istio sidecar. The production checklist solution for this is to make sure you're using something like OPPA to ensure that these annotations are not there in your environment. And developers are not relying on these type of annotations to get around the problem. Perfect. So similar to our last example, I recently chatted with another Istio adopter who had issues with their SQL server RDS database running on AWS. As all relational databases are, it had become a massive bottleneck. Basically, all their microservices running in EKS had uncontrolled access to stored procedures and functions, causing database records to lock up. This Wild West was tolerated until a major outage occurred, bringing down the entire platform. This is a common problem that we've seen is that people don't think about egress controls at all until something bad happens. Like egress is just not even a concern. Every developer, every microservice talks to whatever external endpoint that it has access to, and that continues to go on until something bad happens. Maybe that external endpoint that a lot of services depend on now has a rate limit set on it, and now it's restricting further connections. And then you're in a scramble trying to figure out which microservice is hammering this external service, and you don't have controls in place to restrict who has access to what and add your own rate limit policies, for example, to it. Or if the URL changes for this external service to be able to seamlessly apply it to your entire environment. So the production checklist for this one is leverage Istio's egress controls. Whether that's as simple as you're just creating service entry objects and you have Istio registry only set, that's a good first step towards it. But the right final step towards it would be to leverage an egress gateway, running on dedicated nodes where you have full control over how traffic leaves your system. The same way you have an ingress gateway where you can control, secure, observe traffic coming in, you need the same things for your external egress as well. Don't wait until it's too late for you to apply those policies. And here we have another important concept, which in fact, is nothing new. It dates back to the Middle Ages, and we call it defense in depth. So if we look at the castle remote system, the way that works is we defend against any particular attack using several independent methods. In other words, we have layering tactics. In the castle's case, the mode is the first line of defense preventing attack is from getting too close. Then we have the overhanging holes, platforms, et cetera, built into the castle so those inside could hurl items at the attacker below. The question is, how can we apply the same concepts to networking and can Istio help? Yeah, I mean, everything we've been talking about kind of builds up to this. Essentially, you want a layered approach, right? I mean, Istio provides a lot of security for your applications. But as you've seen, there's their ways to get around it. There are times when that configuration causes a hole through Istio. And when that does happen, make sure you have another line of defense. And you can do that by leveraging Kubernetes network policies just around your nodes or around your namespaces just to have it as a backup, as a layer three, layer four backup. And then also leverage egress gateways to make sure that traffic is being funneled through the right nodes. And you have controls in place to make sure that if you wanted to cut things off, you can do that running short on time. So this is the last one. We've helped many Istio customers with intermittent problems they hit during pod startup. Looking at the application container logs, we saw that it was related to not being able to talk to the network. The application relies on the network to start properly. And it doesn't have retries resiliency built in, then it results in the pod failing to start and crash loop back off. This is a container race condition, whereby the Istio sidecar fails to start and time the server network request from the app. Yeah, like in production, you want to get rid of all these race conditions as much as possible and have everything be very deterministic. And to do that, you have to understand how your Istio startup process is working for every one of your services. When a pod comes up, by default, Istio init container has to run first to do its IP tables rerouting. And then once that's done, Istio proxy pod has to come up, Istio proxy container has to come up, and then your application pod has everything, the network set up so that it's able to make its IO communications. A lot of problems where we've seen is customers have their own init containers that have a race condition with Istio init container. They see different behavior, whether it runs before Istio's init container or after. Or we've also seen where the customer's container starts up faster than Istio proxy sometimes in production, but in their dev environment, it didn't start up faster. So you can run into these problems where speed makes a difference on how your application behaves. We're hoping ambient deployment pattern will solve this particular set of problems cleanly without you having to worry about it. But until then, make sure that you avoid using init containers if possible, use regular containers so that it always runs after the init container. Use Istio CNI to make sure that maybe if you don't need the init container to do the redirection, you have that set up. And then leverage flags like hold application until Istio proxy starts. There's an environment variable that gives you control over exactly when your pod comes up in relation to the Istio proxy pod. Cool. So I know we covered few different set of use cases, but they were meant to be so that you can build your own production checklist to cover those types of issues. Everything that solo field engineers and our customer success engineers have hit with our customers over the last three to four years of us helping customers with Istio, we've collected all that feedback and we've built analyzers, automatic analyzers to check for these best practices. These are not just static config analyzers, but also best practice deployment level analyzers. And we built it into our glue core product, which essentially just sits on top of your existing Istio and gives you this insights into your environment. It does life cycle management and helps the operations team make sure that they're running Istio smoothly, upgrade Istio smoothly, make sure they have the right checks in place, et cetera. And that management plane will also provide insights and dashboards, et cetera. So that was the result of all of our work is that we put into building this analyzer solution. Anyway, if you have any questions, please reach out to Simon and I. You can find us on the Istio Slack or you can reach us at the glue solo IO Slack channel. My email address is rom at solo.io. And Simon, what's your email address? It's Simon.green at solo.io. Awesome. So it doesn't look like there's any questions in the chat. So I hope you found that session useful. Again, if you have any questions, please feel free to reach out to us. Have a great rest of your conference, everyone. Thanks, everyone.


Previously on the Tour de Mont Blanc series. We had a beautiful but tough 1300 meter climb ahead of us to reach the high mountains. We climbed a thousand meters, 300 more to go. We hiked on our first snow patch which turned out to be pretty easy. Oh this is good snow for our first snow patch on the Tour de Mont Blanc, it's a really good one. We made our way to our highest overnight hut at almost 2500 meters where we got rewarded with beautiful views and wildlife. In 10 episodes we will take you around the Mont Blanc Massif through France, Italy and Switzerland. This is the Tour de Mont Blanc. Good morning, are you ready? Good morning, yeah we are ready. I think we don't have to walk because we're gonna blown away by the wind to our next destination. Wind is very strong today. Stage 3 today of the Tour de Mont Blanc Tour and we're gonna cross our highest point and that's already 200 meters from here so very nearby and we're gonna cross the border of France and Italy. Yeah and we're really lucky with the weather because the weather forecast said that it will be thunderstorming and raining and all the heavy weather all day long but people at the hut told us that it's only gonna be very very windy. The end destination of today is Cour Meure which is a beautiful town in Italy and to get there we have to climb 1500 meters and descend 2000. So it's a big day and we have already started 7 o'clock now so let's go. We just had our big first descent of the day. Yes and from here now 700 meters climbing and then we're at Col de La Seigne which is the border of France and Italy so a big climb but we're looking forward to it. We're now at 2500 meters it's one of the highest points of the Tour de Mont Blanc. We took like an alternative route this day to was one and a half hour shorter because we have a very big day so our highest point was this morning and otherwise it will be in a couple of days. So one more big climb and then we're almost there. Two and a half hours from here 500 meters up and then a little down and then we're at our hut. We're already almost 10 hours on the way so it's a very long day but we're still happy going strong. It was a brutal climb right? Yeah it was ready for some food. After a very long day of 13 hours of hiking we finally arrived at our hut for a well-deserved rest. Good night and see you in the next video. On the next episode of the Tour de Mont Blanc series. We have a short day and we'll reach the first big city on the Tour de Mont Blanc Courmayeur where we will have some pizza. On our way to the next hut we unfortunately run into some bad weather but luckily we got a good tip from a mountain guide. So right now we're counting the thunder and the lightning just to be safe. It's really hot.


One run game in the bottom of the seventh inning, Perdomo just came in for the Pirates to face Soto. This breakdown is brought to you by the Warehouse Games YouTube channel. OO Count, slider away, Soto doesn't even really register. It's like, whatever. And then fastball in, he nods. He's like, OK, clock that one. I'll put that one in my memory. 1-1, slider. That's the combo. Keep your hip in. Keep your hip in 1. That's what he's telling himself. Watch that hip. Just goes, ugh, it leaks away. That pitch is too close to be leaking away. 2-1 pitch. They're stealing and thrown out. Nice play. Jumping tag from the rookie there. 3-1 pitch. Fastball again. And Soto goes, I clocked that one already, dude. Gone. Mashed.  Shouldn't have stole. I had it the whole way. Bored by it. Little elbow pound. Then he sees Tatis. He's like, bump, bump, bump, bump, bump, bump, bump, bump. Look at this. Bam. Bored. Boring. Easy. Manny comes up. And Perdomo, just all his masculinity and his manhood has been questioned. So he's got to throw it behind Manny's back. And the umpire, Tumpain, quickly out. Quickly like some doesn't seem right. I don't like that. Chill out. And Manny's being calm about it. Just kind of chewing his gum, looking at him. Like really, dude? One hurts your feelings?  You all right? Okay, yeah. He didn't really say anything. I don't know if anyone. Santana comes over on the pirates and he's gonna be like, sorry, dude. I don't think that was that cool. That's our bad. And yeah, behind the back. Pretty scary. Ready? Ugh, just kind of folds him the wrong direction and it grazed him, which probably hurt more. And then he kind of steps towards him with this face. And I think that was a bad vibe, you know? Why can't you just be like, if it's an accident, you'd be like, sorry, this dude knew it.  What? Throw him out.  I throw him out. You got, okay, I'll just wait. I'll let you make your decision. The umpires get together. They're talking about it. They're discussing it. They're like, I don't know. It seemed like super on purpose. Adjected, no warnings. Shelty comes out. Come on. What are we doing? What are we doing? Come on, why? I like that. Why? He's like, I don't know. Seemed like it. Sure. Why?  Oh, ejected. Don't ask what we're doing three times. No way. Why'd you throw him out?  No warnings, nothing, just immediate ejection. Now I gotta get another guy up. We wasted him. What are you doing?  You don't like that at all. At all. They had to bring in another pitcher, down two now, two outs. First pitch, fun little pitch, gets the pop-up, ends the inning, but that was that. Warehouse games, tons of fun. Subscribe and check it out.


Hello and welcome to this session. In this session we will discuss a question which says that if vector a is equal to audit pair minus 2,3 and vector b is equal to audit pair 1,4, then find vector a plus vector b also represents it dynamically. Now before starting the solution of this question, we should know some results. First is if vector a is equal to audit pair x1, y1, vector b is equal to audit pair x2, y2, then vector a plus vector b is equal to audit pair x1 plus x2, y1 plus y2. And second result is to represent the addition of two vectors a and b dynamically, we draw the two vectors one after the other placing the initial point of the succeeding vector on the terminal point of the previous vector. Then we draw the resultant vector from the initial point of the first vector to the terminal point of the last vector and this resultant is vector a plus vector b. So these results will work out as a key idea for solving out the given question. Now let us start with the solution of the given question. Now here we are given vector a is equal to audit pair minus 2,3 and vector b is equal to audit pair 1,4 and we have to find vector a plus vector b. For this we will use the first result that is given to us in the key idea. So vector a plus vector b is equal to audit pair x1 plus x2 that is minus 2 plus 1, y1 plus y2 that is 3 plus 4. Which is equal to audit pair minus 1,7. So vector a plus vector b is equal to audit pair minus 1,7. Now we have to represent it diagrammatically. For this we will make use of the second result given in the key idea. Now first of all we will draw the vector a with components minus 2,3. We will take this grid paper and we will take any point on this paper as initial point. Now let us take this initial point at the original. Now here you can see x component of this vector is minus 2 and y component is 3. So from this initial point we will move 2 units to the left and 3 units up and we reach this terminal point. So this is the vector a. Now here as we have moved upwards so we show upward direction. Now let us draw vector b with components 1,4. Now creating this terminal point of vector a as initial point of vector b. We move 1 unit to the right and 4 units up and we reach at the terminal point of vector b. So this is the vector b. Then we draw the reversal factor from the initial point of vector a to the terminal point of vector b. Now from this point as we have moved upwards so we show upward direction. And this resultant vector is vector a plus vector b. Now this is the initial point of vector a plus vector b and this is its terminal point. Now here you can see that from initial point we have moved 1 unit to the left and 1,2,3,4,5,6 and 7 units upwards. And we have reached the terminal point of vector a plus vector b thus its components are minus 1,7. So this is the solution of the given question and that's all for this session hope you all have enjoyed the session.


Early one Tuesday at about 4 a.m., a group of armed thieves broke into a cellular phone store by cutting and removing the hinges from the front door. Although two of them were dressed in casual clothes and carried handguns, the other two wore full military combat uniforms, right down to their ballistic helmets and knee pads, and they carried M-16 rifles. These thieves stole a pallet of mobile phones and some cash. The country's military police teamed up with law enforcement to investigate. It was critical to know if military personnel were involved in the crime. Fortunately, a year before this incident, the military had adopted a new lie detection technology that can spot a liar by measuring involuntary changes in the eyes. The military had great success using the technology to screen thousands of recruits and existing personnel. Now it was time to use it for an investigation, like this one. Over a hundred soldiers in the area were tested to see if they had been involved in the cell phone store heist. The test quickly identified a few most likely involved in the theft. They were investigated, promptly dismissed and charged with the crime. Today, four other top federal agencies in the country, as well as dozens of other countries worldwide, also use this technology to quickly and accurately find the truth and expose lies. What is this technology? It's called eye detect. Eye detect is the first true breakthrough in credibility assessment technology since the polygraph was invented about a hundred years ago. Eye detect provides federal, state or local government seven key benefits. One, pre-screen and fast-track the best job applicants. Two, screen job applicants for past illegal activities. Three, continuously monitor employees for insider threats. Four, investigate employees for possible illegal activities. Five, quickly and safely give interim security clearances. Six, guarantee that everyone receives an unbiased test. And seven, maintain safe physical distancing during testing. An eye detect test takes just 15 to 30 minutes. Results are ready in less than five minutes. The technology has been scientifically validated by 16 research studies, nine of which are peer reviewed. Today, nearly 600 customers in 43 countries successfully run eye detect tests, including local police and sheriff departments, state correction facilities, national military divisions and federal governments. The eye detect technology would allow your organization to streamline its processes. It will actually end up saving resources for an organization, which is always a challenge. But in the end, it actually serves to protect information or protect national security in a way that previously was really not possible.


Please state your first name age and current city of residence. My name is Fred I'm 80 years old and I live in Berthold, Colorado How long have you lived in your current residence? since last August of 2022 and where did you live before that in Longmont and How long have you lived in Colorado about 40 years? Where were you born and where else have you lived? I was born in Rochester, New York, and I've lived in numerous places in California and in Illinois Can you tell me about a hobby or interest you have had over the years? Most of my life. I've been a model rewording fan Can you tell us more about what that is? I've built a number of model train layouts over the years and I'm currently building one in my basement in Berthold and How many different layouts have you created? I think it's six and Are they large or small? they would be categorized by model reworders as a medium size and Are they a particular are the trains in particular size? Yes I my model in n scale, which is one 160th of reality What do you enjoy most about creating layouts? Actually, I like all of the disciplines a little bit. I'm not terribly good at them, but I like the carpentry I like building model buildings and track scenery mountains such like that is There a particular place that you like your layouts to portray Right here in the state. I usually have something like the Rocky Mountains In the layout Where did this interest come from? My dad Was a real train enthusiast he worked on Railroads not for the railroad. He worked for the railway mail service, but He loved trains his whole life and it Passed on to me From its beginnings during the Civil War until its slow decline after World War two the core of America's postal system was the railway mail service Previously mail had been carried in locked pouches aboard trains and then sorted at their destination Under the new system mail was sorted en route while the train moved between two points The idea proved successful and a large portion of the nation's mail was sorted while being carried on the rail lines As highway mail transportation became more prevalent the railway mail service was gradually discontinued with all service officially terminated in 1977 and It's our understanding that you'd like to read from your father's autobiography. Yes After taking a test for a civil service appointment I was appointed to the railway mail service of the US post office in August 1941 in the same month my draft board called me Terry that's his wife knew one of the members of The draft board and the members suggested that if we married and had the kids I would not be drafted that winter We decided to marry on January 10th 1942 but Pearl Harbor pushed the date up to December 27th 1941. I was officially drafted for the war in 1943 at that time the US Marine Corps was in need of mail clerks a US Marine Corps sergeant followed me through the whole Induction right and guaranteed me that I would be a mail clerk in the Corps I served without injury in Oganawa Japan until my release from this from the service soon after the war ended in 1948 I became a regular clerk in the railway mail service and I was given a run from Detroit to Buffalo I worked five days a week and received the next nine days off The train left at 9 p.m. And we arrived in Buffalo at about 2 a.m. We left Buffalo at 3 30 a.m. And arrived in Detroit at 8 30 a.m. We did this Sunday to Friday. I did this until 1950 When an opening occurred on the local from Rochester, New York, which was called the old road Thank you How did he share his involvement with trains with you? The first remembrance I have is that the home we lived in in Rochester Rochester, excuse me had An enclosed front porch and in that room He built a model railroad layout for me complete with towns The old train layout and I became a fan right from them Did you guys ever go anywhere? To watch the trains? Yeah, there's one particular memory. I have there was a Highway overpass over the main line of the New York Central outside of Rochester and at that time the New York Central had a four-track main line this would have been in the late 1940s and we'd go there and park the car and Just watch the trains go by which was very frequent What do you hope others will learn from your story? Well, I'd like to to see the interest in rail rearing Continued in this country. It's been a big part of our our history and Outside of the the recent negative news It's it's an important part of our economy Although probably a shrinking part of our of the importance in our economy in the future But I'd still like to see where it's remembered understood And admired Anything else you would like to share the The hobby is a lot of fun. It uses a lot of different skills and I've been I've enjoyed it for No, probably for 70 75 years Great, well, thank you for your time today. Thank you


So, in the last class we started discussing chemical equilibrium and we have shown that at equilibrium delta G is equal to 0, which is the change in Gibbs free energy is 0 for a chemical equilibrium process. And from there we have shown that delta G naught is equal to R T L L K P, where delta G naught is the change in Gibbs free energy at standard state. And R this R is the universal gas constant, temperature in Kelvin and K P is the equilibrium constant. This is defined for standard pressure. So, P naught is 1 atmosphere. Now, we have also shown that the Gibbs free energy for standard state can be obtained by knowing the molar Gibbs free energy of formation of different species. We have also shown that for the formation reactions, since we can estimate how much is the, since we know the Gibbs free energy of formation, we can estimate the K P for formation reactions. Then for a complex reaction and not a formation reaction, we have shown in the last class that by combining different reactions, we can get the expression for K P for little more complex reaction by combining certain few formation reactions. Now, let us continue from there. We have been discussing this K P in the last class. Now, let us look at various forms of this constant. Let us consider this chemical reaction, the generic chemical reaction that we have been discussing so far. This is our generic chemical reaction. What we are now going to talk about is various forms of equilibrium constant for this chemical reaction, generic chemical reaction at equilibrium. Let us consider at equilibrium. So, first of all K P, we have defined K P. We know that K P is a function of temperature and we have defined it as pi i equal to 1 to n that is product of partial pressure at equilibrium of different species rest to repower the difference in stoichiometric coefficient. This we have done in the previous class. Now, we can define the equilibrium constant in terms of moles also, K n. So, K n is defined as pi i equal to 1 to n. The number of moles of particular species i at equilibrium rest to repower again the difference in stoichiometric coefficient where in this reaction, sorry in this equation n i represents the actual number of moles of species i which is typically given as the partial pressure multiplied by volume divided by R T. So, this is equal to P i by P by totals number of moles multiplied by total numbers of moles where N T is the total number of moles in the mixture. So, N T is the total number of moles in the mixture. N T is nothing but the summation of number of moles of all the species i. Similarly, we can define K C that is the equilibrium constant based on concentration. So, that is defined as pi i equal to 1 to n C i e to the power the difference in the stoichiometric coefficient where the C i e represent the concentration of species i at equilibrium. So, that is the equilibrium constant based on concentration. Similarly, we can define based on mole fraction K x. So, on mole fraction based on mole fraction we can get again the concentration of species i as a mole fraction of species i at equilibrium rest to repower the difference in stoichiometric coefficient. Here once again kappa i is the mole fraction of i which is nothing but equal to P i by P that is N i by N T. P i is the partial pressure at equilibrium of species i, P is the total pressure of the system, N i is number of moles of a particular species i, N T is total number of moles. So, this is how it is defined for based on mole fraction. Now, similarly we can also define this property equilibrium constant based on mass fraction y. So, based on mass fraction I can define it as very similar definition where y i is the mass fraction of species i. So, y i is mass fraction. So, that is equal to molecular weight of species i times partial pressure times rho T R. So, that is nothing but molecular weight times concentration divided by density or the density of species i divided by total mass average density that is the definition of mass fraction. So, these are defined properties. Now, I would like to point out one more thing the relationship between all this different representation of equilibrium constant. For that let us first define the change in number of moles in a chemical reaction. So, change in number of moles in a chemical reaction given by delta N is equal to the sum of the number of moles in the product side minus sum of moles number of moles in the reactant side. So, that is the total change in the number of moles. Then it can be shown that K p is equal to K c R T to the power delta N. This is also equal to K n R T by V to the power delta N. Also equal to K kappa P to the power delta N. It is also equal to K y R T rho to the power delta N. Also equal to K kappa P to the power delta N. It is also equal to K y R T rho to the power delta N times pi i equal to 1 to N omega i to the power this. So, this are the different equilibrium constant based on different properties and this is the relationship among them. Now, depending on what is known to us we can estimate the other. So, this is something that is a very important information which is typically used to estimate one of this equilibrium constant or other knowing the other properties. Now, before we proceed further with the chemical equilibrium let us solve a problem to essentially make this concept clearer. Let us consider that we have a mixture of 1 mole of nitrogen and half mole of oxygen and they are heated at 4000 degree Kelvin. So, because of and 1 atmosphere pressure and 1 atmosphere pressure. So, because of that there is a resulting reaction and we get the final equilibrium mixture consist of nitrogen, oxygen and some nitrogen, nitric oxide NO NOX. We can also assume the initial temperature of both nitrogen and oxygen T i is 298.15 Kelvin that is essentially the standard temperature. So, nitrogen and oxygen are supplied at a standard temperature and then they were heated steadily. Now, the question is here how much heat will be required to take this to 4000 degree Kelvin temperature. So, how much delta q is equal to what how much heat is required. So, first for this problem let us look at what is known to us. First we want to estimate this A B and C how much how much is the total what is the total so that the final composition. In order to do that first we do that atomic species balance. So, we have two species nitrogen and oxygen. In the reactant side we had we have two atoms of nitrogen. So, this is equal to then 2 A plus C in the product and the oxygen in the reactant side we have one atom of oxygen this is equal to then 2 B plus C. So, if you simplify this we get A is equal to 1 minus C by 2 B equal to half minus C by 2. So, then at equilibrium this is what is our final composition. So, if you can estimate C we know how much is the final product composition. So, my final equilibrium reaction then is this looks like 1 minus C by 2 times N 2 plus half minus C by 2 times O 2 plus C N O. Now, what is given by this? Given to us that the initial temperature is T i the final temperature of the mixture is 4000 Kelvin. So, here what we are solving is that what we are saying that initially the mixtures were at this temperature first they were heated to this temperature then reaction occurs. It is equivalent to saying that the reaction occurs at this temperature and then the heat takes this to this temperature. So, both of them are equivalent that we have already discussed. Now, if we had a stoichiometric reaction. So, this reaction as you can see clearly is not stoichiometric, but for a stoichiometric reaction it will be half N 2 plus half O 2 giving N O. So, if you have to produce 1 mole of N O we need half N 2 and half O that is my stoichiometric reaction and the value of K p for this reaction can be obtained from thermo chemical tables this is equal to 0.03. Now, as we can see here from our discussion we had 2 species we had 3 unknowns. So, you are not able to solve this. Now, we are be using that information the K p information to solve this. Now, this K p is applicable at equilibrium and this stoichiometric reaction is the equilibrium stoichiometric reaction.  Now, what is the partial pressure of N O in this mixture? It is the number of moles times the total pressure divided by total number of moles. So, it is a mole fraction times the pressure. So, first of all P N O is kappa N O times the total pressure and the mole fraction is the number of moles of N O in the final mixture which is C divided by total number of moles which is let us say at the for the time being is N T we will estimate that also times pressure. Similarly, the mole fraction of N 2 in the final mixture is A by N T times P and A according to this estimate is 1 minus C by 2 times N 2 by A by N T times P. Similarly, mole fraction of O 2 is B by N T times P. So, this is equal to half minus C by 2 by N T times P. Now, these are our actual mole fractions. So, we can estimate the partial pressure for every molecule here now using this because the partial pressure of N 2 will be nothing but mole fraction multiplied by total pressure sorry this P will not come here sorry because we are talking about just the mole fraction. So, now we come back to this equation. We write the partial pressure for all of them power half half minus C by 2 by N T times P to the power half. So, you can see here now we have one equation which relates which is a function of only C. So, if I now expand this first of all this N T will cancel off pressure will cancel off. So, we have a simplified expression which gives us the value of C in terms of K P. So, by simplifying this we get K P is equal to C upon 1 minus C by 2 to the power half times half minus C by 2 to the power half. After we expand this putting K P equal to 0.3 you get this. Now, let us solve for C is a quadratic equation. So, it can be very easily solved this gives C is equal to 0.1825 or minus 0.212516. Now, if I look at this two numbers the negative value is physically not possible because there has to be some amount of nitrogen oxide present nitric oxide present. So, therefore, this is the correct value once we have C then we can estimate A and B also.  This is how we get the final composition. Once we have the final composition now we know how much is our final temperature we can get how much heat is required. So, let us look at that first of all delta H of formation for N O is equal to plus 21 per 5 8 kilo calorie. Now, this is a constant pressure process. So, delta Q is equal to delta H. So, essentially we have to find out the total enthalpy change in this process which is equal to how do we do it? We assume that first the reaction had occurred at standard state and then the products are heated to the final temperature. So, total delta H is equal to first of all heat of total heat of formation which is equal to nothing but this we have seen in the previous class rather two class back I think. So, this is the total heat involved in the formation reactions. This is total heat of formation of all the product species total heat of formation of all the reacting species. So, that is the heat involved during the reaction at standard state and then the products are heated delta H P from this standard state of 298 Kelvin to 4000 Kelvin which is my final temperature. Now, if I look at this in the product side we have that composition. So, we have 1825 times delta H F of N naught.  So, this is the total change in the formation enthalpy and then the heat required to heat it up. So, that will be equal to now this amount of nitrogen is heated from 298 to 4000. So, that is first of all let us look at nitrogen. So, this amount of nitrogen is there initially in the final which is heated now for nitrogen then oxygen is heated again from the initial temperature of 298 Kelvin to the final temperature and N O is heated again from 298 to final temperature. Now, what is the heat of formation of nitrogen? It is 0 because nitrogen appears as nitrogen molecule here. So, this is 0 heat of formation of oxygen is also 0 and these values are we can get from thermo chemical tables. The enthalpy for nitrogen for oxygen for N O at different temperatures are tabulated in thermo chemical tables. So, we can get that once we do that if I estimate the final heat is 5.53 kilo calorie. So, 5.53 kilo calorie of heat must be supplied in order to take to carry out this reaction. This is an endothermic reaction. So, much of heat is required. So, that explains how we estimate. So, in this problem we showed first that how do we estimate the final composition and then instead of solving for adiabatic flame temperature we said that the flame temperature is known how much heat is required. So, this is how we do it. I would like to point out one more thing here that for the estimation of K p we talked about Gibbs free energy. Many times Gibbs free energy is not available to us, but typically the enthalpy variations changes are given. So, how do we get the Gibbs free energy or rather the K p if enthalpy change is given. So, for that we use Clausius Clapeyron equation. Let us see how we get that. We have already shown that ln K p is equal to minus delta G naught by R T and we have shown that Gibbs free energy is equal to H minus T s. Therefore, at standard pressure this was defined as standard pressure H naught minus T s. So, therefore, the change in Gibbs free energy is equal to delta H naught minus T delta s naught and therefore, we can write delta G naught by T equal to delta H naught by T minus delta s naught. Now, let us look back again at this equation and let us differentiate it with respect to temperature. So, if we do d d T of 1 K p this is equal to nothing but 1 by R minus 1 by R d d T of delta G naught by T that comes from by differentiating this. So, we define first of all from here we have shown that d d T of ln K p is equal to this. Now, let us look at first this term d d T of d ln T. So, first let us look at d d T of delta G naught by T delta G naught by T if according to this is equal to delta H naught by T minus T delta s naught minus delta s naught. So, this will be equal to minus delta H naught by T square plus 1 by T d d T of delta H naught minus T d d T of delta s naught. So, because H naught is also a function of temperature. So, we can write this like this. Now, let us look at the Gibbs equation. It says that d H equal to T d s plus V d p. Since we are considering a constant pressure process therefore, d p is 0. So, this term is 0. So, d H equal to T d s. Therefore, we can write this as d of delta H naught is equal to T d of delta s. Therefore, d d T of delta H naught equal to T times d d T of delta S naught. Here we are now we are imposing the condition that the enthalpy and the entropy here at essentially the process is at standard pressure. Now, if I look at this expression and this expression we have this minus this appearing here. Therefore, this term is 0. So, therefore, this term goes to 0. So, what we are left with is only this portion of this expression. Therefore, once we put it here this term d d T of G naught by T delta G naught by T is equal to nothing but minus delta H naught by T square. So, if I put it here this comes to be equal to delta H naught by R T square. So, here now we have got an expression for K p in terms of delta H naught which is something typically a known property universal gas constant and temperature. So, this equation is called Clasius-Caperron equation which gives us the value of K p if delta H naught is known. So, now so far we have been discussing typically simpler reactions one step reaction, but in our rockets we have complex reactions involving may be multiple reactions. What we know is initially the reactants that we are supplying we may not even know what is the final products. If we know the final products let us say we know the final products we do not know what are the reactions occurring. So, now let us try to get the reactions which are occurring in a practical system where we have more complex chemical equilibrium. So, the next thing that we are going to discuss is complex chemical equilibrium and how to get that condition. So, next is complex chemical equilibrium. Now, we have seen some example in the previous class that at one of the examples where the reaction was occurring at high temperature we had four species and nine unknowns. So, atom balance was not able to provide us enough equations to solve the problem. Even in the previous case we used one K p equation, but when we are going to more complex systems if we have S species and from C elements then from atom balance for C elements we get C equations. So, we get C equations from atom balance which we have already discussed many times. Now therefore, this S minus C is our additional required equations which we need to close this problem. So, this term S minus C is called the degree of reaction freedom. A reaction having only one degree of reaction freedom is called a simple reaction like the reaction we took in the example. But if the degree of reaction freedom is greater than 1 then that reaction is said to be complex. So, if S minus C is greater than 1 that is called a complex reaction. Now, we want to work with a complex reaction. We have seen earlier that for any reaction no matter whether simple or complex we have seen that at equilibrium d G is equal to 0. And what is d G if we have S species what is total d G for that total change in free energy this is nothing, but sum over this S species the gives free energy for independent species individual species times the change in number of moles of the species. So, that is the total d G and this is equal to 0 at equilibrium we will use this relationship to obtain the equilibrium relations. Let us start with an example that will make it easier to explain. The example we have already seen similar example before that we let us say we have some methane and some oxygen as reactant and the products what we have is some unburned methane some oxygen some water vapor some carbon monoxide some carbon dioxide these are the products. Now, this is typically what happens we have carbon monoxide carbon dioxide water vapor unburned hydrocarbon oxygen everything is present at equilibrium. We want to find out then what are the reactions equilibrium reactions that are occurring what are our elements in this case the elements are carbon hydrogen and oxygen. So, we will get three equations from there then in the final product. So, our chemical reaction is something I do not I am not mentioning how much it is there the final composition will have something like this. So, in the final composition we have N C H 4 moles of methane N O 2 moles of oxygen N H 2 O moles of water vapor N C O moles of carbon monoxide and N C O 2 moles of carbon dioxide. Now, we want to find out relationships to get this only then our final composition will be known. So, in order to do that let us first to get the equations that we are looking for first the three elements are this. Let us say that depending on the initial composition we have N H number of hydrogen. So, then N H is equal to in the in this product side we will have 4 N C H 4 plus 2 N H 2 O right because 1 C H 4 molecule will give 4 hydrogen atoms 1 H 2 O molecule will give 2 hydrogen atoms. So, if N H is the initial number of hydrogen atoms this is will be the product side. Similarly, we can get N O number of atoms of oxygen. So, that will be from atom balance 2 N C O 2 plus 2 N O 2 plus N H 2 O plus N C O. Similarly, we have N C is the number of atoms of carbon. So, that is equal to N C H 4 plus N C O 2 plus N C O. So, now our atom balance is done. We get only 3 reactions and we have 5 unknowns. So, we need 2 more equations somehow. So, let us look at the changes. First of all what is the change in number of atoms of hydrogen D H N N H is 0 right because that is going to be conserved. So, this is equal to 0 and that then is equal to nothing, but change in this plus change in this. So, this is equal to this therefore, from this 3 equations similarly, we get D N O equal to 0 and D N C equal to 0.  So, this represent 2 D N C H 4 plus 2 D N C this represents D N O and this represent D N H. So, the change in number of atoms we get 3 equations here. Now, as I have just mentioned that we have 5 species in the product and 3 elements. So, the degree of reaction freedom in this case is 2. So, we need to have 2 more equation. Now, what we do is since we have 5 variables, what we will do is first let us choose 2 of these variables as independent variables and express the other variables as function of these 2. So, what will be the most logical choice? Let us say we choose methane because that is our field. So, we choose one of them methane as one of the independent variable and the other independent variable let us say is carbon monoxide because typically in stoichiometric reaction we should get carbon dioxide. Since we are getting carbon monoxide that is some intermediate reaction occurring. So, we choose that as one of the reactant independent variable. So, then what we can do is from these 3 equations we can write from this equation D N H 2 O is equal to minus 2 D N C H 4 let me call this equation 1. Then from this other equations we get D N O 2 is equal to half D N C O plus 2 D N C H 4 let me call this equation 2 and similarly we get D N C O 2 from this equation is equal to minus D N C H 4 minus D N C O let me call this equation 3. So, essentially what we are doing is we are representing D N H 2 O D N O 2 and D N C O 2 as function of D N C H 4 and D N C O. So, change in moles of methane and carbon monoxide. Now, we have chosen methane and carbon monoxide as independent variables. So, now we have these 3 equations. Next step now is bringing our discussion on free energy. What is the total free energy? The total free energy change total free energy change is D G.  So, this is my total change in this free energy all 5 species are considered. So, let me call this equation 4. Now, what we do is from this expression let us eliminate this this and this then it will remain only a function of C H 4 and C O.  So, that is the total change in this free energy in terms of the free energy of all the species we are considering times the change in number of moles of methane and carbon monoxide. Now, from the equilibrium D G is 0. So, this term must be equal to 0. Now, let us see this is not 0 and this is not 0. Therefore, in order and this is positive this is actually this is non zero this is non zero. Therefore, in order for this to be 0 this must be 0 and this must be 0. So, in order for this to be 0 mathematically what we have is D G D N C H 4 equal to 0 D G D N C O equal to 0 and that means that this term is equal to 0 and this term is equal to 0. So, what we get is G C H 4 plus 2 G O 2 minus 2 G H 2 O minus G C O 2 equal to 0. This then gives me after eliminating these things and the and from this I get G O 2 plus 2 G C O minus 2 G C O 2 equal to 0. I get these two equations. Now, these two equation corresponds to the equilibrium condition for two equilibrium reactions. First of them comes from here. This will be valid for an equilibrium reaction at standard temperature and pressure which will be C H 4 plus 2 O 2 equal to 2 H 2 O plus C O 2. If I have an equilibrium equation at standard temperature and pressure then the total change in gives free energy delta G naught for this is equal to 0. We have already talked about it. Therefore, in order for this to be correct we need to have this condition. Actually, it may not be a standard temperature and pressure. Any reaction can do that because delta G naught delta G for a chemical reaction at equilibrium is 0. Therefore, in order for this to be correct we have this equilibrium reaction. Similarly, for this to be correct we have another equilibrium reaction which is now this reaction C O is something as I said is appearing as one of the intermediate products. So, this is appearing from this reaction. Now, I have these two equilibrium reactions. Once we have these two equilibrium reaction what is the advantage I am gaining now? For this equilibrium reaction I have a K p. For this equilibrium reaction I have another K p. So, and those K p's can be easily obtained. For example, if I look at this reaction then K p for that reaction is equal to P C naught P O 2 to the power half by P C O 2. So, this can be further written as mole fraction of C O times total pressure mole fraction of O 2 times total pressure to the power half divided by mole fraction of C O 2 times total pressure. So, this is equal to K C O K O 2 a kappa O 2 kappa C O 2 times pressure to the power half. So, for the given pressure if you know the value of K p if you know the value of K the total pressure we now get one relationship rating this three. Similarly, we can get for the other reaction K p is equal to P H 2 O square P C O 2 by P C O 2 by P C H 4 P O 2 square in this equation pressure term will not come out. So, finally, this will be equal to this is square this is square. So, now, I get this two equations for anything is missing here this will be half there will be half here. So, I have this two equations for K p's and K p's as I said is available from the standard table we can find out K p. So, once K p's are known or we can estimate K p from the definition that as a Cassius-Caperron equation or from delta G we can estimate K p for this equilibrium reactions. Once K p's are known now I have one and two these two equations relating this five mole fractions and three we had already got before from atom balance. So, now, I have five equations five unknowns which can be then now solved for the final composition. So, that is how now I will get the final composition. So, now, let us look at more complex reaction I will not I am not going to derive it, but I will show what are the reactions equilibrium reactions that will be there. So, we will look at a very complex reaction. Let us say we are looking at combustion of methane in air at very high temperature this is air at very high temperature. So, that is at temperature is so high that we have dissociation also then for that case the composition is going to be like this as you can see they are considering lots of species including the formation of NOx including the formation of NOx we are considering and then we are considering dissociation of NOx we are considering this equations. So, this is my total number of species or the product species. Now, let us say what is the degree of reaction freedom here I have carbon hydrogen nitrogen oxygen. So, I have four atoms and how many unknowns do I have 1 2 3 4 5 6 7 8 9 10 11 12. So, we have four atomic species and 12 unknowns. So, my degree of reaction freedom is 8. So, I need to have eight equilibrium reactions like we have done like here to close the problem and those eight reactions are going to be like this that essentially is obtained following the process I have just discussed. So, this eight equations are 1 2 3 4 5 6 7 and 8. So, as you can see now I have this eight equilibrium equations and this eight equilibrium equations now I can get 8 k p values and now I will have the remaining 8 equations I can get from this k p values I can complete the problem and solve for the entire composition. So, this is typically what is done in solving the complex chemical equilibrium problems. So, this brings us to our discussion on the chemistry part. So, let me just summarize what we have learned and what can we get from here. We have looked at chemical equilibrium, we have defined various properties like k p delta g naught etcetera etcetera and then we have shown that if only we know what are that species going to be in the product side, we can form certain equilibrium reactions. Once we form those equilibrium reactions for those equilibrium reactions k p values can be obtained from the tables then we have the additional equations to close the problem particularly with complex reactions where the degree of reaction freedom is more than 1. So, now one more point I will have to point out here that this k p values as we have said is a function of temperature. So far in this case we are considering that we know the temperature. Now, if I combine this discussion with the discussion of adiabatic flame temperature, what did I said at that time that first we choose the value of adiabatic flame temperature. So, let us say we choose the value of adiabatic flame temperature then we formulate this, we get the k p value for that temperature, we solve for the final composition like we have done also for the problem that we solve today. So, we solve for that we get the final composition. Once we have the final composition we do the energy balance that is how much heat is going to heat up like the problem we solved. Then we see that from the energy balance this mass energy is produced by a chemical reaction and finally, going to the final temperature this much is required do we have the match. If we do not we change the initial case of the final temperature and repeat this process. So, essentially the problem that I have worked out we repeat that again and again for different temperatures till we get the final composition as well as the final all the equilibrium reactions will emerge now. So, everything we will get we get the final composition we get the final temperature. What will that give me once we have this we get the chamber temperature T c naught and remember that pressure is also included here. So, pressure is something that needs to be provided. So, pressure is one of the parameters that will appear we get T c naught and once we have the mixture we can get the molecular weight first of all of the mixture because we know the entire composition we can get the molecular weight of the mixture. Once we have the molecular weight we can get the value of r for the mixture. Similarly, we can get C p for the mixture because that is mass averaged we can get C v for the mixture because that is also mass averaged. Once we have this two we can get gamma for the mixture which is C p by C v. So, now we have gamma we have T c naught pressure is already given. So, now we have all the things required to estimate the thrust and start designing the nozzle also. So, therefore, this is how this is what comes from the combustor combustor design where after the combustion when we specify the fuel and oxidizer we know how much is coming at what pressure at and what temperature we get the final temperature considering adiabatic mixture as well as adiabatic combustion as well as the final composition. Then we now have all the necessary ingredients to carry forward this analysis. So, that is what I wanted to discuss in the combustion part. One point I made here is that we need to know the fuel composition. So, that is what I am going to start and discuss in the next couple of lectures. We will first radicate one lecture to solid propellants and then to liquid propellants. We talk about the fuels we talk about how the solid propellant rockets work. Then we talk about liquid propellants what are the liquid propellant rockets what are the components and how they work and that completes in our discussion on chemical rockets. After that we will dedicate couple of lectures on electric propulsion. So, that will complete the course. So, I will stop here today and next class we will discuss solid propellant rockets. Thank you.


to add the number of the decorator on it, and it only optimizes that function or those functions if you have many of them. The nice thing with that is that it allows us to react to the semantics. That means we are not bound to Python's user semantics. We can cheat a bit and we cheat actually quite a bit in order to optimize your code. But also, your high-level code around that, all your classes and meta classes and so on, they can still use all kinds of complicated things that number doesn't support, but it's not a problem. Because since they are executed in the regular Python environments, then number doesn't care. So as I said, specialized, so really, well, right now it's specialized for number crunching. It's really, I would say, it's tailored for NumPy arrays. That is, NumPy array is the dominant data type in scientific computing. It has a lot of features, and we try to support them.  So we are slowly trying to extend the range of things that we support, but still, right now, it's more specialized in number crunching. So the main target is the CPU. We officially support x86 and x8664. Ideally, LLVM provides us with support for many other architectures. And we also have a target for NVIDIA GPUs using CUDA. So this means you write Python code and you can execute it on the GPU. But we have a limited feature set, because there are some limitations on what you can do on a GPU, of course. There isn't a real runtime. You will be able to do memory allocation, but it will be quite slow. And the allocated memory will run in the GPU's global memory, which is not very fast. We also have potential support for other architectures thanks to LLVM. So one of my colleagues tried a number on the Raspberry Pi, and it actually works. But we don't support it officially. I think LLVM takes several hours to compile. We have some support going on for HSA, which is something by AMD called it means Heterogeneous System Architecture. It's an architecture for what they call APUs. So the goal is to blend the programming model between GPUs and CPUs. You write one implementation, and it can run either simultaneously on the GPU or CPU, or you can run it on either of them. And supposedly, there's some memory sharing and so on. Let's talk a bit about the architecture. So number, if you compare it to other jets, is quite straightforward. It's not very exciting. It works one function at a time, which is a constraint which we're going to relax because we need to relax it in order to support recursion. But right now, it's one function at a time. It starts from the Python bytecode. So we don't have a parser. We just use the bytecode emitted by Cpython. And we have a compilation analysis chain, which transforms it slowly across various steps to LLVM IR. So LLVM IR, it's LLVM's internal representation. It's a kind of, let's say, a portable assembly. And it allows you to specify a lot of things. The difference we see, for example, is that you can specify some behaviors in a very granular way. For example, you can specify if signed overflow on integers is well-defined or undefined. If you have, for example, in this example, if you have undefined behavior on signed integers overflow, then it allows LLVM to do further optimizations. So after the LLVM IR is shipped to LLVM, everything is delegated to LLVM itself, including low-level optimizations and also executed in the function. And on top of that, we also generate some Python facing wrappers because each function gets a low-level implementation which takes some native types. And you have to marshal those from and to Python objects. So this is the compilation pipeline. You see there are two entry points there. You can see the wavy rows. So the first entry point is the Python bytecode itself, as I said. We have an analysis chain from the bytecode. First, the bytecode is analyzed. We build a control flow graph, a data flow graph, and we produce something which is called number IR. So number has our intermediate representation, which is quite as high-level as bytecode. But it's a bit different. It's not a stack machine. It's based on values. The second entry point is when a function is actually called. When a function is actually called, we record the types of the values. And we do type inference of those values. We try to propagate all the types across the function. I'm going to talk about the number types just after. It's much more complicated than just mapping some classes to some types because we have more granular typing in number than in Python. After the type inference pass, there's a pass which deals with rewriting the IR. So it's an optional pass which has some optimizations. The next pass is lowering. Lowering is from the LLVM jargon. It means that you take a high-level language, which is numbers IR, and you lower it to something very low-level, which in this case is LLVM IR. And then we ship everything to LLVM, to the LLVMJIT, which produces machine code, and we execute it. So there is a small rectangle named cash, which is grayed out because it's not implemented yet. But ideally, we will be able to cache either the machine code or the LLVM IR in order to have faster compilation times. So number types. As I said, the number type system is more granular and more precise than the Python type system. We have several integer types based on their depending on the bitness, on the signness. We have a single precision and double precision floating point types. We have tuples are typed, which means that you don't have a single tuple type. You have a different tuple type for every kind of parameter that's in the tuple. So tuples are typed based on each element's number type. So you have a different type or type, for example, for a pair of int and float 64, for a pair of float 64 and float 32, and so on. NumPy array themselves, so they are a very important part of number and of scientific computing. They are typed according to their dimensionality and to their contiguousness. So the lowering pass is what really takes the type inferred number IR, and it transforms it into LLVM code, LLVM IR. So this is always straightforward and not very exciting part, but it has a lot of code because we implement a lot of functions. We implement all the operators. We implement math functions and so on. If we are careful enough with what we generate, we can allow LLVM to inline and do other optimizations here. So what's supported? NumPy supports a rather small subset of Python, at least. Unless in text field, unless in text front, it supports quite a bit, but not all. It supports all control flow routines or constructs. It supports raising exceptions, but not catching them. It supports calling other compile functions. We have recent support for generators, but only the simple kind of generators, that is not those to which you can send values, not control routines, but just syntactic iterators with a yield keyword. So what don't we support? We don't support, well, over rest. We don't support exception catching code. We don't support context managers. We don't support comprehensions. And actually, we don't support list and sets and dicts yet, although it will certainly come. And we don't support yield from. As for the built-in types and functions, we have support for most types which are useful for scientific computing. So all the numeric types, integrals, floats, and so on. Topples unknown, which are quite basic. And we have support for the buffer protocol, which means that you can address, you can index over byte by trace memory views. And the very thing which supports the buffer protocol, which also includes, for example, memory map files using the M-map module. We have support for a bunch of built-in functions. And we have support for most operators, but of course, only the types that we support, so all the numeric types. We are able to optimize several of the standard library modules, mostly those which are specialized for numeric computing, so C-map and math, of course. We have support for a random number generation. We actually use the same algorithm as C-piphones, of a mouse and twister, except that we have a separate state. We have support for C-types, which means you can call row C functions from number code, which is a cheap way of actually calling C libraries. And it generates very fast code because it calls it from a native context. Similarly, we support CFFR, which is just a replacement for C-types most of the time. And we support mostly NumPy, at least a large subset of NumPy. So what we support in NumPy is really the objective of the whole page in the documentation. So I'm not really, I'm talking a bit about it here. We support most kinds of arrays in NumPy, so most dimensionalities from 0D to ND. We support arrays of various D-types, scalar arrays, numbers, and so on, structured arrays. We support arrays with sub-arrays in them. The only thing we don't support, and we won't support in a long time, I think, is arrays containing Python objects. Because the whole point of NumPy is to generate native code, which doesn't go through the C-type in API. We have recently added support for constructors, so we can do memory allocation, allocate memory from number functions. Various operations on arrays, such as iterating, indexing, slicing, so there are various kinds of iterators we support, such as v.flat operator and more or less fancy ones. We have support for reductions of the products, accumulative sums, and so on. On the scalar types front, we support a daytime 64 and time delta 64, which are weird, and I think little-known types, which allow you to do low-level computations on some daytime and time deltas. And we support NumPy.random in the same way that we support the random module. So the limitations, apart from what we don't support in terms of syntax, in terms of syntax, and in terms of types, we don't support recursion, so that's because we're compiling one function at a time and we'll have to change that. We can't compile classes. Again, that's because we compile one function at a time, so we don't have a way of specifying a structure and several methods operating on a user-defined type. And the other limitation is that type influence is really has to succeed. If a type influence path fails to infer a type for a given variable, then the whole compilation fails. Ideally, we would have a way to say, well, this is a Python object, but the rest is still in third, so we will be able to bridge it. But right now, this is not possible. And actually, when type inference fails, it goes into a mode called Object Mode, which is not very interesting as far as performance is concerned. So as I said, the fact that it's opt-in, it allows us to relax the semantics. As you have understood, perhaps, it has fixed-size integers up to 64 bits. So for example, if you have an addition of two integers and the result overflows, then you are just seeing a truncated result. You don't have an overflow or anything. We take the liberty of freezing the global and outer variables, so we consider them constants, which makes it much easier to compile. And it allows us to generate more optimized code. For example, if you have a math.py, then usually math.py won't change, so it's only fair to consider it a constant.  It will keep the order value. So we don't have any frame introspection. Basically, we don't have any debugging features right now, neither from the C level nor from the Python level. So this is something which, at least at the C level, we're going to work on it, because we want to expose the names of the JIT functions to LLVM so that you can fire some JDB and have a nice traceback. So how to use it? So basically, the main way to use it is to use the JIT decorator. It's very simple, so you have a function, and you just tag the decorator on it, and hopefully, it will be able to compile it. So the default way is not to pass any argument to the JIT decorator. And it will lazily compile a function. This means that it will wait for a function to be called, and it will do the type inference thing at this point, and it will generate the native code. And since you're calling the function, it will call the native code on the fly. And there's another way to call it, which is to manually specialize the arguments. Let's say you really know you have some 32-bit ints, and you want some double precision floats, or some single precision floats. And so you are able to pass an explicit signature to number the JIT. But this is not really recommended. It's mostly for us to test. So there's an option to remove the guill, which is quite easy for us, since we are not calling any CPiPhone API from the generated native code. So you just pass no guill equals 2, and the guill will be removed. So the guill is a global interpreter lock. For those who don't know, it's a lock which constrains CPiPhone execution to a single thread. If you remove the guill, you can call your function or your functions from several threads and have a parallel execution on several cores. But of course, you have no protection from these conditions. So you are in the same position as a C++ programmer who has to be careful about not having several threads accessing the same data and mutating it, for example. As a tip, instead of having your own thread pool, we just use concurrent.futures on Python 3. Another feature is the vectorized decorator. So NumPy has something called a universal function. To explain what a universal function is, it's better to take an example. So if you take the plus operator between arrays, for example, which is a shortcut to the np.add function, the np.add function is basically doing an element-wise operation on all elements of its inputs. And the way it's implemented is really to have a loop on the element-wise operation internally. And then the nice thing with a universal function is that you have several additional features. There's something called broadcasting in NumPy. So if you are adding, for example, a scalar and an array, actually, the scalar will be added to each element in the array. So really, the lower dimensional argument is broadcasted onto the higher dimensional argument. So this is handled automatically by the UFUNC framework. And the inner loop doesn't have to care about that. And it also gives you, for free, some reduction methods. So you have some reduce and accumulation functions. So NumPy comes with a fixed set of universal functions, so add, multiplication, square root, and so on. Traditionally, if you want to add a universal function, write your own, you have to go in C. So you write your inner loop in C with a specific C API provided by NumPy. You compile it against the right NumPy version, and you get your universal function. So it's not very convenient for users, and the users don't do that. So using NumPy, you can write the element-wise function in the pubes, I think. And you can put the vectorized decorator on it, and it will generate the UFUNC. Another more sophisticated feature of NumPy is a generalized universal function. So this is an extension of the idea of a universal function. The universal function works on one element at a time. It doesn't see the neighbors of the rest of your arrays. A generalized universal function, you can see the whole arrays, and you have to specify exactly what the layout of the inputs are. So it's almost for some more sophisticated functions, such as a moving average. So NumPy also allows you to generate a generalized universal function using the geo-vectorized decorator. So here is an example. It's called an Ising model. So it's something which is used, apparently, mainly for benchmarking, but it seems inspired from some physics model. The basic idea is that you have a 2D grid, a two-dimension grid of Boolean states, either Boolean or binary states, and you can think of it as each element having either a value plus one or minus one, and it starts from a random state, basically, and at each iteration, you make each element a value based upon its neighbors. So at the end, it's supposed to converge towards something which is quite stable. So this was generated with number, this animation. So if you look at how it looks like, well, you have an inner function which processes each element in the array and which updates it based on its neighbor's value. So there are a couple of operations. It takes its neighbor's value, combines it with the actual value of the element, and it takes a decision based on that and a random number. And the outer loop is just looping over the whole array and it updates all elements. So the outer loop which we see in update one frame, it does one iteration, and then if you want to make the model converge, you have to call it a number of times. So if you measure that, well, you get 100 times speedup for number of a C Python, which is less than you get with Fortran, but still it's within range. In this case, it's twice lower and we know why, actually, because array indexing in Python is more sophisticated. For example, well, the main reason is that if you, Python allows negative array indexing, you know that if you have a negative index, you are indexing from the end, so you have to have a runtime check of the negativeness of each number. And in some cases, LRVM isn't able to optimize it out. So besides that, we have QDA support, as I said. So the main API for that is the QDA.Jet decorator. So we don't try to hide the QDA programming model. The QDA programming model is based on the notion of a grid of threads. So you have blocks of threads and you have a grid of blocks. And the GPU executes all those threads in parallel, more or less. But you have to tell the GPU which is the topology of threads. And besides that, there are two types of functions. There are kernel functions, which are called from the CPU, actually. So the kernel function is not able to return a value. You pass it some arrays, some input arrays, some output arrays, which are marshaled automatically by number to the GPU. And you write the results in the array from the GPU. And there's something called device functions which are really sub-functions and they are called from the GPU to the GPU. So these ones can return values. When you're using the QDA support in number, you have a limited array of features because, as I said, you don't have a large runtime available in the GPU. So it also requires the programmer to have not only some knowledge of QDA on how a GPU works, but also to have some intuition of how to optimize the code for execution on the GPU. Because it's not usually, you're not usually arranging your algorithm in the same way on the GPU or on the CPU, especially except in trivial cases. So here is an example. It's a very simple example of this one. It's just to show you how it works. We are trying to compute the cosine of an array. So we're using the QDA.Jet decorator. We have a function which takes two arguments. The first argument is the input array. The second argument is the output array. So there is no convention. It's just a choice here, for example. We must, the idea is that each GPU thread which will compute one value over the array. So it will take one element in the array and compute the cosine and put it in the output array. So the first thing is that you are computing the index. So to compute the index of a current thread, you call the QDA grid function. And then you have to just call math.cos on the input and write it in the output. So this is the definition. Then you want to call it. You have to, so GPU cos defines the GPU function. Then you want to instantiate the kernel, actually. And instantiated the kernel means that you define the grid topology. So this is the thread config here. It's a two-element topo. The first element is the number of blocks in the grid, I think. And the second number is the number of threads in each block. So you define the topology based on the output. And you call the GPU cos function with the topology and the input and output. So, well, in this example, the numbers are better on the GPU, but it's not very important because you won't. You wouldn't use a GPU just to compute a cosine. You will do something more complex. So if you want to install number, since it's open source, you can compile it from scratch if you want. But you have to compile LLVM in a specific version of it because LLVM has backwards and compatible changes in each feature release. So the current version of number is LLVM 3.6. And you will have to fetch LLVM 3.6, compile it for your platform, or get, if you can get them, some binary development packages. And then you have to compile LLVM light with a sufficiently recent C++ compiler, which is not trivial at all. So we really recommend you use Conda, which is a continuous-owned package manager. So it's an open-source package manager. And it comes with a default distribution of binary packages called Anaconda. And if you have Conda, you just type Conda installed number and you have it on your platform. So, let's wrap up. So you can find documentation on the web. We have, of course, GitHub account with code and issue tracker. You are very welcome to come to a number user's mailing list, either as a user or as a potential contributor. I must also mention that number is commercially supported by Continuum Analytics. So if you want to buy consulting enhancements, support for some architectures, you can write to sales at Continuum.io. And there's a last thing called NumberPro, which is an extension, a proprietary extension to Number, which provides bindings to some specialized libraries for the GPU, various scientific specialized libraries. And it also has, I think it has extensions to allow it to parallelize the code easier on the CPU. So that's it. So two questions about your use of LLVM.  Why is it that you don't just have the same support requirements and platform list as LLVM? What did you say? We support a subset of what? Do you support everything that LLVM supports or do you only support a couple? You mean as architectures? Yes. It's a matter of validation because ideally it works, but who knows what it will give actually, you know? Okay. And I was also wondering a couple of years ago, the attempt to marry CPython and LLVM together called Unladen Swallow. I was wondering if like nothing ultimately came of it and Unladen Swallow died, but I was wondering if the work that they had done was helpful at all in the development of Numba. I don't think so. Well, not directly. Then at the time they said that they had helped LLVM improve their support for JIT compilers, perhaps indirectly benefited, but we didn't take anything from them because we use our own wrapper run LLVM called LLVM Lite. And then Numba is pure Python. The big difference with Unladen Swallow is that Unladen Swallow did everything in C++, which I think was a very, I mean, it's necessary if you want to compile very fast, but it's also much less flexible. So pure Python allows us to experiment and develop very quickly. I have three questions. First question is, does a number compile, do you do the JIT compiling in a separate thread? No, it's in the same thread. So you actually have to wait for the compilation to finish before it gets fast? Yeah, well, what will you do anyway? Oh, you mean when you, because it's lazily compiling, so if it's compiling when you're calling the function, anyway, you must wait for it. Yeah, of course, but I mean, well, anyway. Sometimes in some JIT compilers, they do it in a separate thread and it just continues with the slow version until it's done. Oh, right, no, we don't do it. Okay. Second one is, do you have any support for storing the compiled code? For? For storing the compiled code on this? Oh, not yet, no, as I said, we want to support caching, but not yet. So that's what you meant with caching. So you actually, not like PyPy, which has the problem that it cannot store the compiled version? I'm not sure if PyPy does that. Okay. So they have to redo it every time you run the code. So it would be more efficient if you just do it once and then store it and then just finish it. That's not the best way, not the best thing to add, but right now we don't have it. Okay, and third one is, how do you do error handling? Because you said you don't have any way to catch exceptions? Yeah, so we have a way to raise them, so if you raise an exception for number code, then you just catch in when it goes outside of the number code. So you can communicate errors to the user, but you can't handle it in the number code. And maybe an extra question. So you support, so you're working for the support of NumPy? Do you plan also to support CYPy? Are there some plans for that or? Not yet. We mostly support NumPy right now. So every kind of pure Python code which relies on NumPy arrays may be perhaps accelerated if it intersects with a subset of things we support. But we don't have direct support for anything other than NumPy right now. I suppose someday we want to support pandas. Yeah. We have no more time for questions. Thank you.