Writing a Script

The script you write is executed every time the optimisation program runs, with different input variables each time.

The script is written in C# using the .net 4.6 scripting language Roslyn.

Referencing Other Libraries

Other .net libraries can be referenced for use in the C# scripting environment by placing the following at the top of the script:

#r "C:\Some\Path\To\.net\library.dll"

Importing Namespaces

Namespaces can be imported by using the “imports XXXXX;” syntax, placed directly after any references to other libraries at the top of the script.

For example, to reference the a library called “DataAnalysis.dll” which contains the namespace “DataAnalysis”, the top of your script would look like this:

#r "C:\MyDlls\DataAnalysis.dll"
imports DataAnalysis;

If you try to use a namespace which cannot be found in any of the loaded libraries, pressing Build will result in an error in the Compilation Warnings window.

Comments

It is a good idea to comment your code so other people will understand what your script should be doing. It is also useful for when you re-read your script. To add a comment to your script, use the standard C# syntax for comments:

//Create a new instance of Tas3D (this is a comment)
Tas3D.T3DDocument doc = new Tas3D.T3DDocument();

Multithreading

GenOpt is multithreaded, which means your script might get executed several times at once. This is great for saving time, but you must be careful to ensure your script will not be ‘fighting for resources’. If your script opens a file, only one application can access the file at a time. If thread 1 opens your file and then thread 2 tries to open the same file, an error will occur. It is therefore a good idea to make a copy of the file and save it in the current working directory. The current working directory is unique for each thread, so this will prevent the script ‘fighting’ for the same resources:

string pathToFile =TasFiles.getFiles(TasGenComm.TasFiles.TasExtension.T3D)["MyT3D.t3d"].FullPath;
string newPathToFile = TasExtensions.CopyToCurrentDirectory(pathToFile,true);

The variable pathToFile points to the file called ‘MyT3D.t3d’ in the main project directory selected when launching TasGenOpt.

The variable newPathToFile is created by getting the current directory and combining this with the file name from the other directory.

The file is then copied from the original path to the new path, and the file can then be opened using the newPathToFile.

Writing a Good Cost Function

One of the biggest challenges associated with optimisation is writing a good cost function. Remember, every time GenOpt runs it tries to work out which variable values minimise your cost function which you set via the Result output variable.

If you are only interested in one output, e.g. daylight factor or heating demand, the cost function can be that value directly (or the inverse of that value, if you are trying to maximise it).

If you are interested in multiple output values, e.g. balancing internal temperature with the daylight factor, the cost function must be a function of internal temperature and daylight factor such that increasing the daylight factor decreases the overall cost function and increasing the internal temperature increases the overall cost function. One example might be:

\[Result = 1/DaylightFactor + InternalTemperature\]

The cost function can quickly get very complicated if you want your output variables to be within certain ranges!

Troubleshooting

Sometimes you may find that your script does not run the way you expect it to. You may find that when you press Simulate, there is an error but you can’t tell where the error occurs.

The first thing to do is to check the Simulation Errors output window carefully, as this will often tell you the line number in your script where the error occured:

images/sim_err.png

Occasionally, you may not be able to determine which line the error occurs on; in this situation, it is usually a good idea to print messages to the screen that give you information about what the script is doing. For example, consider the following example script:

TAS3D.T3DDocument doc = new TAS3D.T3DDocument();
doc.Open(TasFiles.getFiles(TasGenComm.TasFiles.TasExtension.T3D)["MyT3D.t3d"].FullPath);
doc.Building.northAngle = Variables["MyVariableName"].VariableValue;
doc.DaylightInitCalculation(1,1,1,0);
doc.DaylightCalculation(0);

double daylightFactor = doc.GetDaylightFactor(doc.Building.GetZone(1));

ScriptOutput.SetValue("Result",daylightFactor);

This script opens a T3D document, changes the north angle and performs a daylight calculation and returns the daylight factor.

If you press Simulate you will find that the script does not run properly, and it is not clear why. Now consider the following modification:

Console.WriteLine("Creating new T3D document object");
TAS3D.T3DDocument doc = new TAS3D.T3DDocument();

Console.WriteLine("Open the T3D file called 'MyT3D'");
doc.Open(TasFiles.getFiles(TasGenComm.TasFiles.TasExtension.T3D)["MyT3D.t3d"].FullPath);

Console.WriteLine("Change the north angle");
doc.Building.northAngle = Variables["MyVariableName"].VariableValue;

Console.WriteLine("Prepare to do a daylight calculation");
doc.DaylightInitCalculation(1,1,1,0);

Console.WriteLine("Do the daylight calculation");
doc.DaylightCalculation(0);

Console.WriteLine("Get the daylight factor for the first zone");
double daylightFactor = doc.GetDaylightFactor(doc.Building.GetZone(1));

Console.WriteLine("Set the daylight factor result as the result for the cost function");
ScriptOutput.SetValue("Result",daylightFactor);

Console.WriteLine("Script finished successfully");
When we examine the TasGenExecute window when we press simulate, we get the following output:
_images/consoleoutput.png

We can see that the script is getting stuck trying to initialise the daylight calculation. We can open the T3D file and try to perform a daylight calculation to investigate further.

If you find that the console window is closing too quickly for you to read the messages, you can try telling the script to pause in various places until you press a key on the keyboard:

Console.WriteLine("Waiting for key press to continue");
Console.ReadKey();
_images/readkey.png

You can place several of these throughout the script to determine where the script gets to before something goes wrong.