Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalized Tecplot ASCII and Binary Readers/Writers #95

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6c8fc28
Implemented tecplot ascii and binary readers and writers for n-dimens…
lamkina Jun 29, 2024
16191ce
Fixing black
lamkina Jun 29, 2024
3718d06
Adding docs for tecplot module
lamkina Jun 29, 2024
b277258
Bumped the minor version
lamkina Jun 29, 2024
0f35428
Fixed exception in external io test to catch all errors
lamkina Jun 29, 2024
b03bcac
Adding zone input validation, better use of enums, refactoring, and b…
lamkina Jul 20, 2024
9ebce66
Fixing regex for zone name matching
lamkina Aug 4, 2024
0288bee
Added terminating comma to regex pattern for zone header
lamkina Aug 4, 2024
d8fdc99
Fixed regex for zone name matching
lamkina Sep 13, 2024
660609b
Updating tecplot writers in the weight problem
lamkina Sep 13, 2024
f88c903
Fixing if checks for types
lamkina Sep 13, 2024
47903db
Updating tecplot writers in the aero solver
lamkina Sep 13, 2024
75f59ea
Fixing strand ID and solution time bugs in ASCII writer
lamkina Sep 20, 2024
80196c6
Fixed random data in ordered zones and added stress testing
lamkina Sep 20, 2024
63169ee
Added block format writer and reader to adhere to line width constraints
lamkina Sep 24, 2024
a503e8c
Added line length test for ASCII files
lamkina Sep 24, 2024
fc5c1c2
Improved the ascii data reader to use multiple separators and ignore …
lamkina Sep 24, 2024
066a6bd
Added full reader and writer separator support with tests
lamkina Sep 24, 2024
449c9b9
Cleaning up documentation, imports, and api
lamkina Sep 25, 2024
c2baf7c
Added tri connectivity property for FE zones with tests
lamkina Nov 8, 2024
fc5fbe8
Flake 8 is always watching
lamkina Nov 8, 2024
1e44f71
Added unique indices and nodes to fe zones
lamkina Nov 8, 2024
b9b83aa
New connectivity handling for FE zones with unique data and connectiv…
lamkina Nov 10, 2024
b30741e
Fixed remap connectivity bug
lamkina Nov 12, 2024
99e04c7
Switched remap connectivity to numpy for sppeeeed
lamkina Nov 12, 2024
7fc9a08
Updgraded the zone name matching to be more robust
lamkina Nov 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 11 additions & 14 deletions baseclasses/__init__.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
__version__ = "1.8.0"
__version__ = "1.9.0"

from .problems import (
AeroProblem,
TransiProblem,
StructProblem,
AeroStructProblem,
EngineProblem,
FieldPerformanceProblem,
FluidProperties,
FuelCase,
ICAOAtmosphere,
LGProblem,
MissionProblem,
MissionProfile,
MissionSegment,
StructProblem,
TransiProblem,
WeightProblem,
FuelCase,
FluidProperties,
ICAOAtmosphere,
EngineProblem,
FieldPerformanceProblem,
LGProblem,
)

from .solvers import BaseSolver, AeroSolver

from .utils import getPy3SafeString

from .solvers import AeroSolver, BaseSolver
from .testing import BaseRegTest, getTol
from .utils import getPy3SafeString, tecplotIO
121 changes: 62 additions & 59 deletions baseclasses/problems/pyWeight_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@
Holds the weightProblem class for weightandbalance solvers.
"""

import numpy as np
import copy
from pathlib import Path

import numpy as np

from ..utils import TecplotFEZone, TecplotOrderedZone, writeTecplot
from ..utils.tecplotIO import ZoneType

try:
from pygeo import geo_utils
Expand Down Expand Up @@ -68,9 +73,9 @@
"""

# Check if components is of type Component or list, otherwise raise Error
if type(components) == list:
if isinstance(components, list):

Check warning on line 76 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L76

Added line #L76 was not covered by tests
pass
elif type(components) == object:
elif isinstance(components, object):

Check warning on line 78 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L78

