diff --git a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/appendix-A-using-opentd-with-MATLAB.md b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/appendix-A-using-opentd-with-MATLAB.md index 7f644b4234..e775351756 100644 --- a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/appendix-A-using-opentd-with-MATLAB.md +++ b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/appendix-A-using-opentd-with-MATLAB.md @@ -6,6 +6,7 @@ While it is not feasible for us to maintain separate "Getting Started with OpenT %% Using OpenTDv242 with MATLAB % CRTech % Tested with MATLAB R2023b + % OpenTD is an Application Programming Interface (API) for Thermal Desktop % (TD) that allows you to automate many of the tasks currently performed % interactively using TD’s Graphical User Interface (GUI). OpenTD gives you @@ -13,6 +14,7 @@ While it is not feasible for us to maintain separate "Getting Started with OpenT % models. You can use any .NET language to interact with OpenTD (C#, % VB.NET, F\#, etc.) or any system that can load .NET assemblies such as % MATLAB or Python. + % Regardless of how you interact with OpenTD, you’ll need to have at least % an intermediate understanding of .NET object-oriented programming. If you % are starting from scratch, we recommend learning C#, since it is the @@ -20,106 +22,123 @@ While it is not feasible for us to maintain separate "Getting Started with OpenT % compelling reasons for you to connect to OpenTD via MATLAB. It is % possible, although the way MATLAB handles .NET enums is awkward and % MATLAB does not support implicit constructors. + % To get started with OpenTD, read "Getting Started with OpenTDv242.pdf", % which can be found in your TD v241 installation directory under "Manual". % The Getting Started guide explains the fundamental concepts of OpenTD, % using several C# examples. We've ported one of those examples to MATLAB % below. + %% The "Create and Run a Case" example ported to MATLAB % See "Getting Started with OpenTDv242.pdf" in your TD v241 installation % directory under "Manual" for an explanation of this script. + % Note: Please contact us at crtech.support@ansys.com if you think there are % better ways to use OpenTD with MATLAB, especially with regard to .NET % enums and implicit constructors. For examples of awkward code, see how a % node is set to be a boundary node and how the InitialTemp of a node is % set -- in the script below vs. in the original C#. + openTD = NET.addAssembly('OpenTDv242'); -import OpenTDv242.\*; +import OpenTDv242.*; td = ThermalDesktop; td.Connect(); -% \*\*\* Create a simple model of a heated bar \*\*\* + +% *** Create a simple model of a heated bar *** barNodes = NET.createArray('OpenTDv242.Node', 10); for i = 1:10 -n = td.CreateNode(); -n.Submodel = SubmodelNameData('bar'); -n.Id = i; -n.MassVol = 10; -n.Origin = Point3d(0.01 \* (i - 1), 1, 0); -n.InitialTemp = Dimensional(n.InitialTemp, 300); -n.Update(); -barNodes(i) = n; + n = td.CreateNode(); + n.Submodel = SubmodelNameData('bar'); + n.Id = i; + n.MassVol = 10; + n.Origin = Point3d(0.01 * (i - 1), 1, 0); + n.InitialTemp = Dimensional(n.InitialTemp, 300); + n.Update(); + barNodes(i) = n; end for i = 1:9 -c = td.CreateConductor(... -Connection(barNodes(i).Handle), Connection(barNodes(i+1).Handle)); -c.Submodel = SubmodelNameData('bar'); -c.Value = 0.1; -c.Update(); + c = td.CreateConductor(... + Connection(barNodes(i).Handle), Connection(barNodes(i+1).Handle)); + c.Submodel = SubmodelNameData('bar'); + c.Value = 0.1; + c.Update(); end + roomAir = td.CreateNode(); roomAir.Submodel = SubmodelNameData('room'); roomAir.NodeType = OpenTDv242.('RcNodeData+NodeTypes').BOUNDARY; roomAir.Origin = Point3d(0.055, 1.1, 0); roomAir.InitialTemp = Dimensional(roomAir.InitialTemp, 300); roomAir.Update(); + barConnections = NET.createGeneric(... -'System.Collections.Generic.List', {'OpenTDv242.Connection'},10); + 'System.Collections.Generic.List', {'OpenTDv242.Connection'},10); for i = 1:10 -barConnections.Add(Connection(barNodes(i).Handle)); + barConnections.Add(Connection(barNodes(i).Handle)); end convection = td.CreateConductor(... -Connection(roomAir.Handle), barConnections); + Connection(roomAir.Handle), barConnections); convection.Value = 1; convection.Submodel = SubmodelNameData('room'); convection.Update(); + qTorch = td.CreateSymbol('qTorch', '80'); heatLoadConnections = NET.createGeneric(... -'System.Collections.Generic.List', {'OpenTDv242.Connection'},1); + 'System.Collections.Generic.List', {'OpenTDv242.Connection'},1); heatLoadConnections.Add(Connection(barNodes(1).Handle)); torch = td.CreateHeatLoad(heatLoadConnections); torch.ValueExp.Value = qTorch.Name; torch.Submodel = SubmodelNameData('torch'); torch.Update(); + td.ZoomExtents(); -% \*\*\* End simple model creation \*\*\* +% *** End simple model creation *** + % Create a transient case and run it: nominal = td.CreateCaseSet(... -'transient with nominal torch', '', 'torchNom'); + 'transient with nominal torch', '', 'torchNom'); nominal.SteadyState = 0; nominal.Transient = 1; nominal.SindaControl.timend... -= Dimensional(nominal.SindaControl.timend, 600); + = Dimensional(nominal.SindaControl.timend, 600); nominal.Update(); nominal.Run(); + % Create a cold case by overriding a symbol, and run it: cold = td.CreateCaseSet(... -'transient with cold torch', '', 'torchCold'); + 'transient with cold torch', '', 'torchCold'); cold.SteadyState = 0; cold.Transient = 1; cold.SindaControl.timend... -= Dimensional(nominal.SindaControl.timend, 1200); + = Dimensional(nominal.SindaControl.timend, 1200); cold.SymbolNames.Add(qTorch.Name); cold.SymbolValues.Add('50'); cold.SymbolComments.Add('cold torch heat input'); cold.SaveAll = 1; cold.Update(); cold.Run(); + %% Working with Dimensionals + % All dimensional quanitities in the API are stored using a custom .NET % generic type called a Dimensional. For example, a Dimensional % stores temperatures. Using C#, Dimensionals are implicitly cast to and % from doubles as required, but this does not appear to work in MATLAB. % Instead, we've overloaded the double function and created a Dimensional % function to explicitly cast doubles to Dimensionals. + function x = double(Dimensional) % Cast a .NET generic Dimensional type to a double -x = Dimensional.op_Implicit(Dimensional); + x = Dimensional.op_Implicit(Dimensional); end + function x = Dimensional(Dimensional, double) % Cast a double to a .NET generic Dimensional type -x = Dimensional.op_Implicit(double); + x = Dimensional.op_Implicit(double); end + %% Acknowledgements + % Thank you to Dan Hensley and Daniel Reasa with ATA Engineering for % performing some of the early work to determine how to use OpenTD with % MATLAB. diff --git a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/appendix-B-using-opentd-with-python.md b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/appendix-B-using-opentd-with-python.md index d33afe78e4..8fa3641fe3 100644 --- a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/appendix-B-using-opentd-with-python.md +++ b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/appendix-B-using-opentd-with-python.md @@ -3,61 +3,74 @@ While it is not feasible for us to maintain separate "Getting Started with OpenTD" guides for every programming language, we would still like to help you get started with OpenTD, even if you are not using C#. The following .py script is a MATLAB port of the program in the [Create and run a case](working-with-case-sets.md#create-and-run-a-case) section. This can be used as a sort of "Rosetta Stone" to help you translate other C# examples to Python. It uses the pythonnet module, found at: [http://pythonnet.github.io/](http://pythonnet.github.io/). ```python -\#\#\#\# Using OpenTDv242 with Python \#\#\#\# -\# CRTech -\# Feb, 2022 -\# Created with Python 2.7.15 and pythonnet 2.3.0 -\# OpenTD is an Application Programming Interface (API) for Thermal Desktop -\# (TD) that allows you to automate many of the tasks currently performed -\# interactively using TD's Graphical User Interface (GUI). OpenTD gives you -\# the tools to programmatically create, query, edit, delete, and run -\# models. You can use any .NET language to interact with OpenTD (C#, -\# VB.NET, F#, etc.) or any system that can load .NET assemblies such as -\# MATLAB or Python. -\# Regardless of how you interact with OpenTD, you'll need to have at least -\# an intermediate understanding of .NET object-oriented programming. If you -\# are starting from scratch, we recommend learning C#, since it is the -\# language that we support. However, we understand that there might be -\# compelling reasons for you to connect to OpenTD via Python. It is -\# possible using the pythonnet module: -\# http://pythonnet.github.io/ -\# To get started with OpenTD, read "Getting Started with OpenTDv242.pdf", -\# which can be found in your TD v241 installation directory under "Manual". -\# The Getting Started guide explains the fundamental concepts of OpenTD, -\# using several C# examples. We've ported one of those examples to Python -\# below. -\#\#\#\# The "Create and Run a Case" example ported to Python \#\#\#\# -\# See "Getting Started with OpenTDv242.pdf" in your TD v241 installation -\# directory under "Manual" for an explanation of this script. -\# Note: Please contact us at crtech.support@ansys.com if you think there are -\# better ways to use OpenTD with Python, especially with regard to setting -\# dimensional values. -\# REQUIREMENT: You must install the pythonnet module to use this script. +#### Using OpenTDv242 with Python #### +# CRTech +# Feb, 2022 +# Created with Python 2.7.15 and pythonnet 2.3.0 + +# OpenTD is an Application Programming Interface (API) for Thermal Desktop +# (TD) that allows you to automate many of the tasks currently performed +# interactively using TD's Graphical User Interface (GUI). OpenTD gives you +# the tools to programmatically create, query, edit, delete, and run +# models. You can use any .NET language to interact with OpenTD (C#, +# VB.NET, F#, etc.) or any system that can load .NET assemblies such as +# MATLAB or Python. + +# Regardless of how you interact with OpenTD, you'll need to have at least +# an intermediate understanding of .NET object-oriented programming. If you +# are starting from scratch, we recommend learning C#, since it is the +# language that we support. However, we understand that there might be +# compelling reasons for you to connect to OpenTD via Python. It is +# possible using the pythonnet module: + +# http://pythonnet.github.io/ + +# To get started with OpenTD, read "Getting Started with OpenTDv242.pdf", +# which can be found in your TD v241 installation directory under "Manual". +# The Getting Started guide explains the fundamental concepts of OpenTD, +# using several C# examples. We've ported one of those examples to Python +# below. + +#### The "Create and Run a Case" example ported to Python #### +# See "Getting Started with OpenTDv242.pdf" in your TD v241 installation +# directory under "Manual" for an explanation of this script. + +# Note: Please contact us at crtech.support@ansys.com if you think there are +# better ways to use OpenTD with Python, especially with regard to setting +# dimensional values. + +# REQUIREMENT: You must install the pythonnet module to use this script. + import sys import clr -\# Need to add explicit GAC path to sys.path so clr.AddReference -\# can find OpenTDv242.dll. Note the use of forward slashes in the path: + +# Need to add explicit GAC path to sys.path so clr.AddReference +# can find OpenTDv242.dll. Note the use of forward slashes in the path: sys.path.append("C:/Windows/Microsoft.NET/assembly/GAC_MSIL/OpenTDv242/ReplaceMe") clr.AddReference("OpenTDv242") -from OpenTDv242 import \* -\# We'll want to use .NET System types and generic Lists: -from System import \* +from OpenTDv242 import * + +# We'll want to use .NET System types and generic Lists: +from System import * from System.Collections.Generic import List -\# To access dimensional quantities in OpenTD, we need to use Dimensionals. -\# These are cast to/from doubles implicitly in C#, but here we'll need to -\# refer to them explicitly. (See setting InitialTemp, below.) + +# To access dimensional quantities in OpenTD, we need to use Dimensionals. +# These are cast to/from doubles implicitly in C#, but here we'll need to +# refer to them explicitly. (See setting InitialTemp, below.) from OpenTDv242 import Dimension -from OpenTDv242.Dimension import \* +from OpenTDv242.Dimension import * + td = ThermalDesktop() td.Connect() -\# \*\*\* Create a simple model of a heated bar \*\*\* + +# *** Create a simple model of a heated bar *** barNodes = List[Node]() for i in range(10): n = td.CreateNode() n.Submodel = SubmodelNameData("bar") n.Id = i + 1 n.MassVol = 10.0 - n.Origin = Point3d(0.01 \* i, 1.0, 0.0) + n.Origin = Point3d(0.01 * i, 1.0, 0.0) n.InitialTemp = Dimensional[Dimension.Temp](300.0) n.Update() barNodes.Add(n) @@ -66,12 +79,14 @@ for i in range(9): c.Submodel = SubmodelNameData("bar") c.Value = 0.1 c.Update() + roomAir = td.CreateNode() roomAir.Submodel = SubmodelNameData('room') roomAir.NodeType = RcNodeData.NodeTypes.BOUNDARY roomAir.Origin = Point3d(0.055, 1.1, 0.0) roomAir.InitialTemp = Dimensional[Dimension.Temp](300.0) roomAir.Update() + barConnections = List[Connection]() for n in barNodes: barConnections.Add(Connection(n)) @@ -79,6 +94,7 @@ convection = td.CreateConductor(Connection(roomAir), barConnections) convection.Value = 1.0 convection.Submodel = SubmodelNameData("room") convection.Update() + qTorch = td.CreateSymbol("qTorch", "80") heatLoadConnections = List[Connection]() heatLoadConnections.Add(Connection(barNodes[0])) @@ -86,16 +102,19 @@ torch = td.CreateHeatLoad(heatLoadConnections) torch.ValueExp.Value = qTorch.Name torch.Submodel = SubmodelNameData("torch") torch.Update() + td.ZoomExtents() -\# \*\*\* End simple model creation \*\*\* -\# Create a transient case and run it: +# *** End simple model creation *** + +# Create a transient case and run it: nominal = td.CreateCaseSet("transient with nominal torch", "", "torchNom") nominal.SteadyState = 0 nominal.Transient = 1 nominal.SindaControl.timend = Dimensional[Dimension.Time](600.0) nominal.Update() nominal.Run() -\# Create a cold case by overriding a symbol, and run it: + +# Create a cold case by overriding a symbol, and run it: cold = td.CreateCaseSet("transient with cold torch", "", "torchCold") cold.SteadyState = 0 cold.Transient = 1 @@ -103,12 +122,13 @@ cold.SindaControl.timend = Dimensional[Dimension.Time](1200.0) cold.SaveQ = 1 cold.SymbolNames.Add(qTorch.Name) cold.SymbolValues.Add("50") -cold.SymbolComments.Add("cold torch heat input"); -cold.SaveAll = 1; +cold.SymbolComments.Add("cold torch heat input") +cold.SaveAll = 1 cold.Update() cold.Run() -\#\#\#\# Acknowledgements -\# Thank you to James Etchells with the European Space Agency (ESA) for -\# performing some of the early work to determine how to use OpenTD with -\# Python. + +#### Acknowledgements +# Thank you to James Etchells with the European Space Agency (ESA) for +# performing some of the early work to determine how to use OpenTD with +# Python. ``` diff --git a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/connections-handles-markers-domains.md b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/connections-handles-markers-domains.md index 16421d59c3..fbb1f1f4cd 100644 --- a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/connections-handles-markers-domains.md +++ b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/connections-handles-markers-domains.md @@ -2,7 +2,7 @@ To connect objects in TD, you will use a Connection. A Connection contains a handle and a marker. As discussed in [Create nodes and a conductor](nodes-and-conductor.md) section, a handle is a string that TD uses to uniquely identify each object in a drawing. You have probably seen them listed in the Model Browser: -![Model Browser Example](../media/model-browser-example.png) +![Model Browser Example](../media/2f2bcdeb872649910f747dfa5b80c4fa.png) In addition to Connections, OpenTD uses handles to find objects when, for example, you call the Update() method on an object. Internally, OpenTD keeps track of which dwg contains the object, and finds it in the dwg using the Handle property of the object. diff --git a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/hello-world.md b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/hello-world.md index 9e803fbfb1..5eb5d98403 100644 --- a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/hello-world.md +++ b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/hello-world.md @@ -30,7 +30,7 @@ When you run the program, an instance of TD should open and a node should be cre Assuming it worked, let’s examine how. First, we created a `ThermalDesktop` object called `td`. This object represents one instance of TD. It has hundreds of methods for interacting with TD models. A single OpenTD client program can create an arbitrary number of ThermalDesktop instances, allowing you to manipulate several models and communicate between them. -Next, we called the `ThermalDesktop.Connect()` method. By default, this will start a new instance of TD using the latest version of AutoCAD installed. You can control how it works using the `ThermalDesktop*.ConnectConfig*` property ([Control how OpenTD connects to Thermal Desktop section](../extras.md#control-how-opentd-connects-to-thermal-desktop)). +Next, we called the `ThermalDesktop.Connect()` method. By default, this will start a new instance of TD using the latest version of AutoCAD installed. You can control how it works using the `ThermalDesktop.ConnectConfig` property ([Control how OpenTD connects to Thermal Desktop section](../extras.md#control-how-opentd-connects-to-thermal-desktop)). `Connect()`, like most ThermalDesktop commands, is called synchronously, so it will only return control to your program once it finishes. If there is a problem, it will throw an exception. All OpenTD methods throw exceptions if there is a problem; you do not need to check return values for success. diff --git a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/nodes-and-conductor.md b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/nodes-and-conductor.md index 43a490bf9d..9d09fe8bfe 100644 --- a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/nodes-and-conductor.md +++ b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/nodes-and-conductor.md @@ -32,12 +32,12 @@ namespace OpenTDv242GettingStarted How did this program work? After starting a new instance of TD, we created two `Node` objects, `n1` and `n2`, using the`CreateNode()` method. -When TD created each node, it set the `Node.*Handle*` property to a unique identifier, the same string you may have noticed in the TD Model Browser: +When TD created each node, it set the `Node.Handle` property to a unique identifier, the same string you may have noticed in the TD Model Browser: ![C:\\Users\\matt\\AppData\\Local\\Temp\\SNAGHTML29a2a79e.PNG](../media/2f2bcdeb872649910f747dfa5b80c4fa.png) Since TD allows duplicate SINDA names for some entities, OpenTD uses AutoCAD *handles* to identify most entities uniquely. (See the [Work with connections, handles, markers, and domains section](./connections-handles-markers-domains.md) for a detailed discussion of handles and related concepts.) -Next, we called the `*CreateConductor*` method. This method accepts two `*Connections*` representing the nodes connected to the conductor. Each Connection consists of a handle and a `*marker*`. As mentioned above, a handle is a unique identifier for a TD entity. A marker is an integer that determines how something is connected such as Top or XMAX. (See the [Work with connections, handles, markers, and domains](./connections-handles-markers-domains.md) section) +Next, we called the `CreateConductor` method. This method accepts two `Connections` representing the nodes connected to the conductor. Each Connection consists of a handle and a `marker`. As mentioned above, a handle is a unique identifier for a TD entity. A marker is an integer that determines how something is connected such as Top or XMAX. (See the [Work with connections, handles, markers, and domains](./connections-handles-markers-domains.md) section) When we called CreateConductor, we simply passed it our two nodes, n1 and n2. OpenTD knows how to implicitly create new Connections from Nodes by reading the `Node.Handle` property and assuming a default value for the`Connection.Marker` property, which is fine because node connections do not use markers. (See the [Execute TD COM commands](../extras.md#execute-td-com-commands) section for a discussion of implicit casting.) diff --git a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/units-symbols-expressions.md b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/units-symbols-expressions.md index 9ffcea7aa5..2bb87f2e52 100644 --- a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/units-symbols-expressions.md +++ b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/creating-td-model/units-symbols-expressions.md @@ -1,6 +1,6 @@ # Work with units, symbols, and expressions -OpenTD offers full support for units, symbols, and expressions. The most important concept to understand is that-except for a few exceptions discussed below–all dimensional values in OpenTD are expressed in the units defined in a thread static variable called `*Units.WorkingUnits*`, which is completely independent of the drawing units set in any connected TD instance. +OpenTD offers full support for units, symbols, and expressions. The most important concept to understand is that-except for a few exceptions discussed below–all dimensional values in OpenTD are expressed in the units defined in a thread static variable called `Units.WorkingUnits`, which is completely independent of the drawing units set in any connected TD instance. You can use expressions in OpenTD anywhere you can use them in the GUI. Look for members named "SomethingExp" to set the expression corresponding to the member "Something." Just like in the GUI, expressions have their own unit system, independent of the dwg units and the WorkingUnits. This is the main exception to the rule that all dimensional values in OpenTD are expressed in `Units.WorkingUnits`. The other exceptions are rare properties that must be entered in a specific unit, for example km for *PlanetParameters.radiusKm*. In all cases these will be indicated by the unit name in the name of the property. Any other exceptions will be class members with fixed units in their names. diff --git a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/interacting-with-end-users.md b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/interacting-with-end-users.md index 94923bbe17..fd779860eb 100644 --- a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/interacting-with-end-users.md +++ b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/interacting-with-end-users.md @@ -121,7 +121,7 @@ Loggers are created using the *LoggerFactory* class, usually as a static member ```c# private static readonly Logger log = -LoggerFactory.GetLogger(typeof(ThermalDesktop).ToString()); + LoggerFactory.GetLogger(typeof(ThermalDesktop).ToString()); ``` The LoggerFactory.*GetLogger* method accepts a string representing the name of the logger. This name will be used to route messages from the logger to files. Conventionally, this is the full name of the class that it is defined in, to make it obvious where messages originated. In the above line, we used “typeof(ThermalDesktop).ToString()” instead of the literal string “OpenTDv242.ThermalDesktop” to ensure that the name is correct with no typos. Did you notice the typo in that literal string? @@ -133,40 +133,40 @@ This is a recent configuration file installed with TD: ```lua - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + ``` -**Note**: Subject to change. You may find this file in the TD installation directory. If you’d like to use it, copy it to the `%localappdata%\\ThermalDesktop` directory. +**Note**: Subject to change. You may find this file in the TD installation directory. If you’d like to use it, copy it to the `%localappdata%\ThermalDesktop` directory. Two types of objects are defined in the configuration file: loggers and listeners. Loggers emit messages, while listeners route them to destinations. In each case, they only act on messages that are at or above the level they are defined at. @@ -180,7 +180,7 @@ This means that any logger in an OpenTD client program whose name starts with Op There is also a *RootLogger* defined. This is activated by any loggers whose names do not match the named loggers defined in the block. -There are three listeners defined, corresponding to three output files. Listener Log will write any-level messages to `%localappdata%\\ThermalDesktop\\log\\OpenTD.Client.log`, while listener ErrorLog will only write Error-level messages to `OpenTD.Client.Error.log`. And the OpenTDDemos listener will write any-level messages to `OpenTDv242Demos.log`. +There are three listeners defined, corresponding to three output files. Listener Log will write any-level messages to `%localappdata%\ThermalDesktop\log\OpenTD.Client.log`, while listener ErrorLog will only write Error-level messages to `OpenTD.Client.Error.log`. And the OpenTDDemos listener will write any-level messages to `OpenTDv242Demos.log`. Using the default configuration file, let’s look at some examples of how messages are routed to files. @@ -214,7 +214,7 @@ A logger in a client program is defined with the name “SatelliteBuilder.BusBui ```c# private static readonly Logger log3 = -LoggerFactory.GetLogger(“SatelliteBuilder.BusBuilder”); + LoggerFactory.GetLogger(“SatelliteBuilder.BusBuilder”); ``` It sends an Information-level message: @@ -235,5 +235,5 @@ Listener ErrorLog writes messages at Error-level only, so it does not write this - ThermalDesktop.*Print* prints a message to the AutoCAD console. - The User Coordinate System (UCS) can be queried or set using the ThermalDesktop.*UCS* property. - Model Browser visibility can be controlled using the ThermalDesktop.*ShowModelBrowser* and *HideModelBrowser* methods. -- Get a System.Windows.Forms.NativeWindow representing the main AutoCAD window using the ThermalDesktop.*GetMainWindow()* method. NativeWindow - mplements the IWin32Window interface, so this object can be used anywhere your application requires an IWin32Window that represents the main - utoCAD window. +- Get a System.Windows.Forms.NativeWindow representing the main AutoCAD window using the ThermalDesktop.*GetMainWindow()* method. NativeWindow implements the IWin32Window interface, so this object can be used anywhere your application requires an IWin32Window that represents the main AutoCAD window. diff --git a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/modifying-td-models.md b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/modifying-td-models.md index bdf5d6d0a7..a1d16ba547 100644 --- a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/modifying-td-models.md +++ b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/modifying-td-models.md @@ -1,26 +1,26 @@ # Modifying TD models -So far, you have seen how to create new entities in TD, but OpenTD can also be used to query existing models and modify their contents. For most entity types, there is a ThermalDesktop method to get all items of that type in the model, and a method to get a specific item. For example, *GetNodes()* returns a list of all Nodes, and *GetNode(string handle)* returns a specific node if you know its AutoCAD handle. (See the [Work with connections, handles, markers, and domains section](creating-td-model/connections-handles-markers-domains.md)) It is often convenient to use the *LINQ Single* or *Where* methods to search a returned list of entities to find the items that meet some criteria. For example, to find all the arithmetic nodes on layer “sheet”, you could do something like this: +So far, you have seen how to create new entities in TD, but OpenTD can also be used to query existing models and modify their contents. For most entity types, there is a ThermalDesktop method to get all items of that type in the model, and a method to get a specific item. For example, *GetNodes()* returns a list of all Nodes, and *GetNode(string handle)* returns a specific node if you know its AutoCAD handle. (See the [Work with connections, handles, markers, and domains](creating-td-model/connections-handles-markers-domains.md) section) It is often convenient to use the *LINQ Single* or *Where* methods to search a returned list of entities to find the items that meet some criteria. For example, to find all the arithmetic nodes on layer “sheet”, you could do something like this: ```c# var arithmeticNodes = td.GetNodes().Where -(x => x.NodeType == RcNodeData.NodeTypes.ARITHMETIC -&& x.Layer == “sheet”); + (x => x.NodeType == RcNodeData.NodeTypes.ARITHMETIC + && x.Layer == “sheet”); ``` -The variable `arithmeticNodes` would now be an `*IEnumerable*` containing all of the arithmetic nodes on layer “sheet”. +The variable `arithmeticNodes` would now be an `IEnumerable` containing all of the arithmetic nodes on layer “sheet”. **Note**: You can use foreach to iterate over the elements of an `IEnumerable`, just like a List. Or you can convert the `IEnumerable` to a List using the `ToList()` method. -Another useful LINQ technique is to use the `*Select*` method to extract a related list from an input list. For example, the following line creates an `IEnumerable` containing the handles of all of the nodes returned by `GetNodes()`: +Another useful LINQ technique is to use the `Select` method to extract a related list from an input list. For example, the following line creates an `IEnumerable` containing the handles of all of the nodes returned by `GetNodes()`: ```c# var nodeHandles = td.GetNodes().Select(x => x.Handle); ``` -To delete any item with an AutoCAD handle, use the `*ThermalDesktop.DeleteEntity*` method. For items without handles, there are specialized delete methods such as `ThermalDesktop.DeleteSymbol*`, which accepts the name of the symbol to delete. +To delete any item with an AutoCAD handle, use the `ThermalDesktop.DeleteEntity` method. For items without handles, there are specialized delete methods such as `ThermalDesktop.DeleteSymbol`, which accepts the name of the symbol to delete. -The following examples demonstrate querying, modifying and deleting entities in a model. +The following examples demonstrate querying, modifying, and deleting entities in a model. ## Query and edit a model diff --git a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/reading-results.md b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/reading-results.md index 89ccf4493a..870f413f52 100644 --- a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/reading-results.md +++ b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/reading-results.md @@ -13,7 +13,7 @@ The classes for working directly with save files, CSR’s or other solution resu ### Before using OpenTDv242.Results -To use OpenTD to explore results directly (rather than via an instance of TD), you will need to add a reference to the OpenTDv242.esults.dll assembly. You can find it in the GAC in the 64-bit directory. (Try looking under C:\\Windows\\Microsoft.ET\\assembly\\GAC_64\\OpenTDv242.Results.) You will also probably need to add a reference to OpenTDv242.dll, as usual. [See the Hello World](creating-td-model/hello-world.md) +To use OpenTD to explore results directly (rather than via an instance of TD), you will need to add a reference to the OpenTDv242.Results.dll assembly. You can find it in the GAC in the 64-bit directory. (Try looking under C:\\Windows\\Microsoft.ET\\assembly\\GAC_64\\OpenTDv242.Results.) You will also probably need to add a reference to OpenTDv242.dll, as usual. [See the Hello World](creating-td-model/hello-world.md) Since OpenTDv242.Results is a 64-bit assembly, your project will also have to be 64-bit. In Visual Studio, use the Configuration manager to create a 64-bit solution and a 64-bit project. When set up correctly, your Configuration Manager dialog should look something like this: ![Configuration Manager dialog](media/19913b5a9a51f4926a07426227c010fa.png) @@ -22,7 +22,9 @@ Since OpenTDv242.Results is a 64-bit assembly, your project will also have to be OpenTD offers powerful tools for manipulating solution results, but it is a lot to learn all at once. This section shows how to imply get some data out of a save file or CSR. First, reference the OpenTDv242.Results dll as discussed above. Next, add a using statement for convenience: +```c# using OpenTDv242.Results.Dataset; +``` Now you can connect to a save file: @@ -68,7 +70,7 @@ You can construct an array of strings to pass to GetData. For example, to get te ```c# string[] someNames = new string[100]; for (int i = 0; i < 100; ++i) -someNames[i] = "MAIN.T" + (i + 1); + someNames[i] = "MAIN.T" + (i + 1); var someTs = myData.GetData(someNames).GetValues(Units.SI); ``` @@ -84,7 +86,7 @@ var times = myData.GetTimes().GetValues(); This returns a list of times in the current WorkingUnits. -### Advanced Results Manipulation and XY Plots +### Advanced results manipulation and XY plots The previous section showed how to easily get data out of save files or CSR’s. In this and the following sections we will show how to manipulate that data, work with groups and multiple datasets, combine data in arbitrarily complex ways, and create simple XY plots. @@ -137,7 +139,7 @@ Compared to previous methods for extracting and plotting SINDA/FLUINT data, Open In this program, we will make use of the “torchNom.sav” and “torchCold.sav” files created in the [Create and run a case](working-with-case-sets.md#create-and-run-a-case) section, so please run that program and locate the two save files. -Once Visual Studio is set up with a 64-bit solution and project ( Section [Before using OpenTDv242.Results](#before-using-opentdv242results)), and you have added references to OpenTDv242.dll and OpenTDv242.Results.dll, you will be ready to try the following program. +Once Visual Studio is set up with a 64-bit solution and project ([Before using OpenTDv242.Results](#before-using-opentdv242results) section), and you have added references to OpenTDv242.dll and OpenTDv242.Results.dll, you will be ready to try the following program. ```c# using System; @@ -460,11 +462,11 @@ namespace OpenTDv242GettingStarted As shown in the preceding sections, the DataSubtype class is used to describe types of data found in solution results such as “node temperature T” or “lump pressure PL”. There are several methods that require a DataSubtype as a parameter. When using those methods, you can create your own DataSubtype, but it is usually easier to allow OpenTD to do it for you by making use of the StandardDataSubtypes enum and/or the FullStandardDataSubtype struct. -Through the magic of implicit casting (See the [Execute TD COM commands section](extras.md#execute-td-com-commands)) any method that accepts a DataSubtype will accept either a StandardDataSubtypes or FullStandardDataSubtype instead. For example, one of the GetData overloads has the following signature: +Through the magic of implicit casting (See the [Execute TD COM commands](extras.md#execute-td-com-commands) section) any method that accepts a DataSubtype will accept either a StandardDataSubtypes or FullStandardDataSubtype instead. For example, one of the GetData overloads has the following signature: ```c# DataArrayCollection GetData( -ItemIdentifierCollection itemIds, DataSubtype subtype, UnitsData units = null) + ItemIdentifierCollection itemIds, DataSubtype subtype, UnitsData units = null) ``` It expects a list of entity names (the ItemIdentifierCollection), the type of data to get (the DataSubtype), and you can optionally specify the units for any registers in the ItemIdentifierCollection. To get node temperatures for all the nodes in the “PANEL” domain from TD instance “td”, you could do this: @@ -539,9 +541,9 @@ You may notice that each of the conductors is listed twice, once from node A to Model topology along with solution results can be used to determine heat rates between groups of entities. This is done using an *IBrowser*. -The following program uses the solution results from section [Create and run a case](working-with-case-sets.md#create-and-run-a-case) . Make sure to run that program first before trying this one. As you may recall, that program creates a model of a bar heated on one end, convecting to a room along its length. We will be using results from a transient case, starting with a cold bar. +The following program uses the solution results from the [Create and run a case](working-with-case-sets.md#create-and-run-a-case) section. Make sure to run that program first before trying this one. As you may recall, that program creates a model of a bar heated on one end, convecting to a room along its length. We will be using results from a transient case, starting with a cold bar. -We will create two IBrowsers, one early in the solution and one at the final record, using them to find the total heat rate from the bar to the room at the two times. We will also use a SumDataArray (section [Advanced results manipulation and XY plots](#advanced-results-manipulation-and-xy-plots)) to plot the constant total external heat into the bar over the whole solution. We expect the heat rate from the bar to the room to approach the external heat rate as the system approaches steady-state. +We will create two IBrowsers, one early in the solution and one at the final record, using them to find the total heat rate from the bar to the room at the two times. We will also use a SumDataArray ([Advanced results manipulation and XY plots](#advanced-results-manipulation-and-xy-plots) section) to plot the constant total external heat into the bar over the whole solution. We expect the heat rate from the bar to the room to approach the external heat rate as the system approaches steady-state. ```c# using System; diff --git a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/working-with-case-sets.md b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/working-with-case-sets.md index 5deeff6209..1f963cac2b 100644 --- a/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/working-with-case-sets.md +++ b/2024R2/thermal-desktop-opentd-24-r2/articles/getting-started/working-with-case-sets.md @@ -100,7 +100,7 @@ namespace OpenTDv242GettingStarted } ``` -Solution files, including “torchNom.sav” and “torchCold.sav”, will be written to the working directory, which we created and then set with ThermalDesktop*.ConnectConfig.StartDirectory*. (See the [Control how OpenTD connects to Thermal Desktop](extras.md#control-how-opentd-connects-to-thermal-desktop) section for more information about controlling how OpenTD connects to TD.) Otherwise, the working directory would have probably been the directory containing your exe. You can also use the ThermalDesktop.*SaveAs* method before running to save the dwg and set the working directory. +Solution files, including “torchNom.sav” and “torchCold.sav”, will be written to the working directory, which we created and then set with ThermalDesktop.*ConnectConfig.StartDirectory*. (See the [Control how OpenTD connects to Thermal Desktop](extras.md#control-how-opentd-connects-to-thermal-desktop) section for more information about controlling how OpenTD connects to TD.) Otherwise, the working directory would have probably been the directory containing your exe. You can also use the ThermalDesktop.*SaveAs* method before running to save the dwg and set the working directory. ## Create an orbit and apply it to a case set @@ -151,7 +151,7 @@ namespace OpenTDv242GettingStarted When you call CaseSet.Run(), it is the same as selecting and running a single case in the GUI. If you would like to select multiple cases and run, either in Demand or Batch mode, you can use ThermalDesktop.*CaseSetManager*. It provides all the functionality of the Case Set Manager, including the ability to adjust Manager-level options, using the CaseSetManager.*Options* member. -To run multiple cases – just like selecting them all in the GUI and running – use the following CaseSetManager.Run overload: +To run multiple cases–just like selecting them all in the GUI and running–use the following CaseSetManager.Run overload: ```c# void Run(IEnumerable caseIndices) diff --git a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/appendix-A-using-opentd-with-MATLAB.md b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/appendix-A-using-opentd-with-MATLAB.md index 31052b8d07..43a9c3377b 100644 --- a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/appendix-A-using-opentd-with-MATLAB.md +++ b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/appendix-A-using-opentd-with-MATLAB.md @@ -1,125 +1,144 @@ # Appendix A: Using OpenTD with MATLAB -While it is not feasible for us to maintain separate "Getting Started with OpenTD" guides for every programming language, we would still like to help you get started with OpenTD, even if you are not using C\#. The following .m script is a MATLAB port of the program in the [Create and run a case](working-with-case-sets.md#create-and-run-a-case) section. This can be used as a sort of "Rosetta Stone" to help you translate other C\# examples to MATLAB. +While it is not feasible for us to maintain separate "Getting Started with OpenTD" guides for every programming language, we would still like to help you get started with OpenTD, even if you are not using C#. The following .m script is a MATLAB port of the program in the [Create and run a case](working-with-case-sets.md#create-and-run-a-case) section. This can be used as a sort of "Rosetta Stone" to help you translate other C# examples to MATLAB. ```MATLAB %% Using OpenTD with MATLAB % CRTech % Tested with MATLAB R2023b + % OpenTD is an Application Programming Interface (API) for Thermal Desktop % (TD) that allows you to automate many of the tasks currently performed % interactively using TD’s Graphical User Interface (GUI). OpenTD gives you % the tools to programmatically create, query, edit, delete, and run -% models. You can use any .NET language to interact with OpenTD (C\#, +% models. You can use any .NET language to interact with OpenTD (C#, % VB.NET, F\#, etc.) or any system that can load .NET assemblies such as % MATLAB or Python. + % Regardless of how you interact with OpenTD, you’ll need to have at least % an intermediate understanding of .NET object-oriented programming. If you -% are starting from scratch, we recommend learning C\#, since it is the +% are starting from scratch, we recommend learning C#, since it is the % language that we support. However, we understand that there might be % compelling reasons for you to connect to OpenTD via MATLAB. It is % possible, although the way MATLAB handles .NET enums is awkward and % MATLAB does not support implicit constructors. + % To get started with OpenTD, read "Getting Started with OpenTD.pdf", % which can be found in your TD v241 installation directory under "Manual". % The Getting Started guide explains the fundamental concepts of OpenTD, -% using several C\# examples. We've ported one of those examples to MATLAB +% using several C# examples. We've ported one of those examples to MATLAB % below. + %% The "Create and Run a Case" example ported to MATLAB % See "Getting Started with OpenTD.pdf" in your TD v241 installation % directory under "Manual" for an explanation of this script. + % Note: Please contact us at crtech.support@ansys.com if you think there are % better ways to use OpenTD with MATLAB, especially with regard to .NET % enums and implicit constructors. For examples of awkward code, see how a % node is set to be a boundary node and how the InitialTemp of a node is -% set -- in the script below vs. in the original C\#. +% set -- in the script below vs. in the original C#. + openTD = NET.addAssembly('OpenTD'); -import OpenTD.\*; +import OpenTD.*; td = ThermalDesktop; td.Connect(); -% \*\*\* Create a simple model of a heated bar \*\*\* + +% *** Create a simple model of a heated bar *** barNodes = NET.createArray('OpenTD.Node', 10); for i = 1:10 -n = td.CreateNode(); -n.Submodel = SubmodelNameData('bar'); -n.Id = i; -n.MassVol = 10; -n.Origin = Point3d(0.01 \* (i - 1), 1, 0); -n.InitialTemp = Dimensional(n.InitialTemp, 300); -n.Update(); -barNodes(i) = n; + n = td.CreateNode(); + n.Submodel = SubmodelNameData('bar'); + n.Id = i; + n.MassVol = 10; + n.Origin = Point3d(0.01 * (i - 1), 1, 0); + n.InitialTemp = Dimensional(n.InitialTemp, 300); + n.Update(); + barNodes(i) = n; end for i = 1:9 -c = td.CreateConductor(... -Connection(barNodes(i).Handle), Connection(barNodes(i+1).Handle)); -c.Submodel = SubmodelNameData('bar'); -c.Value = 0.1; -c.Update(); + c = td.CreateConductor(... + Connection(barNodes(i).Handle), Connection(barNodes(i+1).Handle)); + c.Submodel = SubmodelNameData('bar'); + c.Value = 0.1; + c.Update(); end + roomAir = td.CreateNode(); roomAir.Submodel = SubmodelNameData('room'); roomAir.NodeType = OpenTD.('RcNodeData+NodeTypes').BOUNDARY; roomAir.Origin = Point3d(0.055, 1.1, 0); roomAir.InitialTemp = Dimensional(roomAir.InitialTemp, 300); roomAir.Update(); + barConnections = NET.createGeneric(... -'System.Collections.Generic.List', {'OpenTD.Connection'},10); + 'System.Collections.Generic.List', {'OpenTD.Connection'},10); for i = 1:10 -barConnections.Add(Connection(barNodes(i).Handle)); + barConnections.Add(Connection(barNodes(i).Handle)); end convection = td.CreateConductor(... -Connection(roomAir.Handle), barConnections); + Connection(roomAir.Handle), barConnections); convection.Value = 1; convection.Submodel = SubmodelNameData('room'); convection.Update(); + qTorch = td.CreateSymbol('qTorch', '80'); heatLoadConnections = NET.createGeneric(... -'System.Collections.Generic.List', {'OpenTD.Connection'},1); + 'System.Collections.Generic.List', {'OpenTD.Connection'},1); heatLoadConnections.Add(Connection(barNodes(1).Handle)); torch = td.CreateHeatLoad(heatLoadConnections); torch.ValueExp.Value = qTorch.Name; torch.Submodel = SubmodelNameData('torch'); torch.Update(); + td.ZoomExtents(); -% \*\*\* End simple model creation \*\*\* +% *** End simple model creation *** + % Create a transient case and run it: nominal = td.CreateCaseSet(... -'transient with nominal torch', '', 'torchNom'); + 'transient with nominal torch', '', 'torchNom'); nominal.SteadyState = 0; nominal.Transient = 1; nominal.SindaControl.timend... -= Dimensional(nominal.SindaControl.timend, 600); + = Dimensional(nominal.SindaControl.timend, 600); nominal.Update(); nominal.Run(); + % Create a cold case by overriding a symbol, and run it: cold = td.CreateCaseSet(... -'transient with cold torch', '', 'torchCold'); + 'transient with cold torch', '', 'torchCold'); cold.SteadyState = 0; cold.Transient = 1; cold.SindaControl.timend... -= Dimensional(nominal.SindaControl.timend, 1200); + = Dimensional(nominal.SindaControl.timend, 1200); cold.SymbolNames.Add(qTorch.Name); cold.SymbolValues.Add('50'); cold.SymbolComments.Add('cold torch heat input'); cold.SaveAll = 1; cold.Update(); cold.Run(); + %% Working with Dimensionals + % All dimensional quanitities in the API are stored using a custom .NET % generic type called a Dimensional. For example, a Dimensional -% stores temperatures. Using C\#, Dimensionals are implicitly cast to and +% stores temperatures. Using C#, Dimensionals are implicitly cast to and % from doubles as required, but this does not appear to work in MATLAB. % Instead, we've overloaded the double function and created a Dimensional % function to explicitly cast doubles to Dimensionals. + function x = double(Dimensional) % Cast a .NET generic Dimensional type to a double -x = Dimensional.op_Implicit(Dimensional); + x = Dimensional.op_Implicit(Dimensional); end + function x = Dimensional(Dimensional, double) % Cast a double to a .NET generic Dimensional type -x = Dimensional.op_Implicit(double); + x = Dimensional.op_Implicit(double); end + %% Acknowledgements + % Thank you to Dan Hensley and Daniel Reasa with ATA Engineering for % performing some of the early work to determine how to use OpenTD with % MATLAB. diff --git a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/appendix-B-using-opentd-with-python.md b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/appendix-B-using-opentd-with-python.md index 18665318c8..db150505de 100644 --- a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/appendix-B-using-opentd-with-python.md +++ b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/appendix-B-using-opentd-with-python.md @@ -1,63 +1,76 @@ # Appendix B: Using OpenTD with Python -While it is not feasible for us to maintain separate "Getting Started with OpenTD" guides for every programming language, we would still like to help you get started with OpenTD, even if you are not using C\#. The following .py script is a MATLAB port of the program in the [Create and run a case](working-with-case-sets.md#create-and-run-a-case) section. This can be used as a sort of "Rosetta Stone" to help you translate other C\# examples to Python. It uses the pythonnet module, found at: [http://pythonnet.github.io/](http://pythonnet.github.io/). +While it is not feasible for us to maintain separate "Getting Started with OpenTD" guides for every programming language, we would still like to help you get started with OpenTD, even if you are not using C#. The following .py script is a MATLAB port of the program in the [Create and run a case](working-with-case-sets.md#create-and-run-a-case) section. This can be used as a sort of "Rosetta Stone" to help you translate other C# examples to Python. It uses the pythonnet module, found at: [http://pythonnet.github.io/](http://pythonnet.github.io/). ```python -\#\#\#\# Using OpenTD with Python \#\#\#\# -\# CRTech -\# Feb, 2022 -\# Created with Python 2.7.15 and pythonnet 2.3.0 -\# OpenTD is an Application Programming Interface (API) for Thermal Desktop -\# (TD) that allows you to automate many of the tasks currently performed -\# interactively using TD's Graphical User Interface (GUI). OpenTD gives you -\# the tools to programmatically create, query, edit, delete, and run -\# models. You can use any .NET language to interact with OpenTD (C\#, -\# VB.NET, F\#, etc.) or any system that can load .NET assemblies such as -\# MATLAB or Python. -\# Regardless of how you interact with OpenTD, you'll need to have at least -\# an intermediate understanding of .NET object-oriented programming. If you -\# are starting from scratch, we recommend learning C\#, since it is the -\# language that we support. However, we understand that there might be -\# compelling reasons for you to connect to OpenTD via Python. It is -\# possible using the pythonnet module: -\# http://pythonnet.github.io/ -\# To get started with OpenTD, read "Getting Started with OpenTD.pdf", -\# which can be found in your TD v241 installation directory under "Manual". -\# The Getting Started guide explains the fundamental concepts of OpenTD, -\# using several C\# examples. We've ported one of those examples to Python -\# below. -\#\#\#\# The "Create and Run a Case" example ported to Python \#\#\#\# -\# See "Getting Started with OpenTD.pdf" in your TD v241 installation -\# directory under "Manual" for an explanation of this script. -\# Note: Please contact us at crtech.support@ansys.com if you think there are -\# better ways to use OpenTD with Python, especially with regard to setting -\# dimensional values. -\# REQUIREMENT: You must install the pythonnet module to use this script. +#### Using OpenTD with Python #### +# CRTech +# Feb, 2022 +# Created with Python 2.7.15 and pythonnet 2.3.0 + +# OpenTD is an Application Programming Interface (API) for Thermal Desktop +# (TD) that allows you to automate many of the tasks currently performed +# interactively using TD's Graphical User Interface (GUI). OpenTD gives you +# the tools to programmatically create, query, edit, delete, and run +# models. You can use any .NET language to interact with OpenTD (C#, +# VB.NET, F#, etc.) or any system that can load .NET assemblies such as +# MATLAB or Python. + +# Regardless of how you interact with OpenTD, you'll need to have at least +# an intermediate understanding of .NET object-oriented programming. If you +# are starting from scratch, we recommend learning C#, since it is the +# language that we support. However, we understand that there might be +# compelling reasons for you to connect to OpenTD via Python. It is +# possible using the pythonnet module: + +# http://pythonnet.github.io/ + +# To get started with OpenTD, read "Getting Started with OpenTD.pdf", +# which can be found in your TD v241 installation directory under "Manual". +# The Getting Started guide explains the fundamental concepts of OpenTD, +# using several C# examples. We've ported one of those examples to Python +# below. + +#### The "Create and Run a Case" example ported to Python #### +# See "Getting Started with OpenTD.pdf" in your TD v241 installation +# directory under "Manual" for an explanation of this script. + +# Note: Please contact us at crtech.support@ansys.com if you think there are +# better ways to use OpenTD with Python, especially with regard to setting +# dimensional values. + +# REQUIREMENT: You must install the pythonnet module to use this script. + import sys import clr -\# Need to add explicit GAC path to sys.path so clr.AddReference -\# can find OpenTD.dll. Note the use of forward slashes in the path: + +# Need to add explicit GAC path to sys.path so clr.AddReference +# can find OpenTD.dll. Note the use of forward slashes in the path: sys.path.append("C:/Windows/Microsoft.NET/assembly/GAC_MSIL/OpenTD/ReplaceMe") clr.AddReference("OpenTD") -from OpenTD import \* -\# We'll want to use .NET System types and generic Lists: -from System import \* +from OpenTD import * + +# We'll want to use .NET System types and generic Lists: +from System import * from System.Collections.Generic import List -\# To access dimensional quantities in OpenTD, we need to use Dimensionals. -\# These are cast to/from doubles implicitly in C\#, but here we'll need to -\# refer to them explicitly. (See setting InitialTemp, below.) + +# To access dimensional quantities in OpenTD, we need to use Dimensionals. +# These are cast to/from doubles implicitly in C#, but here we'll need to +# refer to them explicitly. (See setting InitialTemp, below.) from OpenTD import Dimension -from OpenTD.Dimension import \* +from OpenTD.Dimension import * + td = ThermalDesktop() td.Connect() -\# \*\*\* Create a simple model of a heated bar \*\*\* + +# *** Create a simple model of a heated bar *** barNodes = List[Node]() for i in range(10): n = td.CreateNode() n.Submodel = SubmodelNameData("bar") n.Id = i + 1 n.MassVol = 10.0 - n.Origin = Point3d(0.01 \* i, 1.0, 0.0) + n.Origin = Point3d(0.01 * i, 1.0, 0.0) n.InitialTemp = Dimensional[Dimension.Temp](300.0) n.Update() barNodes.Add(n) @@ -66,12 +79,14 @@ for i in range(9): c.Submodel = SubmodelNameData("bar") c.Value = 0.1 c.Update() + roomAir = td.CreateNode() roomAir.Submodel = SubmodelNameData('room') roomAir.NodeType = RcNodeData.NodeTypes.BOUNDARY roomAir.Origin = Point3d(0.055, 1.1, 0.0) roomAir.InitialTemp = Dimensional[Dimension.Temp](300.0) roomAir.Update() + barConnections = List[Connection]() for n in barNodes: barConnections.Add(Connection(n)) @@ -79,6 +94,7 @@ convection = td.CreateConductor(Connection(roomAir), barConnections) convection.Value = 1.0 convection.Submodel = SubmodelNameData("room") convection.Update() + qTorch = td.CreateSymbol("qTorch", "80") heatLoadConnections = List[Connection]() heatLoadConnections.Add(Connection(barNodes[0])) @@ -86,16 +102,19 @@ torch = td.CreateHeatLoad(heatLoadConnections) torch.ValueExp.Value = qTorch.Name torch.Submodel = SubmodelNameData("torch") torch.Update() + td.ZoomExtents() -\# \*\*\* End simple model creation \*\*\* -\# Create a transient case and run it: +# *** End simple model creation *** + +# Create a transient case and run it: nominal = td.CreateCaseSet("transient with nominal torch", "", "torchNom") nominal.SteadyState = 0 nominal.Transient = 1 nominal.SindaControl.timend = Dimensional[Dimension.Time](600.0) nominal.Update() nominal.Run() -\# Create a cold case by overriding a symbol, and run it: + +# Create a cold case by overriding a symbol, and run it: cold = td.CreateCaseSet("transient with cold torch", "", "torchCold") cold.SteadyState = 0 cold.Transient = 1 @@ -103,12 +122,13 @@ cold.SindaControl.timend = Dimensional[Dimension.Time](1200.0) cold.SaveQ = 1 cold.SymbolNames.Add(qTorch.Name) cold.SymbolValues.Add("50") -cold.SymbolComments.Add("cold torch heat input"); -cold.SaveAll = 1; +cold.SymbolComments.Add("cold torch heat input") +cold.SaveAll = 1 cold.Update() cold.Run() -\#\#\#\# Acknowledgements -\# Thank you to James Etchells with the European Space Agency (ESA) for -\# performing some of the early work to determine how to use OpenTD with -\# Python. + +#### Acknowledgements +# Thank you to James Etchells with the European Space Agency (ESA) for +# performing some of the early work to determine how to use OpenTD with +# Python. ``` diff --git a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/connections-handles-markers-domains.md b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/connections-handles-markers-domains.md index 50cbffff85..ddce507612 100644 --- a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/connections-handles-markers-domains.md +++ b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/connections-handles-markers-domains.md @@ -2,7 +2,7 @@ To connect objects in TD, you will use a Connection. A Connection contains a handle and a marker. As discussed in [Create nodes and a conductor](nodes-and-conductor.md) section, a handle is a string that TD uses to uniquely identify each object in a drawing. You have probably seen them listed in the Model Browser: -![Model Browser Example](../media/model-browser-example.png) +![Model Browser Example](../media/2f2bcdeb872649910f747dfa5b80c4fa.png) In addition to Connections, OpenTD uses handles to find objects when, for example, you call the Update() method on an object. Internally, OpenTD keeps track of which dwg contains the object, and finds it in the dwg using the Handle property of the object. diff --git a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/hello-world.md b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/hello-world.md index c76eb2965b..bb497bd361 100644 --- a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/hello-world.md +++ b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/hello-world.md @@ -1,6 +1,6 @@ # Hello World (Start TD and create a node) -Let’s create a simple OpenTD program. Start by creating a `C\#` console application in Visual Studio. Look for the template called “Console App (.NET Framework)”, not “.NET Core” or “.NET Standard”. It should look something like this: +Let’s create a simple OpenTD program. Start by creating a `C#` console application in Visual Studio. Look for the template called “Console App (.NET Framework)”, not “.NET Core” or “.NET Standard”. It should look something like this: ![A screenshot of a computer screen Description automatically generated with low confidence](../media/d47e44c0a654c0607631af3cacc32f6a.png) @@ -28,12 +28,12 @@ namespace OpenTDGettingStarted When you run the program, an instance of TD should open and a node should be created at (0, 0, 0). When you edit the node, the comment should be “Hello World!”. If any of these things are not true, check the [Troubleshooting](../troubleshooting.md) section at the end of this guide. -Assuming it worked, let’s examine how. First, we created a `_ThermalDesktop_` object called `td`. This object represents one instance of TD. It has hundreds of methods for interacting with TD models. A single OpenTD client program can create an arbitrary number of ThermalDesktop instances, allowing you to manipulate several models and communicate between them. +Assuming it worked, let’s examine how. First, we created a `ThermalDesktop` object called `td`. This object represents one instance of TD. It has hundreds of methods for interacting with TD models. A single OpenTD client program can create an arbitrary number of ThermalDesktop instances, allowing you to manipulate several models and communicate between them. -Next, we called the `ThermalDesktop._Connect()_` method. By default, this will start a new instance of TD using the latest version of AutoCAD installed. You can control how it works using the `ThermalDesktop*.ConnectConfig*` property ([Control how OpenTD connects to Thermal Desktop section](../extras.md#control-how-opentd-connects-to-thermal-desktop)). +Next, we called the `ThermalDesktop.Connect()` method. By default, this will start a new instance of TD using the latest version of AutoCAD installed. You can control how it works using the `ThermalDesktop.ConnectConfig` property ([Control how OpenTD connects to Thermal Desktop section](../extras.md#control-how-opentd-connects-to-thermal-desktop)). `Connect()`, like most ThermalDesktop commands, is called synchronously, so it will only return control to your program once it finishes. If there is a problem, it will throw an exception. All OpenTD methods throw exceptions if there is a problem; you do not need to check return values for success. -Once `Connect()` returned, we called `ThermalDesktop._CreateNode()_` to create a node in TD with default settings. We put the return value in a variable called n. This variable is of type `_Node_` and represents the TD node in our client program. +Once `Connect()` returned, we called `ThermalDesktop.CreateNode()` to create a node in TD with default settings. We put the return value in a variable called n. This variable is of type `Node` and represents the TD node in our client program. -Next, we updated the `_Comment_` member of n. This only updated the comment for the client-program Node. To send that update to TD, we called the `Node._Update()_` method. This is an important concept to understand; when you work with objects in your client program that represent objects in TD, they do not automatically propagate their changes to TD. To do that, you need to call the `Update()` method. (Some objects also have`_UpdateFromTD()_` methods to get the latest changes from TD.) +Next, we updated the `Comment` member of n. This only updated the comment for the client-program Node. To send that update to TD, we called the `Node.Update()` method. This is an important concept to understand; when you work with objects in your client program that represent objects in TD, they do not automatically propagate their changes to TD. To do that, you need to call the `Update()` method. (Some objects also have`UpdateFromTD()` methods to get the latest changes from TD.) diff --git a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/nodes-and-conductor.md b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/nodes-and-conductor.md index a0c74a69bd..79ec14bca5 100644 --- a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/nodes-and-conductor.md +++ b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/nodes-and-conductor.md @@ -1,6 +1,6 @@ # Create nodes and a conductor -This program demonstrates how to create two nodes and connect them with a conductor. To try it, create a .NET Framework C\# console application that references OpenTD, add the following code, then compile and run it. +This program demonstrates how to create two nodes and connect them with a conductor. To try it, create a .NET Framework C# console application that references OpenTD, add the following code, then compile and run it. ```c# using OpenTD; @@ -32,12 +32,12 @@ namespace OpenTDGettingStarted How did this program work? After starting a new instance of TD, we created two `Node` objects, `n1` and `n2`, using the`CreateNode()` method. -When TD created each node, it set the `Node.*Handle*` property to a unique identifier, the same string you may have noticed in the TD Model Browser: +When TD created each node, it set the `Node.Handle` property to a unique identifier, the same string you may have noticed in the TD Model Browser: ![C:\\Users\\matt\\AppData\\Local\\Temp\\SNAGHTML29a2a79e.PNG](../media/2f2bcdeb872649910f747dfa5b80c4fa.png) Since TD allows duplicate SINDA names for some entities, OpenTD uses AutoCAD *handles* to identify most entities uniquely. (See the [Work with connections, handles, markers, and domains section](./connections-handles-markers-domains.md) for a detailed discussion of handles and related concepts.) -Next, we called the `*CreateConductor*` method. This method accepts two `*Connections*` representing the nodes connected to the conductor. Each Connection consists of a handle and a `*marker*`. As mentioned above, a handle is a unique identifier for a TD entity. A marker is an integer that determines how something is connected such as Top or XMAX. (See the [Work with connections, handles, markers, and domains](./connections-handles-markers-domains.md) section) +Next, we called the `CreateConductor` method. This method accepts two `Connections` representing the nodes connected to the conductor. Each Connection consists of a handle and a `marker`. As mentioned above, a handle is a unique identifier for a TD entity. A marker is an integer that determines how something is connected such as Top or XMAX. (See the [Work with connections, handles, markers, and domains](./connections-handles-markers-domains.md) section) When we called CreateConductor, we simply passed it our two nodes, n1 and n2. OpenTD knows how to implicitly create new Connections from Nodes by reading the `Node.Handle` property and assuming a default value for the`Connection.Marker` property, which is fine because node connections do not use markers. (See the [Execute TD COM commands](../extras.md#execute-td-com-commands) section for a discussion of implicit casting.) diff --git a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/units-symbols-expressions.md b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/units-symbols-expressions.md index 8cf185f0cf..b130b1c0cc 100644 --- a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/units-symbols-expressions.md +++ b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/creating-td-model/units-symbols-expressions.md @@ -1,6 +1,6 @@ # Work with units, symbols, and expressions -OpenTD offers full support for units, symbols, and expressions. The most important concept to understand is that-except for a few exceptions discussed below–all dimensional values in OpenTD are expressed in the units defined in a thread static variable called `*Units.WorkingUnits*`, which is completely independent of the drawing units set in any connected TD instance. +OpenTD offers full support for units, symbols, and expressions. The most important concept to understand is that-except for a few exceptions discussed below–all dimensional values in OpenTD are expressed in the units defined in a thread static variable called `Units.WorkingUnits`, which is completely independent of the drawing units set in any connected TD instance. You can use expressions in OpenTD anywhere you can use them in the GUI. Look for members named "SomethingExp" to set the expression corresponding to the member "Something." Just like in the GUI, expressions have their own unit system, independent of the dwg units and the WorkingUnits. This is the main exception to the rule that all dimensional values in OpenTD are expressed in `Units.WorkingUnits`. The other exceptions are rare properties that must be entered in a specific unit, for example km for *PlanetParameters.radiusKm*. In all cases these will be indicated by the unit name in the name of the property. Any other exceptions will be class members with fixed units in their names. diff --git a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/interacting-with-end-users.md b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/interacting-with-end-users.md index 96e1f42b7a..a98d98c2bc 100644 --- a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/interacting-with-end-users.md +++ b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/interacting-with-end-users.md @@ -121,7 +121,7 @@ Loggers are created using the *LoggerFactory* class, usually as a static member ```c# private static readonly Logger log = -LoggerFactory.GetLogger(typeof(ThermalDesktop).ToString()); + LoggerFactory.GetLogger(typeof(ThermalDesktop).ToString()); ``` The LoggerFactory.*GetLogger* method accepts a string representing the name of the logger. This name will be used to route messages from the logger to files. Conventionally, this is the full name of the class that it is defined in, to make it obvious where messages originated. In the above line, we used “typeof(ThermalDesktop).ToString()” instead of the literal string “OpenTD.ThermalDesktop” to ensure that the name is correct with no typos. Did you notice the typo in that literal string? @@ -133,40 +133,40 @@ This is a recent configuration file installed with TD: ```lua - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + ``` -**Note**: Subject to change. You may find this file in the TD installation directory. If you’d like to use it, copy it to the `%localappdata%\\ThermalDesktop` directory. +**Note**: Subject to change. You may find this file in the TD installation directory. If you’d like to use it, copy it to the `%localappdata%\ThermalDesktop` directory. Two types of objects are defined in the configuration file: loggers and listeners. Loggers emit messages, while listeners route them to destinations. In each case, they only act on messages that are at or above the level they are defined at. @@ -180,7 +180,7 @@ This means that any logger in an OpenTD client program whose name starts with Op There is also a *RootLogger* defined. This is activated by any loggers whose names do not match the named loggers defined in the block. -There are three listeners defined, corresponding to three output files. Listener Log will write any-level messages to `%localappdata%\\ThermalDesktop\\log\\OpenTD.Client.log`, while listener ErrorLog will only write Error-level messages to `OpenTD.Client.Error.log`. And the OpenTDDemos listener will write any-level messages to `OpenTDDemos.log`. +There are three listeners defined, corresponding to three output files. Listener Log will write any-level messages to `%localappdata%\ThermalDesktop\log\OpenTD.Client.log`, while listener ErrorLog will only write Error-level messages to `OpenTD.Client.Error.log`. And the OpenTDDemos listener will write any-level messages to `OpenTDDemos.log`. Using the default configuration file, let’s look at some examples of how messages are routed to files. @@ -214,7 +214,7 @@ A logger in a client program is defined with the name “SatelliteBuilder.BusBui ```c# private static readonly Logger log3 = -LoggerFactory.GetLogger(“SatelliteBuilder.BusBuilder”); + LoggerFactory.GetLogger(“SatelliteBuilder.BusBuilder”); ``` It sends an Information-level message: @@ -235,5 +235,5 @@ Listener ErrorLog writes messages at Error-level only, so it does not write this - ThermalDesktop.*Print* prints a message to the AutoCAD console. - The User Coordinate System (UCS) can be queried or set using the ThermalDesktop.*UCS* property. - Model Browser visibility can be controlled using the ThermalDesktop.*ShowModelBrowser* and *HideModelBrowser* methods. -- Get a System.Windows.Forms.NativeWindow representing the main AutoCAD window using the ThermalDesktop.*GetMainWindow()* method. NativeWindow - mplements the IWin32Window interface, so this object can be used anywhere your application requires an IWin32Window that represents the main - utoCAD window. +- Get a System.Windows.Forms.NativeWindow representing the main AutoCAD window using the ThermalDesktop.*GetMainWindow()* method. NativeWindow implements the IWin32Window interface, so this object can be used anywhere your application requires an IWin32Window that represents the main AutoCAD window. diff --git a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/modifying-td-models.md b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/modifying-td-models.md index 6046489a48..94db2f0437 100644 --- a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/modifying-td-models.md +++ b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/modifying-td-models.md @@ -1,26 +1,26 @@ # Modifying TD models -So far, you have seen how to create new entities in TD, but OpenTD can also be used to query existing models and modify their contents. For most entity types, there is a ThermalDesktop method to get all items of that type in the model, and a method to get a specific item. For example, *GetNodes()* returns a list of all Nodes, and *GetNode(string handle)* returns a specific node if you know its AutoCAD handle. (See the [Work with connections, handles, markers, and domains section](creating-td-model/connections-handles-markers-domains.md)) It is often convenient to use the *LINQ Single* or *Where* methods to search a returned list of entities to find the items that meet some criteria. For example, to find all the arithmetic nodes on layer “sheet”, you could do something like this: +So far, you have seen how to create new entities in TD, but OpenTD can also be used to query existing models and modify their contents. For most entity types, there is a ThermalDesktop method to get all items of that type in the model, and a method to get a specific item. For example, *GetNodes()* returns a list of all Nodes, and *GetNode(string handle)* returns a specific node if you know its AutoCAD handle. (See the [Work with connections, handles, markers, and domains](creating-td-model/connections-handles-markers-domains.md) section) It is often convenient to use the *LINQ Single* or *Where* methods to search a returned list of entities to find the items that meet some criteria. For example, to find all the arithmetic nodes on layer “sheet”, you could do something like this: ```c# var arithmeticNodes = td.GetNodes().Where -(x => x.NodeType == RcNodeData.NodeTypes.ARITHMETIC -&& x.Layer == “sheet”); + (x => x.NodeType == RcNodeData.NodeTypes.ARITHMETIC + && x.Layer == “sheet”); ``` -The variable `arithmeticNodes` would now be an `*IEnumerable*` containing all of the arithmetic nodes on layer “sheet”. +The variable `arithmeticNodes` would now be an `IEnumerable` containing all of the arithmetic nodes on layer “sheet”. **Note**: You can use foreach to iterate over the elements of an `IEnumerable`, just like a List. Or you can convert the `IEnumerable` to a List using the `ToList()` method. -Another useful LINQ technique is to use the `*Select*` method to extract a related list from an input list. For example, the following line creates an `IEnumerable` containing the handles of all of the nodes returned by `GetNodes()`: +Another useful LINQ technique is to use the `Select` method to extract a related list from an input list. For example, the following line creates an `IEnumerable` containing the handles of all of the nodes returned by `GetNodes()`: ```c# var nodeHandles = td.GetNodes().Select(x => x.Handle); ``` -To delete any item with an AutoCAD handle, use the `*ThermalDesktop.DeleteEntity*` method. For items without handles, there are specialized delete methods such as `ThermalDesktop.DeleteSymbol*`, which accepts the name of the symbol to delete. +To delete any item with an AutoCAD handle, use the `ThermalDesktop.DeleteEntity` method. For items without handles, there are specialized delete methods such as `ThermalDesktop.DeleteSymbol`, which accepts the name of the symbol to delete. -The following examples demonstrate querying, modifying and deleting entities in a model. +The following examples demonstrate querying, modifying, and deleting entities in a model. ## Query and edit a model diff --git a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/reading-results.md b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/reading-results.md index 50967e9394..2c73afcdad 100644 --- a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/reading-results.md +++ b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/reading-results.md @@ -62,7 +62,7 @@ You can construct an array of strings to pass to GetData. For example, to get te ```c# string[] someNames = new string[100]; for (int i = 0; i < 100; ++i) -someNames[i] = "MAIN.T" + (i + 1); + someNames[i] = "MAIN.T" + (i + 1); var someTs = myData.GetData(someNames).GetValues(Units.SI); ``` @@ -78,7 +78,7 @@ var times = myData.GetTimes().GetValues(); This returns a list of times in the current WorkingUnits. -### Advanced Results Manipulation and XY Plots +### Advanced results manipulation and XY plots The previous section showed how to easily get data out of save files or CSR’s. In this and the following sections we will show how to manipulate that data, work with groups and multiple datasets, combine data in arbitrarily complex ways, and create simple XY plots. @@ -131,7 +131,7 @@ Compared to previous methods for extracting and plotting SINDA/FLUINT data, Open In this program, we will make use of the “torchNom.sav” and “torchCold.sav” files created in the [Create and run a case](working-with-case-sets.md#create-and-run-a-case) section, so please run that program and locate the two save files. -Once Visual Studio is set up with a 64-bit solution and project ( Section [Before using OpenTD.Results](#before-using-OpenTDresults)), and you have added references to OpenTD.dll and OpenTD.Results.dll, you will be ready to try the following program. +Once Visual Studio is set up with a 64-bit solution and project ([Before using OpenTD.Results](#before-using-OpenTDresults) section), and you have added references to OpenTD.dll and OpenTD.Results.dll, you will be ready to try the following program. ```c# using System; @@ -454,11 +454,11 @@ namespace OpenTDGettingStarted As shown in the preceding sections, the DataSubtype class is used to describe types of data found in solution results such as “node temperature T” or “lump pressure PL”. There are several methods that require a DataSubtype as a parameter. When using those methods, you can create your own DataSubtype, but it is usually easier to allow OpenTD to do it for you by making use of the StandardDataSubtypes enum and/or the FullStandardDataSubtype struct. -Through the magic of implicit casting (See the [Execute TD COM commands section](extras.md#execute-td-com-commands)) any method that accepts a DataSubtype will accept either a StandardDataSubtypes or FullStandardDataSubtype instead. For example, one of the GetData overloads has the following signature: +Through the magic of implicit casting (See the [Execute TD COM commands](extras.md#execute-td-com-commands) section) any method that accepts a DataSubtype will accept either a StandardDataSubtypes or FullStandardDataSubtype instead. For example, one of the GetData overloads has the following signature: ```c# DataArrayCollection GetData( -ItemIdentifierCollection itemIds, DataSubtype subtype, UnitsData units = null) + ItemIdentifierCollection itemIds, DataSubtype subtype, UnitsData units = null) ``` It expects a list of entity names (the ItemIdentifierCollection), the type of data to get (the DataSubtype), and you can optionally specify the units for any registers in the ItemIdentifierCollection. To get node temperatures for all the nodes in the “PANEL” domain from TD instance “td”, you could do this: @@ -533,9 +533,9 @@ You may notice that each of the conductors is listed twice, once from node A to Model topology along with solution results can be used to determine heat rates between groups of entities. This is done using an *IBrowser*. -The following program uses the solution results from section [Create and run a case](working-with-case-sets.md#create-and-run-a-case) . Make sure to run that program first before trying this one. As you may recall, that program creates a model of a bar heated on one end, convecting to a room along its length. We will be using results from a transient case, starting with a cold bar. +The following program uses the solution results from the [Create and run a case](working-with-case-sets.md#create-and-run-a-case) section. Make sure to run that program first before trying this one. As you may recall, that program creates a model of a bar heated on one end, convecting to a room along its length. We will be using results from a transient case, starting with a cold bar. -We will create two IBrowsers, one early in the solution and one at the final record, using them to find the total heat rate from the bar to the room at the two times. We will also use a SumDataArray (section [Advanced results manipulation and XY plots](#advanced-results-manipulation-and-xy-plots)) to plot the constant total external heat into the bar over the whole solution. We expect the heat rate from the bar to the room to approach the external heat rate as the system approaches steady-state. +We will create two IBrowsers, one early in the solution and one at the final record, using them to find the total heat rate from the bar to the room at the two times. We will also use a SumDataArray ([Advanced results manipulation and XY plots](#advanced-results-manipulation-and-xy-plots) section) to plot the constant total external heat into the bar over the whole solution. We expect the heat rate from the bar to the room to approach the external heat rate as the system approaches steady-state. ```c# using System; diff --git a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/working-with-case-sets.md b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/working-with-case-sets.md index 57befdd0cd..1a9a92f5fa 100644 --- a/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/working-with-case-sets.md +++ b/2025R1/thermal-desktop-opentd-92.0.0.0/articles/getting-started/working-with-case-sets.md @@ -100,7 +100,7 @@ namespace OpenTDGettingStarted } ``` -Solution files, including “torchNom.sav” and “torchCold.sav”, will be written to the working directory, which we created and then set with ThermalDesktop*.ConnectConfig.StartDirectory*. (See the [Control how OpenTD connects to Thermal Desktop](extras.md#control-how-opentd-connects-to-thermal-desktop) section for more information about controlling how OpenTD connects to TD.) Otherwise, the working directory would have probably been the directory containing your exe. You can also use the ThermalDesktop.*SaveAs* method before running to save the dwg and set the working directory. +Solution files, including “torchNom.sav” and “torchCold.sav”, will be written to the working directory, which we created and then set with ThermalDesktop.*ConnectConfig.StartDirectory*. (See the [Control how OpenTD connects to Thermal Desktop](extras.md#control-how-opentd-connects-to-thermal-desktop) section for more information about controlling how OpenTD connects to TD.) Otherwise, the working directory would have probably been the directory containing your exe. You can also use the ThermalDesktop.*SaveAs* method before running to save the dwg and set the working directory. ## Create an orbit and apply it to a case set @@ -151,7 +151,7 @@ namespace OpenTDGettingStarted When you call CaseSet.Run(), it is the same as selecting and running a single case in the GUI. If you would like to select multiple cases and run, either in Demand or Batch mode, you can use ThermalDesktop.*CaseSetManager*. It provides all the functionality of the Case Set Manager, including the ability to adjust Manager-level options, using the CaseSetManager.*Options* member. -To run multiple cases – just like selecting them all in the GUI and running – use the following CaseSetManager.Run overload: +To run multiple cases–just like selecting them all in the GUI and running–use the following CaseSetManager.Run overload: ```c# void Run(IEnumerable caseIndices)