diff --git a/2025R2/thermal-desktop-opentd-for-demo/.gitignore b/2025R2/thermal-desktop-opentd-for-demo/.gitignore new file mode 100644 index 0000000000..4378419e7f --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/.gitignore @@ -0,0 +1,9 @@ +############### +# folder # +############### +/**/DROP/ +/**/TEMP/ +/**/packages/ +/**/bin/ +/**/obj/ +_site diff --git a/2025R2/thermal-desktop-opentd-for-demo/.vale.ini b/2025R2/thermal-desktop-opentd-for-demo/.vale.ini new file mode 100644 index 0000000000..4e3997ac45 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/.vale.ini @@ -0,0 +1,10 @@ +StylesPath = styles + +Vocab = ansys + +MinAlertLevel = suggestion + +Packages = Google + +[*.md] +BasedOnStyles = Vale, Google \ No newline at end of file diff --git a/2025R2/thermal-desktop-opentd-for-demo/api/.gitignore b/2025R2/thermal-desktop-opentd-for-demo/api/.gitignore new file mode 100644 index 0000000000..e8079a3bef --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/api/.gitignore @@ -0,0 +1,5 @@ +############### +# temp file # +############### +*.yml +.manifest diff --git a/2025R2/thermal-desktop-opentd-for-demo/api/index.md b/2025R2/thermal-desktop-opentd-for-demo/api/index.md new file mode 100644 index 0000000000..78dc9c0057 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/api/index.md @@ -0,0 +1,2 @@ +# PLACEHOLDER +TODO: Add .NET projects to the *src* folder and run `docfx` to generate **REAL** *API Documentation*! diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/changelog.md b/2025R2/thermal-desktop-opentd-for-demo/articles/changelog.md new file mode 100644 index 0000000000..537bff24fa --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/changelog.md @@ -0,0 +1,62 @@ +# Changelog + +## Version 2024 R2 + +### New features + +- added `case set group name` parameter to `TDSF_CoSolver` constructors +- added `Message` member to `CompareSuite`; just returns `Log` member +- twin lump ids are now automatically sequenced if `lump.TwinId == 0` +- added auto start of OpenTD servers on `_SAVEAS` for all versions of OpenTD + +## Version 2024 R1 + +### Note + +This was an administrative release. There is only one new feature: added `Comparer.ToString()` method. + +## Version 2023 R2 + +### Major new features + +- added support for controlling item visibility via the `ThermalDesktop.VisibilityManager` +- added `ReadMeshDataFile` method to read various mesh data formats into TD +- added support for stack aliases +- added `DynamicSindaStatus` class for interacting with messages generated by `Dynamic Sinda` +- added limited support for new beta `SaveX` file format + +### Other new features + +- added `MeshDisplayer.BaseTrans` property -- now you can move FEM's +- added experimental `CaseSetManager.IsCaseRunning()` method for asynchronous cases +- added `Contactor.Comment` property +- use lightweight SubmodelNameData's to identify submodels for FloCAD objects +- added `GetNumberOfDbObjects(...)` method +- implemented `ConvertFDtoFE` method +- `Matrix3d.SetOrigin` now returns the new matrix instead of `void` +- `Dataset.Factory.Load` method to load `sav`, `savx`, or `CSR` +- `Comparer` ctor overload to accept `IDatasets` instead of `Datasets` +- added `Close` and `ReOpen` methods to `IDataset` +- added `CloseDatasets` and `ReOpenDatasets` methods to `Comparer` +- added ability to rename and delete aliases +- added `CaseSetManagerOptions.ShowTextScreenDuringRun` member +- added `Conductor.UseGlobalAccelm` member +- added `RcEntityData.GlobalContactArray` member +- added `RcSolidElement.AnalysisGroupsVolumetric` member +- added `RcFdSolidData.AnalysisGroupsVolumetric` member +- added `FkLocator.Anchor` member +- added `Pipe.LengthDivisions` and `RadialDivisions` members +- added `Tie.LengthDivisions`, `RadialDivisions`, and `UseGlobalAccelm` members + +### Performance improvements + +- `CreateCone` returns correct node names +- `Polygon.Update()` no longer duplicates vertices +- `CoSolver.Continue()` returns -1 if `SF` disconnected, instead of an exception +- New `scr` filename and pipe name conventions to avoid Windows Defender mistaking `scr` files for viruses +- avoid issues with duplicate handles in Assembly +- fix parsing mixed-case subtypes like "DeltaP" +- fix `GetMeshFD(s)` so it populates returned object(s) correctly +- `GetPipe` no longer returns pipes with blank signatures +- pipe ties now handle domains correctly +- `CaseSet.Run` and `CaseSetManager.Run` now handle casesets with drive symbols from Excel diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/docfx.json b/2025R2/thermal-desktop-opentd-for-demo/articles/docfx.json new file mode 100644 index 0000000000..8b11bf0e2b --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/docfx.json @@ -0,0 +1,13 @@ +{ + "build": { + "globalMetadata": { + "title": "Thermal Desktop OpenTD 2025 R2", + "summary": "", + "version": "2025 R2", + "product": "Thermal Desktop", + "programming language": "C#", + "product collection": "Fluids", + "physics": "Fluids" + } + } +} \ No newline at end of file diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/appendix-A-using-opentd-with-MATLAB.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/appendix-A-using-opentd-with-MATLAB.md new file mode 100644 index 0000000000..5628fa6a80 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/appendix-A-using-opentd-with-MATLAB.md @@ -0,0 +1,126 @@ +# 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. + +```MATLAB +%% 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 +% 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 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.\*; +td = ThermalDesktop; +td.Connect(); +% \*\*\* 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; +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(); +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); +for i = 1:10 +barConnections.Add(Connection(barNodes(i).Handle)); +end +convection = td.CreateConductor(... +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); +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 \*\*\* +% 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(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'); +cold.SteadyState = 0; +cold.Transient = 1; +cold.SindaControl.timend... += 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); +end +function x = Dimensional(Dimensional, double) +% Cast a double to a .NET generic Dimensional type +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/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/appendix-B-using-opentd-with-python.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/appendix-B-using-opentd-with-python.md new file mode 100644 index 0000000000..fa28d7080c --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/appendix-B-using-opentd-with-python.md @@ -0,0 +1,114 @@ +# 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/). + +```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. +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: +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 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.) +from OpenTDv242 import Dimension +from OpenTDv242.Dimension import \* +td = ThermalDesktop() +td.Connect() +\# \*\*\* 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.InitialTemp = Dimensional[Dimension.Temp](300.0) + n.Update() + barNodes.Add(n) +for i in range(9): + c = td.CreateConductor(Connection(barNodes[i]), Connection(barNodes[i+1])) + 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)) +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])) +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: +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: +cold = td.CreateCaseSet("transient with cold torch", "", "torchCold") +cold.SteadyState = 0 +cold.Transient = 1 +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.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. +``` diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/appendix-C-using-opentd-with-powershell.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/appendix-C-using-opentd-with-powershell.md new file mode 100644 index 0000000000..7043a122b7 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/appendix-C-using-opentd-with-powershell.md @@ -0,0 +1,15 @@ +# Appendix C: Using OpenTD with PowerShell + +Windows PowerShell can be used to interact with OpenTD, which is useful since it is included with Windows, that is, you don't need to install Visual Studio, MATLAB, or anything extra to use OpenTD. And unlike Python or MATLAB, PowerShell was designed to support .NET objects, so its .NET syntax isn't too bad. + +PowerShell is likely already installed on your Windows machine. If not, or you'd like help finding it, check out the official documentation: + +[https://docs.microsoft.com/en-us/powershell/](https://docs.microsoft.com/en-us/powershell/) + +Here’s a simple PowerShell script that loads OpenTD, creates a ThermalDesktop instance and opens it: + +```powershell +Add-Type -Path "C:\\Windows\\Microsoft.NET\\assembly\\GAC_MSIL\\OpenTDv242\\v4.0_23.2.0.0__65e6d95ed5c2e178\\OpenTDv242.dll" +\$td = New-Object -TypeName 'OpenTDv232.ThermalDesktop' +\$td.Connect() +``` diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/appendix-D-using-opentd-with-csharp-compiler.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/appendix-D-using-opentd-with-csharp-compiler.md new file mode 100644 index 0000000000..4bb5470ce8 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/appendix-D-using-opentd-with-csharp-compiler.md @@ -0,0 +1,21 @@ + +# Appendix D: Using OpenTD Interactively with the C# Interactive Compiler + +Normally C\# is compiled before running, but you can open an interactive C\# Read-eval-print loop (REPL) in Visual Studio using the following command: View-\>Other Windows-\>C\# Interactive + +Once open, you can use it to interactively execute C\# code, including OpenTD. For example: + +```csharp +\> \#r "OpenTDv242" // loads the dll as a reference +\> using OpenTDv242; +\> var td = new ThermalDesktop(); +\> td.Connect(); +\> var n = td.CreateNode(new Point3d(1, 1, 3)); +\> td.ZoomExtents(); +\> n.Comment = "Hello World!"; +\> n.Update(); +\> var nTest = td.GetNodes().First(); +\> Console.WriteLine(nTest); +RcNode.MAIN.1::236 "Hello World!" +\> td.Quit(); +``` diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/communicating-with-sinda-fluint.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/communicating-with-sinda-fluint.md new file mode 100644 index 0000000000..3dc546c6ab --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/communicating-with-sinda-fluint.md @@ -0,0 +1,9 @@ +# Communicating with SINDA/FLUINT + +OpenTD can be used to communicate with and control running SINDA/FLUINT (S/F) solutions using the classes in the OpenTDv242.*CoSolver* namespace: + +- *SF_Launcher* is used to load and run a S/F model directly from an input file, such as an *inp* file created by the TD Case Set Manager. Once launched, the solution proceeds normally with no interaction from the SF_Launcher object. +- *SF_CoSolver* is like an SF_Launcher in that it launches a S/F model from an input file, but once launched it attempts to connect to and control it. +- *TDSF_CoSolver* launches a S/F model from within the TD Case Set Manager, then attempts to connect to and control it. + +There is a demo of CoSolver usage available in the OpenTD 2023 R2 demos package. (See [Further reading section](further-reading.md)) diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/basetrans-and-localtrans.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/basetrans-and-localtrans.md new file mode 100644 index 0000000000..a5c5685648 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/basetrans-and-localtrans.md @@ -0,0 +1,59 @@ +# Additional information on positioning entities using BaseTrans and LocalTrans + +As discussed in [Create and position finite-difference surfaces and solids](finite-difference-surfaces-and-solids.md), many OpenTD classes contain the members BaseTrans and LocalTrans, which both can be used to position entities. BaseTrans is equivalent to using AutoCAD commands like MOVE or ROTATE3D to position the entity, while LocalTrans is equivalent to using the Trans/Rot tab that can be found when editing an entity: + +![A screenshot of a computer Description automatically generated with medium confidence](../media/3c770a52859919ecb6e3a152a4c38b0d.png) + +These particular Trans/Rot parameters would result in the following transformations: + +1. Translate 2 m along the entity's base Y axis +2. Rotate -30 deg about the entity's Y axis +3. Rotate 45 deg about the entity's new X axis, that is, rotations are intrinsic (they are about the entity's current axes, not some fixed axes). + +LocalTrans is an instance of the *Transformation* class. To use it to perform the operations listed above, you'd use something like this: + +```c# +a.LocalTrans.Ty = 2; +a.LocalTrans.Axis1 = 1; // Y +a.LocalTrans.Rot1 = -30; +a.LocalTrans.Axis2 = 0; // X +a.LocalTrans.Rot2 = 45; +a.Update(); +``` + +BaseTrans is an instance of the *Matrix3d* class, that is, it is a 4x4 matrix representing a geometric transformation: + +![A picture containing screenshot, text, number, font Description automatically generated](../media/24e388913334338e77b9c87f790b9e76.png) + +The upper-left 3x3 submatrix represents a rotation. (In general it could represent many other operations, but when positioning entities using OpenTD, you should stick to rotations.) The 3x1 column vector on the right represents a translation. The bottom row should always be 0 0 0 1. + +OpenTD positions entities at the WCS origin, then transforms them by BaseTrans, followed by LocalTrans. Some of the methods available to BaseTrans are frequently misunderstood. There is a family of methods that sets the rotation matrix: + +- SetToRotation +- SetToRotX +- SetToRotY +- SetToRotZ + +These cannot be used sequentially to perform sequential rotations. Each one clears the rotation matrix and sets it to a single rotation. For example, SetToRotX(45) creates a rotation matrix that rotates 45 deg about the X axis. + +To perform sequential rotations, use matrix multiplication. For example, to perform a 10 deg rotation about an entity's Z axis, followed by a 50 deg rotation about its new X axis (that is, intrinsic rotations), you could use something like: + +```c# +var A = new Matrix3d().SetToRotZ(10); +var B = new Matrix3d().SetToRotX(50); +a.BaseTrans = A \* B; +a.Update(); +``` + +For intrinsic rotations, multiply matrices in order from left to right. + +Translations can also be included using matrix multiplication. For example, to perform a 10 deg rotation about an entity's Z axis, followed by a 2 m translation along its X axis, followed by a 50 deg rotation about its X axis, you could use something like: + +```c# +var A = new Matrix3d().SetToRotZ(10); +var T = new Matrix3d(); +T.SetOrigin(new Point3d(2, 0, 0)); +var B = new Matrix3d().SetToRotX(50); +a.BaseTrans = A * T * B; +a.Update(); +``` diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/bivariate-arrays.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/bivariate-arrays.md new file mode 100644 index 0000000000..42917332a2 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/bivariate-arrays.md @@ -0,0 +1,99 @@ +# Create thermophysical properties using bivariate arrays + +The following program demonstrates how to create or open a thermophysical property database, and how to create materials in it. One of the material definitions uses bivariate arrays, which are used in many places within SINDA/FLUINT, TD, and OpenTD. + +```c# +using System.Collections.Generic; +using OpenTDv242; + +namespace OpenTDv242GettingStarted +{ + class CreateThermophysicalProps + { + public static void Main(string[] args) + { + var td = new ThermalDesktop(); + td.Connect(); + + // Let's make sure we're working with an empty database. + // Note: relative pathnames in OpenTD are relative to the current + // working directory, which usually starts at the location of your + // exe file. + string dbPath = "TemporaryThermoPropDatabase.tdp"; + System.IO.File.Delete(dbPath); + td.OpenThermoPropDB(dbPath); + + // We'll create a thermophysical property representing Al 6061-T6, + // with data taken from the Spacecraft Thermal Control Handbook. + // The handbook uses the following units: + // density: kg/cm3 + // k: W/(cm.degC) + // Cp: W-hr/(kg.degC) + // We'll set WorkingUnits to SI with cm before setting density and k. + // For Cp, we'll need to set energy units to W-hr. + // Since we're working with inconsistent units, we'll save and restore + // whatever working unit system was in use before now. + Units.SaveWorkingUnits(); + Units.WorkingUnits.SetToSI(); + Units.WorkingUnits.modelLength = UnitsData.ModelLength.CM; + var Al6061 = td.CreateThermoProps("Al6061-T6"); + Al6061.Comment = "Al 6061-T6 from Spacecraft Thermal Control Handbook\\n" + "The Aerospace Corp., 2002"; + Al6061.Density = 0.00277; + Al6061.Conductivity = 1.679; + Units.WorkingUnits.energy = UnitsData.Energy.WATT_HOUR; + Al6061.SpecificHeat = 0.267; + Al6061.Update(); + Units.RestoreWorkingUnits(); + + // To rename a thermophysical property, you need to use Rename, + // since thermophysical properties are stored in TD using names as + // identifiers, unlike other entities that use AutoCAD handles. + Al6061.Rename("Aluminum 6061-T6"); + + // What if you've got a material with anisotropic, + // temperature- and pressure-dependent conductivity? + // For example, here's the conductivity of "Material A": + + // conductivity in x and y directions: + // 100 K: 21 W/(m.K) + // 200 K: 25 W/(m.K) + // 300 K: 27 W/(m.K) + + // conductivity in z-dir: (W/(m.K)) + // 150 K 250 K 350 K + // 50 kPa 3 5 8 + // 100 kPa 6 9 10 + + // Here's how to create a material with temperature- + // and pressure-dependent conductivity. + Units.WorkingUnits.SetToSI(); + var materialA = td.CreateThermoProps("Material A"); + materialA.Comment = "Aniso k demo"; + materialA.Anisotropic = 1; + materialA.VarConductivity = 1; + materialA.VarConductivityY = 1; + var kxyTemp = new List { 100, 200, 300, }; + var kxyValue = new List { 21, 25, 27, }; + materialA.ConductivityTemp = kxyTemp; + materialA.ConductivityValue = kxyValue; + materialA.ConductivityYTemp = kxyTemp; + materialA.ConductivityYValue = kxyValue; + materialA.VarCondTempPresZ = 1; + materialA.bivarTemperatureZ = new List { 150, 250, 350 }; + materialA.bivarPressureZ = new List { 50, 100 }; + materialA.bivarConductivityZ = new List + { + 3, 5, 8, + 6, 9, 10, + }; + materialA.Update(); + } + } +} +``` + +After running the program, the kz conductivity for Material A will show that the three lists of doubles we input are now expressed as a bivariate array: + +![Bivariate array](../media/b81c03156e87978bef43d64eefb85d01.png) + +The dwg units default to SI so the pressures are shown in Pa, even though we set the OpenTD WorkingUnits to kPa. Remember that WorkingUnits are independent of dwg units (See the [Work with units, symbols, and expressions](units-symbols-expressions.md) section). diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/connections-handles-markers-domains.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/connections-handles-markers-domains.md new file mode 100644 index 0000000000..81b8829c71 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/connections-handles-markers-domains.md @@ -0,0 +1,82 @@ +# Work with connections, handles, markers, and domains + +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: + +![C:\\Users\\matt\\AppData\\Local\\Temp\\SNAGHTML29a2a79e.PNG](../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. + +The other part of a Connection is a marker. This is an integer that specifies how the associated object is connected. For example, marker = 1 connects to the XMIN surface of an FD brick. Marker = 42 connects to XMAX, YMAX, and ZMAX. And Marker = 63 connects to all six surfaces of a brick. You might be wondering if those are random numbers! Converted to binary they make more sense: + +| Decimal | Binary | Applied Surfaces | | | | | | +|---------|----------|------------------|------|------|------|------|------| +| 1 | 0b000001 | | | | | | XMIN | +| 42 | 0b101010 | ZMAX | | YMAX | | XMAX | | +| 63 | 0b111111 | ZMAX | ZMIN | YMAX | YMIN | XMAX | XMIN | + +There is a special value for markers: if Marker is set to -999, then the Connection connects to a TD domain. In this special case, the Handle member no longer specifies the handle of a single TD object, but rather the name of the domain. + +The following program demonstrates these concepts: + +```c# +using System.Collections.Generic; +using OpenTDv242; + +namespace OpenTDv242GettingStarted +{ + class WorkWithConnections + { + public static void Main(string[] args) + { + var td = new ThermalDesktop(); + td.Connect(); + + // create a rectangle: + var brick = td.CreateSolidBrick(); + + // create a heatload with default connection: + // equiv. to td.CreateHeatLoad(new Connection(brick.Handle, 1)); + var heatLoad = td.CreateHeatLoad(brick); + heatLoad.AppliedType = RcHeatLoadData.AppliedTypeBoundaryConds.SURFACE; + heatLoad.Update(); + + // with marker = 1 = 0b000001, heatload applied to XMIN + // let's apply it to XMIN and YMIN: + heatLoad.ApplyConnections[0].Marker = 0b000101; + heatLoad.Name = "q applied to brick"; + heatLoad.Update(); + + // create a rectangle: + var rect = td.CreateRectangle(); + rect.BaseTrans.SetToRotX(90); + rect.BaseTrans.SetOrigin(new Point3d(0, 0, 2)); + rect.XMax = 2; + rect.YMax = 3; + rect.BreakdownU.Num = 10; + rect.BreakdownV.Num = 15; + rect.Update(); + + // create a domain that includes some of the rect nodes: + var domainConnections = new List(); + foreach (Node n in td.GetNodes()) + { + if (rect.AttachedNodeHandles.Contains(n.Handle)) + { + if (n.Origin.Z < 4 && n.Origin.X < 1) + domainConnections.Add(new Connection(n)); + } + } + td.GetDomainManager().CreateDomain("HEATED", DomainType.NODESET, domainConnections); + + // apply a heat load to the domain: + var rectHeatLoad = td.CreateHeatLoad(new Connection("HEATED", -999)); + rectHeatLoad.Name = "q applied to rectangle domain"; + rectHeatLoad.Update(); + + td.SetVisualStyle(VisualStyles.THERMAL); + td.RestoreIsoView(IsoViews.SW); + td.ZoomExtents(); + } + } +} +``` diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/finite-difference-surfaces-and-solids.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/finite-difference-surfaces-and-solids.md new file mode 100644 index 0000000000..2be73ed22b --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/finite-difference-surfaces-and-solids.md @@ -0,0 +1,63 @@ +# Create and position finite-difference surfaces and solids + +You can use OpenTD to create Finite Difference (FD) surfaces and solids, and other geometric entities. When working with geometric entities in OpenTD, you will use two class members to position and orient objects: + +**BaseTrans**: This Matrix3d represents the position and orientation of the entity’s local coordinate system relative to the AutoCAD World Coordinate System (WCS). Modifying this member is equivalent to using AutoCAD commands such as MOVE or ROTATE3D to position and orient the entity. + +**LocalTrans**: This *Transformation* represents the position and orientation of the entity relative to its local coordinate system. Modifying this member is equivalent to editing the “Trans/Rot” tab in the GUI: + +![Trans/Rot tab in the GUI](../media/4e8146a507a20e79c517c1fe15f18d47.png) + + Here is a program that demonstrates creating FD entities and positioning them using BaseTrans and LocalTrans: + +```c# +using OpenTDv242; +namespace OpenTDv242GettingStarted +{ + class PositionFiniteDifference + { + public static void Main(string[] args) + { + var td = new ThermalDesktop(); + td.Connect(); + + // create a rectangle and position it using BaseTrans, + // which is equivalent to moving and rotating it using + // AutoCAD commands + var rect = td.CreateRectangle(); + rect.TopStartSubmodel = "plate"; + rect.TopStartId = 1; + rect.XMax = 1.1; + rect.YMax = 2.1; + rect.BreakdownU.Num = 10; + rect.BreakdownV.Num = 20; + rect.BaseTrans.SetToRotX(30); + rect.BaseTrans.SetOrigin(new Point3d(0, 0, 1)); + rect.Update(); + + // create an FD solid brick and position it using LocalTrans, + // which is equivalent to moving and rotating it using + // the TD Trans/Rot tab + var fdBrick = td.CreateSolidBrick(); + fdBrick.StartSubmodel = "brick"; + fdBrick.StartId = 1; + fdBrick.XMax = 0.19; + fdBrick.YMax = 0.31; + fdBrick.ZMax = 0.50; + fdBrick.BreakdownU.Num = 2; + fdBrick.BreakdownV.Num = 3; + fdBrick.BreakdownW.Num = 5; + fdBrick.LocalTrans.Tx = 0.5; + fdBrick.LocalTrans.Ty = 1.0; + fdBrick.LocalTrans.Tz = 0.5; + fdBrick.LocalTrans.Axis1 = 2; // rotate about z + fdBrick.LocalTrans.Rot1 = 30; // rotate 30 deg about z + fdBrick.Update(); + + // control view + td.SetVisualStyle(VisualStyles.THERMAL_PP); + td.RestoreIsoView(IsoViews.NE); + } + } +} +``` diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/finite-elements.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/finite-elements.md new file mode 100644 index 0000000000..84646cb5cc --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/finite-elements.md @@ -0,0 +1,87 @@ +# Create finite elements + +In TD, finite elements can be created directly by attaching them to existing nodes, but the preferred approach is to use an FE Mesh Importer. OpenTD allows you to use either method. + +Creating a finite element mesh using the *FEMeshImporter* class is demonstrated in the following program: + +```c# +using System; +using OpenTDv242; + +namespace OpenTDv242GettingStarted +{ + class CreateFiniteElements + { + public static void Main(string[] args) + { + var td = new ThermalDesktop(); + td.Connect(); + + // In TD and OpenTD, you can create a FEM with nodes and elements + // directly, but the preferred approach is to use an FE Mesh Importer. + + // We'll demonstrate how to use a mesh importer. We'll start + // by creating an empty one: + bool useUCS = false; + var meshImporter = td.CreateFEMeshImporter("a mesh importer", useUCS); + + // We're going to call the FEMeshImporter.SetMesh command, but + // first we'll need to construct an FEMesh to pass to it. We'll + // use linear quads, but a full complement of linear and quadratic + // surface and solid element types are available. + // The FEMesh object is a lightweight description of the mesh, with + // lightweight nodes and elements that are only used as input to + // the SetMesh command. + var feMesh = new OpenTDv242.RadCAD.FEModel.FEMesh(); + int uDiv = 10; + int vDiv = 10; + double height = 0.5; + double xPeriods = 2.0; + double yPeriods = 1.0; + double xLen = 5.0; + double yLen = 3.0; + int id = 0; + int elemId = 0; + for (int j = 0; j < vDiv + 1; ++j) + { + double y = j * yLen / vDiv; + for (int i = 0; i < uDiv + 1; ++i) + { + double x = i * xLen / uDiv; + double z = height * Math.Cos(x / xLen * xPeriods * 2.0 * Math.PI) * Math.Cos(y / yLen * yPeriods * 2.0 * Math.PI); + // lightweight node description: + var node = new OpenTDv242.RadCAD.FEModel.Node(); + node.x = x; + node.y = y; + node.z = z; + node.Nx = 0.0; + node.Ny = 0.0; + node.Nz = 1.0; + node.id = ++id; + feMesh.nodes.Add(node); + if (i < uDiv && j < vDiv) + { + // lightweight surface description: + var face = new OpenTDv242.RadCAD.FEModel.SurfaceElement(); + face.id = ++elemId; + face.order = 1; + face.numNodes = 4; + int baseIndex = j * (uDiv + 1) + i + 1; + face.nodeIds.Add(baseIndex); + face.nodeIds.Add(baseIndex + 1); + face.nodeIds.Add(baseIndex + 1 + uDiv + 1); + face.nodeIds.Add(baseIndex + uDiv + 1); + feMesh.surfaceElements.Add(face); + } + } + } + meshImporter.SetMesh(feMesh); + td.SetVisualStyle(VisualStyles.THERMAL_PP); + td.RestoreIsoView(IsoViews.SE); + td.ZoomExtents(); + } + } +} +``` + +If you create a mesh using the FEMeshImporter class (the preferred approach), it is important to note that the *FEMesh* definition provided during creation is only used at that time. After creation, the client-side FEMesh object is not connected to the TD model and if you want to edit the mesh, you will have to get the editable objects to modify. This is discussed in section [Query and edit finite elements](../modifying-td-models.md#query-and-edit-finite-elements). diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/fluid-entities.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/fluid-entities.md new file mode 100644 index 0000000000..de477bccd4 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/fluid-entities.md @@ -0,0 +1,62 @@ +# Create fluid entities + +With a FloCAD license, you can use OpenTD to work with FloCAD entities, using methods like those we’ve already discussed for thermal entities. Here is a program that demonstrates working with FloCAD: + +```c# +using System.Collections.Generic; +using OpenTDv242; +using OpenTDv242.FloCAD; + +namespace OpenTDv242GettingStarted +{ + class CreateFluidEntities + { + public static void Main(string[] args) + { + var td = new ThermalDesktop(); + td.Connect(); + + // create a fluid submodel + var primary = td.CreateFluidSubmodel("PRIMARY"); + primary.ClearFluidLists(); + primary.FluidIds.Add(6070); + primary.FluidLetters.Add(0); // 0 = A, 1 = B, etc. + primary.FluidFilenames.Add(""); // will be set to "Water", b/c ID 6070 + primary.Update(); + + // create some lumps + var lumps = new List(); + for (int i = 0; i < 10; ++i) + { + var lump = td.CreateLump(); + lump.Submodel = "PRIMARY"; + lump.Origin = new Point3d(0.1 * i, 1, 0); + lump.Volume = 1e-4; + lump.Update(); + lumps.Add(lump); + } + + // make end lumps into plenums + lumps[0].LumpType = RcLumpData.LumpTypes.PLENUM; + lumps[0].InitialPres = 2e5; + lumps[0].Update(); + lumps[lumps.Count - 1].LumpType = RcLumpData.LumpTypes.PLENUM; + lumps[lumps.Count - 1].InitialPres = 1e5; + lumps[lumps.Count - 1].Update(); + + // connect the lumps with stubes + for (int i = 0; i < lumps.Count - 1; ++i) + { + var stube = td.CreatePath(lumps[i], lumps[i + 1]); + stube.FlowArea = 0.003; + stube.Update(); + } + + // control view + td.SetVisualStyle(VisualStyles.THERMAL_PP); + td.RestoreIsoView(IsoViews.SW); + td.ZoomExtents(); + } + } +} +``` diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/hello-world.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/hello-world.md new file mode 100644 index 0000000000..973d3e3362 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/hello-world.md @@ -0,0 +1,39 @@ +# 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: + +![A screenshot of a computer screen Description automatically generated with low confidence](../media/d47e44c0a654c0607631af3cacc32f6a.png) + +Next, add a reference to the `OpenTDv242.dll` assembly, which you can find in the GAC. (Try looking under C:\\Windows\\Microsoft.NET\\assembly\\GAC_MSIL\\OpenTDv242.) If there are multiple directories, use the one with the highest Assembly Version, which you will see in the directory name, for example “…_24.2.0.0__...”. + +Add the following code, then compile and run the program: + +```csharp +using OpenTDv242; +namespace OpenTDv242GettingStarted +{ + class HelloWorld + { + public static void Main(string[] args) + { + var td = new ThermalDesktop(); + td.Connect(); + var n = td.CreateNode(); + n.Comment = "Hello World!"; + n.Update(); + } + } +} +``` + +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. + +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. + +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/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/nodes-and-conductor.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/nodes-and-conductor.md new file mode 100644 index 0000000000..9a9f300d4a --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/nodes-and-conductor.md @@ -0,0 +1,43 @@ +# 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. + +```c# +using OpenTDv242; +namespace OpenTDv242GettingStarted +{ + class CreateNodesAndConductors + { + public static void Main(string[] args) + { + var td = new ThermalDesktop(); + td.Connect(); + var n1 = td.CreateNode(); + n1.Submodel = "bar"; + n1.Id = 100; + n1.Update(); + var n2 = td.CreateNode(); + n2.Submodel = "bar"; + n2.Id = 110; + n2.Origin = new Point3d(1, 1, 0); + n2.Update(); + var c = td.CreateConductor(n1, n2); + c.Submodel = "bar"; + c.Value = 10; + c.Update(); + } + } +} +``` + +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: + +![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) + +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/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/optical-properties.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/optical-properties.md new file mode 100644 index 0000000000..83138f1d9e --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/optical-properties.md @@ -0,0 +1,53 @@ +# Create optical properties + +If you have a RadCAD license, you can create optical properties with OpenTD. The following program creates a simple optical property, and a more complicated wavelength-dependent property: + +```c# +using System.Collections.Generic; +using OpenTDv242; + +namespace OpenTDv242GettingStarted +{ + class CreateOpticalProperties + { + public static void Main(string[] args) + { + var td = new ThermalDesktop(); + td.Connect(); + + // Let's make sure we're working with an empty optical database. + // Note: relative pathnames in OpenTD are relative to the current + // working directory, which usually starts at the location of your + // exe file. + string dbPath = "TemporaryOpticalPropDatabase.rco"; + System.IO.File.Delete(dbPath); + td.OpenOpticalPropDB(dbPath); + + // create simple optical property + var black = td.CreateOpticalProps("black"); + black.Comment = "ideal black surface"; + black.Alph = 1; + black.Emis = 1; + black.Update(); + + // create wavelength-dependent optical property + var catalac = td.CreateOpticalProps("Cat-A-Lac Black"); + catalac.Comment = "Cat-A-Lac Black from TwoPlates.dwg"; + catalac.UseWaveLengthDepProps = 1; + catalac.UseVarWaveLengthEmiss = 1; + + // wavelength always in micrometers, regardless of WorkingUnits: + catalac.emissVarWaveLengthum = new List\< double\> { + + 0.100, 8.000, 10.000, 13.000, 19.000, 20.000, + 30.000, 40.000, 60.000, 110.000, 1000.000, + }; + catalac.emissVarWaveLengthValue = new List { + 0.92, 0.92, 0.85, 0.91, 0.94, 0.82, + 0.95, 0.95, 0.78, 0.6, 0.1, + }; + catalac.Update(); + } + } +} +``` diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/overview.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/overview.md new file mode 100644 index 0000000000..5b0c748a17 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/overview.md @@ -0,0 +1,3 @@ +# Creating TD models + +We will start our tour of OpenTD by learning how to connect to TD and create new entities like nodes and conductors. diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/units-symbols-expressions.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/units-symbols-expressions.md new file mode 100644 index 0000000000..9ffcea7aa5 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/units-symbols-expressions.md @@ -0,0 +1,91 @@ +# 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. + +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. + +The following program shows how to use WorkingUnits, symbols, and expressions: + +```c# +using System; +using System.Collections.Generic; +using System.Linq; // for the Select method, below +using OpenTDv242; + +namespace OpenTDv242GettingStarted +{ + class WorkWithUnitsSymbolsExpressions + { + public static void Main(string[] args) + { + var td = new ThermalDesktop(); + td.Connect(); + + // To set the units used in the GUI, use SetDwgUnits. + // This is equivalent to setting Preferences->Units. + // Here we'll set the dwg units to English with inches + // instead of feet for model length: + var dwgUnits = new UnitsData(); + dwgUnits.SetToEng(); + dwgUnits.modelLength = UnitsData.ModelLength.INCH; + td.SetDwgUnits(dwgUnits); + + // OpenTD uses its own unit system called WorkingUnits + // to control input and output of all dimensional + // values. In this example we'll set WorkingUnits to SI, + // then set and get the density of a material in kg/m3. + // Then we'll set WorkingUnits.modelLength to cm and get + // the same property, showing that it will now return as + // kg/cm3. Note that since the dwg units were set to inches + // and lbm, the value shown in the GUI is 0.289018 lbm/in^3: + // it's completely independent of the WorkingUnits. + string materialName = "steel"; + if (td.GetThermoPropss().Select(x => x.Name).Contains(materialName)) + td.DeleteThermoProps(materialName); + var material = td.CreateThermoProps(materialName); + Units.WorkingUnits.SetToSI(); // this is the default anyway + material.Density = 8000; // kg/m3 + material.Update(); + Console.WriteLine(material.Density); // "8000" + Console.WriteLine(material.Density.ToString()); // "8000 kg/m^3" + Units.WorkingUnits.modelLength = UnitsData.ModelLength.CM; + Console.WriteLine(material.Density); // "0.008" + Console.WriteLine(material.Density.ToString()); // "0.008 kg/cm^3" + + // You can set both the dwg units and WorkingUnits with the + // SetUnits method. Also, you don't always have to create + // a new UnitsData. The Units.SI and Units.Eng UnitsData + // objects are convenient static readonly objects that + // correspond to standard SI and English units systems. + td.SetUnits(Units.SI); + + // Create symbols using the CreateSymbol method. Here we'll + // create a symbol representing a heat load value in Btu/hr: + string symbolName = "heatload"; + var heatload = td.CreateSymbol(symbolName, "34.12 * 2"); + heatload.Description = "heat load in Btu/hr"; + heatload.Update(); + + // Get evaluated symbol values using GetSymbolValue. These + // represent the basic symbol values, unmodified by Case Sets + // or other means. + var heatloadValue = td.GetSymbolValue(symbolName); + Console.WriteLine($"{symbolName} value = {heatloadValue}"); + + // You can use expressions in OpenTD anywhere you can use + // them in the GUI. Here we'll create a heatload, set its + // value expression ("ValueExp") to our symbol created above, + // then set the units of the expression to BTU/hr to match + // the symbol: + var n = td.CreateNode(); + var q = td.CreateHeatLoad(new List { n }); + q.ValueExp.Value = symbolName; + q.ValueExp.units.energy = UnitsData.Energy.BTU; + q.ValueExp.units.time = UnitsData.Time.HR; + q.Update(); + + td.ZoomExtents(); + } + } +} +``` diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/use-a-loop.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/use-a-loop.md new file mode 100644 index 0000000000..25deef6c8b --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/creating-td-model/use-a-loop.md @@ -0,0 +1,76 @@ +# Use a loop to create many layers, nodes, and conductors + +It is easy to create two nodes and a conductor using the GUI. The real usefulness of an API like OpenTD is in automating things that are tedious and/or time-consuming. For example, the following program creates 101 nodes in a sinusoid pattern connected by conductors and puts them on 101 randomly colored layers. This program only uses a few new OpenTD concepts, but it demonstrates how OpenTD types can be combined with C\# statements to quickly accomplish things that would take much longer using the GUI. + +```c# +using System; +using System.Collections.Generic; +using OpenTDv242; + +namespace OpenTDv242GettingStarted +{ + class UseLoop + { + public static void Main(string[] args) + { + // parameters + const int numNodes = 101; + const string submodel = "wavybeam"; + const int startingNodeNum = 200; + const string layerPrefix = "Random Layer"; + const double Length = 10.0; + const double amplitude = 2.0; + const double freq = 4; + var startingPoint = new Point3d(0, 1, 0); + + // start TD + var td = new ThermalDesktop(); + td.Connect(); + + // create nodes and put them in a list for later use + var r = new Random(); + var nodes = new List(); + + for (int i = 0; i < numNodes; ++i) + { + var layer = td.CreateLayer(layerPrefix + " " + i); + layer.ColorIndex = r.Next(254) + 1; + layer.Update(); + + double x = Length / (numNodes - 1) * i; + double y = amplitude * Math.Sin(freq * x / Length * 2 * Math.PI); + var nodeDisplacementFromStartingPoint = new Vector3d(x, y, 0); + + var n = td.CreateNode(); + n.Layer = layer.Name; + n.Submodel = submodel; + n.Id = startingNodeNum + i; + n.Origin = startingPoint + nodeDisplacementFromStartingPoint; + n.Update(); + + nodes.Add(n); + } + + // create conductors + for (int i = 0; i < nodes.Count - 1; ++i) + { + var c = td.CreateConductor(nodes[i], nodes[i + 1]); + c.Layer = nodes[i].Layer; + c.Submodel = submodel; + c.Update(); + } + + // control view + td.ZoomExtents(); + } + } +} +``` + +In the above program, note that we performed vector addition using the + operator: + +```csharp +n.Origin = startingPoint + nodeDisplacementFromStartingPoint; +``` + +OpenTD knows how to perform limited arithmetic with its *Point2d*, *Point3d*, *Vector3d*, and *Matrix3d* objects. diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/extras.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/extras.md new file mode 100644 index 0000000000..09a14e2d88 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/extras.md @@ -0,0 +1,240 @@ +# Extras + +The Extras section covers advanced topics and additional functionalities in OpenTD, including connection management, server control, command execution, implicit casting, and versioning considerations. + +## Control how OpenTD connects to Thermal Desktop + +In this guide, we mostly call ThermalDesktop.Connect() with default options, which means it starts a new instance of TD with the latest version of AutoCAD available, then creates a new, blank drawing. To change this behavior, set the ThermalDesktop.*ConnectConfig* member before calling Connect(), as shown in the following program, which hides the AutoCAD window while it’s running: + +```c# +using OpenTDv242; +namespace OpenTDv242GettingStarted +{ + class ControlHowOpenTDConnects + { + public static void Main(string[] args) + { + var td = new ThermalDesktop(); + td.ConnectConfig.AcadVisible = false; + td.Connect(); + // useful code goes here... + td.Quit(); + } + } +} +``` + +This program also demonstrates the ThermalDesktop.*Quit()* method, which tells AutoCAD to close, regardless of whether there are unsaved changes. (To save a dwg, use ThermalDesktop.*SaveAs*.) To *really* force AutoCAD to quit – by killing the acad.exe process – use ThermalDesktop.Quit(true). This should be considered a last resort. It may leave lock files in the dwg directory and/or have other unintended consequences. + +Here are some useful members of ConnectConfig: + +- **AcadExePathname**: By default, Connect() starts the latest version of AutoCAD found on your machine. Set AcadExePathname to the full path of any acad.exe to use it instead. + +- **AcadVisible**: Set to false to hide the AutoCAD window. This only works when starting new TD instances, not attaching to already-running instances. + +- **DwgPathname**: If this is set, Connect() will try to attach to or start a TD instance with this dwg. It will throw an exception if the dwg does not exist. Instead of editing ConnectConfig, this can also be set using an overloaded ThermalDesktop constructor: + +```c# +var td = new ThermalDesktop(@”path\\to\\dwg”); +``` + +- **PipeEndpointName**: Use this after issuing one of the TD commands for starting servers (See the [Control OpenTD servers from AutoCAD](#control-opentd-servers-from-autocad) section) to connect to an already-running instance of TD. + +- **Type**: This determines whether Connect() will try to attach to an already-running instance of TD or start a new one. The default is AUTO, which means it will try both – first it will try to attach, but if that fails, it will start a new instance. + +A complete list of ConnectConfig members (along with all OpenTD types) can be found in the “OpenTD Class Reference” document. (See the [Further reading](further-reading.md) section) + +## Control OpenTD servers from AutoCAD + +A client program communicates with TD via an OpenTD server launched within the acad.exe process, identified with a string called a *Pipe Endpoint Name*. When you load a dwg containing TD entities, an OpenTD server is started using the dwg pathname to generate the pipe endpoint name. That’s how the Connect() method finds the correct acad process when DwgPathname is set (See the [Control how OpenTD connects to Thermal Desktop](#control-how-opentd-connects-to-thermal-desktop) section). An OpenTD server is also automatically started when you start a new instance of TD via OpenTD. + +There are commands you can use at the AutoCAD command line to query and start OpenTD servers: + +- **RCOPENTDV242**: This command will ask you for a pipe endpoint name and start a server with that name. +- **RCOPENTDV242RANDOM**: This command will start a server with a random name. +- **RCOPENTDV242DWG**: This command will start a server with a name based on the dwg pathname. It is included for completeness, but there should never be a reason to call it, since it is called automatically by TD. +- **RCOPENTDV242LISTSERVERS**: This command will list the pipe endpoint names of the active OpenTDv242 servers. + +To connect a client program to a server based on endpoint name, set ThermalDesktop.ConnectConfig.PipeEndpointName before calling Connect() – (See the [Control how OpenTD connects to Thermal Desktop](#control-how-opentd-connects-to-thermal-desktop) section). + +## Execute AutoCAD commands + +When an OpenTD method is not available to perform a task, you might be able to use the ThermalDesktop.*SendCommand* method to send an AutoCAD command to TD. SendCommand has the following signature: + +```c# +void SendCommand(string command, bool echo = true, int delay = 1000) +``` + +In addition to the string containing the command, there are two optional parameters: *echo* and *delay*. Echo determines whether your command will be echoed to the AutoCAD command line and defaults to true. Delay is the time in milliseconds that your program will wait after issuing the command before continuing. SendCommand executes asynchronously, and currently there is no way for OpenTD to check when it is done. The workaround is to wait a fixed amount of time before continuing. The default delay is 1000 ms. You may wish to experiment with shorter delays to speed up execution. + +The following program demonstrates using SendCommand: + +```c# +using OpenTDv242; +namespace OpenTDv242GettingStarted +{ + class ExecuteAutocadCommands + { + public static void Main(string[] args) + { + var td = new ThermalDesktop(); + td.Connect(); + + // draw an AutoCAD rectangle: + td.SendCommand("rectang 3,3 4,5 "); + + // draw AutoCAD text: (Using a dash in front + // of the command to make it command-line only. + // This works for some AutoCAD commands.) + td.SendCommand("-text 3,2.6 0.25 0 A Door\\n"); + + // zoom extents using OpenTD method: + td.ZoomExtents(); + + // zoom view to scale factor 1.5: (using + // abbreviated command names) + td.SendCommand("z s 1.5 "); + } + } +} +``` + +## Execute TD COM commands + +Before OpenTD, there was a Windows Component Object Model (COM) interface to TD. It could be used to perform a subset of OpenTD functions. To use it, commands were entered as text strings and parsed by the TD COM server. + +In OpenTD, the ThermalDesktop.*SendLegacyComCommand* method emulates the TD COM parser without actually using a COM connection. + +Most TD COM functionality can be accomplished using native OpenTD methods. The SendLegacyComCommand method is included for completeness, and to ease the process of migrating an existing TD COM application to OpenTD. SendLegacyComCommand is not recommended to be used by new OpenTD applications. + +Since the underlying RadCAD functions used by the COM server report success/failure via the AutoCAD console and not via a return value, SendLegacyComCommand may appear to succeed when it did not. It will only throw exceptions if it doesn't recognize a command or if the command crashes AutoCAD, and not if the command fails in some non-catastrophic way. + +SendLegacyComCommand usually returns an empty string. The only exception to this is the "get" command, which attempts to return a string representing the value of a symbol. + +The following commands are supported: + +- **acadcommand "command" ["optional parameter" "optional parameter" ...]** + Executes an AutoCAD console command. The command and any parameters are individually enclosed in double quotes. New applications should use ThermalDesktop.SendCommand instead. Examples: + + - SendLegacyComCommand("acadcommand \\"zoom\\" \\"extents\\"") + - SendLegacyComCommand("acadcommand \\"line\\" \\"1,1\\" \\"2,2\\" \\"\\"") + +- **case [optional parameters]** +Calculates radiation and Cond/Cap data for the current case set. New applications should use OpenTD CaseSetManager and/or CaseSet instead. Examples: + - SendLegacyComCommand("case") // Calculates all radiation and cond/cap data. + - SendLegacyComCommand("case rad0 rad3 cc") // Calculates 1st and 4th radiation tasks and cond/cap data. + +- **caseset parameters** +Provides access to the Case Set Manager. New applications should use OpenTD CaseSetManager and/or CaseSet instead. + +- **copyradkfiles fromFilename toFilename** +Copies radk files. + +- **createmapset** +Undocumented interactive command. + +- **disableuserbreaks** +Disables the ability to press ESC to end tasks. + +- **displaycurrentdataset** + Displays the current post-processing dataset. New applications should use OpenTD.PostProcessing instead. + +- **dumpppmap outputFilename** +Undocumented post-processing command. New applications should use OpenTD.Results instead. + +- **exitautocad** +Attempts to exit Thermal Desktop without saving the dwg. New applications should use ThermalDesktop.Quit instead. + +- **exportnodeinfo** +Calls the RcExportNodeInfo command. New applications should use ThermalDesktop.ExportNodeInfo instead. + +- **get symbolName** +Returns a string representing the evaluated value of a symbol. New applications should use ThermalDesktop.GetSymbolValue instead. + +- **importcomet filename** +Undocumented. + +- **mapnastran inputFilename outputFilename [optional tolerance]** +Maps the current post-processing data to the Nastran mesh defined in inputFilename, writing the results in Nastran format in outputFilename. New applications should use PostProcessing.*DataMapper* instead. + +- **object** +This command is used by Dynamic SINDA/FLUINT to display the value of OBJECT in the TD Dynamic SINDA/FLUINT status window. + +- **opticalias alias opticalProp** +Changes what optical property an alias refers to. The names cannot include spaces. New applications should use ThermalDesktop.OpticalPropAliasManager instead. + +- **orbit parameters** +Provides access to the Heating Rate Case Manager. New applications should use OpenTD Orbit instead. + +- **output message** +Writes message to the TD Dynamic SINDA/FLUINT status window. + +- **postprocess filename [optional delay in ms]** +Creates or updates a TEXT-type dataset from a file. New applications should use PostProcessing.DatasetManager instead. + +- **ppnexttime** +Steps forward to the next record in the current dataset. New applications should use PostProcessing.DatasetManager instead. + +- **ppsavefile savOrCsrPathname** +Creates or updates a SF-type dataset from a save file or CSR directory. New applications should use PostProcessing.DatasetManager instead. + +- **ppsettime index** +Sets the record for the current post-processing dataset. Uses 0-indexed record array index (0, 1, 2, etc) not record number. New applications should use PostProcessing.DatasetManager instead. + +- **sendf4** +Sends the F4 keycode. Useful for capturing the screen using hypersnap/cam. + +- **set symbolName expressionIncludingSpaces** +Updates an existing symbol's expression. New applications should use OpenTD Symbol instead. + +- **setmapconstanttol toleranceInDwgUnits** +Sets the constant tolerance to be used by the mapnastran command, in dwg units. New applications should use PostProcessing.DataMapper instead. + +- **setmapcurrentorall parameter** +If parameter is ALL, the mapnastran command will perform the mapping for all records in the dataset. If parameter is any other value, it will perform the mapping at the current record. New applications should use PostProcessing.DataMapper instead. + +- **setmapset mapsetName** +Instructs the mapnastran command to only use the specified object mapset. + +- **setmapvariabletol TolerancesSeperatedBySpaces** +Sets the progressive tolerance to be used by the mapnastran command, in dwg units. + +- **startcase [optional name]** +Runs the current case set, or the one specified by the optional name. New applications should use OpenTD CaseSetManager and/or CaseSet instead. + +- **tdmapallmappers appendToFilename** +Executes all mappers. Inserts the appendToFilename string at the end of each output file, before any extension. New applications should use PostProcessing.DataMapper instead. + +- **thermoalias alias thermoProp** +Changes what thermophysical property an alias refers to. The names cannot include spaces. New applications should use ThermalDesktop.ThermoPropAliasManager instead. + +- **update** +Updates all entity values based on symbol expressions. + +## The magic of implicit casting + +In the [Create nodes and a conductor](creating-td-model/nodes-and-conductor.md) section, we created a conductor with the following code: + +```c# +var c = td.CreateConductor(n1, n2); +``` + +where n1 and n2 were existing Node objects. CreateConductor has several overloads. The one we used is: + +```c# +Conductor CreateConductor(Connection from, Connection to) +``` + +We took advantage of the fact that OpenTD will implicitly cast a *DbObject* (like a Node) to a new Connection. Explicitly, the C\# compiler constructed Connections from our Nodes like this: + +```c# +var c = td.CreateConductor(new Connection(n1, 1), new Connection(n2, 1)); +``` + +OpenTD uses implicit casting in many places. For example, to cast StandardDataSubtypes to DataSubtypes. (See the [A note on DataSubtypes](reading-results.md#a-note-on-datasubtypes) section) Some languages do not support .NET implicit casting. If you’re using one of those languages to interface with OpenTD, you can always explicitly cast to the required type. (See [Appendix A: Using OpenTD with MATLAB](appendix-A-using-opentd-with-MATLAB.md) and [Appendix B: Using OpenTD with Python](appendix-B-using-opentd-with-python.md)) + +## A note on OpenTD versioning + +OpenTDv242 is included with TD as the OpenTDv242.dll, OpenTDv242.CoSolver.dll, and OpenTDv242.Results.dll assemblies installed in the Global Assembly Cache (GAC). All OpenTDv242 types are contained within the "OpenTDv242" namespace. Any changes we make to this interface will be additive. That is, we will not remove classes or methods. Therefore, you can write software referencing OpenTDv242 knowing that it will not be broken by updates or new releases of TD. + +Each subsequent release of OpenTD will be contained in its own family of dll’s (OpenTDv64.dll, OpenTDv64.Results.dll, etc.) and use its own namespace. When we develop each subsequent release, we will start with a complete copy of the previous release, then make changes only as required. Most commands should remain unchanged from release to release, and you should be able to take advantage of new features in new versions of OpenTD with a minimum of changes to your old programs. diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/further-reading.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/further-reading.md new file mode 100644 index 0000000000..7fc06080c9 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/further-reading.md @@ -0,0 +1,11 @@ +# Further reading + +- Also installed with TD is a file called “OpenTDv242 Class Reference.chm”. This contains a complete list of all public types, members, and methods in OpenTDv242. You can find it in the TD installation directory, usually in the same location as this guide. + +- The TD user forum ([http://www.crtech.com/forum](http://www.crtech.com/forum)) contains more OpenTD demos, written in C#, MATLAB, and Python. Two boards are especially useful: + +- Software Usage->Tutorials->OpenTD contains a post called OpenTDv242 Demos that contains a Visual Studio project that demonstrates many more features of OpenTD: + +![Graphical user interface, text, application, email Description automatically generated](media/1fe5ddd44d6df8c7835612e8287ecb11.png) + +- Software Usage->Product-specific Discussions->OpenTD is a place to ask and answer questions about OpenTD. There are dozens of discussions, covering many aspects of OpenTD usage. diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/interacting-with-end-users.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/interacting-with-end-users.md new file mode 100644 index 0000000000..19f307fca6 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/interacting-with-end-users.md @@ -0,0 +1,239 @@ +# Interacting with end users + +## Control the view + +There are several techniques you can use to control how the model is displayed in the main Thermal Desktop window: + +- Use the ThermalDesktop.VisibilityManager to get and set item and item label visibility. + +- Use an object’s *Layer* member to change what layer it is on, perhaps moving it to or from a frozen layer. + +- Use ThermalDesktop.*GetLayers* or .*GetLayer* to get an existing layer, then change its color, frozen status, and so on. + +- Use an object’s *ColorIndex* member to directly change its color. + +- Use ThermalDesktop.*RestoreIsoView* to set the view to one of the standard isometric views. + +- Use ThermalDesktop.*RestoreOrthoView* to set the view to one of the standard orthographic views. + +- Use ThermalDesktop.*RestoreView* to set the view to a pre-defined, custom named view. These can also contain layer settings. Create named views in the GUI using the AutoCAD “view” command. + +- Use ThermalDesktop.*SetView* and either an *IsoViews* enum, an *OrthoViews* enum, or a string representing a named view to set the view. + +- Use ThermalDesktop.*SetVisualStyle* to select wireframe, hidden, shaded, and more. + +- Use ThermalDesktop.*ResetGraphics* to redraw everything in the main window. + +- Display contour plots using the ThermalDesktop.*DatasetManager*. See the [Reading result](reading-results.md#create-contour-plots) section. + +## Capture graphics area + +Once you have set up the main TD view using the techniques discussed above, you may wish to capture the graphics area as a bitmap for use elsewhere. To do this, use the ThermalDesktop.*CaptureGraphicsArea* method, with the following signature: + +System.Drawing.Bitmap ThermalDesktop.CaptureGraphicsArea() + +The Bitmap object it returns can be saved to a file, or further processed within your program. + +Caution: Internally, this method uses the Windows clipboard to get the bitmap out of TD. Unfortunately, it deletes anything that was on the clipboard before. + +## Working with the selection set + +OpenTD allows you to ask the end user to select entities on screen, just like a TD command. It also allows you to do the opposite: set the selection set programmatically. These two operations are performed with the ThermalDesktop.*GetSelection* and *SetSelection* methods, respectively. There is also a *ClearSelection* method. + +GetSelection returns a list of *EntityDescriptors*, each containing a Connection for a selected entity and a string called *RawType* from AutoCAD describing what it is. For example, if the user selected a node, the RawType would be “RcNode”. + +EntityDescriptors are also returned by the ThermalDesktop.*GetEntityType* and *GetEntityTypes* methods, which can be used to determine entity types from handles. + +The following program demonstrates working with selection sets. It also uses the LINQ *query syntax* (for example: ‘from node in td.GetNodes() where node.Submodel == “MAIN”…’), which is a declarative syntax that can be easier to read than the *method syntax* we have used previously. + +```c# +using System; +using System.Linq; +using OpenTDv242; + +namespace OpenTDv242GettingStarted +{ + class Selections + { + public static void Main(string[] args) + { + var td = new ThermalDesktop(); + td.Connect(); + + // Create some randomly-placed nodes and lumps: + var rand = new Random(); + const int numberOfItems = 200; + for (int i = 0; i < numberOfItems / 2; ++i) + { + td.CreateNode(new Point3d( + rand.NextDouble(), rand.NextDouble(), rand.NextDouble())); + var lump = td.CreateLump(); + lump.Origin = new Point3d( + rand.NextDouble(), rand.NextDouble(), rand.NextDouble()); + lump.Update(); + } + td.SetView(IsoViews.SE); + + Console.WriteLine("Using SetSelection to select entities for which" + + " X < 0.5, Y < 0.5, and Z > 0.5"); + var NodeHandles = from node in td.GetNodes() + where node.Origin.X < 0.5 + && node.Origin.Y < 0.5 + && node.Origin.Z > 0.5 + select node.Handle; + var LumpHandles = from lump in td.GetLumps() + where lump.Origin.X < 0.5 + && lump.Origin.Y < 0.5 + && lump.Origin.Z > 0.5 + select lump.Handle; + var Region1Handles = NodeHandles.Concat(LumpHandles); + td.SetSelection(Region1Handles); + Console.WriteLine($"Selected {NodeHandles.Count()} nodes" + + $" and {LumpHandles.Count()} lumps. You may" + + $" have to move your mouse into the AutoCAD window" + + $" to see the selection."); + Console.WriteLine("Press [ENTER] to continue..."); + Console.ReadLine(); + + Console.WriteLine("Now asking user to select entites."); + td.ClearSelection(); + var selectedEntities = td.GetSelection(); + var selectedNodeHandles = from entity in selectedEntities + where entity.RawType == "RcNode" + select entity.Connection.Handle; + var selectedLumpHandles = from entity in selectedEntities + where entity.RawType == "RcLump" + select entity.Connection.Handle; + Console.WriteLine($"User selected {selectedNodeHandles.Count()}" + + $" nodes and {LumpHandles.Count()} lumps."); + } + } +} +``` + +## Using loggers + +Using log files to record program operations and errors can be a helpful technique, especially when debugging problems. OpenTD offers access to a powerful logging framework, the same one used by us within TD. + +To use the logging framework, you will create an OpenTDv242.*Logging.Logger* object, then call various methods on it to send messages to log files. The messages have one of the following levels assigned to them, from most to least important: Error, Warning, Information, and Verbose. + +Loggers are created using the *LoggerFactory* class, usually as a static member of a class. For example, here is the one we use internally for the ThermalDesktop class: + +```c# +private static readonly Logger log = +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? + +After calling GetLogger, your log is ready to use. Interestingly, you don’t define a log file location within your program. Instead, this is controlled at runtime using the configuration file located at %localappdata%\\ThermalDesktop\\OpenTDLogConfig.xml. This makes logging more flexible. During debugging on an end-user’s computer, you can adjust this configuration file to concentrate on the problem areas in your program. + +This is a recent configuration file installed with TD: + +```lua +\ +\ +\ + +This example is a modification of System Coupling's _Oscillating Plate Fluid-Structure Interaction_ tutorial. + +The setup of the Mechanical participant is identical to the oscillating plate tutorial. A thin flexible plate, made of a linear elastic material, (Young's modulus = 2.5E6 [Pa], Poisson's ratio = 0.35, density = 2550 [kg m^-3]) has a fixed support along its bottom face. A pressure load of 100 [Pa] is applied on one side of the plate for the first 0.5 [s] of the simulation, which starts the oscillation. The setup is illustrated in _Figure 1_. + + +![Figure 1: Structural solver geometry](../../images/PlateDampingTutorialFigure1.png) +_Figure 1: Structural solver geometry_ + +Since the purpose of this example is to demonstrate the use of Participant +Library APIs for a transient analysis, a simple damping force solver will be +used to couple with Mechanical via System Coupling. This solver receives nodal +displacements $\vec{X}$ from Mechanical and calculates the damping force +$\vec{F}$ using the following formula: + +$$ +\vec{F} = - c \frac{d\vec{X}}{dt} +$$ + +Formula + + +\vec{F} = - c \frac{d\vec{X}}{dt} + + +where $c$ is the damping coefficient and $\frac{d\vec{X}}{dt}$ is the rate of change +of nodal positions with respect to time (nodal velocities). +The damping solver then provides the calculated +forces to Mechanical via System Coupling, and these damping forces cause the +oscillations to diminish in amplitude. The higher the damping coefficient value is, +the faster the oscillations will diminish. The damping coefficient value of 1.0 +will be provided to the damping solver via a command line argument `--dampcoeff 1.0`. + +The surface mesh for the damping solver consists of 11 quadrilateral elements +that overlap the plate surface in Mechanical. The surface mesh is shown in _Figure 2_. + +![Figure 2: Surface mesh in the damping solver](media/19913b5a9a51f4926a07426227c010fa.png) +_Figure 2: Surface mesh in the damping solver_ + + +## Fortran + +Download the [SCP library tutorial package](https://github.com/ansys/DevRelPublics/raw/main/Downloads/SystemCoupling/syc_ParticipantLibrary_r1_25.zip) +and extract it to a local directory. Inside the resulting directory, you will +find a subdirectory called **OscillatingPlateDamping**. This will serve as the +simulation working directory and contains all the files needed for this +tutorial. The contents of this subdirectory are: + +## Visualize the results in Ansys EnSight + +Use Ansys EnSight to view the Mechanical solver results after the co-simulation run is complete. +You'll be able to plot the plate deformation over time. +One point at the top of the plate will be used to track the displacement +in the chart, which is a useful way to verify that the damping occurs +due to the force calculated in the damping solver. + +1. **Open Ansys EnSight.** + +2. **Load the Mechanical solver results file.** + + ```python + # This program prints Hello, world! + print('Hello, world!') + ``` + +3. **Enable deformation.** + +```python +# This program prints Hello, world! +print('Hello 2, world!') +``` + +4. **Visualize the nodal displacement.** + + ``` + # This program prints Hello, world! + print('Hello, world!') + ``` + diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/troubleshooting.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/troubleshooting.md new file mode 100644 index 0000000000..b4bc7f89ce --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/troubleshooting.md @@ -0,0 +1,21 @@ +# Troubleshooting + +## Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly […]. The system cannot find the file specified. + +When you try to run your program, it throws an exception like the above, referring to a dll such as SinapsXNet, CRlog4net, or something else. This likely means you tried to create a .NET Core or Standard project instead of a .NET Framework project, or your Thermal Desktop installation is corrupt. If the former, start a new .NET Framework project. In Visual Studio the project template should look something like this: + +![A screenshot of a computer screen Description automatically generated with low confidence](media/d47e44c0a654c0607631af3cacc32f6a.png) + +If that does not work, download and reinstall Thermal Desktop. + +## SINDA/FLUINT throws an error when I try to run a case using OpenTD + +You have tried to run a case using CaseSet.Run but it does not work, even though you can normally run cases using the GUI. Are you running your client program from within Visual Studio using the debugger or the “Start Without Debugging” command? Try building your client and launching it by double-clicking on the exe file in Windows Explorer instead. Sometimes Visual Studio introduces environment variables into child processes that interfere with SINDA/FLUINT and cause it to fail. + +## Unhandled Exception: System.BadImageFormatException: Could not load file or assembly 'OpenTDv242.Results […]’ or one of its dependencies. An attempt was made to load a program with an incorrect format. + +When you try to run a program that references OpenTDv242.Results.dll, you might get this exception. We had to compile OpenTDv242.Results.dll for x64 platforms, not “Any CPU” like many .NET assemblies. This means that if you reference it, your program also needs to compile for x64 platforms. See the [Work directly with results using OpenTDv242.Results](reading-results.md#work-directly-with-results-using-opentdv242results) section for more information on how to set up your program correctly. + +## My problem is not listed here + +Please contact us at [crtech.support@ansys.com](mailto:crtech.support@ansys.com). Please include “OpenTD” and a descriptive title for your problem in the subject line, with a detailed description in the main body. We will be happy to help get OpenTD working for you. diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/working-with-case-sets.md b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/working-with-case-sets.md new file mode 100644 index 0000000000..14a1a6edd6 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/getting-started/working-with-case-sets.md @@ -0,0 +1,160 @@ +# Working with case sets + +OpenTD gives you full control over case sets. You can create, query, modify, run, or delete them. The following sections show how. + +## Create and run a Case + +OpenTD can be used to interact with the Case Set Manager to create and run cases as shown in the following program: + +```c# +using System.Collections.Generic; +using System.IO; +using OpenTDv242; + +namespace OpenTDv242GettingStarted +{ + class CreateAndRunCase + { + public static void Main(string[] args) + { + // you may wish to change the location of the working dir: + string workingDir = @"c:\\temp\\OpenTDCreateAndRunCase"; + if (Directory.Exists(workingDir)) + Directory.Delete(workingDir, true); + Directory.CreateDirectory(workingDir); + + var td = new ThermalDesktop(); + td.ConnectConfig.StartDirectory = workingDir; + td.Connect(); + + // \*\*\* Create a simple model of a heated bar \*\*\* + var barNodes = new List\< Node\> (); + for (int i = 0; i \< 10; ++i) + { + var n = td.CreateNode(); + n.Submodel = "bar"; + n.Id = i + 1; + n.MassVol = 10; + n.Origin = new Point3d(0.01 * i, 1, 0); + n.InitialTemp = 300; + n.Update(); + barNodes.Add(n); + } + for (int i = 0; i < barNodes.Count - 1; ++i) + { + var c = td.CreateConductor(barNodes[i], barNodes[i + 1]); + c.Submodel = "bar"; + c.Id = i + 1; + c.Value = 0.1; + c.Update(); + } + var roomAir = td.CreateNode(); + roomAir.Submodel = "room"; + roomAir.NodeType = RcNodeData.NodeTypes.BOUNDARY; + roomAir.Origin = new Point3d(0.055, 1.1, 0); + roomAir.InitialTemp = 300; + roomAir.Update(); + + var barConnections = new List(); + foreach (Node n in barNodes) + barConnections.Add(new Connection(n)); + var convection = td.CreateConductor(roomAir, barConnections); + convection.Value = 1; + convection.Submodel = "room"; + convection.Update(); + + var qTorch = td.CreateSymbol("qTorch", "80"); + qTorch.OutputAsRegister = true; + qTorch.Update(); + + var torch = td.CreateHeatLoad(new Connection(barNodes[0])); + torch.ValueExp.Value = qTorch.Name; + torch.Submodel = "torch"; + torch.Update(); + + td.ZoomExtents(); + // \*\*\* End simple model creation \*\*\* + + // Create a transient case and run it: + var nominal = td.CreateCaseSet("transient with nominal torch", "", "torchNom"); + nominal.SteadyState = 0; + nominal.Transient = 1; + nominal.SindaControl.timend = 600; + nominal.Update(); + nominal.Run(); + + // Create a cold case by overriding a symbol, and run it: + var cold = td.CreateCaseSet + ("transient with cold torch", "", "torchCold"); + cold.SteadyState = 0; + cold.Transient = 1; + cold.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(); + } + } +} +``` + +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 + +Orbits are created using the ThermalDesktop.*CreateOrbit* method. Once created, they are applied to case sets by adding a new item to the *CaseSet.RadiationTasks* list. This can also be used to add other types of radiation tasks, such as RADK calculations, as shown in the following program: + +```c# +using OpenTDv242; +using OpenTDv242.RadCAD; + +namespace OpenTDv242GettingStarted +{ + class CreateOrbit + { + public static void Main(string[] args) + { + var td = new ThermalDesktop(); + td.Connect(); + + // create an orbit + var beta30 = td.CreateOrbit("beta30"); + beta30.OrbitType = Orbit.OrbitTypes.BASIC; + beta30.Planet = Orbit.Planets.EARTH; + beta30.OrbitData.Inclination = 30; + beta30.Update(); + + // add orbit to a new case set + var beta30Case = td.CreateCaseSet("beta30 case"); + // first add a RADK task: + beta30Case.RadiationTasks.Add(new RadiationTaskData() + { + TypeCalc = RadiationTaskData.calcType.RADK, + AnalGroup = "BASE", + }); + // now add the orbital heat rates task: + beta30Case.RadiationTasks.Add(new RadiationTaskData() + { + TypeCalc = RadiationTaskData.calcType.HEATRATE, + OrbitName = "beta30", + AnalGroup = "BASE", + }); + beta30Case.Update(); + } + } +} +``` + +## Run in batch mode + +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: + +```c# +void Run(IEnumerable\ caseIndices) +``` + +In other words, you provide a List\ or other IEnumerable\ containing the indices of the cases you would like to run. These indices correspond to the list indices returned by CaseSetManager.*GetCaseSets()* or the equivalent ThermalDesktop.*GetCaseSets()* method. diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/index.md b/2025R2/thermal-desktop-opentd-for-demo/articles/index.md new file mode 100644 index 0000000000..0be733cce8 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/index.md @@ -0,0 +1,19 @@ +# Introduction + +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 and delete models, interact with end users, run and control solutions, and manipulate results. 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 will 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. There are many excellent books and internet tutorials available for learning C#. For the remainder of this guide, we will assume you have at least an intermediate knowledge of object-oriented programming and C#, and some familiarity with the .NET global assembly cache (GAC). + +OpenTD was installed beginning with TD 6.1, which was released in early 2019. (Preliminary versions of OpenTD were called "TD API". ) + +We will now introduce OpenTD concepts and syntax in a series of example programs. The latter programs build on concepts introduced in the earlier ones, so we recommend you try them in order. + +## Authors + +OpenTD was developed and is maintained by a dedicated team of engineers: + +- Matthew D. Garrett +- Timothy D. Panczak +- Mark J. Schmidt +- Dave Wilkins +- Michael A. Madden diff --git a/2025R2/thermal-desktop-opentd-for-demo/articles/toc.yml b/2025R2/thermal-desktop-opentd-for-demo/articles/toc.yml new file mode 100644 index 0000000000..b53e0e2b4b --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/articles/toc.yml @@ -0,0 +1,63 @@ +- name: Introduction + href: index.md +- name: Getting started + items: + - name: Prerequisites + href: getting-started/prerequisites.md + - name: Test demo + href: getting-started/test-demo.md + - name: Creating TD models + href: getting-started/creating-td-model/overview.md + items: + - name: Hello World + href: getting-started/creating-td-model/hello-world.md + - name: Create nodes and a conductor + href: getting-started/creating-td-model/nodes-and-conductor.md + - name: Use a loop to create many layers-nodes-conductors + href: getting-started/creating-td-model/use-a-loop.md + - name: Create and position finite-difference surfaces and solids + href: getting-started/creating-td-model/finite-difference-surfaces-and-solids.md + - name: Additional information on using BaseTrans and LocalTrans + href: getting-started/creating-td-model/basetrans-and-localtrans.md + - name: Create finite elements + href: getting-started/creating-td-model/finite-elements.md + - name: Work with connections + href: getting-started/creating-td-model/connections-handles-markers-domains.md + - name: Work with units + href: getting-started/creating-td-model/units-symbols-expressions.md + - name: Create thermophysical properties + href: getting-started/creating-td-model/bivariate-arrays.md + - name: Create optical properties + href: getting-started/creating-td-model/optical-properties.md + - name: Create fluid entities + href: getting-started/creating-td-model/fluid-entities.md + - name: Modifying TD models + href: getting-started/modifying-td-models.md + - name: Interacting with end users + href: getting-started/interacting-with-end-users.md + - name: Working with case sets + href: getting-started/working-with-case-sets.md + - name: Communicating with SINDA/FLUINT + href: getting-started/communicating-with-sinda-fluint.md + - name: Reading results + href: getting-started/reading-results.md + - name: Launching programs in the Thermal Desktop Process using add-ins + href: getting-started/launching-programs-td-process-using-add-ins.md + - name: Extras + href: getting-started/extras.md + - name: Further reading + href: getting-started/further-reading.md + - name: Troubleshooting + href: getting-started/troubleshooting.md + - name: Using TD models with other languages + items: + - name: Appendix A - Using OpenTD with MATLAB + href: getting-started/appendix-A-using-opentd-with-MATLAB.md + - name: Appendix B - Using OpenTD with Python + href: getting-started/appendix-B-using-opentd-with-python.md + - name: Appendix C - Using OpenTD with Powershell + href: getting-started/appendix-C-using-opentd-with-powershell.md + - name: Appendix D - Using OpenTD Interactively with the C# Interactive Compiler + href: getting-started/appendix-D-using-opentd-with-csharp-compiler.md +- name: Changelog + href: changelog.md \ No newline at end of file diff --git a/2025R2/thermal-desktop-opentd-for-demo/docfx.json b/2025R2/thermal-desktop-opentd-for-demo/docfx.json new file mode 100644 index 0000000000..2746768cb1 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/docfx.json @@ -0,0 +1,68 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ + "src/**.csproj" + ] + } + ], + "dest": "api", + "disableGitFeatures": false, + "disableDefaultFilter": false + } + ], + "build": { + "content": [ + { + "files": [ + "api/**.yml", + "api/index.md" + ] + }, + { + "files": [ + "articles/**.md", + "articles/**/toc.yml", + "toc.yml", + "*.md" + ] + } + ], + "resource": [ + { + "files": [ + "images/**", + "**/*.png", + "**/*.jpg", + "**/*.gif", + "**/*.svg" + ] + } + ], + "overwrite": [ + { + "files": [ + "apidoc/**.md" + ], + "exclude": [ + "obj/**", + "_site/**" + ] + } + ], + "dest": "_site", + "globalMetadataFiles": [], + "fileMetadataFiles": [], + "template": [ + "default" + ], + "postProcessors": [], + "markdownEngineName": "markdig", + "noLangKeyword": false, + "keepFileLink": false, + "cleanupCacheHistory": false, + "disableGitFeatures": false + } +} \ No newline at end of file diff --git a/2025R2/thermal-desktop-opentd-for-demo/index.md b/2025R2/thermal-desktop-opentd-for-demo/index.md new file mode 100644 index 0000000000..3ae2506361 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/index.md @@ -0,0 +1,4 @@ +# This is the **HOMEPAGE**. +Refer to [Markdown](http://daringfireball.net/projects/markdown/) for how to write markdown files. +## Quick Start Notes: +1. Add images to the *images* folder if the file is referencing an image. diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/AMPM.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/AMPM.yml new file mode 100644 index 0000000000..37b49edf87 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/AMPM.yml @@ -0,0 +1,9 @@ +extends: existence +message: "Use 'AM' or 'PM' (preceded by a space)." +link: "https://developers.google.com/style/word-list" +level: error +nonword: true +tokens: + - '\d{1,2}[AP]M\b' + - '\d{1,2} ?[ap]m\b' + - '\d{1,2} ?[aApP]\.[mM]\.' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Acronyms.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Acronyms.yml new file mode 100644 index 0000000000..f41af0189b --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Acronyms.yml @@ -0,0 +1,64 @@ +extends: conditional +message: "Spell out '%s', if it's unfamiliar to the audience." +link: 'https://developers.google.com/style/abbreviations' +level: suggestion +ignorecase: false +# Ensures that the existence of 'first' implies the existence of 'second'. +first: '\b([A-Z]{3,5})\b' +second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)' +# ... with the exception of these: +exceptions: + - API + - ASP + - CLI + - CPU + - CSS + - CSV + - DEBUG + - DOM + - DPI + - FAQ + - GCC + - GDB + - GET + - GPU + - GTK + - GUI + - HTML + - HTTP + - HTTPS + - IDE + - JAR + - JSON + - JSX + - LESS + - LLDB + - NET + - NOTE + - NVDA + - OSS + - PATH + - PDF + - PHP + - POST + - RAM + - REPL + - RSA + - SCM + - SCSS + - SDK + - SQL + - SSH + - SSL + - SVG + - TBD + - TCP + - TODO + - URI + - URL + - USB + - UTF + - XML + - XSS + - YAML + - ZIP diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Colons.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Colons.yml new file mode 100644 index 0000000000..99363fbd46 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Colons.yml @@ -0,0 +1,8 @@ +extends: existence +message: "'%s' should be in lowercase." +link: 'https://developers.google.com/style/colons' +nonword: true +level: warning +scope: sentence +tokens: + - ':\s[A-Z]' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Contractions.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Contractions.yml new file mode 100644 index 0000000000..4f6fd5d489 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Contractions.yml @@ -0,0 +1,30 @@ +extends: substitution +message: "Use '%s' instead of '%s'." +link: 'https://developers.google.com/style/contractions' +level: suggestion +ignorecase: true +action: + name: replace +swap: + are not: aren't + cannot: can't + could not: couldn't + did not: didn't + do not: don't + does not: doesn't + has not: hasn't + have not: haven't + how is: how's + is not: isn't + it is: it's + should not: shouldn't + that is: that's + they are: they're + was not: wasn't + we are: we're + we have: we've + were not: weren't + what is: what's + when is: when's + where is: where's + will not: won't diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/DateFormat.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/DateFormat.yml new file mode 100644 index 0000000000..e9d227fa13 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/DateFormat.yml @@ -0,0 +1,9 @@ +extends: existence +message: "Use 'July 31, 2016' format, not '%s'." +link: 'https://developers.google.com/style/dates-times' +ignorecase: true +level: error +nonword: true +tokens: + - '\d{1,2}(?:\.|/)\d{1,2}(?:\.|/)\d{4}' + - '\d{1,2} (?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)|May|Jun(?:e)|Jul(?:y)|Aug(?:ust)|Sep(?:tember)?|Oct(?:ober)|Nov(?:ember)?|Dec(?:ember)?) \d{4}' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Ellipses.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Ellipses.yml new file mode 100644 index 0000000000..1e070517bf --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Ellipses.yml @@ -0,0 +1,9 @@ +extends: existence +message: "In general, don't use an ellipsis." +link: 'https://developers.google.com/style/ellipses' +nonword: true +level: warning +action: + name: remove +tokens: + - '\.\.\.' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/EmDash.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/EmDash.yml new file mode 100644 index 0000000000..5a81fb0942 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/EmDash.yml @@ -0,0 +1,13 @@ +extends: existence +message: "Don't put a space before or after a dash." +link: "https://developers.google.com/style/dashes" +nonword: true +level: error +action: + name: edit + params: + - trim + - " " +tokens: + - '\s[—–]\s' + diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Exclamation.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Exclamation.yml new file mode 100644 index 0000000000..b4e4a1f7e9 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Exclamation.yml @@ -0,0 +1,12 @@ +extends: existence +message: "Don't use exclamation points in text." +link: "https://developers.google.com/style/exclamation-points" +nonword: true +level: error +action: + name: edit + params: + - trim_right + - "!" +tokens: + - '\w+!(?:\s|$)' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/FirstPerson.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/FirstPerson.yml new file mode 100644 index 0000000000..0b7b8828ca --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/FirstPerson.yml @@ -0,0 +1,13 @@ +extends: existence +message: "Avoid first-person pronouns such as '%s'." +link: 'https://developers.google.com/style/pronouns#personal-pronouns' +ignorecase: true +level: warning +nonword: true +tokens: + - (?:^|\s)I\s + - (?:^|\s)I,\s + - \bI'm\b + - \bme\b + - \bmy\b + - \bmine\b diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Gender.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Gender.yml new file mode 100644 index 0000000000..c8486181d6 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Gender.yml @@ -0,0 +1,9 @@ +extends: existence +message: "Don't use '%s' as a gender-neutral pronoun." +link: 'https://developers.google.com/style/pronouns#gender-neutral-pronouns' +level: error +ignorecase: true +tokens: + - he/she + - s/he + - \(s\)he diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/GenderBias.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/GenderBias.yml new file mode 100644 index 0000000000..36f5a3f86e --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/GenderBias.yml @@ -0,0 +1,43 @@ +extends: substitution +message: "Consider using '%s' instead of '%s'." +ignorecase: true +link: "https://developers.google.com/style/inclusive-documentation" +level: error +action: + name: replace +swap: + (?:alumna|alumnus): graduate + (?:alumnae|alumni): graduates + air(?:m[ae]n|wom[ae]n): pilot(s) + anchor(?:m[ae]n|wom[ae]n): anchor(s) + authoress: author + camera(?:m[ae]n|wom[ae]n): camera operator(s) + door(?:m[ae]|wom[ae]n): concierge(s) + draft(?:m[ae]n|wom[ae]n): drafter(s) + fire(?:m[ae]n|wom[ae]n): firefighter(s) + fisher(?:m[ae]n|wom[ae]n): fisher(s) + fresh(?:m[ae]n|wom[ae]n): first-year student(s) + garbage(?:m[ae]n|wom[ae]n): waste collector(s) + lady lawyer: lawyer + ladylike: courteous + mail(?:m[ae]n|wom[ae]n): mail carriers + man and wife: husband and wife + man enough: strong enough + mankind: human kind|humanity + manmade: manufactured + manpower: personnel + middle(?:m[ae]n|wom[ae]n): intermediary + news(?:m[ae]n|wom[ae]n): journalist(s) + ombuds(?:man|woman): ombuds + oneupmanship: upstaging + poetess: poet + police(?:m[ae]n|wom[ae]n): police officer(s) + repair(?:m[ae]n|wom[ae]n): technician(s) + sales(?:m[ae]n|wom[ae]n): salesperson or sales people + service(?:m[ae]n|wom[ae]n): soldier(s) + steward(?:ess)?: flight attendant + tribes(?:m[ae]n|wom[ae]n): tribe member(s) + waitress: waiter + woman doctor: doctor + woman scientist[s]?: scientist(s) + work(?:m[ae]n|wom[ae]n): worker(s) diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/HeadingPunctuation.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/HeadingPunctuation.yml new file mode 100644 index 0000000000..c1729868b6 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/HeadingPunctuation.yml @@ -0,0 +1,13 @@ +extends: existence +message: "Don't put a period at the end of a heading." +link: "https://developers.google.com/style/capitalization#capitalization-in-titles-and-headings" +nonword: true +level: warning +scope: heading +action: + name: edit + params: + - trim_right + - "." +tokens: + - '[a-z0-9][.]\s*$' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Headings.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Headings.yml new file mode 100644 index 0000000000..c8d5be26e1 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Headings.yml @@ -0,0 +1,29 @@ +extends: capitalization +message: "'%s' should use sentence-style capitalization." +link: "https://developers.google.com/style/capitalization#capitalization-in-titles-and-headings" +level: warning +scope: heading +match: $sentence +indicators: + - ":" +exceptions: + - Azure + - CLI + - Cosmos + - Docker + - Emmet + - gRPC + - I + - Kubernetes + - Linux + - macOS + - Marketplace + - MongoDB + - REPL + - Studio + - TypeScript + - URLs + - Visual + - VS + - Windows + - JSON diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Latin.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Latin.yml new file mode 100644 index 0000000000..ca03b9154b --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Latin.yml @@ -0,0 +1,11 @@ +extends: substitution +message: "Use '%s' instead of '%s'." +link: 'https://developers.google.com/style/abbreviations' +ignorecase: true +level: error +nonword: true +action: + name: replace +swap: + '\b(?:eg|e\.g\.)(?=[\s,;])': for example + '\b(?:ie|i\.e\.)(?=[\s,;])': that is diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/LyHyphens.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/LyHyphens.yml new file mode 100644 index 0000000000..50dacb40db --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/LyHyphens.yml @@ -0,0 +1,14 @@ +extends: existence +message: "'%s' doesn't need a hyphen." +link: "https://developers.google.com/style/hyphens" +level: error +ignorecase: false +nonword: true +action: + name: edit + params: + - regex + - "-" + - " " +tokens: + - '\b[^\s-]+ly-\w+\b' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/OptionalPlurals.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/OptionalPlurals.yml new file mode 100644 index 0000000000..4a8767d6f5 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/OptionalPlurals.yml @@ -0,0 +1,12 @@ +extends: existence +message: "Don't use plurals in parentheses such as in '%s'." +link: "https://developers.google.com/style/plurals-parentheses" +level: error +nonword: true +action: + name: edit + params: + - trim_right + - "(s)" +tokens: + - '\b\w+\(s\)' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Ordinal.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Ordinal.yml new file mode 100644 index 0000000000..d1ac7d27e8 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Ordinal.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Spell out all ordinal numbers ('%s') in text." +link: 'https://developers.google.com/style/numbers' +level: error +nonword: true +tokens: + - \d+(?:st|nd|rd|th) diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/OxfordComma.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/OxfordComma.yml new file mode 100644 index 0000000000..b9ba21ebb2 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/OxfordComma.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Use the Oxford comma in '%s'." +link: 'https://developers.google.com/style/commas' +scope: sentence +level: warning +tokens: + - '(?:[^,]+,){1,}\s\w+\s(?:and|or)' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Parens.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Parens.yml new file mode 100644 index 0000000000..3b8711d0c8 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Parens.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Use parentheses judiciously." +link: 'https://developers.google.com/style/parentheses' +nonword: true +level: suggestion +tokens: + - '\(.+\)' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Passive.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Passive.yml new file mode 100644 index 0000000000..3265890e52 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Passive.yml @@ -0,0 +1,184 @@ +extends: existence +link: 'https://developers.google.com/style/voice' +message: "In general, use active voice instead of passive voice ('%s')." +ignorecase: true +level: suggestion +raw: + - \b(am|are|were|being|is|been|was|be)\b\s* +tokens: + - '[\w]+ed' + - awoken + - beat + - become + - been + - begun + - bent + - beset + - bet + - bid + - bidden + - bitten + - bled + - blown + - born + - bought + - bound + - bred + - broadcast + - broken + - brought + - built + - burnt + - burst + - cast + - caught + - chosen + - clung + - come + - cost + - crept + - cut + - dealt + - dived + - done + - drawn + - dreamt + - driven + - drunk + - dug + - eaten + - fallen + - fed + - felt + - fit + - fled + - flown + - flung + - forbidden + - foregone + - forgiven + - forgotten + - forsaken + - fought + - found + - frozen + - given + - gone + - gotten + - ground + - grown + - heard + - held + - hidden + - hit + - hung + - hurt + - kept + - knelt + - knit + - known + - laid + - lain + - leapt + - learnt + - led + - left + - lent + - let + - lighted + - lost + - made + - meant + - met + - misspelt + - mistaken + - mown + - overcome + - overdone + - overtaken + - overthrown + - paid + - pled + - proven + - put + - quit + - read + - rid + - ridden + - risen + - run + - rung + - said + - sat + - sawn + - seen + - sent + - set + - sewn + - shaken + - shaven + - shed + - shod + - shone + - shorn + - shot + - shown + - shrunk + - shut + - slain + - slept + - slid + - slit + - slung + - smitten + - sold + - sought + - sown + - sped + - spent + - spilt + - spit + - split + - spoken + - spread + - sprung + - spun + - stolen + - stood + - stridden + - striven + - struck + - strung + - stuck + - stung + - stunk + - sung + - sunk + - swept + - swollen + - sworn + - swum + - swung + - taken + - taught + - thought + - thrived + - thrown + - thrust + - told + - torn + - trodden + - understood + - upheld + - upset + - wed + - wept + - withheld + - withstood + - woken + - won + - worn + - wound + - woven + - written + - wrung diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Periods.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Periods.yml new file mode 100644 index 0000000000..d24a6a6c03 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Periods.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Don't use periods with acronyms or initialisms such as '%s'." +link: 'https://developers.google.com/style/abbreviations' +level: error +nonword: true +tokens: + - '\b(?:[A-Z]\.){3,}' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Quotes.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Quotes.yml new file mode 100644 index 0000000000..3cb6f1abd1 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Quotes.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Commas and periods go inside quotation marks." +link: 'https://developers.google.com/style/quotation-marks' +level: error +nonword: true +tokens: + - '"[^"]+"[.,?]' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Ranges.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Ranges.yml new file mode 100644 index 0000000000..3ec045e777 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Ranges.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Don't add words such as 'from' or 'between' to describe a range of numbers." +link: 'https://developers.google.com/style/hyphens' +nonword: true +level: warning +tokens: + - '(?:from|between)\s\d+\s?-\s?\d+' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Semicolons.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Semicolons.yml new file mode 100644 index 0000000000..bb8b85b420 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Semicolons.yml @@ -0,0 +1,8 @@ +extends: existence +message: "Use semicolons judiciously." +link: 'https://developers.google.com/style/semicolons' +nonword: true +scope: sentence +level: suggestion +tokens: + - ';' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Slang.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Slang.yml new file mode 100644 index 0000000000..63f4c248a8 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Slang.yml @@ -0,0 +1,11 @@ +extends: existence +message: "Don't use internet slang abbreviations such as '%s'." +link: 'https://developers.google.com/style/abbreviations' +ignorecase: true +level: error +tokens: + - 'tl;dr' + - ymmv + - rtfm + - imo + - fwiw diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Spacing.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Spacing.yml new file mode 100644 index 0000000000..66e45a6b72 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Spacing.yml @@ -0,0 +1,10 @@ +extends: existence +message: "'%s' should have one space." +link: 'https://developers.google.com/style/sentence-spacing' +level: error +nonword: true +action: + name: remove +tokens: + - '[a-z][.?!] {2,}[A-Z]' + - '[a-z][.?!][A-Z]' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Spelling.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Spelling.yml new file mode 100644 index 0000000000..527ac07d31 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Spelling.yml @@ -0,0 +1,10 @@ +extends: existence +message: "In general, use American spelling instead of '%s'." +link: 'https://developers.google.com/style/spelling' +ignorecase: true +level: warning +tokens: + - '(?:\w+)nised?' + - 'colour' + - 'labour' + - 'centre' diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Units.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Units.yml new file mode 100644 index 0000000000..53522ab2de --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Units.yml @@ -0,0 +1,8 @@ +extends: existence +message: "Put a nonbreaking space between the number and the unit in '%s'." +link: "https://developers.google.com/style/units-of-measure" +nonword: true +level: error +tokens: + - \b\d+(?:B|kB|MB|GB|TB) + - \b\d+(?:ns|ms|s|min|h|d) diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/We.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/We.yml new file mode 100644 index 0000000000..c7ac7d3622 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/We.yml @@ -0,0 +1,11 @@ +extends: existence +message: "Try to avoid using first-person plural like '%s'." +link: 'https://developers.google.com/style/pronouns#personal-pronouns' +level: warning +ignorecase: true +tokens: + - we + - we'(?:ve|re) + - ours? + - us + - let's diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Will.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Will.yml new file mode 100644 index 0000000000..128a918362 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/Will.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Avoid using '%s'." +link: 'https://developers.google.com/style/tense' +ignorecase: true +level: warning +tokens: + - will diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/WordList.yml b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/WordList.yml new file mode 100644 index 0000000000..b3c6a403c0 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/WordList.yml @@ -0,0 +1,80 @@ +extends: substitution +message: "Use '%s' instead of '%s'." +link: "https://developers.google.com/style/word-list" +level: warning +ignorecase: false +action: + name: replace +swap: + "(?:API Console|dev|developer) key": API key + "(?:cell ?phone|smart ?phone)": phone|mobile phone + "(?:dev|developer|APIs) console": API console + "(?:e-mail|Email|E-mail)": email + "(?:file ?path|path ?name)": path + "(?:kill|terminate|abort)": stop|exit|cancel|end + "(?:OAuth ?2|Oauth)": OAuth 2.0 + "(?:ok|Okay)": OK|okay + "(?:WiFi|wifi)": Wi-Fi + '[\.]+apk': APK + '3\-D': 3D + 'Google (?:I\-O|IO)': Google I/O + "tap (?:&|and) hold": touch & hold + "un(?:check|select)": clear + above: preceding + account name: username + action bar: app bar + admin: administrator + Ajax: AJAX + a\.k\.a|aka: or|also known as + Android device: Android-powered device + android: Android + API explorer: APIs Explorer + application: app + approx\.: approximately + authN: authentication + authZ: authorization + autoupdate: automatically update + cellular data: mobile data + cellular network: mobile network + chapter: documents|pages|sections + check box: checkbox + CLI: command-line tool + click on: click|click in + Cloud: Google Cloud Platform|GCP + Container Engine: Kubernetes Engine + content type: media type + curated roles: predefined roles + data are: data is + Developers Console: Google API Console|API Console + disabled?: turn off|off + ephemeral IP address: ephemeral external IP address + fewer data: less data + file name: filename + firewalls: firewall rules + functionality: capability|feature + Google account: Google Account + Google accounts: Google Accounts + Googling: search with Google + grayed-out: unavailable + HTTPs: HTTPS + in order to: to + ingest: import|load + k8s: Kubernetes + long press: touch & hold + network IP address: internal IP address + omnibox: address bar + open-source: open source + overview screen: recents screen + regex: regular expression + SHA1: SHA-1|HAS-SHA1 + sign into: sign in to + sign-?on: single sign-on + static IP address: static external IP address + stylesheet: style sheet + synch: sync + tablename: table name + tablet: device + touch: tap + url: URL + vs\.: versus + World Wide Web: web diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/meta.json b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/meta.json new file mode 100644 index 0000000000..a5da2a8480 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/meta.json @@ -0,0 +1,4 @@ +{ + "feed": "https://github.com/errata-ai/Google/releases.atom", + "vale_version": ">=1.0.0" +} diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/Google/vocab.txt b/2025R2/thermal-desktop-opentd-for-demo/styles/Google/vocab.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/2025R2/thermal-desktop-opentd-for-demo/styles/config/vocabularies/ansys/accept.txt b/2025R2/thermal-desktop-opentd-for-demo/styles/config/vocabularies/ansys/accept.txt new file mode 100644 index 0000000000..c9482b21f8 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/styles/config/vocabularies/ansys/accept.txt @@ -0,0 +1,47 @@ +Ansys +OpenTD +Panczak +API +APIs +[Nn]amespace +dll +enum +[Ss]ubmodel +[Ss]ubmodels +dialogs +dwg +Postprocessing +flowrates +thermophysical +thermoProp +thermoalias +tdmapallmappers +mapnastran +mapset +IBrowser +IBrowsers +csv +FTie +IFace +PostProcessing +radk +acadcommand +[Bb]ivariate +SF_Launcher +pythonnet +Exceedances +IDataset +inp +kz +kPa +FEM's +ctor +FEMesh +submatrix +interprocess +IEnumerable +arithmeticNodes +Fortran + + + diff --git a/2025R2/thermal-desktop-opentd-for-demo/toc.yml b/2025R2/thermal-desktop-opentd-for-demo/toc.yml new file mode 100644 index 0000000000..59f8010471 --- /dev/null +++ b/2025R2/thermal-desktop-opentd-for-demo/toc.yml @@ -0,0 +1,5 @@ +- name: Articles + href: articles/ +- name: Api Documentation + href: api/ + homepage: api/index.md