Added line #L78 was not covered by tests
components = [components]
else:
raise Error("addComponents() takes in either a list of or a single component")
Expand Down Expand Up @@ -132,7 +137,7 @@

"""

if type(surf) == list:
if isinstance(surf, list):

Check warning on line 140 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L140

Added line #L140 was not covered by tests
self.p0 = np.array(surf[0])
self.v1 = np.array(surf[1])
self.v2 = np.array(surf[2])
Expand Down Expand Up @@ -194,24 +199,28 @@
File name for tecplot file. Should have a .dat extension.

"""
f = open(fileName, "w")
f.write('TITLE = "weight_problem Surface Mesh"\n')
f.write('VARIABLES = "CoordinateX" "CoordinateY" "CoordinateZ"\n')
f.write("Zone T=%s\n" % ("surf"))
f.write("Nodes = %d, Elements = %d ZONETYPE=FETRIANGLE\n" % (len(self.p0) * 3, len(self.p0)))
f.write("DATAPACKING=POINT\n")
for i in range(len(self.p0)):
points = []
points.append(self.p0[i])
points.append(self.p0[i] + self.v1[i])
points.append(self.p0[i] + self.v2[i])
for i in range(len(points)):
f.write(f"{points[i][0]:f} {points[i][1]:f} {points[i][2]:f}\n")
# Build the FETriangle data array
dataArrays = np.zeros((len(self.p0) * 3, 3), dtype=float)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking here, but why use this large array? Makes it more readable to just use x etc. If there is no need to keep the data together, I would favor readability. This appears in other classes as well.

dataArrays[::3] = self.p0
dataArrays[1::3] = self.p0 + self.v1
dataArrays[2::3] = self.p0 + self.v2
data = {"CoordinateX": dataArrays[:, 0], "CoordinateY": dataArrays[:, 1], "CoordinateZ": dataArrays[:, 2]}

Check warning on line 207 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L203-L207

Added lines #L203 - L207 were not covered by tests

# Create the connectivity
conn = np.zeros((len(self.p0), 3), dtype=int)

Check warning on line 210 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L210

Added line #L210 was not covered by tests
for i in range(len(self.p0)):
f.write("%d %d %d\n" % (3 * i + 1, 3 * i + 2, 3 * i + 3))
conn[i, :] = [3 * i + 1, 3 * i + 2, 3 * i + 3]

Check warning on line 212 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L212

Added line #L212 was not covered by tests

f.close()
# Create the single zone
zones = [TecplotFEZone("surf", data, conn, zoneType=ZoneType.FETRIANGLE)]

Check warning on line 215 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L215

Added line #L215 was not covered by tests

writeTecplot(

Check warning on line 217 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L217

Added line #L217 was not covered by tests
fileName,
title="weight_problem Surface Mesh",
zones=zones,
datapacking="POINT",
precision="SINGLE",
)

def writeTecplot(self, fileName):
"""
Expand Down Expand Up @@ -362,9 +371,9 @@
"""

# Check if case is a single entry or a list, otherwise raise Error
if type(cases) == list:
if isinstance(cases, list):

Check warning on line 374 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L374

Added line #L374 was not covered by tests
pass
elif type(cases) == object:
elif isinstance(cases, object):

Check warning on line 376 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L376

Added line #L376 was not covered by tests
cases = [cases]
else:
raise Error("addFuelCases() takes in either a list of or a single fuelcase")
Expand Down Expand Up @@ -447,7 +456,7 @@

if includeType is not None:
# Specified a list of component types to include
if type(includeType) == str:
if isinstance(includeType, str):

Check warning on line 459 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L459

Added line #L459 was not covered by tests
includeType = [includeType]
weightKeysTmp = set()
for key in weightKeys:
Expand All @@ -457,21 +466,21 @@

if include is not None:
# Specified a list of compoents to include
if type(include) == str:
if isinstance(include, str):

Check warning on line 469 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L469

Added line #L469 was not covered by tests
include = [include]
include = set(include)
weightKeys.intersection_update(include)

