In the implementation of a flow models that function with Modelica Standard Library DynamicPipe (or a similar model that builds from PartialTwoPortFlow) there are examples of flow models that take place in an environment with heat transfer that requires wall properties (e.g., heatPorts.T and/or heatPorts.Q_flow) in order to calculate the pressure drop.
For example, a pressure drop model may need to calculate a new visocisty or Prandtl number based on the medium pressure and the wall temperature to capture cooling/heating effects, etc.
The heat transfer model obtains properties of the medium via passing the "states" however there is no existing connection in DynamicPipe or PartialTwoPortFlow that goes the other way.
I've tried numerous variations of ideas and have had no success, including creating a new PartialTwoPortFlow that contains all the heat transfer calls that exist in DynamicPipe.
I hesitate to post this question as I am surprised I am having so much difficulty with this and would not be surprised to find a straight forward solution. Nevertheless I need this ability and curious if others have already solved this issue as I am running short on ideas.
So my questions is:
What is a proper/efficient means of passing the heatPorts.T values to the flowModel?
For those familiar with the MSL Fluids library and more specifically the Pipe models provided, this answer should (hopefully) make sense.
Aside:
It seems the dynamic pipe could be improved a little bit by not restricting the heat transfer area to the perimeter x lengths and instead introduce a parameter (e.g., heatTransferArea) that would permit the user to define it and default to perimeter x lengths. See below
parameter SI.Area heatTransferArea = perimeter*lengths "Total heat transfer area";
HeatTransfer heatTransfer(
...
final surfaceAreas=heatTransferArea , //perimeter*lengths <- replaced
...
End Aside:
In order to communicate heatPorts.T to the flowModel and to not have errors when I checked each of the models I had to do the following:
Make an "input" in the flowModel for Ts_w. Not parameter (take a look at how mediums.state is passed)! Might have to do some finagling with it like "diameters" (see DetailedPipeFlow) to make it be used how you think it's going to be used.
Duplicate PartialTwoPortFlow and add the final Ts_w = Ts_wFM to flowModel. Additionally define the variable SI.Temperature[nFM+1] Ts_wFM in PartialTwoPortFlow and establish definitions similar to statesFM in the equation section.
This will require adding a HeatPorts model to be added.
Duplicate DynamicPipe and change the extension to the new PartialTwoPortFlow. Set use_HeatTransfer to true (as I've set it up this has to be true now for this to work which isn't ideal but manageable). Might be good to make it a final parameter so it can't be changed.
Don't forget to connect heatPorts to the heatports added in step 2.
I believe that this capture a quick version of how I was able to get the wall temperature passed to the flowModel. Perhaps there is a more elegant way but I though this was pretty serviceable. I now simply have one more Partial model and one more pipe model called PartialTwoPort_wTemp and GenericDynamicPipe (I also incorporated my surfaceArea correction in the new pipe).
Related
I am interested to replace my own PID-regulator models with MSL/Blocks/Continuous/LimPID. The problem is that this model restricts limitations of output signals to be parameters and thus do not allow time-varying limits, which I need to have.
Studying the code I understand that the output limitation is created by a block MSL/Blocks/Nonlinear/Limiter and I just want to change this to the block VariableLimiter.
I can imagine that you need to ensure that changes of output-limitations vary in a time-scale slower than the regulator in order to not excite unwanted behaviour of the controller. Still here is a class of problems where it would be very useful to allow this limits to vary slowly.
Thanks for the good input to my question and below a very simple example to refine my question. (The LimPID is more complicated and I come back to that).
Let us instead just modify the block Add to a local block in MyModel.
I copy the code from Modelica.Blocks.Math.Add and call it Addb in MyModel. Since here is a dependence of Interfaces.SI2SO I need to make an import before the extends-clause. This import I take from the ordinary general MSL package, instead of copying also that in to MyModel. Then I introduce a new parameter "bias" and modify the equation. The annotation may need some update as well but we do not bother with that now.
MyModel
...
block Addb "Output the sum of the two inputs"
import Modelica.Blocks.Interfaces;
extends Interfaces.SI2SO;
parameter Real k1=+1 "Gain of input signal 1";
parameter Real k2=+1 "Gain of input signal 2";
parameter Real bias=0 "Bias term";
equation
y = k1*u1 + k2*u2 + bias;
annotation (...);
end Addb;
MyModel;
This code seems to work.
My added new question is whether it is enough to look up "extends-clauses" and other references to MSL and make the proper imports since the code is now local, or here are more aspects to think of? The LimPID code is rather complex with procedures for initialization etc so I just wonder if here is more to do than just bring in a number of import-clauses?
The models in Modelica Standard Library (MSL) should only be seen as exemplary models, not covering all possible applications. MSL is write protected and it is not possible to replace the limiter block in LimPID (and add max/min input connectors). Also, it wouldn't work out if you shared your simulation model with others, expecting their MSL to work like your modified MSL.
Personally, I have my own libraries of components where MSL models are inadequate. For example, I have PID controllers with variable limits, manual/automatic functions and many more functions which are needed in my applications.
Often, I create a copy of an MSL model, place it in the same package in my own library and make the necessary modifications and additions, e.g. MyLibrary.Blocks.Continuous.PID.
Is it possible to have OSMnx (great tool BTW) include car ferries when building a graph? Failing that, what would be the most direct way to build such a graph? The problem isn't just that the ferry routes themselves aren't present but, without the ferries, islands that are in reality reachable by car aren't included in the road network.
I have tried using osmnx.settings.useful_tags_way to no avail. Using 'route'='ferry' in overpass-api returns what I would like to include in the graph so I have been editing the OSMnx downloads.py file trying to alter the overpass-api call directly.
Thanks!
First pass (hacky)
I've came up with fairly hacky partial solution by editing osmnx's downloads.py file and replacing the line (originally around line 350):
query_str = f"{overpass_settings};(way{osm_filter}(poly:'{polygon_coord_str}');>;);out;"
with:
osm_filter2 = f'["route"="ferry"]'
query_str = f"{overpass_settings};(way{osm_filter}(poly:'{polygon_coord_str}');>;way{osm_filter2}(poly:'{polygon_coord_str}');>;);out;"
The query string format took some trial and error. If this, or something like it, turns out to be the best approach, I'll try to make it more broadly applicable (add "ferry" to the predefined filter list rather than hardcoded, pass a list of filters, etc).
Much Better
I found that building separate graphs and unioning them using networkx.union or networkx.disjoint_union did not give usable results. So I have added a multiple filter capability to my version of the osmnx downloads.py file. I also added some additional network type options. So it's now possible to pass, for instance, "ferry" as a network_type for the osmnx.graph_from_* functions:
network_type = "ferry"
I can also now pass multiple network types using a pipe delimiter:
network_type = "drive|ferry"
to get a graph that is the union of the two. When doing this, I found that it's useful to create a second ferry-only graph and use that as a reference to update the tags in the combined network graph. It is also better to load non-simplified graphs at first and and simplify it/them yourself after this step.
Still experimenting
Still having some issues with non-connectedness - now in the ferry-only network. Car ferries at isolated crossings than don't share a harbor with a through-ferry are not included in the ferries-only graphs and therefore the tags of their counterparts in the combined network aren't getting updated as needed. The ferries in the combined network (network_type = "drive|ferry") are all present and connected correctly and therefore their respective islands are now on the road network - which is great. But, because their tags aren't being updated, these isolated ferries are getting default highway speeds (and I'm doing travel time analysis). I can use work around this using:
if not 'highway' in edge[3]:
but, for a robust solution, I think we want to be able to tag them explicitly.
I'd still love to hear what other think.
I've created a Pure Data abstraction which takes 5 MIDI controller IDs as arguments, and has two inlets (velocity and MIDI controller). I use spigot to output the input velocity at outlet i if the MIDI controller ID matches the i th argument to the abstraction.
I use this to control 5 sliders (volume, attack, decay, sustain, release) from my MIDI controller, which look like this:
As you can see, the abstraction is very repetitive, and ideally it would be able to take n arguments, outputting the slider value of the given MIDI slider at the i th outlet. Alternatively I could just use a single argument and use the abstraction anew for each slider, but that's a bit repetitive too.
Is there a way to take n arguments in my abstraction? Or, is there any other more elegant solution to control sliders from MIDI that I'm missing?
For core vanilla objects or externals it is a common feature to take a variable amount of arguments. Many objects like [trigger], [select], [pack] or [unpack] behave this way and create a number of xlets according to how many arguments they are given.
For abstractions however, there is no simple way to have a variable number of outputs depending on the number of arguments given. It's possible, but it's rather a hack.
Let's first look at some techniques to make the patches easier.
As you can see in the following screenshot the [expr] object in your patch can easily be substituted by a simple Pd object: [==]
Let's look at the MIDI messages. MIDI objects output the elements of the hierarchical tree: channel, controller, value in this order but from right to left (true for all objects in Pd, the rightmost outlet fires first). What you want is routing them according to the controller number, ignoring the channel number. For this you need to flip the order of the two first outlets so you can use the controller number as a selector in a list. One way to do this is to pack the numbers and then reorder them in a message using the dollar symbols (careful, dollar symbols in message objects operate on local messages, they have nothing to do with what dollar symbols do in object boxes). Another method would be to use the object [swap] (using [swap] in this case would reduce the number of objects by one in the patch, but the [pack] and [message( is more versatile, that's why I show it here).
Regarding the actual question of taking n arguments to change the number of outlets: This challenge are two separate problems:
How to detect the number of arguments
How to change the number of outlets dynamically
Until recently there hasn't been a way proper way to detect the existence of arguments. Since Pd 0.50 there is [pdcontrol] which allows exactly this.
Using [initbang] here because [loadbang] would fire too late for creating the outlets.
The second part of the challenge may be solved either through a technique called 'dynamic patching' or by outputting a list instead of creating additional outlets. However with a list output you'd need to route it afterwards and then you'll arrive quickly at the patch pictured above.
I am currently coding a new library with several models in it (I am used to Matlab, but not to Simulink). I am able to create a model with block parameters, let's say parameter 'p', and a callback function (initfct) which uses this parameter to compute specific values used inside my model (let say a simple gain K=K(p)).
My problem is that my parameter 'p' and 'K' are available directly on the workspace, what I don't want to. Moreover, if I use twice or more this model in a system, the two models share always the same 'K', which also I don't want to.
So how I can make these variables 'p' and 'K' independent when I use my custom model several time, and to prevent these variables to be viewed in the workspace ?
Should I use "Reference models", but I am not familiar with this feature ... ?
Thanks for you answer,
Michael
Within a callback, gcb returns the path to the block which currently executes the callback. Having the path, you can use get_param to access the parameters.
Just for demonstation purposes, insert the following to the MoveFcn of a delay block:
set_param(gcb,'DelayLength',num2str(randi(10)))
It will randomly change the delay whenever the block is moved.
I am not sure if my answer explains everything you need. It might be that you also need a Mask. If you think this answer is incomplete, please update your question and include a small example model demonstrating your problem.
Thanks, with your help I was able to solve the problem.
To be more specific if someone else has the same problem : you need in your mask to declare also internal variables used by the callback function. Unchecked the relevant options so that they not appear as standard input parameters of your model.
My problem was also to use num2str instead of mat2str (when the gain was a matrix acting on multiple inputs).
I am using Behavior Search to calibrate my NetLogo model for 20 different hospital units. I am using global variables to set the min and max for several sliders in my model, but I think this is causing an error in Behavior Search when I attempt to load the parameter values from the model. However, I don't want to manually enter these parameter ranges manually each time I use Behavior Search.
Is there a way to get around this error? Is there a way to set the min and max for a specific slider to a constant, rather than using global variables?
Thanks for your help!
BehaviorSearch developer here -- if I'm understanding your question correctly, your NetLogo model has a slider which has a min/max constraint that is not set to a constant, but is instead set to a global variable (in the slider settings, accessed from the NetLogo interface).
When I choose such a model using the BehaviorSearch GUI, and then click the "Load parameter ranges from model interface" button, then I get the value of 0 for that constraint. (I don't see any error message -- just the value 0 (if you're getting an error message instead, then I may not be understanding your situation correctly, and perhaps you could post exactly what error message you're seeing?)
This will be true even if you are setting the slider min/max to a global value in the special STARTUP procedure (see: http://ccl.northwestern.edu/netlogo/docs/dict/startup.html), because STARTUP is only run when a model loads in the NetLogo GUI, and not when a model is loaded in headless NetLogo.
Thus, unfortunately, I think the answer to your question is: "no, there isn't a way to get BehaviorSearch to load the parameter ranges from global variables within the model".
Some possible work-arounds:
BehaviorSearch is open-source -- some changes could be made to it -- i.e., maybe adding in a call to "startup" whenever BehaviorSearch GUI loads the parameter ranges would be sufficient for you.
If you're only doing a few searches, I don't see why manually editing the parameter ranges would be particularly onerous. However, if you're generating a lot of different searches with this model, then I can see how it might be an issue. The .bsearch files are just XML text files, so you might consider generating them without the BehaviorSearch GUI, e.g. using a scripting language.