if exclude is not None:
# Specified a list of components to exclude
if type(exclude) == str:
if isinstance(exclude, str):

Check warning on line 476 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L476

Added line #L476 was not covered by tests
exclude = [exclude]
exclude = set(exclude)
weightKeys.difference_update(exclude)

if excludeType is not None:
# Specified a list of compoent types to exclude
if type(excludeType) == str:
if isinstance(excludeType, str):

Check warning on line 483 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L483

Added line #L483 was not covered by tests
excludeType = [excludeType]
weightKeysTmp = copy.copy(weightKeys)
for key in weightKeys:
Expand All @@ -490,48 +499,42 @@

filename: str
filename for writing the masses. This string will have the
.dat suffix appended to it.
# .dat suffix appended to it if it does not already have it.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# intentional?

"""

fileHandle = filename + ".dat"
f = open(fileHandle, "w")
nMasses = len(self.nameList)
f.write('TITLE = "%s: Mass Data"\n' % self.name)
f.write('VARIABLES = "X", "Y", "Z", "Mass"\n')
locList = ["current", "fwd", "aft"]

zones = []

Check warning on line 508 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L508

Added line #L508 was not covered by tests
for loc in locList:
f.write('ZONE T="%s", I=%d, J=1, K=1, DATAPACKING=POINT\n' % (loc, nMasses))

for key in self.components.keys():
dataArray = np.zeros((nMasses, 4), dtype=float)
for i, key in enumerate(self.components.keys()):

Check warning on line 511 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L510-L511

Added lines #L510 - L511 were not covered by tests
CG = self.components[key].getCG(loc)
mass = self.components[key].getMass()
x = np.real(CG[0])
y = np.real(CG[1])
z = np.real(CG[2])
m = np.real(mass)

f.write(f"{x:f} {y:f} {z:f} {m:f}\n")

# end
f.write("\n")
# end

# textOffset = 0.5
# for loc in locList:
# for name in self.nameList:
# x= np.real(self.componentDict[name].CG[loc][0])
# y= np.real(self.componentDict[name].CG[loc][1])
# z= np.real(self.componentDict[name].CG[loc][2])+textOffset
# m= np.real(self.componentDict[name].W)

# f.write('TEXT CS=GRID3D, HU=POINT, X=%f, Y=%f, Z=%f, H=12, T="%s"\n'%(x,y,z,name+' '+loc))
# # end

# # end

f.close()
return
dataArray[i, 0] = CG[0]
dataArray[i, 1] = CG[1]
dataArray[i, 2] = CG[2]
dataArray[i, 3] = mass

Check warning on line 517 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L514-L517

Added lines #L514 - L517 were not covered by tests

data = {

Check warning on line 519 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L519

Added line #L519 was not covered by tests
"CoordinateX": dataArray[:, 0],
"CoordinateY": dataArray[:, 1],
"CoordinateZ": dataArray[:, 2],
"Mass": dataArray[:, 3],
}

zones.append(TecplotOrderedZone(loc, data))

Check warning on line 526 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L526

Added line #L526 was not covered by tests

# Create the path with the .dat extension
filePath = Path(filename).with_suffix(".dat")

Check warning on line 529 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L529

Added line #L529 was not covered by tests

writeTecplot(

Check warning on line 531 in baseclasses/problems/pyWeight_problem.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/problems/pyWeight_problem.py#L531

Added line #L531 was not covered by tests
filePath,
title=f"{self.name}: Mass Data",
zones=zones,
datapacking="POINT",
precision="SINGLE",
)

def writeProblemData(self, fileName):
"""
Expand Down
35 changes: 18 additions & 17 deletions baseclasses/solvers/pyAero_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
# Extension modules
# =============================================================================
from .BaseSolver import BaseSolver
from ..utils import CaseInsensitiveDict, Error
from ..utils import CaseInsensitiveDict, Error, TecplotFEZone, writeTecplot
from ..utils.tecplotIO import ZoneType

# =============================================================================
# AeroSolver Class
# =============================================================================


class AeroSolver(BaseSolver):

"""
Abstract Class for Aerodynamic Solver Object
"""
Expand Down Expand Up @@ -207,24 +207,25 @@
"""
[p0, v1, v2] = self.getTriangulatedMeshSurface(groupName, **kwargs)
if self.comm.rank == 0:
f = open(fileName, "w")
f.write('TITLE = "%s Surface Mesh"\n' % self.name)
f.write('VARIABLES = "CoordinateX" "CoordinateY" "CoordinateZ"\n')
f.write("Zone T=%s\n" % ("surf"))
f.write("Nodes = %d, Elements = %d ZONETYPE=FETRIANGLE\n" % (len(p0) * 3, len(p0)))
f.write("DATAPACKING=POINT\n")
for i in range(len(p0)):
points = []
points.append(p0[i])
points.append(p0[i] + v1[i])
points.append(p0[i] + v2[i])
for i in range(len(points)):
f.write(f"{points[i][0]:f} {points[i][1]:f} {points[i][2]:f}\n")
dataArray = np.zeros((len(p0) * 3, 3), dtype=float)
dataArray[::3] = p0
dataArray[1::3] = p0 + v1
dataArray[2::3] = p0 + v2
data = {"CoordinateX": dataArray[:, 0], "CoordinateY": dataArray[:, 1], "CoordinateZ": dataArray[:, 2]}

Check warning on line 214 in baseclasses/solvers/pyAero_solver.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/solvers/pyAero_solver.py#L210-L214

Added lines #L210 - L214 were not covered by tests

conn = np.zeros((len(p0), 3), dtype=int)

Check warning on line 216 in baseclasses/solvers/pyAero_solver.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/solvers/pyAero_solver.py#L216

Added line #L216 was not covered by tests
for i in range(len(p0)):
f.write("%d %d %d\n" % (3 * i + 1, 3 * i + 2, 3 * i + 3))
conn[i, :] = [3 * i + 1, 3 * i + 2, 3 * i + 3]

Check warning on line 218 in baseclasses/solvers/pyAero_solver.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/solvers/pyAero_solver.py#L218

Added line #L218 was not covered by tests

f.close()
zones = [TecplotFEZone("surf", data, conn, zoneType=ZoneType.FETRIANGLE)]

Check warning on line 220 in baseclasses/solvers/pyAero_solver.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/solvers/pyAero_solver.py#L220

Added line #L220 was not covered by tests

writeTecplot(

Check warning on line 222 in baseclasses/solvers/pyAero_solver.py

View check run for this annotation

Codecov / codecov/patch

baseclasses/solvers/pyAero_solver.py#L222

Added line #L222 was not covered by tests
fileName,
title=f"{self.name} Surface Mesh",
zones=zones,
datapacking="POINT",
precision="SINGLE",
)

def checkSolutionFailure(self, aeroProblem, funcs):
"""Take in a an aeroProblem and check for failure. Then append the
Expand Down
12 changes: 9 additions & 3 deletions baseclasses/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from .containers import CaseInsensitiveSet, CaseInsensitiveDict
from .containers import CaseInsensitiveDict, CaseInsensitiveSet
from .error import Error
from .utils import getPy3SafeString, pp, ParseStringFormat
from .fileIO import writeJSON, readJSON, writePickle, readPickle, redirectIO, redirectingIO
from .fileIO import readJSON, readPickle, redirectingIO, redirectIO, writeJSON, writePickle
from .solverHistory import SolverHistory
from .tecplotIO import TecplotFEZone, TecplotOrderedZone, TecplotZone, readTecplot, writeTecplot
from .utils import ParseStringFormat, getPy3SafeString, pp

__all__ = [
"CaseInsensitiveSet",
Expand All @@ -17,5 +18,10 @@
"redirectIO",
"redirectingIO",
"SolverHistory",
"TecplotZone",
"TecplotFEZone",
"TecplotOrderedZone",
"writeTecplot",
"readTecplot",
"ParseStringFormat",
]
Loading