From 8ebf48deefbee52560197721d02d7f2cc8408c15 Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Tue, 30 Mar 2021 13:34:55 -0400 Subject: [PATCH 01/18] black format --- examples/bwb/bwb.py | 66 +- examples/c172_wing/c172.py | 147 +- pygeo/DVConstraints.py | 3156 ++++++++++++++----------- pygeo/DVGeometry.py | 1467 ++++++------ pygeo/DVGeometryAxi.py | 137 +- pygeo/DVGeometryESP.py | 688 +++--- pygeo/DVGeometryVSP.py | 3 +- pygeo/__init__.py | 4 +- pygeo/geo_utils.py | 2276 +++++++++--------- pygeo/pyBlock.py | 462 ++-- pygeo/pyGeo.py | 636 ++--- pygeo/pyNetwork.py | 90 +- setup.py | 52 +- tests/inputFiles/generateFFD.py | 161 +- tests/inputFiles/generatec172FFD.py | 2 +- tests/inputFiles/generaterectFFD.py | 2 +- tests/reg_tests/commonUtils.py | 232 +- tests/reg_tests/test_Blocks.py | 211 +- tests/reg_tests/test_Cylinder.py | 76 +- tests/reg_tests/test_DVConstraints.py | 650 ++--- tests/reg_tests/test_DVGeometry.py | 726 +++--- tests/reg_tests/test_DVGeometryESP.py | 507 ++-- tests/reg_tests/test_DVGeometryVSP.py | 73 +- 23 files changed, 6307 insertions(+), 5517 deletions(-) diff --git a/examples/bwb/bwb.py b/examples/bwb/bwb.py index d9bdbdda..d85bf8b8 100644 --- a/examples/bwb/bwb.py +++ b/examples/bwb/bwb.py @@ -6,31 +6,31 @@ # Start of Script # ============================================================================== naf = 20 -n0012 = 'naca0012.dat' +n0012 = "naca0012.dat" airfoil_list = [n0012 for i in range(naf)] -for i in range(1,naf-1): +for i in range(1, naf - 1): airfoil_list[i] = None # Use the digitize it data for the planform: -le = numpy.array(numpy.loadtxt('bwb_le.out')) -te = numpy.array(numpy.loadtxt('bwb_te.out')) -front_up = numpy.array(numpy.loadtxt('bwb_front_up.out')) -front_low = numpy.array(numpy.loadtxt('bwb_front_low.out')) +le = numpy.array(numpy.loadtxt("bwb_le.out")) +te = numpy.array(numpy.loadtxt("bwb_te.out")) +front_up = numpy.array(numpy.loadtxt("bwb_front_up.out")) +front_low = numpy.array(numpy.loadtxt("bwb_front_low.out")) -le[0,:] = 0 -te[0,0] = 0 -front_up[0,0] = 0 -front_low[0,0] = 0 +le[0, :] = 0 +te[0, 0] = 0 +front_up[0, 0] = 0 +front_low[0, 0] = 0 # Now make a ONE-DIMENSIONAL spline for each of the le and trailing edes -le_spline = pySpline.curve(X=le[:,1],s=le[:,0], nCtl=11, k=4) -te_spline = pySpline.curve(X=te[:,1],s=te[:,0], nCtl=11, k=4) -up_spline = pySpline.curve(X=front_up[:,1],s=front_up[:,0], nCtl=11, k=4) -low_spline = pySpline.curve(X=front_low[:,1],s=front_low[:,0], nCtl=11, k=4) +le_spline = pySpline.curve(X=le[:, 1], s=le[:, 0], nCtl=11, k=4) +te_spline = pySpline.curve(X=te[:, 1], s=te[:, 0], nCtl=11, k=4) +up_spline = pySpline.curve(X=front_up[:, 1], s=front_up[:, 0], nCtl=11, k=4) +low_spline = pySpline.curve(X=front_low[:, 1], s=front_low[:, 0], nCtl=11, k=4) # Generate consistent equally spaced spline data -span = numpy.linspace(0,1,naf) +span = numpy.linspace(0, 1, naf) le = le_spline(span) te = te_spline(span) @@ -38,27 +38,33 @@ low = low_spline(span) ref_span = 138 -chord = te-le +chord = te - le x = le -z = span*ref_span -mid_y = (up[0]+low[0])/2.0 -y = -(up+low)/2 + mid_y +z = span * ref_span +mid_y = (up[0] + low[0]) / 2.0 +y = -(up + low) / 2 + mid_y # Scale the thicknesses -toc = -(up-low)/chord -thickness = toc/0.12 +toc = -(up - low) / chord +thickness = toc / 0.12 rot_x = numpy.zeros(naf) rot_y = numpy.zeros(naf) rot_z = numpy.zeros(naf) -offset = numpy.zeros((naf,2)) +offset = numpy.zeros((naf, 2)) -bwb = pyGeo('liftingSurface', - xsections=airfoil_list, - scale=chord, offset=offset, - thickness=thickness, - bluntTe=True, teHeight=0.05, - tip='rounded', - x=x,y=y,z=z) +bwb = pyGeo( + "liftingSurface", + xsections=airfoil_list, + scale=chord, + offset=offset, + thickness=thickness, + bluntTe=True, + teHeight=0.05, + tip="rounded", + x=x, + y=y, + z=z, +) -bwb.writeIGES('bwb.igs') +bwb.writeIGES("bwb.igs") diff --git a/examples/c172_wing/c172.py b/examples/c172_wing/c172.py index 85b70d0f..63b59fed 100644 --- a/examples/c172_wing/c172.py +++ b/examples/c172_wing/c172.py @@ -5,52 +5,80 @@ # Start of Script # ============================================================================== naf = 3 -airfoil_list = ['naca2412.dat','naca2412.dat','naca2412.dat'] -chord = [1.67,1.67,1.18] -x = [0,0,.125*1.18] -y = [0,0,0] -z = [0,2.5,10.58/2] -rot_x = [0,0,0] -rot_y = [0,0,0] -rot_z = [0,0,2] -offset = numpy.zeros((naf,2)) +airfoil_list = ["naca2412.dat", "naca2412.dat", "naca2412.dat"] +chord = [1.67, 1.67, 1.18] +x = [0, 0, 0.125 * 1.18] +y = [0, 0, 0] +z = [0, 2.5, 10.58 / 2] +rot_x = [0, 0, 0] +rot_y = [0, 0, 0] +rot_z = [0, 0, 2] +offset = numpy.zeros((naf, 2)) # There are several examples that follow showing many of the different # combinations of tip/trailing edge options that are available. # --------- Sharp Trailing Edge / Rounded Tip ------- -wing = pyGeo('liftingSurface', - xsections=airfoil_list, - scale=chord, offset=offset, x=x, y=y, z=z, - rotX=rot_x, rotY=rot_y, rotZ=rot_z, - kSpan=2, tip='rounded') +wing = pyGeo( + "liftingSurface", + xsections=airfoil_list, + scale=chord, + offset=offset, + x=x, + y=y, + z=z, + rotX=rot_x, + rotY=rot_y, + rotZ=rot_z, + kSpan=2, + tip="rounded", +) -wing.writeTecplot('c172_sharp_te_rounded_tip.dat') -wing.writeIGES('c172_sharp_te_rounded_tip.igs') +wing.writeTecplot("c172_sharp_te_rounded_tip.dat") +wing.writeIGES("c172_sharp_te_rounded_tip.igs") # --------- Sharp Trailing Edge / Pinched Tip ------- -wing = pyGeo('liftingSurface', - xsections=airfoil_list, - scale=chord, offset=offset, x=x, y=y, z=z, - rotX=rot_x, rotY=rot_y, rotZ=rot_z, - kSpan=2, tip='pinched') +wing = pyGeo( + "liftingSurface", + xsections=airfoil_list, + scale=chord, + offset=offset, + x=x, + y=y, + z=z, + rotX=rot_x, + rotY=rot_y, + rotZ=rot_z, + kSpan=2, + tip="pinched", +) -wing.writeTecplot('c172_sharp_te_pinched_tip.dat') -wing.writeIGES('c172_sharp_te_pinched_tip.igs') +wing.writeTecplot("c172_sharp_te_pinched_tip.dat") +wing.writeIGES("c172_sharp_te_pinched_tip.igs") # --------- Sharp Trailing Edge / Rounded Tip with Fitting ------- # This option shouldn't be used except to match previously generated # geometries -wing = pyGeo('liftingSurface', - xsections=airfoil_list, nCtl=29, - scale=chord, offset=offset, x=x, y=y, z=z, - rotX=rot_x, rotY=rot_y, rotZ=rot_z, - kSpan=2, tip='rounded') +wing = pyGeo( + "liftingSurface", + xsections=airfoil_list, + nCtl=29, + scale=chord, + offset=offset, + x=x, + y=y, + z=z, + rotX=rot_x, + rotY=rot_y, + rotZ=rot_z, + kSpan=2, + tip="rounded", +) -wing.writeTecplot('c172_sharp_te_rounded_tip_fitted.dat') -wing.writeIGES('c172_sharp_te_rounded_tip_fitted.igs') +wing.writeTecplot("c172_sharp_te_rounded_tip_fitted.dat") +wing.writeIGES("c172_sharp_te_rounded_tip_fitted.igs") -# --------- Blunt Trailing (Flat) / Rounded Tip ------- +# --------- Blunt Trailing (Flat) / Rounded Tip ------- # This is the normal way of producing blunt TE geometries. The # thickness of the trailing edge is specified with 'te_height', either @@ -59,26 +87,47 @@ # scaled thickness. This option is specified as a fraction of initial # chord, so te_height_scaled=0.002 will give a 0.2% trailing edge # thickness -wing = pyGeo('liftingSurface', - xsections=airfoil_list, - scale=chord, offset=offset, x=x, y=y, z=z, - rotX=rot_x, rotY=rot_y, rotZ=rot_z, - bluntTe=True, teHeightScaled=0.002, - kSpan=2, tip='rounded') +wing = pyGeo( + "liftingSurface", + xsections=airfoil_list, + scale=chord, + offset=offset, + x=x, + y=y, + z=z, + rotX=rot_x, + rotY=rot_y, + rotZ=rot_z, + bluntTe=True, + teHeightScaled=0.002, + kSpan=2, + tip="rounded", +) -wing.writeTecplot('c172_blunt_te_rounded_tip.dat') -wing.writeIGES('c172_blunt_te_rounded_tip.igs') +wing.writeTecplot("c172_blunt_te_rounded_tip.dat") +wing.writeIGES("c172_blunt_te_rounded_tip.igs") -# --------- Blunt Trailing (Rounded) / Rounded Tip ------- +# --------- Blunt Trailing (Rounded) / Rounded Tip ------- # Alternative way of producing rounded trailing edges that can be easier -# to mesh and extrude with pyHyp. -wing = pyGeo('liftingSurface', - xsections=airfoil_list, - scale=chord, offset=offset, x=x, y=y, z=z, - rotX=rot_x, rotY=rot_y, rotZ=rot_z, - bluntTe=True, roundedTe=True, teHeightScaled=0.002, - kSpan=2, tip='rounded') +# to mesh and extrude with pyHyp. +wing = pyGeo( + "liftingSurface", + xsections=airfoil_list, + scale=chord, + offset=offset, + x=x, + y=y, + z=z, + rotX=rot_x, + rotY=rot_y, + rotZ=rot_z, + bluntTe=True, + roundedTe=True, + teHeightScaled=0.002, + kSpan=2, + tip="rounded", +) -wing.writeTecplot('c172_rounded_te_rounded_tip.dat') -wing.writeIGES('c172_rounded_te_rounded_tip.igs') +wing.writeTecplot("c172_rounded_te_rounded_tip.dat") +wing.writeIGES("c172_rounded_te_rounded_tip.igs") diff --git a/pygeo/DVConstraints.py b/pygeo/DVConstraints.py index c483aeb8..84201d22 100644 --- a/pygeo/DVConstraints.py +++ b/pygeo/DVConstraints.py @@ -1,63 +1,69 @@ # ====================================================================== # Imports # ====================================================================== -import numpy,copy +import numpy, copy from . import geo_utils, pyGeo from pyspline import pySpline from mpi4py import MPI from scipy.sparse import csr_matrix import numpy as np + try: from collections import OrderedDict except ImportError: try: from ordereddict import OrderedDict except ImportError: - print("Could not find any OrderedDict class. For 2.6 and earlier, " - "use:\n pip install ordereddict") + print("Could not find any OrderedDict class. For 2.6 and earlier, " "use:\n pip install ordereddict") + class Error(Exception): """ Format the error message in a box to make it clear this was a expliclty raised exception. """ + def __init__(self, message): - msg = '\n+'+'-'*78+'+'+'\n' + '| DVCon Error: ' + msg = "\n+" + "-" * 78 + "+" + "\n" + "| DVCon Error: " i = 14 for word in message.split(): - if len(word) + i + 1 > 78: # Finish line and start new one - msg += ' '*(78-i)+'|\n| ' + word + ' ' - i = 1 + len(word)+1 + if len(word) + i + 1 > 78: # Finish line and start new one + msg += " " * (78 - i) + "|\n| " + word + " " + i = 1 + len(word) + 1 else: - msg += word + ' ' - i += len(word)+1 - msg += ' '*(78-i) + '|\n' + '+'+'-'*78+'+'+'\n' + msg += word + " " + i += len(word) + 1 + msg += " " * (78 - i) + "|\n" + "+" + "-" * 78 + "+" + "\n" print(msg) Exception.__init__(self) + class Warning(object): """ Format a warning message """ + def __init__(self, message): - msg = '\n+'+'-'*78+'+'+'\n' + '| DVConstraints Warning: ' + msg = "\n+" + "-" * 78 + "+" + "\n" + "| DVConstraints Warning: " i = 24 for word in message.split(): - if len(word) + i + 1 > 78: # Finish line and start new one - msg += ' '*(78-i)+'|\n| ' + word + ' ' - i = 1 + len(word)+1 + if len(word) + i + 1 > 78: # Finish line and start new one + msg += " " * (78 - i) + "|\n| " + word + " " + i = 1 + len(word) + 1 else: - msg += word + ' ' - i += len(word)+1 - msg += ' '*(78-i) + '|\n' + '+'+'-'*78+'+'+'\n' + msg += word + " " + i += len(word) + 1 + msg += " " * (78 - i) + "|\n" + "+" + "-" * 78 + "+" + "\n" print(msg) + class GeometricConstraint(object): """ This is a generic base class for all of the geometric constraints. """ - def __init__(self,name, nCon, lower, upper, scale, DVGeo, addToPyOpt): + + def __init__(self, name, nCon, lower, upper, scale, DVGeo, addToPyOpt): """ General init function. Every constraint has these functions """ @@ -71,7 +77,7 @@ def __init__(self,name, nCon, lower, upper, scale, DVGeo, addToPyOpt): return - def setDesignVars(self,x): + def setDesignVars(self, x): """ take in the design var vector from pyopt and set the variables for this constraint This function is constraint specific, so the baseclass doesn't implement anything. @@ -115,9 +121,9 @@ def addConstraintsPyOpt(self, optProb): Add the constraints to pyOpt, if the flag is set """ if self.addToPyOpt: - optProb.addConGroup(self.name, self.nCon, lower=self.lower, - upper=self.upper, scale=self.scale, - wrt=self.getVarNames()) + optProb.addConGroup( + self.name, self.nCon, lower=self.lower, upper=self.upper, scale=self.scale, wrt=self.getVarNames() + ) def addVariablesPyOpt(self, optProb): """ @@ -181,7 +187,7 @@ class DVConstraints(object): """ - def __init__(self,name='DVCon1'): + def __init__(self, name="DVCon1"): """ Create a (empty) DVconstrains object. Specific types of constraints will added individually @@ -197,7 +203,7 @@ def __init__(self,name='DVCon1'): self.surfaces = {} self.DVGeometries = {} - def setSurface(self, surf, name='default', addToDVGeo=False, DVGeoName='default', format='point-vector'): + def setSurface(self, surf, name="default", addToDVGeo=False, DVGeoName="default", format="point-vector"): """ Set the surface DVConstraints will use to perform projections. @@ -238,10 +244,10 @@ def setSurface(self, surf, name='default', addToDVGeo=False, DVGeoName='default' """ if name in self.surfaces.keys(): - raise KeyError('Surface names must be unique. Repeated surface name: ' + str(name)) + raise KeyError("Surface names must be unique. Repeated surface name: " + str(name)) self.surfaces[name] = list() - if format == 'point-vector': + if format == "point-vector": if type(surf) == list: # Data from ADflow p0 = numpy.array(surf[0]) @@ -251,14 +257,14 @@ def setSurface(self, surf, name='default', addToDVGeo=False, DVGeoName='default' # Load the surf as a plot3d file p0, v1, v2 = self._readPlot3DSurfFile(surf) - elif isinstance(surf, pyGeo): # Assume it's a pyGeo surface + elif isinstance(surf, pyGeo): # Assume it's a pyGeo surface p0, v1, v2 = self._generateDiscreteSurface(surf) else: - raise TypeError('surf given is not a supported type [List, plot3D file name, or pyGeo surface]') + raise TypeError("surf given is not a supported type [List, plot3D file name, or pyGeo surface]") p1 = p0 + v1 p2 = p0 + v2 - elif format == 'point-point': + elif format == "point-point": if type(surf) == str: # load from file raise NotImplementedError @@ -268,25 +274,24 @@ def setSurface(self, surf, name='default', addToDVGeo=False, DVGeoName='default' p1 = numpy.array(surf[1]) p2 = numpy.array(surf[2]) elif type(surf) == numpy.ndarray: - surf_length = surf[:,0,:].shape[0] - p0 = surf[:,0,:].reshape(surf_length, 3) - p1 = surf[:,1,:].reshape(surf_length, 3) - p2 = surf[:,2,:].reshape(surf_length, 3) + surf_length = surf[:, 0, :].shape[0] + p0 = surf[:, 0, :].reshape(surf_length, 3) + p1 = surf[:, 1, :].reshape(surf_length, 3) + p2 = surf[:, 2, :].reshape(surf_length, 3) else: - raise TypeError('surf given is not supported [list, numpy.ndarray]') + raise TypeError("surf given is not supported [list, numpy.ndarray]") self.surfaces[name].append(p0) self.surfaces[name].append(p1) self.surfaces[name].append(p2) - if addToDVGeo: self._checkDVGeo(name=DVGeoName) - self.DVGeometries[DVGeoName].addPointSet(self.surfaces[name][0], name + '_p0') - self.DVGeometries[DVGeoName].addPointSet(self.surfaces[name][1], name + '_p1') - self.DVGeometries[DVGeoName].addPointSet(self.surfaces[name][2], name + '_p2') + self.DVGeometries[DVGeoName].addPointSet(self.surfaces[name][0], name + "_p0") + self.DVGeometries[DVGeoName].addPointSet(self.surfaces[name][1], name + "_p1") + self.DVGeometries[DVGeoName].addPointSet(self.surfaces[name][2], name + "_p2") - def setDVGeo(self, DVGeo, name='default'): + def setDVGeo(self, DVGeo, name="default"): """ Set the DVGeometry object that will manipulate this object. Note that DVConstraints doesn't **strictly** need a DVGeometry @@ -310,12 +315,13 @@ def setDVGeo(self, DVGeo, name='default'): for dvname in DVGeo.getVarNames(): for existing_dvname in existing_DVGeo.getVarNames(): if dvname == existing_dvname: - msg = f"Design variable {dvname} in the newly-added DVGeo already exists in DVGeo" \ - f"object named {existing_DVGeo_name} on this DVCon" + msg = ( + f"Design variable {dvname} in the newly-added DVGeo already exists in DVGeo" + f"object named {existing_DVGeo_name} on this DVCon" + ) raise ValueError(msg) self.DVGeometries[name] = DVGeo - def addConstraintsPyOpt(self, optProb): """ Add all constraints to the optProb object. Only constraints @@ -377,7 +383,7 @@ def setDesignVars(self, dvDict): Dictionary of design variables. The keys of the dictionary must correspond to the design variable names. Any additional keys in the dfvdictionary are simply ignored. - """ + """ # loop over the generated constraint objects and add the necessary # variables to pyopt @@ -456,9 +462,9 @@ def writeTecplot(self, fileName): .dat extension will be added automatically. """ - f = open(fileName, 'w') - f.write("TITLE = \"DVConstraints Data\"\n") - f.write("VARIABLES = \"CoordinateX\" \"CoordinateY\" \"CoordinateZ\"\n") + f = open(fileName, "w") + f.write('TITLE = "DVConstraints Data"\n') + f.write('VARIABLES = "CoordinateX" "CoordinateY" "CoordinateZ"\n') # loop over the constraints and add their data to the tecplot file for conTypeKey in self.constraints: @@ -470,7 +476,7 @@ def writeTecplot(self, fileName): self.linearCon[key].writeTecplot(f) f.close() - def writeSurfaceTecplot(self,fileName,surfaceName='default'): + def writeSurfaceTecplot(self, fileName, surfaceName="default"): """ Write the triangulated surface mesh used in the constraint object to a tecplot file for visualization. @@ -484,27 +490,26 @@ def writeSurfaceTecplot(self,fileName,surfaceName='default'): """ p0, p1, p2 = self._getSurfaceVertices(surfaceName=surfaceName) - f = open(fileName, 'w') - f.write("TITLE = \"DVConstraints 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(p0)*3, len(p0))) - f.write('DATAPACKING=POINT\n') + f = open(fileName, "w") + f.write('TITLE = "DVConstraints 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(p0) * 3, len(p0))) + f.write("DATAPACKING=POINT\n") for i in range(len(p0)): points = [] points.append(p0[i]) points.append(p1[i]) points.append(p2[i]) for i in range(len(points)): - f.write('%f %f %f\n'% (points[i][0], points[i][1],points[i][2])) + f.write("%f %f %f\n" % (points[i][0], points[i][1], points[i][2])) for i in range(len(p0)): - f.write('%d %d %d\n'% (3*i+1, 3*i+2,3*i+3)) + f.write("%d %d %d\n" % (3 * i + 1, 3 * i + 2, 3 * i + 3)) f.close() - def writeSurfaceSTL(self,fileName,surfaceName='default',fromDVGeo=None): + def writeSurfaceSTL(self, fileName, surfaceName="default", fromDVGeo=None): """ Write the triangulated surface mesh to a .STL file for manipulation and visualization. @@ -518,28 +523,41 @@ def writeSurfaceSTL(self,fileName,surfaceName='default',fromDVGeo=None): Name of the DVGeo object to obtain the surface from (default is 'None') """ import numpy as np + try: from stl import mesh except: - raise ImportError('numpy-stl package must be installed') + raise ImportError("numpy-stl package must be installed") if fromDVGeo is None: p0, p1, p2 = self._getSurfaceVertices(surfaceName=surfaceName) else: - p0 = self.DVGeometries[fromDVGeo].update(surfaceName+'_p0') - p1 = self.DVGeometries[fromDVGeo].update(surfaceName+'_p1') - p2 = self.DVGeometries[fromDVGeo].update(surfaceName+'_p2') + p0 = self.DVGeometries[fromDVGeo].update(surfaceName + "_p0") + p1 = self.DVGeometries[fromDVGeo].update(surfaceName + "_p1") + p2 = self.DVGeometries[fromDVGeo].update(surfaceName + "_p2") stlmesh = mesh.Mesh(np.zeros(p0.shape[0], dtype=mesh.Mesh.dtype)) - stlmesh.vectors[:,0,:] = p0 - stlmesh.vectors[:,1,:] = p1 - stlmesh.vectors[:,2,:] = p2 + stlmesh.vectors[:, 0, :] = p0 + stlmesh.vectors[:, 1, :] = p1 + stlmesh.vectors[:, 2, :] = p2 # Write the mesh to file "cube.stl" stlmesh.save(fileName) - def addThicknessConstraints2D(self, leList, teList, nSpan, nChord, - lower=1.0, upper=3.0, scaled=True, scale=1.0, - name=None, addToPyOpt=True, surfaceName='default', DVGeoName='default'): + def addThicknessConstraints2D( + self, + leList, + teList, + nSpan, + nChord, + lower=1.0, + upper=3.0, + scaled=True, + scale=1.0, + name=None, + addToPyOpt=True, + surfaceName="default", + DVGeoName="default", + ): """ Add a set of thickness constraints that span a logically a two-dimensional region. A little ASCII art can help here @@ -689,26 +707,35 @@ def addThicknessConstraints2D(self, leList, teList, nSpan, nChord, coords = self._generateIntersections(leList, teList, nSpan, nChord, surfaceName) # Create the thickness constraint object: - coords = coords.reshape((nSpan*nChord*2, 3)) + coords = coords.reshape((nSpan * nChord * 2, 3)) - typeName = 'thickCon' + typeName = "thickCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() # Create a name if name is None: - conName = '%s_thickness_constraints_%d'%(self.name, len(self.constraints[typeName])) + conName = "%s_thickness_constraints_%d" % (self.name, len(self.constraints[typeName])) else: conName = name self.constraints[typeName][conName] = ThicknessConstraint( - conName, coords, lower, upper, scaled, scale, self.DVGeometries[DVGeoName], - addToPyOpt) - - - def addThicknessConstraints1D(self, ptList, nCon, axis, - lower=1.0, upper=3.0, scaled=True, - scale=1.0, name=None, addToPyOpt=True, - surfaceName='default', DVGeoName='default'): + conName, coords, lower, upper, scaled, scale, self.DVGeometries[DVGeoName], addToPyOpt + ) + + def addThicknessConstraints1D( + self, + ptList, + nCon, + axis, + lower=1.0, + upper=3.0, + scaled=True, + scale=1.0, + name=None, + addToPyOpt=True, + surfaceName="default", + DVGeoName="default", + ): """ Add a set of thickness constraints oriented along a poly-line. @@ -813,34 +840,45 @@ def addThicknessConstraints1D(self, ptList, nCon, axis, # Project all the points for i in range(nCon): # Project actual node: - up, down, fail = geo_utils.projectNode( - X[i], axis, p0, p1-p0, p2-p0) + up, down, fail = geo_utils.projectNode(X[i], axis, p0, p1 - p0, p2 - p0) if fail > 0: - raise Error("There was an error projecting a node " - "at (%f, %f, %f) with normal (%f, %f, %f)."% ( - X[i, 0], X[i, 1], X[i, 2], axis[0], axis[1], axis[2])) + raise Error( + "There was an error projecting a node " + "at (%f, %f, %f) with normal (%f, %f, %f)." % (X[i, 0], X[i, 1], X[i, 2], axis[0], axis[1], axis[2]) + ) coords[i, 0] = up coords[i, 1] = down # Create the thickness constraint object: - coords = coords.reshape((nCon*2, 3)) + coords = coords.reshape((nCon * 2, 3)) - typeName = 'thickCon' + typeName = "thickCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: - conName = '%s_thickness_constraints_%d'%(self.name,len(self.constraints[typeName])) + conName = "%s_thickness_constraints_%d" % (self.name, len(self.constraints[typeName])) else: conName = name self.constraints[typeName][conName] = ThicknessConstraint( - conName, coords, lower, upper, scaled, scale, self.DVGeometries[DVGeoName], - addToPyOpt) - - def addLERadiusConstraints(self, leList, nSpan, axis, chordDir, - lower=1.0, upper=3.0, scaled=True, - scale=1.0, name=None, addToPyOpt=True, - surfaceName='default', DVGeoName='default'): + conName, coords, lower, upper, scaled, scale, self.DVGeometries[DVGeoName], addToPyOpt + ) + + def addLERadiusConstraints( + self, + leList, + nSpan, + axis, + chordDir, + lower=1.0, + upper=3.0, + scaled=True, + scale=1.0, + name=None, + addToPyOpt=True, + surfaceName="default", + DVGeoName="default", + ): """ Add a set of leading edge radius constraints. The constraint is set up similar to the 1D thickness or thickness-to-chord constraints. The user @@ -958,64 +996,73 @@ def addLERadiusConstraints(self, leList, nSpan, axis, chordDir, # Project all the points for i in range(nSpan): # Project actual node: - up, down, fail = geo_utils.projectNode( - X[i], axis, p0, p1-p0, p2-p0) + up, down, fail = geo_utils.projectNode(X[i], axis, p0, p1 - p0, p2 - p0) if fail > 0: - raise Error("There was an error projecting a node " - "at (%f, %f, %f) with normal (%f, %f, %f)."% ( - X[i, 0], X[i, 1], X[i, 2], - axis[0], axis[1], axis[2])) + raise Error( + "There was an error projecting a node " + "at (%f, %f, %f) with normal (%f, %f, %f)." % (X[i, 0], X[i, 1], X[i, 2], axis[0], axis[1], axis[2]) + ) coords[i, 0] = up coords[i, 1] = down # Calculate mid-points - midPts = (coords[:,0,:] + coords[:,1,:]) / 2.0 + midPts = (coords[:, 0, :] + coords[:, 1, :]) / 2.0 # Project to get leading edge point lePts = numpy.zeros((nSpan, 3)) - chordDir = numpy.array(chordDir, dtype='d').flatten() + chordDir = numpy.array(chordDir, dtype="d").flatten() chordDir /= numpy.linalg.norm(chordDir) for i in range(nSpan): # Project actual node: - up, down, fail = geo_utils.projectNode( - X[i], chordDir, p0, p1-p0, p2-p0) + up, down, fail = geo_utils.projectNode(X[i], chordDir, p0, p1 - p0, p2 - p0) if fail > 0: - raise Error("There was an error projecting a node " - "at (%f, %f, %f) with normal (%f, %f, %f)."% ( - X[i, 0], X[i, 1], X[i, 2], - chordDir[0], chordDir[1], chordDir[2])) + raise Error( + "There was an error projecting a node " + "at (%f, %f, %f) with normal (%f, %f, %f)." + % (X[i, 0], X[i, 1], X[i, 2], chordDir[0], chordDir[1], chordDir[2]) + ) lePts[i] = up # Check that points can form radius - d = numpy.linalg.norm(coords[:,0,:] - coords[:,1,:], axis=1) + d = numpy.linalg.norm(coords[:, 0, :] - coords[:, 1, :], axis=1) r = numpy.linalg.norm(midPts - lePts, axis=1) for i in range(nSpan): - if d[i] < 2*r[i]: - raise Error("Leading edge radius points are too far from the " - "leading edge point to form a circle between the " - "three points.") + if d[i] < 2 * r[i]: + raise Error( + "Leading edge radius points are too far from the " + "leading edge point to form a circle between the " + "three points." + ) # Add leading edge points and stack points into shape accepted by DVGeo - coords[:,2,:] = lePts - coords = numpy.vstack((coords[:,0,:], coords[:,1,:], coords[:,2,:])) + coords[:, 2, :] = lePts + coords = numpy.vstack((coords[:, 0, :], coords[:, 1, :], coords[:, 2, :])) # Create the thickness constraint object - typeName = 'radiusCon' + typeName = "radiusCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: - conName = '%s_leradius_constraints_%d'%(self.name,len(self.constraints[typeName])) + conName = "%s_leradius_constraints_%d" % (self.name, len(self.constraints[typeName])) else: conName = name self.constraints[typeName][conName] = RadiusConstraint( - conName, coords, lower, upper, scaled, scale, self.DVGeometries[DVGeoName], - addToPyOpt) - - - def addLocationConstraints1D(self, ptList, nCon,lower=None, upper=None, - scaled=False, scale=1.0, name=None, - addToPyOpt=True, DVGeoName='default'): + conName, coords, lower, upper, scaled, scale, self.DVGeometries[DVGeoName], addToPyOpt + ) + + def addLocationConstraints1D( + self, + ptList, + nCon, + lower=None, + upper=None, + scaled=False, + scale=1.0, + name=None, + addToPyOpt=True, + DVGeoName="default", + ): """ Add a polyline in space that cannot move. @@ -1096,23 +1143,33 @@ def addLocationConstraints1D(self, ptList, nCon,lower=None, upper=None, upper = X.flatten() # Create the location constraint object - typeName = 'locCon' + typeName = "locCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: - conName = '%s_location_constraints_%d'%(self.name,len(self.constraints[typeName])) + conName = "%s_location_constraints_%d" % (self.name, len(self.constraints[typeName])) else: conName = name self.constraints[typeName][conName] = LocationConstraint( - conName, X, lower, upper, scaled, scale, self.DVGeometries[DVGeoName], - addToPyOpt) - - - def addProjectedLocationConstraints1D(self, ptList, nCon, axis, bias=0.5, - lower=None, upper=None, - scaled=False, scale=1.0, name=None, addToPyOpt=True, - surfaceName='default', DVGeoName='default'): + conName, X, lower, upper, scaled, scale, self.DVGeometries[DVGeoName], addToPyOpt + ) + + def addProjectedLocationConstraints1D( + self, + ptList, + nCon, + axis, + bias=0.5, + lower=None, + upper=None, + scaled=False, + scale=1.0, + name=None, + addToPyOpt=True, + surfaceName="default", + DVGeoName="default", + ): """This is similar to addLocationConstraints1D except that the actual poly line is determined by first projecting points on to the @@ -1205,16 +1262,16 @@ def addProjectedLocationConstraints1D(self, ptList, nCon, axis, bias=0.5, # Project all the points for i in range(nCon): # Project actual node: - up, down, fail = geo_utils.projectNode( - X[i], axis, p0, p1-p0, p2-p0) + up, down, fail = geo_utils.projectNode(X[i], axis, p0, p1 - p0, p2 - p0) if fail > 0: - raise Error("There was an error projecting a node " - "at (%f, %f, %f) with normal (%f, %f, %f)."% ( - X[i, 0], X[i, 1], X[i, 2], axis[0], axis[1], axis[2])) + raise Error( + "There was an error projecting a node " + "at (%f, %f, %f) with normal (%f, %f, %f)." % (X[i, 0], X[i, 1], X[i, 2], axis[0], axis[1], axis[2]) + ) coords[i, 0] = up coords[i, 1] = down - X = (1-bias)*coords[:, 1] + bias*coords[:, 0] + X = (1 - bias) * coords[:, 1] + bias * coords[:, 0] # X is now what we want to constrain if lower is None: @@ -1223,23 +1280,32 @@ def addProjectedLocationConstraints1D(self, ptList, nCon, axis, bias=0.5, upper = X.flatten() # Create the location constraint object - typeName = 'locCon' + typeName = "locCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: - conName = '%s_location_constraints_%d'%(self.name, len(self.constraints[typeName])) + conName = "%s_location_constraints_%d" % (self.name, len(self.constraints[typeName])) else: conName = name self.constraints[typeName][conName] = LocationConstraint( - conName, X, lower, upper, scaled, scale, self.DVGeometries[DVGeoName], - addToPyOpt) - - def addThicknessToChordConstraints1D(self, ptList, nCon, axis, chordDir, - lower=1.0, upper=3.0, scale=1.0, - name=None, addToPyOpt=True, - surfaceName='default', - DVGeoName='default'): + conName, X, lower, upper, scaled, scale, self.DVGeometries[DVGeoName], addToPyOpt + ) + + def addThicknessToChordConstraints1D( + self, + ptList, + nCon, + axis, + chordDir, + lower=1.0, + upper=3.0, + scale=1.0, + name=None, + addToPyOpt=True, + surfaceName="default", + DVGeoName="default", + ): """ Add a set of thickness-to-chord ratio constraints oriented along a poly-line. @@ -1331,44 +1397,54 @@ def addThicknessToChordConstraints1D(self, ptList, nCon, axis, chordDir, s = numpy.linspace(0, 1, nCon) X = constr_line(s) coords = numpy.zeros((nCon, 4, 3)) - chordDir /= numpy.linalg.norm(numpy.array(chordDir, 'd')) + chordDir /= numpy.linalg.norm(numpy.array(chordDir, "d")) # Project all the points for i in range(nCon): # Project actual node: - up, down, fail = geo_utils.projectNode( - X[i], axis, p0, p1-p0, p2-p0) + up, down, fail = geo_utils.projectNode(X[i], axis, p0, p1 - p0, p2 - p0) if fail: - raise Error("There was an error projecting a node " - "at (%f, %f, %f) with normal (%f, %f, %f)." % ( - X[i, 0], X[i, 1], X[i, 2], axis[0], axis[1], axis[2])) + raise Error( + "There was an error projecting a node " + "at (%f, %f, %f) with normal (%f, %f, %f)." % (X[i, 0], X[i, 1], X[i, 2], axis[0], axis[1], axis[2]) + ) coords[i, 0] = up coords[i, 1] = down height = numpy.linalg.norm(coords[i, 0] - coords[i, 1]) # Third point is the mid-point of thsoe - coords[i, 2] = 0.5*(up + down) + coords[i, 2] = 0.5 * (up + down) # Fourth point is along the chordDir - coords[i, 3] = coords[i, 2] + 0.1*height*chordDir + coords[i, 3] = coords[i, 2] + 0.1 * height * chordDir # Create the thickness constraint object: - coords = coords.reshape((nCon*4, 3)) + coords = coords.reshape((nCon * 4, 3)) - typeName = 'thickCon' + typeName = "thickCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: - conName = '%s_thickness_to_chord_constraints_%d'%(self.name, len(self.constraints[typeName])) + conName = "%s_thickness_to_chord_constraints_%d" % (self.name, len(self.constraints[typeName])) else: conName = name self.constraints[typeName][conName] = ThicknessToChordConstraint( - conName, coords, lower, upper, scale, self.DVGeometries[DVGeoName], addToPyOpt) - - - def addTriangulatedSurfaceConstraint(self, surface_1_name=None, DVGeo_1_name='default', - surface_2_name='default', DVGeo_2_name='default', - rho=50., heuristic_dist=None, perim_scale=0.1, - max_perim=3.0, name=None, scale=1., addToPyOpt=True): + conName, coords, lower, upper, scale, self.DVGeometries[DVGeoName], addToPyOpt + ) + + def addTriangulatedSurfaceConstraint( + self, + surface_1_name=None, + DVGeo_1_name="default", + surface_2_name="default", + DVGeo_2_name="default", + rho=50.0, + heuristic_dist=None, + perim_scale=0.1, + max_perim=3.0, + name=None, + scale=1.0, + addToPyOpt=True, + ): """ Add a single triangulated surface constraint to an aerosurface. This constraint is designed to keep a general 'blob' of watertight @@ -1438,7 +1514,7 @@ def addTriangulatedSurfaceConstraint(self, surface_1_name=None, DVGeo_1_name='de try: import geograd except ImportError: - raise ImportError('Geograd package must be installed to use triangulated surface constraint') + raise ImportError("Geograd package must be installed to use triangulated surface constraint") if DVGeo_1_name is not None: self._checkDVGeo(DVGeo_1_name) DVGeo1 = self.DVGeometries[DVGeo_1_name] @@ -1450,14 +1526,14 @@ def addTriangulatedSurfaceConstraint(self, surface_1_name=None, DVGeo_1_name='de else: DVGeo2 = None if DVGeo1 is None and DVGeo2 is None: - raise UserError('At least one DVGeo object must be specified') + raise UserError("At least one DVGeo object must be specified") - typeName = 'triSurfCon' + typeName = "triSurfCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: - conName = '%s_trisurf_constraint_%d'%(self.name, len(self.constraints[typeName])) + conName = "%s_trisurf_constraint_%d" % (self.name, len(self.constraints[typeName])) else: conName = name @@ -1465,14 +1541,33 @@ def addTriangulatedSurfaceConstraint(self, surface_1_name=None, DVGeo_1_name='de surface_2 = self._getSurfaceVertices(surface_2_name) # Finally add constraint object - self.constraints[typeName][conName] = TriangulatedSurfaceConstraint(conName, - surface_1, surface_1_name, DVGeo1, - surface_2, surface_2_name, DVGeo2, scale, - addToPyOpt, rho, perim_scale, max_perim, heuristic_dist) - - def addTriangulatedVolumeConstraint(self, lower=1.0, upper=99999.0, scaled=True, scale=1.0, - name=None, surfaceName='default', DVGeoName='default', - addToPyOpt=True): + self.constraints[typeName][conName] = TriangulatedSurfaceConstraint( + conName, + surface_1, + surface_1_name, + DVGeo1, + surface_2, + surface_2_name, + DVGeo2, + scale, + addToPyOpt, + rho, + perim_scale, + max_perim, + heuristic_dist, + ) + + def addTriangulatedVolumeConstraint( + self, + lower=1.0, + upper=99999.0, + scaled=True, + scale=1.0, + name=None, + surfaceName="default", + DVGeoName="default", + addToPyOpt=True, + ): """ Add a single triangulated volume constraint to a surface. Computes and constrains the volume of a closed, triangulated surface. @@ -1542,26 +1637,37 @@ def addTriangulatedVolumeConstraint(self, lower=1.0, upper=99999.0, scaled=True, self._checkDVGeo(DVGeoName) DVGeo = self.DVGeometries[DVGeoName] - typeName = 'triVolCon' + typeName = "triVolCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: - conName = '%s_trivolume_constraint_%d'%(self.name, len(self.constraints[typeName])) + conName = "%s_trivolume_constraint_%d" % (self.name, len(self.constraints[typeName])) else: conName = name surface = self._getSurfaceVertices(surfaceName) # Finally add constraint object - self.constraints[typeName][conName] = TriangulatedVolumeConstraint(conName, - surface, surfaceName, lower, upper, - scaled, scale, DVGeo, addToPyOpt) - - def addVolumeConstraint(self, leList, teList, nSpan, nChord, - lower=1.0, upper=3.0, scaled=True, scale=1.0, - name=None, addToPyOpt=True, - surfaceName='default', DVGeoName='default'): + self.constraints[typeName][conName] = TriangulatedVolumeConstraint( + conName, surface, surfaceName, lower, upper, scaled, scale, DVGeo, addToPyOpt + ) + + def addVolumeConstraint( + self, + leList, + teList, + nSpan, + nChord, + lower=1.0, + upper=3.0, + scaled=True, + scale=1.0, + name=None, + addToPyOpt=True, + surfaceName="default", + DVGeoName="default", + ): """ Add a single volume constraint to the wing. The volume constraint is defined over a logically two-dimensional region @@ -1670,27 +1776,26 @@ def addVolumeConstraint(self, leList, teList, nSpan, nChord, """ self._checkDVGeo(DVGeoName) - typeName = 'volCon' + typeName = "volCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: - conName = '%s_volume_constraint_%d'%(self.name, len(self.constraints[typeName])) + conName = "%s_volume_constraint_%d" % (self.name, len(self.constraints[typeName])) else: conName = name coords = self._generateIntersections(leList, teList, nSpan, nChord, surfaceName) - coords = coords.reshape((nSpan*nChord*2, 3)) + coords = coords.reshape((nSpan * nChord * 2, 3)) # Finally add the volume constraint object self.constraints[typeName][conName] = VolumeConstraint( - conName, nSpan, nChord, coords, lower, upper, scaled, scale, - self.DVGeometries[DVGeoName], addToPyOpt) + conName, nSpan, nChord, coords, lower, upper, scaled, scale, self.DVGeometries[DVGeoName], addToPyOpt + ) - - def addCompositeVolumeConstraint(self, vols, lower=1.0, upper=3.0, - scaled=True, scale=1.0, name=None, - addToPyOpt=True, DVGeoName='default'): + def addCompositeVolumeConstraint( + self, vols, lower=1.0, upper=3.0, scaled=True, scale=1.0, name=None, addToPyOpt=True, DVGeoName="default" + ): """ Add a composite volume constraint. This used previously added constraints and combines them to form a single volume constraint. @@ -1756,15 +1861,15 @@ def addCompositeVolumeConstraint(self, vols, lower=1.0, upper=3.0, specified to a logical name for this computation. with addToPyOpt=False, the lower, upper and scale variables are meaningless - """ + """ self._checkDVGeo(DVGeoName) - typeName = 'volCon' + typeName = "volCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: - conName = '%s_composite_volume_constraint_%d'%(self.name, len(self.constraints[typeName])) + conName = "%s_composite_volume_constraint_%d" % (self.name, len(self.constraints[typeName])) else: conName = name @@ -1774,16 +1879,27 @@ def addCompositeVolumeConstraint(self, vols, lower=1.0, upper=3.0, try: volCons.append(self.constraints[typeName][vol]) except KeyError: - raise Error("The supplied volume name '%s' has not" - " already been added with a call to " - "addVolumeConstraint()"% vol) + raise Error( + "The supplied volume name '%s' has not" + " already been added with a call to " + "addVolumeConstraint()" % vol + ) self.constraints[typeName][conName] = CompositeVolumeConstraint( - conName, volCons, lower, upper, scaled, scale, self.DVGeometries[DVGeoName], - addToPyOpt) - - def addLeTeConstraints(self, volID=None, faceID=None,topID=None, - indSetA=None, indSetB=None, name=None, - config=None, childIdx=None, DVGeoName='default'): + conName, volCons, lower, upper, scaled, scale, self.DVGeometries[DVGeoName], addToPyOpt + ) + + def addLeTeConstraints( + self, + volID=None, + faceID=None, + topID=None, + indSetA=None, + indSetB=None, + name=None, + config=None, + childIdx=None, + DVGeoName="default", + ): """ Add a set of 'leading edge' or 'trailing edge' constraints to DVConstraints. These are just a particular form of linear @@ -1879,27 +1995,26 @@ def addLeTeConstraints(self, volID=None, faceID=None,topID=None, iFace = False jFace = False kFace = False - if faceID.lower() == 'ilow': + if faceID.lower() == "ilow": indices = lIndex[0, :, :] iFace = True - elif faceID.lower() == 'ihigh': + elif faceID.lower() == "ihigh": indices = lIndex[-1, :, :] iFace = True - elif faceID.lower() == 'jlow': + elif faceID.lower() == "jlow": indices = lIndex[:, 0, :] jFace = True - elif faceID.lower() == 'jhigh': + elif faceID.lower() == "jhigh": indices = lIndex[:, -1, :] jFace = True - elif faceID.lower() == 'klow': + elif faceID.lower() == "klow": indices = lIndex[:, :, 0] kFace = True - elif faceID.lower() == 'khigh': + elif faceID.lower() == "khigh": indices = lIndex[:, :, -1] kFace = True else: - raise Error("faceID must be one of iLow, iHigh, jLow, jHigh, " - "kLow or kHigh.") + raise Error("faceID must be one of iLow, iHigh, jLow, jHigh, " "kLow or kHigh.") # Now we see if one and exactly one length in 2: shp = indices.shape @@ -1911,53 +2026,56 @@ def addLeTeConstraints(self, volID=None, faceID=None,topID=None, indSetB = indices[:, 1] else: if topID is not None: - if topID.lower()=='i' and not iFace: + if topID.lower() == "i" and not iFace: indSetA = indices[0, :] indSetB = indices[1, :] - elif topID.lower()=='j' and not jFace: + elif topID.lower() == "j" and not jFace: if iFace: indSetA = indices[0, :] indSetB = indices[1, :] else: indSetA = indices[:, 0] indSetB = indices[:, 1] - elif topID.lower()=='k' and not kFace: + elif topID.lower() == "k" and not kFace: indSetA = indices[:, 0] indSetB = indices[:, 1] else: - raise Error("Invalid value for topID. value must be" - " i, j or k") + raise Error("Invalid value for topID. value must be" " i, j or k") else: - raise Error("Cannot add leading edge constraints. One (and " - "exactly one) of FFD block dimensions on the" - " specified face must be 2. The dimensions of " - "the selected face are: " - "(%d, %d). For this case you must specify " - "topID" % (shp[0], shp[1])) + raise Error( + "Cannot add leading edge constraints. One (and " + "exactly one) of FFD block dimensions on the" + " specified face must be 2. The dimensions of " + "the selected face are: " + "(%d, %d). For this case you must specify " + "topID" % (shp[0], shp[1]) + ) elif indSetA is not None and indSetB is not None: if len(indSetA) != len(indSetB): - raise Error("The length of the supplied indices are not " - "the same length") + raise Error("The length of the supplied indices are not " "the same length") else: - raise Error("Incorrect data supplied to addLeTeConstraint. The " - "keyword arguments 'volID' and 'faceID' must be " - "specified **or** 'indSetA' and 'indSetB'") + raise Error( + "Incorrect data supplied to addLeTeConstraint. The " + "keyword arguments 'volID' and 'faceID' must be " + "specified **or** 'indSetA' and 'indSetB'" + ) if name is None: - conName = '%s_lete_constraint_%d'%(self.name, len(self.linearCon)) + conName = "%s_lete_constraint_%d" % (self.name, len(self.linearCon)) else: conName = name # Finally add the volume constraint object n = len(indSetA) self.linearCon[conName] = LinearConstraint( - conName, indSetA, indSetB, numpy.ones(n), numpy.ones(n), - lower=0, upper=0, DVGeo=DVGeo, config=config) + conName, indSetA, indSetB, numpy.ones(n), numpy.ones(n), lower=0, upper=0, DVGeo=DVGeo, config=config + ) - def addLinearConstraintsShape(self, indSetA, indSetB, factorA, factorB, - lower=0, upper=0, name=None, config=None, DVGeoName='default'): + def addLinearConstraintsShape( + self, indSetA, indSetB, factorA, factorB, lower=0, upper=0, name=None, config=None, DVGeoName="default" + ): """ Add a complete generic set of linear constraints for the shape variables that have been added to DVGeo. The constraints are @@ -2020,11 +2138,10 @@ def addLinearConstraintsShape(self, indSetA, indSetB, factorA, factorB, self._checkDVGeo(DVGeoName) if len(indSetA) != len(indSetB): - raise Error("The length of the supplied indices are not " - "the same length") + raise Error("The length of the supplied indices are not " "the same length") if name is None: - conName = '%s_linear_constraint_%d'%(self.name, len(self.linearCon)) + conName = "%s_linear_constraint_%d" % (self.name, len(self.linearCon)) else: conName = name @@ -2036,36 +2153,45 @@ def addLinearConstraintsShape(self, indSetA, indSetB, factorA, factorB, n = len(indSetA) if len(factorA) == 1: - factorA = factorA[0]*numpy.ones(n) + factorA = factorA[0] * numpy.ones(n) elif len(factorA) != n: - raise Error('Length of factorA invalid!') + raise Error("Length of factorA invalid!") if len(factorB) == 1: - factorB = factorB[0]*numpy.ones(n) + factorB = factorB[0] * numpy.ones(n) elif len(factorB) != n: - raise Error('Length of factorB invalid!') + raise Error("Length of factorB invalid!") if len(lower) == 1: - lower = lower[0]*numpy.ones(n) + lower = lower[0] * numpy.ones(n) elif len(lower) != n: - raise Error('Length of lower invalid!') + raise Error("Length of lower invalid!") if len(upper) == 1: - upper = upper[0]*numpy.ones(n) + upper = upper[0] * numpy.ones(n) elif len(upper) != n: - raise Error('Length of upper invalid!') + raise Error("Length of upper invalid!") # Finally add the linear constraint object self.linearCon[conName] = LinearConstraint( - conName, indSetA, indSetB, factorA, factorB, lower, upper, - self.DVGeometries[DVGeoName], config=config) - - def addGearPostConstraint(self, wimpressCalc, position, axis, - thickLower=1.0, thickUpper=3.0, - thickScaled=True, - MACFracLower=0.50, MACFracUpper=0.60, - name=None, addToPyOpt=True, - surfaceName='default', DVGeoName='default'): + conName, indSetA, indSetB, factorA, factorB, lower, upper, self.DVGeometries[DVGeoName], config=config + ) + + def addGearPostConstraint( + self, + wimpressCalc, + position, + axis, + thickLower=1.0, + thickUpper=3.0, + thickScaled=True, + MACFracLower=0.50, + MACFracUpper=0.60, + name=None, + addToPyOpt=True, + surfaceName="default", + DVGeoName="default", + ): """Code for doing landing gear post constraints on the fly in an optimization. As it turns out, this is a critical constraint @@ -2135,34 +2261,52 @@ def addGearPostConstraint(self, wimpressCalc, position, axis, self._checkDVGeo(DVGeoName) p0, p1, p2 = self._getSurfaceVertices(surfaceName=surfaceName) - typeName = 'gearCon' + typeName = "gearCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: - conName = '%s_gear_constraint_%d'%(self.name, len(self.constraints[typeName])) + conName = "%s_gear_constraint_%d" % (self.name, len(self.constraints[typeName])) else: conName = name # Project the actual location we were give: - up, down, fail = geo_utils.projectNode( - position, axis, p0, p1-p0, p2-p0) + up, down, fail = geo_utils.projectNode(position, axis, p0, p1 - p0, p2 - p0) if fail > 0: - raise Error("There was an error projecting a node " - "at (%f, %f, %f) with normal (%f, %f, %f)."% ( - position)) + raise Error( + "There was an error projecting a node " "at (%f, %f, %f) with normal (%f, %f, %f)." % (position) + ) self.constraints[typeName][conName] = GearPostConstraint( - conName, wimpressCalc, up, down, thickLower, thickUpper, - thickScaled, MACFracLower, MACFracUpper, self.DVGeometries[DVGeoName], - addToPyOpt) - - - def addCircularityConstraint(self,origin,rotAxis,radius, - zeroAxis,angleCW,angleCCW, - nPts=4, - upper=1.0,lower=1.0, scale=1.0, - name=None, addToPyOpt=True, DVGeoName='default'): + conName, + wimpressCalc, + up, + down, + thickLower, + thickUpper, + thickScaled, + MACFracLower, + MACFracUpper, + self.DVGeometries[DVGeoName], + addToPyOpt, + ) + + def addCircularityConstraint( + self, + origin, + rotAxis, + radius, + zeroAxis, + angleCW, + angleCCW, + nPts=4, + upper=1.0, + lower=1.0, + scale=1.0, + name=None, + addToPyOpt=True, + DVGeoName="default", + ): """ Add a contraint to keep a certain portion of your geometry circular. Define the origin, central axis and radius to define the circle. @@ -2234,30 +2378,36 @@ def addCircularityConstraint(self,origin,rotAxis,radius, """ self._checkDVGeo(DVGeoName) - coords = self._generateCircle(origin,rotAxis,radius,zeroAxis,angleCW,angleCCW, - nPts) + coords = self._generateCircle(origin, rotAxis, radius, zeroAxis, angleCW, angleCCW, nPts) # Create the circularity constraint object: coords = coords.reshape((nPts, 3)) origin = numpy.array(origin).reshape((1, 3)) - typeName = 'circCon' + typeName = "circCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() - # Create a name if name is None: - conName = '%s_circularity_constraints_%d'%(self.name, len(self.constraints[typeName])) + conName = "%s_circularity_constraints_%d" % (self.name, len(self.constraints[typeName])) else: conName = name self.constraints[typeName][conName] = CircularityConstraint( - conName, origin, coords, lower, upper, scale, self.DVGeometries[DVGeoName], - addToPyOpt) - - def addSurfaceAreaConstraint(self,lower=1.0, upper=3.0, scaled=True, scale=1.0, - name=None, addToPyOpt=True, - surfaceName='default', DVGeoName='default'): + conName, origin, coords, lower, upper, scale, self.DVGeometries[DVGeoName], addToPyOpt + ) + + def addSurfaceAreaConstraint( + self, + lower=1.0, + upper=3.0, + scaled=True, + scale=1.0, + name=None, + addToPyOpt=True, + surfaceName="default", + DVGeoName="default", + ): """ Sum up the total surface area of the triangles included in the DVCon surface @@ -2311,27 +2461,34 @@ def addSurfaceAreaConstraint(self,lower=1.0, upper=3.0, scaled=True, scale=1.0, meaningless """ - - self._checkDVGeo(DVGeoName) p0, p1, p2 = self._getSurfaceVertices(surfaceName=surfaceName) - typeName = 'surfAreaCon' + typeName = "surfAreaCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() # Create a name if name is None: - conName = '%s_surfaceArea_constraints_%d'%(self.name, len(self.constraints[typeName])) + conName = "%s_surfaceArea_constraints_%d" % (self.name, len(self.constraints[typeName])) else: conName = name self.constraints[typeName][conName] = SurfaceAreaConstraint( - conName, p0, p1-p0, p2-p0, lower, upper, scale, scaled, self.DVGeometries[DVGeoName], - addToPyOpt) - - def addProjectedAreaConstraint(self, axis='y', lower=1.0, upper=3.0, scaled=True, - scale=1.0, name=None,addToPyOpt=True, - surfaceName='default', DVGeoName='default'): + conName, p0, p1 - p0, p2 - p0, lower, upper, scale, scaled, self.DVGeometries[DVGeoName], addToPyOpt + ) + + def addProjectedAreaConstraint( + self, + axis="y", + lower=1.0, + upper=3.0, + scaled=True, + scale=1.0, + name=None, + addToPyOpt=True, + surfaceName="default", + DVGeoName="default", + ): """ Sum up the total surface area of the triangles included in the DVCon surface projected to a plane defined by "axis". @@ -2391,30 +2548,38 @@ def addProjectedAreaConstraint(self, axis='y', lower=1.0, upper=3.0, scaled=True self._checkDVGeo(DVGeoName) p0, p1, p2 = self._getSurfaceVertices(surfaceName=surfaceName) - if axis=='x': - axis = numpy.array([1,0,0]) - elif axis=='y': - axis = numpy.array([0,1,0]) - elif axis=='z': - axis = numpy.array([0,0,1]) + if axis == "x": + axis = numpy.array([1, 0, 0]) + elif axis == "y": + axis = numpy.array([0, 1, 0]) + elif axis == "z": + axis = numpy.array([0, 0, 1]) - typeName = 'projAreaCon' + typeName = "projAreaCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() # Create a name if name is None: - conName = '%s_projectedArea_constraints_%d'%(self.name, len(self.constraints[typeName])) + conName = "%s_projectedArea_constraints_%d" % (self.name, len(self.constraints[typeName])) else: conName = name self.constraints[typeName][conName] = ProjectedAreaConstraint( - conName, p0, p1-p0, p2-p0, axis, lower, upper, scale, scaled, - self.DVGeometries[DVGeoName], addToPyOpt) - - def addPlanarityConstraint(self,origin,planeAxis, - upper=0.0,lower=0.0, scale=1.0, - name=None, addToPyOpt=True, - surfaceName='default', DVGeoName='default'): + conName, p0, p1 - p0, p2 - p0, axis, lower, upper, scale, scaled, self.DVGeometries[DVGeoName], addToPyOpt + ) + + def addPlanarityConstraint( + self, + origin, + planeAxis, + upper=0.0, + lower=0.0, + scale=1.0, + name=None, + addToPyOpt=True, + surfaceName="default", + DVGeoName="default", + ): """ Add a contraint to keep the surface in set in DVCon planar Define the origin, and the plane axis. @@ -2473,22 +2638,40 @@ def addPlanarityConstraint(self,origin,planeAxis, planeAxis = numpy.array(planeAxis).reshape((1, 3)) # Create a name - typeName = 'planeCon' + typeName = "planeCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: - conName = '%s_planarity_constraints_%d'%(self.name, len(self.constraints[typeName])) + conName = "%s_planarity_constraints_%d" % (self.name, len(self.constraints[typeName])) else: conName = name self.constraints[typeName][conName] = PlanarityConstraint( - conName, planeAxis, origin, p0, p1-p0, p2-p0, lower, upper, scale, self.DVGeometries[DVGeoName], - addToPyOpt) - - def addColinearityConstraint(self, origin, lineAxis, distances, - upper=0.0,lower=0.0, scale=1.0, - name=None, addToPyOpt=True, - DVGeoName='default'): + conName, + planeAxis, + origin, + p0, + p1 - p0, + p2 - p0, + lower, + upper, + scale, + self.DVGeometries[DVGeoName], + addToPyOpt, + ) + + def addColinearityConstraint( + self, + origin, + lineAxis, + distances, + upper=0.0, + lower=0.0, + scale=1.0, + name=None, + addToPyOpt=True, + DVGeoName="default", + ): """ Add a contraint to keep a set of points aligned. Define the origin, and axis of the line and then a set of distances @@ -2546,7 +2729,7 @@ def addColinearityConstraint(self, origin, lineAxis, distances, nPts = len(distances) coords = [] for dist in distances: - coords.append(dist*lineAxis+origin) + coords.append(dist * lineAxis + origin) # Create the circularity constraint object: coords = numpy.array(coords).reshape((nPts, 3)) @@ -2554,21 +2737,31 @@ def addColinearityConstraint(self, origin, lineAxis, distances, lineAxis = numpy.array(lineAxis).reshape((1, 3)) # Create a name - typeName = 'coLinCon' + typeName = "coLinCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: - conName = '%s_colinearity_constraints_%d'%(self.name, len(self.constraints[typeName])) + conName = "%s_colinearity_constraints_%d" % (self.name, len(self.constraints[typeName])) else: conName = name self.constraints[typeName][conName] = ColinearityConstraint( - conName, lineAxis, origin, coords, lower, upper, scale, - self.DVGeometries[DVGeoName], addToPyOpt) - - def addCurvatureConstraint(self, surfFile, curvatureType='Gaussian', lower=-1e20, upper=1e20, - scaled=True, scale=1.0, KSCoeff=None, - name=None,addToPyOpt=False,DVGeoName='default'): + conName, lineAxis, origin, coords, lower, upper, scale, self.DVGeometries[DVGeoName], addToPyOpt + ) + + def addCurvatureConstraint( + self, + surfFile, + curvatureType="Gaussian", + lower=-1e20, + upper=1e20, + scaled=True, + scale=1.0, + KSCoeff=None, + name=None, + addToPyOpt=False, + DVGeoName="default", + ): """ Add a curvature contraint for the prescribed surface. The only required input for this constraint is a structured plot 3D file of the surface (there can be multiple @@ -2643,42 +2836,52 @@ def addCurvatureConstraint(self, surfFile, curvatureType='Gaussian', lower=-1e20 """ - self._checkDVGeo(DVGeoName) # Use pyGeo to load the plot3d file - geo = pyGeo('plot3d', surfFile) + geo = pyGeo("plot3d", surfFile) # node and edge tolerance for pyGeo (these are never used so # we just fix them) - node_tol = 1e-8 - edge_tol = 1e-8 + node_tol = 1e-8 + edge_tol = 1e-8 # Explicity do the connectivity here since we don't want to # write a con file: geo._calcConnectivity(node_tol, edge_tol) surfs = geo.surfs - typeName = 'curveCon' + typeName = "curveCon" if not typeName in self.constraints: self.constraints[typeName] = OrderedDict() # Create a name if name is None: - if curvatureType == 'Gaussian': - conName = '%s_gaussian_curvature_constraint_%d'%(self.name, len(self.constraints[typeName])) - elif curvatureType == 'mean': - conName = '%s_mean_curvature_constraint_%d'%(self.name, len(self.constraints[typeName])) - elif curvatureType == 'combined': - conName = '%s_combined_curvature_constraint_%d'%(self.name, len(self.constraints[typeName])) - elif curvatureType == 'KSmean': - conName = '%s_ksmean_curvature_constraint_%d'%(self.name, len(self.constraints[typeName])) + if curvatureType == "Gaussian": + conName = "%s_gaussian_curvature_constraint_%d" % (self.name, len(self.constraints[typeName])) + elif curvatureType == "mean": + conName = "%s_mean_curvature_constraint_%d" % (self.name, len(self.constraints[typeName])) + elif curvatureType == "combined": + conName = "%s_combined_curvature_constraint_%d" % (self.name, len(self.constraints[typeName])) + elif curvatureType == "KSmean": + conName = "%s_ksmean_curvature_constraint_%d" % (self.name, len(self.constraints[typeName])) else: - raise Error("The curvatureType parameter should be Gaussian, mean, combined, or KSmean " - "%s is not supported!"%curvatureType) + raise Error( + "The curvatureType parameter should be Gaussian, mean, combined, or KSmean " + "%s is not supported!" % curvatureType + ) else: conName = name self.constraints[typeName][conName] = CurvatureConstraint( - conName, surfs, curvatureType, lower, upper, scaled, scale, KSCoeff, self.DVGeometries[DVGeoName], addToPyOpt) - - def addMonotonicConstraints(self, key, slope=1.0, name=None, start=0, - stop=-1, config=None, DVGeoName='default'): + conName, + surfs, + curvatureType, + lower, + upper, + scaled, + scale, + KSCoeff, + self.DVGeometries[DVGeoName], + addToPyOpt, + ) + + def addMonotonicConstraints(self, key, slope=1.0, name=None, start=0, stop=-1, config=None, DVGeoName="default"): """ Parameters ---------- @@ -2711,19 +2914,26 @@ def addMonotonicConstraints(self, key, slope=1.0, name=None, start=0, self._checkDVGeo(DVGeoName) if name is None: - conName = '%s_monotonic_constraint_%d'%(self.name, len(self.linearCon)) + conName = "%s_monotonic_constraint_%d" % (self.name, len(self.linearCon)) else: conName = name options = { - 'slope':slope, - 'start':start, - 'stop':stop, + "slope": slope, + "start": start, + "stop": stop, } # Finally add the global linear constraint object self.linearCon[conName] = GlobalLinearConstraint( - conName, key, type='monotonic', options=options, - lower=0, upper=None, DVGeo=self.DVGeometries[DVGeoName], config=config) + conName, + key, + type="monotonic", + options=options, + lower=0, + upper=None, + DVGeo=self.DVGeometries[DVGeoName], + config=config, + ) def _readPlot3DSurfFile(self, fileName): """Read a plot3d file and return the points and connectivity in @@ -2732,56 +2942,57 @@ def _readPlot3DSurfFile(self, fileName): pts = None conn = None - f = open(fileName, 'r') - nSurf = numpy.fromfile(f, 'int', count=1, sep=' ')[0] - sizes = numpy.fromfile(f, 'int', count=3*nSurf, sep=' ').reshape((nSurf, 3)) + f = open(fileName, "r") + nSurf = numpy.fromfile(f, "int", count=1, sep=" ")[0] + sizes = numpy.fromfile(f, "int", count=3 * nSurf, sep=" ").reshape((nSurf, 3)) nElem = 0 for i in range(nSurf): - nElem += (sizes[i, 0]-1)*(sizes[i, 1]-1) + nElem += (sizes[i, 0] - 1) * (sizes[i, 1] - 1) # Generate the uncompacted point and connectivity list: - p0 = numpy.zeros((nElem*2, 3)) - v1 = numpy.zeros((nElem*2, 3)) - v2 = numpy.zeros((nElem*2, 3)) + p0 = numpy.zeros((nElem * 2, 3)) + v1 = numpy.zeros((nElem * 2, 3)) + v2 = numpy.zeros((nElem * 2, 3)) elemCount = 0 for iSurf in range(nSurf): - curSize = sizes[iSurf, 0]*sizes[iSurf, 1] + curSize = sizes[iSurf, 0] * sizes[iSurf, 1] pts = numpy.zeros((curSize, 3)) for idim in range(3): - pts[:, idim] = numpy.fromfile(f, 'float', curSize, sep=' ') + pts[:, idim] = numpy.fromfile(f, "float", curSize, sep=" ") - pts = pts.reshape((sizes[iSurf,0], sizes[iSurf,1], 3), order='f') - for j in range(sizes[iSurf, 1]-1): - for i in range(sizes[iSurf, 0]-1): + pts = pts.reshape((sizes[iSurf, 0], sizes[iSurf, 1], 3), order="f") + for j in range(sizes[iSurf, 1] - 1): + for i in range(sizes[iSurf, 0] - 1): # Each quad is split into two triangles p0[elemCount] = pts[i, j] - v1[elemCount] = pts[i+1, j] - pts[i, j] - v2[elemCount] = pts[i, j+1] - pts[i, j] + v1[elemCount] = pts[i + 1, j] - pts[i, j] + v2[elemCount] = pts[i, j + 1] - pts[i, j] elemCount += 1 - p0[elemCount] = pts[i+1, j] - v1[elemCount] = pts[i+1, j+1] - pts[i+1, j] - v2[elemCount] = pts[i, j+1] - pts[i+1, j] + p0[elemCount] = pts[i + 1, j] + v1[elemCount] = pts[i + 1, j + 1] - pts[i + 1, j] + v2[elemCount] = pts[i, j + 1] - pts[i + 1, j] elemCount += 1 return p0, v1, v2 - - def _checkDVGeo(self, name='default'): + def _checkDVGeo(self, name="default"): """check if DVGeo exists""" if name not in self.DVGeometries.keys(): - raise Error("A DVGeometry object must be added to DVCon before " - "using a call to DVCon.setDVGeo(DVGeo) before " - "constraints can be added.") + raise Error( + "A DVGeometry object must be added to DVCon before " + "using a call to DVCon.setDVGeo(DVGeo) before " + "constraints can be added." + ) def _getSurfaceVertices(self, surfaceName): if surfaceName not in self.surfaces.keys(): - raise KeyError('Need to add surface "'+surfaceName+'" to the DVConstraints object') + raise KeyError('Need to add surface "' + surfaceName + '" to the DVConstraints object') p0 = self.surfaces[surfaceName][0] p1 = self.surfaces[surfaceName][1] p2 = self.surfaces[surfaceName][2] @@ -2795,13 +3006,13 @@ def _convertTo2D(self, value, dim1, dim2): """ if numpy.isscalar: - return value*numpy.ones((dim1, dim2)) + return value * numpy.ones((dim1, dim2)) else: temp = numpy.atleast_2d(value) if temp.shape[0] == dim1 and temp.shape[1] == dim2: return value else: - raise Error('The size of the 2D array was the incorret shape') + raise Error("The size of the 2D array was the incorret shape") def _convertTo1D(self, value, dim1): """ @@ -2811,13 +3022,13 @@ def _convertTo1D(self, value, dim1): """ if numpy.isscalar: - return value*numpy.ones(dim1) + return value * numpy.ones(dim1) else: temp = numpy.atleast_1d(value) if temp.shape[0] == dim1: return value else: - raise Error('The size of the 1D array was the incorret shape') + raise Error("The size of the 1D array was the incorret shape") def _generateIntersections(self, leList, teList, nSpan, nChord, surfaceName): """ @@ -2833,38 +3044,36 @@ def _generateIntersections(self, leList, teList, nSpan, nChord, surfaceName): le_s = pySpline.Curve(X=leList, k=2) te_s = pySpline.Curve(X=teList, k=2) root_s = pySpline.Curve(X=[leList[0], teList[0]], k=2) - tip_s = pySpline.Curve(X=[leList[-1], teList[-1]], k=2) + tip_s = pySpline.Curve(X=[leList[-1], teList[-1]], k=2) # Generate parametric distances span_s = numpy.linspace(0.0, 1.0, nSpan) chord_s = numpy.linspace(0.0, 1.0, nChord) # Generate a 2D region of intersections - X = geo_utils.tfi_2d(le_s(span_s), te_s(span_s), - root_s(chord_s), tip_s(chord_s)) + X = geo_utils.tfi_2d(le_s(span_s), te_s(span_s), root_s(chord_s), tip_s(chord_s)) coords = numpy.zeros((nSpan, nChord, 2, 3)) for i in range(nSpan): for j in range(nChord): # Generate the 'up_vec' from taking the cross product # across a quad if i == 0: - uVec = X[i+1, j]-X[i, j] + uVec = X[i + 1, j] - X[i, j] elif i == nSpan - 1: - uVec = X[i, j] - X[i-1, j] + uVec = X[i, j] - X[i - 1, j] else: - uVec = X[i+1, j] - X[i-1, j] + uVec = X[i + 1, j] - X[i - 1, j] if j == 0: - vVec = X[i, j+1]-X[i, j] + vVec = X[i, j + 1] - X[i, j] elif j == nChord - 1: - vVec = X[i, j] - X[i, j-1] + vVec = X[i, j] - X[i, j - 1] else: - vVec = X[i, j+1] - X[i, j-1] + vVec = X[i, j + 1] - X[i, j - 1] upVec = numpy.cross(uVec, vVec) # Project actual node: - up, down, fail = geo_utils.projectNode( - X[i ,j], upVec, p0, p1-p0, p2-p0) + up, down, fail = geo_utils.projectNode(X[i, j], upVec, p0, p1 - p0, p2 - p0) if fail == 0: coords[i, j, 0] = up @@ -2874,10 +3083,11 @@ def _generateIntersections(self, leList, teList, nSpan, nChord, surfaceName): coords[i, j, 0] = down coords[i, j, 1] = up else: - raise Error('There was an error projecting a node \ - at (%f, %f, %f) with normal (%f, %f, %f).'% ( - X[i, j, 0], X[i, j, 1], X[i, j, 2], - upVec[0], upVec[1], upVec[2])) + raise Error( + "There was an error projecting a node \ + at (%f, %f, %f) with normal (%f, %f, %f)." + % (X[i, j, 0], X[i, j, 1], X[i, j, 2], upVec[0], upVec[1], upVec[2]) + ) return coords @@ -2903,24 +3113,24 @@ def _generateDiscreteSurface(self, wing): u = geo_utils.fillKnots(tu, ku, level) v = geo_utils.fillKnots(tv, kv, level) - for i in range(len(u)-1): - for j in range(len(v)-1): - P0 = surf(u[i ], v[j ]) - P1 = surf(u[i+1], v[j ]) - P2 = surf(u[i ], v[j+1]) - P3 = surf(u[i+1], v[j+1]) + for i in range(len(u) - 1): + for j in range(len(v) - 1): + P0 = surf(u[i], v[j]) + P1 = surf(u[i + 1], v[j]) + P2 = surf(u[i], v[j + 1]) + P3 = surf(u[i + 1], v[j + 1]) p0.append(P0) - v1.append(P1-P0) - v2.append(P2-P0) + v1.append(P1 - P0) + v2.append(P2 - P0) p0.append(P3) - v1.append(P2-P3) - v2.append(P1-P3) + v1.append(P2 - P3) + v2.append(P1 - P3) return numpy.array(p0), numpy.array(v1), numpy.array(v2) - def _generateCircle(self,origin,rotAxis,radius,zeroAxis,angleCW,angleCCW,nPts): + def _generateCircle(self, origin, rotAxis, radius, zeroAxis, angleCW, angleCCW, nPts): """ generate the coordinates for a circle. The user should not have to call this directly. @@ -2955,34 +3165,34 @@ def _generateCircle(self,origin,rotAxis,radius,zeroAxis,angleCW,angleCCW,nPts): origin = numpy.array(origin).reshape((3,)) # Create the coordinate array - coords = numpy.zeros((nPts,3)) + coords = numpy.zeros((nPts, 3)) # get the angles about the zero axis for the points - if angleCW<0: + if angleCW < 0: raise Error("Negative angle specified. angleCW should be positive.") - if angleCCW<0: + if angleCCW < 0: raise Error("Negative angle specified. angleCCW should be positive.") - angles = numpy.linspace(numpy.deg2rad(-angleCW),numpy.deg2rad(angleCCW),nPts) + angles = numpy.linspace(numpy.deg2rad(-angleCW), numpy.deg2rad(angleCCW), nPts) # --------- # Generate a unit vector in the zero axis direction # ---- # get the third axis by taking the cross product of rotAxis and zeroAxis - axis = numpy.cross(zeroAxis,rotAxis) + axis = numpy.cross(zeroAxis, rotAxis) - #now use these axis to regenerate the orthogonal zero axis - zeroAxisOrtho = numpy.cross(rotAxis,axis) + # now use these axis to regenerate the orthogonal zero axis + zeroAxisOrtho = numpy.cross(rotAxis, axis) # now normalize the length of the zeroAxisOrtho length = numpy.linalg.norm(zeroAxisOrtho) - zeroAxisOrtho /=length + zeroAxisOrtho /= length # ------- # Normalize the rotation axis # ------- length = numpy.linalg.norm(rotAxis) - rotAxis /=length + rotAxis /= length # --------- # now rotate, multiply by radius ,and add to the origin to get the coords @@ -2990,11 +3200,12 @@ def _generateCircle(self,origin,rotAxis,radius,zeroAxis,angleCW,angleCCW,nPts): for i in range(nPts): newUnitVec = geo_utils.rotVbyW(zeroAxisOrtho, rotAxis, angles[i]) - newUnitVec*=radius - coords[i,:] = newUnitVec+origin + newUnitVec *= radius + coords[i, :] = newUnitVec + origin return coords + class ThicknessConstraint(GeometricConstraint): """ DVConstraints representation of a set of thickness @@ -3003,11 +3214,10 @@ class ThicknessConstraint(GeometricConstraint): made. The user should not have to deal with this class directly. """ - def __init__(self, name, coords, lower, upper, scaled, scale, DVGeo, - addToPyOpt): + def __init__(self, name, coords, lower, upper, scaled, scale, DVGeo, addToPyOpt): self.name = name self.coords = coords - self.nCon = len(self.coords)//2 + self.nCon = len(self.coords) // 2 self.lower = lower self.upper = upper self.scaled = scaled @@ -3015,9 +3225,9 @@ def __init__(self, name, coords, lower, upper, scaled, scale, DVGeo, self.DVGeo = DVGeo self.addToPyOpt = addToPyOpt - GeometricConstraint.__init__(self, self.name, self.nCon, self.lower, - self.upper, self.scale, self.DVGeo, - self.addToPyOpt) + GeometricConstraint.__init__( + self, self.name, self.nCon, self.lower, self.upper, self.scale, self.DVGeo, self.addToPyOpt + ) # First thing we can do is embed the coordinates into DVGeo # with the name provided: @@ -3026,8 +3236,7 @@ def __init__(self, name, coords, lower, upper, scaled, scale, DVGeo, # Now get the reference lengths self.D0 = numpy.zeros(self.nCon) for i in range(self.nCon): - self.D0[i] = numpy.linalg.norm( - self.coords[2*i] - self.coords[2*i+1]) + self.D0[i] = numpy.linalg.norm(self.coords[2 * i] - self.coords[2 * i + 1]) def evalFunctions(self, funcs, config): """ @@ -3042,7 +3251,7 @@ def evalFunctions(self, funcs, config): self.coords = self.DVGeo.update(self.name, config=config) D = numpy.zeros(self.nCon) for i in range(self.nCon): - D[i] = numpy.linalg.norm(self.coords[2*i] - self.coords[2*i+1]) + D[i] = numpy.linalg.norm(self.coords[2 * i] - self.coords[2 * i + 1]) if self.scaled: D[i] /= self.D0[i] funcs[self.name] = D @@ -3060,21 +3269,17 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dTdPt = numpy.zeros((self.nCon, - self.coords.shape[0], - self.coords.shape[1])) + dTdPt = numpy.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) for i in range(self.nCon): - p1b, p2b = geo_utils.eDist_b( - self.coords[2*i, :], self.coords[2*i+1, :]) + p1b, p2b = geo_utils.eDist_b(self.coords[2 * i, :], self.coords[2 * i + 1, :]) if self.scaled: p1b /= self.D0[i] p2b /= self.D0[i] - dTdPt[i, 2*i , :] = p1b - dTdPt[i, 2*i+1, :] = p2b + dTdPt[i, 2 * i, :] = p1b + dTdPt[i, 2 * i + 1, :] = p2b - funcsSens[self.name] = self.DVGeo.totalSensitivity( - dTdPt, self.name, config=config) + funcsSens[self.name] = self.DVGeo.totalSensitivity(dTdPt, self.name, config=config) def writeTecplot(self, handle): """ @@ -3082,16 +3287,15 @@ def writeTecplot(self, handle): to the open file handle """ - handle.write('Zone T=%s\n'% self.name) - handle.write('Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n'% ( - len(self.coords), len(self.coords)//2)) - handle.write('DATAPACKING=POINT\n') + handle.write("Zone T=%s\n" % self.name) + handle.write("Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n" % (len(self.coords), len(self.coords) // 2)) + handle.write("DATAPACKING=POINT\n") for i in range(len(self.coords)): - handle.write('%f %f %f\n'% (self.coords[i, 0], self.coords[i, 1], - self.coords[i, 2])) + handle.write("%f %f %f\n" % (self.coords[i, 0], self.coords[i, 1], self.coords[i, 2])) + + for i in range(len(self.coords) // 2): + handle.write("%d %d\n" % (2 * i + 1, 2 * i + 2)) - for i in range(len(self.coords)//2): - handle.write('%d %d\n'% (2*i+1, 2*i+2)) class RadiusConstraint(GeometricConstraint): """ @@ -3101,11 +3305,10 @@ class RadiusConstraint(GeometricConstraint): to deal with this class directly. """ - def __init__(self, name, coords, lower, upper, scaled, scale, DVGeo, - addToPyOpt): + def __init__(self, name, coords, lower, upper, scaled, scale, DVGeo, addToPyOpt): self.name = name self.coords = coords - self.nCon = len(self.coords)//3 + self.nCon = len(self.coords) // 3 self.lower = lower self.upper = upper self.scaled = scaled @@ -3113,9 +3316,9 @@ def __init__(self, name, coords, lower, upper, scaled, scale, DVGeo, self.DVGeo = DVGeo self.addToPyOpt = addToPyOpt - GeometricConstraint.__init__(self, self.name, self.nCon, self.lower, - self.upper, self.scale, self.DVGeo, - self.addToPyOpt) + GeometricConstraint.__init__( + self, self.name, self.nCon, self.lower, self.upper, self.scale, self.DVGeo, self.addToPyOpt + ) # First thing we can do is embed the coordinates into DVGeo # with the name provided: @@ -3125,9 +3328,9 @@ def __init__(self, name, coords, lower, upper, scaled, scale, DVGeo, self.r0, self.c0 = self.computeCircle(self.coords) def splitPointSets(self, coords): - p1 = coords[:self.nCon] - p2 = coords[self.nCon:self.nCon*2] - p3 = coords[self.nCon*2:] + p1 = coords[: self.nCon] + p2 = coords[self.nCon : self.nCon * 2] + p3 = coords[self.nCon * 2 :] return p1, p2, p3 def computeReferenceFrames(self, coords): @@ -3142,8 +3345,8 @@ def computeReferenceFrames(self, coords): neta[i] /= geo_utils.euclideanNorm(neta[i]) # Compute component of eta in the xi direction - eta_on_xi = numpy.einsum('ij,ij->i', nxi, neta) - xi_of_eta = numpy.einsum('ij,i->ij', nxi, eta_on_xi) + eta_on_xi = numpy.einsum("ij,ij->i", nxi, neta) + xi_of_eta = numpy.einsum("ij,i->ij", nxi, eta_on_xi) # Remove component of eta in the xi direction neta = neta - xi_of_eta @@ -3153,7 +3356,7 @@ def computeReferenceFrames(self, coords): return origin, nxi, neta def computeCircle(self, coords): - ''' + """ A circle in a 2D coordinate system is defined by the equation: A*xi**2 + A*eta**2 + B*xi + C*eta + D = 0 @@ -3169,38 +3372,46 @@ def computeCircle(self, coords): Finally, we convert the reference coordinates of the center back into 3D space. - ''' + """ p1, p2, p3 = self.splitPointSets(coords) # Compute origin and unit vectors (xi, eta) of 2d space origin, nxi, neta = self.computeReferenceFrames(coords) # Compute xi component of p1, p2, and p3 - xi1 = numpy.einsum('ij,ij->i', p1 - origin, nxi) - xi2 = numpy.einsum('ij,ij->i', p2 - origin, nxi) - xi3 = numpy.einsum('ij,ij->i', p3 - origin, nxi) + xi1 = numpy.einsum("ij,ij->i", p1 - origin, nxi) + xi2 = numpy.einsum("ij,ij->i", p2 - origin, nxi) + xi3 = numpy.einsum("ij,ij->i", p3 - origin, nxi) # Compute eta component of p1, p2, and p3 - eta1 = numpy.einsum('ij,ij->i', p1 - origin, neta) - eta2 = numpy.einsum('ij,ij->i', p2 - origin, neta) - eta3 = numpy.einsum('ij,ij->i', p3 - origin, neta) + eta1 = numpy.einsum("ij,ij->i", p1 - origin, neta) + eta2 = numpy.einsum("ij,ij->i", p2 - origin, neta) + eta3 = numpy.einsum("ij,ij->i", p3 - origin, neta) # Compute the radius of curvature - A = xi1*(eta2 - eta3) - eta1*(xi2 - xi3) + xi2*eta3 - xi3*eta2 - B = (xi1**2 + eta1**2)*(eta3 - eta2) + (xi2**2 + eta2**2)*(eta1 - eta3) \ - + (xi3**2 + eta3**2)*(eta2 - eta1) - C = (xi1**2 + eta1**2)*(xi2 - xi3) + (xi2**2 + eta2**2)*(xi3 - xi1) \ - + (xi3**2 + eta3**2)*(xi1 - xi2) - D = (xi1**2 + eta1**2)*(xi3*eta2 - xi2*eta3) \ - + (xi2**2 + eta2**2)*(xi1*eta3 - xi3*eta1) \ - + (xi3**2 + eta3**2)*(xi2*eta1 - xi1*eta2) + A = xi1 * (eta2 - eta3) - eta1 * (xi2 - xi3) + xi2 * eta3 - xi3 * eta2 + B = ( + (xi1 ** 2 + eta1 ** 2) * (eta3 - eta2) + + (xi2 ** 2 + eta2 ** 2) * (eta1 - eta3) + + (xi3 ** 2 + eta3 ** 2) * (eta2 - eta1) + ) + C = ( + (xi1 ** 2 + eta1 ** 2) * (xi2 - xi3) + + (xi2 ** 2 + eta2 ** 2) * (xi3 - xi1) + + (xi3 ** 2 + eta3 ** 2) * (xi1 - xi2) + ) + D = ( + (xi1 ** 2 + eta1 ** 2) * (xi3 * eta2 - xi2 * eta3) + + (xi2 ** 2 + eta2 ** 2) * (xi1 * eta3 - xi3 * eta1) + + (xi3 ** 2 + eta3 ** 2) * (xi2 * eta1 - xi1 * eta2) + ) xiC = -B / 2 / A etaC = -C / 2 / A - r = numpy.sqrt((B**2 + C**2 - 4*A*D) / 4 / A**2) + r = numpy.sqrt((B ** 2 + C ** 2 - 4 * A * D) / 4 / A ** 2) # Convert center coordinates back - center = origin + nxi*xiC[:,None] + neta*etaC[:,None] + center = origin + nxi * xiC[:, None] + neta * etaC[:, None] return r, center @@ -3240,14 +3451,14 @@ def evalFunctionsSens(self, funcsSens, config): # : drdPt = numpy.zeros((self.nCon, 9)) - coords = self.coords.astype('D') - for i in range(3): # loop over pts at given slice - for j in range(3): # loop over coordinates in pt - coords[i*self.nCon:(i+1)*self.nCon,j] += 1e-40j + coords = self.coords.astype("D") + for i in range(3): # loop over pts at given slice + for j in range(3): # loop over coordinates in pt + coords[i * self.nCon : (i + 1) * self.nCon, j] += 1e-40j r, c = self.computeCircle(coords) - drdPt[:,i*3+j] = r.imag / 1e-40 - coords[i*self.nCon:(i+1)*self.nCon,j] -= 1e-40j + drdPt[:, i * 3 + j] = r.imag / 1e-40 + coords[i * self.nCon : (i + 1) * self.nCon, j] -= 1e-40j # We now need to convert to the 3d sparse matrix form of the jacobian. # We need the derivative of each radius w.r.t. all of the points @@ -3256,19 +3467,20 @@ def evalFunctionsSens(self, funcsSens, config): # We also have to scale the sensitivities if scale is True. if self.scaled: - eye = numpy.diag(1/self.r0) + eye = numpy.diag(1 / self.r0) else: eye = numpy.eye(self.nCon) - drdPt_sparse = numpy.einsum('ij,jk->ijk', eye, drdPt) - drdPt_sparse = drdPt_sparse.reshape(self.nCon, self.nCon*3, 3) - drdPt_sparse = numpy.hstack([ - drdPt_sparse[:,::3,:], - drdPt_sparse[:,1::3,:], - drdPt_sparse[:,2::3,:], - ]) - - funcsSens[self.name] = self.DVGeo.totalSensitivity( - drdPt_sparse, self.name, config=config) + drdPt_sparse = numpy.einsum("ij,jk->ijk", eye, drdPt) + drdPt_sparse = drdPt_sparse.reshape(self.nCon, self.nCon * 3, 3) + drdPt_sparse = numpy.hstack( + [ + drdPt_sparse[:, ::3, :], + drdPt_sparse[:, 1::3, :], + drdPt_sparse[:, 2::3, :], + ] + ) + + funcsSens[self.name] = self.DVGeo.totalSensitivity(drdPt_sparse, self.name, config=config) def writeTecplot(self, handle): """ @@ -3281,24 +3493,24 @@ def writeTecplot(self, handle): origin, nxi, neta = self.computeReferenceFrames(self.coords) nres = 50 - theta = numpy.linspace(0, 2*numpy.pi, nres+1)[:-1] - handle.write('Zone T=%s\n'% self.name) - handle.write('Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n'% ( - self.nCon*nres, self.nCon*nres)) - handle.write('DATAPACKING=POINT\n') + theta = numpy.linspace(0, 2 * numpy.pi, nres + 1)[:-1] + handle.write("Zone T=%s\n" % self.name) + handle.write("Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n" % (self.nCon * nres, self.nCon * nres)) + handle.write("DATAPACKING=POINT\n") for i in range(self.nCon): - cos_part = numpy.outer(numpy.cos(theta), nxi*r[i]) - sin_part = numpy.outer(numpy.sin(theta), neta*r[i]) - x = c[i,0] + cos_part[:,0] + sin_part[:,0] - y = c[i,1] + cos_part[:,1] + sin_part[:,1] - z = c[i,2] + cos_part[:,2] + sin_part[:,2] + cos_part = numpy.outer(numpy.cos(theta), nxi * r[i]) + sin_part = numpy.outer(numpy.sin(theta), neta * r[i]) + x = c[i, 0] + cos_part[:, 0] + sin_part[:, 0] + y = c[i, 1] + cos_part[:, 1] + sin_part[:, 1] + z = c[i, 2] + cos_part[:, 2] + sin_part[:, 2] for j in range(nres): - handle.write('%f %f %f\n'% (x[j], y[j], z[j])) + handle.write("%f %f %f\n" % (x[j], y[j], z[j])) for i in range(self.nCon): for j in range(nres): - handle.write('%d %d\n'% (i*nres + j + 1, i*nres + (j+1)%nres + 1)) + handle.write("%d %d\n" % (i * nres + j + 1, i * nres + (j + 1) % nres + 1)) + class LocationConstraint(GeometricConstraint): """ @@ -3308,8 +3520,7 @@ class LocationConstraint(GeometricConstraint): made. The user should not have to deal with this class directly. """ - def __init__(self, name, coords, lower, upper, scaled, scale, DVGeo, - addToPyOpt): + def __init__(self, name, coords, lower, upper, scaled, scale, DVGeo, addToPyOpt): self.name = name self.coords = coords self.nCon = len(self.coords.flatten()) @@ -3320,9 +3531,9 @@ def __init__(self, name, coords, lower, upper, scaled, scale, DVGeo, self.DVGeo = DVGeo self.addToPyOpt = addToPyOpt - GeometricConstraint.__init__(self, self.name, self.nCon, self.lower, - self.upper, self.scale, self.DVGeo, - self.addToPyOpt) + GeometricConstraint.__init__( + self, self.name, self.nCon, self.lower, self.upper, self.scale, self.DVGeo, self.addToPyOpt + ) # First thing we can do is embed the coordinates into DVGeo # with the name provided: @@ -3365,19 +3576,16 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dTdPt = numpy.zeros((self.nCon, - self.coords.shape[0], - self.coords.shape[1])) + dTdPt = numpy.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) counter = 0 - for i in range( self.coords.shape[0]): - for j in range( self.coords.shape[1]): + for i in range(self.coords.shape[0]): + for j in range(self.coords.shape[1]): dTdPt[counter][i][j] = 1.0 if self.scaled: dTdPt[counter][i][j] /= self.X0[i] - counter+=1 + counter += 1 - funcsSens[self.name] = self.DVGeo.totalSensitivity( - dTdPt, self.name, config=config) + funcsSens[self.name] = self.DVGeo.totalSensitivity(dTdPt, self.name, config=config) def writeTecplot(self, handle): """ @@ -3385,16 +3593,14 @@ def writeTecplot(self, handle): to the open file handle """ - handle.write('Zone T=%s\n'% self.name) - handle.write('Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n'% ( - len(self.coords), len(self.coords)-1)) - handle.write('DATAPACKING=POINT\n') + handle.write("Zone T=%s\n" % self.name) + handle.write("Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n" % (len(self.coords), len(self.coords) - 1)) + handle.write("DATAPACKING=POINT\n") for i in range(len(self.coords)): - handle.write('%f %f %f\n'% (self.coords[i, 0], self.coords[i, 1], - self.coords[i, 2])) + handle.write("%f %f %f\n" % (self.coords[i, 0], self.coords[i, 1], self.coords[i, 2])) - for i in range(len(self.coords)-1): - handle.write('%d %d\n'% (i+1, i+2)) + for i in range(len(self.coords) - 1): + handle.write("%d %d\n" % (i + 1, i + 2)) class ThicknessToChordConstraint(GeometricConstraint): @@ -3409,16 +3615,16 @@ class ThicknessToChordConstraint(GeometricConstraint): def __init__(self, name, coords, lower, upper, scale, DVGeo, addToPyOpt): self.name = name self.coords = coords - self.nCon = len(self.coords)//4 + self.nCon = len(self.coords) // 4 self.lower = lower self.upper = upper self.scale = scale self.DVGeo = DVGeo self.addToPyOpt = addToPyOpt - GeometricConstraint.__init__(self, self.name, self.nCon, self.lower, - self.upper, self.scale, self.DVGeo, - self.addToPyOpt) + GeometricConstraint.__init__( + self, self.name, self.nCon, self.lower, self.upper, self.scale, self.DVGeo, self.addToPyOpt + ) # First thing we can do is embed the coordinates into DVGeo # with the name provided: @@ -3427,9 +3633,9 @@ def __init__(self, name, coords, lower, upper, scale, DVGeo, addToPyOpt): # Now get the reference lengths self.ToC0 = numpy.zeros(self.nCon) for i in range(self.nCon): - t = numpy.linalg.norm(self.coords[4*i] - self.coords[4*i+1]) - c = numpy.linalg.norm(self.coords[4*i+2] - self.coords[4*i+3]) - self.ToC0[i] = t/c + t = numpy.linalg.norm(self.coords[4 * i] - self.coords[4 * i + 1]) + c = numpy.linalg.norm(self.coords[4 * i + 2] - self.coords[4 * i + 3]) + self.ToC0[i] = t / c def evalFunctions(self, funcs, config): """ @@ -3444,9 +3650,9 @@ def evalFunctions(self, funcs, config): self.coords = self.DVGeo.update(self.name, config=config) ToC = numpy.zeros(self.nCon) for i in range(self.nCon): - t = geo_utils.eDist(self.coords[4*i], self.coords[4*i+1]) - c = geo_utils.eDist(self.coords[4*i+2], self.coords[4*i+3]) - ToC[i] = (t/c)/self.ToC0[i] + t = geo_utils.eDist(self.coords[4 * i], self.coords[4 * i + 1]) + c = geo_utils.eDist(self.coords[4 * i + 2], self.coords[4 * i + 3]) + ToC[i] = (t / c) / self.ToC0[i] funcs[self.name] = ToC @@ -3463,26 +3669,21 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dToCdPt = numpy.zeros((self.nCon, - self.coords.shape[0], - self.coords.shape[1])) + dToCdPt = numpy.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) for i in range(self.nCon): - t = geo_utils.eDist(self.coords[4*i], self.coords[4*i+1]) - c = geo_utils.eDist(self.coords[4*i+2], self.coords[4*i+3]) + t = geo_utils.eDist(self.coords[4 * i], self.coords[4 * i + 1]) + c = geo_utils.eDist(self.coords[4 * i + 2], self.coords[4 * i + 3]) - p1b, p2b = geo_utils.eDist_b( - self.coords[4*i, :], self.coords[4*i+1, :]) - p3b, p4b = geo_utils.eDist_b( - self.coords[4*i+2, :], self.coords[4*i+3, :]) + p1b, p2b = geo_utils.eDist_b(self.coords[4 * i, :], self.coords[4 * i + 1, :]) + p3b, p4b = geo_utils.eDist_b(self.coords[4 * i + 2, :], self.coords[4 * i + 3, :]) - dToCdPt[i, 4*i , :] = p1b/c / self.ToC0[i] - dToCdPt[i, 4*i+1, :] = p2b/c / self.ToC0[i] - dToCdPt[i, 4*i+2, :] = (-p3b*t/c**2) / self.ToC0[i] - dToCdPt[i, 4*i+3, :] = (-p4b*t/c**2) / self.ToC0[i] + dToCdPt[i, 4 * i, :] = p1b / c / self.ToC0[i] + dToCdPt[i, 4 * i + 1, :] = p2b / c / self.ToC0[i] + dToCdPt[i, 4 * i + 2, :] = (-p3b * t / c ** 2) / self.ToC0[i] + dToCdPt[i, 4 * i + 3, :] = (-p4b * t / c ** 2) / self.ToC0[i] - funcsSens[self.name] = self.DVGeo.totalSensitivity( - dToCdPt, self.name, config=config) + funcsSens[self.name] = self.DVGeo.totalSensitivity(dToCdPt, self.name, config=config) def writeTecplot(self, handle): """ @@ -3490,16 +3691,15 @@ def writeTecplot(self, handle): to the open file handle """ - handle.write('Zone T=%s\n'% self.name) - handle.write('Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n'% ( - len(self.coords), len(self.coords)//2)) - handle.write('DATAPACKING=POINT\n') + handle.write("Zone T=%s\n" % self.name) + handle.write("Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n" % (len(self.coords), len(self.coords) // 2)) + handle.write("DATAPACKING=POINT\n") for i in range(len(self.coords)): - handle.write('%f %f %f\n'% (self.coords[i, 0], self.coords[i, 1], - self.coords[i, 2])) + handle.write("%f %f %f\n" % (self.coords[i, 0], self.coords[i, 1], self.coords[i, 2])) + + for i in range(len(self.coords) // 2): + handle.write("%d %d\n" % (2 * i + 1, 2 * i + 2)) - for i in range(len(self.coords)//2): - handle.write('%d %d\n'% (2*i+1, 2*i+2)) class TriangulatedSurfaceConstraint(GeometricConstraint): """ @@ -3507,14 +3707,28 @@ class TriangulatedSurfaceConstraint(GeometricConstraint): aerodynamic surface. """ - def __init__(self, name, surface_1, surface_1_name, DVGeo1, surface_2, surface_2_name, DVGeo2, scale, addToPyOpt, - rho, perim_scale, max_perim, heuristic_dist): + def __init__( + self, + name, + surface_1, + surface_1_name, + DVGeo1, + surface_2, + surface_2_name, + DVGeo2, + scale, + addToPyOpt, + rho, + perim_scale, + max_perim, + heuristic_dist, + ): self.name = name # get the point sets self.surface_1_name = surface_1_name self.surface_2_name = surface_2_name if DVGeo1 is None and DVGeo2 is None: - raise UserError('Must include at least one geometric parametrization in constraint '+str(name)) + raise UserError("Must include at least one geometric parametrization in constraint " + str(name)) self.DVGeo1 = DVGeo1 self.DVGeo2 = DVGeo2 @@ -3528,21 +3742,20 @@ def __init__(self, name, surface_1, surface_1_name, DVGeo1, surface_2, surface_2 self.surf2_p1 = surface_2[1].transpose() self.surf2_p2 = surface_2[2].transpose() - xyzmax = np.maximum(np.maximum(self.surf2_p0.max(axis=1), self.surf2_p1.max(axis=1)), - self.surf2_p2.max(axis=1)) - xyzmin = np.minimum(np.minimum(self.surf2_p0.min(axis=1), self.surf2_p1.min(axis=1)), - self.surf2_p2.min(axis=1)) + xyzmax = np.maximum(np.maximum(self.surf2_p0.max(axis=1), self.surf2_p1.max(axis=1)), self.surf2_p2.max(axis=1)) + xyzmin = np.minimum(np.minimum(self.surf2_p0.min(axis=1), self.surf2_p1.min(axis=1)), self.surf2_p2.min(axis=1)) - - computed_maxdim = np.sqrt(np.sum((xyzmax-xyzmin)**2)) + computed_maxdim = np.sqrt(np.sum((xyzmax - xyzmin) ** 2)) if heuristic_dist is not None: if heuristic_dist < computed_maxdim: - raise ValueError('The heuristic distance must be less than the max diagonal' \ - 'dimension of the bounding box, '+str(computed_maxdim)) + raise ValueError( + "The heuristic distance must be less than the max diagonal" + "dimension of the bounding box, " + str(computed_maxdim) + ) self.maxdim = heuristic_dist else: - self.maxdim = computed_maxdim*1.05 + self.maxdim = computed_maxdim * 1.05 self.scale = scale self.addToPyOpt = addToPyOpt @@ -3589,22 +3802,21 @@ def evalFunctions(self, funcs, config): # check if the first mesh has a DVGeo, and if it does, update the points if self.DVGeo1 is not None: - self.surf1_p0 = self.DVGeo1.update(self.surface_1_name+'_p0', config=config).transpose() - self.surf1_p1 = self.DVGeo1.update(self.surface_1_name+'_p1', config=config).transpose() - self.surf1_p2 = self.DVGeo1.update(self.surface_1_name+'_p2', config=config).transpose() + self.surf1_p0 = self.DVGeo1.update(self.surface_1_name + "_p0", config=config).transpose() + self.surf1_p1 = self.DVGeo1.update(self.surface_1_name + "_p1", config=config).transpose() + self.surf1_p2 = self.DVGeo1.update(self.surface_1_name + "_p2", config=config).transpose() # check if the second mesh has a DVGeo, and if it does, update the points if self.DVGeo2 is not None: - self.surf2_p0 = self.DVGeo2.update(self.surface_2_name+'_p0', config=config).transpose() - self.surf2_p1 = self.DVGeo2.update(self.surface_2_name+'_p1', config=config).transpose() - self.surf2_p2 = self.DVGeo2.update(self.surface_2_name+'_p2', config=config).transpose() + self.surf2_p0 = self.DVGeo2.update(self.surface_2_name + "_p0", config=config).transpose() + self.surf2_p1 = self.DVGeo2.update(self.surface_2_name + "_p1", config=config).transpose() + self.surf2_p2 = self.DVGeo2.update(self.surface_2_name + "_p2", config=config).transpose() KS, perim, failflag = self.evalTriangulatedSurfConstraint() - funcs[self.name+'_KS'] = KS - funcs[self.name+'_perim'] = perim + funcs[self.name + "_KS"] = KS + funcs[self.name + "_perim"] = perim if failflag: - funcs['fail'] = failflag - + funcs["fail"] = failflag def evalFunctionsSens(self, funcsSens, config): """ @@ -3623,8 +3835,6 @@ def evalFunctionsSens(self, funcsSens, config): tmpTotalKS = {} tmpTotalPerim = {} - - deriv_outputs = self.evalTriangulatedSurfConstraintSens() # deriv outputs contains: # KS, intersect_length, mindist, timings, unbalance (index 0 through 4) @@ -3639,16 +3849,27 @@ def evalFunctionsSens(self, funcsSens, config): if nDV1 > 0: # compute sensitivity with respect to the first mesh # grad indices 0-2 are for mesh 1 p0, 1, 2 / 3-5 are for mesh 2 p0, 1, 2 - tmp_KS_p0 = self.DVGeo1.totalSensitivity(np.transpose(deriv_outputs[5]), self.surface_1_name+'_p0', config=config) - tmp_KS_p1 = self.DVGeo1.totalSensitivity(np.transpose(deriv_outputs[6]), self.surface_1_name+'_p1', config=config) - tmp_KS_p2 = self.DVGeo1.totalSensitivity(np.transpose(deriv_outputs[7]), self.surface_1_name+'_p2', config=config) - tmp_perim_p0 = self.DVGeo1.totalSensitivity(np.transpose(deriv_outputs[11]), self.surface_1_name+'_p0', config=config) - tmp_perim_p1 = self.DVGeo1.totalSensitivity(np.transpose(deriv_outputs[12]), self.surface_1_name+'_p1', config=config) - tmp_perim_p2 = self.DVGeo1.totalSensitivity(np.transpose(deriv_outputs[13]), self.surface_1_name+'_p2', config=config) + tmp_KS_p0 = self.DVGeo1.totalSensitivity( + np.transpose(deriv_outputs[5]), self.surface_1_name + "_p0", config=config + ) + tmp_KS_p1 = self.DVGeo1.totalSensitivity( + np.transpose(deriv_outputs[6]), self.surface_1_name + "_p1", config=config + ) + tmp_KS_p2 = self.DVGeo1.totalSensitivity( + np.transpose(deriv_outputs[7]), self.surface_1_name + "_p2", config=config + ) + tmp_perim_p0 = self.DVGeo1.totalSensitivity( + np.transpose(deriv_outputs[11]), self.surface_1_name + "_p0", config=config + ) + tmp_perim_p1 = self.DVGeo1.totalSensitivity( + np.transpose(deriv_outputs[12]), self.surface_1_name + "_p1", config=config + ) + tmp_perim_p2 = self.DVGeo1.totalSensitivity( + np.transpose(deriv_outputs[13]), self.surface_1_name + "_p2", config=config + ) for key in tmp_KS_p0: - tmpTotalKS[key] = tmp_KS_p0[key]+tmp_KS_p1[key]+tmp_KS_p2[key] - tmpTotalPerim[key] = tmp_perim_p0[key]+tmp_perim_p1[key]+tmp_perim_p2[key] - + tmpTotalKS[key] = tmp_KS_p0[key] + tmp_KS_p1[key] + tmp_KS_p2[key] + tmpTotalPerim[key] = tmp_perim_p0[key] + tmp_perim_p1[key] + tmp_perim_p2[key] if self.DVGeo2 is not None: nDV2 = self.DVGeo2.getNDV() @@ -3658,17 +3879,29 @@ def evalFunctionsSens(self, funcsSens, config): if nDV2 > 0: # compute sensitivity with respect to the first mesh # grad indices 0-2 are for mesh 1 p0, 1, 2 / 3-5 are for mesh 2 p0, 1, 2 - tmp_KS_p0 = self.DVGeo2.totalSensitivity(np.transpose(deriv_outputs[8]), self.surface_2_name+'_p0', config=config) - tmp_KS_p1 = self.DVGeo2.totalSensitivity(np.transpose(deriv_outputs[9]), self.surface_2_name+'_p1', config=config) - tmp_KS_p2 = self.DVGeo2.totalSensitivity(np.transpose(deriv_outputs[10]), self.surface_2_name+'_p2', config=config) - tmp_perim_p0 = self.DVGeo2.totalSensitivity(np.transpose(deriv_outputs[14]), self.surface_2_name+'_p0', config=config) - tmp_perim_p1 = self.DVGeo2.totalSensitivity(np.transpose(deriv_outputs[15]), self.surface_2_name+'_p1', config=config) - tmp_perim_p2 = self.DVGeo2.totalSensitivity(np.transpose(deriv_outputs[16]), self.surface_2_name+'_p2', config=config) + tmp_KS_p0 = self.DVGeo2.totalSensitivity( + np.transpose(deriv_outputs[8]), self.surface_2_name + "_p0", config=config + ) + tmp_KS_p1 = self.DVGeo2.totalSensitivity( + np.transpose(deriv_outputs[9]), self.surface_2_name + "_p1", config=config + ) + tmp_KS_p2 = self.DVGeo2.totalSensitivity( + np.transpose(deriv_outputs[10]), self.surface_2_name + "_p2", config=config + ) + tmp_perim_p0 = self.DVGeo2.totalSensitivity( + np.transpose(deriv_outputs[14]), self.surface_2_name + "_p0", config=config + ) + tmp_perim_p1 = self.DVGeo2.totalSensitivity( + np.transpose(deriv_outputs[15]), self.surface_2_name + "_p1", config=config + ) + tmp_perim_p2 = self.DVGeo2.totalSensitivity( + np.transpose(deriv_outputs[16]), self.surface_2_name + "_p2", config=config + ) for key in tmp_KS_p0: - tmpTotalKS[key] = tmp_KS_p0[key]+tmp_KS_p1[key]+tmp_KS_p2[key] - tmpTotalPerim[key] = tmp_perim_p0[key]+tmp_perim_p1[key]+tmp_perim_p2[key] - funcsSens[self.name+'_KS'] = tmpTotalKS - funcsSens[self.name+'_perim'] = tmpTotalPerim + tmpTotalKS[key] = tmp_KS_p0[key] + tmp_KS_p1[key] + tmp_KS_p2[key] + tmpTotalPerim[key] = tmp_perim_p0[key] + tmp_perim_p1[key] + tmp_perim_p2[key] + funcsSens[self.name + "_KS"] = tmpTotalKS + funcsSens[self.name + "_perim"] = tmpTotalPerim def evalTriangulatedSurfConstraint(self): """ @@ -3676,14 +3909,35 @@ def evalTriangulatedSurfConstraint(self): """ # first compute the length of the intersection surface between the object and surf mesh from geograd import geograd_parallel + mindist_tmp = 0.0 # first run to get the minimum distance - _, perim_length, mindist, _, _ = geograd_parallel.compute(self.surf1_p0, self.surf1_p1, self.surf1_p2, - self.surf2_p0, self.surf2_p1, self.surf2_p2, mindist_tmp, self.rho, self.maxdim, MPI.COMM_WORLD.py2f()) + _, perim_length, mindist, _, _ = geograd_parallel.compute( + self.surf1_p0, + self.surf1_p1, + self.surf1_p2, + self.surf2_p0, + self.surf2_p1, + self.surf2_p2, + mindist_tmp, + self.rho, + self.maxdim, + MPI.COMM_WORLD.py2f(), + ) # second run gets the well-conditioned KS - KS, perim_length, mindist, _, _ = geograd_parallel.compute(self.surf1_p0, self.surf1_p1, self.surf1_p2, - self.surf2_p0, self.surf2_p1, self.surf2_p2, mindist, self.rho, self.maxdim, MPI.COMM_WORLD.py2f()) + KS, perim_length, mindist, _, _ = geograd_parallel.compute( + self.surf1_p0, + self.surf1_p1, + self.surf1_p2, + self.surf2_p0, + self.surf2_p1, + self.surf2_p2, + mindist, + self.rho, + self.maxdim, + MPI.COMM_WORLD.py2f(), + ) self.perim_length = perim_length self.minimum_distance = mindist @@ -3691,7 +3945,7 @@ def evalTriangulatedSurfConstraint(self): if self.perim_length > self.max_perim: failflag = True if mpi4py.COMM_WORLD.rank == 0: - print('Intersection length ', str(perim_length), ' exceeds tol, returning fail flag') + print("Intersection length ", str(perim_length), " exceeds tol, returning fail flag") else: failflag = False return KS, perim_length, failflag @@ -3703,10 +3957,18 @@ def evalTriangulatedSurfConstraintSens(self): # first compute the length of the intersection surface between the object and surf mesh from geograd import geograd_parallel - - deriv_output = geograd_parallel.compute_derivs(self.surf1_p0, self.surf1_p1, self.surf1_p2, - self.surf2_p0, self.surf2_p1, self.surf2_p2, - self.minimum_distance, self.rho, self.maxdim, MPI.COMM_WORLD.py2f()) + deriv_output = geograd_parallel.compute_derivs( + self.surf1_p0, + self.surf1_p1, + self.surf1_p2, + self.surf2_p0, + self.surf2_p1, + self.surf2_p2, + self.minimum_distance, + self.rho, + self.maxdim, + MPI.COMM_WORLD.py2f(), + ) return deriv_output def addConstraintsPyOpt(self, optProb): @@ -3714,13 +3976,17 @@ def addConstraintsPyOpt(self, optProb): Add the constraints to pyOpt, if the flag is set """ if self.addToPyOpt: - optProb.addConGroup(self.name+'_KS', 1, lower=self.lower, - upper=self.upper, scale=self.scale, - wrt=self.getVarNames()) - optProb.addConGroup(self.name+'_perim', 1, lower=self.lower, - upper=self.upper, scale=self.perim_scale, - wrt=self.getVarNames()) - + optProb.addConGroup( + self.name + "_KS", 1, lower=self.lower, upper=self.upper, scale=self.scale, wrt=self.getVarNames() + ) + optProb.addConGroup( + self.name + "_perim", + 1, + lower=self.lower, + upper=self.upper, + scale=self.perim_scale, + wrt=self.getVarNames(), + ) class TriangulatedVolumeConstraint(GeometricConstraint): @@ -3765,9 +4031,9 @@ def evalFunctions(self, funcs, config): # running setSurface() # check if the first mesh has a DVGeo, and if it does, update the points - self.surf_p0 = self.DVGeo.update(self.surface_name+'_p0', config=config).reshape(self.surf_size, 3) - self.surf_p1 = self.DVGeo.update(self.surface_name+'_p1', config=config).reshape(self.surf_size, 3) - self.surf_p2 = self.DVGeo.update(self.surface_name+'_p2', config=config).reshape(self.surf_size, 3) + self.surf_p0 = self.DVGeo.update(self.surface_name + "_p0", config=config).reshape(self.surf_size, 3) + self.surf_p1 = self.DVGeo.update(self.surface_name + "_p1", config=config).reshape(self.surf_size, 3) + self.surf_p2 = self.DVGeo.update(self.surface_name + "_p2", config=config).reshape(self.surf_size, 3) volume = self.compute_volume(self.surf_p0, self.surf_p1, self.surf_p2) if self.vol_0 is None: @@ -3801,16 +4067,16 @@ def evalFunctionsSens(self, funcsSens, config): grad_vol = self.compute_volume_sens(self.surf_p0, self.surf_p1, self.surf_p2) nDV = self.DVGeo.getNDV() if self.scaled: - tmp_p0 = self.DVGeo.totalSensitivity(grad_vol[0] / self.vol_0, self.surface_name+'_p0', config=config) - tmp_p1 = self.DVGeo.totalSensitivity(grad_vol[1] / self.vol_0, self.surface_name+'_p1', config=config) - tmp_p2 = self.DVGeo.totalSensitivity(grad_vol[2] / self.vol_0, self.surface_name+'_p2', config=config) + tmp_p0 = self.DVGeo.totalSensitivity(grad_vol[0] / self.vol_0, self.surface_name + "_p0", config=config) + tmp_p1 = self.DVGeo.totalSensitivity(grad_vol[1] / self.vol_0, self.surface_name + "_p1", config=config) + tmp_p2 = self.DVGeo.totalSensitivity(grad_vol[2] / self.vol_0, self.surface_name + "_p2", config=config) else: - tmp_p0 = self.DVGeo.totalSensitivity(grad_vol[0], self.surface_name+'_p0', config=config) - tmp_p1 = self.DVGeo.totalSensitivity(grad_vol[1], self.surface_name+'_p1', config=config) - tmp_p2 = self.DVGeo.totalSensitivity(grad_vol[2], self.surface_name+'_p2', config=config) + tmp_p0 = self.DVGeo.totalSensitivity(grad_vol[0], self.surface_name + "_p0", config=config) + tmp_p1 = self.DVGeo.totalSensitivity(grad_vol[1], self.surface_name + "_p1", config=config) + tmp_p2 = self.DVGeo.totalSensitivity(grad_vol[2], self.surface_name + "_p2", config=config) for key in tmp_p0: - tmpTotal[key] = tmp_p0[key]+tmp_p1[key]+tmp_p2[key] + tmpTotal[key] = tmp_p0[key] + tmp_p1[key] + tmp_p2[key] funcsSens[self.name] = tmpTotal @@ -3835,12 +4101,17 @@ def compute_volume(self, p0, p1, p2): The volume of the triangulated surface """ - volume = np.sum(p1[:, 0] * p2[:, 1] * p0[:, 2] + - p2[:, 0] * p0[:, 1] * p1[:, 2] + - p0[:, 0] * p1[:, 1] * p2[:, 2] - - p1[:, 0] * p0[:, 1] * p2[:, 2] - - p2[:, 0] * p1[:, 1] * p0[:, 2] - - p0[:, 0] * p2[:, 1] * p1[:, 2]) / 6.0 + volume = ( + np.sum( + p1[:, 0] * p2[:, 1] * p0[:, 2] + + p2[:, 0] * p0[:, 1] * p1[:, 2] + + p0[:, 0] * p1[:, 1] * p2[:, 2] + - p1[:, 0] * p0[:, 1] * p2[:, 2] + - p2[:, 0] * p1[:, 1] * p0[:, 2] + - p0[:, 0] * p2[:, 1] * p1[:, 2] + ) + / 6.0 + ) return volume @@ -3865,17 +4136,17 @@ def compute_volume_sens(self, p0, p1, p2): grad_1 = np.zeros((num_pts, 3)) grad_2 = np.zeros((num_pts, 3)) - grad_0[:, 0] = (p1[:, 1] * p2[:, 2] - p1[:, 2] * p2[:, 1]) - grad_0[:, 1] = (p1[:, 2] * p2[:, 0] - p1[:, 0] * p2[:, 2]) - grad_0[:, 2] = (p1[:, 0] * p2[:, 1] - p1[:, 1] * p2[:, 0]) + grad_0[:, 0] = p1[:, 1] * p2[:, 2] - p1[:, 2] * p2[:, 1] + grad_0[:, 1] = p1[:, 2] * p2[:, 0] - p1[:, 0] * p2[:, 2] + grad_0[:, 2] = p1[:, 0] * p2[:, 1] - p1[:, 1] * p2[:, 0] - grad_1[:, 0] = (p0[:, 2] * p2[:, 1] - p0[:, 1] * p2[:, 2]) - grad_1[:, 1] = (p0[:, 0] * p2[:, 2] - p0[:, 2] * p2[:, 0]) - grad_1[:, 2] = (p0[:, 1] * p2[:, 0] - p0[:, 0] * p2[:, 1]) + grad_1[:, 0] = p0[:, 2] * p2[:, 1] - p0[:, 1] * p2[:, 2] + grad_1[:, 1] = p0[:, 0] * p2[:, 2] - p0[:, 2] * p2[:, 0] + grad_1[:, 2] = p0[:, 1] * p2[:, 0] - p0[:, 0] * p2[:, 1] - grad_2[:, 0] = (p0[:, 1] * p1[:, 2] - p0[:, 2] * p1[:, 1]) - grad_2[:, 1] = (p0[:, 2] * p1[:, 0] - p0[:, 0] * p1[:, 2]) - grad_2[:, 2] = (p0[:, 0] * p1[:, 1] - p0[:, 1] * p1[:, 0]) + grad_2[:, 0] = p0[:, 1] * p1[:, 2] - p0[:, 2] * p1[:, 1] + grad_2[:, 1] = p0[:, 2] * p1[:, 0] - p0[:, 0] * p1[:, 2] + grad_2[:, 2] = p0[:, 0] * p1[:, 1] - p0[:, 1] * p1[:, 0] return grad_0 / 6.0, grad_1 / 6.0, grad_2 / 6.0 @@ -3887,8 +4158,7 @@ class VolumeConstraint(GeometricConstraint): the DVConstraints class """ - def __init__(self, name, nSpan, nChord, coords, lower, upper, scaled, - scale, DVGeo, addToPyOpt): + def __init__(self, name, nSpan, nChord, coords, lower, upper, scaled, scale, DVGeo, addToPyOpt): self.name = name self.nCon = 1 @@ -3903,9 +4173,9 @@ def __init__(self, name, nSpan, nChord, coords, lower, upper, scaled, self.addToPyOpt = addToPyOpt self.flipVolume = False - GeometricConstraint.__init__(self, self.name, self.nCon, self.lower, - self.upper, self.scale, self.DVGeo, - self.addToPyOpt) + GeometricConstraint.__init__( + self, self.name, self.nCon, self.lower, self.upper, self.scale, self.DVGeo, self.addToPyOpt + ) # First thing we can do is embed the coordinates into DVGeo # with the name provided: @@ -3914,7 +4184,6 @@ def __init__(self, name, nSpan, nChord, coords, lower, upper, scaled, # Now get the reference volume self.V0 = self.evalVolume() - def evalFunctions(self, funcs, config): """ Evaluate the function this object has and place in the funcs dictionary @@ -3948,9 +4217,7 @@ def evalFunctionsSens(self, funcsSens, config): dVdPt /= self.V0 # Now compute the DVGeo total sensitivity: - funcsSens[self.name] = self.DVGeo.totalSensitivity( - dVdPt, self.name, config=config) - + funcsSens[self.name] = self.DVGeo.totalSensitivity(dVdPt, self.name, config=config) def writeTecplot(self, handle): """ @@ -3959,15 +4226,12 @@ def writeTecplot(self, handle): # Reshape coordinates back to 3D format x = self.coords.reshape([self.nSpan, self.nChord, 2, 3]) - handle.write("ZONE T=\"%s\" I=%d J=%d K=%d\n"%( - self.name, self.nSpan, self.nChord, 2)) + handle.write('ZONE T="%s" I=%d J=%d K=%d\n' % (self.name, self.nSpan, self.nChord, 2)) handle.write("DATAPACKING=POINT\n") for k in range(2): for j in range(self.nChord): for i in range(self.nSpan): - handle.write('%f %f %f\n'%(x[i, j, k, 0], - x[i, j, k, 1], - x[i, j, k, 2])) + handle.write("%f %f %f\n" % (x[i, j, k, 0], x[i, j, k, 1], x[i, j, k, 2])) def evalVolume(self): """ @@ -3975,11 +4239,18 @@ def evalVolume(self): """ Volume = 0.0 x = self.coords.reshape((self.nSpan, self.nChord, 2, 3)) - for j in range(self.nChord-1): - for i in range(self.nSpan-1): + for j in range(self.nChord - 1): + for i in range(self.nSpan - 1): Volume += self.evalVolumeHex( - x[i, j, 0], x[i+1, j, 0], x[i, j+1, 0], x[i+1, j+1, 0], - x[i, j, 1], x[i+1, j, 1], x[i, j+1, 1], x[i+1, j+1, 1]) + x[i, j, 0], + x[i + 1, j, 0], + x[i, j + 1, 0], + x[i + 1, j + 1, 0], + x[i, j, 1], + x[i + 1, j, 1], + x[i, j + 1, 1], + x[i + 1, j + 1, 1], + ) if Volume < 0: Volume = -Volume @@ -3994,13 +4265,26 @@ def evalVolumeSens(self): """ x = self.coords.reshape((self.nSpan, self.nChord, 2, 3)) xb = numpy.zeros_like(x) - for j in range(self.nChord-1): - for i in range(self.nSpan-1): + for j in range(self.nChord - 1): + for i in range(self.nSpan - 1): self.evalVolumeHex_b( - x[i, j, 0], x[i+1, j, 0], x[i, j+1, 0], x[i+1, j+1, 0], - x[i, j, 1], x[i+1, j, 1], x[i, j+1, 1], x[i+1, j+1, 1], - xb[i, j, 0], xb[i+1, j, 0], xb[i, j+1, 0], xb[i+1, j+1, 0], - xb[i, j, 1], xb[i+1, j, 1], xb[i, j+1, 1], xb[i+1, j+1, 1]) + x[i, j, 0], + x[i + 1, j, 0], + x[i, j + 1, 0], + x[i + 1, j + 1, 0], + x[i, j, 1], + x[i + 1, j, 1], + x[i, j + 1, 1], + x[i + 1, j + 1, 1], + xb[i, j, 0], + xb[i + 1, j, 0], + xb[i, j + 1, 0], + xb[i + 1, j + 1, 0], + xb[i, j, 1], + xb[i + 1, j, 1], + xb[i, j + 1, 1], + xb[i + 1, j + 1, 1], + ) # We haven't divided by 6.0 yet...lets do it here.... xb /= 6.0 @@ -4008,7 +4292,7 @@ def evalVolumeSens(self): xb = -xb # Reshape back to flattened array for DVGeo - xb = xb.reshape((self.nSpan*self.nChord*2, 3)) + xb = xb.reshape((self.nSpan * self.nChord * 2, 3)) return xb @@ -4039,19 +4323,20 @@ def volpym(self, a, b, c, d, p): """ Compute volume of a square-based pyramid """ - fourth = 1.0/4.0 + fourth = 1.0 / 4.0 - volpym = (p[0] - fourth*(a[0] + b[0] + c[0] + d[0])) \ - * ((a[1] - c[1])*(b[2] - d[2]) - (a[2] - c[2])*(b[1] - d[1])) + \ - (p[1] - fourth*(a[1] + b[1] + c[1] + d[1])) \ - * ((a[2] - c[2])*(b[0] - d[0]) - (a[0] - c[0])*(b[2] - d[2])) + \ - (p[2] - fourth*(a[2] + b[2] + c[2] + d[2])) \ - * ((a[0] - c[0])*(b[1] - d[1]) - (a[1] - c[1])*(b[0] - d[0])) + volpym = ( + (p[0] - fourth * (a[0] + b[0] + c[0] + d[0])) + * ((a[1] - c[1]) * (b[2] - d[2]) - (a[2] - c[2]) * (b[1] - d[1])) + + (p[1] - fourth * (a[1] + b[1] + c[1] + d[1])) + * ((a[2] - c[2]) * (b[0] - d[0]) - (a[0] - c[0]) * (b[2] - d[2])) + + (p[2] - fourth * (a[2] + b[2] + c[2] + d[2])) + * ((a[0] - c[0]) * (b[1] - d[1]) - (a[1] - c[1]) * (b[0] - d[0])) + ) return volpym - def evalVolumeHex_b(self, x0, x1, x2, x3, x4, x5, x6, x7, - x0b, x1b, x2b, x3b, x4b, x5b, x6b, x7b): + def evalVolumeHex_b(self, x0, x1, x2, x3, x4, x5, x6, x7, x0b, x1b, x2b, x3b, x4b, x5b, x6b, x7b): """ Evaluate the derivative of the volume defined by the 8 coordinates in the array x. @@ -4093,29 +4378,29 @@ def volpym_b(self, a, b, c, d, p, ab, bb, cb, db, pb): fortran code and converted to python to use vectors for the points. """ - fourth = 1.0/4.0 + fourth = 1.0 / 4.0 volpymb = 1.0 - tempb = ((a[1]-c[1])*(b[2]-d[2])-(a[2]-c[2])*(b[1]-d[1]))*volpymb - tempb0 = -(fourth*tempb) - tempb1 = (p[0]-fourth*(a[0]+b[0]+c[0]+d[0]))*volpymb - tempb2 = (b[2]-d[2])*tempb1 - tempb3 = (a[1]-c[1])*tempb1 - tempb4 = -((b[1]-d[1])*tempb1) - tempb5 = -((a[2]-c[2])*tempb1) - tempb6 = ((a[2]-c[2])*(b[0]-d[0])-(a[0]-c[0])*(b[2]-d[2]))*volpymb - tempb7 = -(fourth*tempb6) - tempb8 = (p[1]-fourth*(a[1]+b[1]+c[1]+d[1]))*volpymb - tempb9 = (b[0]-d[0])*tempb8 - tempb10 = (a[2]-c[2])*tempb8 - tempb11 = -((b[2]-d[2])*tempb8) - tempb12 = -((a[0]-c[0])*tempb8) - tempb13 = ((a[0]-c[0])*(b[1]-d[1])-(a[1]-c[1])*(b[0]-d[0]))*volpymb - tempb14 = -(fourth*tempb13) - tempb15 = (p[2]-fourth*(a[2]+b[2]+c[2]+d[2]))*volpymb - tempb16 = (b[1]-d[1])*tempb15 - tempb17 = (a[0]-c[0])*tempb15 - tempb18 = -((b[0]-d[0])*tempb15) - tempb19 = -((a[1]-c[1])*tempb15) + tempb = ((a[1] - c[1]) * (b[2] - d[2]) - (a[2] - c[2]) * (b[1] - d[1])) * volpymb + tempb0 = -(fourth * tempb) + tempb1 = (p[0] - fourth * (a[0] + b[0] + c[0] + d[0])) * volpymb + tempb2 = (b[2] - d[2]) * tempb1 + tempb3 = (a[1] - c[1]) * tempb1 + tempb4 = -((b[1] - d[1]) * tempb1) + tempb5 = -((a[2] - c[2]) * tempb1) + tempb6 = ((a[2] - c[2]) * (b[0] - d[0]) - (a[0] - c[0]) * (b[2] - d[2])) * volpymb + tempb7 = -(fourth * tempb6) + tempb8 = (p[1] - fourth * (a[1] + b[1] + c[1] + d[1])) * volpymb + tempb9 = (b[0] - d[0]) * tempb8 + tempb10 = (a[2] - c[2]) * tempb8 + tempb11 = -((b[2] - d[2]) * tempb8) + tempb12 = -((a[0] - c[0]) * tempb8) + tempb13 = ((a[0] - c[0]) * (b[1] - d[1]) - (a[1] - c[1]) * (b[0] - d[0])) * volpymb + tempb14 = -(fourth * tempb13) + tempb15 = (p[2] - fourth * (a[2] + b[2] + c[2] + d[2])) * volpymb + tempb16 = (b[1] - d[1]) * tempb15 + tempb17 = (a[0] - c[0]) * tempb15 + tempb18 = -((b[0] - d[0]) * tempb15) + tempb19 = -((a[1] - c[1]) * tempb15) pb[0] = pb[0] + tempb ab[0] = ab[0] + tempb16 + tempb11 + tempb0 bb[0] = bb[0] + tempb19 + tempb10 + tempb0 @@ -4138,8 +4423,7 @@ class CompositeVolumeConstraint(GeometricConstraint): group of other VolumeConstraints. """ - def __init__(self, name, vols, lower, upper, scaled, scale, - DVGeo, addToPyOpt): + def __init__(self, name, vols, lower, upper, scaled, scale, DVGeo, addToPyOpt): self.name = name self.nCon = 1 self.vols = vols @@ -4151,9 +4435,9 @@ def __init__(self, name, vols, lower, upper, scaled, scale, self.DVGeo = DVGeo self.addToPyOpt = addToPyOpt - GeometricConstraint.__init__(self, self.name, self.nCon, self.lower, - self.upper, self.scale, self.DVGeo, - self.addToPyOpt) + GeometricConstraint.__init__( + self, self.name, self.nCon, self.lower, self.upper, self.scale, self.DVGeo, self.addToPyOpt + ) # Now get the reference volume self.V0 = 0.0 @@ -4188,7 +4472,7 @@ def evalFunctionsSens(self, funcsSens, config): """ nDV = self.DVGeo.getNDV() if nDV > 0: - tmp = [] # List of dict derivatives + tmp = [] # List of dict derivatives for vol in self.vols: dVdPt = vol.evalVolumeSens() if self.scaled: @@ -4201,20 +4485,19 @@ def evalFunctionsSens(self, funcsSens, config): for key in tmp[i]: funcsSens[self.name][key] += tmp[i][key] - - def writeTecplot(self, handle): """No need to write the composite volume since each of the individual ones are already written""" pass + class LinearConstraint(object): """ This class is used to represet a set of generic set of linear constriants coupling local shape variables together. """ - def __init__(self, name, indSetA, indSetB, factorA, factorB, - lower, upper, DVGeo, config): + + def __init__(self, name, indSetA, indSetB, factorA, factorB, lower, upper, DVGeo, config): # No error checking here since the calling routine should have # already done it. self.name = name @@ -4254,7 +4537,7 @@ def evalFunctions(self, funcs): cons.extend(self.jac[key].dot(self.DVGeo.DV_listSpanwiseLocal[key].value)) else: raise Error(f"con {self.name} diffined wrt {key}, but {key} not found in DVGeo") - funcs[self.name] = numpy.array(cons).real.astype('d') + funcs[self.name] = numpy.array(cons).real.astype("d") def evalFunctionsSens(self, funcsSens): """ @@ -4275,9 +4558,17 @@ def addConstraintsPyOpt(self, optProb): """ if self.ncon > 0: for key in self.jac: - optProb.addConGroup(self.name+'_'+key, self.jac[key].shape[0], - lower=self.lower, upper=self.upper, scale=1.0, - linear=True, wrt=key, jac={key:self.jac[key]}) + optProb.addConGroup( + self.name + "_" + key, + self.jac[key].shape[0], + lower=self.lower, + upper=self.upper, + scale=1.0, + linear=True, + wrt=key, + jac={key: self.jac[key]}, + ) + def _finalize(self): """ We have postponed actually determining the constraint jacobian @@ -4289,10 +4580,10 @@ def _finalize(self): self.vizConIndices = {} # Local Shape Variables for key in self.DVGeo.DV_listLocal: - if self.config is None or self.config in self.DVGeo.DV_listLocal[key].config: + if self.config is None or self.config in self.DVGeo.DV_listLocal[key].config: # end for (indSet loop) - cons = self.DVGeo.DV_listLocal[key].mapIndexSets(self.indSetA,self.indSetB) + cons = self.DVGeo.DV_listLocal[key].mapIndexSets(self.indSetA, self.indSetB) ncon = len(cons) if ncon > 0: # Now form the jacobian: @@ -4310,10 +4601,10 @@ def _finalize(self): # Section local shape variables for key in self.DVGeo.DV_listSectionLocal: - if self.config is None or self.config in self.DVGeo.DV_listSectionLocal[key].config: + if self.config is None or self.config in self.DVGeo.DV_listSectionLocal[key].config: # end for (indSet loop) - cons = self.DVGeo.DV_listSectionLocal[key].mapIndexSets(self.indSetA,self.indSetB) + cons = self.DVGeo.DV_listSectionLocal[key].mapIndexSets(self.indSetA, self.indSetB) ncon = len(cons) if ncon > 0: # Now form the jacobian: @@ -4331,10 +4622,10 @@ def _finalize(self): # Section local shape variables for key in self.DVGeo.DV_listSpanwiseLocal: - if self.config is None or self.config in self.DVGeo.DV_listSpanwiseLocal[key].config: + if self.config is None or self.config in self.DVGeo.DV_listSpanwiseLocal[key].config: # end for (indSet loop) - cons = self.DVGeo.DV_listSpanwiseLocal[key].mapIndexSets(self.indSetA,self.indSetB) + cons = self.DVGeo.DV_listSpanwiseLocal[key].mapIndexSets(self.indSetA, self.indSetB) ncon = len(cons) if ncon > 0: # Now form the jacobian: @@ -4361,20 +4652,20 @@ def writeTecplot(self, handle): for key in self.vizConIndices: ncon = len(self.vizConIndices[key]) - nodes = numpy.zeros((ncon*2, 3)) + nodes = numpy.zeros((ncon * 2, 3)) for i in range(ncon): - nodes[2*i] = self.DVGeo.FFD.coef[self.indSetA[i]] - nodes[2*i+1] = self.DVGeo.FFD.coef[self.indSetB[i]] + nodes[2 * i] = self.DVGeo.FFD.coef[self.indSetA[i]] + nodes[2 * i + 1] = self.DVGeo.FFD.coef[self.indSetB[i]] - handle.write('Zone T=%s\n'% (self.name+'_'+key)) - handle.write('Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n'% ( - ncon*2, ncon)) - handle.write('DATAPACKING=POINT\n') - for i in range(ncon*2): - handle.write('%f %f %f\n'% (nodes[i, 0], nodes[i, 1], nodes[i, 2])) + handle.write("Zone T=%s\n" % (self.name + "_" + key)) + handle.write("Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n" % (ncon * 2, ncon)) + handle.write("DATAPACKING=POINT\n") + for i in range(ncon * 2): + handle.write("%f %f %f\n" % (nodes[i, 0], nodes[i, 1], nodes[i, 2])) for i in range(ncon): - handle.write('%d %d\n'% (2*i+1, 2*i+2)) + handle.write("%d %d\n" % (2 * i + 1, 2 * i + 2)) + class GearPostConstraint(GeometricConstraint): """ @@ -4382,9 +4673,21 @@ class GearPostConstraint(GeometricConstraint): parameter list is explained in the addVolumeConstaint() of the DVConstraints class """ - def __init__(self, name, wimpressCalc, up, down, thickLower, - thickUpper, thickScaled, MACFracLower, MACFracUpper, - DVGeo, addToPyOpt): + + def __init__( + self, + name, + wimpressCalc, + up, + down, + thickLower, + thickUpper, + thickScaled, + MACFracLower, + MACFracUpper, + DVGeo, + addToPyOpt, + ): self.name = name self.wimpress = wimpressCalc @@ -4397,9 +4700,7 @@ def __init__(self, name, wimpressCalc, up, down, thickLower, self.DVGeo = DVGeo self.addToPyOpt = addToPyOpt - GeometricConstraint.__init__(self, self.name, None, None, - None,None, self.DVGeo, - self.addToPyOpt) + GeometricConstraint.__init__(self, self.name, None, None, None, None, self.DVGeo, self.addToPyOpt) # First thing we can do is embed the coordinates into DVGeo # with the name provided: self.DVGeo.addPointSet(self.coords, self.name) @@ -4415,19 +4716,19 @@ def evalFunctions(self, funcs, config): # Compute the thickness constraint D = numpy.linalg.norm(self.coords[0] - self.coords[1]) if self.thickScaled: - D = D/self.D0 + D = D / self.D0 # Compute the values we need from the wimpress calc wfuncs = {} self.wimpress.evalFunctions(wfuncs) # Now the constraint value is - postLoc = 0.5*(self.coords[0, 0] + self.coords[1, 0]) - locCon = (postLoc - wfuncs['xLEMAC'])/wfuncs['MAC'] + postLoc = 0.5 * (self.coords[0, 0] + self.coords[1, 0]) + locCon = (postLoc - wfuncs["xLEMAC"]) / wfuncs["MAC"] # Final set of two constrains - funcs[self.name + '_thick'] = D - funcs[self.name + '_MAC'] = locCon + funcs[self.name + "_thick"] = D + funcs[self.name + "_MAC"] = locCon def evalFunctionsSens(self, funcsSens, config): """ @@ -4449,42 +4750,43 @@ def evalFunctionsSens(self, funcsSens, config): self.wimpress.evalFunctionsSens(wSens) # Accumulate the derivative into p1b and p2b - p1b, p2b = geo_utils.eDist_b( - self.coords[0, :], self.coords[1, :]) + p1b, p2b = geo_utils.eDist_b(self.coords[0, :], self.coords[1, :]) if self.thickScaled: p1b /= self.D0 p2b /= self.D0 - funcsSens[self.name + '_thick'] = self.DVGeo.totalSensitivity( - numpy.array([[p1b, p2b]]), self.name, config=config) + funcsSens[self.name + "_thick"] = self.DVGeo.totalSensitivity( + numpy.array([[p1b, p2b]]), self.name, config=config + ) # And now we need the sensitivty of the conLoc calc p1b[:] = 0 p2b[:] = 0 - p1b[0] += 0.5/wfuncs['MAC'] - p2b[0] += 0.5/wfuncs['MAC'] + p1b[0] += 0.5 / wfuncs["MAC"] + p2b[0] += 0.5 / wfuncs["MAC"] - tmpSens = self.DVGeo.totalSensitivity( - numpy.array([[p1b, p2b]]), self.name, config=config) + tmpSens = self.DVGeo.totalSensitivity(numpy.array([[p1b, p2b]]), self.name, config=config) # And we need the sensitity of conLoc wrt 'xLEMAC' and 'MAC' - postLoc = 0.5*(self.coords[0, 0] + self.coords[1, 0]) - for key in wSens['xLEMAC']: - tmpSens[key] -= wSens['xLEMAC'][key]/wfuncs['MAC'] - tmpSens[key] += wfuncs['xLEMAC']/wfuncs['MAC']**2 * wSens['MAC'][key] - tmpSens[key] -= postLoc/wfuncs['MAC']**2 * wSens['MAC'][key] - funcsSens[self.name + '_MAC'] = tmpSens + postLoc = 0.5 * (self.coords[0, 0] + self.coords[1, 0]) + for key in wSens["xLEMAC"]: + tmpSens[key] -= wSens["xLEMAC"][key] / wfuncs["MAC"] + tmpSens[key] += wfuncs["xLEMAC"] / wfuncs["MAC"] ** 2 * wSens["MAC"][key] + tmpSens[key] -= postLoc / wfuncs["MAC"] ** 2 * wSens["MAC"][key] + funcsSens[self.name + "_MAC"] = tmpSens def addConstraintsPyOpt(self, optProb): """ Add the constraints to pyOpt, if the flag is set """ if self.addToPyOpt: - optProb.addCon(self.name + '_thick', lower=self.thickLower, - upper=self.thickUpper, wrt=self.DVGeo.getVarNames()) + optProb.addCon( + self.name + "_thick", lower=self.thickLower, upper=self.thickUpper, wrt=self.DVGeo.getVarNames() + ) - optProb.addCon(self.name + '_MAC', lower=self.MACFracLower, - upper=self.MACFracUpper, wrt=self.DVGeo.getVarNames()) + optProb.addCon( + self.name + "_MAC", lower=self.MACFracLower, upper=self.MACFracUpper, wrt=self.DVGeo.getVarNames() + ) class CircularityConstraint(GeometricConstraint): @@ -4495,29 +4797,27 @@ class CircularityConstraint(GeometricConstraint): The user should not have to deal with this class directly. """ - def __init__(self, name, center, coords, lower, upper, scale, DVGeo, - addToPyOpt): + def __init__(self, name, center, coords, lower, upper, scale, DVGeo, addToPyOpt): self.name = name - self.center = numpy.array(center).reshape((1,3)) + self.center = numpy.array(center).reshape((1, 3)) self.coords = coords - self.nCon = self.coords.shape[0]-1 + self.nCon = self.coords.shape[0] - 1 self.lower = lower self.upper = upper self.scale = scale self.DVGeo = DVGeo self.addToPyOpt = addToPyOpt - GeometricConstraint.__init__(self, self.name, self.nCon, self.lower, - self.upper, self.scale, self.DVGeo, - self.addToPyOpt) - + GeometricConstraint.__init__( + self, self.name, self.nCon, self.lower, self.upper, self.scale, self.DVGeo, self.addToPyOpt + ) self.X = numpy.zeros(self.nCon) # First thing we can do is embed the coordinates into DVGeo # with the name provided: - self.DVGeo.addPointSet(self.coords, self.name+'coords') - self.DVGeo.addPointSet(self.center, self.name+'center') + self.DVGeo.addPointSet(self.coords, self.name + "coords") + self.DVGeo.addPointSet(self.center, self.name + "center") def evalFunctions(self, funcs, config): """ @@ -4529,10 +4829,10 @@ def evalFunctions(self, funcs, config): Dictionary to place function values """ # Pull out the most recent set of coordinates: - self.coords = self.DVGeo.update(self.name+'coords', config=config) - self.center = self.DVGeo.update(self.name+'center', config=config) + self.coords = self.DVGeo.update(self.name + "coords", config=config) + self.center = self.DVGeo.update(self.name + "center", config=config) - self._computeLengths(self.center,self.coords,self.X) + self._computeLengths(self.center, self.coords, self.X) funcs[self.name] = self.X @@ -4549,62 +4849,58 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dLndPt = numpy.zeros((self.nCon, - self.coords.shape[0], - self.coords.shape[1])) - dLndCn = numpy.zeros((self.nCon, - self.center.shape[0], - self.center.shape[1])) + dLndPt = numpy.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) + dLndCn = numpy.zeros((self.nCon, self.center.shape[0], self.center.shape[1])) xb = numpy.zeros(self.nCon) for con in range(self.nCon): - centerb = dLndCn[con,0,:] - coordsb = dLndPt[con,:,:] - xb[:] = 0. - xb[con] = 1. + centerb = dLndCn[con, 0, :] + coordsb = dLndPt[con, :, :] + xb[:] = 0.0 + xb[con] = 1.0 # reflength2 = 0 # for i in range(3): # reflength2 = reflength2 + (center[i]-coords[0,i])**2 - reflength2 = numpy.sum((self.center-self.coords[0,:])**2) + reflength2 = numpy.sum((self.center - self.coords[0, :]) ** 2) reflength2b = 0.0 for i in range(self.nCon): # length2 = 0 # for j in range(3): # length2 = length2 + (center[j]-coords[i+1, j])**2 - length2 = numpy.sum((self.center-self.coords[i+1,:])**2) + length2 = numpy.sum((self.center - self.coords[i + 1, :]) ** 2) - if (length2/reflength2 == 0.0): + if length2 / reflength2 == 0.0: tempb1 = 0.0 else: - tempb1 = xb[i]/(2.0*numpy.sqrt(length2/reflength2)*reflength2) + tempb1 = xb[i] / (2.0 * numpy.sqrt(length2 / reflength2) * reflength2) length2b = tempb1 - reflength2b = reflength2b - length2*tempb1/reflength2 + reflength2b = reflength2b - length2 * tempb1 / reflength2 xb[i] = 0.0 for j in reversed(range(3)): - tempb0 = 2*(self.center[0,j]-self.coords[i+1, j])*length2b + tempb0 = 2 * (self.center[0, j] - self.coords[i + 1, j]) * length2b centerb[j] = centerb[j] + tempb0 - coordsb[i+1, j] = coordsb[i+1, j] - tempb0 - for j in reversed(range(3)):#DO i=3,1,-1 - tempb = 2*(self.center[0,j]-self.coords[0, j])*reflength2b + coordsb[i + 1, j] = coordsb[i + 1, j] - tempb0 + for j in reversed(range(3)): # DO i=3,1,-1 + tempb = 2 * (self.center[0, j] - self.coords[0, j]) * reflength2b centerb[j] = centerb[j] + tempb coordsb[0, j] = coordsb[0, j] - tempb - tmpPt = self.DVGeo.totalSensitivity(dLndPt, self.name+'coords', config=config) - tmpCn = self.DVGeo.totalSensitivity(dLndCn, self.name+'center', config=config) + tmpPt = self.DVGeo.totalSensitivity(dLndPt, self.name + "coords", config=config) + tmpCn = self.DVGeo.totalSensitivity(dLndCn, self.name + "center", config=config) tmpTotal = {} for key in tmpPt: - tmpTotal[key] = tmpPt[key]+tmpCn[key] + tmpTotal[key] = tmpPt[key] + tmpCn[key] funcsSens[self.name] = tmpTotal - def _computeLengths(self,center,coords,X): - ''' + def _computeLengths(self, center, coords, X): + """ compute the lengths from the center and coordinates - ''' - reflength2 = numpy.sum((center-coords[0,:])**2) + """ + reflength2 = numpy.sum((center - coords[0, :]) ** 2) for i in range(self.nCon): - length2 = numpy.sum((self.center-self.coords[i+1,:])**2) - X[i] = numpy.sqrt(length2/reflength2) + length2 = numpy.sum((self.center - self.coords[i + 1, :]) ** 2) + X[i] = numpy.sqrt(length2 / reflength2) def writeTecplot(self, handle): """ @@ -4612,25 +4908,22 @@ def writeTecplot(self, handle): to the open file handle """ - handle.write('Zone T=%s_coords\n'% self.name) - handle.write('Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n'% ( - len(self.coords), len(self.coords)-1)) - handle.write('DATAPACKING=POINT\n') + handle.write("Zone T=%s_coords\n" % self.name) + handle.write("Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n" % (len(self.coords), len(self.coords) - 1)) + handle.write("DATAPACKING=POINT\n") for i in range(len(self.coords)): - handle.write('%f %f %f\n'% (self.coords[i, 0], self.coords[i, 1], - self.coords[i, 2])) + handle.write("%f %f %f\n" % (self.coords[i, 0], self.coords[i, 1], self.coords[i, 2])) - for i in range(len(self.coords)-1): - handle.write('%d %d\n'% (i+1, i+2)) + for i in range(len(self.coords) - 1): + handle.write("%d %d\n" % (i + 1, i + 2)) + + handle.write("Zone T=%s_center\n" % self.name) + handle.write("Nodes = 2, Elements = 1 ZONETYPE=FELINESEG\n") + handle.write("DATAPACKING=POINT\n") + handle.write("%f %f %f\n" % (self.center[0, 0], self.center[0, 1], self.center[0, 2])) + handle.write("%f %f %f\n" % (self.center[0, 0], self.center[0, 1], self.center[0, 2])) + handle.write("%d %d\n" % (1, 2)) - handle.write('Zone T=%s_center\n'% self.name) - handle.write('Nodes = 2, Elements = 1 ZONETYPE=FELINESEG\n') - handle.write('DATAPACKING=POINT\n') - handle.write('%f %f %f\n'% (self.center[0,0], self.center[0,1], - self.center[0,2])) - handle.write('%f %f %f\n'% (self.center[0,0], self.center[0,1], - self.center[0,2])) - handle.write('%d %d\n'% (1, 2)) class PlanarityConstraint(GeometricConstraint): """ @@ -4641,19 +4934,18 @@ class PlanarityConstraint(GeometricConstraint): The user should not have to deal with this class directly. """ - def __init__(self, name, axis, origin, p0, v1, v2, lower, upper, scale, - DVGeo, addToPyOpt): + def __init__(self, name, axis, origin, p0, v1, v2, lower, upper, scale, DVGeo, addToPyOpt): self.name = name - self.nCon = 1#len(p0)*3 + self.nCon = 1 # len(p0)*3 self.lower = lower self.upper = upper self.scale = scale self.DVGeo = DVGeo self.addToPyOpt = addToPyOpt - GeometricConstraint.__init__(self, self.name, self.nCon, self.lower, - self.upper, self.scale, self.DVGeo, - self.addToPyOpt) + GeometricConstraint.__init__( + self, self.name, self.nCon, self.lower, self.upper, self.scale, self.DVGeo, self.addToPyOpt + ) # create the output array self.X = numpy.zeros(self.nCon) @@ -4662,19 +4954,18 @@ def __init__(self, name, axis, origin, p0, v1, v2, lower, upper, scale, # The first thing we do is convert v1 and v2 to coords self.axis = axis self.p0 = p0 - self.p1 = v1+p0 - self.p2 = v2+p0 + self.p1 = v1 + p0 + self.p2 = v2 + p0 self.origin = origin # Now embed the coordinates and origin into DVGeo # with the name provided: # TODO this is duplicating a DVGeo pointset (same as the surface which originally created the constraint) # issue 53 - self.DVGeo.addPointSet(self.p0, self.name+'p0') - self.DVGeo.addPointSet(self.p1, self.name+'p1') - self.DVGeo.addPointSet(self.p2, self.name+'p2') - self.DVGeo.addPointSet(self.origin, self.name+'origin') - + self.DVGeo.addPointSet(self.p0, self.name + "p0") + self.DVGeo.addPointSet(self.p1, self.name + "p1") + self.DVGeo.addPointSet(self.p2, self.name + "p2") + self.DVGeo.addPointSet(self.origin, self.name + "origin") def evalFunctions(self, funcs, config): """ @@ -4686,21 +4977,21 @@ def evalFunctions(self, funcs, config): Dictionary to place function values """ # Pull out the most recent set of coordinates: - self.p0 = self.DVGeo.update(self.name+'p0', config=config) - self.p1 = self.DVGeo.update(self.name+'p1', config=config) - self.p2 = self.DVGeo.update(self.name+'p2', config=config) - self.origin = self.DVGeo.update(self.name+'origin', config=config) + self.p0 = self.DVGeo.update(self.name + "p0", config=config) + self.p1 = self.DVGeo.update(self.name + "p1", config=config) + self.p2 = self.DVGeo.update(self.name + "p2", config=config) + self.origin = self.DVGeo.update(self.name + "origin", config=config) - allPoints = numpy.vstack([self.p0,self.p1,self.p2]) + allPoints = numpy.vstack([self.p0, self.p1, self.p2]) # Compute the distance from the origin to each point - dist = allPoints-self.origin + dist = allPoints - self.origin - #project it onto the axis + # project it onto the axis self.X[0] = 0 - for i in range(self.n*3): - self.X[0] += numpy.dot(self.axis,dist[i,:])**2 - self.X[0]= numpy.sqrt(self.X[0]) + for i in range(self.n * 3): + self.X[0] += numpy.dot(self.axis, dist[i, :]) ** 2 + self.X[0] = numpy.sqrt(self.X[0]) funcs[self.name] = self.X def evalFunctionsSens(self, funcsSens, config): @@ -4716,133 +5007,113 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dPdp0 = numpy.zeros((self.nCon, - self.p0.shape[0], - self.p0.shape[1])) - dPdp1 = numpy.zeros((self.nCon, - self.p1.shape[0], - self.p1.shape[1])) + dPdp0 = numpy.zeros((self.nCon, self.p0.shape[0], self.p0.shape[1])) + dPdp1 = numpy.zeros((self.nCon, self.p1.shape[0], self.p1.shape[1])) - dPdp2 = numpy.zeros((self.nCon, - self.p2.shape[0], - self.p2.shape[1])) + dPdp2 = numpy.zeros((self.nCon, self.p2.shape[0], self.p2.shape[1])) - dPdO = numpy.zeros((self.nCon, - self.origin.shape[0], - self.origin.shape[1])) + dPdO = numpy.zeros((self.nCon, self.origin.shape[0], self.origin.shape[1])) # copy data into all points array # allpoints(1:n) = p0 # allpoints(n:2*n) = p1 # allpoints(2*n:3*n) = p2 - allPoints = numpy.vstack([self.p0,self.p1,self.p2]) + allPoints = numpy.vstack([self.p0, self.p1, self.p2]) # Compute the distance from the origin to each point # for i in range(n*3):#DO i=1,n*3 # for j in range(3):#DO j=1,3 # dist(i, j) = allpoints(i, j) - origin(j) - dist = allPoints-self.origin + dist = allPoints - self.origin - scalardist = numpy.zeros(self.n*3) + scalardist = numpy.zeros(self.n * 3) tmpX = 0 - for i in range(self.n*3): - scalardist[i] = numpy.dot(self.axis,dist[i,:]) - tmpX+=scalardist[i]**2 + for i in range(self.n * 3): + scalardist[i] = numpy.dot(self.axis, dist[i, :]) + tmpX += scalardist[i] ** 2 xb = numpy.zeros(self.nCon) axisb = numpy.zeros(3) - scalardistb = numpy.zeros((self.n*3)) - allpointsb = numpy.zeros((self.n*3,3)) - distb = numpy.zeros((self.n*3,3)) + scalardistb = numpy.zeros((self.n * 3)) + allpointsb = numpy.zeros((self.n * 3, 3)) + distb = numpy.zeros((self.n * 3, 3)) for con in range(self.nCon): - p0b = dPdp0[con,:,:] - p1b = dPdp1[con,:,:] - p2b = dPdp2[con,:,:] - originb = dPdO[con,0,:] + p0b = dPdp0[con, :, :] + p1b = dPdp1[con, :, :] + p2b = dPdp2[con, :, :] + originb = dPdO[con, 0, :] axisb[:] = 0.0 originb[:] = 0.0 scalardistb[:] = 0.0 - allpointsb[:,:] = 0.0 - distb[:,:] = 0.0 + allpointsb[:, :] = 0.0 + distb[:, :] = 0.0 xb[:] = 0 xb[con] = 1.0 - if(self.X[0] == 0.0): + if self.X[0] == 0.0: xb[con] = 0.0 else: - xb[con] = xb[con]/(2.0*numpy.sqrt(tmpX)) + xb[con] = xb[con] / (2.0 * numpy.sqrt(tmpX)) - for i in reversed(range(self.n*3)):#DO i=3*n,1,-1 - scalardistb[i] = scalardistb[i] + 2.0*scalardist[i]*xb[con]#/(self.n*3) + for i in reversed(range(self.n * 3)): # DO i=3*n,1,-1 + scalardistb[i] = scalardistb[i] + 2.0 * scalardist[i] * xb[con] # /(self.n*3) # CALL DOT_B(axis, axisb, dist(i, :), distb(i, :), scalardist(i), & # & scalardistb(i)) - axisb, distb[i,:] = geo_utils.dot_b(self.axis, dist[i, :], scalardistb[i]) + axisb, distb[i, :] = geo_utils.dot_b(self.axis, dist[i, :], scalardistb[i]) scalardistb[i] = 0.0 - for j in reversed(range(3)):#DO j=3,1,-1 + for j in reversed(range(3)): # DO j=3,1,-1 allpointsb[i, j] = allpointsb[i, j] + distb[i, j] originb[j] = originb[j] - distb[i, j] distb[i, j] = 0.0 - p2b[:,:] = 0.0 - p2b[:,:] = allpointsb[2*self.n:3*self.n] - allpointsb[2*self.n:3*self.n] = 0.0 - p1b[:,:] = 0.0 - p1b[:,:] = allpointsb[self.n:2*self.n] - allpointsb[self.n:2*self.n] = 0.0 - p0b[:,:] = 0.0 - p0b[:,:] = allpointsb[0:self.n] - + p2b[:, :] = 0.0 + p2b[:, :] = allpointsb[2 * self.n : 3 * self.n] + allpointsb[2 * self.n : 3 * self.n] = 0.0 + p1b[:, :] = 0.0 + p1b[:, :] = allpointsb[self.n : 2 * self.n] + allpointsb[self.n : 2 * self.n] = 0.0 + p0b[:, :] = 0.0 + p0b[:, :] = allpointsb[0 : self.n] # map back to DVGeo - tmpp0 = self.DVGeo.totalSensitivity(dPdp0, self.name+'p0', - config=config) - tmpp1 = self.DVGeo.totalSensitivity(dPdp1, self.name+'p1', - config=config) - tmpp2 = self.DVGeo.totalSensitivity(dPdp2, self.name+'p2', - config=config) - tmpO = self.DVGeo.totalSensitivity(dPdO, self.name+'origin', - config=config) + tmpp0 = self.DVGeo.totalSensitivity(dPdp0, self.name + "p0", config=config) + tmpp1 = self.DVGeo.totalSensitivity(dPdp1, self.name + "p1", config=config) + tmpp2 = self.DVGeo.totalSensitivity(dPdp2, self.name + "p2", config=config) + tmpO = self.DVGeo.totalSensitivity(dPdO, self.name + "origin", config=config) tmpTotal = {} for key in tmpp0: - tmpTotal[key] = tmpp0[key]+tmpp1[key]+tmpp2[key]+tmpO[key] - + tmpTotal[key] = tmpp0[key] + tmpp1[key] + tmpp2[key] + tmpO[key] funcsSens[self.name] = tmpTotal - def writeTecplot(self, handle): """ Write the visualization of this set of thickness constraints to the open file handle """ - handle.write('Zone T=%s_surface\n'% self.name) - handle.write('Nodes = %d, Elements = %d ZONETYPE=FETRIANGLE\n'% ( - 3*self.n, self.n)) - handle.write('DATAPACKING=POINT\n') + handle.write("Zone T=%s_surface\n" % self.name) + handle.write("Nodes = %d, Elements = %d ZONETYPE=FETRIANGLE\n" % (3 * self.n, self.n)) + handle.write("DATAPACKING=POINT\n") for i in range(self.n): - handle.write('%f %f %f\n'% (self.p0[i, 0], self.p0[i, 1], - self.p0[i, 2])) + handle.write("%f %f %f\n" % (self.p0[i, 0], self.p0[i, 1], self.p0[i, 2])) for i in range(self.n): - handle.write('%f %f %f\n'% (self.p1[i, 0], self.p1[i, 1], - self.p1[i, 2])) + handle.write("%f %f %f\n" % (self.p1[i, 0], self.p1[i, 1], self.p1[i, 2])) for i in range(self.n): - handle.write('%f %f %f\n'% (self.p2[i, 0], self.p2[i, 1], - self.p2[i, 2])) + handle.write("%f %f %f\n" % (self.p2[i, 0], self.p2[i, 1], self.p2[i, 2])) for i in range(self.n): - handle.write('%d %d %d\n'% (i+1, i+self.n+1, i+self.n*2+1)) + handle.write("%d %d %d\n" % (i + 1, i + self.n + 1, i + self.n * 2 + 1)) + + handle.write("Zone T=%s_center\n" % self.name) + handle.write("Nodes = 2, Elements = 1 ZONETYPE=FELINESEG\n") + handle.write("DATAPACKING=POINT\n") + handle.write("%f %f %f\n" % (self.origin[0, 0], self.origin[0, 1], self.origin[0, 2])) + handle.write("%f %f %f\n" % (self.origin[0, 0], self.origin[0, 1], self.origin[0, 2])) + handle.write("%d %d\n" % (1, 2)) - handle.write('Zone T=%s_center\n'% self.name) - handle.write('Nodes = 2, Elements = 1 ZONETYPE=FELINESEG\n') - handle.write('DATAPACKING=POINT\n') - handle.write('%f %f %f\n'% (self.origin[0,0], self.origin[0,1], - self.origin[0,2])) - handle.write('%f %f %f\n'% (self.origin[0,0], self.origin[0,1], - self.origin[0,2])) - handle.write('%d %d\n'% (1, 2)) class ColinearityConstraint(GeometricConstraint): """ @@ -4854,8 +5125,7 @@ class ColinearityConstraint(GeometricConstraint): The user should not have to deal with this class directly. """ - def __init__(self, name, axis, origin, coords, lower, upper, scale, - DVGeo, addToPyOpt): + def __init__(self, name, axis, origin, coords, lower, upper, scale, DVGeo, addToPyOpt): self.name = name self.nCon = len(coords) self.lower = lower @@ -4864,9 +5134,9 @@ def __init__(self, name, axis, origin, coords, lower, upper, scale, self.DVGeo = DVGeo self.addToPyOpt = addToPyOpt - GeometricConstraint.__init__(self, self.name, self.nCon, self.lower, - self.upper, self.scale, self.DVGeo, - self.addToPyOpt) + GeometricConstraint.__init__( + self, self.name, self.nCon, self.lower, self.upper, self.scale, self.DVGeo, self.addToPyOpt + ) # create the output array self.X = numpy.zeros(self.nCon) @@ -4878,9 +5148,8 @@ def __init__(self, name, axis, origin, coords, lower, upper, scale, # Now embed the coordinates and origin into DVGeo # with the name provided: - self.DVGeo.addPointSet(self.origin, self.name+'origin') - self.DVGeo.addPointSet(self.coords, self.name+'coords') - + self.DVGeo.addPointSet(self.origin, self.name + "origin") + self.DVGeo.addPointSet(self.coords, self.name + "coords") def evalFunctions(self, funcs, config): """ @@ -4892,8 +5161,8 @@ def evalFunctions(self, funcs, config): Dictionary to place function values """ # Pull out the most recent set of coordinates: - self.coords = self.DVGeo.update(self.name+'coords', config=config) - self.origin = self.DVGeo.update(self.name+'origin', config=config) + self.coords = self.DVGeo.update(self.name + "coords", config=config) + self.origin = self.DVGeo.update(self.name + "origin", config=config) # # Compute the direction from each point to the origin # dirVec = self.origin-self.coords @@ -4904,7 +5173,7 @@ def evalFunctions(self, funcs, config): # for i in range(len(resultDir)): # self.X[i] = geo_utils.euclideanNorm(resultDir[i,:]) - self.X = self._computeDist(self.origin,self.coords,self.axis) + self.X = self._computeDist(self.origin, self.coords, self.axis) funcs[self.name] = self.X @@ -4921,21 +5190,15 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dCdPt = numpy.zeros((self.nCon, - self.coords.shape[0], - self.coords.shape[1])) - dCdOrigin = numpy.zeros((self.nCon, - self.origin.shape[0], - self.origin.shape[1])) - dCdAxis = numpy.zeros((self.nCon, - self.axis.shape[0], - self.axis.shape[1])) - - #Compute the direction from each point to the origin + dCdPt = numpy.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) + dCdOrigin = numpy.zeros((self.nCon, self.origin.shape[0], self.origin.shape[1])) + dCdAxis = numpy.zeros((self.nCon, self.axis.shape[0], self.axis.shape[1])) + + # Compute the direction from each point to the origin # for i in range(n): # for j in range(3): # dirvec[i, j] = origin[j] - coords[i, j] - dirVec = self.origin-self.coords + dirVec = self.origin - self.coords # axisb = 0.0 # dirvecb = 0.0 @@ -4944,103 +5207,97 @@ def evalFunctionsSens(self, funcsSens, config): # self.X[i] = 0 # for j in range(3): # self.X[i] = self.X[i] + resultdir[j]**2 - resultDir = numpy.cross(self.axis,dirVec) + resultDir = numpy.cross(self.axis, dirVec) tmpX = numpy.zeros(self.nCon) for i in range(len(resultDir)): - #self.X[i] = geo_utils.euclideanNorm(resultDir[i,:]) + # self.X[i] = geo_utils.euclideanNorm(resultDir[i,:]) for j in range(3): - tmpX[i] += resultDir[i,j]**2 + tmpX[i] += resultDir[i, j] ** 2 resultdirb = numpy.zeros(3) dirvecb = numpy.zeros_like(dirVec) xb = numpy.zeros(self.nCon) for con in range(self.nCon): - originb = dCdOrigin[con,0,:] - coordsb = dCdPt[con,:,:] - axisb = dCdAxis[con,0,:] - xb[:] = 0. - xb[con] = 1. + originb = dCdOrigin[con, 0, :] + coordsb = dCdPt[con, :, :] + axisb = dCdAxis[con, 0, :] + xb[:] = 0.0 + xb[con] = 1.0 for i in range(self.nCon): - if (tmpX[i] == 0.0): + if tmpX[i] == 0.0: xb[i] = 0.0 else: - xb[i] = xb[i]/(2.0*numpy.sqrt(tmpX[i])) + xb[i] = xb[i] / (2.0 * numpy.sqrt(tmpX[i])) resultdirb[:] = 0.0 - for j in reversed(range(3)):#DO j=3,1,-1 - resultdirb[j] = resultdirb[j] + 2*resultDir[i,j]*xb[i] + for j in reversed(range(3)): # DO j=3,1,-1 + resultdirb[j] = resultdirb[j] + 2 * resultDir[i, j] * xb[i] xb[i] = 0.0 - #CALL CROSS_B(axis, axisb, dirvec(i, :), dirvecb(i, :), resultdirb) - axisb, dirvecb[i,:] = geo_utils.cross_b(self.axis[0,:],dirVec[i, :], resultdirb) + # CALL CROSS_B(axis, axisb, dirvec(i, :), dirvecb(i, :), resultdirb) + axisb, dirvecb[i, :] = geo_utils.cross_b(self.axis[0, :], dirVec[i, :], resultdirb) # coordsb = 0.0 # originb = 0.0 - for i in reversed(range(len(coordsb))):#DO i=n,1,-1 - for j in reversed(range(3)):#DO j=3,1,-1 + for i in reversed(range(len(coordsb))): # DO i=n,1,-1 + for j in reversed(range(3)): # DO j=3,1,-1 originb[j] = originb[j] + dirvecb[i, j] coordsb[i, j] = coordsb[i, j] - dirvecb[i, j] dirvecb[i, j] = 0.0 - tmpPt = self.DVGeo.totalSensitivity(dCdPt, self.name+'coords', - config=config) - tmpOrigin = self.DVGeo.totalSensitivity(dCdOrigin, self.name+'origin', - config=config) + tmpPt = self.DVGeo.totalSensitivity(dCdPt, self.name + "coords", config=config) + tmpOrigin = self.DVGeo.totalSensitivity(dCdOrigin, self.name + "origin", config=config) tmpTotal = {} for key in tmpPt: - tmpTotal[key] = tmpPt[key]+tmpOrigin[key] + tmpTotal[key] = tmpPt[key] + tmpOrigin[key] - tmpTotal[self.name+'axis'] = dCdAxis + tmpTotal[self.name + "axis"] = dCdAxis funcsSens[self.name] = tmpTotal - def addVariablesPyOpt(self,optProb): + def addVariablesPyOpt(self, optProb): """ Add the axis variable for the colinearity constraint to pyOpt """ if self.addVarToPyOpt: - optProb.addVarGroup(dv.name, dv.nVal, 'c', value=dv.value, - lower=dv.lower, upper=dv.upper, - scale=dv.scale) + optProb.addVarGroup(dv.name, dv.nVal, "c", value=dv.value, lower=dv.lower, upper=dv.upper, scale=dv.scale) def writeTecplot(self, handle): """ Write the visualization of this set of thickness constraints to the open file handle """ - handle.write('Zone T=%s_coords\n'% self.name) - handle.write('Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n'% ( - len(self.coords)+1, len(self.coords))) - handle.write('DATAPACKING=POINT\n') - handle.write('%f %f %f\n'% (self.origin[0,0], self.origin[0,1], - self.origin[0,2])) + handle.write("Zone T=%s_coords\n" % self.name) + handle.write("Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n" % (len(self.coords) + 1, len(self.coords))) + handle.write("DATAPACKING=POINT\n") + handle.write("%f %f %f\n" % (self.origin[0, 0], self.origin[0, 1], self.origin[0, 2])) for i in range(len(self.coords)): - handle.write('%f %f %f\n'% (self.coords[i, 0], self.coords[i, 1], - self.coords[i, 2])) + handle.write("%f %f %f\n" % (self.coords[i, 0], self.coords[i, 1], self.coords[i, 2])) for i in range(len(self.coords)): - handle.write('%d %d\n'% (i+1, i+2)) + handle.write("%d %d\n" % (i + 1, i + 2)) - def _computeDist(self,origin,coords,axis, dtype='d'): + def _computeDist(self, origin, coords, axis, dtype="d"): """ compute the distance of coords from the defined axis. """ # Compute the direction from each point to the origin - dirVec = origin-coords + dirVec = origin - coords # compute the cross product with the desired axis. Cross product # will be zero if the direction vector is the same as the axis - resultDir = numpy.cross(axis,dirVec) + resultDir = numpy.cross(axis, dirVec) - X = numpy.zeros(len(coords),dtype) + X = numpy.zeros(len(coords), dtype) for i in range(len(resultDir)): - X[i] = geo_utils.euclideanNorm(resultDir[i,:]) + X[i] = geo_utils.euclideanNorm(resultDir[i, :]) return X + class SurfaceAreaConstraint(GeometricConstraint): """ DVConstraints representation of a surface area @@ -5049,8 +5306,7 @@ class SurfaceAreaConstraint(GeometricConstraint): The user should not have to deal with this class directly. """ - def __init__(self, name, p0, v1, v2, lower, upper, scale, scaled, DVGeo, - addToPyOpt): + def __init__(self, name, p0, v1, v2, lower, upper, scale, scaled, DVGeo, addToPyOpt): self.name = name self.nCon = 1 self.lower = lower @@ -5060,9 +5316,9 @@ def __init__(self, name, p0, v1, v2, lower, upper, scale, scaled, DVGeo, self.DVGeo = DVGeo self.addToPyOpt = addToPyOpt - GeometricConstraint.__init__(self, self.name, self.nCon, self.lower, - self.upper, self.scale, self.DVGeo, - self.addToPyOpt) + GeometricConstraint.__init__( + self, self.name, self.nCon, self.lower, self.upper, self.scale, self.DVGeo, self.addToPyOpt + ) # create output array self.X = numpy.zeros(self.nCon) @@ -5070,18 +5326,18 @@ def __init__(self, name, p0, v1, v2, lower, upper, scale, scaled, DVGeo, # The first thing we do is convert v1 and v2 to coords self.p0 = p0 - self.p1 = v1+p0 - self.p2 = v2+p0 + self.p1 = v1 + p0 + self.p2 = v2 + p0 # Now embed the coordinates into DVGeo # with the name provided: # TODO this is duplicating a DVGeo pointset (same as the surface which originally created the constraint) - self.DVGeo.addPointSet(self.p0, self.name+'p0') - self.DVGeo.addPointSet(self.p1, self.name+'p1') - self.DVGeo.addPointSet(self.p2, self.name+'p2') + self.DVGeo.addPointSet(self.p0, self.name + "p0") + self.DVGeo.addPointSet(self.p1, self.name + "p1") + self.DVGeo.addPointSet(self.p2, self.name + "p2") # compute the reference area - self.X0 = self._computeArea(self.p0,self.p1,self.p2) + self.X0 = self._computeArea(self.p0, self.p1, self.p2) def evalFunctions(self, funcs, config): """ @@ -5093,13 +5349,13 @@ def evalFunctions(self, funcs, config): Dictionary to place function values """ # Pull out the most recent set of coordinates: - self.p0 = self.DVGeo.update(self.name+'p0', config=config) - self.p1 = self.DVGeo.update(self.name+'p1', config=config) - self.p2 = self.DVGeo.update(self.name+'p2', config=config) + self.p0 = self.DVGeo.update(self.name + "p0", config=config) + self.p1 = self.DVGeo.update(self.name + "p1", config=config) + self.p2 = self.DVGeo.update(self.name + "p2", config=config) - self.X = self._computeArea(self.p0,self.p1,self.p2) + self.X = self._computeArea(self.p0, self.p1, self.p2) if self.scaled: - self.X/= self.X0 + self.X /= self.X0 funcs[self.name] = self.X def evalFunctionsSens(self, funcsSens, config): @@ -5115,52 +5371,46 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dAdp0 = numpy.zeros((self.nCon, - self.p0.shape[0], - self.p0.shape[1])) - dAdp1 = numpy.zeros((self.nCon, - self.p1.shape[0], - self.p1.shape[1])) + dAdp0 = numpy.zeros((self.nCon, self.p0.shape[0], self.p0.shape[1])) + dAdp1 = numpy.zeros((self.nCon, self.p1.shape[0], self.p1.shape[1])) - dAdp2 = numpy.zeros((self.nCon, - self.p2.shape[0], - self.p2.shape[1])) + dAdp2 = numpy.zeros((self.nCon, self.p2.shape[0], self.p2.shape[1])) p0 = self.p0 p1 = self.p1 p2 = self.p2 for con in range(self.nCon): - p0b = dAdp0[con,:,:] - p1b = dAdp1[con,:,:] - p2b = dAdp2[con,:,:] + p0b = dAdp0[con, :, :] + p1b = dAdp1[con, :, :] + p2b = dAdp2[con, :, :] areab = 1 areasb = numpy.empty(self.n) - crossesb = numpy.empty((self.n,3)) - v1b = numpy.empty((self.n,3)) - v2b = numpy.empty((self.n,3)) + crossesb = numpy.empty((self.n, 3)) + v1b = numpy.empty((self.n, 3)) + v2b = numpy.empty((self.n, 3)) if self.scaled: - areab = areab/self.X0 - areasb[:] = areab/2. + areab = areab / self.X0 + areasb[:] = areab / 2.0 v1 = p1 - p0 v2 = p2 - p0 crosses = numpy.cross(v1, v2) - # for j in range(3): - # areas(i) = areas(i) + crosses(i, j)**2 - #areas[i] = numpy.sum(crosses[i, :]**2) - areas = numpy.sum(crosses**2,axis=1) - for i in range(self.n):#DO i=1,n - if (areas[i] == 0.0): + # for j in range(3): + # areas(i) = areas(i) + crosses(i, j)**2 + # areas[i] = numpy.sum(crosses[i, :]**2) + areas = numpy.sum(crosses ** 2, axis=1) + for i in range(self.n): # DO i=1,n + if areas[i] == 0.0: areasb[i] = 0.0 else: - areasb[i] = areasb[i]/(2.0*numpy.sqrt(areas[i])) + areasb[i] = areasb[i] / (2.0 * numpy.sqrt(areas[i])) # for j in reversed(range(3)):#DO j=3,1,-1 # crossesb(i, j) = crossesb(i, j) + 2*crosses(i, j)*areasb(i) - crossesb[i, :] = 2*crosses[i, :]*areasb[i] + crossesb[i, :] = 2 * crosses[i, :] * areasb[i] - v1b[i,:],v2b[i,:] = geo_utils.cross_b(v1[i, :], v2[i, :], crossesb[i, :]) + v1b[i, :], v2b[i, :] = geo_utils.cross_b(v1[i, :], v2[i, :], crossesb[i, :]) # for j in reversed(range(3)):#DO j=3,1,-1 # p2b(i, j) = p2b(i, j) + v2b(i, j) @@ -5169,21 +5419,15 @@ def evalFunctionsSens(self, funcsSens, config): # p1b(i, j) = p1b(i, j) + v1b(i, j) # v1b(i, j) = 0.0 p2b[i, :] = v2b[i, :] - p0b[i, :] = - v1b[i, :] - v2b[i, :] + p0b[i, :] = -v1b[i, :] - v2b[i, :] p1b[i, :] = p1b[i, :] + v1b[i, :] - - - tmpp0 = self.DVGeo.totalSensitivity(dAdp0, self.name+'p0', - config=config) - tmpp1 = self.DVGeo.totalSensitivity(dAdp1, self.name+'p1', - config=config) - tmpp2 = self.DVGeo.totalSensitivity(dAdp2, self.name+'p2', - config=config) + tmpp0 = self.DVGeo.totalSensitivity(dAdp0, self.name + "p0", config=config) + tmpp1 = self.DVGeo.totalSensitivity(dAdp1, self.name + "p1", config=config) + tmpp2 = self.DVGeo.totalSensitivity(dAdp2, self.name + "p2", config=config) tmpTotal = {} for key in tmpp0: - tmpTotal[key] = tmpp0[key]+tmpp1[key]+tmpp2[key] - + tmpTotal[key] = tmpp0[key] + tmpp1[key] + tmpp2[key] funcsSens[self.name] = tmpTotal @@ -5192,19 +5436,19 @@ def _computeArea(self, p0, p1, p2): compute area based on three point arrays """ # convert p1 and p2 to v1 and v2 - v1 = p1- p0 - v2 = p2- p0 + v1 = p1 - p0 + v2 = p2 - p0 - #compute the areas + # compute the areas areaVec = numpy.cross(v1, v2) - #area = numpy.linalg.norm(areaVec,axis=1) + # area = numpy.linalg.norm(areaVec,axis=1) area = 0 for i in range(len(areaVec)): - area += geo_utils.euclideanNorm(areaVec[i,:]) + area += geo_utils.euclideanNorm(areaVec[i, :]) - #return numpy.sum(area)/2.0 - return area/2.0 + # return numpy.sum(area)/2.0 + return area / 2.0 def writeTecplot(self, handle): """ @@ -5212,23 +5456,19 @@ def writeTecplot(self, handle): to the open file handle """ - handle.write('Zone T=%s_surface\n'% self.name) - handle.write('Nodes = %d, Elements = %d ZONETYPE=FETRIANGLE\n'% ( - 3*self.n, self.n)) - handle.write('DATAPACKING=POINT\n') + handle.write("Zone T=%s_surface\n" % self.name) + handle.write("Nodes = %d, Elements = %d ZONETYPE=FETRIANGLE\n" % (3 * self.n, self.n)) + handle.write("DATAPACKING=POINT\n") for i in range(self.n): - handle.write('%f %f %f\n'% (self.p0[i, 0], self.p0[i, 1], - self.p0[i, 2])) + handle.write("%f %f %f\n" % (self.p0[i, 0], self.p0[i, 1], self.p0[i, 2])) for i in range(self.n): - handle.write('%f %f %f\n'% (self.p1[i, 0], self.p1[i, 1], - self.p1[i, 2])) + handle.write("%f %f %f\n" % (self.p1[i, 0], self.p1[i, 1], self.p1[i, 2])) for i in range(self.n): - handle.write('%f %f %f\n'% (self.p2[i, 0], self.p2[i, 1], - self.p2[i, 2])) + handle.write("%f %f %f\n" % (self.p2[i, 0], self.p2[i, 1], self.p2[i, 2])) for i in range(self.n): - handle.write('%d %d %d\n'% (i+1, i+self.n+1, i+self.n*2+1)) + handle.write("%d %d %d\n" % (i + 1, i + self.n + 1, i + self.n * 2 + 1)) class ProjectedAreaConstraint(GeometricConstraint): @@ -5239,8 +5479,7 @@ class ProjectedAreaConstraint(GeometricConstraint): The user should not have to deal with this class directly. """ - def __init__(self, name, p0, v1, v2, axis, lower, upper, scale, scaled, - DVGeo, addToPyOpt): + def __init__(self, name, p0, v1, v2, axis, lower, upper, scale, scaled, DVGeo, addToPyOpt): self.name = name self.nCon = 1 self.lower = lower @@ -5250,9 +5489,9 @@ def __init__(self, name, p0, v1, v2, axis, lower, upper, scale, scaled, self.DVGeo = DVGeo self.addToPyOpt = addToPyOpt - GeometricConstraint.__init__(self, self.name, self.nCon, self.lower, - self.upper, self.scale, self.DVGeo, - self.addToPyOpt) + GeometricConstraint.__init__( + self, self.name, self.nCon, self.lower, self.upper, self.scale, self.DVGeo, self.addToPyOpt + ) # create output array self.X = numpy.zeros(self.nCon) @@ -5262,15 +5501,15 @@ def __init__(self, name, p0, v1, v2, axis, lower, upper, scale, scaled, # The first thing we do is convert v1 and v2 to coords self.p0 = p0 - self.p1 = v1+p0 - self.p2 = v2+p0 + self.p1 = v1 + p0 + self.p2 = v2 + p0 # Now embed the coordinates into DVGeo # with the name provided: # TODO this is duplicating a DVGeo pointset (same as the surface which originally created the constraint) - self.DVGeo.addPointSet(self.p0, self.name+'p0') - self.DVGeo.addPointSet(self.p1, self.name+'p1') - self.DVGeo.addPointSet(self.p2, self.name+'p2') + self.DVGeo.addPointSet(self.p0, self.name + "p0") + self.DVGeo.addPointSet(self.p1, self.name + "p1") + self.DVGeo.addPointSet(self.p2, self.name + "p2") # compute the reference area self.X0 = self._computeArea(self.p0, self.p1, self.p2, self.axis) @@ -5285,9 +5524,9 @@ def evalFunctions(self, funcs, config): Dictionary to place function values """ # Pull out the most recent set of coordinates: - self.p0 = self.DVGeo.update(self.name+'p0', config=config) - self.p1 = self.DVGeo.update(self.name+'p1', config=config) - self.p2 = self.DVGeo.update(self.name+'p2', config=config) + self.p0 = self.DVGeo.update(self.name + "p0", config=config) + self.p1 = self.DVGeo.update(self.name + "p1", config=config) + self.p2 = self.DVGeo.update(self.name + "p2", config=config) self.X = self._computeArea(self.p0, self.p1, self.p2, self.axis) if self.scaled: @@ -5306,32 +5545,26 @@ def evalFunctionsSens(self, funcsSens, config): """ nDV = self.DVGeo.getNDV() if nDV > 0: - dAdp0 = numpy.zeros((self.nCon, - self.p0.shape[0], - self.p0.shape[1])) - dAdp1 = numpy.zeros((self.nCon, - self.p1.shape[0], - self.p1.shape[1])) - - dAdp2 = numpy.zeros((self.nCon, - self.p2.shape[0], - self.p2.shape[1])) + dAdp0 = numpy.zeros((self.nCon, self.p0.shape[0], self.p0.shape[1])) + dAdp1 = numpy.zeros((self.nCon, self.p1.shape[0], self.p1.shape[1])) + + dAdp2 = numpy.zeros((self.nCon, self.p2.shape[0], self.p2.shape[1])) p0 = self.p0 p1 = self.p1 p2 = self.p2 for con in range(self.nCon): - p0b = dAdp0[con,:,:] - p1b = dAdp1[con,:,:] - p2b = dAdp2[con,:,:] + p0b = dAdp0[con, :, :] + p1b = dAdp1[con, :, :] + p2b = dAdp2[con, :, :] areab = 1 areasb = numpy.empty(self.n) if self.scaled: - areab = areab/self.X0 - areasb[:] = areab/2. + areab = areab / self.X0 + areasb[:] = areab / 2.0 for i in range(self.n): - v1 = p1[i,:] - p0[i,:] - v2 = p2[i,:] - p0[i,:] + v1 = p1[i, :] - p0[i, :] + v2 = p2[i, :] - p0[i, :] SAvec = numpy.cross(v1, v2) PA = numpy.dot(SAvec, self.axis) if PA > 0: @@ -5340,19 +5573,16 @@ def evalFunctionsSens(self, funcsSens, config): PAb = 0.0 SAvecb, axisb = geo_utils.dot_b(SAvec, self.axis, PAb) v1b, v2b = geo_utils.cross_b(v1, v2, SAvecb) - p2b[i,:] = p2b[i,:] + v2b - p1b[i,:] = p1b[i,:] + v1b - p0b[i,:] = p0b[i,:] - v1b - v2b - - tmpp0 = self.DVGeo.totalSensitivity(dAdp0, self.name+'p0', - config=config) - tmpp1 = self.DVGeo.totalSensitivity(dAdp1, self.name+'p1', - config=config) - tmpp2 = self.DVGeo.totalSensitivity(dAdp2, self.name+'p2', - config=config) + p2b[i, :] = p2b[i, :] + v2b + p1b[i, :] = p1b[i, :] + v1b + p0b[i, :] = p0b[i, :] - v1b - v2b + + tmpp0 = self.DVGeo.totalSensitivity(dAdp0, self.name + "p0", config=config) + tmpp1 = self.DVGeo.totalSensitivity(dAdp1, self.name + "p1", config=config) + tmpp2 = self.DVGeo.totalSensitivity(dAdp2, self.name + "p2", config=config) tmpTotal = {} for key in tmpp0: - tmpTotal[key] = tmpp0[key]+tmpp1[key]+tmpp2[key] + tmpTotal[key] = tmpp0[key] + tmpp1[key] + tmpp2[key] funcsSens[self.name] = tmpTotal @@ -5362,8 +5592,8 @@ def _computeArea(self, p0, p1, p2, axis, plot=False): """ # Convert p1 and p2 to v1 and v2 - v1 = p1- p0 - v2 = p2- p0 + v1 = p1 - p0 + v2 = p2 - p0 # Compute the surface area vectors for each triangle patch surfaceAreas = numpy.cross(v1, v2) @@ -5379,14 +5609,13 @@ def _computeArea(self, p0, p1, p2, axis, plot=False): else: projectedAreas[i] = 0.0 else: - projectedAreas[projectedAreas<0] = 0.0 + projectedAreas[projectedAreas < 0] = 0.0 # Sum projected areas and divide by two for triangle area - totalProjectedArea = numpy.sum(projectedAreas)/2.0 + totalProjectedArea = numpy.sum(projectedAreas) / 2.0 return totalProjectedArea - def writeTecplot(self, handle): """ Write the visualization of this set of thickness constraints @@ -5398,38 +5627,37 @@ def writeTecplot(self, handle): p1 = self.p1.copy() p2 = self.p2.copy() if self.axis[0] == 1.0: - p0[:,0] = numpy.zeros(self.n) - p1[:,0] = numpy.zeros(self.n) - p2[:,0] = numpy.zeros(self.n) + p0[:, 0] = numpy.zeros(self.n) + p1[:, 0] = numpy.zeros(self.n) + p2[:, 0] = numpy.zeros(self.n) if self.axis[1] == 1.0: - p0[:,1] = numpy.zeros(self.n) - p1[:,1] = numpy.zeros(self.n) - p2[:,1] = numpy.zeros(self.n) + p0[:, 1] = numpy.zeros(self.n) + p1[:, 1] = numpy.zeros(self.n) + p2[:, 1] = numpy.zeros(self.n) if self.axis[2] == 1.0: - p0[:,2] = numpy.zeros(self.n) - p1[:,2] = numpy.zeros(self.n) - p2[:,2] = numpy.zeros(self.n) - - handle.write('Zone T=%s_surface\n'% self.name) - handle.write('Nodes = %d, Elements = %d ZONETYPE=FETRIANGLE\n'% ( - 3*nActiveTris, nActiveTris)) - handle.write('DATAPACKING=POINT\n') + p0[:, 2] = numpy.zeros(self.n) + p1[:, 2] = numpy.zeros(self.n) + p2[:, 2] = numpy.zeros(self.n) + + handle.write("Zone T=%s_surface\n" % self.name) + handle.write("Nodes = %d, Elements = %d ZONETYPE=FETRIANGLE\n" % (3 * nActiveTris, nActiveTris)) + handle.write("DATAPACKING=POINT\n") for i in range(self.n): if self.activeTris[i]: - handle.write('%f %f %f\n'% (p0[i, 0], p0[i, 1], p0[i, 2])) + handle.write("%f %f %f\n" % (p0[i, 0], p0[i, 1], p0[i, 2])) for i in range(self.n): if self.activeTris[i]: - handle.write('%f %f %f\n'% (p1[i, 0], p1[i, 1], p1[i, 2])) + handle.write("%f %f %f\n" % (p1[i, 0], p1[i, 1], p1[i, 2])) for i in range(self.n): if self.activeTris[i]: - handle.write('%f %f %f\n'% (p2[i, 0], p2[i, 1], p2[i, 2])) + handle.write("%f %f %f\n" % (p2[i, 0], p2[i, 1], p2[i, 2])) iActive = 0 for i in range(self.n): if self.activeTris[i]: - handle.write('%d %d %d\n'% (iActive+1, iActive+nActiveTris+1, - iActive+nActiveTris*2+1)) + handle.write("%d %d %d\n" % (iActive + 1, iActive + nActiveTris + 1, iActive + nActiveTris * 2 + 1)) iActive += 1 + class CurvatureConstraint(GeometricConstraint): """ DVConstraints representation of a set of the curvature constraint. @@ -5437,10 +5665,9 @@ class CurvatureConstraint(GeometricConstraint): The user should not have to deal with this class directly. """ - def __init__(self, name, surfs, curvatureType, lower, upper, scaled, scale, KSCoeff, DVGeo, - addToPyOpt): + def __init__(self, name, surfs, curvatureType, lower, upper, scaled, scale, KSCoeff, DVGeo, addToPyOpt): self.name = name - self.nSurfs = len(surfs) # we support multiple surfaces (plot3D files) + self.nSurfs = len(surfs) # we support multiple surfaces (plot3D files) self.X = [] self.X_map = [] self.node_map = [] @@ -5448,51 +5675,54 @@ def __init__(self, name, surfs, curvatureType, lower, upper, scaled, scale, KSCo for iSurf in range(self.nSurfs): # A list of the coordinates arrays for each surface, flattened in order # to vectorize operations - self.X += [numpy.reshape(surfs[iSurf].X,-1)] + self.X += [numpy.reshape(surfs[iSurf].X, -1)] # A list of maping arrays used to translate from the structured index # to the flatten index number of X # For example: X[iSurf][X_map[iSurf][i,j,2]] gives the z coordinate # of the node in the i-th row and j-th column on surface iSurf - self.X_map += [numpy.reshape(numpy.array(range(surfs[iSurf].X.size)),surfs[iSurf].X.shape)] + self.X_map += [numpy.reshape(numpy.array(range(surfs[iSurf].X.size)), surfs[iSurf].X.shape)] # A list of maping arrays used to provide a unique node number for # every node on each surface # For example: node_map[iSurf][i,j] gives the node number # of the node in the i-th row and j-th column on surface iSurf - self.node_map += [numpy.reshape(numpy.array(range(surfs[iSurf].X.size//3)),(surfs[iSurf].X.shape[0],surfs[iSurf].X.shape[1]))] + self.node_map += [ + numpy.reshape( + numpy.array(range(surfs[iSurf].X.size // 3)), (surfs[iSurf].X.shape[0], surfs[iSurf].X.shape[1]) + ) + ] # A list of the coordinates arrays for each surface, in the shape that DVGeo expects (N_nodes,3) - self.coords += [numpy.reshape(self.X[iSurf],(surfs[iSurf].X.shape[0]*surfs[iSurf].X.shape[1],3))] + self.coords += [numpy.reshape(self.X[iSurf], (surfs[iSurf].X.shape[0] * surfs[iSurf].X.shape[1], 3))] self.nCon = 1 self.curvatureType = curvatureType self.lower = lower self.upper = upper self.scaled = scaled self.scale = scale - self.KSCoeff=KSCoeff - if self.KSCoeff==None: + self.KSCoeff = KSCoeff + if self.KSCoeff == None: # set KSCoeff to be the number of points in the plot 3D files - self.KSCoeff=0.0 + self.KSCoeff = 0.0 for i in range(len(self.coords)): - self.KSCoeff+=len(self.coords[i]) + self.KSCoeff += len(self.coords[i]) self.DVGeo = DVGeo self.addToPyOpt = addToPyOpt - GeometricConstraint.__init__(self, self.name, self.nCon, self.lower, - self.upper, self.scale, self.DVGeo, - self.addToPyOpt) + GeometricConstraint.__init__( + self, self.name, self.nCon, self.lower, self.upper, self.scale, self.DVGeo, self.addToPyOpt + ) # First thing we can do is embed the coordinates into DVGeo # with the name provided. We need to add a point set for each surface: for iSurf in range(self.nSurfs): - self.DVGeo.addPointSet(self.coords[iSurf], self.name+'%d'%(iSurf)) + self.DVGeo.addPointSet(self.coords[iSurf], self.name + "%d" % (iSurf)) # compute the reference curvature for normalization - self.curvatureRef=0.0 + self.curvatureRef = 0.0 for iSurf in range(self.nSurfs): self.curvatureRef += self.evalCurvArea(iSurf)[0] - if(MPI.COMM_WORLD.rank==0): - print("Reference curvature: ",self.curvatureRef) - + if MPI.COMM_WORLD.rank == 0: + print("Reference curvature: ", self.curvatureRef) def evalFunctions(self, funcs, config): """ @@ -5506,10 +5736,10 @@ def evalFunctions(self, funcs, config): # Pull out the most recent set of coordinates for each surface: funcs[self.name] = 0 for iSurf in range(self.nSurfs): - self.coords[iSurf] = self.DVGeo.update(self.name+'%d'%(iSurf), config=config) - self.X[iSurf] = numpy.reshape(self.coords[iSurf],-1) + self.coords[iSurf] = self.DVGeo.update(self.name + "%d" % (iSurf), config=config) + self.X[iSurf] = numpy.reshape(self.coords[iSurf], -1) if self.scaled: - funcs[self.name] += self.evalCurvArea(iSurf)[0]/self.curvatureRef + funcs[self.name] += self.evalCurvArea(iSurf)[0] / self.curvatureRef else: funcs[self.name] += self.evalCurvArea(iSurf)[0] @@ -5535,558 +5765,620 @@ def evalFunctionsSens(self, funcsSens, config): DkSDpt = numpy.reshape(DkSDX, self.coords[iSurf].shape) if iSurf == 0: funcsSens[self.name] = self.DVGeo.totalSensitivity( - DkSDpt, self.name+'%d'%(iSurf), config=config) + DkSDpt, self.name + "%d" % (iSurf), config=config + ) else: - tmp = self.DVGeo.totalSensitivity( - DkSDpt, self.name+'%d'%(iSurf), config=config) + tmp = self.DVGeo.totalSensitivity(DkSDpt, self.name + "%d" % (iSurf), config=config) for key in funcsSens[self.name]: funcsSens[self.name][key] += tmp[key] def evalCurvArea(self, iSurf): - ''' + """ Evaluate the integral K**2 over the surface area of the wing. Where K is the Gaussian curvature. - ''' + """ # Evaluate the derivitive of the position vector of every point on the # surface wrt to the parameteric corrdinate u and v - t_u = self.evalDiff(iSurf, self.X[iSurf], 'u') - t_v = self.evalDiff(iSurf, self.X[iSurf], 'v') + t_u = self.evalDiff(iSurf, self.X[iSurf], "u") + t_v = self.evalDiff(iSurf, self.X[iSurf], "v") # Compute the normal vector by taking the cross product of t_u and t_v - n = self.evalCross(iSurf, t_u,t_v) + n = self.evalCross(iSurf, t_u, t_v) # Compute the norm of tu_ x tv n_norm = self.evalNorm(iSurf, n) # Normalize the normal vector n_hat = numpy.zeros_like(n) - n_hat[self.X_map[iSurf][:,:,0]]=n[self.X_map[iSurf][:,:,0]]/n_norm[self.node_map[iSurf][:,:]] - n_hat[self.X_map[iSurf][:,:,1]]=n[self.X_map[iSurf][:,:,1]]/n_norm[self.node_map[iSurf][:,:]] - n_hat[self.X_map[iSurf][:,:,2]]=n[self.X_map[iSurf][:,:,2]]/n_norm[self.node_map[iSurf][:,:]] + n_hat[self.X_map[iSurf][:, :, 0]] = n[self.X_map[iSurf][:, :, 0]] / n_norm[self.node_map[iSurf][:, :]] + n_hat[self.X_map[iSurf][:, :, 1]] = n[self.X_map[iSurf][:, :, 1]] / n_norm[self.node_map[iSurf][:, :]] + n_hat[self.X_map[iSurf][:, :, 2]] = n[self.X_map[iSurf][:, :, 2]] / n_norm[self.node_map[iSurf][:, :]] # Evaluate the second derivitives of the position vector wrt u and v - t_uu = self.evalDiff(iSurf, t_u, 'u') - t_vv = self.evalDiff(iSurf, t_v, 'v') - t_uv = self.evalDiff(iSurf, t_v, 'u') + t_uu = self.evalDiff(iSurf, t_u, "u") + t_vv = self.evalDiff(iSurf, t_v, "v") + t_uv = self.evalDiff(iSurf, t_v, "u") # Compute the components of the first fundamental form of a parameteric # surface - E = self.evalInProd(iSurf, t_u,t_u) - F = self.evalInProd(iSurf, t_v,t_u) - G = self.evalInProd(iSurf, t_v,t_v) + E = self.evalInProd(iSurf, t_u, t_u) + F = self.evalInProd(iSurf, t_v, t_u) + G = self.evalInProd(iSurf, t_v, t_v) # Compute the components of the second fundamental form of a parameteric # surface - L = self.evalInProd(iSurf, t_uu,n_hat) - M = self.evalInProd(iSurf, t_uv,n_hat) - N = self.evalInProd(iSurf, t_vv,n_hat) + L = self.evalInProd(iSurf, t_uu, n_hat) + M = self.evalInProd(iSurf, t_uv, n_hat) + N = self.evalInProd(iSurf, t_vv, n_hat) # Compute Gaussian and mean curvature (K and H) - K = (L*N-M*M)/(E*G-F*F) - H = (E*N - 2*F*M + G*L)/(2*(E*G-F*F)) + K = (L * N - M * M) / (E * G - F * F) + H = (E * N - 2 * F * M + G * L) / (2 * (E * G - F * F)) # Compute the combined curvature (C) - C = 4.0*H*H-2.0*K + C = 4.0 * H * H - 2.0 * K # Assign integration weights for each point # 1 for center nodes # 1/2 for edge nodes # 1/4 for corner nodes - wt = numpy.zeros_like(n_norm)+1 - wt[self.node_map[iSurf][0,:]] *= 0.5 - wt[self.node_map[iSurf][-1,:]] *= 0.5 - wt[self.node_map[iSurf][:,0]] *= 0.5 - wt[self.node_map[iSurf][:,-1]] *= 0.5 + wt = numpy.zeros_like(n_norm) + 1 + wt[self.node_map[iSurf][0, :]] *= 0.5 + wt[self.node_map[iSurf][-1, :]] *= 0.5 + wt[self.node_map[iSurf][:, 0]] *= 0.5 + wt[self.node_map[iSurf][:, -1]] *= 0.5 # Compute discrete area associated with each node - dS = wt*n_norm + dS = wt * n_norm one = numpy.ones(self.node_map[iSurf].size) - if self.curvatureType == 'Gaussian': + if self.curvatureType == "Gaussian": # Now compute integral (K**2) over S, equivelent to sum(K**2*dS) - kS = numpy.dot(one,K*K*dS) + kS = numpy.dot(one, K * K * dS) return [kS, K, H, C] - elif self.curvatureType == 'mean': + elif self.curvatureType == "mean": # Now compute integral (H**2) over S, equivelent to sum(H**2*dS) - hS = numpy.dot(one,H*H*dS) + hS = numpy.dot(one, H * H * dS) return [hS, K, H, C] - elif self.curvatureType == 'combined': + elif self.curvatureType == "combined": # Now compute integral C over S, equivelent to sum(C*dS) - cS = numpy.dot(one,C*dS) + cS = numpy.dot(one, C * dS) return [cS, K, H, C] - elif self.curvatureType == 'KSmean': + elif self.curvatureType == "KSmean": # Now compute the KS function for mean curvature, equivelent to KS(H*H*dS) - sigmaH=numpy.dot(one,numpy.exp(self.KSCoeff*H*H*dS)) - KSmean=numpy.log(sigmaH)/self.KSCoeff - if(MPI.COMM_WORLD.rank==0): - print("Max curvature: ",max(H*H*dS)) + sigmaH = numpy.dot(one, numpy.exp(self.KSCoeff * H * H * dS)) + KSmean = numpy.log(sigmaH) / self.KSCoeff + if MPI.COMM_WORLD.rank == 0: + print("Max curvature: ", max(H * H * dS)) return [KSmean, K, H, C] else: - raise Error("The curvatureType parameter should be Gaussian, mean, or combined, " - "%s is not supported!"%curvatureType) - + raise Error( + "The curvatureType parameter should be Gaussian, mean, or combined, " + "%s is not supported!" % curvatureType + ) def evalCurvAreaSens(self, iSurf): - ''' + """ Compute sensitivity of the integral K**2 wrt the coordinate locations X - ''' + """ # Evaluate the derivitive of the position vector of every point on the # surface wrt to the parameteric corrdinate u and v - t_u = self.evalDiff(iSurf, self.X[iSurf], 'u') - Dt_uDX = self.evalDiffSens(iSurf, 'u') - t_v = self.evalDiff(iSurf, self.X[iSurf], 'v') - Dt_vDX = self.evalDiffSens(iSurf,'v') + t_u = self.evalDiff(iSurf, self.X[iSurf], "u") + Dt_uDX = self.evalDiffSens(iSurf, "u") + t_v = self.evalDiff(iSurf, self.X[iSurf], "v") + Dt_vDX = self.evalDiffSens(iSurf, "v") # Compute the normal vector by taking the cross product of t_u and t_v - n = self.evalCross(iSurf,t_u,t_v) - [DnDt_u, DnDt_v] = self.evalCrossSens(iSurf,t_u,t_v) + n = self.evalCross(iSurf, t_u, t_v) + [DnDt_u, DnDt_v] = self.evalCrossSens(iSurf, t_u, t_v) DnDX = DnDt_u.dot(Dt_uDX) + DnDt_v.dot(Dt_vDX) # Compute the norm of tu_ x tv - n_norm = self.evalNorm(iSurf,n) - Dn_normDn = self.evalNormSens(iSurf,n) + n_norm = self.evalNorm(iSurf, n) + Dn_normDn = self.evalNormSens(iSurf, n) Dn_normDX = Dn_normDn.dot(DnDX) # Normalize the normal vector n_hat = numpy.zeros_like(n) - n_hat[self.X_map[iSurf][:,:,0]]=n[self.X_map[iSurf][:,:,0]]/n_norm[self.node_map[iSurf][:,:]] - n_hat[self.X_map[iSurf][:,:,1]]=n[self.X_map[iSurf][:,:,1]]/n_norm[self.node_map[iSurf][:,:]] - n_hat[self.X_map[iSurf][:,:,2]]=n[self.X_map[iSurf][:,:,2]]/n_norm[self.node_map[iSurf][:,:]] + n_hat[self.X_map[iSurf][:, :, 0]] = n[self.X_map[iSurf][:, :, 0]] / n_norm[self.node_map[iSurf][:, :]] + n_hat[self.X_map[iSurf][:, :, 1]] = n[self.X_map[iSurf][:, :, 1]] / n_norm[self.node_map[iSurf][:, :]] + n_hat[self.X_map[iSurf][:, :, 2]] = n[self.X_map[iSurf][:, :, 2]] / n_norm[self.node_map[iSurf][:, :]] ii = [] data = [] for i in range(3): # Dn_hat[self.X_map[iSurf][:,:,i]]/Dn[self.X_map[iSurf][:,:,i]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,i],-1)) - data +=list(numpy.reshape(n_norm[self.node_map[iSurf][:,:]]**-1,-1)) - Dn_hatDn = csr_matrix((data,[ii,ii]),shape=(self.X[iSurf].size,self.X[iSurf].size)) + ii += list(numpy.reshape(self.X_map[iSurf][:, :, i], -1)) + data += list(numpy.reshape(n_norm[self.node_map[iSurf][:, :]] ** -1, -1)) + Dn_hatDn = csr_matrix((data, [ii, ii]), shape=(self.X[iSurf].size, self.X[iSurf].size)) ii = [] jj = [] data = [] for i in range(3): # Dn_hat[self.X_map[iSurf][:,:,i]]/Dn_norm[self.node_map[iSurf][:,:]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,i],-1)) - jj += list(numpy.reshape(self.node_map[iSurf][:,:],-1)) - data +=list(numpy.reshape(-n[self.X_map[iSurf][:,:,i]]/(n_norm[self.node_map[iSurf][:,:]]**2),-1)) - Dn_hatDn_norm = csr_matrix((data,[ii,jj]),shape=(n_hat.size,n_norm.size)) + ii += list(numpy.reshape(self.X_map[iSurf][:, :, i], -1)) + jj += list(numpy.reshape(self.node_map[iSurf][:, :], -1)) + data += list(numpy.reshape(-n[self.X_map[iSurf][:, :, i]] / (n_norm[self.node_map[iSurf][:, :]] ** 2), -1)) + Dn_hatDn_norm = csr_matrix((data, [ii, jj]), shape=(n_hat.size, n_norm.size)) - Dn_hatDX=Dn_hatDn.dot(DnDX)+Dn_hatDn_norm.dot(Dn_normDX) + Dn_hatDX = Dn_hatDn.dot(DnDX) + Dn_hatDn_norm.dot(Dn_normDX) # Evaluate the second derivitives of the position vector wrt u and v - t_uu = self.evalDiff(iSurf,t_u, 'u') - Dt_uuDt_u = self.evalDiffSens(iSurf,'u') + t_uu = self.evalDiff(iSurf, t_u, "u") + Dt_uuDt_u = self.evalDiffSens(iSurf, "u") Dt_uuDX = Dt_uuDt_u.dot(Dt_uDX) - t_vv = self.evalDiff(iSurf,t_v, 'v') - Dt_vvDt_v = self.evalDiffSens(iSurf,'v') + t_vv = self.evalDiff(iSurf, t_v, "v") + Dt_vvDt_v = self.evalDiffSens(iSurf, "v") Dt_vvDX = Dt_vvDt_v.dot(Dt_vDX) - t_uv = self.evalDiff(iSurf,t_v, 'u') - Dt_uvDt_v = self.evalDiffSens(iSurf,'u') + t_uv = self.evalDiff(iSurf, t_v, "u") + Dt_uvDt_v = self.evalDiffSens(iSurf, "u") Dt_uvDX = Dt_uvDt_v.dot(Dt_vDX) # Compute the components of the first fundamental form of a parameteric # surface - E = self.evalInProd(iSurf,t_u,t_u) - [DEDt_u, _] = self.evalInProdSens(iSurf,t_u,t_u) - DEDt_u*=2 + E = self.evalInProd(iSurf, t_u, t_u) + [DEDt_u, _] = self.evalInProdSens(iSurf, t_u, t_u) + DEDt_u *= 2 DEDX = DEDt_u.dot(Dt_uDX) - F = self.evalInProd(iSurf,t_v,t_u) - [DFDt_v, DFDt_u] = self.evalInProdSens(iSurf,t_v,t_u) + F = self.evalInProd(iSurf, t_v, t_u) + [DFDt_v, DFDt_u] = self.evalInProdSens(iSurf, t_v, t_u) DFDX = DFDt_v.dot(Dt_vDX) + DFDt_u.dot(Dt_uDX) - G = self.evalInProd(iSurf,t_v,t_v) - [DGDt_v, _] = self.evalInProdSens(iSurf,t_v,t_v) - DGDt_v*=2 + G = self.evalInProd(iSurf, t_v, t_v) + [DGDt_v, _] = self.evalInProdSens(iSurf, t_v, t_v) + DGDt_v *= 2 DGDX = DGDt_v.dot(Dt_vDX) # Compute the components of the second fundamental form of a parameteric # surface - L = self.evalInProd(iSurf,t_uu,n_hat) - [DLDt_uu, DLDn_hat] = self.evalInProdSens(iSurf,t_uu,n_hat) - DLDX = DLDt_uu.dot(Dt_uuDX)+DLDn_hat.dot(Dn_hatDX) + L = self.evalInProd(iSurf, t_uu, n_hat) + [DLDt_uu, DLDn_hat] = self.evalInProdSens(iSurf, t_uu, n_hat) + DLDX = DLDt_uu.dot(Dt_uuDX) + DLDn_hat.dot(Dn_hatDX) - M = self.evalInProd(iSurf,t_uv,n_hat) - [DMDt_uv, DMDn_hat] = self.evalInProdSens(iSurf,t_uv,n_hat) - DMDX = DMDt_uv.dot(Dt_uvDX)+DMDn_hat.dot(Dn_hatDX) + M = self.evalInProd(iSurf, t_uv, n_hat) + [DMDt_uv, DMDn_hat] = self.evalInProdSens(iSurf, t_uv, n_hat) + DMDX = DMDt_uv.dot(Dt_uvDX) + DMDn_hat.dot(Dn_hatDX) - N = self.evalInProd(iSurf,t_vv,n_hat) - [DNDt_vv, DNDn_hat] = self.evalInProdSens(iSurf,t_vv,n_hat) - DNDX = DNDt_vv.dot(Dt_vvDX)+DNDn_hat.dot(Dn_hatDX) + N = self.evalInProd(iSurf, t_vv, n_hat) + [DNDt_vv, DNDn_hat] = self.evalInProdSens(iSurf, t_vv, n_hat) + DNDX = DNDt_vv.dot(Dt_vvDX) + DNDn_hat.dot(Dn_hatDX) # Compute Gaussian and mean curvature (K and H) - K = (L*N-M*M)/(E*G-F*F) - DKDE = self.diags(-(L*N-M*M)/(E*G-F*F)**2*G) - DKDF = self.diags((L*N-M*M)/(E*G-F*F)**2*2*F) - DKDG = self.diags(-(L*N-M*M)/(E*G-F*F)**2*E) - DKDL = self.diags(N/(E*G-F*F)) - DKDM = self.diags(2*M/(E*G-F*F)) - DKDN = self.diags(L/(E*G-F*F)) - DKDX = DKDE.dot(DEDX) + DKDF.dot(DFDX) + DKDG.dot(DGDX) +\ - DKDL.dot(DLDX) + DKDM.dot(DMDX) + DKDN.dot(DNDX) - - H = (E*N - 2*F*M + G*L)/(2*(E*G-F*F)) - DHDE = self.diags(N/(2*(E*G-F*F)) - (E*N - 2*F*M + G*L)/(2*(E*G-F*F))**2*2*G) - DHDF = self.diags(-2*M/(2*(E*G-F*F)) + (E*N - 2*F*M + G*L)/(2*(E*G-F*F))**2*4*F) - DHDG = self.diags(L/(2*(E*G-F*F)) - (E*N - 2*F*M + G*L)/(2*(E*G-F*F))**2*2*E) - DHDL = self.diags(G/(2*(E*G-F*F))) - DHDM = self.diags(-2*F/(2*(E*G-F*F))) - DHDN = self.diags(E/(2*(E*G-F*F))) - DHDX = DHDE.dot(DEDX) + DHDF.dot(DFDX) + DHDG.dot(DGDX)+\ - DHDL.dot(DLDX) + DHDM.dot(DMDX) + DHDN.dot(DNDX) + K = (L * N - M * M) / (E * G - F * F) + DKDE = self.diags(-(L * N - M * M) / (E * G - F * F) ** 2 * G) + DKDF = self.diags((L * N - M * M) / (E * G - F * F) ** 2 * 2 * F) + DKDG = self.diags(-(L * N - M * M) / (E * G - F * F) ** 2 * E) + DKDL = self.diags(N / (E * G - F * F)) + DKDM = self.diags(2 * M / (E * G - F * F)) + DKDN = self.diags(L / (E * G - F * F)) + DKDX = DKDE.dot(DEDX) + DKDF.dot(DFDX) + DKDG.dot(DGDX) + DKDL.dot(DLDX) + DKDM.dot(DMDX) + DKDN.dot(DNDX) + + H = (E * N - 2 * F * M + G * L) / (2 * (E * G - F * F)) + DHDE = self.diags(N / (2 * (E * G - F * F)) - (E * N - 2 * F * M + G * L) / (2 * (E * G - F * F)) ** 2 * 2 * G) + DHDF = self.diags( + -2 * M / (2 * (E * G - F * F)) + (E * N - 2 * F * M + G * L) / (2 * (E * G - F * F)) ** 2 * 4 * F + ) + DHDG = self.diags(L / (2 * (E * G - F * F)) - (E * N - 2 * F * M + G * L) / (2 * (E * G - F * F)) ** 2 * 2 * E) + DHDL = self.diags(G / (2 * (E * G - F * F))) + DHDM = self.diags(-2 * F / (2 * (E * G - F * F))) + DHDN = self.diags(E / (2 * (E * G - F * F))) + DHDX = DHDE.dot(DEDX) + DHDF.dot(DFDX) + DHDG.dot(DGDX) + DHDL.dot(DLDX) + DHDM.dot(DMDX) + DHDN.dot(DNDX) # Assign integration weights for each point # 1 for center nodes # 1/2 for edge nodes # 1/4 for corner nodes - wt = numpy.zeros_like(n_norm)+1 - wt[self.node_map[iSurf][0,:]] *= 0.5 - wt[self.node_map[iSurf][-1,:]] *= 0.5 - wt[self.node_map[iSurf][:,0]] *= 0.5 - wt[self.node_map[iSurf][:,-1]] *= 0.5 - #Compute discrete area associated with each node - dS = wt*n_norm + wt = numpy.zeros_like(n_norm) + 1 + wt[self.node_map[iSurf][0, :]] *= 0.5 + wt[self.node_map[iSurf][-1, :]] *= 0.5 + wt[self.node_map[iSurf][:, 0]] *= 0.5 + wt[self.node_map[iSurf][:, -1]] *= 0.5 + # Compute discrete area associated with each node + dS = wt * n_norm DdSDX = self.diags(wt).dot(Dn_normDX) one = numpy.ones(self.node_map[iSurf].size) - if self.curvatureType == 'Gaussian': + if self.curvatureType == "Gaussian": # Now compute integral (K**2) over S, equivelent to sum(K**2*dS) - kS = numpy.dot(one,K*K*dS) - DkSDX = (self.diags(2*K*dS).dot(DKDX)+self.diags(K*K).dot(DdSDX)).T.dot(one) + kS = numpy.dot(one, K * K * dS) + DkSDX = (self.diags(2 * K * dS).dot(DKDX) + self.diags(K * K).dot(DdSDX)).T.dot(one) return DkSDX - elif self.curvatureType == 'mean': + elif self.curvatureType == "mean": # Now compute integral (H**2) over S, equivelent to sum(H**2*dS) - hS = numpy.dot(one,H*H*dS) - DhSDX = (self.diags(2*H*dS).dot(DHDX)+self.diags(H*H).dot(DdSDX)).T.dot(one) + hS = numpy.dot(one, H * H * dS) + DhSDX = (self.diags(2 * H * dS).dot(DHDX) + self.diags(H * H).dot(DdSDX)).T.dot(one) return DhSDX - elif self.curvatureType == 'combined': + elif self.curvatureType == "combined": # Now compute dcSDX. Note: cS= sum( (4*H*H-2*K)*dS ), DcSDX = term1 - term2 # where term1 = sum( 8*H*DHDX*dS + 4*H*H*DdSdX ), term2 = sum( 2*DKDX*dS + 2*K*DdSdX ) - term1 = (self.diags(8*H*dS).dot(DHDX)+self.diags(4*H*H).dot(DdSDX)).T.dot(one) - term2 = (self.diags(2*dS).dot(DKDX)+self.diags(2*K).dot(DdSDX)).T.dot(one) + term1 = (self.diags(8 * H * dS).dot(DHDX) + self.diags(4 * H * H).dot(DdSDX)).T.dot(one) + term2 = (self.diags(2 * dS).dot(DKDX) + self.diags(2 * K).dot(DdSDX)).T.dot(one) DcSDX = term1 - term2 return DcSDX - elif self.curvatureType == 'KSmean': - sigmaH=numpy.dot(one,numpy.exp(self.KSCoeff*H*H*dS)) - DhSDX = (self.diags(2*H*dS/sigmaH*numpy.exp(self.KSCoeff*H*H*dS)).dot(DHDX)+self.diags(H*H/sigmaH*numpy.exp(self.KSCoeff*H*H*dS)).dot(DdSDX)).T.dot(one) + elif self.curvatureType == "KSmean": + sigmaH = numpy.dot(one, numpy.exp(self.KSCoeff * H * H * dS)) + DhSDX = ( + self.diags(2 * H * dS / sigmaH * numpy.exp(self.KSCoeff * H * H * dS)).dot(DHDX) + + self.diags(H * H / sigmaH * numpy.exp(self.KSCoeff * H * H * dS)).dot(DdSDX) + ).T.dot(one) return DhSDX else: - raise Error("The curvatureType parameter should be Gaussian, mean, or combined, " - "%s is not supported!"%curvatureType) + raise Error( + "The curvatureType parameter should be Gaussian, mean, or combined, " + "%s is not supported!" % curvatureType + ) def evalCross(self, iSurf, u, v): - ''' + """ Evaluate the cross product of two vector fields on the surface (n = u x v) - ''' + """ n = numpy.zeros_like(self.X[iSurf]) - n[self.X_map[iSurf][:,:,0]] = u[self.X_map[iSurf][:,:,1]]*v[self.X_map[iSurf][:,:,2]] - u[self.X_map[iSurf][:,:,2]]*v[self.X_map[iSurf][:,:,1]] - n[self.X_map[iSurf][:,:,1]] = -u[self.X_map[iSurf][:,:,0]]*v[self.X_map[iSurf][:,:,2]] + u[self.X_map[iSurf][:,:,2]]*v[self.X_map[iSurf][:,:,0]] - n[self.X_map[iSurf][:,:,2]] = u[self.X_map[iSurf][:,:,0]]*v[self.X_map[iSurf][:,:,1]] - u[self.X_map[iSurf][:,:,1]]*v[self.X_map[iSurf][:,:,0]] + n[self.X_map[iSurf][:, :, 0]] = ( + u[self.X_map[iSurf][:, :, 1]] * v[self.X_map[iSurf][:, :, 2]] + - u[self.X_map[iSurf][:, :, 2]] * v[self.X_map[iSurf][:, :, 1]] + ) + n[self.X_map[iSurf][:, :, 1]] = ( + -u[self.X_map[iSurf][:, :, 0]] * v[self.X_map[iSurf][:, :, 2]] + + u[self.X_map[iSurf][:, :, 2]] * v[self.X_map[iSurf][:, :, 0]] + ) + n[self.X_map[iSurf][:, :, 2]] = ( + u[self.X_map[iSurf][:, :, 0]] * v[self.X_map[iSurf][:, :, 1]] + - u[self.X_map[iSurf][:, :, 1]] * v[self.X_map[iSurf][:, :, 0]] + ) return n def evalCrossSens(self, iSurf, u, v): - ''' + """ Evaluate sensitivity of cross product wrt to the input vectors u and v (DnDu, DnDv) - ''' + """ # Compute sensitivity wrt v ii = [] jj = [] data = [] # Dn[self.X_map[iSurf][:,:,0]]/Dv[self.X_map[iSurf][:,:,2]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,0],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,2],-1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:,:,1]],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) + data += list(numpy.reshape(u[self.X_map[iSurf][:, :, 1]], -1)) # Dn[self.X_map[iSurf][:,:,0]]/Dv[self.X_map[iSurf][:,:,1]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,0],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,1],-1)) - data += list(numpy.reshape(-u[self.X_map[iSurf][:,:,2]],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) + data += list(numpy.reshape(-u[self.X_map[iSurf][:, :, 2]], -1)) # Dn[self.X_map[iSurf][:,:,1]]/Dv[self.X_map[iSurf][:,:,2]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,1],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,2],-1)) - data += list(numpy.reshape(-u[self.X_map[iSurf][:,:,0]],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) + data += list(numpy.reshape(-u[self.X_map[iSurf][:, :, 0]], -1)) # Dn[self.X_map[iSurf][:,:,1]]/Dv[self.X_map[iSurf][:,:,0]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,1],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,0],-1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:,:,2]],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) + data += list(numpy.reshape(u[self.X_map[iSurf][:, :, 2]], -1)) # Dn[self.X_map[iSurf][:,:,2]]/Dv[self.X_map[iSurf][:,:,1]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,2],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,1],-1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:,:,0]],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) + data += list(numpy.reshape(u[self.X_map[iSurf][:, :, 0]], -1)) # Dn[self.X_map[iSurf][:,:,2]]/Dv[self.X_map[iSurf][:,:,0]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,2],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,0],-1)) - data += list(numpy.reshape(-u[self.X_map[iSurf][:,:,1]],-1)) - + ii += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) + data += list(numpy.reshape(-u[self.X_map[iSurf][:, :, 1]], -1)) - DnDv = csr_matrix((data,[ii,jj]),shape=(self.X[iSurf].size,self.X[iSurf].size)) + DnDv = csr_matrix((data, [ii, jj]), shape=(self.X[iSurf].size, self.X[iSurf].size)) # Now wrt v ii = [] jj = [] data = [] # Dn[self.X_map[iSurf][:,:,0]]/Du[self.X_map[iSurf][:,:,1]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,0],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,1],-1)) - data += list(numpy.reshape(v[self.X_map[iSurf][:,:,2]],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) + data += list(numpy.reshape(v[self.X_map[iSurf][:, :, 2]], -1)) # Dn[self.X_map[iSurf][:,:,0]]/Du[self.X_map[iSurf][:,:,2]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,0],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,2],-1)) - data += list(numpy.reshape(-v[self.X_map[iSurf][:,:,1]],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) + data += list(numpy.reshape(-v[self.X_map[iSurf][:, :, 1]], -1)) # Dn[self.X_map[iSurf][:,:,1]]/Du[self.X_map[iSurf][:,:,0]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,1],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,0],-1)) - data += list(numpy.reshape(-v[self.X_map[iSurf][:,:,2]],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) + data += list(numpy.reshape(-v[self.X_map[iSurf][:, :, 2]], -1)) # Dn[self.X_map[iSurf][:,:,1]]/Du[self.X_map[iSurf][:,:,2]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,1],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,2],-1)) - data += list(numpy.reshape(v[self.X_map[iSurf][:,:,0]],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) + data += list(numpy.reshape(v[self.X_map[iSurf][:, :, 0]], -1)) # Dn[self.X_map[iSurf][:,:,2]]/Du[self.X_map[iSurf][:,:,0]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,2],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,0],-1)) - data += list(numpy.reshape(v[self.X_map[iSurf][:,:,1]],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) + data += list(numpy.reshape(v[self.X_map[iSurf][:, :, 1]], -1)) # Dn[self.X_map[iSurf][:,:,2]]/Du[self.X_map[iSurf][:,:,1]] - ii += list(numpy.reshape(self.X_map[iSurf][:,:,2],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,1],-1)) - data += list(numpy.reshape(-v[self.X_map[iSurf][:,:,0]],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) + data += list(numpy.reshape(-v[self.X_map[iSurf][:, :, 0]], -1)) - - DnDu = csr_matrix((data,[ii,jj]),shape=(self.X[iSurf].size,self.X[iSurf].size)) + DnDu = csr_matrix((data, [ii, jj]), shape=(self.X[iSurf].size, self.X[iSurf].size)) return [DnDu, DnDv] def evalNorm(self, iSurf, u): - ''' + """ Evaluate the norm of vector field on the surface (u o u)**1/2 - ''' - u_norm = numpy.zeros(self.X[iSurf].size//3) - u_norm[self.node_map[iSurf][:,:]] = numpy.sqrt(u[self.X_map[iSurf][:,:,0]]**2 + \ - u[self.X_map[iSurf][:,:,1]]**2 + u[self.X_map[iSurf][:,:,2]]**2) + """ + u_norm = numpy.zeros(self.X[iSurf].size // 3) + u_norm[self.node_map[iSurf][:, :]] = numpy.sqrt( + u[self.X_map[iSurf][:, :, 0]] ** 2 + u[self.X_map[iSurf][:, :, 1]] ** 2 + u[self.X_map[iSurf][:, :, 2]] ** 2 + ) return u_norm def evalNormSens(self, iSurf, u): - ''' + """ Evaluate the sensitivity of the norm wrt input vector u - ''' - u_norm = numpy.zeros(self.X[iSurf].size//3) - u_norm[self.node_map[iSurf][:,:]] = numpy.sqrt(u[self.X_map[iSurf][:,:,0]]**2 + \ - u[self.X_map[iSurf][:,:,1]]**2 + u[self.X_map[iSurf][:,:,2]]**2) + """ + u_norm = numpy.zeros(self.X[iSurf].size // 3) + u_norm[self.node_map[iSurf][:, :]] = numpy.sqrt( + u[self.X_map[iSurf][:, :, 0]] ** 2 + u[self.X_map[iSurf][:, :, 1]] ** 2 + u[self.X_map[iSurf][:, :, 2]] ** 2 + ) ii = [] jj = [] data = [] # Du_norm[self.node_map[iSurf][:,:]]Du[self.X_map[iSurf][:,:,0]] - ii += list(numpy.reshape(self.node_map[iSurf][:,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,0],-1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:,:,0]]/u_norm[self.node_map[iSurf][:,:]],-1)) + ii += list(numpy.reshape(self.node_map[iSurf][:, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) + data += list(numpy.reshape(u[self.X_map[iSurf][:, :, 0]] / u_norm[self.node_map[iSurf][:, :]], -1)) # Du_norm[self.node_map[iSurf][:,:]]Du[self.X_map[iSurf][:,:,1]] - ii += list(numpy.reshape(self.node_map[iSurf][:,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,1],-1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:,:,1]]/u_norm[self.node_map[iSurf][:,:]],-1)) + ii += list(numpy.reshape(self.node_map[iSurf][:, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) + data += list(numpy.reshape(u[self.X_map[iSurf][:, :, 1]] / u_norm[self.node_map[iSurf][:, :]], -1)) # Du_norm[self.node_map[iSurf][:,:]]Du[self.X_map[iSurf][:,:,2]] - ii += list(numpy.reshape(self.node_map[iSurf][:,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,2],-1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:,:,2]]/u_norm[self.node_map[iSurf][:,:]],-1)) + ii += list(numpy.reshape(self.node_map[iSurf][:, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) + data += list(numpy.reshape(u[self.X_map[iSurf][:, :, 2]] / u_norm[self.node_map[iSurf][:, :]], -1)) - Du_normDu = csr_matrix((data,[ii,jj]),shape=(u_norm.size,self.X[iSurf].size)) + Du_normDu = csr_matrix((data, [ii, jj]), shape=(u_norm.size, self.X[iSurf].size)) return Du_normDu def evalInProd(self, iSurf, u, v): - ''' + """ Evaluate the inner product of two vector fields on the surface (ip = u o v) - ''' + """ ip = numpy.zeros(self.node_map[iSurf].size) for i in range(3): - ip[self.node_map[iSurf][:,:]] += u[self.X_map[iSurf][:,:,i]]*v[self.X_map[iSurf][:,:,i]] + ip[self.node_map[iSurf][:, :]] += u[self.X_map[iSurf][:, :, i]] * v[self.X_map[iSurf][:, :, i]] return ip def evalInProdSens(self, iSurf, u, v): - ''' + """ Evaluate sensitivity of inner product wrt to the input vectors u and v (DipDu, DipDv) - ''' + """ ii = [] jj = [] data = [] for i in range(3): # Dip[node_map[:,:]]/Du[self.X_map[iSurf][:,:,i]] - ii += list(numpy.reshape(self.node_map[iSurf][:,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,i],-1)) - data += list(numpy.reshape(v[self.X_map[iSurf][:,:,i]],-1)) - DipDu = csr_matrix((data,[ii,jj]),shape=(self.node_map[iSurf].size,self.X_map[iSurf].size)) + ii += list(numpy.reshape(self.node_map[iSurf][:, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, i], -1)) + data += list(numpy.reshape(v[self.X_map[iSurf][:, :, i]], -1)) + DipDu = csr_matrix((data, [ii, jj]), shape=(self.node_map[iSurf].size, self.X_map[iSurf].size)) ii = [] jj = [] data = [] for i in range(3): # Dip[node_map[:,:]]/Dv[self.X_map[iSurf][:,:,i]] - ii += list(numpy.reshape(self.node_map[iSurf][:,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,:,i],-1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:,:,i]],-1)) - DipDv = csr_matrix((data,[ii,jj]),shape=(self.node_map[iSurf].size,self.X_map[iSurf].size)) + ii += list(numpy.reshape(self.node_map[iSurf][:, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, :, i], -1)) + data += list(numpy.reshape(u[self.X_map[iSurf][:, :, i]], -1)) + DipDv = csr_matrix((data, [ii, jj]), shape=(self.node_map[iSurf].size, self.X_map[iSurf].size)) return [DipDu, DipDv] def evalDiff(self, iSurf, v, wrt): - ''' + """ Diferentiate vector field v wrt the parameteric coordinate u or v. Second order accurate. Central difference for nodes in the center forward/backward difference for nodes on the edge - ''' + """ v_wrt = numpy.zeros_like(v) - if wrt == 'u': - v_wrt[self.X_map[iSurf][1:-1,:,:]]=(v[self.X_map[iSurf][2:,:,:]]-v[self.X_map[iSurf][0:-2,:,:]])/2.0 - v_wrt[self.X_map[iSurf][0,:,:]]=(-1*v[self.X_map[iSurf][2,:,:]]+4*v[self.X_map[iSurf][1,:,:]]-3*v[self.X_map[iSurf][0,:,:]])/2.0 - v_wrt[self.X_map[iSurf][-1,:,:]]=-(-1*v[self.X_map[iSurf][-3,:,:]]+4*v[self.X_map[iSurf][-2,:,:]]-3*v[self.X_map[iSurf][-1,:,:]])/2.0 - elif wrt == 'v': - v_wrt[self.X_map[iSurf][:,1:-1,:]]=(v[self.X_map[iSurf][:,2:,:]]-v[self.X_map[iSurf][:,0:-2,:]])/2.0 - v_wrt[self.X_map[iSurf][:,0,:]]=(-1*v[self.X_map[iSurf][:,2,:]]+4*v[self.X_map[iSurf][:,1,:]]-3*v[self.X_map[iSurf][:,0,:]])/2.0 - v_wrt[self.X_map[iSurf][:,-1,:]]=-(-1*v[self.X_map[iSurf][:,-3,:]]+4*v[self.X_map[iSurf][:,-2,:]]-3*v[self.X_map[iSurf][:,-1,:]])/2.0 + if wrt == "u": + v_wrt[self.X_map[iSurf][1:-1, :, :]] = ( + v[self.X_map[iSurf][2:, :, :]] - v[self.X_map[iSurf][0:-2, :, :]] + ) / 2.0 + v_wrt[self.X_map[iSurf][0, :, :]] = ( + -1 * v[self.X_map[iSurf][2, :, :]] + + 4 * v[self.X_map[iSurf][1, :, :]] + - 3 * v[self.X_map[iSurf][0, :, :]] + ) / 2.0 + v_wrt[self.X_map[iSurf][-1, :, :]] = ( + -( + -1 * v[self.X_map[iSurf][-3, :, :]] + + 4 * v[self.X_map[iSurf][-2, :, :]] + - 3 * v[self.X_map[iSurf][-1, :, :]] + ) + / 2.0 + ) + elif wrt == "v": + v_wrt[self.X_map[iSurf][:, 1:-1, :]] = ( + v[self.X_map[iSurf][:, 2:, :]] - v[self.X_map[iSurf][:, 0:-2, :]] + ) / 2.0 + v_wrt[self.X_map[iSurf][:, 0, :]] = ( + -1 * v[self.X_map[iSurf][:, 2, :]] + + 4 * v[self.X_map[iSurf][:, 1, :]] + - 3 * v[self.X_map[iSurf][:, 0, :]] + ) / 2.0 + v_wrt[self.X_map[iSurf][:, -1, :]] = ( + -( + -1 * v[self.X_map[iSurf][:, -3, :]] + + 4 * v[self.X_map[iSurf][:, -2, :]] + - 3 * v[self.X_map[iSurf][:, -1, :]] + ) + / 2.0 + ) return v_wrt def evalDiffSens(self, iSurf, wrt): - ''' + """ Compute sensitivity of v_wrt with respect to input vector fiel v (Dv_wrt/Dv) - ''' + """ ii = [] jj = [] data = [] - if wrt == 'u': + if wrt == "u": # Central Difference # Dt_u[X_map[1:-1,:,:]]/DX[X_map[2:,:,:]] = 1/2 - ii += list(numpy.reshape(self.X_map[iSurf][1:-1,:,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][2:,:,:],-1)) - data+=[0.5]*len(numpy.reshape(self.X_map[iSurf][1:-1,:,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][1:-1, :, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][2:, :, :], -1)) + data += [0.5] * len(numpy.reshape(self.X_map[iSurf][1:-1, :, :], -1)) # Dt_u[X_map[1:-1,:,:]]/DX[X_map[0:-2,:,:]] = -1/2 - ii += list(numpy.reshape(self.X_map[iSurf][1:-1,:,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][0:-2,:,:],-1)) - data+=[-0.5]*len(numpy.reshape(self.X_map[iSurf][1:-1,:,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][1:-1, :, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][0:-2, :, :], -1)) + data += [-0.5] * len(numpy.reshape(self.X_map[iSurf][1:-1, :, :], -1)) # Forward Difference # Dt_u[X_map[0,:,:]]/DX[X_map[2,:,:]] = -1/2 - ii += list(numpy.reshape(self.X_map[iSurf][0,:,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][2,:,:],-1)) - data+=[-0.5]*len(numpy.reshape(self.X_map[iSurf][0,:,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][2, :, :], -1)) + data += [-0.5] * len(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) # Dt_u[X_map[0,:,:]]/DX[X_map[1,:,:]] = 4/2 - ii += list(numpy.reshape(self.X_map[iSurf][0,:,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][1,:,:],-1)) - data+=[2]*len(numpy.reshape(self.X_map[iSurf][0,:,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][1, :, :], -1)) + data += [2] * len(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) # Dt_u[X_map[0,:,:]]/DX[X_map[0,:,:]] = -3/2 - ii += list(numpy.reshape(self.X_map[iSurf][0,:,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][0,:,:],-1)) - data+=[-1.5]*len(numpy.reshape(self.X_map[iSurf][0,:,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) + data += [-1.5] * len(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) # Backward Difference # Dt_u[X_map[-1,:,:]]/DX[X_map[-3,:,:]] = 1/2 - ii += list(numpy.reshape(self.X_map[iSurf][-1,:,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][-3,:,:],-1)) - data+=[0.5]*len(numpy.reshape(self.X_map[iSurf][-1,:,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][-1, :, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][-3, :, :], -1)) + data += [0.5] * len(numpy.reshape(self.X_map[iSurf][-1, :, :], -1)) # Dt_u[X_map[-1,:,:]]/DX[X_map[-2,:,:]] = -4/2 - ii += list(numpy.reshape(self.X_map[iSurf][-1,:,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][-2,:,:],-1)) - data+=[-2.0]*len(numpy.reshape(self.X_map[iSurf][-2,:,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][-1, :, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][-2, :, :], -1)) + data += [-2.0] * len(numpy.reshape(self.X_map[iSurf][-2, :, :], -1)) # Dt_u[X_map[-1,:,:]]/DX[X_map[-1,:,:]] = 3/2 - ii += list(numpy.reshape(self.X_map[iSurf][-1,:,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][-1,:,:],-1)) - data+=[1.5]*len(numpy.reshape(self.X_map[iSurf][-1,:,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][-1, :, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][-1, :, :], -1)) + data += [1.5] * len(numpy.reshape(self.X_map[iSurf][-1, :, :], -1)) - elif wrt == 'v': + elif wrt == "v": # Central Difference # Dt_u[X_map[:,1:-1,:]]/DX[X_map[:,2:,:]] = 1/2 - ii += list(numpy.reshape(self.X_map[iSurf][:,1:-1,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,2:,:],-1)) - data+=[0.5]*len(numpy.reshape(self.X_map[iSurf][:,1:-1,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, 1:-1, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, 2:, :], -1)) + data += [0.5] * len(numpy.reshape(self.X_map[iSurf][:, 1:-1, :], -1)) # Dt_u[X_map[:,1:-1,:]]/DX[X_map[:,0:-2,:]] = -1/2 - ii += list(numpy.reshape(self.X_map[iSurf][:,1:-1,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,0:-2,:],-1)) - data+=[-0.5]*len(numpy.reshape(self.X_map[iSurf][:,1:-1,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, 1:-1, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, 0:-2, :], -1)) + data += [-0.5] * len(numpy.reshape(self.X_map[iSurf][:, 1:-1, :], -1)) # Forward Difference # Dt_u[X_map[:,0,:]]/DX[X_map[:,2,:]] = -1/2 - ii += list(numpy.reshape(self.X_map[iSurf][:,0,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,2,:],-1)) - data+=[-0.5]*len(numpy.reshape(self.X_map[iSurf][:,0,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, 2, :], -1)) + data += [-0.5] * len(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) # Dt_u[X_map[:,0,:]]/DX[X_map[:,1,:]] = 4/2 - ii += list(numpy.reshape(self.X_map[iSurf][:,0,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,1,:],-1)) - data+=[2]*len(numpy.reshape(self.X_map[iSurf][:,0,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, 1, :], -1)) + data += [2] * len(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) # Dt_u[X_map[:,0,:]]/DX[X_map[:,0,:]] = -3/2 - ii += list(numpy.reshape(self.X_map[iSurf][:,0,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,0,:],-1)) - data+=[-1.5]*len(numpy.reshape(self.X_map[iSurf][:,0,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) + data += [-1.5] * len(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) # Backward Difference # Dt_u[X_map[:,-1,:]]/DX[X_map[:,-3,:]] = 1/2 - ii += list(numpy.reshape(self.X_map[iSurf][:,-1,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,-3,:],-1)) - data+=[0.5]*len(numpy.reshape(self.X_map[iSurf][:,-1,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, -1, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, -3, :], -1)) + data += [0.5] * len(numpy.reshape(self.X_map[iSurf][:, -1, :], -1)) # Dt_u[X_map[:,-1,:]]/DX[X_map[:,-2,:]] = -4/2 - ii += list(numpy.reshape(self.X_map[iSurf][:,-1,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,-2,:],-1)) - data+=[-2.0]*len(numpy.reshape(self.X_map[iSurf][:,-2,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, -1, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, -2, :], -1)) + data += [-2.0] * len(numpy.reshape(self.X_map[iSurf][:, -2, :], -1)) # Dt_u[X_map[:,-1,:]]/DX[X_map[:,-1,:]] = 3/2 - ii += list(numpy.reshape(self.X_map[iSurf][:,-1,:],-1)) - jj += list(numpy.reshape(self.X_map[iSurf][:,-1,:],-1)) - data+=[1.5]*len(numpy.reshape(self.X_map[iSurf][:,-1,:],-1)) + ii += list(numpy.reshape(self.X_map[iSurf][:, -1, :], -1)) + jj += list(numpy.reshape(self.X_map[iSurf][:, -1, :], -1)) + data += [1.5] * len(numpy.reshape(self.X_map[iSurf][:, -1, :], -1)) - Dv_uDX = csr_matrix((data,[ii,jj]),shape=(self.X[iSurf].size,self.X[iSurf].size)) + Dv_uDX = csr_matrix((data, [ii, jj]), shape=(self.X[iSurf].size, self.X[iSurf].size)) return Dv_uDX def diags(self, a): - ''' + """ A standard vectorized sparse diagnal matrix function. Similar to the above \ function some versions of scipy don't have this function, so this is here to prevent\ potential import problems. - ''' - ii=range(len(a)) - return csr_matrix((a,[ii,ii]),(len(a),len(a))) + """ + ii = range(len(a)) + return csr_matrix((a, [ii, ii]), (len(a), len(a))) def writeTecplot(self, handle1): - ''' + """ Write Curvature data on the surface to a tecplot file. Data includes mean curvature, H, and Gaussian curvature, K. Input: tec_file: name of TecPlot file. - ''' + """ # we ignore the input handle and use this separated name for curvature constraint tecplot file # NOTE: we use this tecplot file to only visualize the local distribution of curctures. # The plotted local curvatures are not exactly as that computed in the evalCurvArea function - handle = open('%s.dat'%self.name,'w') + handle = open("%s.dat" % self.name, "w") handle.write('title = "DVConstraint curvature constraint"\n') - varbs='variables = "x", "y", "z", "K", "H" "C"' - handle.write(varbs+'\n') + varbs = 'variables = "x", "y", "z", "K", "H" "C"' + handle.write(varbs + "\n") for iSurf in range(self.nSurfs): - [_,K,H,C] = self.evalCurvArea(iSurf) - handle.write('Zone T=%s_%d\n'% (self.name,iSurf)) + [_, K, H, C] = self.evalCurvArea(iSurf) + handle.write("Zone T=%s_%d\n" % (self.name, iSurf)) - handle.write('Nodes = %d, Elements = %d, f=fepoint, et=quadrilateral\n'% ( - len(self.coords[iSurf]), (self.X_map[iSurf].shape[0]-1)*(self.X_map[iSurf].shape[1]-1))) + handle.write( + "Nodes = %d, Elements = %d, f=fepoint, et=quadrilateral\n" + % (len(self.coords[iSurf]), (self.X_map[iSurf].shape[0] - 1) * (self.X_map[iSurf].shape[1] - 1)) + ) for i in range(self.X_map[iSurf].shape[0]): for j in range(self.X_map[iSurf].shape[1]): - handle.write('%E %E %E %E %E %E\n'% (self.X[iSurf][self.X_map[iSurf][i, j, 0]], self.X[iSurf][self.X_map[iSurf][i, j, 1]], - self.X[iSurf][self.X_map[iSurf][i, j, 2]],K[self.node_map[iSurf][i,j]],H[self.node_map[iSurf][i,j]],C[self.node_map[iSurf][i,j]])) - handle.write('\n') - for i in range(self.X_map[iSurf].shape[0]-1): - for j in range(self.X_map[iSurf].shape[1]-1): - handle.write('%d %d %d %d\n'% (self.node_map[iSurf][i,j]+1, self.node_map[iSurf][i+1,j]+1,self.node_map[iSurf][i+1,j+1]+1,self.node_map[iSurf][i,j+1]+1)) + handle.write( + "%E %E %E %E %E %E\n" + % ( + self.X[iSurf][self.X_map[iSurf][i, j, 0]], + self.X[iSurf][self.X_map[iSurf][i, j, 1]], + self.X[iSurf][self.X_map[iSurf][i, j, 2]], + K[self.node_map[iSurf][i, j]], + H[self.node_map[iSurf][i, j]], + C[self.node_map[iSurf][i, j]], + ) + ) + handle.write("\n") + for i in range(self.X_map[iSurf].shape[0] - 1): + for j in range(self.X_map[iSurf].shape[1] - 1): + handle.write( + "%d %d %d %d\n" + % ( + self.node_map[iSurf][i, j] + 1, + self.node_map[iSurf][i + 1, j] + 1, + self.node_map[iSurf][i + 1, j + 1] + 1, + self.node_map[iSurf][i, j + 1] + 1, + ) + ) handle.close() + class GlobalLinearConstraint(object): """ This class is used to represent a set of generic set of linear constriants coupling global design variables together. """ + def __init__(self, name, key, type, options, lower, upper, DVGeo, config): # No error checking here since the calling routine should have # already done it. @@ -6099,7 +6391,7 @@ def __init__(self, name, key, type, options, lower, upper, DVGeo, config): self.ncon = 0 self.jac = {} self.config = config - if self.type == 'monotonic': + if self.type == "monotonic": self.setMonotonic(options) def evalFunctions(self, funcs): @@ -6119,7 +6411,7 @@ def evalFunctions(self, funcs): for key in self.jac: cons.extend(self.jac[key].dot(self.DVGeo.DV_listGlobal[key].value)) - funcs[self.name] = numpy.array(cons).real.astype('d') + funcs[self.name] = numpy.array(cons).real.astype("d") def evalFunctionsSens(self, funcsSens): """ @@ -6140,9 +6432,17 @@ def addConstraintsPyOpt(self, optProb): """ if self.ncon > 0: for key in self.jac: - optProb.addConGroup(self.name+'_'+key, self.jac[key].shape[0], - lower=self.lower, upper=self.upper, scale=1.0, - linear=True, wrt=key, jac={key:self.jac[key]}) + optProb.addConGroup( + self.name + "_" + key, + self.jac[key].shape[0], + lower=self.lower, + upper=self.upper, + scale=1.0, + linear=True, + wrt=key, + jac={key: self.jac[key]}, + ) + def setMonotonic(self, options): """ Set up monotonicity jacobian for the given global design variable @@ -6151,8 +6451,8 @@ def setMonotonic(self, options): if self.config is None or self.config in self.DVGeo.DV_listGlobal[self.key].config: ndv = self.DVGeo.DV_listGlobal[self.key].nVal - start = options['start'] - stop = options['stop'] + start = options["start"] + stop = options["stop"] if stop == -1: stop = ndv @@ -6162,10 +6462,10 @@ def setMonotonic(self, options): ncon = len(numpy.zeros(ndv)[start:stop]) - 1 jacobian = numpy.zeros((ncon, ndv)) - slope = options['slope'] + slope = options["slope"] for i in range(ncon): - jacobian[i, start+i] = 1.0*slope - jacobian[i, start+i+1] = -1.0*slope + jacobian[i, start + i] = 1.0 * slope + jacobian[i, start + i + 1] = -1.0 * slope self.jac[self.key] = jacobian self.ncon += ncon diff --git a/pygeo/DVGeometry.py b/pygeo/DVGeometry.py index d5804d77..4f98c291 100644 --- a/pygeo/DVGeometry.py +++ b/pygeo/DVGeometry.py @@ -1,15 +1,15 @@ # ====================================================================== # Imports # ====================================================================== -import copy,time +import copy, time + try: from collections import OrderedDict except ImportError: try: from ordereddict import OrderedDict except ImportError: - print("Could not find any OrderedDict class. For 2.6 and earlier, " - "use:\n pip install ordereddict") + print("Could not find any OrderedDict class. For 2.6 and earlier, " "use:\n pip install ordereddict") import numpy from scipy import sparse from mpi4py import MPI @@ -17,25 +17,28 @@ from . import pyNetwork, pyBlock, geo_utils import os + class Error(Exception): """ Format the error message in a box to make it clear this was a explicitly raised exception. """ + def __init__(self, message): - msg = '\n+'+'-'*78+'+'+'\n' + '| DVGeometry Error: ' + msg = "\n+" + "-" * 78 + "+" + "\n" + "| DVGeometry Error: " i = 19 for word in message.split(): - if len(word) + i + 1 > 78: # Finish line and start new one - msg += ' '*(78-i)+'|\n| ' + word + ' ' - i = 1 + len(word)+1 + if len(word) + i + 1 > 78: # Finish line and start new one + msg += " " * (78 - i) + "|\n| " + word + " " + i = 1 + len(word) + 1 else: - msg += word + ' ' - i += len(word)+1 - msg += ' '*(78-i) + '|\n' + '+'+'-'*78+'+'+'\n' + msg += word + " " + i += len(word) + 1 + msg += " " * (78 - i) + "|\n" + "+" + "-" * 78 + "+" + "\n" print(msg) Exception.__init__(self) + class DVGeometry(object): """ A class for manipulating geometry. @@ -95,13 +98,14 @@ class DVGeometry(object): >>> # Now add local (shape) variables >>> DVGeo.addGeoDVLocal('shape', lower=-0.5, upper=0.5, axis='y') >>> - """ + """ + def __init__(self, fileName, complex=False, child=False, faceFreeze=None, name=None, *args, **kwargs): - self.DV_listGlobal = OrderedDict() # Global Design Variable List - self.DV_listLocal = OrderedDict() # Local Design Variable List - self.DV_listSectionLocal = OrderedDict() # Local Normal Design Variable List - self.DV_listSpanwiseLocal = OrderedDict() # Local Normal Design Variable List + self.DV_listGlobal = OrderedDict() # Global Design Variable List + self.DV_listLocal = OrderedDict() # Local Design Variable List + self.DV_listSectionLocal = OrderedDict() # Local Normal Design Variable List + self.DV_listSpanwiseLocal = OrderedDict() # Local Normal Design Variable List # Coefficient rotation matrix dict for Section Local variables self.coefRotM = {} @@ -119,15 +123,14 @@ def __init__(self, fileName, complex=False, child=False, faceFreeze=None, name=N self.finalized = False self.complex = complex if self.complex: - self.dtype = 'D' + self.dtype = "D" else: - self.dtype = 'd' + self.dtype = "d" # Load the FFD file in FFD mode. Also note that args and # kwargs are passed through in case additional pyBlock options # need to be set. - self.FFD = pyBlock('plot3d', fileName=fileName, FFD=True, - *args, **kwargs) + self.FFD = pyBlock("plot3d", fileName=fileName, FFD=True, *args, **kwargs) self.origFFDCoef = self.FFD.coef.copy() # Jacobians: @@ -144,15 +147,15 @@ def __init__(self, fileName, complex=False, child=False, faceFreeze=None, name=N self.dCoefdXdvl = None # derivative counters for offsets - self.nDV_T = None # total number of design variables + self.nDV_T = None # total number of design variables self.nDVG_T = None self.nDVL_T = None self.nDVSL_T = None self.nDVSW_T = None - self.nDVG_count = 0 # number of global (G) variables - self.nDVL_count = 0 # number of local (L) variables - self.nDVSL_count = 0 # number of section (SL) local variables - self.nDVSW_count = 0 # number of spanwise (SW) local variables + self.nDVG_count = 0 # number of global (G) variables + self.nDVL_count = 0 # number of local (L) variables + self.nDVSL_count = 0 # number of section (SL) local variables + self.nDVSW_count = 0 # number of spanwise (SW) local variables # The set of user supplied axis. self.axis = OrderedDict() @@ -160,30 +163,32 @@ def __init__(self, fileName, complex=False, child=False, faceFreeze=None, name=N # Generate coefMask regardless coefMask = [] for iVol in range(self.FFD.nVol): - coefMask.append(numpy.zeros((self.FFD.vols[iVol].nCtlu, - self.FFD.vols[iVol].nCtlv, - self.FFD.vols[iVol].nCtlw), dtype=bool)) + coefMask.append( + numpy.zeros( + (self.FFD.vols[iVol].nCtlu, self.FFD.vols[iVol].nCtlv, self.FFD.vols[iVol].nCtlw), dtype=bool + ) + ) # Now do the faceFreeze if faceFreeze is not None: for iVol in range(self.FFD.nVol): - key = '%d'%iVol + key = "%d" % iVol if key in faceFreeze.keys(): - if 'iLow' in faceFreeze[key]: + if "iLow" in faceFreeze[key]: coefMask[iVol][0, :, :] = True coefMask[iVol][1, :, :] = True - if 'iHigh' in faceFreeze[key]: + if "iHigh" in faceFreeze[key]: coefMask[iVol][-1, :, :] = True coefMask[iVol][-2, :, :] = True - if 'jLow' in faceFreeze[key]: + if "jLow" in faceFreeze[key]: coefMask[iVol][:, 0, :] = True coefMask[iVol][:, 1, :] = True - if 'jHigh' in faceFreeze[key]: + if "jHigh" in faceFreeze[key]: coefMask[iVol][:, -1, :] = True coefMask[iVol][:, -2, :] = True - if 'kLow' in faceFreeze[key]: + if "kLow" in faceFreeze[key]: coefMask[iVol][:, :, 0] = True coefMask[iVol][:, :, 1] = True - if 'kHigh' in faceFreeze[key]: + if "kHigh" in faceFreeze[key]: coefMask[iVol][:, :, -1] = True coefMask[iVol][:, :, -2] = True @@ -199,11 +204,25 @@ def __init__(self, fileName, complex=False, child=False, faceFreeze=None, name=N tmp[ind] = True self.masks = tmp - def addRefAxis(self, name, curve=None, xFraction=None, yFraction=None, zFraction=None, volumes=None, - rotType=5, axis='x', alignIndex=None, rotAxisVar=None, - rot0ang=None, rot0axis=[1, 0, 0], - xFractionOrder=2, includeVols=[], ignoreInd=[], - raySize=1.5): + def addRefAxis( + self, + name, + curve=None, + xFraction=None, + yFraction=None, + zFraction=None, + volumes=None, + rotType=5, + axis="x", + alignIndex=None, + rotAxisVar=None, + rot0ang=None, + rot0axis=[1, 0, 0], + xFractionOrder=2, + includeVols=[], + ignoreInd=[], + raySize=1.5, + ): """ This function is used to add a 'reference' axis to the DVGeometry object. Adding a reference axis is only required @@ -329,46 +348,64 @@ def addRefAxis(self, name, curve=None, xFraction=None, yFraction=None, zFraction # dictionary structure. if axis is None: pass - elif axis.lower() == 'x': - axis = numpy.array([1, 0, 0], 'd') - elif axis.lower() == 'y': - axis = numpy.array([0, 1, 0], 'd') - elif axis.lower() == 'z': - axis = numpy.array([0, 0, 1], 'd') + elif axis.lower() == "x": + axis = numpy.array([1, 0, 0], "d") + elif axis.lower() == "y": + axis = numpy.array([0, 1, 0], "d") + elif axis.lower() == "z": + axis = numpy.array([0, 0, 1], "d") if curve is not None: # Explicit curve has been supplied: if self.FFD.symmPlane is None: if volumes is None: volumes = numpy.arange(self.FFD.nVol) - self.axis[name] = {'curve':curve, 'volumes':volumes, - 'rotType':rotType, 'axis':axis, 'rot0ang':rot0ang, 'rot0axis':rot0axis} + self.axis[name] = { + "curve": curve, + "volumes": volumes, + "rotType": rotType, + "axis": axis, + "rot0ang": rot0ang, + "rot0axis": rot0axis, + } else: # get the direction of the symmetry plane - if self.FFD.symmPlane.lower() == 'x': + if self.FFD.symmPlane.lower() == "x": index = 0 - elif self.FFD.symmPlane.lower() == 'y': + elif self.FFD.symmPlane.lower() == "y": index = 1 - elif self.FFD.symmPlane.lower() == 'z': + elif self.FFD.symmPlane.lower() == "z": index = 2 # mirror the axis and attach the mirrored vols if volumes is None: - volumes = numpy.arange(self.FFD.nVol/2) + volumes = numpy.arange(self.FFD.nVol / 2) volumesSymm = [] for volume in volumes: - volumesSymm.append(volume+self.FFD.nVol/2) + volumesSymm.append(volume + self.FFD.nVol / 2) curveSymm = copy.deepcopy(curve) curveSymm.reverse() for coef in curveSymm.coef: - curveSymm.coef[:,index]=-curveSymm.coef[:,index] - self.axis[name] = {'curve':curve, 'volumes':volumes, - 'rotType':rotType, 'axis':axis,'rot0ang':rot0ang, 'rot0axis':rot0axis} - self.axis[name+'Symm'] = {'curve':curveSymm, 'volumes':volumesSymm, - 'rotType':rotType, 'axis':axis, 'rot0ang':rot0ang, 'rot0axis':rot0axis} + curveSymm.coef[:, index] = -curveSymm.coef[:, index] + self.axis[name] = { + "curve": curve, + "volumes": volumes, + "rotType": rotType, + "axis": axis, + "rot0ang": rot0ang, + "rot0axis": rot0axis, + } + self.axis[name + "Symm"] = { + "curve": curveSymm, + "volumes": volumesSymm, + "rotType": rotType, + "axis": axis, + "rot0ang": rot0ang, + "rot0axis": rot0axis, + } nAxis = len(curve.coef) elif xFraction or yFraction or zFraction: # Some assumptions @@ -385,16 +422,16 @@ def addRefAxis(self, name, curve=None, xFraction=None, yFraction=None, zFraction # This is the block direction along which the reference axis will lie # alignIndex = 'k' if alignIndex is None: - raise Error('Must specify alignIndex to use xFraction.') + raise Error("Must specify alignIndex to use xFraction.") # Get index direction along which refaxis will be aligned - if alignIndex.lower() == 'i': + if alignIndex.lower() == "i": alignIndex = 0 faceCol = 2 - elif alignIndex.lower() == 'j': + elif alignIndex.lower() == "j": alignIndex = 1 faceCol = 4 - elif alignIndex.lower() == 'k': + elif alignIndex.lower() == "k": alignIndex = 2 faceCol = 0 @@ -409,16 +446,17 @@ def addRefAxis(self, name, curve=None, xFraction=None, yFraction=None, zFraction for iter in range(nVol): for vInd, i in enumerate(v): for pInd, j in enumerate(volOrd): - if faceLink[i,faceCol] == faceLink[j,faceCol+1]: - volOrd.insert(pInd+1, v.pop(vInd)) + if faceLink[i, faceCol] == faceLink[j, faceCol + 1]: + volOrd.insert(pInd + 1, v.pop(vInd)) break - elif faceLink[i,faceCol+1] == faceLink[j,faceCol]: + elif faceLink[i, faceCol + 1] == faceLink[j, faceCol]: volOrd.insert(pInd, v.pop(vInd)) break if len(volOrd) < nVol: - raise Error("The volumes are not ordered with matching faces" - " in the direction of the reference axis.") + raise Error( + "The volumes are not ordered with matching faces" " in the direction of the reference axis." + ) # Count total number of sections and check if volumes are aligned # face to face along refaxis direction @@ -451,9 +489,9 @@ def addRefAxis(self, name, curve=None, xFraction=None, yFraction=None, zFraction # rotating the FFD to be aligned with main axes for ct_ in range(numpy.shape(pts_vec)[0]): # here we loop over the pts_vec, rotate them and insert them inplace in pts_vec again - p_ = numpy.copy(pts_vec[ct_ , :]) + p_ = numpy.copy(pts_vec[ct_, :]) p_rot = geo_utils.rotVbyW(p_, rot0axis, numpy.pi / 180 * (rot0ang)) - pts_vec[ct_ , :] = p_rot + pts_vec[ct_, :] = p_rot # Temporary ref axis node coordinates - aligned with main system of reference if xFraction: @@ -501,18 +539,23 @@ def addRefAxis(self, name, curve=None, xFraction=None, yFraction=None, zFraction # Generate reference axis pySpline curve curve = pySpline.Curve(X=refaxisNodes, k=2) nAxis = len(curve.coef) - self.axis[name] = {'curve':curve, 'volumes':volumes, - 'rotType':rotType, 'axis':axis, 'rot0ang':rot0ang, 'rot0axis':rot0axis, - 'rotAxisVar':rotAxisVar} + self.axis[name] = { + "curve": curve, + "volumes": volumes, + "rotType": rotType, + "axis": axis, + "rot0ang": rot0ang, + "rot0axis": rot0axis, + "rotAxisVar": rotAxisVar, + } else: - raise Error("One of 'curve' or 'xFraction' must be " - "specified for a call to addRefAxis") + raise Error("One of 'curve' or 'xFraction' must be " "specified for a call to addRefAxis") # Specify indices to be ignored - self.axis[name]['ignoreInd'] = ignoreInd + self.axis[name]["ignoreInd"] = ignoreInd # Add the raySize multiplication factor for this axis - self.axis[name]['raySize'] = raySize + self.axis[name]["raySize"] = raySize return nAxis @@ -539,13 +582,12 @@ def addPointSet(self, points, ptName, origConfig=True, **kwargs): always be True except in circumstances when the user knows exactly what they are doing.""" - # save this name so that we can zero out the jacobians properly self.ptSetNames.append(ptName) self.zeroJacobians([ptName]) - self.nPts[ptName]=None + self.nPts[ptName] = None - points = numpy.array(points).real.astype('d') + points = numpy.array(points).real.astype("d") self.points[ptName] = points # Ensure we project into the undeformed geometry @@ -556,11 +598,9 @@ def addPointSet(self, points, ptName, origConfig=True, **kwargs): # Project the last set of points into the volume if self.isChild: - self.FFD.attachPoints( - self.points[ptName], ptName, interiorOnly=True, **kwargs) + self.FFD.attachPoints(self.points[ptName], ptName, interiorOnly=True, **kwargs) else: - self.FFD.attachPoints( - self.points[ptName], ptName, interiorOnly=False) + self.FFD.attachPoints(self.points[ptName], ptName, interiorOnly=False) if origConfig: self.FFD.coef = tmpCoef @@ -595,28 +635,26 @@ def addChild(self, childDVGeo): # Make sure the DVGeo being added is flaged as a child: if childDVGeo.isChild is False: - raise Error("Trying to add a child FFD that has NOT been " - "created as a child. This operation is illegal.") + raise Error("Trying to add a child FFD that has NOT been " "created as a child. This operation is illegal.") # Extract the coef from the child FFD and ref axis and embed # them into the parent and compute their derivatives iChild = len(self.children) childDVGeo.iChild = iChild - self.FFD.attachPoints(childDVGeo.FFD.coef, 'child%d_coef'%(iChild)) - self.FFD.calcdPtdCoef('child%d_coef'%(iChild)) + self.FFD.attachPoints(childDVGeo.FFD.coef, "child%d_coef" % (iChild)) + self.FFD.calcdPtdCoef("child%d_coef" % (iChild)) # We must finalize the Child here since we need the ref axis # coefficients childDVGeo._finalizeAxis() - self.FFD.attachPoints(childDVGeo.refAxis.coef, 'child%d_axis'%(iChild)) - self.FFD.calcdPtdCoef('child%d_axis'%(iChild)) + self.FFD.attachPoints(childDVGeo.refAxis.coef, "child%d_axis" % (iChild)) + self.FFD.calcdPtdCoef("child%d_axis" % (iChild)) # Add the child to the parent and return self.children.append(childDVGeo) - def addGeoDVGlobal(self, dvName, value, func, lower=None, upper=None, - scale=1.0, config=None): + def addGeoDVGlobal(self, dvName, value, func, lower=None, upper=None, scale=1.0, config=None): """ Add a global design variable to the DVGeometry object. This type of design variable acts on one or more reference axis. @@ -660,15 +698,15 @@ def addGeoDVGlobal(self, dvName, value, func, lower=None, upper=None, """ # if the parent DVGeometry object has a name attribute, prepend it if self.name is not None: - dvName = self.name + '_' + dvName + dvName = self.name + "_" + dvName if type(config) == str: config = [config] - self.DV_listGlobal[dvName] = geoDVGlobal( - dvName, value, lower, upper, scale, func, config) + self.DV_listGlobal[dvName] = geoDVGlobal(dvName, value, lower, upper, scale, func, config) - def addGeoDVLocal(self, dvName, lower=None, upper=None, scale=1.0, - axis='y', volList=None, pointSelect=None, config=None): + def addGeoDVLocal( + self, dvName, lower=None, upper=None, scale=1.0, axis="y", volList=None, pointSelect=None, config=None + ): """ Add one or more local design variables ot the DVGeometry object. Local variables are used for small shape modifications. @@ -731,13 +769,13 @@ def addGeoDVLocal(self, dvName, lower=None, upper=None, scale=1.0, >>> nVar = DVGeo.addGeoDVLocal('shape_vars', lower=-1.0, upper=1.0, pointSelect=PS) """ if self.name is not None: - dvName = self.name + '_' + dvName + dvName = self.name + "_" + dvName if type(config) == str: config = [config] if pointSelect is not None: - if pointSelect.type != 'ijkBounds': + if pointSelect.type != "ijkBounds": pts, ind = pointSelect.getPoints(self.FFD.coef) else: pts, ind = pointSelect.getPoints_ijk(self) @@ -747,10 +785,10 @@ def addGeoDVLocal(self, dvName, lower=None, upper=None, scale=1.0, for vol in volList: volListTmp.append(vol) for vol in volList: - volListTmp.append(vol+self.FFD.nVol/2) + volListTmp.append(vol + self.FFD.nVol / 2) volList = volListTmp - volList = numpy.atleast_1d(volList).astype('int') + volList = numpy.atleast_1d(volList).astype("int") ind = [] for iVol in volList: ind.extend(self.FFD.topo.lIndex[iVol].flatten()) @@ -759,35 +797,43 @@ def addGeoDVLocal(self, dvName, lower=None, upper=None, scale=1.0, # Just take'em all ind = numpy.arange(len(self.FFD.coef)) - self.DV_listLocal[dvName] = geoDVLocal(dvName, lower, upper, - scale, axis, ind, self.masks, - config) + self.DV_listLocal[dvName] = geoDVLocal(dvName, lower, upper, scale, axis, ind, self.masks, config) return self.DV_listLocal[dvName].nVal - def addGeoDVSpanwiseLocal(self, dvName, spanIndex, axis='y', lower=None, upper=None, - scale=1.0, pointSelect=None, volList=None, config=None): + def addGeoDVSpanwiseLocal( + self, + dvName, + spanIndex, + axis="y", + lower=None, + upper=None, + scale=1.0, + pointSelect=None, + volList=None, + config=None, + ): """ Add one or more spanwise local design variables to the DVGeometry - object. Spanwise local variables are alternative form of local shape - variables used to apply equal DV changes in a chosen direction. + object. Spanwise local variables are alternative form of local shape + variables used to apply equal DV changes in a chosen direction. Some scenarios were this could be useful are: - - 1. 2D airfoil shape optimization. Because adflow works with 3D meshes, - 2D problems are represented my a mesh a single cell wide. Therefor, - to change the 2D representation of the airfoil both sides of the - mesh must be moved equally. This can be done with the addition of - linear constraints on a set of local shape variables, however this - approach requires more DVs than necessary (which complicates DV - sweeps) and the constaints are only enforced to a tolerance. Using - spanwise local design variables insures the airfoil is always - correctly represented in the 3D mesh using the correct amount of - design variables. - - 2. 3D wing optimization with constant airfoil shape. If the initial - wing geometry has a constant airfoil shape and constant chord, then - spanwise local dvs can be used to change the airfoil shape of the - wing while still keeping it constant along the span of the wing. + + 1. 2D airfoil shape optimization. Because adflow works with 3D meshes, + 2D problems are represented my a mesh a single cell wide. Therefor, + to change the 2D representation of the airfoil both sides of the + mesh must be moved equally. This can be done with the addition of + linear constraints on a set of local shape variables, however this + approach requires more DVs than necessary (which complicates DV + sweeps) and the constaints are only enforced to a tolerance. Using + spanwise local design variables insures the airfoil is always + correctly represented in the 3D mesh using the correct amount of + design variables. + + 2. 3D wing optimization with constant airfoil shape. If the initial + wing geometry has a constant airfoil shape and constant chord, then + spanwise local dvs can be used to change the airfoil shape of the + wing while still keeping it constant along the span of the wing. Parameters ---------- @@ -802,11 +848,11 @@ def addGeoDVSpanwiseLocal(self, dvName, spanIndex, axis='y', lower=None, upper=N The coordinate directions to move. Permissible values are `x`, `y` and `z`. If more than one direction is required, use multiple calls to addGeoDVLocal with different axis values. - + lower : float The lower bound for the variable(s). This will be applied to all shape variables - + upper : float The upper bound for the variable(s). This will be applied to all shape variables @@ -844,10 +890,10 @@ def addGeoDVSpanwiseLocal(self, dvName, spanIndex, axis='y', lower=None, upper=N >>> DVGeo.addGeoDVSpanwiseLocal("shape", 'k', lower=-0.5, upper=0.5, axis="z", scale=1.0) """ if type(config) == str: - config = [config] + config = [config] if pointSelect is not None: - if pointSelect.type != 'ijkBounds': + if pointSelect.type != "ijkBounds": pts, ind = pointSelect.getPoints(self.FFD.coef) else: pts, ind = pointSelect.getPoints_ijk(self) @@ -857,10 +903,10 @@ def addGeoDVSpanwiseLocal(self, dvName, spanIndex, axis='y', lower=None, upper=N for vol in volList: volListTmp.append(vol) for vol in volList: - volListTmp.append(vol+self.FFD.nVol/2) + volListTmp.append(vol + self.FFD.nVol / 2) volList = volListTmp - volList = numpy.atleast_1d(volList).astype('int') + volList = numpy.atleast_1d(volList).astype("int") ind = [] for iVol in volList: ind.extend(self.FFD.topo.lIndex[iVol].flatten()) @@ -870,19 +916,16 @@ def addGeoDVSpanwiseLocal(self, dvName, spanIndex, axis='y', lower=None, upper=N volList = numpy.arange(self.FFD.nVol) ind = numpy.arange(len(self.FFD.coef)) - secLink = numpy.zeros(self.FFD.coef.shape[0], dtype=int) secTransform = [numpy.eye(3)] if type(spanIndex) is str: - spanIndex = [spanIndex]*len(volList) + spanIndex = [spanIndex] * len(volList) elif type(spanIndex) is list: if len(spanIndex) != len(volList): - raise Error('If a list is given for spanIndex, the length must be' - ' equal to the length of volList.') - - ijk_2_idx = {'i':0, 'j':1, 'k':2} + raise Error("If a list is given for spanIndex, the length must be" " equal to the length of volList.") + ijk_2_idx = {"i": 0, "j": 1, "k": 2} volDVMap = [] for ivol in volList: @@ -901,9 +944,7 @@ def addGeoDVSpanwiseLocal(self, dvName, spanIndex, axis='y', lower=None, upper=N # make a map from dvs to the ind that are controlled by that dv. # (phrased another way) map from dv to all ind in the same span size position - dv_to_coef_ind = numpy.zeros((n_dvs,n_linked_coef), dtype='intc') - - + dv_to_coef_ind = numpy.zeros((n_dvs, n_linked_coef), dtype="intc") # slice lIndex to get the indices of the coeffs that are in the same # spanwise position @@ -912,11 +953,11 @@ def addGeoDVSpanwiseLocal(self, dvName, spanIndex, axis='y', lower=None, upper=N for j in range(dvs_shape[1]): # no need to use fancy axis manipulation, since it doesn't need # to be fast and if statements are expressive - if spanIndex[ivol] == 'i': + if spanIndex[ivol] == "i": coef_ind = lIndex[:, i, j] - elif spanIndex[ivol] == 'j': + elif spanIndex[ivol] == "j": coef_ind = lIndex[i, :, j] - elif spanIndex[ivol] == 'k' : + elif spanIndex[ivol] == "k": coef_ind = lIndex[i, j, :] dv_to_coef_ind[dv_idx] = coef_ind @@ -925,15 +966,26 @@ def addGeoDVSpanwiseLocal(self, dvName, spanIndex, axis='y', lower=None, upper=N # the for this volume is complete and can be added to the list of maps volDVMap.append(dv_to_coef_ind) - self.DV_listSpanwiseLocal[dvName] = geoDVSpanwiseLocal(dvName, lower, upper, - scale, axis, volDVMap, self.masks, - config) + self.DV_listSpanwiseLocal[dvName] = geoDVSpanwiseLocal( + dvName, lower, upper, scale, axis, volDVMap, self.masks, config + ) return self.DV_listSpanwiseLocal[dvName].nVal - def addGeoDVSectionLocal(self, dvName, secIndex, lower=None, upper=None, - scale=1.0, axis=1, pointSelect=None, volList=None, - orient0=None, orient2='svd', config=None): + def addGeoDVSectionLocal( + self, + dvName, + secIndex, + lower=None, + upper=None, + scale=1.0, + axis=1, + pointSelect=None, + volList=None, + orient0=None, + orient2="svd", + config=None, + ): """ Add one or more section local design variables to the DVGeometry object. Section local variables are used as an alternative to local @@ -1066,32 +1118,32 @@ class in geo_utils. Using pointSelect discards everything in volList. >>> DVGeo.addGeoDVSectionLocal('shape_vars', secIndex='k', lower=-1, upper=1, axis=1) """ if self.name is not None: - dvName = self.name + '_' + dvName + dvName = self.name + "_" + dvName if type(config) == str: config = [config] # Pick out control points if pointSelect is not None: - if pointSelect.type != 'ijkBounds': + if pointSelect.type != "ijkBounds": pts, ind = pointSelect.getPoints(self.FFD.coef) - volList = numpy.arange(self.FFD.nVol) # Select all volumes + volList = numpy.arange(self.FFD.nVol) # Select all volumes else: pts, ind = pointSelect.getPoints_ijk(self) - volList = pointSelect.ijkBounds.keys() # Select only volumes used by pointSelect + volList = pointSelect.ijkBounds.keys() # Select only volumes used by pointSelect elif volList is not None: if self.FFD.symmPlane is not None: volListTmp = [] for vol in volList: volListTmp.append(vol) for vol in volList: - volListTmp.append(vol+self.FFD.nVol/2) + volListTmp.append(vol + self.FFD.nVol / 2) volList = volListTmp - volList = numpy.atleast_1d(volList).astype('int') + volList = numpy.atleast_1d(volList).astype("int") ind = [] for iVol in volList: - ind.extend(self.FFD.topo.lIndex[iVol].flatten()) # Get all indices from this block + ind.extend(self.FFD.topo.lIndex[iVol].flatten()) # Get all indices from this block ind = geo_utils.unique(ind) else: # Just take'em all @@ -1102,46 +1154,44 @@ class in geo_utils. Using pointSelect discards everything in volList. secTransform = [numpy.eye(3)] if type(secIndex) is str: - secIndex = [secIndex]*len(volList) + secIndex = [secIndex] * len(volList) elif type(secIndex) is list: if len(secIndex) != len(volList): - raise Error('If a list is given for secIndex, the length must be' - ' equal to the length of volList.') + raise Error("If a list is given for secIndex, the length must be" " equal to the length of volList.") if orient0 is not None: # 'i', 'j', or 'k' if type(orient0) is str: - orient0 = [orient0]*len(volList) + orient0 = [orient0] * len(volList) # ['k', 'k', 'i', etc.] elif type(orient0) is list: if len(orient0) != len(volList): - raise Error('If a list is given for orient0, the length must' - ' be equal to the length of volList.') + raise Error("If a list is given for orient0, the length must" " be equal to the length of volList.") # numpy.array([1.0, 0.0, 0.0]) elif type(orient0) is numpy.ndarray: # vector if len(orient0.shape) == 1: - orient0 = numpy.reshape(orient0, (1,3)) + orient0 = numpy.reshape(orient0, (1, 3)) orient0 = numpy.repeat(orient0, len(volList), 0) elif orient0.shape[0] == 1: orient0 = numpy.repeat(orient0, len(volList), 0) elif orient0.shape[0] != len(volList): - raise Error('If an array is given for orient0, the row dimension' - ' must be equal to the length of volList.') + raise Error( + "If an array is given for orient0, the row dimension" " must be equal to the length of volList." + ) for i, iVol in enumerate(volList): - self.sectionFrame(secIndex[i], secTransform, secLink, iVol, - orient0[i], orient2=orient2) + self.sectionFrame(secIndex[i], secTransform, secLink, iVol, orient0[i], orient2=orient2) else: for i, iVol in enumerate(volList): self.sectionFrame(secIndex[i], secTransform, secLink, iVol, orient2=orient2) - self.DV_listSectionLocal[dvName] = geoDVSectionLocal(dvName, lower, upper, - scale, axis, ind, self.masks, - config, secTransform, secLink) + self.DV_listSectionLocal[dvName] = geoDVSectionLocal( + dvName, lower, upper, scale, axis, ind, self.masks, config, secTransform, secLink + ) return self.DV_listSectionLocal[dvName].nVal - def getSymmetricCoefList(self,volList=None, pointSelect=None, tol = 1e-8): + def getSymmetricCoefList(self, volList=None, pointSelect=None, tol=1e-8): """ Determine the pairs of coefs that need to be constrained for symmetry. @@ -1172,19 +1222,19 @@ def getSymmetricCoefList(self,volList=None, pointSelect=None, tol = 1e-8): """ if self.FFD.symmPlane is None: - #nothing to be done + # nothing to be done indSetA = [] indSetB = [] else: # get the direction of the symmetry plane - if self.FFD.symmPlane.lower() == 'x': + if self.FFD.symmPlane.lower() == "x": index = 0 - elif self.FFD.symmPlane.lower() == 'y': + elif self.FFD.symmPlane.lower() == "y": index = 1 - elif self.FFD.symmPlane.lower() == 'z': + elif self.FFD.symmPlane.lower() == "z": index = 2 - #get the points to be matched up + # get the points to be matched up if pointSelect is not None: pts, ind = pointSelect.getPoints(self.FFD.coef) elif volList is not None: @@ -1192,10 +1242,10 @@ def getSymmetricCoefList(self,volList=None, pointSelect=None, tol = 1e-8): for vol in volList: volListTmp.append(vol) for vol in volList: - volListTmp.append(vol+self.FFD.nVol/2) + volListTmp.append(vol + self.FFD.nVol / 2) volList = volListTmp - volList = numpy.atleast_1d(volList).astype('int') + volList = numpy.atleast_1d(volList).astype("int") ind = [] for iVol in volList: ind.extend(self.FFD.topo.lIndex[iVol].flatten()) @@ -1210,14 +1260,13 @@ def getSymmetricCoefList(self,volList=None, pointSelect=None, tol = 1e-8): # value of the symmetry direction, that way when we search we will get # back index pairs which is what we want. baseCoords = copy.copy(pts) - baseCoords[:,index] = abs(baseCoords[:,index]) + baseCoords[:, index] = abs(baseCoords[:, index]) - #now use the baseCoords to create a KD tree + # now use the baseCoords to create a KD tree try: from scipy.spatial import cKDTree except: - raise Error("scipy.spatial " - "must be available to use detect symmetry") + raise Error("scipy.spatial " "must be available to use detect symmetry") # Now make a KD-tree so we can use it to find the unique nodes tree = cKDTree(baseCoords) @@ -1227,17 +1276,17 @@ def getSymmetricCoefList(self,volList=None, pointSelect=None, tol = 1e-8): indSetA = [] indSetB = [] for pt in pts: - if pt[index]>tol: + if pt[index] > tol: # Now find any matching nodes within tol. there should be 2 and # only 2 if the mesh is symmtric - Ind =tree.query_ball_point(pt, tol)#should this be a separate tol - if not(len(Ind)==2): + Ind = tree.query_ball_point(pt, tol) # should this be a separate tol + if not (len(Ind) == 2): raise Error("more than 2 coefs found that match pt") else: indSetA.append(Ind[0]) indSetB.append(Ind[1]) - return indSetA,indSetB + return indSetA, indSetB def setDesignVars(self, dvDict): """ @@ -1250,7 +1299,7 @@ def setDesignVars(self, dvDict): Dictionary of design variables. The keys of the dictionary must correspond to the design variable names. Any additional keys in the dfvdictionary are simply ignored. - """ + """ # Coefficients must be complexifed from here on if complex if self.complex: @@ -1259,44 +1308,49 @@ def setDesignVars(self, dvDict): for key in dvDict: if key in self.DV_listGlobal: - vals_to_set = numpy.atleast_1d(dvDict[key]).astype('D') + vals_to_set = numpy.atleast_1d(dvDict[key]).astype("D") if len(vals_to_set) != self.DV_listGlobal[key].nVal: - raise Error("Incorrect number of design variables " - "for DV: %s.\nExpecting %d variables and " - "received %d variabes" % ( - key, self.DV_listGlobal[key].nVal, - len(vals_to_set))) + raise Error( + "Incorrect number of design variables " + "for DV: %s.\nExpecting %d variables and " + "received %d variabes" % (key, self.DV_listGlobal[key].nVal, len(vals_to_set)) + ) self.DV_listGlobal[key].value = vals_to_set if key in self.DV_listLocal: - vals_to_set = numpy.atleast_1d(dvDict[key]).astype('D') + vals_to_set = numpy.atleast_1d(dvDict[key]).astype("D") if len(vals_to_set) != self.DV_listLocal[key].nVal: - raise Error('Incorrect number of design variables \ + raise Error( + "Incorrect number of design variables \ for DV: %s.\nExpecting %d variables and received \ - %d variabes'%(key, self.DV_listLocal[key].nVal, - len(vals_to_set))) + %d variabes" + % (key, self.DV_listLocal[key].nVal, len(vals_to_set)) + ) self.DV_listLocal[key].value = vals_to_set if key in self.DV_listSectionLocal: - vals_to_set = numpy.atleast_1d(dvDict[key]).astype('D') + vals_to_set = numpy.atleast_1d(dvDict[key]).astype("D") if len(vals_to_set) != self.DV_listSectionLocal[key].nVal: - raise Error('Incorrect number of design variables \ + raise Error( + "Incorrect number of design variables \ for DV: %s.\nExpecting %d variables and received \ - %d variabes'%(key, self.DV_listSectionLocal[key].nVal, - len(vals_to_set))) + %d variabes" + % (key, self.DV_listSectionLocal[key].nVal, len(vals_to_set)) + ) self.DV_listSectionLocal[key].value = vals_to_set if key in self.DV_listSpanwiseLocal: - vals_to_set = numpy.atleast_1d(dvDict[key]).astype('D') + vals_to_set = numpy.atleast_1d(dvDict[key]).astype("D") if len(vals_to_set) != self.DV_listSpanwiseLocal[key].nVal: - raise Error('Incorrect number of design variables \ + raise Error( + "Incorrect number of design variables \ for DV: %s.\nExpecting %d variables and received \ - %d variabes'%(key, self.DV_listSpanwiseLocal[key].nVal, - len(vals_to_set))) + %d variabes" + % (key, self.DV_listSpanwiseLocal[key].nVal, len(vals_to_set)) + ) self.DV_listSpanwiseLocal[key].value = vals_to_set - # Jacobians are, in general, no longer up to date self.zeroJacobians(self.ptSetNames) @@ -1309,17 +1363,17 @@ def setDesignVars(self, dvDict): for child in self.children: child.setDesignVars(dvDict) - def zeroJacobians(self,ptSetNames): - ''' + def zeroJacobians(self, ptSetNames): + """ set stored jacobians to None for ptSetNames Parameters ---------- ptSetNames : list list of ptSetNames to zero the jacobians. - ''' + """ for name in ptSetNames: - self.JT[name] = None # J is no longer up to date + self.JT[name] = None # J is no longer up to date def getValues(self): """ @@ -1359,34 +1413,27 @@ def getValues(self): return dvDict def extractCoef(self, axisID): - """ Extract the coefficients for the selected reference + """Extract the coefficients for the selected reference axis. This should be used only inside design variable functions""" axisNumber = self._getAxisNumber(axisID) - C = numpy.zeros((len(self.refAxis.topo.lIndex[axisNumber]), 3), - self.coef.dtype) + C = numpy.zeros((len(self.refAxis.topo.lIndex[axisNumber]), 3), self.coef.dtype) - C[:, 0] = numpy.take(self.coef[:, 0], - self.refAxis.topo.lIndex[axisNumber]) - C[:, 1] = numpy.take(self.coef[:, 1], - self.refAxis.topo.lIndex[axisNumber]) - C[:, 2] = numpy.take(self.coef[:, 2], - self.refAxis.topo.lIndex[axisNumber]) + C[:, 0] = numpy.take(self.coef[:, 0], self.refAxis.topo.lIndex[axisNumber]) + C[:, 1] = numpy.take(self.coef[:, 1], self.refAxis.topo.lIndex[axisNumber]) + C[:, 2] = numpy.take(self.coef[:, 2], self.refAxis.topo.lIndex[axisNumber]) return C def restoreCoef(self, coef, axisID): - """ Restore the coefficients for the selected reference + """Restore the coefficients for the selected reference axis. This should be used inside design variable functions""" # Reset axisNumber = self._getAxisNumber(axisID) - numpy.put(self.coef[:, 0], - self.refAxis.topo.lIndex[axisNumber], coef[:, 0]) - numpy.put(self.coef[:, 1], - self.refAxis.topo.lIndex[axisNumber], coef[:, 1]) - numpy.put(self.coef[:, 2], - self.refAxis.topo.lIndex[axisNumber], coef[:, 2]) + numpy.put(self.coef[:, 0], self.refAxis.topo.lIndex[axisNumber], coef[:, 0]) + numpy.put(self.coef[:, 1], self.refAxis.topo.lIndex[axisNumber], coef[:, 1]) + numpy.put(self.coef[:, 2], self.refAxis.topo.lIndex[axisNumber], coef[:, 2]) def extractS(self, axisID): """Extract the parametric positions of the control @@ -1416,7 +1463,7 @@ def updateCalculations(self, new_pts, isComplex, config): # higher levels. # just use complex dtype here. we will convert to real in the end - self.links_x = self.links_x.astype('D') + self.links_x = self.links_x.astype("D") for ipt in range(self.nPtAttach): base_pt = self.refAxis.curves[self.curveIDs[ipt]](self.links_s[ipt]) @@ -1433,34 +1480,33 @@ def updateCalculations(self, new_pts, isComplex, config): for ipt in range(self.nPtAttach): base_pt = self.refAxis.curves[self.curveIDs[ipt]](self.links_s[ipt]) # Variables for rotType = 0 rotation + scaling - ang = self.axis[self.curveIDNames[ipt]]['rot0ang'] - ax_dir = self.axis[self.curveIDNames[ipt]]['rot0axis'] + ang = self.axis[self.curveIDNames[ipt]]["rot0ang"] + ax_dir = self.axis[self.curveIDNames[ipt]]["rot0axis"] scale = self.scale[self.curveIDNames[ipt]](self.links_s[ipt]) scale_x = self.scale_x[self.curveIDNames[ipt]](self.links_s[ipt]) scale_y = self.scale_y[self.curveIDNames[ipt]](self.links_s[ipt]) scale_z = self.scale_z[self.curveIDNames[ipt]](self.links_s[ipt]) - rotType = self.axis[self.curveIDNames[ipt]]['rotType'] + rotType = self.axis[self.curveIDNames[ipt]]["rotType"] if rotType == 0: - bp_ = numpy.copy(base_pt) # copy of original pointset - will not be rotated - if isinstance(ang,(float, int)): # rotation active only if a non-default value is provided - ang *= numpy.pi/180 # conv to [rad] + bp_ = numpy.copy(base_pt) # copy of original pointset - will not be rotated + if isinstance(ang, (float, int)): # rotation active only if a non-default value is provided + ang *= numpy.pi / 180 # conv to [rad] # Rotating the FFD according to inputs # The FFD points should now be aligned with the main system of reference base_pt = geo_utils.rotVbyW(bp_, ax_dir, ang) - deriv = self.refAxis.curves[ - self.curveIDs[ipt]].getDerivative(self.links_s[ipt]) - deriv /= geo_utils.euclideanNorm(deriv) # Normalize + deriv = self.refAxis.curves[self.curveIDs[ipt]].getDerivative(self.links_s[ipt]) + deriv /= geo_utils.euclideanNorm(deriv) # Normalize new_vec = -numpy.cross(deriv, self.links_n[ipt]) if isComplex: - new_pts[ipt] = bp_ + new_vec*scale # using "unrotated" bp_ vector + new_pts[ipt] = bp_ + new_vec * scale # using "unrotated" bp_ vector else: - new_pts[ipt] = numpy.real(bp_ + new_vec*scale) + new_pts[ipt] = numpy.real(bp_ + new_vec * scale) - if isinstance(ang,(float, int)): + if isinstance(ang, (float, int)): # Rotating to be aligned with main sys ref - nv_ = numpy.copy(new_vec) + nv_ = numpy.copy(new_vec) new_vec = geo_utils.rotVbyW(nv_, ax_dir, ang) # Apply scaling @@ -1468,12 +1514,14 @@ def updateCalculations(self, new_pts, isComplex, config): new_vec[1] *= scale_y new_vec[2] *= scale_z - if isinstance(ang,(float, int)): + if isinstance(ang, (float, int)): # Rotating back the scaled pointset to its original position - nv_rot = numpy.copy(new_vec) # nv_rot is scaled and rotated - new_vec = geo_utils.rotVbyW(nv_rot , ax_dir, -ang) + nv_rot = numpy.copy(new_vec) # nv_rot is scaled and rotated + new_vec = geo_utils.rotVbyW(nv_rot, ax_dir, -ang) - new_vec = geo_utils.rotVbyW(new_vec, deriv, self.rot_theta[self.curveIDNames[ipt]](self.links_s[ipt])*numpy.pi/180) + new_vec = geo_utils.rotVbyW( + new_vec, deriv, self.rot_theta[self.curveIDNames[ipt]](self.links_s[ipt]) * numpy.pi / 180 + ) if isComplex: new_pts[ipt] = bp_ + new_vec @@ -1481,12 +1529,9 @@ def updateCalculations(self, new_pts, isComplex, config): new_pts[ipt] = numpy.real(bp_ + new_vec) else: - rotX = geo_utils.rotxM(self.rot_x[ - self.curveIDNames[ipt]](self.links_s[ipt])) - rotY = geo_utils.rotyM(self.rot_y[ - self.curveIDNames[ipt]](self.links_s[ipt])) - rotZ = geo_utils.rotzM(self.rot_z[ - self.curveIDNames[ipt]](self.links_s[ipt])) + rotX = geo_utils.rotxM(self.rot_x[self.curveIDNames[ipt]](self.links_s[ipt])) + rotY = geo_utils.rotyM(self.rot_y[self.curveIDNames[ipt]](self.links_s[ipt])) + rotZ = geo_utils.rotzM(self.rot_z[self.curveIDNames[ipt]](self.links_s[ipt])) D = self.links_x[ipt] @@ -1503,28 +1548,29 @@ def updateCalculations(self, new_pts, isComplex, config): D = numpy.dot(rotM, D) if rotType == 7: # only apply the theta rotations in certain cases - deriv = self.refAxis.curves[ - self.curveIDs[ipt]].getDerivative(self.links_s[ipt]) - deriv /= geo_utils.euclideanNorm(deriv) # Normalize - D = geo_utils.rotVbyW(D, deriv, numpy.pi/180*self.rot_theta[ - self.curveIDNames[ipt]](self.links_s[ipt])) + deriv = self.refAxis.curves[self.curveIDs[ipt]].getDerivative(self.links_s[ipt]) + deriv /= geo_utils.euclideanNorm(deriv) # Normalize + D = geo_utils.rotVbyW( + D, deriv, numpy.pi / 180 * self.rot_theta[self.curveIDNames[ipt]](self.links_s[ipt]) + ) elif rotType == 8: - varname = self.axis[self.curveIDNames[ipt]]['rotAxisVar'] + varname = self.axis[self.curveIDNames[ipt]]["rotAxisVar"] slVar = self.DV_listSectionLocal[varname] attachedPoint = self.ptAttachInd[ipt] - W = slVar.sectionTransform[slVar.sectionLink[attachedPoint]][:,2] - D = geo_utils.rotVbyW(D, W, numpy.pi/180*self.rot_theta[ - self.curveIDNames[ipt]](self.links_s[ipt])) + W = slVar.sectionTransform[slVar.sectionLink[attachedPoint]][:, 2] + D = geo_utils.rotVbyW( + D, W, numpy.pi / 180 * self.rot_theta[self.curveIDNames[ipt]](self.links_s[ipt]) + ) D[0] *= scale_x D[1] *= scale_y D[2] *= scale_z if isComplex: - new_pts[ipt] = base_pt + D*scale + new_pts[ipt] = base_pt + D * scale else: - new_pts[ipt] = numpy.real(base_pt + D*scale) + new_pts[ipt] = numpy.real(base_pt + D * scale) def update(self, ptSetName, childDelta=True, config=None): """ @@ -1547,7 +1593,7 @@ def update(self, ptSetName, childDelta=True, config=None): configurations. The default value of None implies that the design variable appies to *ALL* configurations. - """ + """ self.curPtSet = ptSetName # We've postponed things as long as we can...do the finialization. self._finalize() @@ -1568,22 +1614,22 @@ def update(self, ptSetName, childDelta=True, config=None): if self.complex: # Now we have to propagate the complex part through Xstart - tempCoef = self.FFD.coef.copy().astype('D') - Xstart = Xstart.astype('D') + tempCoef = self.FFD.coef.copy().astype("D") + Xstart = Xstart.astype("D") imag_part = numpy.imag(tempCoef) imag_j = 1j dPtdCoef = self.FFD.embededVolumes[ptSetName].dPtdCoef if dPtdCoef is not None: for ii in range(3): - Xstart[:, ii] += imag_j*dPtdCoef.dot(imag_part[:, ii]) + Xstart[:, ii] += imag_j * dPtdCoef.dot(imag_part[:, ii]) # Step 1: Call all the design variables IFF we have ref axis: if len(self.axis) > 0: if self.complex: - new_pts = numpy.zeros((self.nPtAttach, 3), 'D') + new_pts = numpy.zeros((self.nPtAttach, 3), "D") else: - new_pts = numpy.zeros((self.nPtAttach, 3), 'd') + new_pts = numpy.zeros((self.nPtAttach, 3), "d") # Apply the global design variables self.updateCalculations(new_pts, isComplex=self.complex, config=config) @@ -1617,7 +1663,7 @@ def update(self, ptSetName, childDelta=True, config=None): # Above, we only took the real part of the coef because # _updateVolumeCoef gets rid of it anyway. Here, we need to include # the complex part because we want to propagate it through - tempCoef = self.FFD.coef.copy().astype('D') + tempCoef = self.FFD.coef.copy().astype("D") if len(self.axis) > 0: numpy.put(tempCoef[:, 0], self.ptAttachInd, new_pts[:, 0]) numpy.put(tempCoef[:, 1], self.ptAttachInd, new_pts[:, 1]) @@ -1631,14 +1677,14 @@ def update(self, ptSetName, childDelta=True, config=None): for key in self.DV_listLocal: self.DV_listLocal[key].updateComplex(tempCoef, config) - Xfinal = Xfinal.astype('D') + Xfinal = Xfinal.astype("D") imag_part = numpy.imag(tempCoef) imag_j = 1j dPtdCoef = self.FFD.embededVolumes[ptSetName].dPtdCoef if dPtdCoef is not None: for ii in range(3): - Xfinal[:, ii] += imag_j*dPtdCoef.dot(imag_part[:, ii]) + Xfinal[:, ii] += imag_j * dPtdCoef.dot(imag_part[:, ii]) # Now loop over the children set the FFD and refAxis control # points as evaluated from the parent @@ -1651,18 +1697,18 @@ def update(self, ptSetName, childDelta=True, config=None): # need to propagate the sensitivity to the children Xfinal here to do this # correctly child._complexifyCoef() - child.FFD.coef = child.FFD.coef.astype('D') + child.FFD.coef = child.FFD.coef.astype("D") - dXrefdCoef = self.FFD.embededVolumes['child%d_axis'%(iChild)].dPtdCoef - dCcdCoef = self.FFD.embededVolumes['child%d_coef'%(iChild)].dPtdCoef + dXrefdCoef = self.FFD.embededVolumes["child%d_axis" % (iChild)].dPtdCoef + dCcdCoef = self.FFD.embededVolumes["child%d_coef" % (iChild)].dPtdCoef if dXrefdCoef is not None: for ii in range(3): - child.coef[:, ii] += imag_j*dXrefdCoef.dot(imag_part[:, ii]) + child.coef[:, ii] += imag_j * dXrefdCoef.dot(imag_part[:, ii]) if dCcdCoef is not None: for ii in range(3): - child.FFD.coef[:, ii] += imag_j*dCcdCoef.dot(imag_part[:, ii]) + child.FFD.coef[:, ii] += imag_j * dCcdCoef.dot(imag_part[:, ii]) child.refAxis.coef = child.coef.copy() child.refAxis._updateCurveCoef() @@ -1686,8 +1732,8 @@ def applyToChild(self, iChild): child = self.children[iChild] # Set FFD points and reference axis points from parent - child.FFD.coef = self.FFD.getAttachedPoints('child%d_coef'%(iChild)) - child.coef = self.FFD.getAttachedPoints('child%d_axis'%(iChild)) + child.FFD.coef = self.FFD.getAttachedPoints("child%d_coef" % (iChild)) + child.coef = self.FFD.getAttachedPoints("child%d_axis" % (iChild)) # Update the reference axes on the child child.refAxis.coef = child.coef.copy() @@ -1743,38 +1789,36 @@ def convertSensitivityToDict(self, dIdx, out1D=False): for key in self.DV_listGlobal: dv = self.DV_listGlobal[key] if out1D: - dIdxDict[dv.name] = numpy.ravel(dIdx[:, i:i+dv.nVal]) + dIdxDict[dv.name] = numpy.ravel(dIdx[:, i : i + dv.nVal]) else: - dIdxDict[dv.name] = dIdx[:, i:i+dv.nVal] + dIdxDict[dv.name] = dIdx[:, i : i + dv.nVal] i += dv.nVal - i = DVCountSpanLoc for key in self.DV_listSpanwiseLocal: dv = self.DV_listSpanwiseLocal[key] if out1D: - dIdxDict[dv.name] = numpy.ravel(dIdx[:, i:i+dv.nVal]) + dIdxDict[dv.name] = numpy.ravel(dIdx[:, i : i + dv.nVal]) else: - dIdxDict[dv.name] = dIdx[:, i:i+dv.nVal] + dIdxDict[dv.name] = dIdx[:, i : i + dv.nVal] i += dv.nVal - i = DVCountSecLoc for key in self.DV_listSectionLocal: dv = self.DV_listSectionLocal[key] if out1D: - dIdxDict[dv.name] = numpy.ravel(dIdx[:, i:i+dv.nVal]) + dIdxDict[dv.name] = numpy.ravel(dIdx[:, i : i + dv.nVal]) else: - dIdxDict[dv.name] = dIdx[:, i:i+dv.nVal] + dIdxDict[dv.name] = dIdx[:, i : i + dv.nVal] i += dv.nVal i = DVCountLocal for key in self.DV_listLocal: dv = self.DV_listLocal[key] if out1D: - dIdxDict[dv.name] = numpy.ravel(dIdx[:, i:i+dv.nVal]) + dIdxDict[dv.name] = numpy.ravel(dIdx[:, i : i + dv.nVal]) else: - dIdxDict[dv.name] = dIdx[:, i:i+dv.nVal] + dIdxDict[dv.name] = dIdx[:, i : i + dv.nVal] i += dv.nVal @@ -1784,9 +1828,9 @@ def convertSensitivityToDict(self, dIdx, out1D=False): # update the total sensitivities with the derivatives from the child for key in childdIdx: if key in dIdxDict.keys(): - dIdxDict[key]+=childdIdx[key] + dIdxDict[key] += childdIdx[key] else: - dIdxDict[key]=childdIdx[key] + dIdxDict[key] = childdIdx[key] return dIdxDict @@ -1813,32 +1857,32 @@ def convertDictToSensitivity(self, dIdxDict): i = DVCountGlobal for key in self.DV_listGlobal: dv = self.DV_listGlobal[key] - dIdx[i:i+dv.nVal] = dIdxDict[dv.name] + dIdx[i : i + dv.nVal] = dIdxDict[dv.name] i += dv.nVal i = DVCountLocal for key in self.DV_listLocal: dv = self.DV_listLocal[key] - dIdx[i:i+dv.nVal] = dIdxDict[dv.name] + dIdx[i : i + dv.nVal] = dIdxDict[dv.name] i += dv.nVal i = DVCountSecLoc for key in self.DV_listSectionLocal: dv = self.DV_listSectionLocal[key] - dIdx[i:i+dv.nVal] = dIdxDict[dv.name] + dIdx[i : i + dv.nVal] = dIdxDict[dv.name] i += dv.nVal i = DVCountSpanLoc for key in self.DV_listSpanLocal: dv = self.DV_listSpanLocal[key] - dIdx[i:i+dv.nVal] = dIdxDict[dv.name] + dIdx[i : i + dv.nVal] = dIdxDict[dv.name] i += dv.nVal - #Note: not sure if this works with (multiple) sibling child FFDs + # Note: not sure if this works with (multiple) sibling child FFDs for iChild in range(len(self.children)): childdIdx = self.children[iChild].convertDictToSensitivity(dIdxDict) # update the total sensitivities with the derivatives from the child - dIdx+=childdIdx + dIdx += childdIdx return dIdx def getVarNames(self): @@ -1910,16 +1954,16 @@ def totalSensitivity(self, dIdpt, ptSetName, comm=None, config=None): N = dIdpt.shape[0] # generate the total Jacobian self.JT - self.computeTotalJacobian(ptSetName,config=config) + self.computeTotalJacobian(ptSetName, config=config) # now that we have self.JT compute the Mat-Mat multiplication nDV = self._getNDV() - dIdx_local = numpy.zeros((N, nDV), 'd') + dIdx_local = numpy.zeros((N, nDV), "d") for i in range(N): if self.JT[ptSetName] is not None: - dIdx_local[i,:] = self.JT[ptSetName].dot(dIdpt[i,:,:].flatten()) + dIdx_local[i, :] = self.JT[ptSetName].dot(dIdpt[i, :, :].flatten()) - if comm: # If we have a comm, globaly reduce with sum + if comm: # If we have a comm, globaly reduce with sum dIdx = comm.allreduce(dIdx_local, op=MPI.SUM) else: dIdx = dIdx_local @@ -1929,8 +1973,7 @@ def totalSensitivity(self, dIdpt, ptSetName, comm=None, config=None): return dIdx - def totalSensitivityProd(self, vec, ptSetName, comm=None, child=False, - nDVStore=0, config=None): + def totalSensitivityProd(self, vec, ptSetName, comm=None, child=False, nDVStore=0, config=None): """ This function computes sensitivty information. @@ -1967,10 +2010,10 @@ def totalSensitivityProd(self, vec, ptSetName, comm=None, child=False, internally and should not be changed by the user. """ - self.computeTotalJacobian(ptSetName,config=config) + self.computeTotalJacobian(ptSetName, config=config) names = self.getVarNames() - newvec = numpy.zeros(self.getNDV(),self.dtype) + newvec = numpy.zeros(self.getNDV(), self.dtype) i = 0 for key in names: if key in self.DV_listGlobal: @@ -1983,7 +2026,7 @@ def totalSensitivityProd(self, vec, ptSetName, comm=None, child=False, dv = self.DV_listLocal[key] if key in vec: - newvec[i:i+dv.nVal] = vec[key] + newvec[i : i + dv.nVal] = vec[key] i += dv.nVal @@ -1992,14 +2035,13 @@ def totalSensitivityProd(self, vec, ptSetName, comm=None, child=False, xsdot = numpy.zeros((0, 3)) else: xsdot = self.JT[ptSetName].T.dot(newvec) - xsdot.reshape(len(xsdot)//3, 3) + xsdot.reshape(len(xsdot) // 3, 3) # Maybe this should be: - #xsdot = xsdot.reshape(len(xsdot)//3, 3) + # xsdot = xsdot.reshape(len(xsdot)//3, 3) return xsdot - def totalSensitivityTransProd(self, vec, ptSetName, comm=None, child=False, - nDVStore=0, config=None): + def totalSensitivityTransProd(self, vec, ptSetName, comm=None, child=False, nDVStore=0, config=None): """ This function computes sensitivty information. @@ -2043,7 +2085,7 @@ def totalSensitivityTransProd(self, vec, ptSetName, comm=None, child=False, internally and should not be changed by the user. """ - self.computeTotalJacobian(ptSetName,config=config) + self.computeTotalJacobian(ptSetName, config=config) # perform the product if self.JT[ptSetName] == None: @@ -2064,12 +2106,12 @@ def totalSensitivityTransProd(self, vec, ptSetName, comm=None, child=False, dv = self.DV_listSectionLocal[key] else: dv = self.DV_listLocal[key] - xsdict[key] = xsdot[i:i+dv.nVal] + xsdict[key] = xsdot[i : i + dv.nVal] i += dv.nVal return xsdict - def computeDVJacobian(self,config=None): + def computeDVJacobian(self, config=None): """ return J_temp for a given config """ @@ -2096,43 +2138,43 @@ def computeDVJacobian(self,config=None): # add them together if J_attach is not None: - J_temp = sparse.lil_matrix(J_attach) + J_temp = sparse.lil_matrix(J_attach) if J_spanwiselocal is not None: if J_temp is None: - J_temp = sparse.lil_matrix(J_spanwiselocal) + J_temp = sparse.lil_matrix(J_spanwiselocal) else: J_temp += J_spanwiselocal if J_sectionlocal is not None: if J_temp is None: - J_temp = sparse.lil_matrix(J_sectionlocal) + J_temp = sparse.lil_matrix(J_sectionlocal) else: J_temp += J_sectionlocal if J_local is not None: if J_temp is None: - J_temp = sparse.lil_matrix(J_local) + J_temp = sparse.lil_matrix(J_local) else: J_temp += J_local if J_casc is not None: if J_temp is None: - J_temp = sparse.lil_matrix(J_casc) + J_temp = sparse.lil_matrix(J_casc) else: J_temp += J_casc return J_temp def computeTotalJacobian(self, ptSetName, config=None): - """ Return the total point jacobian in CSR format since we + """Return the total point jacobian in CSR format since we need this for TACS""" # Finalize the object, if not done yet self._finalize() self.curPtSet = ptSetName - if not(self.JT[ptSetName] is None): + if not (self.JT[ptSetName] is None): return # compute the derivatives of the coeficients of this level wrt all of the design @@ -2152,27 +2194,26 @@ def computeTotalJacobian(self, ptSetName, config=None): col = dPtdCoef.col data = dPtdCoef.data - new_row = numpy.zeros(3*len(row), 'int') - new_col = numpy.zeros(3*len(row), 'int') - new_data = numpy.zeros(3*len(row)) + new_row = numpy.zeros(3 * len(row), "int") + new_col = numpy.zeros(3 * len(row), "int") + new_data = numpy.zeros(3 * len(row)) # Loop over each entry and expand: for j in range(3): new_data[j::3] = data - new_row[j::3] = row*3 + j - new_col[j::3] = col*3 + j + new_row[j::3] = row * 3 + j + new_col[j::3] = col * 3 + j # Size of New Matrix: - Nrow = dPtdCoef.shape[0]*3 - Ncol = dPtdCoef.shape[1]*3 + Nrow = dPtdCoef.shape[0] * 3 + Ncol = dPtdCoef.shape[1] * 3 # Create new matrix in coo-dinate format and convert to csr - new_dPtdCoef = sparse.coo_matrix( - (new_data, (new_row, new_col)), shape=(Nrow, Ncol)).tocsr() + new_dPtdCoef = sparse.coo_matrix((new_data, (new_row, new_col)), shape=(Nrow, Ncol)).tocsr() # Do Sparse Mat-Mat multiplication and resort indices if J_temp is not None: - self.JT[ptSetName] = (J_temp.T*new_dPtdCoef.T).tocsr() + self.JT[ptSetName] = (J_temp.T * new_dPtdCoef.T).tocsr() self.JT[ptSetName].sort_indices() # Add in child portion @@ -2180,7 +2221,7 @@ def computeTotalJacobian(self, ptSetName, config=None): # Reset control points on child for child link derivatives self.applyToChild(iChild) - self.children[iChild].computeTotalJacobian(ptSetName,config=config) + self.children[iChild].computeTotalJacobian(ptSetName, config=config) if self.JT[ptSetName] is not None: self.JT[ptSetName] = self.JT[ptSetName] + self.children[iChild].JT[ptSetName] @@ -2189,15 +2230,14 @@ def computeTotalJacobian(self, ptSetName, config=None): else: self.JT[ptSetName] = None - def computeTotalJacobianCS(self, ptSetName, config=None): - """ Return the total point jacobian in CSR format since we + """Return the total point jacobian in CSR format since we need this for TACS""" self._finalize() self.curPtSet = ptSetName - if not(self.JT[ptSetName] is None): + if not (self.JT[ptSetName] is None): return if self.isChild: @@ -2213,7 +2253,7 @@ def computeTotalJacobianCS(self, ptSetName, config=None): h = 1e-40j - self.JT[ptSetName] = numpy.zeros([self.nDV_T,self.nPts[ptSetName]]) + self.JT[ptSetName] = numpy.zeros([self.nDV_T, self.nPts[ptSetName]]) self._complexifyCoef() for key in self.DV_listGlobal: for j in range(self.DV_listGlobal[key].nVal): @@ -2227,9 +2267,9 @@ def computeTotalJacobianCS(self, ptSetName, config=None): self.DV_listGlobal[key].value[j] += h - deriv = numpy.imag(self._update_deriv_cs(ptSetName,config=config).flatten())/numpy.imag(h) + deriv = numpy.imag(self._update_deriv_cs(ptSetName, config=config).flatten()) / numpy.imag(h) - self.JT[ptSetName][DVGlobalCount,:]=deriv + self.JT[ptSetName][DVGlobalCount, :] = deriv DVGlobalCount += 1 self.DV_listGlobal[key].value[j] = refVal @@ -2246,9 +2286,9 @@ def computeTotalJacobianCS(self, ptSetName, config=None): refVal = self.DV_listSpanwiseLocal[key].value[j] self.DV_listSpanwiseLocal[key].value[j] += h - deriv = numpy.imag(self._update_deriv_cs(ptSetName,config=config).flatten())/numpy.imag(h) + deriv = numpy.imag(self._update_deriv_cs(ptSetName, config=config).flatten()) / numpy.imag(h) - self.JT[ptSetName][DVSpanLocCount,:] = deriv + self.JT[ptSetName][DVSpanLocCount, :] = deriv DVSpanLocCount += 1 self.DV_listSpanwiseLocal[key].value[j] = refVal @@ -2264,9 +2304,9 @@ def computeTotalJacobianCS(self, ptSetName, config=None): refVal = self.DV_listSectionLocal[key].value[j] self.DV_listSectionLocal[key].value[j] += h - deriv = numpy.imag(self._update_deriv_cs(ptSetName,config=config).flatten())/numpy.imag(h) + deriv = numpy.imag(self._update_deriv_cs(ptSetName, config=config).flatten()) / numpy.imag(h) - self.JT[ptSetName][DVSecLocCount,:] = deriv + self.JT[ptSetName][DVSecLocCount, :] = deriv DVSecLocCount += 1 self.DV_listSectionLocal[key].value[j] = refVal @@ -2282,14 +2322,13 @@ def computeTotalJacobianCS(self, ptSetName, config=None): refVal = self.DV_listLocal[key].value[j] self.DV_listLocal[key].value[j] += h - deriv = numpy.imag(self._update_deriv_cs(ptSetName,config=config).flatten())/numpy.imag(h) + deriv = numpy.imag(self._update_deriv_cs(ptSetName, config=config).flatten()) / numpy.imag(h) - self.JT[ptSetName][DVLocalCount,:] = deriv + self.JT[ptSetName][DVLocalCount, :] = deriv DVLocalCount += 1 self.DV_listLocal[key].value[j] = refVal - for iChild in range(len(self.children)): child = self.children[iChild] child._finalize() @@ -2301,13 +2340,21 @@ def computeTotalJacobianCS(self, ptSetName, config=None): self.applyToChild(iChild) # Now get jacobian from child and add to parent jacobian - child.computeTotalJacobianCS(ptSetName,config=config) + child.computeTotalJacobianCS(ptSetName, config=config) self.JT[ptSetName] = self.JT[ptSetName] + child.JT[ptSetName] return - def addVariablesPyOpt(self, optProb, globalVars=True, localVars=True, - sectionlocalVars=True, spanwiselocalVars=True, ignoreVars=None, freezeVars=None): + def addVariablesPyOpt( + self, + optProb, + globalVars=True, + localVars=True, + sectionlocalVars=True, + spanwiselocalVars=True, + ignoreVars=None, + freezeVars=None, + ): """ Add the current set of variables to the optProb object. @@ -2321,10 +2368,10 @@ def addVariablesPyOpt(self, optProb, globalVars=True, localVars=True, localVars : bool Flag specifying whether local variables are to be added - + sectionlocalVars : bool Flag specifying whether section local variables are to be added - + spanwiselocalVars : bool Flag specifying whether spanwiselocal variables are to be added @@ -2344,31 +2391,42 @@ def addVariablesPyOpt(self, optProb, globalVars=True, localVars=True, freezeVars = set() # Add design variables from the master: - varLists = OrderedDict([('globalVars',self.DV_listGlobal), - ('localVars',self.DV_listLocal), - ('sectionlocalVars',self.DV_listSectionLocal), - ('spanwiselocalVars',self.DV_listSpanwiseLocal)]) + varLists = OrderedDict( + [ + ("globalVars", self.DV_listGlobal), + ("localVars", self.DV_listLocal), + ("sectionlocalVars", self.DV_listSectionLocal), + ("spanwiselocalVars", self.DV_listSpanwiseLocal), + ] + ) for lst in varLists: - if lst == 'globalVars' and globalVars\ - or lst=='localVars' and localVars \ - or lst=='sectionlocalVars' and sectionlocalVars\ - or lst=='spanwiselocalVars' and spanwiselocalVars: + if ( + lst == "globalVars" + and globalVars + or lst == "localVars" + and localVars + or lst == "sectionlocalVars" + and sectionlocalVars + or lst == "spanwiselocalVars" + and spanwiselocalVars + ): for key in varLists[lst]: if key not in ignoreVars: dv = varLists[lst][key] if key not in freezeVars: - optProb.addVarGroup(dv.name, dv.nVal, 'c', value=dv.value, - lower=dv.lower, upper=dv.upper, - scale=dv.scale) + optProb.addVarGroup( + dv.name, dv.nVal, "c", value=dv.value, lower=dv.lower, upper=dv.upper, scale=dv.scale + ) else: - optProb.addVarGroup(dv.name, dv.nVal, 'c', value=dv.value, - lower=dv.value, upper=dv.value, - scale=dv.scale) + optProb.addVarGroup( + dv.name, dv.nVal, "c", value=dv.value, lower=dv.value, upper=dv.value, scale=dv.scale + ) # Add variables from the children for child in self.children: - child.addVariablesPyOpt(optProb, globalVars, localVars, sectionlocalVars, spanwiselocalVars, - ignoreVars, freezeVars) + child.addVariablesPyOpt( + optProb, globalVars, localVars, sectionlocalVars, spanwiselocalVars, ignoreVars, freezeVars + ) def writeTecplot(self, fileName): """Write the (deformed) current state of the FFD's to a tecplot file, @@ -2381,7 +2439,7 @@ def writeTecplot(self, fileName): """ # Name here doesn't matter, just take the first one - if len(self.points)>0: + if len(self.points) > 0: keyToUpdate = list(self.points.keys())[0] self.update(keyToUpdate, childDelta=False) @@ -2392,7 +2450,7 @@ def writeTecplot(self, fileName): vol_counter += self._writeVols(f, vol_counter) pySpline.closeTecplot(f) - if len(self.points)>0: + if len(self.points) > 0: self.update(keyToUpdate, childDelta=True) def writeRefAxes(self, fileName): @@ -2408,12 +2466,12 @@ def writeRefAxes(self, fileName): # Name here doesnt matter, just take the first one self.update(self.points.keys()[0], childDelta=False) - gFileName = fileName+'_parent.dat' - if not len(self.axis)==0: + gFileName = fileName + "_parent.dat" + if not len(self.axis) == 0: self.refAxis.writeTecplot(gFileName, orig=True, curves=True, coef=True) # Write children axes: for iChild in range(len(self.children)): - cFileName = fileName+'_child{:03d}.dat'.format(iChild) + cFileName = fileName + "_child{:03d}.dat".format(iChild) self.children[iChild].refAxis.writeTecplot(cFileName, orig=True, curves=True, coef=True) def writeLinks(self, fileName): @@ -2426,20 +2484,20 @@ def writeLinks(self, fileName): """ self._finalize() f = pySpline.openTecplot(fileName, 3) - f.write('ZONE NODES=%d ELEMENTS=%d ZONETYPE=FELINESEG\n'%(self.nPtAttach*2, self.nPtAttach)) - f.write('DATAPACKING=POINT\n') + f.write("ZONE NODES=%d ELEMENTS=%d ZONETYPE=FELINESEG\n" % (self.nPtAttach * 2, self.nPtAttach)) + f.write("DATAPACKING=POINT\n") for ipt in range(self.nPtAttach): pt1 = self.refAxis.curves[self.curveIDs[ipt]](self.links_s[ipt]) pt2 = self.links_x[ipt] + pt1 - f.write('%.12g %.12g %.12g\n'%(pt1[0], pt1[1], pt1[2])) - f.write('%.12g %.12g %.12g\n'%(pt2[0], pt2[1], pt2[2])) + f.write("%.12g %.12g %.12g\n" % (pt1[0], pt1[1], pt1[2])) + f.write("%.12g %.12g %.12g\n" % (pt2[0], pt2[1], pt2[2])) for i in range(self.nPtAttach): - f.write('%d %d\n'%(2*i+1, 2*i+2)) + f.write("%d %d\n" % (2 * i + 1, 2 * i + 2)) pySpline.closeTecplot(f) - def writePointSet(self,name,fileName): + def writePointSet(self, name, fileName): """ Write a given point set to a tecplot file @@ -2456,7 +2514,7 @@ def writePointSet(self,name,fileName): raise Error('Must call "writePointSet" from parent DVGeo.') else: coords = self.update(name, childDelta=True) - fileName = fileName+'_%s.dat'%name + fileName = fileName + "_%s.dat" % name f = pySpline.openTecplot(fileName, 3) pySpline.writeTecplot1D(f, name, coords) pySpline.closeTecplot(f) @@ -2473,11 +2531,11 @@ def writePlot3d(self, fileName): fileName : str Filename of the plot3D file to write. Should have a .fmt file extension. - """ + """ self.FFD.writePlot3dCoef(fileName) def updatePyGeo(self, geo, outputType, fileName, nRefU=0, nRefV=0): - """ Deform a pyGeo object and write to a file of specified type + """Deform a pyGeo object and write to a file of specified type given the (deformed) current state of the FFD object. Parameters @@ -2498,7 +2556,7 @@ def updatePyGeo(self, geo, outputType, fileName, nRefU=0, nRefV=0): If scalar, it is applied across each surface. If list, the length must match the number of surfaces in the object and corresponding entries are matched with surfaces """ - # Function to check if value matches a knot point + # Function to check if value matches a knot point # (set to 1e-12 to match pySpline mult. tolerance) def check_mult(val, knots): for iKnot in range(len(knots)): @@ -2513,7 +2571,7 @@ def check_mult(val, knots): for iSurf in range(geo.nSurf): for iX in Refine_U: if not check_mult(iX, geo.surfs[iSurf].tu): - geo.surfs[iSurf].insertKnot('u', iX, 1) + geo.surfs[iSurf].insertKnot("u", iX, 1) elif isinstance(nRefU, list): if len(nRefU) != geo.nSurf: raise RuntimeError("Length of nRefU does not match number of surfaces in object") @@ -2522,7 +2580,7 @@ def check_mult(val, knots): Refine_U = numpy.linspace(0.0, 1.0, nRefU[iSurf] + 2) for iX in Refine_U: if not check_mult(iX, geo.surfs[iSurf].tu): - geo.surfs[iSurf].insertKnot('u', iX, 1) + geo.surfs[iSurf].insertKnot("u", iX, 1) else: raise TypeError("nRefU type not recognized, must be: integer or list of integers") @@ -2533,7 +2591,7 @@ def check_mult(val, knots): for iSurf in range(geo.nSurf): for iY in Refine_V: if not check_mult(iY, geo.surfs[iSurf].tv): - geo.surfs[iSurf].insertKnot('v', iY, 1) + geo.surfs[iSurf].insertKnot("v", iY, 1) elif isinstance(nRefV, list): if len(nRefU) != geo.nSurf: raise RuntimeError("Length of nRefV does not match number of surfaces in object") @@ -2542,18 +2600,18 @@ def check_mult(val, knots): Refine_V = numpy.linspace(0.0, 1.0, nRefV[iSurf] + 2) for iY in Refine_V: if not check_mult(iY, geo.surfs[iSurf].tv): - geo.surfs[iSurf].insertKnot('v', iY, 1) + geo.surfs[iSurf].insertKnot("v", iY, 1) else: raise TypeError("nRefV type not recognized, must be: integer or list of integers") # Update Coefficients for iSurf in range(geo.nSurf): # Add Point Sets - npt = geo.surfs[iSurf].nCtlu*geo.surfs[iSurf].nCtlv - self.addPointSet(geo.surfs[iSurf].coef.reshape((npt, 3)), 'coef%d'%iSurf) + npt = geo.surfs[iSurf].nCtlu * geo.surfs[iSurf].nCtlv + self.addPointSet(geo.surfs[iSurf].coef.reshape((npt, 3)), "coef%d" % iSurf) # Update and Overwrite Old Values - geo.surfs[iSurf].coef = self.update('coef%d'%iSurf).reshape(geo.surfs[iSurf].coef.shape) + geo.surfs[iSurf].coef = self.update("coef%d" % iSurf).reshape(geo.surfs[iSurf].coef.shape) # Write File if outputType == "iges": @@ -2564,7 +2622,7 @@ def check_mult(val, knots): raise ValueError("Type {} not recognized. Must be either 'iges' or 'tecplot'".format(outputType)) def getLocalIndex(self, iVol): - """ Return the local index mapping that points to the global + """Return the local index mapping that points to the global coefficient list for a given volume""" return self.FFD.topo.lIndex[iVol].copy() @@ -2578,8 +2636,7 @@ def getFlattenedChildren(self): return flatChildren - def demoDesignVars(self, directory, includeLocal=True, includeGlobal=True, - pointSet=None, callBack=None, freq=2): + def demoDesignVars(self, directory, includeLocal=True, includeGlobal=True, pointSet=None, callBack=None, freq=2): """ This function can be used to "test" the design variable parametrization for a given optimization problem. It should be called in the script @@ -2607,8 +2664,8 @@ def demoDesignVars(self, directory, includeLocal=True, includeGlobal=True, a given variable. If greater than 2, will do a sinusoidal sweep. """ # Generate directories - os.system('mkdir -p {:s}/ffd'.format(directory)) - os.system('mkdir -p {:s}/pointset'.format(directory)) + os.system("mkdir -p {:s}/ffd".format(directory)) + os.system("mkdir -p {:s}/pointset".format(directory)) # Get design variables dvDict = self.getValues() @@ -2619,8 +2676,7 @@ def demoDesignVars(self, directory, includeLocal=True, includeGlobal=True, if self.ptSetNames: pointSet = self.ptSetNames[0] else: - raise Error('DVGeo must have a point set to update for ' - 'demoDesignVars to work.') + raise Error("DVGeo must have a point set to update for " "demoDesignVars to work.") else: writePointSet = True @@ -2655,8 +2711,7 @@ def demoDesignVars(self, directory, includeLocal=True, includeGlobal=True, upper = geo.DV_listGlobal[key].upper if lower is None or upper is None: - raise Error('demoDesignVars requires upper and lower bounds' - 'on all design variables.') + raise Error("demoDesignVars requires upper and lower bounds" "on all design variables.") x = dvDict[key].flatten() nDV = len(lower) @@ -2673,16 +2728,16 @@ def demoDesignVars(self, directory, includeLocal=True, includeGlobal=True, # Add perturbation to the design variable and update old_val = x[j] x[j] = val - dvDict.update({key:x}) + dvDict.update({key: x}) self.setDesignVars(dvDict) X = self.update(pointSet) # Write FFD - self.writeTecplot('{}/ffd/iter_{:03d}.dat'.format(directory, count)) + self.writeTecplot("{}/ffd/iter_{:03d}.dat".format(directory, count)) # Write pointset if writePointSet: - self.writePointSet(pointSet, '{}/pointset/iter_{:03d}'.format(directory, count)) + self.writePointSet(pointSet, "{}/pointset/iter_{:03d}".format(directory, count)) # Call user function if callBack is not None: @@ -2690,14 +2745,14 @@ def demoDesignVars(self, directory, includeLocal=True, includeGlobal=True, # Reset variable x[j] = old_val - dvDict.update({key:x}) + dvDict.update({key: x}) # Iterate counter count += 1 -# ---------------------------------------------------------------------- -# THE REMAINDER OF THE FUNCTIONS NEED NOT BE CALLED BY THE USER -# ---------------------------------------------------------------------- + # ---------------------------------------------------------------------- + # THE REMAINDER OF THE FUNCTIONS NEED NOT BE CALLED BY THE USER + # ---------------------------------------------------------------------- def _finalizeAxis(self): """ @@ -2710,7 +2765,7 @@ def _finalizeAxis(self): curves = [] for axis in self.axis: - curves.append(self.axis[axis]['curve']) + curves.append(self.axis[axis]["curve"]) # Setup the network of reference axis curves self.refAxis = pyNetwork(curves) @@ -2723,7 +2778,7 @@ def _finalizeAxis(self): self.scale_x = OrderedDict() self.scale_y = OrderedDict() self.scale_z = OrderedDict() - self.coef = self.refAxis.coef # pointer + self.coef = self.refAxis.coef # pointer self.coef0 = self.coef.copy().astype(self.dtype) i = 0 @@ -2777,14 +2832,14 @@ def _finalize(self): curveID = 0 # Loop over the axis we have: for key in self.axis: - vol_list = numpy.atleast_1d(self.axis[key]['volumes']).astype('intc') + vol_list = numpy.atleast_1d(self.axis[key]["volumes"]).astype("intc") temp = [] for iVol in vol_list: for i in range(self.FFD.vols[iVol].nCtlu): for j in range(self.FFD.vols[iVol].nCtlv): for k in range(self.FFD.vols[iVol].nCtlw): ind = self.FFD.topo.lIndex[iVol][i, j, k] - if coefMask[ind] == False and ind not in self.axis[key]['ignoreInd']: + if coefMask[ind] == False and ind not in self.axis[key]["ignoreInd"]: temp.append(ind) # Unique the values and append to the master list @@ -2796,12 +2851,12 @@ def _finalize(self): # Now do the projections for *just* the axis defined by my # key. - if self.axis[key]['axis'] is None: + if self.axis[key]["axis"] is None: tmpIDs, tmpS0 = self.refAxis.projectPoints(curPts, curves=[curveID]) else: tmpIDs, tmpS0 = self.refAxis.projectRays( - curPts, self.axis[key]['axis'], curves=[curveID], - raySize=self.axis[key]['raySize']) + curPts, self.axis[key]["axis"], curves=[curveID], raySize=self.axis[key]["raySize"] + ) curveIDs.extend(tmpIDs) s.extend(tmpS0) @@ -2822,12 +2877,9 @@ def _finalize(self): self.links_n = [] for i in range(self.nPtAttach): - self.links_x.append( - self.ptAttach[i] - \ - self.refAxis.curves[self.curveIDs[i]](s[i])) - deriv = self.refAxis.curves[ - self.curveIDs[i]].getDerivative(self.links_s[i]) - deriv /= geo_utils.euclideanNorm(deriv) # Normalize + self.links_x.append(self.ptAttach[i] - self.refAxis.curves[self.curveIDs[i]](s[i])) + deriv = self.refAxis.curves[self.curveIDs[i]].getDerivative(self.links_s[i]) + deriv /= geo_utils.euclideanNorm(deriv) # Normalize self.links_n.append(numpy.cross(deriv, self.links_x[-1])) self.links_x = numpy.array(self.links_x) @@ -2836,7 +2888,7 @@ def _finalize(self): def _setInitialValues(self): if len(self.axis) > 0: - self.coef[:,:] = copy.deepcopy(self.coef0) + self.coef[:, :] = copy.deepcopy(self.coef0) for key in self.axis: self.scale[key].coef[:] = copy.deepcopy(self.scale0[key].coef) self.scale_x[key].coef[:] = copy.deepcopy(self.scale_x0[key].coef) @@ -2868,7 +2920,7 @@ def _getRotMatrix(self, rotX, rotY, rotZ, rotType): def _getNDV(self): """Return the actual number of design variables, global + local - + section local + spanwise local + + section local + spanwise local """ return self._getNDVGlobal() + self._getNDVLocal() + self._getNDVSectionLocal() + self._getNDVSpanwiseLocal() @@ -2880,7 +2932,7 @@ def getNDV(self): ------- nDV : int Total number of design variables - """ + """ return self._getNDV() def _getNDVGlobal(self): @@ -2987,9 +3039,9 @@ def _getNDVSpanwiseLocalSelf(self): return nDV def _getDVOffsets(self): - ''' + """ return the global and local DV offsets for this FFD - ''' + """ # figure out the split between local and global Variables # All global vars at all levels come first @@ -2997,8 +3049,13 @@ def _getDVOffsets(self): # Parent Vars come before child Vars # get the global and local DV numbers on the parents if we don't have them - if self.nDV_T==None or self.nDVG_T == None or self.nDVL_T==None \ - or self.nDVSL_T==None or self.nDVSW_T==None: + if ( + self.nDV_T == None + or self.nDVG_T == None + or self.nDVL_T == None + or self.nDVSL_T == None + or self.nDVSW_T == None + ): self.nDV_T = self._getNDV() self.nDVG_T = self._getNDVGlobal() self.nDVL_T = self._getNDVLocal() @@ -3035,10 +3092,10 @@ def _getDVOffsets(self): return self.nDVG_count, self.nDVL_count, self.nDVSL_count, self.nDVSW_count - def _update_deriv(self, iDV=0, h=1.0e-40j, oneoverh=1.0/1e-40, config=None, localDV=False): + def _update_deriv(self, iDV=0, h=1.0e-40j, oneoverh=1.0 / 1e-40, config=None, localDV=False): """Copy of update function for derivative calc""" - new_pts = numpy.zeros((self.nPtAttach, 3), 'D') + new_pts = numpy.zeros((self.nPtAttach, 3), "D") # Step 1: Call all the design variables IFF we have ref axis: if len(self.axis) > 0: @@ -3047,41 +3104,38 @@ def _update_deriv(self, iDV=0, h=1.0e-40j, oneoverh=1.0/1e-40, config=None, loca self.updateCalculations(new_pts, isComplex=True, config=config) # create a vector of the size of the full FFD - numpy.put(self.FFD.coef[:, 0], self.ptAttachInd, new_pts[:,0]) - numpy.put(self.FFD.coef[:, 1], self.ptAttachInd, new_pts[:,1]) - numpy.put(self.FFD.coef[:, 2], self.ptAttachInd, new_pts[:,2]) + numpy.put(self.FFD.coef[:, 0], self.ptAttachInd, new_pts[:, 0]) + numpy.put(self.FFD.coef[:, 1], self.ptAttachInd, new_pts[:, 1]) + numpy.put(self.FFD.coef[:, 2], self.ptAttachInd, new_pts[:, 2]) # Add dependence of section variables on the global dv rotations for key in self.DV_listSectionLocal: self.DV_listSectionLocal[key].updateComplex(self.FFD.coef, self.coefRotM, config) # Send values back to new_pts - new_pts[:,0] = self.FFD.coef[self.ptAttachInd,0] - new_pts[:,1] = self.FFD.coef[self.ptAttachInd,1] - new_pts[:,2] = self.FFD.coef[self.ptAttachInd,2] + new_pts[:, 0] = self.FFD.coef[self.ptAttachInd, 0] + new_pts[:, 1] = self.FFD.coef[self.ptAttachInd, 1] + new_pts[:, 2] = self.FFD.coef[self.ptAttachInd, 2] # set the forward effect of the global design vars in each child for iChild in range(len(self.children)): # get the derivative of the child axis and control points wrt the parent # control points - dXrefdCoef = self.FFD.embededVolumes['child%d_axis'%(iChild)].dPtdCoef - dCcdCoef = self.FFD.embededVolumes['child%d_coef'%(iChild)].dPtdCoef + dXrefdCoef = self.FFD.embededVolumes["child%d_axis" % (iChild)].dPtdCoef + dCcdCoef = self.FFD.embededVolumes["child%d_coef" % (iChild)].dPtdCoef # create a vector with the derivative of the parent control points wrt the # parent global variables - tmp = numpy.zeros(self.FFD.coef.shape, dtype='d') - numpy.put(tmp[:, 0], self.ptAttachInd, - numpy.imag(new_pts[:,0])*oneoverh) - numpy.put(tmp[:, 1], self.ptAttachInd, - numpy.imag(new_pts[:,1])*oneoverh) - numpy.put(tmp[:, 2], self.ptAttachInd, - numpy.imag(new_pts[:,2])*oneoverh) + tmp = numpy.zeros(self.FFD.coef.shape, dtype="d") + numpy.put(tmp[:, 0], self.ptAttachInd, numpy.imag(new_pts[:, 0]) * oneoverh) + numpy.put(tmp[:, 1], self.ptAttachInd, numpy.imag(new_pts[:, 1]) * oneoverh) + numpy.put(tmp[:, 2], self.ptAttachInd, numpy.imag(new_pts[:, 2]) * oneoverh) # create variables for the total derivative of the child axis and control # points wrt the parent global variables - dXrefdXdv = numpy.zeros((dXrefdCoef.shape[0]*3), 'd') - dCcdXdv = numpy.zeros((dCcdCoef.shape[0]*3), 'd') + dXrefdXdv = numpy.zeros((dXrefdCoef.shape[0] * 3), "d") + dCcdXdv = numpy.zeros((dCcdCoef.shape[0] * 3), "d") # multiply the derivative of the child axis wrt the parent control points # by the derivative of the parent control points wrt the parent global vars. @@ -3106,34 +3160,34 @@ def _update_deriv_cs(self, ptSetName, config=None): """ A version of the update_deriv function specifically for use - in the computeTotalJacobianCS function. """ - new_pts = numpy.zeros((self.nPtAttachFull, 3), 'D') + in the computeTotalJacobianCS function.""" + new_pts = numpy.zeros((self.nPtAttachFull, 3), "D") # Make sure coefficients are complex self._complexifyCoef() # Set all coef Values back to initial values if not self.isChild: - self.FFD.coef = self.FFD.coef.astype('D') + self.FFD.coef = self.FFD.coef.astype("D") self._setInitialValues() else: # Update all coef - self.FFD.coef = self.FFD.coef.astype('D') + self.FFD.coef = self.FFD.coef.astype("D") self.FFD._updateVolumeCoef() # Evaluate starting pointset Xstart = self.FFD.getAttachedPoints(ptSetName) # Now we have to propagate the complex part through Xstart - tempCoef = self.FFD.coef.copy().astype('D') - Xstart = Xstart.astype('D') + tempCoef = self.FFD.coef.copy().astype("D") + Xstart = Xstart.astype("D") imag_part = numpy.imag(tempCoef) imag_j = 1j dPtdCoef = self.FFD.embededVolumes[ptSetName].dPtdCoef if dPtdCoef is not None: for ii in range(3): - Xstart[:, ii] += imag_j*dPtdCoef.dot(imag_part[:, ii]) + Xstart[:, ii] += imag_j * dPtdCoef.dot(imag_part[:, ii]) # Step 1: Call all the design variables IFF we have ref axis: if len(self.axis) > 0: @@ -3166,89 +3220,84 @@ def _update_deriv_cs(self, ptSetName, config=None): Xfinal = self.FFD.getAttachedPoints(ptSetName) # now project derivs through from the coef to the pts - Xfinal = Xfinal.astype('D') + Xfinal = Xfinal.astype("D") imag_part = numpy.imag(self.FFD.coef) imag_j = 1j dPtdCoef = self.FFD.embededVolumes[ptSetName].dPtdCoef if dPtdCoef is not None: for ii in range(3): - Xfinal[:, ii] += imag_j*dPtdCoef.dot(imag_part[:, ii]) + Xfinal[:, ii] += imag_j * dPtdCoef.dot(imag_part[:, ii]) # now do the same for the children for iChild in range(len(self.children)): - #first, update the coef. to their new locations + # first, update the coef. to their new locations child = self.children[iChild] child._finalize() self.applyToChild(iChild) # now cast forward the complex part of the derivative child._complexifyCoef() - child.FFD.coef = child.FFD.coef.astype('D') + child.FFD.coef = child.FFD.coef.astype("D") - dXrefdCoef = self.FFD.embededVolumes['child%d_axis'%(iChild)].dPtdCoef - dCcdCoef = self.FFD.embededVolumes['child%d_coef'%(iChild)].dPtdCoef + dXrefdCoef = self.FFD.embededVolumes["child%d_axis" % (iChild)].dPtdCoef + dCcdCoef = self.FFD.embededVolumes["child%d_coef" % (iChild)].dPtdCoef if dXrefdCoef is not None: for ii in range(3): - child.coef[:, ii] += imag_j*dXrefdCoef.dot(imag_part[:, ii]) + child.coef[:, ii] += imag_j * dXrefdCoef.dot(imag_part[:, ii]) if dCcdCoef is not None: for ii in range(3): - child.FFD.coef[:, ii] += imag_j*dCcdCoef.dot(imag_part[:, ii]) + child.FFD.coef[:, ii] += imag_j * dCcdCoef.dot(imag_part[:, ii]) child.refAxis.coef = child.coef.copy() child.refAxis._updateCurveCoef() Xfinal += child._update_deriv_cs(ptSetName, config=config) child._unComplexifyCoef() - self.FFD.coef = self.FFD.coef.real.astype('d') + self.FFD.coef = self.FFD.coef.real.astype("d") if self.isChild: return Xfinal - Xstart else: return Xfinal - def _complexifyCoef(self): """Convert coef to complex temporarily""" if len(self.axis) > 0: for key in self.axis: - self.rot_x[key].coef = self.rot_x[key].coef.astype('D') - self.rot_y[key].coef = self.rot_y[key].coef.astype('D') - self.rot_z[key].coef = self.rot_z[key].coef.astype('D') - self.rot_theta[key].coef = self.rot_theta[key].coef.astype('D') + self.rot_x[key].coef = self.rot_x[key].coef.astype("D") + self.rot_y[key].coef = self.rot_y[key].coef.astype("D") + self.rot_z[key].coef = self.rot_z[key].coef.astype("D") + self.rot_theta[key].coef = self.rot_theta[key].coef.astype("D") - self.scale[key].coef = self.scale[key].coef.astype('D') - self.scale_x[key].coef = self.scale_x[key].coef.astype('D') - self.scale_y[key].coef = self.scale_y[key].coef.astype('D') - self.scale_z[key].coef = self.scale_z[key].coef.astype('D') + self.scale[key].coef = self.scale[key].coef.astype("D") + self.scale_x[key].coef = self.scale_x[key].coef.astype("D") + self.scale_y[key].coef = self.scale_y[key].coef.astype("D") + self.scale_z[key].coef = self.scale_z[key].coef.astype("D") for i in range(self.refAxis.nCurve): - self.refAxis.curves[i].coef = ( - self.refAxis.curves[i].coef.astype('D')) - self.coef = self.coef.astype('D') - - + self.refAxis.curves[i].coef = self.refAxis.curves[i].coef.astype("D") + self.coef = self.coef.astype("D") def _unComplexifyCoef(self): """Convert coef back to reals""" if len(self.axis) > 0 and not self.complex: for key in self.axis: - self.rot_x[key].coef = self.rot_x[key].coef.real.astype('d') - self.rot_y[key].coef = self.rot_y[key].coef.real.astype('d') - self.rot_z[key].coef = self.rot_z[key].coef.real.astype('d') - self.rot_theta[key].coef = self.rot_theta[key].coef.real.astype('d') + self.rot_x[key].coef = self.rot_x[key].coef.real.astype("d") + self.rot_y[key].coef = self.rot_y[key].coef.real.astype("d") + self.rot_z[key].coef = self.rot_z[key].coef.real.astype("d") + self.rot_theta[key].coef = self.rot_theta[key].coef.real.astype("d") - self.scale[key].coef = self.scale[key].coef.real.astype('d') - self.scale_x[key].coef = self.scale_x[key].coef.real.astype('d') - self.scale_y[key].coef = self.scale_y[key].coef.real.astype('d') - self.scale_z[key].coef = self.scale_z[key].coef.real.astype('d') + self.scale[key].coef = self.scale[key].coef.real.astype("d") + self.scale_x[key].coef = self.scale_x[key].coef.real.astype("d") + self.scale_y[key].coef = self.scale_y[key].coef.real.astype("d") + self.scale_z[key].coef = self.scale_z[key].coef.real.astype("d") for i in range(self.refAxis.nCurve): - self.refAxis.curves[i].coef = ( - self.refAxis.curves[i].coef.real.astype('d')) + self.refAxis.curves[i].coef = self.refAxis.curves[i].coef.real.astype("d") - self.coef = self.coef.real.astype('d') + self.coef = self.coef.real.astype("d") def computeTotalJacobianFD(self, ptSetName, config=None): """This function takes the total derivative of an objective, @@ -3261,7 +3310,7 @@ def computeTotalJacobianFD(self, ptSetName, config=None): self._finalize() self.curPtSet = ptSetName - if not(self.JT[ptSetName] is None): + if not (self.JT[ptSetName] is None): return if self.isChild: @@ -3283,7 +3332,7 @@ def computeTotalJacobianFD(self, ptSetName, config=None): h = 1e-6 - self.JT[ptSetName] = numpy.zeros([self.nDV_T,self.nPts[ptSetName]]) + self.JT[ptSetName] = numpy.zeros([self.nDV_T, self.nPts[ptSetName]]) for key in self.DV_listGlobal: for j in range(self.DV_listGlobal[key].nVal): @@ -3299,8 +3348,8 @@ def computeTotalJacobianFD(self, ptSetName, config=None): coordsph = self.update(ptSetName, childDelta=False, config=config).flatten() - deriv = (coordsph-coords0)/h - self.JT[ptSetName][DVGlobalCount,:]=deriv + deriv = (coordsph - coords0) / h + self.JT[ptSetName][DVGlobalCount, :] = deriv DVGlobalCount += 1 self.DV_listGlobal[key].value[j] = refVal @@ -3318,13 +3367,12 @@ def computeTotalJacobianFD(self, ptSetName, config=None): self.DV_listSpanwiseLocal[key].value[j] += h coordsph = self.update(ptSetName, childDelta=False, config=config).flatten() - deriv = (coordsph-coords0)/h - self.JT[ptSetName][DVSpanLocCount,:]=deriv + deriv = (coordsph - coords0) / h + self.JT[ptSetName][DVSpanLocCount, :] = deriv DVSpanLocCount += 1 self.DV_listSpanwiseLocal[key].value[j] = refVal - for key in self.DV_listSectionLocal: for j in range(self.DV_listSectionLocal[key].nVal): if self.isChild: @@ -3338,8 +3386,8 @@ def computeTotalJacobianFD(self, ptSetName, config=None): self.DV_listSectionLocal[key].value[j] += h coordsph = self.update(ptSetName, childDelta=False, config=config).flatten() - deriv = (coordsph-coords0)/h - self.JT[ptSetName][DVSecLocCount,:]=deriv + deriv = (coordsph - coords0) / h + self.JT[ptSetName][DVSecLocCount, :] = deriv DVSecLocCount += 1 self.DV_listSectionLocal[key].value[j] = refVal @@ -3357,8 +3405,8 @@ def computeTotalJacobianFD(self, ptSetName, config=None): self.DV_listLocal[key].value[j] += h coordsph = self.update(ptSetName, childDelta=False, config=config).flatten() - deriv = (coordsph-coords0)/h - self.JT[ptSetName][DVLocalCount,:]=deriv + deriv = (coordsph - coords0) / h + self.JT[ptSetName][DVLocalCount, :] = deriv DVLocalCount += 1 self.DV_listLocal[key].value[j] = refVal @@ -3388,24 +3436,24 @@ def _attachedPtJacobian(self, config): self._getDVOffsets() h = 1.0e-40j - oneoverh = 1.0/1e-40 + oneoverh = 1.0 / 1e-40 # Just do a CS loop over the coef # First sum the actual number of globalDVs - if nDV != 0: # check this + if nDV != 0: # check this # create a jacobian the size of nPtAttached full by self.nDV_T, the total number of # dvs - Jacobian = numpy.zeros((self.nPtAttachFull*3, self.nDV_T)) + Jacobian = numpy.zeros((self.nPtAttachFull * 3, self.nDV_T)) # Create the storage arrays for the information that must be # passed to the children for iChild in range(len(self.children)): - N = self.FFD.embededVolumes['child%d_axis'%(iChild)].N + N = self.FFD.embededVolumes["child%d_axis" % (iChild)].N # Derivative of reference axis points wrt global DVs at this level - self.children[iChild].dXrefdXdvg = numpy.zeros((N*3, self.nDV_T)) + self.children[iChild].dXrefdXdvg = numpy.zeros((N * 3, self.nDV_T)) - N = self.FFD.embededVolumes['child%d_coef'%(iChild)].N + N = self.FFD.embededVolumes["child%d_coef" % (iChild)].N # derivative of the control points wrt the global DVs at this level - self.children[iChild].dCcdXdvg = numpy.zeros((N*3, self.nDV_T)) + self.children[iChild].dCcdXdvg = numpy.zeros((N * 3, self.nDV_T)) # We need to save the reference state so that we can always start # from the same place when calling _update_deriv @@ -3414,9 +3462,11 @@ def _attachedPtJacobian(self, config): iDV = self.nDVG_count for key in self.DV_listGlobal: - if self.DV_listGlobal[key].config is None or \ - config is None or \ - any(c0 == config for c0 in self.DV_listGlobal[key].config): + if ( + self.DV_listGlobal[key].config is None + or config is None + or any(c0 == config for c0 in self.DV_listGlobal[key].config) + ): nVal = self.DV_listGlobal[key].nVal for j in range(nVal): @@ -3425,23 +3475,20 @@ def _attachedPtJacobian(self, config): self.DV_listGlobal[key].value[j] += h # Reset coefficients - self.FFD.coef = refFFDCoef.astype('D') # ffd coefficients - self.coef = refCoef.astype('D') - self.refAxis.coef = refCoef.astype('D') + self.FFD.coef = refFFDCoef.astype("D") # ffd coefficients + self.coef = refCoef.astype("D") + self.refAxis.coef = refCoef.astype("D") self._complexifyCoef() # Make sure coefficients are complex self.refAxis._updateCurveCoef() - deriv = oneoverh*numpy.imag(self._update_deriv(iDV,h,oneoverh,config=config)).flatten() + deriv = oneoverh * numpy.imag(self._update_deriv(iDV, h, oneoverh, config=config)).flatten() # reset the FFD and axis self._unComplexifyCoef() - self.FFD.coef = self.FFD.coef.real.astype('d') + self.FFD.coef = self.FFD.coef.real.astype("d") - numpy.put(Jacobian[0::3, iDV], self.ptAttachInd, - deriv[0::3]) - numpy.put(Jacobian[1::3, iDV], self.ptAttachInd, - deriv[1::3]) - numpy.put(Jacobian[2::3, iDV], self.ptAttachInd, - deriv[2::3]) + numpy.put(Jacobian[0::3, iDV], self.ptAttachInd, deriv[0::3]) + numpy.put(Jacobian[1::3, iDV], self.ptAttachInd, deriv[1::3]) + numpy.put(Jacobian[2::3, iDV], self.ptAttachInd, deriv[2::3]) iDV += 1 @@ -3453,7 +3500,6 @@ def _attachedPtJacobian(self, config): return Jacobian - def _spanwiselocalDVJacobian(self, config=None): """ Return the derivative of the coefficients wrt the local normal design @@ -3465,63 +3511,62 @@ def _spanwiselocalDVJacobian(self, config=None): self._getDVOffsets() if nDV != 0: - Jacobian = sparse.lil_matrix((self.nPtAttachFull*3, self.nDV_T)) + Jacobian = sparse.lil_matrix((self.nPtAttachFull * 3, self.nDV_T)) # Create the storage arrays for the information that must be # passed to the children for iChild in range(len(self.children)): - N = self.FFD.embededVolumes['child%d_axis'%(iChild)].N - self.children[iChild].dXrefdXdvl = numpy.zeros((N*3, self.nDV_T)) + N = self.FFD.embededVolumes["child%d_axis" % (iChild)].N + self.children[iChild].dXrefdXdvl = numpy.zeros((N * 3, self.nDV_T)) - N = self.FFD.embededVolumes['child%d_coef'%(iChild)].N - self.children[iChild].dCcdXdvl = numpy.zeros((N*3, self.nDV_T)) + N = self.FFD.embededVolumes["child%d_coef" % (iChild)].N + self.children[iChild].dCcdXdvl = numpy.zeros((N * 3, self.nDV_T)) iDVSpanwiseLocal = self.nDVSW_count for key in self.DV_listSpanwiseLocal: dv = self.DV_listSpanwiseLocal[key] - + # check that the dv is active for this config if dv.config is None or config is None or any(c0 == config for c0 in dv.config): nVal = dv.nVal - - #apply this dv to FFD + + # apply this dv to FFD self.DV_listSpanwiseLocal[key](self.FFD.coef, config) - # loop over value of the dv - # (for example a single shape dv may have 20 values that + # loop over value of the dv + # (for example a single shape dv may have 20 values that # control the shape of the FFD at 20 points) for j in range(nVal): coefs = dv.dv_to_coefs[j] # affected control points of FFD # this is map from dvs to coef for coef in coefs: - irow = coef*3 + dv.axis + irow = coef * 3 + dv.axis # *3 because the jacobian has a row for each x,y,z of the FFD # It is basically # row number = coef index * n dimensions + dimension index - - # value of FFD node location = x0 + dv_SWLocal[j] - # so partial(FFD node location)/partial(dv_SWLocal) = 1 + + # value of FFD node location = x0 + dv_SWLocal[j] + # so partial(FFD node location)/partial(dv_SWLocal) = 1 # for each node effected by the dv_SWLocal[j] Jacobian[irow, iDVSpanwiseLocal] = 1.0 for iChild in range(len(self.children)): # Get derivatives of child ref axis and FFD control # points w.r.t. parent's FFD control points - dXrefdCoef = self.FFD.embededVolumes['child%d_axis'%(iChild)].dPtdCoef - dCcdCoef = self.FFD.embededVolumes['child%d_coef'%(iChild)].dPtdCoef + dXrefdCoef = self.FFD.embededVolumes["child%d_axis" % (iChild)].dPtdCoef + dCcdCoef = self.FFD.embededVolumes["child%d_coef" % (iChild)].dPtdCoef # derivative of Change in the FFD coef due to DVs # same as Jacobian above, but differnt ordering - dCoefdXdvl = numpy.zeros(self.FFD.coef.shape,dtype='d') + dCoefdXdvl = numpy.zeros(self.FFD.coef.shape, dtype="d") for coef in coefs: dCoefdXdvl[coef, dv.axis] = 1.0 - - dXrefdXdvl = numpy.zeros((dXrefdCoef.shape[0]*3),'d') - dCcdXdvl = numpy.zeros((dCcdCoef.shape[0]*3),'d') + dXrefdXdvl = numpy.zeros((dXrefdCoef.shape[0] * 3), "d") + dCcdXdvl = numpy.zeros((dCcdCoef.shape[0] * 3), "d") dXrefdXdvl[0::3] = dXrefdCoef.dot(dCoefdXdvl[:, 0]) dXrefdXdvl[1::3] = dXrefdCoef.dot(dCoefdXdvl[:, 1]) @@ -3545,10 +3590,8 @@ def _spanwiselocalDVJacobian(self, config=None): else: Jacobian = None - return Jacobian - def _sectionlocalDVJacobian(self, config=None): """ Return the derivative of the coefficients wrt the local normal design @@ -3560,17 +3603,17 @@ def _sectionlocalDVJacobian(self, config=None): self._getDVOffsets() if nDV != 0: - Jacobian = sparse.lil_matrix((self.nPtAttachFull*3, self.nDV_T)) + Jacobian = sparse.lil_matrix((self.nPtAttachFull * 3, self.nDV_T)) # Create the storage arrays for the information that must be # passed to the children for iChild in range(len(self.children)): - N = self.FFD.embededVolumes['child%d_axis'%(iChild)].N - self.children[iChild].dXrefdXdvl = numpy.zeros((N*3, self.nDV_T)) + N = self.FFD.embededVolumes["child%d_axis" % (iChild)].N + self.children[iChild].dXrefdXdvl = numpy.zeros((N * 3, self.nDV_T)) - N = self.FFD.embededVolumes['child%d_coef'%(iChild)].N - self.children[iChild].dCcdXdvl = numpy.zeros((N*3, self.nDV_T)) + N = self.FFD.embededVolumes["child%d_coef" % (iChild)].N + self.children[iChild].dCcdXdvl = numpy.zeros((N * 3, self.nDV_T)) iDVSectionLocal = self.nDVSL_count for key in self.DV_listSectionLocal: @@ -3583,7 +3626,7 @@ def _sectionlocalDVJacobian(self, config=None): for j in range(nVal): coef = dv.coefList[j] # affected control point T = dv.sectionTransform[dv.sectionLink[coef]] - inFrame = numpy.zeros((3,1)) + inFrame = numpy.zeros((3, 1)) # Set axis that is being perturbed to 1.0 inFrame[dv.axis] = 1.0 @@ -3592,18 +3635,18 @@ def _sectionlocalDVJacobian(self, config=None): # the original was: # rows = range(coef*3,(coef+1)*3) # Jacobian[rows, iDVSectionLocal] += R.dot(T.dot(inFrame)) - Jacobian[coef*3:(coef+1)*3, iDVSectionLocal] += R.dot(T.dot(inFrame)) + Jacobian[coef * 3 : (coef + 1) * 3, iDVSectionLocal] += R.dot(T.dot(inFrame)) for iChild in range(len(self.children)): - dXrefdCoef = self.FFD.embededVolumes['child%d_axis'%(iChild)].dPtdCoef - dCcdCoef = self.FFD.embededVolumes['child%d_coef'%(iChild)].dPtdCoef + dXrefdCoef = self.FFD.embededVolumes["child%d_axis" % (iChild)].dPtdCoef + dCcdCoef = self.FFD.embededVolumes["child%d_coef" % (iChild)].dPtdCoef - tmp = numpy.zeros(self.FFD.coef.shape, dtype='d') + tmp = numpy.zeros(self.FFD.coef.shape, dtype="d") - tmp[coef,:] = R.dot(T.dot(inFrame)).flatten() + tmp[coef, :] = R.dot(T.dot(inFrame)).flatten() - dXrefdXdvl = numpy.zeros((dXrefdCoef.shape[0]*3),'d') - dCcdXdvl = numpy.zeros((dCcdCoef.shape[0]*3),'d') + dXrefdXdvl = numpy.zeros((dXrefdCoef.shape[0] * 3), "d") + dCcdXdvl = numpy.zeros((dCcdCoef.shape[0] * 3), "d") dXrefdXdvl[0::3] = dXrefdCoef.dot(tmp[:, 0]) dXrefdXdvl[1::3] = dXrefdCoef.dot(tmp[:, 1]) @@ -3626,7 +3669,6 @@ def _sectionlocalDVJacobian(self, config=None): else: Jacobian = None - return Jacobian def _localDVJacobian(self, config=None): @@ -3641,43 +3683,45 @@ def _localDVJacobian(self, config=None): self._getDVOffsets() if nDV != 0: - Jacobian = sparse.lil_matrix((self.nPtAttachFull*3, self.nDV_T)) + Jacobian = sparse.lil_matrix((self.nPtAttachFull * 3, self.nDV_T)) # Create the storage arrays for the information that must be # passed to the children for iChild in range(len(self.children)): - N = self.FFD.embededVolumes['child%d_axis'%(iChild)].N - self.children[iChild].dXrefdXdvl = numpy.zeros((N*3, self.nDV_T)) + N = self.FFD.embededVolumes["child%d_axis" % (iChild)].N + self.children[iChild].dXrefdXdvl = numpy.zeros((N * 3, self.nDV_T)) - N = self.FFD.embededVolumes['child%d_coef'%(iChild)].N - self.children[iChild].dCcdXdvl = numpy.zeros((N*3, self.nDV_T)) + N = self.FFD.embededVolumes["child%d_coef" % (iChild)].N + self.children[iChild].dCcdXdvl = numpy.zeros((N * 3, self.nDV_T)) iDVLocal = self.nDVL_count for key in self.DV_listLocal: - if self.DV_listLocal[key].config is None or \ - config is None or \ - any(c0 == config for c0 in self.DV_listLocal[key].config): + if ( + self.DV_listLocal[key].config is None + or config is None + or any(c0 == config for c0 in self.DV_listLocal[key].config) + ): self.DV_listLocal[key](self.FFD.coef, config) nVal = self.DV_listLocal[key].nVal for j in range(nVal): pt_dv = self.DV_listLocal[key].coefList[j] - irow = pt_dv[0]*3 + pt_dv[1] + irow = pt_dv[0] * 3 + pt_dv[1] Jacobian[irow, iDVLocal] = 1.0 for iChild in range(len(self.children)): # Get derivatives of child ref axis and FFD control # points w.r.t. parent's FFD control points - dXrefdCoef = self.FFD.embededVolumes['child%d_axis'%(iChild)].dPtdCoef - dCcdCoef = self.FFD.embededVolumes['child%d_coef'%(iChild)].dPtdCoef + dXrefdCoef = self.FFD.embededVolumes["child%d_axis" % (iChild)].dPtdCoef + dCcdCoef = self.FFD.embededVolumes["child%d_coef" % (iChild)].dPtdCoef - tmp = numpy.zeros(self.FFD.coef.shape,dtype='d') + tmp = numpy.zeros(self.FFD.coef.shape, dtype="d") - tmp[pt_dv[0],pt_dv[1]] = 1.0 + tmp[pt_dv[0], pt_dv[1]] = 1.0 - dXrefdXdvl = numpy.zeros((dXrefdCoef.shape[0]*3),'d') - dCcdXdvl = numpy.zeros((dCcdCoef.shape[0]*3),'d') + dXrefdXdvl = numpy.zeros((dXrefdCoef.shape[0] * 3), "d") + dCcdXdvl = numpy.zeros((dCcdCoef.shape[0] * 3), "d") dXrefdXdvl[0::3] = dXrefdCoef.dot(tmp[:, 0]) dXrefdXdvl[1::3] = dXrefdCoef.dot(tmp[:, 1]) @@ -3700,7 +3744,6 @@ def _localDVJacobian(self, config=None): else: Jacobian = None - return Jacobian def _cascadedDVJacobian(self, config=None): @@ -3712,7 +3755,7 @@ def _cascadedDVJacobian(self, config=None): return None # we are now on a child. Add in dependence passed from parent - Jacobian = sparse.lil_matrix((self.nPtAttachFull*3, self.nDV_T)) + Jacobian = sparse.lil_matrix((self.nPtAttachFull * 3, self.nDV_T)) # Save reference values (these are necessary so that we always start # from the base state on the current DVGeo, and then apply the design @@ -3721,7 +3764,7 @@ def _cascadedDVJacobian(self, config=None): refCoef = copy.copy(self.coef) h = 1.0e-40j - oneoverh = 1.0/1e-40 + oneoverh = 1.0 / 1e-40 if self.dXrefdXdvg is not None: for iDV in range(self.dXrefdXdvg.shape[1]): nz1 = numpy.count_nonzero(self.dXrefdXdvg[:, iDV]) @@ -3730,36 +3773,36 @@ def _cascadedDVJacobian(self, config=None): continue # Complexify all of the coefficients - self.FFD.coef = refFFDCoef.astype('D') - self.coef = refCoef.astype('D') + self.FFD.coef = refFFDCoef.astype("D") + self.coef = refCoef.astype("D") self._complexifyCoef() # Add a complex pertubation representing the change in the child # reference axis wrt the parent global DVs - self.coef[:,0] += self.dXrefdXdvg[0::3, iDV]*h - self.coef[:,1] += self.dXrefdXdvg[1::3, iDV]*h - self.coef[:,2] += self.dXrefdXdvg[2::3, iDV]*h + self.coef[:, 0] += self.dXrefdXdvg[0::3, iDV] * h + self.coef[:, 1] += self.dXrefdXdvg[1::3, iDV] * h + self.coef[:, 2] += self.dXrefdXdvg[2::3, iDV] * h # insert the new coef into the refAxis self.refAxis.coef = self.coef.copy() self.refAxis._updateCurveCoef() - #Complexify the child FFD coords - tmp1 = numpy.zeros_like(self.FFD.coef,dtype='D') + # Complexify the child FFD coords + tmp1 = numpy.zeros_like(self.FFD.coef, dtype="D") # add the effect of the global coordinates on the actual control points - tmp1[:,0] = self.dCcdXdvg[0::3, iDV]*h - tmp1[:,1] = self.dCcdXdvg[1::3, iDV]*h - tmp1[:,2] = self.dCcdXdvg[2::3, iDV]*h + tmp1[:, 0] = self.dCcdXdvg[0::3, iDV] * h + tmp1[:, 1] = self.dCcdXdvg[1::3, iDV] * h + tmp1[:, 2] = self.dCcdXdvg[2::3, iDV] * h - self.FFD.coef+=tmp1 + self.FFD.coef += tmp1 - #Store the original FFD coordinates so that we can get the delta + # Store the original FFD coordinates so that we can get the delta oldCoefLocations = self.FFD.coef.copy() # compute the deriv of the child FFD coords wrt the parent by processing # the above CS perturbation - new_pts = self._update_deriv(iDV,h,oneoverh, config=config) + new_pts = self._update_deriv(iDV, h, oneoverh, config=config) # insert this result in the the correct locations of a vector the correct # size @@ -3774,13 +3817,13 @@ def _cascadedDVJacobian(self, config=None): self.FFD.coef -= oldCoefLocations # sum up all of the various influences - Jacobian[0::3, iDV] += oneoverh*numpy.imag(self.FFD.coef[:,0:1]) - Jacobian[1::3, iDV] += oneoverh*numpy.imag(self.FFD.coef[:,1:2]) - Jacobian[2::3, iDV] += oneoverh*numpy.imag(self.FFD.coef[:,2:3]) + Jacobian[0::3, iDV] += oneoverh * numpy.imag(self.FFD.coef[:, 0:1]) + Jacobian[1::3, iDV] += oneoverh * numpy.imag(self.FFD.coef[:, 1:2]) + Jacobian[2::3, iDV] += oneoverh * numpy.imag(self.FFD.coef[:, 2:3]) # decomplexify the coefficients - self.coef = self.coef.real.astype('d') - self.FFD.coef = self.FFD.coef.real.astype('d') + self.coef = self.coef.real.astype("d") + self.FFD.coef = self.FFD.coef.real.astype("d") self._unComplexifyCoef() if self.dXrefdXdvl is not None: @@ -3793,36 +3836,36 @@ def _cascadedDVJacobian(self, config=None): continue # Complexify all of the coefficients - self.FFD.coef = refFFDCoef.astype('D') - self.coef = refCoef.astype('D') + self.FFD.coef = refFFDCoef.astype("D") + self.coef = refCoef.astype("D") self._complexifyCoef() # Add a complex pertubation representing the change in the child # reference axis wrt the parent local DVs - self.coef[:,0] += self.dXrefdXdvl[0::3, iDV]*h - self.coef[:,1] += self.dXrefdXdvl[1::3, iDV]*h - self.coef[:,2] += self.dXrefdXdvl[2::3, iDV]*h + self.coef[:, 0] += self.dXrefdXdvl[0::3, iDV] * h + self.coef[:, 1] += self.dXrefdXdvl[1::3, iDV] * h + self.coef[:, 2] += self.dXrefdXdvl[2::3, iDV] * h # insert the new coef into the refAxis self.refAxis.coef = self.coef.copy() self.refAxis._updateCurveCoef() - #Complexify the child FFD coords - tmp1 = numpy.zeros_like(self.FFD.coef,dtype='D') + # Complexify the child FFD coords + tmp1 = numpy.zeros_like(self.FFD.coef, dtype="D") # add the effect of the global coordinates on the actual control points - tmp1[:,0] = self.dCcdXdvl[0::3, iDV]*h - tmp1[:,1] = self.dCcdXdvl[1::3, iDV]*h - tmp1[:,2] = self.dCcdXdvl[2::3, iDV]*h + tmp1[:, 0] = self.dCcdXdvl[0::3, iDV] * h + tmp1[:, 1] = self.dCcdXdvl[1::3, iDV] * h + tmp1[:, 2] = self.dCcdXdvl[2::3, iDV] * h self.FFD.coef += tmp1 - #Store the original FFD coordinates so that we can get the delta + # Store the original FFD coordinates so that we can get the delta oldCoefLocations = self.FFD.coef.copy() # compute the deriv of the child FFD coords wrt the parent by processing # the above CS perturbation - new_pts = self._update_deriv(iDV, h, oneoverh, config=config,localDV=True) + new_pts = self._update_deriv(iDV, h, oneoverh, config=config, localDV=True) numpy.put(self.FFD.coef[:, 0], self.ptAttachInd, new_pts[:, 0]) numpy.put(self.FFD.coef[:, 1], self.ptAttachInd, new_pts[:, 1]) numpy.put(self.FFD.coef[:, 2], self.ptAttachInd, new_pts[:, 2]) @@ -3834,20 +3877,20 @@ def _cascadedDVJacobian(self, config=None): self.FFD.coef -= oldCoefLocations # sum up all of the various influences - Jacobian[0::3, iDV] += oneoverh*numpy.imag(self.FFD.coef[:,0:1]) - Jacobian[1::3, iDV] += oneoverh*numpy.imag(self.FFD.coef[:,1:2]) - Jacobian[2::3, iDV] += oneoverh*numpy.imag(self.FFD.coef[:,2:3]) + Jacobian[0::3, iDV] += oneoverh * numpy.imag(self.FFD.coef[:, 0:1]) + Jacobian[1::3, iDV] += oneoverh * numpy.imag(self.FFD.coef[:, 1:2]) + Jacobian[2::3, iDV] += oneoverh * numpy.imag(self.FFD.coef[:, 2:3]) # decomplexify the coefficients - self.coef = self.coef.real.astype('d') - self.FFD.coef = self.FFD.coef.real.astype('d') + self.coef = self.coef.real.astype("d") + self.FFD.coef = self.FFD.coef.real.astype("d") self._unComplexifyCoef() return Jacobian def _writeVols(self, handle, vol_counter): for i in range(len(self.FFD.vols)): - pySpline.writeTecplot3D(handle, 'vol%d'%i, self.FFD.vols[i].coef) + pySpline.writeTecplot3D(handle, "vol%d" % i, self.FFD.vols[i].coef) vol_counter += 1 # Write children volumes: @@ -3864,9 +3907,9 @@ def checkDerivatives(self, ptSetName): ---------- ptSetName : str name of the point set to check - """ + """ - print('Computing Analytic Jacobian...') + print("Computing Analytic Jacobian...") self.zeroJacobians(ptSetName) for child in self.children: child.zeroJacobians(ptSetName) @@ -3877,9 +3920,9 @@ def checkDerivatives(self, ptSetName): Jac = copy.deepcopy(self.JT[ptSetName]) # Global Variables - print('========================================') - print(' Global Variables ') - print('========================================') + print("========================================") + print(" Global Variables ") + print("========================================") if self.isChild: refFFDCoef = copy.copy(self.FFD.coef) @@ -3895,9 +3938,9 @@ def checkDerivatives(self, ptSetName): for key in self.DV_listGlobal: for j in range(self.DV_listGlobal[key].nVal): - print('========================================') - print(' GlobalVar(%s), Value(%d)'%(key, j)) - print('========================================') + print("========================================") + print(" GlobalVar(%s), Value(%d)" % (key, j)) + print("========================================") if self.isChild: self.FFD.coef = refFFDCoef.copy() @@ -3911,15 +3954,14 @@ def checkDerivatives(self, ptSetName): coordsph = self.update(ptSetName).flatten() - deriv = (coordsph-coords0)/h + deriv = (coordsph - coords0) / h for ii in range(len(deriv)): - relErr = (deriv[ii] - Jac[DVCountGlob, ii])/( - 1e-16 + Jac[DVCountGlob, ii]) - absErr = deriv[ii] - Jac[DVCountGlob,ii] + relErr = (deriv[ii] - Jac[DVCountGlob, ii]) / (1e-16 + Jac[DVCountGlob, ii]) + absErr = deriv[ii] - Jac[DVCountGlob, ii] - if abs(relErr) > h*10 and abs(absErr) > h*10: + if abs(relErr) > h * 10 and abs(absErr) > h * 10: print(ii, deriv[ii], Jac[DVCountGlob, ii], relErr, absErr) DVCountGlob += 1 @@ -3928,9 +3970,9 @@ def checkDerivatives(self, ptSetName): for key in self.DV_listLocal: for j in range(self.DV_listLocal[key].nVal): - print('========================================') - print(' LocalVar(%s), Value(%d) '%(key, j)) - print('========================================') + print("========================================") + print(" LocalVar(%s), Value(%d) " % (key, j)) + print("========================================") if self.isChild: self.FFD.coef = refFFDCoef.copy() @@ -3943,12 +3985,11 @@ def checkDerivatives(self, ptSetName): self.DV_listLocal[key].value[j] += h coordsph = self.update(ptSetName).flatten() - deriv = (coordsph-coords0)/h + deriv = (coordsph - coords0) / h for ii in range(len(deriv)): - relErr = (deriv[ii] - Jac[DVCountLoc, ii])/( - 1e-16 + Jac[DVCountLoc, ii]) - absErr = deriv[ii] - Jac[DVCountLoc,ii] + relErr = (deriv[ii] - Jac[DVCountLoc, ii]) / (1e-16 + Jac[DVCountLoc, ii]) + absErr = deriv[ii] - Jac[DVCountLoc, ii] if abs(relErr) > h and abs(absErr) > h: print(ii, deriv[ii], Jac[DVCountLoc, ii], relErr, absErr) @@ -3959,9 +4000,9 @@ def checkDerivatives(self, ptSetName): for key in self.DV_listSectionLocal: for j in range(self.DV_listSectionLocal[key].nVal): - print('========================================') - print(' SectionLocalVar(%s), Value(%d) '%(key, j)) - print('========================================') + print("========================================") + print(" SectionLocalVar(%s), Value(%d) " % (key, j)) + print("========================================") if self.isChild: self.FFD.coef = refFFDCoef.copy() @@ -3974,12 +4015,11 @@ def checkDerivatives(self, ptSetName): self.DV_listSectionLocal[key].value[j] += h coordsph = self.update(ptSetName).flatten() - deriv = (coordsph-coords0)/h + deriv = (coordsph - coords0) / h for ii in range(len(deriv)): - relErr = (deriv[ii] - Jac[DVCountSecLoc, ii])/( - 1e-16 + Jac[DVCountSecLoc, ii]) - absErr = deriv[ii] - Jac[DVCountSecLoc,ii] + relErr = (deriv[ii] - Jac[DVCountSecLoc, ii]) / (1e-16 + Jac[DVCountSecLoc, ii]) + absErr = deriv[ii] - Jac[DVCountSecLoc, ii] if abs(relErr) > h and abs(absErr) > h: print(ii, deriv[ii], Jac[DVCountSecLoc, ii], relErr, absErr) @@ -3990,9 +4030,9 @@ def checkDerivatives(self, ptSetName): for key in self.DV_listSpanwiseLocal: for j in range(self.DV_listSpanwiseLocal[key].nVal): - print('========================================') - print(' SpanwiseLocalVar(%s), Value(%d) '%(key, j)) - print('========================================') + print("========================================") + print(" SpanwiseLocalVar(%s), Value(%d) " % (key, j)) + print("========================================") if self.isChild: self.FFD.coef = refFFDCoef.copy() @@ -4005,12 +4045,11 @@ def checkDerivatives(self, ptSetName): self.DV_listSpanwiseLocal[key].value[j] += h coordsph = self.update(ptSetName).flatten() - deriv = (coordsph-coords0)/h + deriv = (coordsph - coords0) / h for ii in range(len(deriv)): - relErr = (deriv[ii] - Jac[DVCountSpanLoc, ii])/( - 1e-16 + Jac[DVCountSpanLoc, ii]) - absErr = deriv[ii] - Jac[DVCountSpanLoc,ii] + relErr = (deriv[ii] - Jac[DVCountSpanLoc, ii]) / (1e-16 + Jac[DVCountSpanLoc, ii]) + absErr = deriv[ii] - Jac[DVCountSpanLoc, ii] if abs(relErr) > h and abs(absErr) > h: print(ii, deriv[ii], Jac[DVCountSpanLoc, ii], relErr, absErr) @@ -4027,25 +4066,24 @@ def printDesignVariables(self): Print a formatted list of design variables to the screen """ for dg in self.DV_listGlobal: - print('%s'%(self.DV_listGlobal[dg].name)) + print("%s" % (self.DV_listGlobal[dg].name)) for i in range(self.DV_listGlobal[dg].nVal): - print('%20.15f'%(self.DV_listGlobal[dg].value[i])) + print("%20.15f" % (self.DV_listGlobal[dg].value[i])) for dl in self.DV_listLocal: - print('%s'%(self.DV_listLocal[dl].name)) + print("%s" % (self.DV_listLocal[dl].name)) for i in range(self.DV_listLocal[dl].nVal): - print('%20.15f'%(self.DV_listLocal[dl].value[i])) + print("%20.15f" % (self.DV_listLocal[dl].value[i])) for dsl in self.DV_listSectionLocal: - print('%s'%(self.DV_listSectionLocal[dsl].name)) + print("%s" % (self.DV_listSectionLocal[dsl].name)) for i in range(self.DV_listSectionLocal[dsl].nVal): - print('%20.15f'%(self.DV_listSectionLocal[dsl].value[i])) + print("%20.15f" % (self.DV_listSectionLocal[dsl].value[i])) for child in self.children: child.printDesignVariables() - def sectionFrame(self, sectionIndex, sectionTransform, sectionLink, ivol=0, - orient0=None, orient2='svd'): + def sectionFrame(self, sectionIndex, sectionTransform, sectionLink, ivol=0, orient0=None, orient2="svd"): """ This function computes a unique reference coordinate frame for each section of an FFD volume. You can choose which axis of the FFD you would @@ -4103,8 +4141,8 @@ def sectionFrame(self, sectionIndex, sectionTransform, sectionLink, ivol=0, List of transformation matrices for the sections of a given volume. Transformations are set up from local section frame to global frame. """ - xyz_2_idx = {'x':0, 'y':1, 'z':2} - ijk_2_idx = {'i':0, 'j':1, 'k':2} + xyz_2_idx = {"x": 0, "y": 1, "z": 2} + ijk_2_idx = {"i": 0, "j": 1, "k": 2} lIndex = self.FFD.topo.lIndex[ivol] # Get normal index @@ -4117,8 +4155,7 @@ def sectionFrame(self, sectionIndex, sectionTransform, sectionLink, ivol=0, elif type(orient0) is numpy.ndarray: orient0vec = True else: - raise Error('orient0 must be an index (i, j, or k) or a ' - 'vector.') + raise Error("orient0 must be an index (i, j, or k) or a " "vector.") # Get section index and number of sections sectionIndex = ijk_2_idx[sectionIndex.lower()] nSections = lIndex.shape[sectionIndex] @@ -4137,33 +4174,33 @@ def sectionFrame(self, sectionIndex, sectionTransform, sectionLink, ivol=0, # Compute singular value decomposition of points in section (the # U matrix should provide us with a pretty good approximation # of the transformation matrix) - pts = self.FFD.coef[rolledlIndex[i,:,:]] + pts = self.FFD.coef[rolledlIndex[i, :, :]] nJ, nI = pts.shape[:-1] - X = numpy.reshape(pts, (nI*nJ, 3)) - c = numpy.mean(X,0) + X = numpy.reshape(pts, (nI * nJ, 3)) + c = numpy.mean(X, 0) A = X - c - U,S,V = numpy.linalg.svd(A.T) + U, S, V = numpy.linalg.svd(A.T) # Choose section plane normal axis - if orient2 == 'svd': - ax2 = U[:,2] - elif orient2 == 'ffd': + if orient2 == "svd": + ax2 = U[:, 2] + elif orient2 == "ffd": # Use a centered FD approximation (first order at the boundaries) if i == 0: - pt = numpy.mean(self.FFD.coef[rolledlIndex[i,:,:]].reshape(nI*nJ,3), 0) - ptp = numpy.mean(self.FFD.coef[rolledlIndex[i+1,:,:]].reshape(nI*nJ,3), 0) - ax2 = ptp-pt - elif i == nSections-1: - pt = numpy.mean(self.FFD.coef[rolledlIndex[i,:,:]].reshape(nI*nJ,3), 0) - ptm = numpy.mean(self.FFD.coef[rolledlIndex[i-1,:,:]].reshape(nI*nJ,3), 0) - ax2 = pt-ptm + pt = numpy.mean(self.FFD.coef[rolledlIndex[i, :, :]].reshape(nI * nJ, 3), 0) + ptp = numpy.mean(self.FFD.coef[rolledlIndex[i + 1, :, :]].reshape(nI * nJ, 3), 0) + ax2 = ptp - pt + elif i == nSections - 1: + pt = numpy.mean(self.FFD.coef[rolledlIndex[i, :, :]].reshape(nI * nJ, 3), 0) + ptm = numpy.mean(self.FFD.coef[rolledlIndex[i - 1, :, :]].reshape(nI * nJ, 3), 0) + ax2 = pt - ptm else: - ptp = numpy.mean(self.FFD.coef[rolledlIndex[i+1,:,:]].reshape(nI*nJ,3), 0) - ptm = numpy.mean(self.FFD.coef[rolledlIndex[i-1,:,:]].reshape(nI*nJ,3), 0) - ax2 = ptp-ptm + ptp = numpy.mean(self.FFD.coef[rolledlIndex[i + 1, :, :]].reshape(nI * nJ, 3), 0) + ptm = numpy.mean(self.FFD.coef[rolledlIndex[i - 1, :, :]].reshape(nI * nJ, 3), 0) + ax2 = ptp - ptm ax2 /= numpy.linalg.norm(ax2) else: - raise Error('orient2 must be \'svd\' or \'ffd\'') + raise Error("orient2 must be 'svd' or 'ffd'") # Options for choosing in-plane axes # 1. Align axis '0' with projection of the given vector on section @@ -4176,39 +4213,39 @@ def sectionFrame(self, sectionIndex, sectionTransform, sectionLink, ivol=0, # through the section points. if orient0vec or orient0idx: if orient0vec: - u = orient0/numpy.linalg.norm(orient0) + u = orient0 / numpy.linalg.norm(orient0) else: - u = numpy.mean((pts[-1,:] - pts[0,:]), axis=0) - u = u/numpy.linalg.norm(u) - ax0 = u - u.dot(ax2)*ax2 - ax1 = numpy.cross(ax2,ax0) + u = numpy.mean((pts[-1, :] - pts[0, :]), axis=0) + u = u / numpy.linalg.norm(u) + ax0 = u - u.dot(ax2) * ax2 + ax1 = numpy.cross(ax2, ax0) else: - ax0 = U[:,0] - ax1 = U[:,1] + ax0 = U[:, 0] + ax1 = U[:, 1] - T = numpy.vstack((ax0,ax1,ax2)).T + T = numpy.vstack((ax0, ax1, ax2)).T sectionTransform.append(T) # Designate section transformation matrix for each control point in # section - sectionLink[rolledlIndex[i,:,:]] = Tcount + sectionLink[rolledlIndex[i, :, :]] = Tcount Tcount += 1 # Need to initialize coefRotM to identity matrix for case with no # global design variables - for slice in rolledlIndex[i,:,:]: + for slice in rolledlIndex[i, :, :]: for coef in slice: self.coefRotM[coef] = numpy.eye(3) return nSections -class geoDVGlobal(object): +class geoDVGlobal(object): def __init__(self, dv_name, value, lower, upper, scale, function, config): """Create a geometric design variable (or design variable group) See addGeoDVGlobal in DVGeometry class for more information """ self.name = dv_name - self.value = numpy.atleast_1d(numpy.array(value)).astype('D') + self.value = numpy.atleast_1d(numpy.array(value)).astype("D") self.nVal = len(self.value) self.lower = None self.upper = None @@ -4235,8 +4272,8 @@ def __call__(self, geo, config): else: return self.function(numpy.real(self.value), geo) -class geoDVLocal(object): +class geoDVLocal(object): def __init__(self, dvName, lower, upper, scale, axis, coefListIn, mask, config): """Create a set of geometric design variables which change the shape @@ -4246,14 +4283,14 @@ def __init__(self, dvName, lower, upper, scale, axis, coefListIn, mask, config): """ coefList = [] - #create a new coefficent list that excludes any values that are masked + # create a new coefficent list that excludes any values that are masked for i in range(len(coefListIn)): - if mask[coefListIn[i]]==False: + if mask[coefListIn[i]] == False: coefList.append(coefListIn[i]) N = len(axis) - self.nVal = len(coefList)*N - self.value = numpy.zeros(self.nVal, 'D') + self.nVal = len(coefList) * N + self.value = numpy.zeros(self.nVal, "D") self.name = dvName self.lower = None self.upper = None @@ -4265,17 +4302,17 @@ def __init__(self, dvName, lower, upper, scale, axis, coefListIn, mask, config): if scale is not None: self.scale = _convertTo1D(scale, self.nVal) - self.coefList = numpy.zeros((self.nVal, 2), 'intc') + self.coefList = numpy.zeros((self.nVal, 2), "intc") j = 0 for i in range(len(coefList)): - if 'x' in axis.lower(): + if "x" in axis.lower(): self.coefList[j] = [coefList[i], 0] j += 1 - elif 'y' in axis.lower(): + elif "y" in axis.lower(): self.coefList[j] = [coefList[i], 1] j += 1 - elif 'z' in axis.lower(): + elif "z" in axis.lower(): self.coefList[j] = [coefList[i], 2] j += 1 @@ -4291,14 +4328,14 @@ def __call__(self, coef, config): def updateComplex(self, coef, config): if self.config is None or config is None or any(c0 == config for c0 in self.config): for i in range(self.nVal): - coef[self.coefList[i, 0], self.coefList[i, 1]] += self.value[i].imag*1j + coef[self.coefList[i, 0], self.coefList[i, 1]] += self.value[i].imag * 1j return coef - def mapIndexSets(self,indSetA,indSetB): - ''' + def mapIndexSets(self, indSetA, indSetB): + """ Map the index sets from the full coefficient indices to the local set. - ''' + """ # Temp is the list of FFD coefficients that are included # as shape variables in this localDV "key" temp = self.coefList @@ -4321,6 +4358,7 @@ def mapIndexSets(self,indSetA,indSetB): return cons + def _convertTo1D(value, dim1): """ Generic function to process 'value'. In the end, it must be @@ -4329,17 +4367,16 @@ def _convertTo1D(value, dim1): """ if numpy.isscalar: - return value*numpy.ones(dim1) + return value * numpy.ones(dim1) else: temp = numpy.atleast_1d(value) if temp.shape[0] == dim1: return value else: - raise Error('The size of the 1D array was the incorret shape') + raise Error("The size of the 1D array was the incorret shape") class geoDVSpanwiseLocal(geoDVLocal): - def __init__(self, dvName, lower, upper, scale, axis, vol_dv_to_coefs, mask, config): """Create a set of geometric design variables which change the shape @@ -4350,7 +4387,6 @@ def __init__(self, dvName, lower, upper, scale, axis, vol_dv_to_coefs, mask, con self.dv_to_coefs = [] - # add all the coefs to a flat array, but check that it isn't masked first for ivol in range(len(vol_dv_to_coefs)): for loc_dv in range(len(vol_dv_to_coefs[ivol])): @@ -4358,26 +4394,24 @@ def __init__(self, dvName, lower, upper, scale, axis, vol_dv_to_coefs, mask, con loc_dv_to_coefs = [] - #loop through each of coefs to see if it is masked + # loop through each of coefs to see if it is masked for coef in coefs: - if mask[coef]==False: + if mask[coef] == False: loc_dv_to_coefs.append(coef) - self.dv_to_coefs.append(loc_dv_to_coefs) - - if 'x' == axis.lower(): + if "x" == axis.lower(): self.axis = 0 - elif 'y' == axis.lower(): + elif "y" == axis.lower(): self.axis = 1 - elif 'z' == axis.lower(): + elif "z" == axis.lower(): self.axis = 2 else: raise NotImplementedError self.nVal = len(self.dv_to_coefs) - self.value = numpy.zeros(self.nVal, 'D') + self.value = numpy.zeros(self.nVal, "D") self.name = dvName self.lower = None @@ -4391,7 +4425,6 @@ def __init__(self, dvName, lower, upper, scale, axis, vol_dv_to_coefs, mask, con if scale is not None: self.scale = _convertTo1D(scale, self.nVal) - def __call__(self, coef, config): """When the object is called, apply the design variable values to coefficients""" @@ -4404,14 +4437,14 @@ def __call__(self, coef, config): def updateComplex(self, coef, config): if self.config is None or config is None or any(c0 == config for c0 in self.config): for i in range(self.nVal): - coef[self.dv_to_coefs[i], self.axis] += self.value[i].imag*1j + coef[self.dv_to_coefs[i], self.axis] += self.value[i].imag * 1j return coef - def mapIndexSets(self,indSetA,indSetB): - ''' + def mapIndexSets(self, indSetA, indSetB): + """ Map the index sets from the full coefficient indices to the local set. - ''' + """ cons = [] for j in range(len(indSetA)): @@ -4437,9 +4470,7 @@ def mapIndexSets(self,indSetA,indSetB): class geoDVSectionLocal(object): - - def __init__(self, dvName, lower, upper, scale, axis, coefListIn, mask, - config, sectionTransform, sectionLink): + def __init__(self, dvName, lower, upper, scale, axis, coefListIn, mask, config, sectionTransform, sectionLink): """ Create a set of geometric design variables which change the shape of a surface. @@ -4447,13 +4478,13 @@ def __init__(self, dvName, lower, upper, scale, axis, coefListIn, mask, """ self.coefList = [] - #create a new coefficent list that excludes any values that are masked + # create a new coefficent list that excludes any values that are masked for i in range(len(coefListIn)): - if mask[coefListIn[i]]==False: + if mask[coefListIn[i]] == False: self.coefList.append(coefListIn[i]) self.nVal = len(self.coefList) - self.value = numpy.zeros(self.nVal, 'D') + self.value = numpy.zeros(self.nVal, "D") self.name = dvName self.lower = None self.upper = None @@ -4487,17 +4518,17 @@ def updateComplex(self, coef, coefRotM, config): if self.config is None or config is None or any(c0 == config for c0 in self.config): for i in range(len(self.coefList)): T = self.sectionTransform[self.sectionLink[self.coefList[i]]] - inFrame = numpy.zeros(3, 'D') + inFrame = numpy.zeros(3, "D") inFrame[self.axis] = self.value[i] R = coefRotM[self.coefList[i]] - coef[self.coefList[i]] += R.dot(T.dot(inFrame)).imag*1j + coef[self.coefList[i]] += R.dot(T.dot(inFrame)).imag * 1j return coef - def mapIndexSets(self,indSetA,indSetB): - ''' + def mapIndexSets(self, indSetA, indSetB): + """ Map the index sets from the full coefficient indices to the local set. - ''' + """ # Temp is the list of FFD coefficients that are included # as shape variables in this localDV "key" temp = self.coefList diff --git a/pygeo/DVGeometryAxi.py b/pygeo/DVGeometryAxi.py index 44ac50ed..375731c6 100644 --- a/pygeo/DVGeometryAxi.py +++ b/pygeo/DVGeometryAxi.py @@ -1,5 +1,4 @@ - -import numpy as np +import numpy as np from scipy import sparse try: @@ -8,23 +7,22 @@ try: from ordereddict import OrderedDict except ImportError: - print("Could not find any OrderedDict class. For 2.6 and earlier, " - "use:\n pip install ordereddict") + print("Could not find any OrderedDict class. For 2.6 and earlier, " "use:\n pip install ordereddict") -from . import DVGeometry +from . import DVGeometry AXES_2_IDX = {"x": 0, "y": 1, "z": 2} -AXES = set(['x', 'y', 'z']) +AXES = set(["x", "y", "z"]) -class _AxiTransform(object): - """Collapses a set of cartesian coordiantes into a single plane to allow +class _AxiTransform(object): + """Collapses a set of cartesian coordiantes into a single plane to allow for axi-symmetric FFD. Also expands them back to their original annular location Parameters ----------- - pts: (n,3) + pts: (n,3) array of points to be transformed center: (3,) @@ -32,35 +30,37 @@ class _AxiTransform(object): This can be any point along the rotation axis of the body collapse_into: 2-tuple of strings - Two coordinate axes that you wish to collapse your points into. This should + Two coordinate axes that you wish to collapse your points into. This should align with the specific direction you are moving FFD control points. The first item in the tuple is taken as the rotation axis for the axi-symmetric coordinate system. So ("x","z") - means to collapse into the x,z plane and use x as the rotational axis. ("z", "x") means to collapse + means to collapse into the x,z plane and use x as the rotational axis. ("z", "x") means to collapse into the x,z plane and use z as the rotational axis - """ + """ - def __init__(self, pts, center, collapse_into, complex=False): - self.complex = complex + def __init__(self, pts, center, collapse_into, complex=False): + self.complex = complex self.c_plane = collapse_into self.n_points = pts.shape[0] self.center = center - self.alpha_idx = AXES_2_IDX[self.c_plane[0]] + self.alpha_idx = AXES_2_IDX[self.c_plane[0]] self.beta_idx = AXES_2_IDX[self.c_plane[1]] - self.gamma_idx = AXES_2_IDX[AXES.difference(set(self.c_plane)).pop()] # which ever one isn't in the c_plane tuple! + self.gamma_idx = AXES_2_IDX[ + AXES.difference(set(self.c_plane)).pop() + ] # which ever one isn't in the c_plane tuple! # self.pts = pts.copy() # re-order the columns to a consistent alpha, beta, gamma frame - alpha = pts[:, self.alpha_idx] + alpha = pts[:, self.alpha_idx] beta = pts[:, self.beta_idx] - center[self.beta_idx] gamma = pts[:, self.gamma_idx] - center[self.gamma_idx] - self.radii = np.sqrt(beta**2 + gamma**2) + self.radii = np.sqrt(beta ** 2 + gamma ** 2) # need to get the real part because arctan2 is not complex save # but its ok, becuase these are constants - self.thetas = np.arctan2(gamma.real, beta.real) + self.thetas = np.arctan2(gamma.real, beta.real) self.cos_thetas = np.cos(self.thetas) self.sin_thetas = np.sin(self.thetas) @@ -68,10 +68,10 @@ def __init__(self, pts, center, collapse_into, complex=False): # transformation jacobian to account for the axisymmetric transformation n_pts = len(pts) - row = np.empty(3*n_pts, dtype="int") - col = np.empty(3*n_pts, dtype="int") - data = np.empty(3*n_pts) - # for j in range(n_pts): + row = np.empty(3 * n_pts, dtype="int") + col = np.empty(3 * n_pts, dtype="int") + data = np.empty(3 * n_pts) + # for j in range(n_pts): # # Pt_j_x # row[j] = 0 + 3*j # col[j] = self.alpha_idx + 3*j @@ -86,61 +86,60 @@ def __init__(self, pts, center, collapse_into, complex=False): # data[j+2] = self.cos_thetas[j] # vectorized - idx = 3*np.arange(n_pts, dtype="int") + idx = 3 * np.arange(n_pts, dtype="int") row[0::3] = idx - row[1::3] = 1+idx - row[2::3] = 2+idx + row[1::3] = 1 + idx + row[2::3] = 2 + idx col[0::3] = self.alpha_idx + idx col[1::3] = self.beta_idx + idx col[2::3] = self.beta_idx + idx - data[0::3] = 1. + data[0::3] = 1.0 data[1::3] = self.sin_thetas data[2::3] = self.cos_thetas # derivative of the Cartesian points w.r.t the collapsed axi-symmetric points - self.dPtCdPtA = sparse.coo_matrix((data, (row, col)), - shape=(3*n_pts, 3*n_pts)).tocsr() + self.dPtCdPtA = sparse.coo_matrix((data, (row, col)), shape=(3 * n_pts, 3 * n_pts)).tocsr() # points collapsed into the prescribed plane # self.c_pts_axi = np.vstack((self.alpha, self.radii, np.zeros(self.n_points))).T - if self.complex: + if self.complex: self.c_pts = np.empty((self.n_points, 3), dtype="complex") - else: + else: self.c_pts = np.empty((self.n_points, 3)) - self.c_pts[:, 0] = alpha + self.c_pts[:, 0] = alpha self.c_pts[:, self.beta_idx] = self.radii - self.c_pts[:, self.gamma_idx] = 0. # no need to store zeros + self.c_pts[:, self.gamma_idx] = 0.0 # no need to store zeros - def expand(self, new_c_pts): + def expand(self, new_c_pts): """given new collapsed points, re-expands them into physical space""" - self.c_pts = new_c_pts - if self.complex: + self.c_pts = new_c_pts + if self.complex: pts = np.empty((self.n_points, 3), dtype="complex") - else: + else: pts = np.empty((self.n_points, 3)) - pts[:, self.alpha_idx] = new_c_pts[:, 0] + pts[:, self.alpha_idx] = new_c_pts[:, 0] new_rads = new_c_pts[:, self.beta_idx] - pts[:, self.beta_idx] = new_rads*self.cos_thetas + self.center[self.beta_idx] - pts[:, self.gamma_idx] = new_rads*self.sin_thetas + self.center[self.gamma_idx] + pts[:, self.beta_idx] = new_rads * self.cos_thetas + self.center[self.beta_idx] + pts[:, self.gamma_idx] = new_rads * self.sin_thetas + self.center[self.gamma_idx] return pts class DVGeometryAxi(DVGeometry): """ - A class for manipulating geometry. - + A class for manipulating geometry. + The purpose of the DVGeometry class is to provide a mapping from user-supplied design variables to an arbitrary set of discrete, three-dimensional coordinates. These three-dimensional coordinates can in general represent anything, but will typically be the surface of an aerodynamic mesh, the nodes of a FE mesh or the - nodes of another geometric construct. + nodes of another geometric construct. In a very general sense, DVGeometry performs two primary functions: @@ -148,36 +147,36 @@ class DVGeometryAxi(DVGeometry): 1. Given a new set of design variables, update the three-dimensional coordinates: :math:`X_{DV}\\rightarrow X_{pt}` where :math:`X_{pt}` are the coordinates and :math:`X_{DV}` - are the user variables. + are the user variables. 2. Determine the derivative of the coordinates with respect to the design variables. That is the derivative :math:`\\frac{dX_{pt}}{dX_{DV}}` - + DVGeometry uses the *Free-Form Deformation* approach for goemetry manipulation. The basic idea is the coordinates are *embedded* in a clear-flexible jelly-like block. Then by stretching moving and 'poking' the volume, the coordinates that are embedded inside move - along with overall deformation of the volume. + along with overall deformation of the volume. Parameters ---------- fileName : str filename of FFD file. This must be a ascii formatted plot3D file - in fortran ordering. + in fortran ordering. center : array, size (3,1) The center about which the axisymmetric FFD should be applied. This can be any point along the rotation axis of the body collapse_into: 2-tuple of strings - Two coordinate axes that you wish to collapse your points into. - This should align with the directions you are moving FFD - control points. The first item in the tuple is taken as the rotation - axis for the axi-symmetric coordinate system. So ("x","z") means to - collapse into the x,z plane and use x as the rotational axis. - ("z", "x") means to collapse into the x,z plane and use z as the + Two coordinate axes that you wish to collapse your points into. + This should align with the directions you are moving FFD + control points. The first item in the tuple is taken as the rotation + axis for the axi-symmetric coordinate system. So ("x","z") means to + collapse into the x,z plane and use x as the rotational axis. + ("z", "x") means to collapse into the x,z plane and use z as the rotational axis complex : bool Make the entire object complex. This should **only** be used when - debugging the entire tool-chain with the complex step method. + debugging the entire tool-chain with the complex step method. child : bool Flag to indicate that this object is a child of parent DVGeo object @@ -199,19 +198,19 @@ class DVGeometryAxi(DVGeometry): >>> DVGeo.addGeoDVGlobal('wing_twist', 0.0, twist, lower=-10, upper=10) >>> # Now add local (shape) variables >>> DVGeo.addGeoDVLocal('shape', lower=-0.5, upper=0.5, axis='y') - >>> - """ + >>> + """ - def __init__(self, fileName, center, collapse_into, complex=False, child=False, *args, **kwargs): + def __init__(self, fileName, center, collapse_into, complex=False, child=False, *args, **kwargs): - self.axiTransforms = OrderedDict() # TODO: Why is this ordered? + self.axiTransforms = OrderedDict() # TODO: Why is this ordered? super(DVGeometryAxi, self).__init__(fileName, complex, child, *args, **kwargs) self.center = center self.collapse_into = collapse_into - def addPointSet(self, points, ptName, origConfig=True, **kwargs): + def addPointSet(self, points, ptName, origConfig=True, **kwargs): """ Add a set of coordinates to DVGeometry @@ -222,7 +221,7 @@ def addPointSet(self, points, ptName, origConfig=True, **kwargs): ---------- points : array, size (N,3) The coordinates to embed. These cordinates *should* all - project into the interior of the FFD volume. + project into the interior of the FFD volume. ptName : str A user supplied name to associate with the set of coordinates. This name will need to be provided when @@ -238,7 +237,7 @@ def addPointSet(self, points, ptName, origConfig=True, **kwargs): super(DVGeometryAxi, self).addPointSet(xform.c_pts, ptName, origConfig, **kwargs) - def update(self, ptSetName, childDelta=True, config=None): + def update(self, ptSetName, childDelta=True, config=None): new_c_pts = super(DVGeometryAxi, self).update(ptSetName, childDelta, config) @@ -246,29 +245,23 @@ def update(self, ptSetName, childDelta=True, config=None): coords = xform.expand(new_c_pts) # coords = new_c_pts - return coords + return coords - def computeTotalJacobian(self, ptSetName, config=None): - """ compute the total point jacobian in CSR format since we + def computeTotalJacobian(self, ptSetName, config=None): + """compute the total point jacobian in CSR format since we need this for TACS""" super(DVGeometryAxi, self).computeTotalJacobian(ptSetName, config) - if self.JT[ptSetName] is not None: + if self.JT[ptSetName] is not None: xform = self.axiTransforms[ptSetName] self.JT[ptSetName] = xform.dPtCdPtA.dot(self.JT[ptSetName].T).T # TODO JSG: the computeTotalJacobianFD method is broken in DVGeometry Base class - # def computeTotalJacobianFD(self, ptSetName, config=None): + # def computeTotalJacobianFD(self, ptSetName, config=None): # super(DVGeometryAxi, self).computeTotalJacobianFD(ptSetName, config) # xform = self.axiTransforms[ptSetName] # self.JT[ptSetName] = xform.dPtCdPtA.dot(self.JT[ptSetName].T).T - - - - - - diff --git a/pygeo/DVGeometryESP.py b/pygeo/DVGeometryESP.py index 7c8135ea..51da1ebe 100644 --- a/pygeo/DVGeometryESP.py +++ b/pygeo/DVGeometryESP.py @@ -14,59 +14,64 @@ from scipy.spatial import cKDTree from mpi4py import MPI from pyOCSM import pyOCSM -import pickle +import pickle import os import sys from contextlib import contextmanager + @contextmanager def stdout_redirected(flag, to=os.devnull): - ''' + """ import os with stdout_redirected(to=filename): print("from Python") os.system("echo non-Python applications are also supported") - ''' + """ + def _redirect_stdout(to): - sys.stdout.close() # + implicit flush() - os.dup2(to.fileno(), fd) # fd writes to 'to' file - sys.stdout = os.fdopen(fd, 'w') # Python writes to fd + sys.stdout.close() # + implicit flush() + os.dup2(to.fileno(), fd) # fd writes to 'to' file + sys.stdout = os.fdopen(fd, "w") # Python writes to fd if flag: fd = sys.stdout.fileno() - with os.fdopen(os.dup(fd), 'w') as old_stdout: - with open(to, 'w') as file: + with os.fdopen(os.dup(fd), "w") as old_stdout: + with open(to, "w") as file: _redirect_stdout(to=file) try: - yield # allow code to be run with the redirected stdout + yield # allow code to be run with the redirected stdout finally: - _redirect_stdout(to=old_stdout) # restore stdout. - # buffering and flags such as - # CLOEXEC may be different + _redirect_stdout(to=old_stdout) # restore stdout. + # buffering and flags such as + # CLOEXEC may be different else: yield + class Error(Exception): """ Format the error message in a box to make it clear this was a explicitly raised exception. """ + def __init__(self, message): - msg = '\n+'+'-'*78+'+'+'\n' + '| DVGeometryESP Error: ' + msg = "\n+" + "-" * 78 + "+" + "\n" + "| DVGeometryESP Error: " i = 22 for word in message.split(): - if len(word) + i + 1 > 78: # Finish line and start new one - msg += ' '*(78-i)+'|\n| ' + word + ' ' - i = 1 + len(word)+1 + if len(word) + i + 1 > 78: # Finish line and start new one + msg += " " * (78 - i) + "|\n| " + word + " " + i = 1 + len(word) + 1 else: - msg += word + ' ' - i += len(word)+1 - msg += ' '*(78-i) + '|\n' + '+'+'-'*78+'+'+'\n' + msg += word + " " + i += len(word) + 1 + msg += " " * (78 - i) + "|\n" + "+" + "-" * 78 + "+" + "\n" print(msg) Exception.__init__(self) + class DVGeometryESP(object): """ A class for manipulating Engineering Sketchpad (ESP) geometry @@ -76,7 +81,7 @@ class DVGeometryESP(object): framework. There are several import limitations: 1. Since ESP is surface based only, it cannot be used to - parameterize a geometry that doesn't lie on the surface. + parameterize a geometry that doesn't lie on the surface. Structural members need to be directly modeled in ESP as surfaces. 2. It cannot handle *moving* intersection. A geometry with static intersections is fine as long as the intersection doesn't move @@ -86,7 +91,7 @@ class DVGeometryESP(object): Parameters ---------- espFile : str - filename of .csm file containing the parameterized CAD + filename of .csm file containing the parameterized CAD comm : MPI Intra Comm Comm on which to build operate the object. This is used to perform embarasisngly parallel finite differencing. Defaults to @@ -96,7 +101,7 @@ class DVGeometryESP(object): geometry. For example, if the ESP model is in inches, and the CFD in meters, scale=0.0254. bodies : list of strings - A list of the names of the ESP bodies to consider. + A list of the names of the ESP bodies to consider. They need to be on the top of the ESP body stack (i.e., visible in the ESP user interface when all the branches are built) projTol : float @@ -121,11 +126,21 @@ class DVGeometryESP(object): >>> DVGeo.addPointSet(Xpt, 'myPoints') >>> """ - def __init__(self, espFile, comm=MPI.COMM_WORLD, scale=1.0, bodies=[], - projTol=0.01, debug=False, maxproc=None, suppress_stdout=False, - exclude_edge_projections=False, - ulimits=None, - vlimits=None): + + def __init__( + self, + espFile, + comm=MPI.COMM_WORLD, + scale=1.0, + bodies=[], + projTol=0.01, + debug=False, + maxproc=None, + suppress_stdout=False, + exclude_edge_projections=False, + ulimits=None, + vlimits=None, + ): if comm.rank == 0: print("Initializing DVGeometryESP") @@ -136,22 +151,24 @@ def __init__(self, espFile, comm=MPI.COMM_WORLD, scale=1.0, bodies=[], self.pointSets = OrderedDict() self.updated = {} self.updatedJac = {} - self.globalDVList = [] # will become a list of tuples with (DVName, localIndex) - used for finite difference load balancing + self.globalDVList = ( + [] + ) # will become a list of tuples with (DVName, localIndex) - used for finite difference load balancing self.suppress_stdout = suppress_stdout self.exclude_edge_projections = exclude_edge_projections # this scales coordinates from esp to mesh geometry self.espScale = scale # and this scales coordinates from mesh to esp geometry - self.meshScale = 1./scale - self.projTol = projTol*self.meshScale # default input is in meters. + self.meshScale = 1.0 / scale + self.projTol = projTol * self.meshScale # default input is in meters. if ulimits is not None: self.ulimits = ulimits else: - self.ulimits = numpy.array([-99999.,99999.]) + self.ulimits = numpy.array([-99999.0, 99999.0]) if vlimits is not None: self.vlimits = vlimits else: - self.vlimits = numpy.array([-99999.,99999.]) + self.vlimits = numpy.array([-99999.0, 99999.0]) self.comm = comm self.espFile = espFile self.debug = debug @@ -165,34 +182,38 @@ def __init__(self, espFile, comm=MPI.COMM_WORLD, scale=1.0, bodies=[], pyOCSM.SetOutLevel(0) else: pyOCSM.SetOutLevel(0) - self.num_branches_baseline, _, allBodyIndices = self.espModel.Build(0,200) #pick 200 as arbitrary large number of bodies to allocate + self.num_branches_baseline, _, allBodyIndices = self.espModel.Build( + 0, 200 + ) # pick 200 as arbitrary large number of bodies to allocate if self.num_branches_baseline < 0: - raise ValueError('It appears the initial build of the ESP model did not succeed') + raise ValueError("It appears the initial build of the ESP model did not succeed") t2 = time.time() if self.comm.rank == 0: - print('Loading the esp model took:', (t2-t1)) + print("Loading the esp model took:", (t2 - t1)) # List of all bodies returned from ESP if not bodies: # no components specified, we use all - self.bodyIndices= allBodyIndices + self.bodyIndices = allBodyIndices else: - raise NotImplementedError('Specifying bodies by name still needs to be ported from the new pyOCSM wrapper.') + raise NotImplementedError("Specifying bodies by name still needs to be ported from the new pyOCSM wrapper.") # we get the comps from the comps list self.bodyIndices = [] for bodyIndex in allBodyIndices: try: # TODO BB this is missing from new wrapper and needs to be reimplemented completely - this_body_name = self.espModel.getTopoAttr(bodyIndex, 'body')['_name'] + this_body_name = self.espModel.getTopoAttr(bodyIndex, "body")["_name"] except KeyError: # no _name attribute, make a default - this_body_name = 'body'+str(bodyIndex) + this_body_name = "body" + str(bodyIndex) if this_body_name in bodies: self.bodyIndices.append(bodyIndex) if len(self.bodyIndices) == 0: - raise Error('No bodies matching the provided body names were found. \ - Check that _name attributes are set correctly in the ESP model') + raise Error( + "No bodies matching the provided body names were found. \ + Check that _name attributes are set correctly in the ESP model" + ) # Initial list of DVs self.DVs = OrderedDict() @@ -206,32 +227,33 @@ def __init__(self, espFile, comm=MPI.COMM_WORLD, scale=1.0, bodies=[], while pmtrsleft: try: pmtrIndex += 1 - pmtrType, numRow, numCol, pmtrName= self.espModel.GetPmtr(pmtrIndex) - baseValue = numpy.zeros(numRow*numCol) + pmtrType, numRow, numCol, pmtrName = self.espModel.GetPmtr(pmtrIndex) + baseValue = numpy.zeros(numRow * numCol) for rowIdx in range(numRow): for colIdx in range(numCol): try: - baseValue[colIdx+numCol*rowIdx] = self.espModel.GetValu(pmtrIndex, rowIdx+1, colIdx+1)[0] + baseValue[colIdx + numCol * rowIdx] = self.espModel.GetValu( + pmtrIndex, rowIdx + 1, colIdx + 1 + )[0] except pyOCSM.OcsmError as e: - if e.value == 'ILLEGAL_PTMR_INDEX': + if e.value == "ILLEGAL_PTMR_INDEX": # I don't think we should ever make it here if the GetPmtr check is correct - raise Error('Column or row index out of range in design parameter '+pmtrName) - + raise Error("Column or row index out of range in design parameter " + pmtrName) + if pmtrType == ocsmExternal: self.csmDesPmtrs[pmtrName] = ESPParameter(pmtrName, pmtrIndex, numRow, numCol, baseValue) except pyOCSM.OcsmError as e: - if e.value == 'ILLEGAL_PMTR_INDEX': + if e.value == "ILLEGAL_PMTR_INDEX": pmtrsleft = False else: raise e if pmtrIndex == 1: if comm.rank == 0: - print('DVGeometryESP Warning: no design parameters defined in the CSM file') + print("DVGeometryESP Warning: no design parameters defined in the CSM file") if comm.rank == 0: t3 = time.time() - print("Initialized DVGeometryESP in",(t3-t0),"seconds.") - + print("Initialized DVGeometryESP in", (t3 - t0), "seconds.") def addPointSet(self, points, ptName, distributed=True, cache_projections=False, **kwargs): """ @@ -264,40 +286,43 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, """ # save this name so that we can zero out the jacobians properly - self.points[ptName] = True # ADFlow checks self.points to see - # if something is added or not. - points = numpy.array(points).real.astype('d') + self.points[ptName] = True # ADFlow checks self.points to see + # if something is added or not. + points = numpy.array(points).real.astype("d") # check that duplicated pointsets are actually the same length - sizes = numpy.array(self.comm.allgather(points.shape[0]), dtype = 'intc') + sizes = numpy.array(self.comm.allgather(points.shape[0]), dtype="intc") if not distributed: all_same_length = numpy.all(sizes == sizes[0]) if not all_same_length: - raise ValueError('Nondistributed pointsets must be identical on each proc, but these pointsets vary in length per proc. Lengths: ', str(sizes)) - - # check if a cache file exists + raise ValueError( + "Nondistributed pointsets must be identical on each proc, but these pointsets vary in length per proc. Lengths: ", + str(sizes), + ) + + # check if a cache file exists cache_loaded = False # cache_projections=False will disable caching, but None will generate a cachefile name automatically if cache_projections is None: - cache_projections = ptName+'.npz' - + cache_projections = ptName + ".npz" + if cache_projections: if os.path.isfile(cache_projections): cache_loaded = True if self.comm.rank == 0: cached_pt_arrays = numpy.load(cache_projections) - cached_sizes = cached_pt_arrays['sizes'] - cached_nprocs = cached_pt_arrays['nprocs'] - cached_distrib = cached_pt_arrays['distributed'] - bodyIDg = cached_pt_arrays['bodyID'] - faceIDg = cached_pt_arrays['faceID'] - edgeIDg = cached_pt_arrays['edgeID'] - ug = cached_pt_arrays['u'] - vg = cached_pt_arrays['v'] - tg = cached_pt_arrays['t'] - uvlimg = cached_pt_arrays['uvlimits'] - tlimg = cached_pt_arrays['tlimits'] - cached_dmax = cached_pt_arrays['dmax'] + cached_sizes = cached_pt_arrays["sizes"] + cached_nprocs = cached_pt_arrays["nprocs"] + cached_distrib = cached_pt_arrays["distributed"] + bodyIDg = cached_pt_arrays["bodyID"] + faceIDg = cached_pt_arrays["faceID"] + edgeIDg = cached_pt_arrays["edgeID"] + ug = cached_pt_arrays["u"] + vg = cached_pt_arrays["v"] + tg = cached_pt_arrays["t"] + uvlimg = cached_pt_arrays["uvlimits"] + tlimg = cached_pt_arrays["tlimits"] + cached_dmax = cached_pt_arrays["dmax"] else: cached_dmax = 0.0 cached_sizes = 0.0 @@ -311,39 +336,55 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, # find easy cache invalidations: if distributed: if not cached_distrib: - raise ValueError('Cached pointset file ', cache_projections, ' is invalid because the cache was saved for a nondistributed pointset') + raise ValueError( + "Cached pointset file ", + cache_projections, + " is invalid because the cache was saved for a nondistributed pointset", + ) if cached_nprocs != self.comm.size: - raise ValueError('Cached pointset file ', cache_projections, ' is invalid because the cache was saved with different num procs') + raise ValueError( + "Cached pointset file ", + cache_projections, + " is invalid because the cache was saved with different num procs", + ) if not numpy.all(cached_sizes == sizes): - raise ValueError('Cached pointset file ', cache_projections, ' is invalid because point counts have changed on some proc') + raise ValueError( + "Cached pointset file ", + cache_projections, + " is invalid because point counts have changed on some proc", + ) else: if cached_distrib: - raise ValueError('Cached pointset file ', cache_projections, ' is invalid because the cache was saved for a distributed pointset') + raise ValueError( + "Cached pointset file ", + cache_projections, + " is invalid because the cache was saved for a distributed pointset", + ) # now figure out which proc has how many points. - + nptsl = points.shape[0] # set up recieve buffers for all procs - faceIDl = numpy.zeros(nptsl, dtype='intc') - bodyIDl = numpy.zeros(nptsl, dtype='intc') - edgeIDl = numpy.zeros(nptsl, dtype='intc') + faceIDl = numpy.zeros(nptsl, dtype="intc") + bodyIDl = numpy.zeros(nptsl, dtype="intc") + edgeIDl = numpy.zeros(nptsl, dtype="intc") ul = numpy.zeros(nptsl) vl = numpy.zeros(nptsl) tl = numpy.zeros(nptsl) - uvliml = numpy.zeros((nptsl, 4)) - tliml = numpy.zeros((nptsl, 2)) - - recvbuf1 = [bodyIDl, MPI.INT] - recvbuf2 = [faceIDl, MPI.INT] - recvbuf3 = [edgeIDl, MPI.INT] - recvbuf4 = [ul, MPI.DOUBLE] - recvbuf5 = [vl, MPI.DOUBLE] - recvbuf6 = [tl, MPI.DOUBLE] - recvbuf7 = [uvliml, MPI.DOUBLE] - recvbuf8 = [tliml, MPI.DOUBLE] + uvliml = numpy.zeros((nptsl, 4)) + tliml = numpy.zeros((nptsl, 2)) + + recvbuf1 = [bodyIDl, MPI.INT] + recvbuf2 = [faceIDl, MPI.INT] + recvbuf3 = [edgeIDl, MPI.INT] + recvbuf4 = [ul, MPI.DOUBLE] + recvbuf5 = [vl, MPI.DOUBLE] + recvbuf6 = [tl, MPI.DOUBLE] + recvbuf7 = [uvliml, MPI.DOUBLE] + recvbuf8 = [tliml, MPI.DOUBLE] if distributed: # displacements for scatter - disp = numpy.array([numpy.sum(sizes[:i]) for i in range(self.comm.size)], dtype='intc') + disp = numpy.array([numpy.sum(sizes[:i]) for i in range(self.comm.size)], dtype="intc") nptsg = numpy.sum(sizes) if self.comm.rank == 0: sendbuf1 = [bodyIDg, sizes, disp, MPI.INT] @@ -352,8 +393,8 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, sendbuf4 = [ug, sizes, disp, MPI.DOUBLE] sendbuf5 = [vg, sizes, disp, MPI.DOUBLE] sendbuf6 = [tg, sizes, disp, MPI.DOUBLE] - sendbuf7 = [uvlimg, sizes*4, disp*4, MPI.DOUBLE] - sendbuf8 = [tlimg, sizes*2, disp*2, MPI.DOUBLE] + sendbuf7 = [uvlimg, sizes * 4, disp * 4, MPI.DOUBLE] + sendbuf8 = [tlimg, sizes * 2, disp * 2, MPI.DOUBLE] else: sendbuf1 = sendbuf2 = sendbuf3 = sendbuf4 = sendbuf5 = sendbuf6 = sendbuf7 = sendbuf8 = None @@ -378,8 +419,8 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, ul[:] = ug[:] vl[:] = vg[:] tl[:] = tg[:] - uvliml[:,:] = uvlimg[:,:] - tliml[:,:] = tlimg[:,:] + uvliml[:, :] = uvlimg[:, :] + tliml[:, :] = tlimg[:, :] self.comm.Bcast(recvbuf1, root=0) self.comm.Bcast(recvbuf2, root=0) self.comm.Bcast(recvbuf3, root=0) @@ -391,23 +432,24 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, nPts = len(points) if nPts != ul.shape[0]: - raise ValueError('Cached point projections does not match length of point set') + raise ValueError("Cached point projections does not match length of point set") - # go through and check that each point projects + # go through and check that each point projects # within tolerance or else invalidate the cached values proj_pts = self._evaluatePoints(ul, vl, tl, uvliml, tliml, bodyIDl, faceIDl, edgeIDl, nPts) if points.shape[0] == 0: # empty pointset can occur for some distributed pointsets dMax_local = 0.0 else: - dMax_local = numpy.max(numpy.sqrt(numpy.sum((points-proj_pts)**2, axis=1))) + dMax_local = numpy.max(numpy.sqrt(numpy.sum((points - proj_pts) ** 2, axis=1))) dMax_global = self.comm.allreduce(dMax_local, op=MPI.MAX) - if (dMax_global - cached_dmax) / cached_dmax >= 1e-3: - raise ValueError('The cached point projections appear to no longer be valid for this geometry') - uvl = numpy.column_stack([ul,vl]) - self.pointSets[ptName] = PointSet(points, proj_pts, bodyIDl, faceIDl, edgeIDl, uvl, tl, uvliml, tliml, distributed) + raise ValueError("The cached point projections appear to no longer be valid for this geometry") + uvl = numpy.column_stack([ul, vl]) + self.pointSets[ptName] = PointSet( + points, proj_pts, bodyIDl, faceIDl, edgeIDl, uvl, tl, uvliml, tliml, distributed + ) # Set the updated flag to false because the jacobian is not up to date. self.updated[ptName] = False self.updatedJac[ptName] = False @@ -422,18 +464,18 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, proj_pts_esp = numpy.zeros_like(points) npoints = len(points) - bodyIDArray = numpy.zeros(npoints, dtype='intc') - faceIDArray = numpy.zeros(npoints, dtype='intc') - edgeIDArray = numpy.zeros(npoints, dtype='intc') + bodyIDArray = numpy.zeros(npoints, dtype="intc") + faceIDArray = numpy.zeros(npoints, dtype="intc") + edgeIDArray = numpy.zeros(npoints, dtype="intc") uv = numpy.zeros((npoints, 2)) t = numpy.zeros(npoints) uvlimArray = numpy.zeros((npoints, 4)) tlimArray = numpy.zeros((npoints, 2)) - dists = numpy.ones((npoints), dtype='float_')*999999.0 + dists = numpy.ones((npoints), dtype="float_") * 999999.0 t1 = time.time() - # TODO parallelize projections for nondistributed pointsets? - + # TODO parallelize projections for nondistributed pointsets? + # we want to reject points that are far outside the trimmed surface # and slightly prefer surface projections to edge projections rejectuvtol = 1e-4 @@ -452,17 +494,17 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, nEdges = self.espModel.GetBody(bodyIndex)[6] nFaces = self.espModel.GetBody(bodyIndex)[7] if not self.exclude_edge_projections: - for edgeIndex in range(1,nEdges+1): + for edgeIndex in range(1, nEdges + 1): # try to match point on edges first with stdout_redirected(self.suppress_stdout): # get the parametric coordinate along the edge ttemp = self.espModel.GetUV(bodyIndex, pyOCSM.EDGE, edgeIndex, 1, truexyz.tolist()) # get the xyz location of the newly projected point xyztemp = numpy.array(self.espModel.GetXYZ(bodyIndex, pyOCSM.EDGE, edgeIndex, 1, ttemp)) - dist_temp = numpy.sum((truexyz - xyztemp)**2) + dist_temp = numpy.sum((truexyz - xyztemp) ** 2) ttemp = ttemp[0] tlimits = self._getUVLimits(bodyIndex, pyOCSM.EDGE, edgeIndex) - if not(ttemp < tlimits[0]-rejectuvtol or ttemp > tlimits[1]+rejectuvtol): + if not (ttemp < tlimits[0] - rejectuvtol or ttemp > tlimits[1] + rejectuvtol): if dist_temp < dist_best: tlimits_best = tlimits t_best = ttemp @@ -471,19 +513,29 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, dist_best = dist_temp xyzbest = xyztemp.copy() - for faceIndex in range(1,nFaces+1): + for faceIndex in range(1, nFaces + 1): with stdout_redirected(self.suppress_stdout): # get the projected points on the ESP surface in UV coordinates uvtemp = self.espModel.GetUV(bodyIndex, pyOCSM.FACE, faceIndex, 1, truexyz.tolist()) # get the XYZ location of the newly projected points xyztemp = numpy.array(self.espModel.GetXYZ(bodyIndex, pyOCSM.FACE, faceIndex, 1, uvtemp)) - dist_temp = numpy.sum((truexyz - xyztemp)**2) + dist_temp = numpy.sum((truexyz - xyztemp) ** 2) # validate u and v utemp = uvtemp[0] vtemp = uvtemp[1] uvlimits = self._getUVLimits(bodyIndex, pyOCSM.FACE, faceIndex) - if not(utemp < uvlimits[0]-rejectuvtol or utemp > uvlimits[1] + rejectuvtol or vtemp < uvlimits[2]-rejectuvtol or vtemp > uvlimits[3] + rejectuvtol): - if not (utemp < self.ulimits[0] or utemp > self.ulimits[1] or vtemp < self.vlimits[0] or vtemp > self.vlimits[1]): + if not ( + utemp < uvlimits[0] - rejectuvtol + or utemp > uvlimits[1] + rejectuvtol + or vtemp < uvlimits[2] - rejectuvtol + or vtemp > uvlimits[3] + rejectuvtol + ): + if not ( + utemp < self.ulimits[0] + or utemp > self.ulimits[1] + or vtemp < self.vlimits[0] + or vtemp > self.vlimits[1] + ): if dist_temp - edgetol < dist_best: uvlimits_best = uvlimits uv_best = [utemp, vtemp] @@ -497,34 +549,36 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, xyzbest = xyztemp.copy() if dist_best == 99999999999: # all projections failed: this shouldn't occur unless the uv limits are set too tight - raise ValueError('All projections failed for this point. Check ulimits and vlimits') + raise ValueError("All projections failed for this point. Check ulimits and vlimits") faceIDArray[ptidx] = fi_best edgeIDArray[ptidx] = ei_best bodyIDArray[ptidx] = bi_best uvlimArray[ptidx, :] = numpy.array(uvlimits_best) tlimArray[ptidx, :] = numpy.array(tlimits_best) - uv[ptidx,0] = uv_best[0] - uv[ptidx,1] = uv_best[1] + uv[ptidx, 0] = uv_best[0] + uv[ptidx, 1] = uv_best[1] t[ptidx] = t_best dists[ptidx] = dist_best - proj_pts_esp[ptidx,:] = xyzbest - + proj_pts_esp[ptidx, :] = xyzbest + proj_pts = proj_pts_esp * self.espScale if points.shape[0] != 0: - dMax = numpy.max(numpy.sqrt(numpy.sum((points-proj_pts)**2, axis=1))) + dMax = numpy.max(numpy.sqrt(numpy.sum((points - proj_pts) ** 2, axis=1))) else: dMax = 0.0 - + dMax_global = self.comm.allreduce(dMax, op=MPI.MAX) t2 = time.time() if self.comm.rank == 0 or self.comm is None: - print('Adding pointset',ptName, 'took', t2-t1, 'seconds.') - print('Maximum distance between the added points and the ESP geometry is',dMax_global) + print("Adding pointset", ptName, "took", t2 - t1, "seconds.") + print("Maximum distance between the added points and the ESP geometry is", dMax_global) if dMax_global > self.projTol: - raise ValueError('Pointset projection error exceeded tolerance') + raise ValueError("Pointset projection error exceeded tolerance") # Create the little class with the data - self.pointSets[ptName] = PointSet(points, proj_pts, bodyIDArray, faceIDArray, edgeIDArray, uv, t, uvlimArray, tlimArray, distributed) + self.pointSets[ptName] = PointSet( + points, proj_pts, bodyIDArray, faceIDArray, edgeIDArray, uv, t, uvlimArray, tlimArray, distributed + ) # Set the updated flag to false because the jacobian is not up to date. self.updated[ptName] = False @@ -532,13 +586,15 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, if cache_projections and not cache_loaded: # get the global projections and save in compressed npz format - ul = uv[:,0].copy() - vl = uv[:,1].copy() + ul = uv[:, 0].copy() + vl = uv[:, 1].copy() if distributed: - ug, vg, tg, faceIDg, bodyIDg, edgeIDg, uvlimitsg, tlimitsg, sizes = self._allgatherCoordinates(ul,vl,t,faceIDArray,bodyIDArray,edgeIDArray,uvlimArray,tlimArray) + ug, vg, tg, faceIDg, bodyIDg, edgeIDg, uvlimitsg, tlimitsg, sizes = self._allgatherCoordinates( + ul, vl, t, faceIDArray, bodyIDArray, edgeIDArray, uvlimArray, tlimArray + ) else: ug = ul - vg = vl + vg = vl tg = t faceIDg = faceIDArray bodyIDg = bodyIDArray @@ -547,7 +603,21 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, tlimitsg = tlimArray sizes = np.array([len(ug)]) if self.comm.rank == 0: - numpy.savez_compressed(cache_projections, distributed=distributed, sizes=sizes, nprocs=self.comm.size, dmax=dMax_global, u=ug, v=vg, t=tg, faceID=faceIDg, bodyID=bodyIDg, edgeID=edgeIDg, uvlimits=uvlimitsg, tlimits=tlimitsg) + numpy.savez_compressed( + cache_projections, + distributed=distributed, + sizes=sizes, + nprocs=self.comm.size, + dmax=dMax_global, + u=ug, + v=vg, + t=tg, + faceID=faceIDg, + bodyID=bodyIDg, + edgeID=edgeIDg, + uvlimits=uvlimitsg, + tlimits=tlimitsg, + ) return dMax_global @@ -561,7 +631,7 @@ def setDesignVars(self, dvDict, updateJacobian=True): Dictionary of design variables. The keys of the dictionary must correspond to the design variable names. Any additional keys in the dfvdictionary are simply ignored. - """ + """ # Just dump in the values for key in dvDict: @@ -592,35 +662,25 @@ def setDesignVars(self, dvDict, updateJacobian=True): self.updatedJac[ptName] = False return built_successfully - def writeCADFile(self, filename): - valid_filetypes = ['brep', - 'bstl', - 'egads', - 'egg', - 'iges', - 'igs', - 'sens', - 'step', - 'stl', - 'stp', - 'tess', - 'grid'] - splitfile = filename.split('.') - file_extension = filename.split('.')[-1] + valid_filetypes = ["brep", "bstl", "egads", "egg", "iges", "igs", "sens", "step", "stl", "stp", "tess", "grid"] + splitfile = filename.split(".") + file_extension = filename.split(".")[-1] if file_extension.lower() not in valid_filetypes: - raise IOError('CAD filename ' + filename + ' must have a valid exension. ' + - 'Consult the EngineeringSketchPad docs for the DUMP function') + raise IOError( + "CAD filename " + + filename + + " must have a valid exension. " + + "Consult the EngineeringSketchPad docs for the DUMP function" + ) if self.comm.rank == 0: modelCopy = self.espModel.Copy() n_branches, _, _ = modelCopy.Info() - modelCopy.NewBrch(n_branches, - modelCopy.GetCode("dump"), - "", - 0, - filename, "0", "0", "", "", "", "", "", "") + modelCopy.NewBrch( + n_branches, modelCopy.GetCode("dump"), "", 0, filename, "0", "0", "", "", "", "", "", "" + ) modelCopy.Build(0, 0) - + def getValues(self): """ Generic routine to return the current set of design @@ -648,10 +708,10 @@ def update(self, ptSetName, config=None): Name of point-set to return. This must match ones of the given in an :func:`addPointSet()` call. """ - + # this returns the current projection point coordinates newPts = self.pointSets[ptSetName].proj_pts - + if not self.updated[ptSetName]: # get the offset between points and original projected points offset = self.pointSets[ptSetName].offset @@ -673,12 +733,11 @@ def update(self, ptSetName, config=None): return newPts def writeCSMFile(self, fileName): - valid_filetypes = ['csm'] - if fileName.split('.')[-1] not in valid_filetypes: + valid_filetypes = ["csm"] + if fileName.split(".")[-1] not in valid_filetypes: raise IOError('Must use ".csm" file extension') if self.comm.rank == 0: self.espModel.Save(fileName) - def pointSetUpToDate(self, ptSetName): """ @@ -700,7 +759,7 @@ def pointSetUpToDate(self, ptSetName): return True def getNDV(self): - """ + """ Return the number of DVs""" return len(self.globalDVList) @@ -714,12 +773,11 @@ def getVarNames(self): """ return list(self.DVs.keys()) - def totalSensitivity(self, dIdpt, ptSetName, comm=None, config=None): """ This function computes sensitivty information. Specificly, it computes the following: - :math:`\\frac{dI}{d_{pt}}\\frac{dX_{pt}}{dX_{DV}} + :math:`\\frac{dI}{d_{pt}}\\frac{dX_{pt}}{dX_{DV}} Parameters ---------- dIdpt : array of size (Npt, 3) or (N, Npt, 3) @@ -772,7 +830,7 @@ def totalSensitivity(self, dIdpt, ptSetName, comm=None, config=None): # a copy because we may need to modify it. # reshape the dIdpt array from [N] * [nPt] * [3] to [N] * [nPt*3] - dIdpt = dIdpt.reshape((dIdpt.shape[0], dIdpt.shape[1]*3)) + dIdpt = dIdpt.reshape((dIdpt.shape[0], dIdpt.shape[1] * 3)) # # transpose dIdpt and vstack; # # Now vstack the result with seamBar as that is far as the @@ -848,12 +906,13 @@ def totalSensitivityProd(self, vec, ptSetName, comm=None, config=None): if comm: dPt = comm.allreduce(dPtlocal, op=MPI.SUM) else: - dPt = dPtlocal + dPt = dPtlocal return dPt - def addVariable(self, desmptr_name, name=None, value=None, - lower=None, upper=None, scale=1.0, rows=None, cols=None, dh=0.001): + def addVariable( + self, desmptr_name, name=None, value=None, lower=None, upper=None, scale=1.0, rows=None, cols=None, dh=0.001 + ): """ Add an ESP design parameter to the DVGeo problem definition. The name of the parameter must match a despmtr in the .csm file @@ -888,7 +947,7 @@ def addVariable(self, desmptr_name, name=None, value=None, scale : float Scale factor sent to pyOptSparse and used in optimization rows : list or None - Design variable row index(indices) to use. + Design variable row index(indices) to use. Default None uses all rows cols : list or None Design variable col index(indices) to use. @@ -903,12 +962,13 @@ def addVariable(self, desmptr_name, name=None, value=None, dvName = desmptr_name if dvName in self.DVs.keys(): - raise Error('Design variable name '+dvName+' already in use.') + raise Error("Design variable name " + dvName + " already in use.") # find the design parm index in ESP if desmptr_name not in self.csmDesPmtrs.keys(): - raise Error('User specified design parameter name "' - + desmptr_name + '" which was not found in the CSM file') + raise Error( + 'User specified design parameter name "' + desmptr_name + '" which was not found in the CSM file' + ) csmDesPmtr = self.csmDesPmtrs[desmptr_name] numRow = csmDesPmtr.numRow @@ -924,37 +984,48 @@ def addVariable(self, desmptr_name, name=None, value=None, value = self._csmToFlat(csmDesPmtr.baseValue, rows, cols, numRow, numCol) else: # validate that it is of correct length - if len(value) != len(rows)*len(cols): - raise Error('User-specified DV value does not match the dimensionality' + - 'of the ESP despmtr. Value is of length ' + str(len(value)) + - ' but should be '+str(len(rows)*len(cols))) + if len(value) != len(rows) * len(cols): + raise Error( + "User-specified DV value does not match the dimensionality" + + "of the ESP despmtr. Value is of length " + + str(len(value)) + + " but should be " + + str(len(rows) * len(cols)) + ) # check that upper and lower are correct length if upper is not None: if isinstance(upper, (float, int)): - upper = numpy.ones((len(rows)*len(cols),))*upper - if len(upper) != len(rows)*len(cols): - raise Error('User-specified DV upper bound does not match the dimensionality' + - 'of the ESP despmtr. Upper is of length ' + str(len(upper)) + - ' but should be '+str(len(rows)*len(cols))) + upper = numpy.ones((len(rows) * len(cols),)) * upper + if len(upper) != len(rows) * len(cols): + raise Error( + "User-specified DV upper bound does not match the dimensionality" + + "of the ESP despmtr. Upper is of length " + + str(len(upper)) + + " but should be " + + str(len(rows) * len(cols)) + ) if lower is not None: if isinstance(lower, (float, int)): - lower = numpy.ones((len(rows)*len(cols),))*lower - if len(lower) != len(rows)*len(cols): - raise Error('User-specified DV lower bound does not match the dimensionality' + - 'of the ESP despmtr. lower is of length ' + str(len(lower)) + - ' but should be '+str(len(rows)*len(cols))) - nVal = len(rows)*len(cols) - + lower = numpy.ones((len(rows) * len(cols),)) * lower + if len(lower) != len(rows) * len(cols): + raise Error( + "User-specified DV lower bound does not match the dimensionality" + + "of the ESP despmtr. lower is of length " + + str(len(lower)) + + " but should be " + + str(len(rows) * len(cols)) + ) + nVal = len(rows) * len(cols) + # add an entry in the global DV list to make finite differencing load balancing easy globalStartInd = len(self.globalDVList) for localInd in range(nVal): self.globalDVList.append((dvName, localInd)) - self.DVs[dvName] = espDV(csmDesPmtr, dvName, - value, lower, upper, scale, rows, cols, dh, globalStartInd) + self.DVs[dvName] = espDV(csmDesPmtr, dvName, value, lower, upper, scale, rows, cols, dh, globalStartInd) def addVariablesPyOpt(self, optProb): """ @@ -967,13 +1038,11 @@ def addVariablesPyOpt(self, optProb): for dvName in self.DVs: dv = self.DVs[dvName] - optProb.addVarGroup(dv.name, dv.nVal, 'c', value=dv.value, - lower=dv.lower, upper=dv.upper, - scale=dv.scale) + optProb.addVarGroup(dv.name, dv.nVal, "c", value=dv.value, lower=dv.lower, upper=dv.upper, scale=dv.scale) -# # ---------------------------------------------------------------------- -# # THE REMAINDER OF THE FUNCTIONS NEED NOT BE CALLED BY THE USER -# # ---------------------------------------------------------------------- + # # ---------------------------------------------------------------------- + # # THE REMAINDER OF THE FUNCTIONS NEED NOT BE CALLED BY THE USER + # # ---------------------------------------------------------------------- def _getUVLimits(self, ibody, seltype, iselect): """ @@ -988,7 +1057,7 @@ def _getUVLimits(self, ibody, seltype, iselect): pyOCSM.EDGE or pyOCSM.FACE iselect : int Index of edge or face - + Outputs ------- uvlimits : list @@ -1005,60 +1074,82 @@ def _csmToFlat(self, value, rows, cols, numRow, numCol): if numRow == 1 and numCol == 1: # early exit for scalars valOut = value - elif len(value) == len(rows)*len(cols): + elif len(value) == len(rows) * len(cols): # early exit for non-sliced arrays valOut = value - else: - valOut = numpy.zeros(len(rows)*len(cols)) + else: + valOut = numpy.zeros(len(rows) * len(cols)) irow = 0 for rowInd in rows: icol = 0 for colInd in cols: - valOut[icol + irow*len(cols)] = value[(colInd-1) + numCol*(rowInd-1)] + valOut[icol + irow * len(cols)] = value[(colInd - 1) + numCol * (rowInd - 1)] icol += 1 irow += 1 return valOut - + def _validateRowCol(self, rows, cols, numRow, numCol, dvName): # check that all rows, cols specified are within desmptr bounds # check for duplicate rows, cols if rows is not None: rowArr = numpy.array(rows) if numpy.max(rowArr) > numRow: - raise Error('Design variable ' + dvName + ' slice out of bounds. ' + - 'Design var has '+str(numRow) + ' rows and index up to ' + - str(numpy.max(rowArr)) + ' was specified: ' + - str(rows)) + raise Error( + "Design variable " + + dvName + + " slice out of bounds. " + + "Design var has " + + str(numRow) + + " rows and index up to " + + str(numpy.max(rowArr)) + + " was specified: " + + str(rows) + ) if numpy.min(rowArr) < 1: - raise Error('Design variable ' + dvName + ' slice out of bounds. ' + - 'Row index less than 1 specified: ' + str(rows)) + raise Error( + "Design variable " + + dvName + + " slice out of bounds. " + + "Row index less than 1 specified: " + + str(rows) + ) if len(rows) != len(set(rows)): # duplicates - raise Error('Duplicate indices specified in the rows of design variable '+ - dvName + ': '+str(rows)) + raise Error("Duplicate indices specified in the rows of design variable " + dvName + ": " + str(rows)) if cols is not None: colArr = numpy.array(cols) if numpy.max(colArr) > numCol: - raise Error('Design variable ' + dvName + ' slice out of bounds. ' + - 'Design var has '+str(numCol) + ' cols and index up to ' + - str(numpy.max(colArr)) + ' was specified: ' + - str(cols)) + raise Error( + "Design variable " + + dvName + + " slice out of bounds. " + + "Design var has " + + str(numCol) + + " cols and index up to " + + str(numpy.max(colArr)) + + " was specified: " + + str(cols) + ) if numpy.min(colArr) < 1: - raise Error('Design variable ' + dvName + ' slice out of bounds. ' + - 'col index less than 1 specified: ' + str(cols)) + raise Error( + "Design variable " + + dvName + + " slice out of bounds. " + + "col index less than 1 specified: " + + str(cols) + ) if len(cols) != len(set(cols)): # duplicates - raise Error('Duplicate indices specified in the cols of design variable '+ - dvName + ': '+str(cols)) - + raise Error("Duplicate indices specified in the cols of design variable " + dvName + ": " + str(cols)) + def _updateESPModel(self): """ Sets design parameters in ESP to the correct value then rebuilds the model. """ # for each design variable in the dictionary: - + # loop through rows and cols setting design paramter values for dvName in self.DVs: dv = self.DVs[dvName] @@ -1070,7 +1161,7 @@ def _updateESPModel(self): espColIdx = dv.cols[colIdx] self.espModel.SetValuD(espParamIdx, irow=espRowIdx, icol=espColIdx, value=dv.value[localIdx]) # finally, rebuild - outtuple = self.espModel.Build(0,0) + outtuple = self.espModel.Build(0, 0) # check that the number of branches built successfully # matches the number when the model was first built on __init__ # otherwise, there was an EGADS/CSM build failure at this design point @@ -1079,7 +1170,6 @@ def _updateESPModel(self): else: # built correctly return True - def _evaluatePoints(self, u, v, t, uvlimits0, tlimits0, bodyID, faceID, edgeID, nPts): points = numpy.zeros((nPts, 3)) @@ -1097,15 +1187,11 @@ def _evaluatePoints(self, u, v, t, uvlimits0, tlimits0, bodyID, faceID, edgeID, trange0 = tlim0[1] - tlim0[0] trange = tlim[1] - tlim[0] tnew = (t[ptidx] - tlim0[0]) * trange / trange0 + tlim[0] - points[ptidx, :] = self.espModel.GetXYZ(bid, - pyOCSM.EDGE, - eid, - 1, - [tnew]) + points[ptidx, :] = self.espModel.GetXYZ(bid, pyOCSM.EDGE, eid, 1, [tnew]) else: # point from a face if fid == -1: - raise ValueError('both edge ID and face ID are unset') + raise ValueError("both edge ID and face ID are unset") # get the upper and lower uv limits of the updated model uvlim0 = uvlimits0[ptidx] uvlim = self._getUVLimits(bid, pyOCSM.FACE, fid) @@ -1115,12 +1201,8 @@ def _evaluatePoints(self, u, v, t, uvlimits0, tlimits0, bodyID, faceID, edgeID, vrange = uvlim[3] - uvlim[2] # scale the input uv points according to the original uv limits unew = (u[ptidx] - uvlim0[0]) * urange / urange0 + uvlim[0] - vnew = (v[ptidx] - uvlim0[2]) * vrange / vrange0 + uvlim[2] - points[ptidx, :] = self.espModel.GetXYZ(bid, - pyOCSM.FACE, - fid, - 1, - [unew, vnew]) + vnew = (v[ptidx] - uvlim0[2]) * vrange / vrange0 + uvlim[2] + points[ptidx, :] = self.espModel.GetXYZ(bid, pyOCSM.FACE, fid, 1, [unew, vnew]) points = points * self.espScale return points @@ -1130,36 +1212,45 @@ def _updateProjectedPts(self): # update the proj_pts for pointSetName in self.pointSets: pointSet = self.pointSets[pointSetName] - proj_pts = self._evaluatePoints(pointSet.u, pointSet.v, pointSet.t, pointSet.uvlimits0, pointSet.tlimits0, - pointSet.bodyID, pointSet.faceID, pointSet.edgeID, pointSet.nPts) + proj_pts = self._evaluatePoints( + pointSet.u, + pointSet.v, + pointSet.t, + pointSet.uvlimits0, + pointSet.tlimits0, + pointSet.bodyID, + pointSet.faceID, + pointSet.edgeID, + pointSet.nPts, + ) pointSet.proj_pts = proj_pts def _allgatherCoordinates(self, ul, vl, tl, faceIDl, bodyIDl, edgeIDl, uvlimitsl, tlimitsl): # create the arrays to receive the global info # now figure out which proc has how many points. - sizes = numpy.array(self.comm.allgather(len(ul)), dtype = 'intc') + sizes = numpy.array(self.comm.allgather(len(ul)), dtype="intc") # displacements for allgather - disp = numpy.array([numpy.sum(sizes[:i]) for i in range(self.comm.size)], dtype='intc') + disp = numpy.array([numpy.sum(sizes[:i]) for i in range(self.comm.size)], dtype="intc") # global number of points nptsg = numpy.sum(sizes) ug = numpy.zeros(nptsg) vg = numpy.zeros(nptsg) tg = numpy.zeros(nptsg) - faceIDg = numpy.zeros(nptsg, dtype='intc') - bodyIDg = numpy.zeros(nptsg, dtype='intc') - edgeIDg = numpy.zeros(nptsg, dtype='intc') + faceIDg = numpy.zeros(nptsg, dtype="intc") + bodyIDg = numpy.zeros(nptsg, dtype="intc") + edgeIDg = numpy.zeros(nptsg, dtype="intc") ulower0g = numpy.zeros(nptsg) uupper0g = numpy.zeros(nptsg) vlower0g = numpy.zeros(nptsg) vupper0g = numpy.zeros(nptsg) tlower0g = numpy.zeros(nptsg) tupper0g = numpy.zeros(nptsg) - ulowerl = uvlimitsl[:,0].copy() - uupperl = uvlimitsl[:,1].copy() - vlowerl = uvlimitsl[:,2].copy() - vupperl = uvlimitsl[:,3].copy() - tlowerl = tlimitsl[:,0].copy() - tupperl = tlimitsl[:,1].copy() + ulowerl = uvlimitsl[:, 0].copy() + uupperl = uvlimitsl[:, 1].copy() + vlowerl = uvlimitsl[:, 2].copy() + vupperl = uvlimitsl[:, 3].copy() + tlowerl = tlimitsl[:, 0].copy() + tupperl = tlimitsl[:, 1].copy() # Now we do an allGatherv to get a long list of all pointset information # TODO probably can avoid breaking up the uvt limits with copies and stack below @@ -1203,22 +1294,22 @@ def _computeSurfJacobian(self, fd=True): nproc = self.maxproc else: nproc = self.comm.size - rank = self.comm.rank - + rank = self.comm.rank + # arrays to collect local pointset info - ul = numpy.zeros(0) # local u coordinates - vl = numpy.zeros(0) # local v coordinates - tl = numpy.zeros(0) # local t coordinates - faceIDl = numpy.zeros(0, dtype = 'intc') # surface index - bodyIDl = numpy.zeros(0, dtype = 'intc') # body index - edgeIDl = numpy.zeros(0, dtype='intc') # edge index - uvlimitsl = numpy.zeros((0,4)) - tlimitsl = numpy.zeros((0,2)) + ul = numpy.zeros(0) # local u coordinates + vl = numpy.zeros(0) # local v coordinates + tl = numpy.zeros(0) # local t coordinates + faceIDl = numpy.zeros(0, dtype="intc") # surface index + bodyIDl = numpy.zeros(0, dtype="intc") # body index + edgeIDl = numpy.zeros(0, dtype="intc") # edge index + uvlimitsl = numpy.zeros((0, 4)) + tlimitsl = numpy.zeros((0, 2)) any_ptset_nondistributed = False any_ptset_distributed = False for ptSetName in self.pointSets: # initialize the Jacobians - self.pointSets[ptSetName].jac = numpy.zeros((3*self.pointSets[ptSetName].nPts, nDV)) + self.pointSets[ptSetName].jac = numpy.zeros((3 * self.pointSets[ptSetName].nPts, nDV)) if self.pointSets[ptSetName].distributed: any_ptset_distributed = True else: @@ -1235,37 +1326,40 @@ def _computeSurfJacobian(self, fd=True): uvlimitsl = numpy.concatenate((uvlimitsl, self.pointSets[ptSetName].uvlimits0)) tlimitsl = numpy.concatenate((tlimitsl, self.pointSets[ptSetName].tlimits0)) if any_ptset_distributed and any_ptset_nondistributed: - raise ValueError('Both nondistributed and distributed pointsets were added to this DVGeoESP which is not yet supported') + raise ValueError( + "Both nondistributed and distributed pointsets were added to this DVGeoESP which is not yet supported" + ) if any_ptset_distributed: # need to get ALL the coordinates from every proc on every proc to do the parallel FD if self.maxproc is not None: - raise ValueError('Max processor limit is not usable with distributed pointsets') + raise ValueError("Max processor limit is not usable with distributed pointsets") # now figure out which proc has how many points. - sizes = numpy.array(self.comm.allgather(len(ul)), dtype = 'intc') + sizes = numpy.array(self.comm.allgather(len(ul)), dtype="intc") # displacements for allgather - disp = numpy.array([numpy.sum(sizes[:i]) for i in range(nproc)], dtype='intc') + disp = numpy.array([numpy.sum(sizes[:i]) for i in range(nproc)], dtype="intc") # global number of points nptsg = numpy.sum(sizes) - ug, vg, tg, faceIDg, bodyIDg, edgeIDg, uvlimitsg, tlimitsg, sizes = self._allgatherCoordinates(ul,vl,tl,faceIDl,bodyIDl,edgeIDl,uvlimitsl,tlimitsl) + ug, vg, tg, faceIDg, bodyIDg, edgeIDg, uvlimitsg, tlimitsg, sizes = self._allgatherCoordinates( + ul, vl, tl, faceIDl, bodyIDl, edgeIDl, uvlimitsl, tlimitsl + ) else: nptsg = len(ul) ug = ul - vg = vl - tg = tl + vg = vl + tg = tl faceIDg = faceIDl bodyIDg = bodyIDl edgeIDg = edgeIDl - uvlimitsg = uvlimitsl + uvlimitsg = uvlimitsl tlimitsg = tlimitsl # create a local new point array. We will use this to get the new # coordinates as we perturb DVs. We just need one (instead of nDV times the size) # because we get the new points, calculate the jacobian and save it right after - ptsNewL = numpy.zeros(len(ul)*3) - - + ptsNewL = numpy.zeros(len(ul) * 3) + # we now have all the point info on all procs. - tcomm += (time.time() - t1) + tcomm += time.time() - t1 # We need to evaluate all the points on respective procs for FD computations @@ -1282,7 +1376,7 @@ def _computeSurfJacobian(self, fd=True): ptsNew = numpy.zeros((n, nptsg, 3)) # perturb the DVs on different procs and compute the new point coordinates. - i = 0 # Counter on local Jac + i = 0 # Counter on local Jac for iDV in range(self.getNDV()): # I have to do this one. @@ -1292,7 +1386,7 @@ def _computeSurfJacobian(self, fd=True): dvLocalIndex = self.globalDVList[iDV][1] dvObj = self.DVs[dvName] # Step size for this particular DV - dh = dvObj.dh + dh = dvObj.dh # Perturb the DV dvSave = dvObj.value.copy() @@ -1302,16 +1396,18 @@ def _computeSurfJacobian(self, fd=True): t11 = time.time() self._updateESPModel() t12 = time.time() - tesp += (t12-t11) + tesp += t12 - t11 t11 = time.time() # evaluate the points - ptsNew[i,:,:] = self._evaluatePoints(ug, vg, tg, uvlimitsg, tlimitsg, bodyIDg, faceIDg, edgeIDg, nptsg) + ptsNew[i, :, :] = self._evaluatePoints( + ug, vg, tg, uvlimitsg, tlimitsg, bodyIDg, faceIDg, edgeIDg, nptsg + ) t12 = time.time() - teval += (t12-t11) + teval += t12 - t11 # now we can calculate the jac and put it back in ptsNew - ptsNew[i, :, :] = (ptsNew[i, :, :] - pts0[:,:]) / dh + ptsNew[i, :, :] = (ptsNew[i, :, :] - pts0[:, :]) / dh # Reset the DV dvObj.value = dvSave.copy() @@ -1325,11 +1421,11 @@ def _computeSurfJacobian(self, fd=True): t11 = time.time() self._updateESPModel() t12 = time.time() - tesp += (t12-t11) - + tesp += t12 - t11 + else: - raise NotImplementedError('ESP analytic derivatives are not implemented') - + raise NotImplementedError("ESP analytic derivatives are not implemented") + ii = 0 # loop over the DVs and scatter the perturbed points to original procs for iDV in range(self.getNDV()): @@ -1338,17 +1434,17 @@ def _computeSurfJacobian(self, fd=True): dvLocalIndex = self.globalDVList[iDV][1] dvObj = self.DVs[dvName] # Step size for this particular DV - dh = dvObj.dh + dh = dvObj.dh t11 = time.time() root_proc = iDV % nproc if any_ptset_distributed: # create the send/recv buffers for the scatter if root_proc == rank: - sendbuf = [ptsNew[ii, :, :].flatten(), sizes*3, disp*3, MPI.DOUBLE] + sendbuf = [ptsNew[ii, :, :].flatten(), sizes * 3, disp * 3, MPI.DOUBLE] else: - sendbuf = [numpy.zeros((0,3)), sizes*3, disp*3, MPI.DOUBLE] - recvbuf = [ptsNewL, MPI.DOUBLE] + sendbuf = [numpy.zeros((0, 3)), sizes * 3, disp * 3, MPI.DOUBLE] + recvbuf = [ptsNewL, MPI.DOUBLE] # scatter the info from the proc that perturbed this DV to all procs self.comm.Scatterv(sendbuf, recvbuf, root=root_proc) else: @@ -1363,7 +1459,7 @@ def _computeSurfJacobian(self, fd=True): self.comm.Barrier() t12 = time.time() - tcomm += (t12-t11) + tcomm += t12 - t11 # calculate the jacobian here for the pointsets offset = 0 @@ -1372,8 +1468,8 @@ def _computeSurfJacobian(self, fd=True): nPts = self.pointSets[ptSet].nPts # indices to extract correct points from the long pointset array - ibeg = offset*3 - iend = ibeg + nPts*3 + ibeg = offset * 3 + iend = ibeg + nPts * 3 # ptsNewL has the jacobian itself... self.pointSets[ptSet].jac[:, iDV] = ptsNewL[ibeg:iend].copy() @@ -1388,15 +1484,16 @@ def _computeSurfJacobian(self, fd=True): t2 = time.time() if rank == 0: - print('FD jacobian calcs with dvgeovsp took',(t2-t1),'seconds in total') - print('updating the esp model took',tesp,'seconds') - print('evaluating the new points took', teval,'seconds') - print('communication took',tcomm,'seconds') + print("FD jacobian calcs with dvgeovsp took", (t2 - t1), "seconds in total") + print("updating the esp model took", tesp, "seconds") + print("evaluating the new points took", teval, "seconds") + print("communication took", tcomm, "seconds") # set the update flags for ptSet in self.pointSets: self.updatedJac[ptSet] = True + class ESPParameter(object): def __init__(self, pmtrName, pmtrIndex, numRow, numCol, baseValue): """Internal class for storing metadata about the ESP model""" @@ -1406,8 +1503,8 @@ def __init__(self, pmtrName, pmtrIndex, numRow, numCol, baseValue): self.numCol = numCol self.baseValue = baseValue -class espDV(object): +class espDV(object): def __init__(self, csmDesPmtr, name, value, lower, upper, scale, rows, cols, dh, globalstartind): """Internal class for storing ESP design variable information""" self.csmDesPmtr = csmDesPmtr @@ -1418,10 +1515,11 @@ def __init__(self, csmDesPmtr, name, value, lower, upper, scale, rows, cols, dh, self.scale = scale self.rows = rows self.cols = cols - self.nVal = len(rows)*len(cols) + self.nVal = len(rows) * len(cols) self.dh = dh self.globalStartInd = globalstartind + class PointSet(object): def __init__(self, points, proj_pts, bodyID, faceID, edgeID, uv, t, uvlimits, tlimits, distributed): self.points = points @@ -1429,8 +1527,8 @@ def __init__(self, points, proj_pts, bodyID, faceID, edgeID, uv, t, uvlimits, tl self.bodyID = bodyID self.faceID = faceID self.edgeID = edgeID - self.u = uv[:,0] - self.v = uv[:,1] + self.u = uv[:, 0] + self.v = uv[:, 1] self.t = t self.uvlimits0 = uvlimits self.tlimits0 = tlimits diff --git a/pygeo/DVGeometryVSP.py b/pygeo/DVGeometryVSP.py index 6df4c951..269a8101 100644 --- a/pygeo/DVGeometryVSP.py +++ b/pygeo/DVGeometryVSP.py @@ -19,7 +19,8 @@ try: import openvsp except ImportError: - raise ImportError('The OpenVSP Python API is required in order to use DVGeometryVSP') + raise ImportError("The OpenVSP Python API is required in order to use DVGeometryVSP") + class Error(Exception): """ diff --git a/pygeo/__init__.py b/pygeo/__init__.py index 51b9eaf1..197f86c9 100644 --- a/pygeo/__init__.py +++ b/pygeo/__init__.py @@ -1,4 +1,4 @@ -__version__ = '1.4.0' +__version__ = "1.4.0" from . import geo_utils from .pyNetwork import pyNetwork @@ -7,8 +7,8 @@ from .DVConstraints import DVConstraints from .DVGeometry import DVGeometry from .DVGeometryAxi import DVGeometryAxi + try: from .DVGeometryVSP import DVGeometryVSP except ImportError: pass - diff --git a/pygeo/geo_utils.py b/pygeo/geo_utils.py index 8ea0bedc..e44f19be 100644 --- a/pygeo/geo_utils.py +++ b/pygeo/geo_utils.py @@ -6,6 +6,7 @@ import sys, os import functools from pyspline import pySpline + # Set a (MUCH) larger recursion limit. For meshes with extremely large # numbers of blocs (> 5000) the recursive edge propagation may hit a # recursion limit. @@ -16,43 +17,43 @@ # -------------------------------------------------------------- def rotxM(theta): """Return x rotation matrix""" - theta = theta*np.pi/180 - M = [[1, 0, 0], [0, np.cos(theta), -np.sin(theta)], \ - [0, np.sin(theta), np.cos(theta)]] + theta = theta * np.pi / 180 + M = [[1, 0, 0], [0, np.cos(theta), -np.sin(theta)], [0, np.sin(theta), np.cos(theta)]] return M + def rotyM(theta): """ Return y rotation matrix""" - theta = theta*np.pi/180 - M = [[np.cos(theta), 0, np.sin(theta)], [0, 1, 0], \ - [-np.sin(theta), 0, np.cos(theta)]] + theta = theta * np.pi / 180 + M = [[np.cos(theta), 0, np.sin(theta)], [0, 1, 0], [-np.sin(theta), 0, np.cos(theta)]] return M + def rotzM(theta): """ Return z rotation matrix""" - theta = theta*np.pi/180 - M = [[np.cos(theta), -np.sin(theta), 0], \ - [np.sin(theta), np.cos(theta), 0],[0, 0, 1]] + theta = theta * np.pi / 180 + M = [[np.cos(theta), -np.sin(theta), 0], [np.sin(theta), np.cos(theta), 0], [0, 0, 1]] return M + def rotxV(x, theta): """ Rotate a coordinate in the local x frame""" - M = [[1, 0, 0], [0, np.cos(theta), -np.sin(theta)], \ - [0, np.sin(theta), np.cos(theta)]] + M = [[1, 0, 0], [0, np.cos(theta), -np.sin(theta)], [0, np.sin(theta), np.cos(theta)]] return np.dot(M, x) + def rotyV(x, theta): """Rotate a coordinate in the local y frame""" - M = [[np.cos(theta), 0, np.sin(theta)], [0, 1, 0], \ - [-np.sin(theta), 0, np.cos(theta)]] + M = [[np.cos(theta), 0, np.sin(theta)], [0, 1, 0], [-np.sin(theta), 0, np.cos(theta)]] return np.dot(M, x) + def rotzV(x, theta): """Roate a coordinate in the local z frame""" - M = [[np.cos(theta), -np.sin(theta), 0], \ - [np.sin(theta), np.cos(theta), 0], [0, 0, 1]] + M = [[np.cos(theta), -np.sin(theta), 0], [np.sin(theta), np.cos(theta), 0], [0, 0, 1]] return np.dot(M, x) + def rotVbyW(V, W, theta): """ Rotate a vector V, about an axis W by angle theta""" ux = W[0] @@ -61,32 +62,36 @@ def rotVbyW(V, W, theta): c = np.cos(theta) s = np.sin(theta) - if np.array(theta).dtype==np.dtype('D') or \ - np.array(W).dtype==np.dtype('D') or \ - np.array(V).dtype==np.dtype('D'): - dtype = 'D' + if ( + np.array(theta).dtype == np.dtype("D") + or np.array(W).dtype == np.dtype("D") + or np.array(V).dtype == np.dtype("D") + ): + dtype = "D" else: - dtype = 'd' + dtype = "d" R = np.zeros((3, 3), dtype) - R[0, 0] = ux**2 + (1-ux**2)*c - R[0, 1] = ux*uy*(1-c) - uz*s - R[0, 2] = ux*uz*(1-c) + uy*s + R[0, 0] = ux ** 2 + (1 - ux ** 2) * c + R[0, 1] = ux * uy * (1 - c) - uz * s + R[0, 2] = ux * uz * (1 - c) + uy * s - R[1, 0] = ux*uy*(1-c) + uz*s - R[1, 1] = uy**2 + (1-uy**2)*c - R[1, 2] = uy*uz*(1-c) - ux*s + R[1, 0] = ux * uy * (1 - c) + uz * s + R[1, 1] = uy ** 2 + (1 - uy ** 2) * c + R[1, 2] = uy * uz * (1 - c) - ux * s - R[2, 0] = ux*uz*(1-c) - uy*s - R[2, 1] = uy*uz*(1-c) + ux*s - R[2, 2] = uz**2+(1-uz**2)*c + R[2, 0] = ux * uz * (1 - c) - uy * s + R[2, 1] = uy * uz * (1 - c) + ux * s + R[2, 2] = uz ** 2 + (1 - uz ** 2) * c return np.dot(R, V) - # ------------------------------------------------------------- - # Norm Functions - # ------------------------------------------------------------- + +# ------------------------------------------------------------- +# Norm Functions +# ------------------------------------------------------------- + def euclideanNorm(inVec): """ @@ -97,34 +102,36 @@ def euclideanNorm(inVec): inVec = np.array(inVec) temp = 0.0 for i in range(inVec.shape[0]): - temp += inVec[i]**2 + temp += inVec[i] ** 2 return np.sqrt(temp) -def cross_b(a, b, crossb): + +def cross_b(a, b, crossb): """ Do the reverse accumulation through a cross product. """ ab = np.zeros_like(a) bb = np.zeros_like(b) - ab[0] = ab[0] + b[1]*crossb[2] - bb[1] = bb[1] + a[0]*crossb[2] - ab[1] = ab[1] - b[0]*crossb[2] - bb[0] = bb[0] - a[1]*crossb[2] + ab[0] = ab[0] + b[1] * crossb[2] + bb[1] = bb[1] + a[0] * crossb[2] + ab[1] = ab[1] - b[0] * crossb[2] + bb[0] = bb[0] - a[1] * crossb[2] crossb[2] = 0.0 - ab[2] = ab[2] + b[0]*crossb[1] - bb[0] = bb[0] + a[2]*crossb[1] - ab[0] = ab[0] - b[2]*crossb[1] - bb[2] = bb[2] - a[0]*crossb[1] + ab[2] = ab[2] + b[0] * crossb[1] + bb[0] = bb[0] + a[2] * crossb[1] + ab[0] = ab[0] - b[2] * crossb[1] + bb[2] = bb[2] - a[0] * crossb[1] crossb[1] = 0.0 - ab[1] = ab[1] + b[2]*crossb[0] - bb[2] = bb[2] + a[1]*crossb[0] - ab[2] = ab[2] - b[1]*crossb[0] - bb[1] = bb[1] - a[2]*crossb[0] + ab[1] = ab[1] + b[2] * crossb[0] + bb[2] = bb[2] + a[1] * crossb[0] + ab[2] = ab[2] - b[1] * crossb[0] + bb[1] = bb[1] - a[2] * crossb[0] crossb[0] = 0.0 return ab, bb + def dot_b(a, b, dotb): """ Do the reverse accumulation through a dot product. @@ -132,62 +139,65 @@ def dot_b(a, b, dotb): ab = np.zeros_like(a) bb = np.zeros_like(b) - ab = ab + b*dotb - bb = bb + a*dotb + ab = ab + b * dotb + bb = bb + a * dotb return ab, bb + def calculateCentroid(p0, v1, v2): - ''' + """ take in a triangulated surface and calculate the centroid - ''' + """ p0 = np.array(p0) - p1 = np.array(v1)+p0 - p2 = np.array(v2)+p0 + p1 = np.array(v1) + p0 + p2 = np.array(v2) + p0 - #compute the areas - areaVec = np.cross(v1, v2)/2.0 + # compute the areas + areaVec = np.cross(v1, v2) / 2.0 area = np.linalg.norm(areaVec, axis=1) # compute the cell centroids - cellCenter = (p0+p1+p2)/3. + cellCenter = (p0 + p1 + p2) / 3.0 centerSum = area.dot(cellCenter) areaSum = np.sum(area) - centroid = centerSum/areaSum + centroid = centerSum / areaSum return centroid + def calculateAverageNormal(p0, v1, v2): - ''' + """ take in a triangulated surface and calculate the centroid - ''' + """ p0 = np.array(p0) - p1 = np.array(v1)+p0 - p2 = np.array(v2)+p0 + p1 = np.array(v1) + p0 + p2 = np.array(v2) + p0 - #compute the normal of each triangle + # compute the normal of each triangle normal = np.cross(v1, v2) - sumNormal = np.sum(normal,axis=0) + sumNormal = np.sum(normal, axis=0) lengthNorm = np.linalg.norm(sumNormal) - unitNormal = sumNormal/lengthNorm + unitNormal = sumNormal / lengthNorm return unitNormal + def calculateRadii(centroid, p0, v1, v2): - ''' + """ take the centroid and compute inner and outer radii of surface - ''' + """ p0 = np.array(p0) - p1 = np.array(v1)+p0 - p2 = np.array(v2)+p0 + p1 = np.array(v1) + p0 + p2 = np.array(v2) + p0 # take the difference between the points and the centroid - d0 = p0-centroid - d1 = p1-centroid - d2 = p2-centroid + d0 = p0 - centroid + d1 = p1 - centroid + d2 = p2 - centroid radO = np.zeros(3) radI = np.zeros(3) @@ -204,38 +214,41 @@ def calculateRadii(centroid, p0, v1, v2): outerRadius = np.max(radO) innerRadius = np.min(radI) - return innerRadius,outerRadius + return innerRadius, outerRadius + - # -------------------------------------------------------------- - # I/O Functions - # -------------------------------------------------------------- +# -------------------------------------------------------------- +# I/O Functions +# -------------------------------------------------------------- -def readNValues(handle, N, dtype, binary=False, sep=' '): + +def readNValues(handle, N, dtype, binary=False, sep=" "): """Read N values of dtype 'float' or 'int' from file handle""" if binary: sep = "" - if dtype == 'int': - values = np.fromfile(handle, dtype='int', count=N, sep=sep) + if dtype == "int": + values = np.fromfile(handle, dtype="int", count=N, sep=sep) else: - values = np.fromfile(handle, dtype='float', count=N, sep=sep) + values = np.fromfile(handle, dtype="float", count=N, sep=sep) return values + def writeValues(handle, values, dtype, binary=False): """Read N values of type 'float' or 'int' from file handle""" if binary: values.tofile(handle) else: - if dtype == 'float': + if dtype == "float": values.tofile(handle, sep=" ", format="%f") - elif dtype == 'int': + elif dtype == "int": values.tofile(handle, sep=" ", format="%d") -def readAirfoilFile(fileName, bluntTe=False, bluntTaperRange=0.1, - bluntThickness=.002): + +def readAirfoilFile(fileName, bluntTe=False, bluntTaperRange=0.1, bluntThickness=0.002): """ Load the airfoil file""" - f = open(fileName, 'r') - line = f.readline() # Read (and ignore) the first line + f = open(fileName, "r") + line = f.readline() # Read (and ignore) the first line r = [] try: r.append([float(s) for s in line.split()]) @@ -245,9 +258,9 @@ def readAirfoilFile(fileName, bluntTe=False, bluntTaperRange=0.1, while 1: line = f.readline() if not line: - break # end of file + break # end of file if line.isspace(): - break # blank line + break # blank line r.append([float(s) for s in line.split()]) rr = np.array(r) @@ -268,30 +281,30 @@ def readAirfoilFile(fileName, bluntTe=False, bluntTaperRange=0.1, # Check for blunt TE: if bluntTe is False: if y[0] != y[-1]: - print('Blunt Trailing Edge on airfoil: %s'%(fileName)) - print('Merging to a point over final %f ...'%(bluntTaperRange)) - yAvg = 0.5*(y[0] + y[-1]) - xAvg = 0.5*(x[0] + x[-1]) + print("Blunt Trailing Edge on airfoil: %s" % (fileName)) + print("Merging to a point over final %f ..." % (bluntTaperRange)) + yAvg = 0.5 * (y[0] + y[-1]) + xAvg = 0.5 * (x[0] + x[-1]) yTop = y[0] yBot = y[-1] xTop = x[0] xBot = x[-1] # Indices on the TOP surface of the wing - indices = np.where(x[0:npt//2]>=(1-bluntTaperRange))[0] + indices = np.where(x[0 : npt // 2] >= (1 - bluntTaperRange))[0] for i in range(len(indices)): - fact = (x[indices[i]]- (x[0]-bluntTaperRange))/bluntTaperRange - y[indices[i]] = y[indices[i]]- fact*(yTop-yAvg) - x[indices[i]] = x[indices[i]]- fact*(xTop-xAvg) + fact = (x[indices[i]] - (x[0] - bluntTaperRange)) / bluntTaperRange + y[indices[i]] = y[indices[i]] - fact * (yTop - yAvg) + x[indices[i]] = x[indices[i]] - fact * (xTop - xAvg) # Indices on the BOTTOM surface of the wing - indices = np.where(x[npt//2:]>=(1-bluntTaperRange))[0] - indices = indices + npt//2 + indices = np.where(x[npt // 2 :] >= (1 - bluntTaperRange))[0] + indices = indices + npt // 2 for i in range(len(indices)): - fact = (x[indices[i]]- (x[-1]-bluntTaperRange))/bluntTaperRange - y[indices[i]] = y[indices[i]]- fact*(yBot-yAvg) - x[indices[i]] = x[indices[i]]- fact*(xBot-xAvg) + fact = (x[indices[i]] - (x[-1] - bluntTaperRange)) / bluntTaperRange + y[indices[i]] = y[indices[i]] - fact * (yBot - yAvg) + x[indices[i]] = x[indices[i]] - fact * (xBot - xAvg) elif bluntTe is True: # Since we will be rescaling the TE regardless, the sharp TE @@ -302,36 +315,36 @@ def readAirfoilFile(fileName, bluntTe=False, bluntTaperRange=0.1, curThick = y[0] - y[-1] # Set the new TE values: - xBreak = 1.0-bluntTaperRange + xBreak = 1.0 - bluntTaperRange # Rescale upper surface: - for i in range(0,npt//2): + for i in range(0, npt // 2): if x[i] > xBreak: - s = (x[i]-xMin-xBreak)/bluntTaperRange - y[i] += s*0.5*(bluntThickness-curThick) + s = (x[i] - xMin - xBreak) / bluntTaperRange + y[i] += s * 0.5 * (bluntThickness - curThick) # Rescale lower surface: - for i in range(npt//2,npt): + for i in range(npt // 2, npt): if x[i] > xBreak: - s = (x[i]-xMin-xBreak)/bluntTaperRange - y[i] -= s*0.5*(bluntThickness-curThick) + s = (x[i] - xMin - xBreak) / bluntTaperRange + y[i] -= s * 0.5 * (bluntThickness - curThick) return x, y -def writeAirfoilFile(fileName,name, x,y): +def writeAirfoilFile(fileName, name, x, y): """ write an airfoil file """ - f = open(fileName, 'w') - f.write("%s\n"%name) + f = open(fileName, "w") + f.write("%s\n" % name) for i in range(len(x)): - f.write('%12.10f %12.10f\n'%(x[i],y[i])) + f.write("%12.10f %12.10f\n" % (x[i], y[i])) f.close() - return + def getCoordinatesFromFile(fileName): """Get a list of coordinates from a file - useful for testing Required: @@ -340,7 +353,7 @@ def getCoordinatesFromFile(fileName): coordinates: list of coordinates """ - f = open(fileName, 'r') + f = open(fileName, "r") coordinates = [] for line in f: aux = line.split() @@ -351,8 +364,9 @@ def getCoordinatesFromFile(fileName): return coordinates + def write_wing_FFD_file(fileName, slices, N0, N1, N2, axes=None, dist=None): - ''' + """ This function can be used to generate a simple FFD. The FFD can be made up of more than one volume, but the volumes will be connected. It is meant for doing simple wing FFDs. @@ -415,58 +429,58 @@ def write_wing_FFD_file(fileName, slices, N0, N1, N2, axes=None, dist=None): ['cosine', 'linear', 'right'] ] - ''' + """ Nvol = slices.shape[0] - 1 if axes is None: - axes=['k', 'j', 'i'] + axes = ["k", "j", "i"] if dist is None: - dist = [['linear', 'linear', 'linear']]*Nvol + dist = [["linear", "linear", "linear"]] * Nvol - assert(len(dist) == Nvol) + assert len(dist) == Nvol # Make sure the sizes are the right type in each dimension. If an integer is # given, use that same size for every volume. size = [N0, N1, N2] for i, item in enumerate(size): if type(item) is int: - size[i] = [item]*Nvol + size[i] = [item] * Nvol elif type(item) is not list: - print('Incorrect type for N0, N1, or N2.') + print("Incorrect type for N0, N1, or N2.") - assert(len(size[i]) == Nvol) + assert len(size[i]) == Nvol N0, N1, N2 = size - f = open(fileName, 'w') - f.write('{}\n'.format(Nvol)) + f = open(fileName, "w") + f.write("{}\n".format(Nvol)) def getDistribution(distIn, N): if type(distIn) is not str: - assert(len(distIn) == N) + assert len(distIn) == N dist = distIn.copy() - elif distIn == 'linear': + elif distIn == "linear": dist = np.linspace(0, 1, N) - elif distIn == 'cosine': + elif distIn == "cosine": dist = (1 - np.cos(np.linspace(0, np.pi, N))) / 2.0 - elif distIn == 'left': - dist = np.linspace(0, 1, N)**(3.0/2.0) - elif distIn == 'right': - dist = np.linspace(0, 1, N)**(2.0/3.0) + elif distIn == "left": + dist = np.linspace(0, 1, N) ** (3.0 / 2.0) + elif distIn == "right": + dist = np.linspace(0, 1, N) ** (2.0 / 3.0) return dist for i in range(Nvol): size = [N0[i], N1[i], N2[i]] - Ni = size[axes.index('i')] - Nj = size[axes.index('j')] - Nk = size[axes.index('k')] - f.write('%d\t%d\t%d\n' % (Ni, Nj, Nk)) + Ni = size[axes.index("i")] + Nj = size[axes.index("j")] + Nk = size[axes.index("k")] + f.write("%d\t%d\t%d\n" % (Ni, Nj, Nk)) for i in range(Nvol): size = [N0[i], N1[i], N2[i]] - Ni = size[axes.index('i')] - Nj = size[axes.index('j')] - Nk = size[axes.index('k')] + Ni = size[axes.index("i")] + Nj = size[axes.index("j")] + Nk = size[axes.index("k")] # Get distributions for each axis d0 = getDistribution(dist[i][0], size[0]) d1 = getDistribution(dist[i][1], size[1]) @@ -476,60 +490,63 @@ def getDistribution(distIn, N): X = np.zeros(size + [3]) for j in range(size[0]): - P = slices[i,0,0] + np.outer(d0, (slices[i+1,0,0] - slices[i,0,0]))[j] - Q = slices[i,0,1] + np.outer(d0, (slices[i+1,0,1] - slices[i,0,1]))[j] - R = slices[i,1,0] + np.outer(d0, (slices[i+1,1,0] - slices[i,1,0]))[j] - S = slices[i,1,1] + np.outer(d0, (slices[i+1,1,1] - slices[i,1,1]))[j] + P = slices[i, 0, 0] + np.outer(d0, (slices[i + 1, 0, 0] - slices[i, 0, 0]))[j] + Q = slices[i, 0, 1] + np.outer(d0, (slices[i + 1, 0, 1] - slices[i, 0, 1]))[j] + R = slices[i, 1, 0] + np.outer(d0, (slices[i + 1, 1, 0] - slices[i, 1, 0]))[j] + S = slices[i, 1, 1] + np.outer(d0, (slices[i + 1, 1, 1] - slices[i, 1, 1]))[j] for k in range(size[1]): U = P + np.outer(d1, (R - P))[k] V = Q + np.outer(d1, (S - Q))[k] - X[j,k] = U + np.outer(d2, (V - U)) - + X[j, k] = U + np.outer(d2, (V - U)) for dim in range(3): - line = '' + line = "" for j in range(Nk): for k in range(Nj): for l in range(Ni): idc = [-1, -1, -1] - idc[axes.index('i')] = l - idc[axes.index('j')] = k - idc[axes.index('k')] = j - line += '{: .4e}\t'.format(X[idc[0],idc[1],idc[2],dim]) + idc[axes.index("i")] = l + idc[axes.index("j")] = k + idc[axes.index("k")] = j + line += "{: .4e}\t".format(X[idc[0], idc[1], idc[2], dim]) if len(line) + 11 > 80: - f.write(line+'\n') - line = '' + f.write(line + "\n") + line = "" if len(line) > 0: - f.write(line+'\n') + f.write(line + "\n") f.close() + + # -------------------------------------------------------------- # Working with Edges Function # -------------------------------------------------------------- + def eDist(x1, x2): """Get the eculidean distance between two points""" - return euclideanNorm(x1-x2)#np.linalg.norm(x1-x2) + return euclideanNorm(x1 - x2) # np.linalg.norm(x1-x2) + def eDist2D(x1, x2): """Get the eculidean distance between two points""" - return np.sqrt((x1[0]-x2[0])**2 + (x1[1]-x2[1])**2) + return np.sqrt((x1[0] - x2[0]) ** 2 + (x1[1] - x2[1]) ** 2) + def eDist_b(x1, x2): x1b = 0.0 x2b = 0.0 - db = 1.0 + db = 1.0 x1b = np.zeros(3) x2b = np.zeros(3) - if ((x1[0]-x2[0])**2 + (x1[1]-x2[1])**2 + (x1[2]-x2[2])**2 == 0.0): + if (x1[0] - x2[0]) ** 2 + (x1[1] - x2[1]) ** 2 + (x1[2] - x2[2]) ** 2 == 0.0: tempb = 0.0 else: - tempb = db/(2.0*np.sqrt( - (x1[0]-x2[0])**2+(x1[1]-x2[1])**2+(x1[2]-x2[2])**2)) + tempb = db / (2.0 * np.sqrt((x1[0] - x2[0]) ** 2 + (x1[1] - x2[1]) ** 2 + (x1[2] - x2[2]) ** 2)) - tempb0 = 2*(x1[0]-x2[0])*tempb - tempb1 = 2*(x1[1]-x2[1])*tempb - tempb2 = 2*(x1[2]-x2[2])*tempb + tempb0 = 2 * (x1[0] - x2[0]) * tempb + tempb1 = 2 * (x1[1] - x2[1]) * tempb + tempb2 = 2 * (x1[2] - x2[2]) * tempb x1b[0] = tempb0 x2b[0] = -tempb0 x1b[1] = tempb1 @@ -544,6 +561,7 @@ def eDist_b(x1, x2): # Truly Miscellaneous Functions # -------------------------------------------------------------- + def unique(s): """Return a list of the elements in s, but without duplicates. @@ -614,6 +632,7 @@ def unique(s): u.append(x) return u + def uniqueIndex(s, sHash=None): """ This function is based on unique @@ -636,7 +655,7 @@ def uniqueIndex(s, sHash=None): t = list(s) t.sort() - diff = np.zeros(n, 'bool') + diff = np.zeros(n, "bool") last = t[0] lasti = i = 1 @@ -650,10 +669,11 @@ def uniqueIndex(s, sHash=None): b = np.where(diff)[0] for i in range(n): - ind[i] -= b.searchsorted(ind[i], side='right') + ind[i] -= b.searchsorted(ind[i], side="right") return t[:lasti], ind + def pointReduce(points, nodeTol=1e-4): """Given a list of N points in ndim space, with possible duplicates, return a list of the unique points AND a pointer list @@ -674,7 +694,7 @@ def pointReduce(points, nodeTol=1e-4): i = 0 cont = True newPoints = [] - link = np.zeros(N, 'intc') + link = np.zeros(N, "intc") linkCounter = 0 while cont: @@ -682,15 +702,15 @@ def pointReduce(points, nodeTol=1e-4): tempInd = [] j = i while cont2: - if abs(dists[ind[i]]-dists[ind[j]]) abs(vDotTot): # Its along u now get if uDotTot >= 0: - return 0 # U same direction + return 0 # U same direction else: - return 1 # U opposite direction + return 1 # U opposite direction else: if vDotTot >= 0: - return 2 # V same direction + return 2 # V same direction else: - return 3 # V opposite direction + return 3 # V opposite direction + def curveDirection(curve1, curve2): """Determine if the direction of curve 1 is basically in the same @@ -888,24 +915,26 @@ def curveDirection(curve1, curve2): for i in range(N): tot += np.dot(curve1.getDerivative(s[i]), curve2.getDerivative(s[i])) dForward += eDist(curve1.getValue(s[i]), curve2.getValue(s[i])) - dBackward += eDist(curve1.getValue(s[i]), curve2.getValue(s[N-i-1])) + dBackward += eDist(curve1.getValue(s[i]), curve2.getValue(s[N - i - 1])) if tot > 0: return tot, dForward else: return tot, dBackward + def indexPosition1D(i, N): """This function is a generic function which determines if index over a list of length N is an interior point or node 0 or node 1. """ - if i > 0 and i < N-1: # Interior + if i > 0 and i < N - 1: # Interior return 0, None - elif i == 0: # Node 0 + elif i == 0: # Node 0 return 1, 0 - elif i == N-1: # Node 1 + elif i == N - 1: # Node 1 return 1, 1 + def indexPosition2D(i, j, N, M): """This function is a generic function which determines if for a grid of data NxM with index i going 0->N-1 and j going 0->M-1, it @@ -918,25 +947,26 @@ def indexPosition2D(i, j, N, M): index: this is the value index along the edge of interest -- only defined for edges""" - if i > 0 and i < N - 1 and j > 0 and j < M-1: # Interior + if i > 0 and i < N - 1 and j > 0 and j < M - 1: # Interior return 0, None, None, None - elif i > 0 and i < N - 1 and j == 0: # Edge 0 + elif i > 0 and i < N - 1 and j == 0: # Edge 0 return 1, 0, None, i - elif i > 0 and i < N - 1 and j == M - 1: # Edge 1 + elif i > 0 and i < N - 1 and j == M - 1: # Edge 1 return 1, 1, None, i - elif i == 0 and j > 0 and j < M - 1: # Edge 2 + elif i == 0 and j > 0 and j < M - 1: # Edge 2 return 1, 2, None, j - elif i == N - 1 and j > 0 and j < M - 1: # Edge 3 + elif i == N - 1 and j > 0 and j < M - 1: # Edge 3 return 1, 3, None, j - elif i == 0 and j == 0: # Node 0 + elif i == 0 and j == 0: # Node 0 return 2, None, 0, None - elif i == N - 1 and j == 0: # Node 1 + elif i == N - 1 and j == 0: # Node 1 return 2, None, 1, None - elif i == 0 and j == M -1 : # Node 2 + elif i == 0 and j == M - 1: # Node 2 return 2, None, 2, None - elif i == N - 1 and j == M - 1: # Node 3 + elif i == N - 1 and j == M - 1: # Node 3 return 2, None, 3, None + def indexPosition3D(i, j, k, N, M, L): """This function is a generic function which determines if for a 3dgrid of data NxMXL with index i going 0->N-1 and j going 0->M-1 @@ -954,73 +984,75 @@ def indexPosition3D(i, j, k, N, M, L): of interest OR edge of interest index2: this is the value index along 1st dir the face of interest - """ + """ # Note to interior->Faces->Edges->Nodes to minimize number of if checks # Interior: - if i > 0 and i < N-1 and j > 0 and j < M-1 and k > 0 and k < L-1: + if i > 0 and i < N - 1 and j > 0 and j < M - 1 and k > 0 and k < L - 1: return 0, None, None, None - elif i > 0 and i < N-1 and j > 0 and j < M-1 and k == 0: # Face 0 + elif i > 0 and i < N - 1 and j > 0 and j < M - 1 and k == 0: # Face 0 return 1, 0, i, j - elif i > 0 and i < N-1 and j > 0 and j < M-1 and k == L-1: # Face 1 + elif i > 0 and i < N - 1 and j > 0 and j < M - 1 and k == L - 1: # Face 1 return 1, 1, i, j - elif i == 0 and j > 0 and j < M-1 and k > 0 and k < L-1: # Face 2 + elif i == 0 and j > 0 and j < M - 1 and k > 0 and k < L - 1: # Face 2 return 1, 2, j, k - elif i == N-1 and j > 0 and j < M-1 and k > 0 and k < L-1: # Face 3 + elif i == N - 1 and j > 0 and j < M - 1 and k > 0 and k < L - 1: # Face 3 return 1, 3, j, k - elif i > 0 and i < N-1 and j == 0 and k > 0 and k < L-1: # Face 4 + elif i > 0 and i < N - 1 and j == 0 and k > 0 and k < L - 1: # Face 4 return 1, 4, i, k - elif i > 0 and i < N-1 and j == M-1 and k > 0 and k < L-1: # Face 5 + elif i > 0 and i < N - 1 and j == M - 1 and k > 0 and k < L - 1: # Face 5 return 1, 5, i, k - elif i > 0 and i < N-1 and j == 0 and k == 0: # Edge 0 + elif i > 0 and i < N - 1 and j == 0 and k == 0: # Edge 0 return 2, 0, i, None - elif i > 0 and i < N-1 and j == M-1 and k == 0: # Edge 1 + elif i > 0 and i < N - 1 and j == M - 1 and k == 0: # Edge 1 return 2, 1, i, None - elif i == 0 and j > 0 and j < M-1 and k == 0: # Edge 2 + elif i == 0 and j > 0 and j < M - 1 and k == 0: # Edge 2 return 2, 2, j, None - elif i == N-1 and j > 0 and j < M-1 and k == 0: # Edge 3 + elif i == N - 1 and j > 0 and j < M - 1 and k == 0: # Edge 3 return 2, 3, j, None - elif i > 0 and i < N-1 and j == 0 and k == L-1: # Edge 4 + elif i > 0 and i < N - 1 and j == 0 and k == L - 1: # Edge 4 return 2, 4, i, None - elif i > 0 and i < N-1 and j == M-1 and k == L-1: # Edge 5 + elif i > 0 and i < N - 1 and j == M - 1 and k == L - 1: # Edge 5 return 2, 5, i, None - elif i == 0 and j > 0 and j < M-1 and k == L-1: # Edge 6 + elif i == 0 and j > 0 and j < M - 1 and k == L - 1: # Edge 6 return 2, 6, j, None - elif i == N-1 and j > 0 and j < M-1 and k == L-1: # Edge 7 + elif i == N - 1 and j > 0 and j < M - 1 and k == L - 1: # Edge 7 return 2, 7, j, None - elif i == 0 and j == 0 and k > 0 and k < L-1: # Edge 8 + elif i == 0 and j == 0 and k > 0 and k < L - 1: # Edge 8 return 2, 8, k, None - elif i == N-1 and j == 0 and k > 0 and k < L-1: # Edge 9 + elif i == N - 1 and j == 0 and k > 0 and k < L - 1: # Edge 9 return 2, 9, k, None - elif i == 0 and j == M-1 and k > 0 and k < L-1: # Edge 10 + elif i == 0 and j == M - 1 and k > 0 and k < L - 1: # Edge 10 return 2, 10, k, None - elif i == N-1 and j == M-1 and k > 0 and k < L-1: # Edge 11 + elif i == N - 1 and j == M - 1 and k > 0 and k < L - 1: # Edge 11 return 2, 11, k, None - elif i == 0 and j == 0 and k == 0: # Node 0 + elif i == 0 and j == 0 and k == 0: # Node 0 return 3, 0, None, None - elif i == N-1 and j == 0 and k == 0: # Node 1 + elif i == N - 1 and j == 0 and k == 0: # Node 1 return 3, 1, None, None - elif i == 0 and j == M-1 and k == 0: # Node 2 + elif i == 0 and j == M - 1 and k == 0: # Node 2 return 3, 2, None, None - elif i == N-1 and j == M-1 and k == 0: # Node 3 + elif i == N - 1 and j == M - 1 and k == 0: # Node 3 return 3, 3, None, None - elif i == 0 and j == 0 and k == L-1: # Node 4 + elif i == 0 and j == 0 and k == L - 1: # Node 4 return 3, 4, None, None - elif i == N-1 and j == 0 and k == L-1: # Node 5 + elif i == N - 1 and j == 0 and k == L - 1: # Node 5 return 3, 5, None, None - elif i == 0 and j == M-1 and k == L-1: # Node 6 + elif i == 0 and j == M - 1 and k == L - 1: # Node 6 return 3, 6, None, None - elif i == N-1 and j == M-1 and k == L-1: # Node 7 + elif i == N - 1 and j == M - 1 and k == L - 1: # Node 7 return 3, 7, None, None + # -------------------------------------------------------------- # Node/Edge Functions # -------------------------------------------------------------- + def edgeFromNodes(n1, n2): """Return the edge coorsponding to nodes n1, n2""" if (n1 == 0 and n2 == 1) or (n1 == 1 and n2 == 0): @@ -1032,6 +1064,7 @@ def edgeFromNodes(n1, n2): elif (n1 == 3 and n2 == 2) or (n1 == 2 and n2 == 3): return 1 + def edgesFromNode(n): """ Return the two edges coorsponding to node n""" if n == 0: @@ -1043,17 +1076,19 @@ def edgesFromNode(n): if n == 3: return 1, 3 + def edgesFromNodeIndex(n, N, M): - """ Return the two edges coorsponding to node n AND return the index -of the node on the edge according to the size (N, M)""" + """Return the two edges coorsponding to node n AND return the index + of the node on the edge according to the size (N, M)""" if n == 0: return 0, 2, 0, 0 if n == 1: - return 0, 3, N-1, 0 + return 0, 3, N - 1, 0 if n == 2: - return 1, 2, 0, M-1 + return 1, 2, 0, M - 1 if n == 3: - return 1, 3, N-1, M-1 + return 1, 3, N - 1, M - 1 + def nodesFromEdge(edge): """Return the nodes on either edge of a standard edge""" @@ -1082,6 +1117,7 @@ def nodesFromEdge(edge): elif edge == 11: return 3, 7 + # Volume Face/edge functions def nodesFromFace(face): if face == 0: @@ -1097,6 +1133,7 @@ def nodesFromFace(face): elif face == 5: return [2, 3, 6, 7] + def edgesFromFace(face): if face == 0: return [0, 1, 2, 3] @@ -1111,62 +1148,65 @@ def edgesFromFace(face): elif face == 5: return [1, 5, 10, 11] + def setNodeValue(arr, value, nodeIndex): # Set "value" in 3D array "arr" at node "nodeIndex": if nodeIndex == 0: - arr[0,0,0] = value + arr[0, 0, 0] = value elif nodeIndex == 1: - arr[-1,0,0] = value + arr[-1, 0, 0] = value elif nodeIndex == 2: - arr[0,-1,0] = value + arr[0, -1, 0] = value elif nodeIndex == 3: - arr[-1,-1,0] = value + arr[-1, -1, 0] = value if nodeIndex == 4: - arr[0,0,-1] = value + arr[0, 0, -1] = value elif nodeIndex == 5: - arr[-1,0,-1] = value + arr[-1, 0, -1] = value elif nodeIndex == 6: - arr[0,-1,-1] = value + arr[0, -1, -1] = value elif nodeIndex == 7: - arr[-1,-1,-1] = value + arr[-1, -1, -1] = value return arr + def setEdgeValue(arr, values, dir, edgeIndex): - if dir == -1: # Reverse values + if dir == -1: # Reverse values values = values[::-1] if edgeIndex == 0: - arr[1:-1,0,0] = values + arr[1:-1, 0, 0] = values elif edgeIndex == 1: - arr[1:-1,-1,0] = values + arr[1:-1, -1, 0] = values elif edgeIndex == 2: arr[0, 1:-1, 0] = values elif edgeIndex == 3: arr[-1, 1:-1, 0] = values elif edgeIndex == 4: - arr[1:-1,0,-1] = values + arr[1:-1, 0, -1] = values elif edgeIndex == 5: - arr[1:-1,-1,-1] = values + arr[1:-1, -1, -1] = values elif edgeIndex == 6: arr[0, 1:-1, -1] = values elif edgeIndex == 7: arr[-1, 1:-1, -1] = values elif edgeIndex == 8: - arr[0,0,1:-1] = values + arr[0, 0, 1:-1] = values elif edgeIndex == 9: - arr[-1,0,1:-1] = values + arr[-1, 0, 1:-1] = values elif edgeIndex == 10: - arr[0,-1,1:-1] = values + arr[0, -1, 1:-1] = values elif edgeIndex == 11: - arr[-1,-1,1:-1] = values + arr[-1, -1, 1:-1] = values return arr + def setFaceValue(arr, values, faceDir, faceIndex): # Orient the array first according to the dir: @@ -1174,20 +1214,21 @@ def setFaceValue(arr, values, faceDir, faceIndex): values = orientArray(faceDir, values) if faceIndex == 0: - arr[1:-1,1:-1,0] = values + arr[1:-1, 1:-1, 0] = values elif faceIndex == 1: - arr[1:-1,1:-1,-1] = values + arr[1:-1, 1:-1, -1] = values elif faceIndex == 2: - arr[0,1:-1,1:-1] = values + arr[0, 1:-1, 1:-1] = values elif faceIndex == 3: - arr[-1,1:-1,1:-1] = values + arr[-1, 1:-1, 1:-1] = values elif faceIndex == 4: - arr[1:-1,0,1:-1] = values + arr[1:-1, 0, 1:-1] = values elif faceIndex == 5: - arr[1:-1,-1,1:-1] = values + arr[1:-1, -1, 1:-1] = values return arr + def setFaceValue2(arr, values, faceDir, faceIndex): # Orient the array first according to the dir: @@ -1195,66 +1236,69 @@ def setFaceValue2(arr, values, faceDir, faceIndex): values = orientArray(faceDir, values) if faceIndex == 0: - arr[1:-1,1:-1,0] = values + arr[1:-1, 1:-1, 0] = values elif faceIndex == 1: - arr[1:-1,1:-1,-1] = values + arr[1:-1, 1:-1, -1] = values elif faceIndex == 2: - arr[0,1:-1,1:-1] = values + arr[0, 1:-1, 1:-1] = values elif faceIndex == 3: - arr[-1,1:-1,1:-1] = values + arr[-1, 1:-1, 1:-1] = values elif faceIndex == 4: - arr[1:-1,0,1:-1] = values + arr[1:-1, 0, 1:-1] = values elif faceIndex == 5: - arr[1:-1,-1,1:-1] = values + arr[1:-1, -1, 1:-1] = values return arr + def getFaceValue(arr, faceIndex, offset): # Return the values from 'arr' on faceIndex with offset of offset: - if faceIndex == 0: - values = arr[:,:,offset] + if faceIndex == 0: + values = arr[:, :, offset] elif faceIndex == 1: - values = arr[:,:,-1-offset] + values = arr[:, :, -1 - offset] elif faceIndex == 2: - values = arr[offset,:,:] + values = arr[offset, :, :] elif faceIndex == 3: - values = arr[-1-offset,:,:] + values = arr[-1 - offset, :, :] elif faceIndex == 4: - values = arr[:,offset,:] + values = arr[:, offset, :] elif faceIndex == 5: - values = arr[:,-1-offset,:] + values = arr[:, -1 - offset, :] return values.copy() + # -------------------------------------------------------------- # Knot Vector Manipulation Functions # -------------------------------------------------------------- + def blendKnotVectors(knotVectors, sym): """Take in a list of knot vectors and average them""" nVec = len(knotVectors) - if sym: # Symmetrize each knot vector first + if sym: # Symmetrize each knot vector first for i in range(nVec): curKnotVec = knotVectors[i].copy() - if np.mod(len(curKnotVec), 2) == 1: #its odd - mid = (len(curKnotVec) -1)//2 + if np.mod(len(curKnotVec), 2) == 1: # its odd + mid = (len(curKnotVec) - 1) // 2 beg1 = curKnotVec[0:mid] - beg2 = (1-curKnotVec[mid+1:])[::-1] + beg2 = (1 - curKnotVec[mid + 1 :])[::-1] # Average - beg = 0.5*(beg1+beg2) + beg = 0.5 * (beg1 + beg2) curKnotVec[0:mid] = beg - curKnotVec[mid+1:] = (1-beg)[::-1] + curKnotVec[mid + 1 :] = (1 - beg)[::-1] curKnotVec[mid] = 0.5 - else: # its even - mid = len(curKnotVec)//2 + else: # its even + mid = len(curKnotVec) // 2 beg1 = curKnotVec[0:mid] - beg2 = (1-curKnotVec[mid:])[::-1] - beg = 0.5*(beg1+beg2) + beg2 = (1 - curKnotVec[mid:])[::-1] + beg = 0.5 * (beg1 + beg2) curKnotVec[0:mid] = beg - curKnotVec[mid:] = (1-beg)[::-1] + curKnotVec[mid:] = (1 - beg)[::-1] knotVectors[i] = curKnotVec @@ -1266,8 +1310,8 @@ def blendKnotVectors(knotVectors, sym): newKnotVec = newKnotVec / nVec return newKnotVec -class PointSelect(object): +class PointSelect(object): def __init__(self, psType, *args, **kwargs): """Initialize a control point selection class. There are several ways @@ -1308,88 +1352,92 @@ def __init__(self, psType, *args, **kwargs): extract the points """ - if psType == 'x' or psType == 'y' or psType == 'z': - assert 'pt1' in kwargs and 'pt2' in kwargs, 'Error:, two points \ + if psType == "x" or psType == "y" or psType == "z": + assert ( + "pt1" in kwargs and "pt2" in kwargs + ), "Error:, two points \ must be specified with initialization type x,y, or z. Points are specified \ -with kwargs pt1=[x1,y1,z1],pt2=[x2,y2,z2]' +with kwargs pt1=[x1,y1,z1],pt2=[x2,y2,z2]" - elif psType == 'quad': - assert 'pt1' in kwargs and 'pt2' in kwargs and 'pt3' in kwargs \ - and 'pt4' in kwargs, 'Error:, four points \ + elif psType == "quad": + assert ( + "pt1" in kwargs and "pt2" in kwargs and "pt3" in kwargs and "pt4" in kwargs + ), "Error:, four points \ must be specified with initialization type quad. Points are specified \ -with kwargs pt1=[x1,y1,z1],pt2=[x2,y2,z2],pt3=[x3,y3,z3],pt4=[x4,y4,z4]' - - elif psType == 'ijkBounds': - assert 'ijkBounds' in kwargs, 'Error:, ijkBounds selection method requires a dictonary with \ - the specific ijkBounds for each volume.' +with kwargs pt1=[x1,y1,z1],pt2=[x2,y2,z2],pt3=[x3,y3,z3],pt4=[x4,y4,z4]" + elif psType == "ijkBounds": + assert ( + "ijkBounds" in kwargs + ), "Error:, ijkBounds selection method requires a dictonary with \ + the specific ijkBounds for each volume." corners = np.zeros([4, 3]) - if psType in ['x', 'y', 'z', 'corners']: - if psType == 'x': - corners[0] = kwargs['pt1'] + if psType in ["x", "y", "z", "corners"]: + if psType == "x": + corners[0] = kwargs["pt1"] - corners[1][1] = kwargs['pt2'][1] - corners[1][2] = kwargs['pt1'][2] + corners[1][1] = kwargs["pt2"][1] + corners[1][2] = kwargs["pt1"][2] - corners[2][1] = kwargs['pt1'][1] - corners[2][2] = kwargs['pt2'][2] + corners[2][1] = kwargs["pt1"][1] + corners[2][2] = kwargs["pt2"][2] - corners[3] = kwargs['pt2'] + corners[3] = kwargs["pt2"] - corners[:, 0] = 0.5*(kwargs['pt1'][0] + kwargs['pt2'][0]) + corners[:, 0] = 0.5 * (kwargs["pt1"][0] + kwargs["pt2"][0]) - elif psType == 'y': - corners[0] = kwargs['pt1'] + elif psType == "y": + corners[0] = kwargs["pt1"] - corners[1][0] = kwargs['pt2'][0] - corners[1][2] = kwargs['pt1'][2] + corners[1][0] = kwargs["pt2"][0] + corners[1][2] = kwargs["pt1"][2] - corners[2][0] = kwargs['pt1'][0] - corners[2][2] = kwargs['pt2'][2] + corners[2][0] = kwargs["pt1"][0] + corners[2][2] = kwargs["pt2"][2] - corners[3] = kwargs['pt2'] + corners[3] = kwargs["pt2"] - corners[:, 1] = 0.5*(kwargs['pt1'][1] + kwargs['pt2'][1]) + corners[:, 1] = 0.5 * (kwargs["pt1"][1] + kwargs["pt2"][1]) - elif psType == 'z': - corners[0] = kwargs['pt1'] + elif psType == "z": + corners[0] = kwargs["pt1"] - corners[1][0] = kwargs['pt2'][0] - corners[1][1] = kwargs['pt1'][1] + corners[1][0] = kwargs["pt2"][0] + corners[1][1] = kwargs["pt1"][1] - corners[2][0] = kwargs['pt1'][0] - corners[2][1] = kwargs['pt2'][1] + corners[2][0] = kwargs["pt1"][0] + corners[2][1] = kwargs["pt2"][1] - corners[3] = kwargs['pt2'] + corners[3] = kwargs["pt2"] - corners[:, 2] = 0.5*(kwargs['pt1'][2] + kwargs['pt2'][2]) + corners[:, 2] = 0.5 * (kwargs["pt1"][2] + kwargs["pt2"][2]) - elif psType == 'quad': - corners[0] = kwargs['pt1'] - corners[1] = kwargs['pt2'] - corners[2] = kwargs['pt4'] # Note the switch here from - # CC orientation - corners[3] = kwargs['pt3'] + elif psType == "quad": + corners[0] = kwargs["pt1"] + corners[1] = kwargs["pt2"] + corners[2] = kwargs["pt4"] # Note the switch here from + # CC orientation + corners[3] = kwargs["pt3"] X = corners self.box = pySpline.bilinearSurface(X) - self.type = 'box' + self.type = "box" - elif psType == 'list': + elif psType == "list": self.box = None - self.type = 'list' + self.type = "list" self.indices = np.array(args[0]) # Check if the list is unique: if len(self.indices) != len(np.unique(self.indices)): - raise ValueError('The indices provided to pointSelect are not unique.') + raise ValueError("The indices provided to pointSelect are not unique.") - elif psType == 'ijkBounds': + elif psType == "ijkBounds": - self.ijkBounds = kwargs['ijkBounds'] # Store the ijk bounds dictionary - self.type = 'ijkBounds' + self.ijkBounds = kwargs["ijkBounds"] # Store the ijk bounds dictionary + self.type = "ijkBounds" def getPoints(self, points): @@ -1397,27 +1445,29 @@ def getPoints(self, points): the point select class.""" ptList = [] indList = [] - if self.type == 'box': + if self.type == "box": for i in range(len(points)): u0, v0, D = self.box.projectPoint(points[i]) - if u0 > 0 and u0 < 1 and v0 > 0 and v0 < 1: #Its Inside + if u0 > 0 and u0 < 1 and v0 > 0 and v0 < 1: # Its Inside ptList.append(points[i]) indList.append(i) - elif self.type == 'list': + elif self.type == "list": for i in range(len(self.indices)): ptList.append(points[self.indices[i]]) indList = self.indices.copy() - elif self.type == 'ijkBounds': - raise NameError('Use PointSelect.getPoints_ijk() to return indices of an object initialized with ijkBounds.') + elif self.type == "ijkBounds": + raise NameError( + "Use PointSelect.getPoints_ijk() to return indices of an object initialized with ijkBounds." + ) return ptList, indList def getPoints_ijk(self, DVGeo): - """ Receives a DVGeo object (with an embedded FFD) and uses the ijk bounds specified in the initialization to extract + """Receives a DVGeo object (with an embedded FFD) and uses the ijk bounds specified in the initialization to extract the corresponding indices. You can only use this method if you initialized PointSelect with 'ijkBounds' option. @@ -1439,13 +1489,14 @@ def getPoints_ijk(self, DVGeo): khigh = self.ijkBounds[iVol][2][1] # Retrieve current points - indList.extend(DVGeo.FFD.topo.lIndex[iVol][ilow:ihigh,jlow:jhigh,klow:khigh].flatten()) + indList.extend(DVGeo.FFD.topo.lIndex[iVol][ilow:ihigh, jlow:jhigh, klow:khigh].flatten()) # Now get the corresponding coordinates ptList = [DVGeo.FFD.coef[ii] for ii in indList] return ptList, indList + class Topology(object): """ The base topology class from which the BlockTopology, @@ -1505,61 +1556,70 @@ class Topology(object): def __init__(self): # Not sure what should go here... - self.nVol = None; self.nFace = None; self.nEdge = None - self.nNode = None; self.nExt = None - self.mNodeEnt = None; self.mEdgeEnt = None; self.mFaceEnt = None - self.nodeLink = None; self.edgeLink = None; self.faceLink = None - self.edgeDir = None; self.faceDir = None - self.lIndex = None; self.gIndex = None - self.edges = None; self.simple = None + self.nVol = None + self.nFace = None + self.nEdge = None + self.nNode = None + self.nExt = None + self.mNodeEnt = None + self.mEdgeEnt = None + self.mFaceEnt = None + self.nodeLink = None + self.edgeLink = None + self.faceLink = None + self.edgeDir = None + self.faceDir = None + self.lIndex = None + self.gIndex = None + self.edges = None + self.simple = None self.topoType = None def _calcDGs(self, edges, edgeLink, edgeLinkSorted, edgeLinkInd): dgCounter = -1 for i in range(self.nEdge): - if edges[i][2] == -1: # Not set yet + if edges[i][2] == -1: # Not set yet dgCounter += 1 edges[i][2] = dgCounter - self._addDGEdge(i, edges, edgeLink, - edgeLinkSorted, edgeLinkInd) + self._addDGEdge(i, edges, edgeLink, edgeLinkSorted, edgeLinkInd) self.nDG = dgCounter + 1 def _addDGEdge(self, i, edges, edgeLink, edgeLinkSorted, edgeLinkInd): - left = edgeLinkSorted.searchsorted(i, side='left') - right = edgeLinkSorted.searchsorted(i, side='right') - res = edgeLinkInd[slice(left, right)] + left = edgeLinkSorted.searchsorted(i, side="left") + right = edgeLinkSorted.searchsorted(i, side="right") + res = edgeLinkInd[slice(left, right)] for j in range(len(res)): - ient = res[j]//self.mEdgeEnt + ient = res[j] // self.mEdgeEnt iedge = np.mod(res[j], self.mEdgeEnt) pEdges = self._getParallelEdges(iedge) oppositeEdges = [] for iii in range(len(pEdges)): - oppositeEdges.append( - edgeLink[self.mEdgeEnt*ient + pEdges[iii]]) + oppositeEdges.append(edgeLink[self.mEdgeEnt * ient + pEdges[iii]]) for ii in range(len(pEdges)): if edges[oppositeEdges[ii]][2] == -1: edges[oppositeEdges[ii]][2] = edges[i][2] - if not edges[oppositeEdges[ii]][0] == \ - edges[oppositeEdges[ii]][1]: - self._addDGEdge(oppositeEdges[ii], edges, - edgeLink, edgeLinkSorted, - edgeLinkInd) + if not edges[oppositeEdges[ii]][0] == edges[oppositeEdges[ii]][1]: + self._addDGEdge(oppositeEdges[ii], edges, edgeLink, edgeLinkSorted, edgeLinkInd) def _getParallelEdges(self, iedge): """Return parallel edges for surfaces and volumes""" - if self.topoType == 'surface': - if iedge == 0: return [1] - if iedge == 1: return [0] - if iedge == 2: return [3] - if iedge == 3: return [2] + if self.topoType == "surface": + if iedge == 0: + return [1] + if iedge == 1: + return [0] + if iedge == 2: + return [3] + if iedge == 3: + return [2] - if self.topoType == 'volume': + if self.topoType == "volume": if iedge == 0: return [1, 4, 5] if iedge == 1: @@ -1584,168 +1644,212 @@ def _getParallelEdges(self, iedge): return [8, 9, 11] if iedge == 11: return [8, 9, 10] - if self.topoType == 'curve': + if self.topoType == "curve": return None def printConnectivity(self): """Print the Edge Connectivity to the screen""" - print('-----------------------------------------------\ --------------------------') - print('%4d %4d %4d %4d %4d '%( - self.nNode, self.nEdge, self.nFace, self.nVol, self.nDG)) + print( + "-----------------------------------------------\ +-------------------------" + ) + print("%4d %4d %4d %4d %4d " % (self.nNode, self.nEdge, self.nFace, self.nVol, self.nDG)) nList = self._getDGList() - print('Design Group | Number') + print("Design Group | Number") for i in range(self.nDG): - print('%5d | %5d '%(i, nList[i])) + print("%5d | %5d " % (i, nList[i])) # Always have edges! - print('Edge Number | n0 | n1 | Cont | Degen | Intsct|\ - DG | N |') + print( + "Edge Number | n0 | n1 | Cont | Degen | Intsct|\ + DG | N |" + ) for i in range(len(self.edges)): self.edges[i].writeInfo(i, sys.stdout) - print('%9s Num |'% (self.topoType),) + print( + "%9s Num |" % (self.topoType), + ) for i in range(self.mNodeEnt): - print(' n%2d|'% (i),) + print( + " n%2d|" % (i), + ) for i in range(self.mEdgeEnt): - print(' e%2d|'% (i), ) - print(' ')# Get New line + print( + " e%2d|" % (i), + ) + print(" ") # Get New line for i in range(self.nEnt): - print(' %5d |'% (i),) + print( + " %5d |" % (i), + ) for j in range(self.mNodeEnt): - print('%4d|'%self.nodeLink[i][j],) + print( + "%4d|" % self.nodeLink[i][j], + ) for j in range(self.mEdgeEnt): - print('%4d|'% (self.edgeLink[i][j]*self.edgeDir[i][j]),) - print(' ') - - print('----------------------------------------------------\ ---------------------') - - if self.topoType == 'volume': - print('Vol Number | f0 | f1 | f2 | f3 | f4 | f5 |f0dir|\ -f1dir|f2dir|f3dir|f4dir|f5dir|') + print( + "%4d|" % (self.edgeLink[i][j] * self.edgeDir[i][j]), + ) + print(" ") + + print( + "----------------------------------------------------\ +--------------------" + ) + + if self.topoType == "volume": + print( + "Vol Number | f0 | f1 | f2 | f3 | f4 | f5 |f0dir|\ +f1dir|f2dir|f3dir|f4dir|f5dir|" + ) for i in range(self.nVol): - print(' %5d |%4d|%4d|%4d|%4d|%4d|%4d|%5d|%5d|\ -%5d|%5d|%5d|%5d|'\ - %(i, self.faceLink[i][0], self.faceLink[i][1], - self.faceLink[i][2], self.faceLink[i][3], - self.faceLink[i][3], self.faceLink[i][5], - self.faceDir[i][0], self.faceDir[i][1], - self.faceDir[i][2], self.faceDir[i][3], - self.faceDir[i][4], self.faceDir[i][5])) + print( + " %5d |%4d|%4d|%4d|%4d|%4d|%4d|%5d|%5d|\ +%5d|%5d|%5d|%5d|" + % ( + i, + self.faceLink[i][0], + self.faceLink[i][1], + self.faceLink[i][2], + self.faceLink[i][3], + self.faceLink[i][3], + self.faceLink[i][5], + self.faceDir[i][0], + self.faceDir[i][1], + self.faceDir[i][2], + self.faceDir[i][3], + self.faceDir[i][4], + self.faceDir[i][5], + ) + ) def writeConnectivity(self, fileName): """Write the full edge connectivity to a file fileName""" - f = open(fileName, 'w') - f.write('%4d %4d %4d %4d %4d\n'%( - self.nNode, self.nEdge, self.nFace, self.nVol, self.nDG)) - f.write('Design Group | Number\n') - # Write out the design groups and their number parameter + f = open(fileName, "w") + f.write("%4d %4d %4d %4d %4d\n" % (self.nNode, self.nEdge, self.nFace, self.nVol, self.nDG)) + f.write("Design Group | Number\n") + # Write out the design groups and their number parameter nList = self._getDGList() for i in range(self.nDG): - f.write('%5d | %5d \n'%(i, nList[i])) + f.write("%5d | %5d \n" % (i, nList[i])) - f.write('Edge Number | n0 | n1 | Cont | Degen |\ - Intsct| DG | N |\n') + f.write( + "Edge Number | n0 | n1 | Cont | Degen |\ + Intsct| DG | N |\n" + ) for i in range(len(self.edges)): self.edges[i].writeInfo(i, f) - f.write('%9s Num |'%(self.topoType)) + f.write("%9s Num |" % (self.topoType)) for i in range(self.mNodeEnt): - f.write(' n%2d|'%(i)) + f.write(" n%2d|" % (i)) for i in range(self.mEdgeEnt): - f.write(' e%2d|'%(i)) - f.write('\n') + f.write(" e%2d|" % (i)) + f.write("\n") for i in range(self.nEnt): - f.write(' %5d |'%(i)) + f.write(" %5d |" % (i)) for j in range(self.mNodeEnt): - f.write('%4d|'%self.nodeLink[i][j]) + f.write("%4d|" % self.nodeLink[i][j]) for j in range(self.mEdgeEnt): - f.write('%4d|'%(self.edgeLink[i][j]*self.edgeDir[i][j])) + f.write("%4d|" % (self.edgeLink[i][j] * self.edgeDir[i][j])) - f.write('\n') + f.write("\n") - if self.topoType == 'volume': + if self.topoType == "volume": - f.write('Vol Number | f0 | f1 | f2 | f3 | f4 | f5 |\ -f0dir|f1dir|f2dir|f3dir|f4dir|f5dir|\n') + f.write( + "Vol Number | f0 | f1 | f2 | f3 | f4 | f5 |\ +f0dir|f1dir|f2dir|f3dir|f4dir|f5dir|\n" + ) for i in range(self.nVol): - f.write(' %5d |%4d|%4d|%4d|%4d|%4d|%4d|%5d|\ -%5d|%5d|%5d|%5d|%5d|\n'% (i, self.faceLink[i][0], self.faceLink[i][1], - self.faceLink[i][2], self.faceLink[i][3], - self.faceLink[i][4], self.faceLink[i][5], - self.faceDir[i][0], self.faceDir[i][1], - self.faceDir[i][2], self.faceDir[i][3], - self.faceDir[i][4], self.faceDir[i][5])) + f.write( + " %5d |%4d|%4d|%4d|%4d|%4d|%4d|%5d|\ +%5d|%5d|%5d|%5d|%5d|\n" + % ( + i, + self.faceLink[i][0], + self.faceLink[i][1], + self.faceLink[i][2], + self.faceLink[i][3], + self.faceLink[i][4], + self.faceLink[i][5], + self.faceDir[i][0], + self.faceDir[i][1], + self.faceDir[i][2], + self.faceDir[i][3], + self.faceDir[i][4], + self.faceDir[i][5], + ) + ) f.close() def readConnectivity(self, fileName): """Read the full edge connectivity from a file fileName""" # We must be able to populate the following: - #nNode, nEdge, nFace,nVol,nodeLink,edgeLink, + # nNode, nEdge, nFace,nVol,nodeLink,edgeLink, # faceLink,edgeDir,faceDir - f = open(fileName, 'r') + f = open(fileName, "r") aux = f.readline().split() self.nNode = int(aux[0]) self.nEdge = int(aux[1]) self.nFace = int(aux[2]) - self.nVol = int(aux[3]) - self.nDG = int(aux[4]) + self.nVol = int(aux[3]) + self.nDG = int(aux[4]) self.edges = [] - if self.topoType == 'volume': + if self.topoType == "volume": self.nEnt = self.nVol - elif self.topoType == 'surface': + elif self.topoType == "surface": self.nEnt = self.nFace - elif self.topoType == 'curve': + elif self.topoType == "curve": self.nEnt = self.nEdge - f.readline() # This is the header line so ignore + f.readline() # This is the header line so ignore - nList = np.zeros(self.nDG, 'intc') + nList = np.zeros(self.nDG, "intc") for i in range(self.nDG): - aux = f.readline().split('|') + aux = f.readline().split("|") nList[i] = int(aux[1]) - f.readline() # Second Header line + f.readline() # Second Header line for i in range(self.nEdge): - aux = f.readline().split('|') - self.edges.append(Edge(int(aux[1]), int(aux[2]), int(aux[3]), - int(aux[4]), int(aux[5]), int(aux[6]), - int(aux[7]))) + aux = f.readline().split("|") + self.edges.append( + Edge(int(aux[1]), int(aux[2]), int(aux[3]), int(aux[4]), int(aux[5]), int(aux[6]), int(aux[7])) + ) - f.readline() # This is the third header line so ignore + f.readline() # This is the third header line so ignore - self.edgeLink = np.zeros((self.nEnt, self.mEdgeEnt), 'intc') - self.nodeLink = np.zeros((self.nEnt, self.mNodeEnt), 'intc') - self.edgeDir = np.zeros((self.nEnt, self.mEdgeEnt), 'intc') + self.edgeLink = np.zeros((self.nEnt, self.mEdgeEnt), "intc") + self.nodeLink = np.zeros((self.nEnt, self.mNodeEnt), "intc") + self.edgeDir = np.zeros((self.nEnt, self.mEdgeEnt), "intc") for i in range(self.nEnt): - aux = f.readline().split('|') + aux = f.readline().split("|") for j in range(self.mNodeEnt): - self.nodeLink[i][j] = int(aux[j+1]) + self.nodeLink[i][j] = int(aux[j + 1]) for j in range(self.mEdgeEnt): - self.edgeDir[i][j] = np.sign(int(aux[j+1+self.mNodeEnt])) - self.edgeLink[i][j] = int( - aux[j+1+self.mNodeEnt])*self.edgeDir[i][j] + self.edgeDir[i][j] = np.sign(int(aux[j + 1 + self.mNodeEnt])) + self.edgeLink[i][j] = int(aux[j + 1 + self.mNodeEnt]) * self.edgeDir[i][j] - if self.topoType == 'volume': - f.readline() # This the fourth header line so ignore + if self.topoType == "volume": + f.readline() # This the fourth header line so ignore - self.faceLink = np.zeros((self.nVol, 6), 'intc') - self.faceDir = np.zeros((self.nVol, 6), 'intc') + self.faceLink = np.zeros((self.nVol, 6), "intc") + self.faceDir = np.zeros((self.nVol, 6), "intc") for ivol in range(self.nVol): - aux = f.readline().split('|') + aux = f.readline().split("|") self.faceLink[ivol] = [int(aux[i]) for i in range(1, 7)] - self.faceDir[ivol] = [int(aux[i]) for i in range(7, 13)] + self.faceDir[ivol] = [int(aux[i]) for i in range(7, 13)] # Set the nList to the edges for iedge in range(self.nEdge): @@ -1760,26 +1864,28 @@ def _getDGList(self): # This can be run in linear time...just loop over each edge # and add to dg list - nList = np.zeros(self.nDG, 'intc') + nList = np.zeros(self.nDG, "intc") for iedge in range(self.nEdge): nList[self.edges[iedge].dg] = self.edges[iedge].N return nList + class CurveTopology(Topology): """ See topology class for more information """ + def __init__(self, coords=None, file=None): """Initialize the class with data required to compute the topology""" Topology.__init__(self) self.mNodeEnt = 2 self.mEdgeEnt = 1 self.mfaceEnt = 0 - self.mVolEnt = 0 + self.mVolEnt = 0 self.nVol = 0 self.nFace = 0 - self.topoType = 'curve' + self.topoType = "curve" self.gIndex = None self.lIndex = None self.nGlobal = None @@ -1793,16 +1899,16 @@ def __init__(self, coords=None, file=None): # Must have curves # Get the end points of each curve self.nEdge = len(coords) - coords = coords.reshape((self.nEdge*2, 3)) + coords = coords.reshape((self.nEdge * 2, 3)) nodeList, self.nodeLink = pointReduce(coords) self.nodeLink = self.nodeLink.reshape((self.nEdge, 2)) self.nNode = len(nodeList) self.edges = [] - self.edgeLink = np.zeros((self.nEdge, 1), 'intc') + self.edgeLink = np.zeros((self.nEdge, 1), "intc") for iedge in range(self.nEdge): self.edgeLink[iedge][0] = iedge - self.edgeDir = np.zeros((self.nEdge, 1), 'intc') + self.edgeDir = np.zeros((self.nEdge, 1), "intc") for iedge in range(self.nEdge): n1 = self.nodeLink[iedge][0] @@ -1831,14 +1937,16 @@ def calcGlobalNumbering(self, sizes, curveList=None): counter = 0 lIndex = [] - assert len(sizes) == len(curveList), 'Error: The list of sizes and \ -the list of surfaces must be the same length' + assert len(sizes) == len( + curveList + ), "Error: The list of sizes and \ +the list of surfaces must be the same length" # Assign unique numbers to the corners -> Corners are indexed # sequentially nodeIndex = np.arange(self.nNode) counter = len(nodeIndex) - edgeIndex = [ [] for i in range(len(self.edges))] + edgeIndex = [[] for i in range(len(self.edges))] # Assign unique numbers to the edges for ii in range(len(curveList)): @@ -1847,31 +1955,31 @@ def calcGlobalNumbering(self, sizes, curveList=None): for iedge in range(1): edge = self.edgeLink[ii][iedge] - if edgeIndex[edge] == []:# Not added yet - for jj in range(curSize[iedge]-2): + if edgeIndex[edge] == []: # Not added yet + for jj in range(curSize[iedge] - 2): edgeIndex[edge].append(counter) counter += 1 - gIndex = [ [] for i in range(counter)] # We must add [] for - # each global node + gIndex = [[] for i in range(counter)] # We must add [] for + # each global node for ii in range(len(curveList)): icurve = curveList[ii] N = sizes[ii] - lIndex.append(-1*np.ones(N, 'intc')) + lIndex.append(-1 * np.ones(N, "intc")) for i in range(N): _type, node = indexPosition1D(i, N) - if _type == 1: # Node + if _type == 1: # Node curNode = self.nodeLink[ii][node] lIndex[ii][i] = nodeIndex[curNode] gIndex[nodeIndex[curNode]].append([icurve, i]) else: if self.edgeDir[ii][0] == -1: - curIndex = edgeIndex[self.edgeLink[ii][0]][N-i-2] + curIndex = edgeIndex[self.edgeLink[ii][0]][N - i - 2] else: - curIndex = edgeIndex[self.edgeLink[ii][0]][i-1] + curIndex = edgeIndex[self.edgeLink[ii][0]][i - 1] lIndex[ii][i] = curIndex gIndex[curIndex].append([icurve, i]) @@ -1882,20 +1990,21 @@ def calcGlobalNumbering(self, sizes, curveList=None): return + class SurfaceTopology(Topology): """ See topology class for more information """ - def __init__(self, coords=None, faceCon=None, fileName=None, nodeTol=1e-4, - edgeTol=1e-4): + + def __init__(self, coords=None, faceCon=None, fileName=None, nodeTol=1e-4, edgeTol=1e-4): """Initialize the class with data required to compute the topology""" Topology.__init__(self) self.mNodeEnt = 4 self.mEdgeEnt = 4 self.mfaceEnt = 1 - self.mVolEnt = 0 + self.mVolEnt = 0 self.nVol = 0 - self.topoType = 'surface' + self.topoType = "surface" self.gIndex = None self.lIndex = None self.nGlobal = None @@ -1915,7 +2024,7 @@ def __init__(self, coords=None, faceCon=None, fileName=None, nodeTol=1e-4, self.simple = True # Check to make sure nodes are sequential self.nNode = len(unique(faceCon.flatten())) - if self.nNode != max(faceCon.flatten())+1: + if self.nNode != max(faceCon.flatten()) + 1: # We don't have sequential nodes print("Error: Nodes are not sequential") sys.exit(1) @@ -1929,33 +2038,31 @@ def __init__(self, coords=None, faceCon=None, fileName=None, nodeTol=1e-4, edges.append([faceCon[iface][0], faceCon[iface][2], -1, 0, 0]) edges.append([faceCon[iface][1], faceCon[iface][3], -1, 0, 0]) - edgeDir = np.ones(len(edges), 'intc') - for iedge in range(self.nFace*4): + edgeDir = np.ones(len(edges), "intc") + for iedge in range(self.nFace * 4): if edges[iedge][0] > edges[iedge][1]: temp = edges[iedge][0] edges[iedge][0] = edges[iedge][1] edges[iedge][1] = temp edgeDir[iedge] = -1 - edgeHash.append( - edges[iedge][0]*4*self.nFace + edges[iedge][1]) + edgeHash.append(edges[iedge][0] * 4 * self.nFace + edges[iedge][1]) edges, edgeLink = uniqueIndex(edges, edgeHash) self.nEdge = len(edges) self.edgeLink = np.array(edgeLink).reshape((self.nFace, 4)) self.nodeLink = np.array(faceCon) - self.edgeDir = np.array(edgeDir).reshape((self.nFace, 4)) + self.edgeDir = np.array(edgeDir).reshape((self.nFace, 4)) edgeLinkSorted = np.sort(edgeLink) - edgeLinkInd = np.argsort(edgeLink) + edgeLinkInd = np.argsort(edgeLink) elif coords is not None: self.nFace = len(coords) - self.nEnt = self.nFace + self.nEnt = self.nFace # We can use the pointReduce algorithim on the nodes - nodeList, nodeLink = pointReduce( - coords[:, 0:4, :].reshape((self.nFace*4, 3)), nodeTol) + nodeList, nodeLink = pointReduce(coords[:, 0:4, :].reshape((self.nFace * 4, 3)), nodeTol) nodeLink = nodeLink.reshape((self.nFace, 4)) # Next Calculate the EDGE connectivity. -- This is Still @@ -1963,8 +2070,8 @@ def __init__(self, coords=None, faceCon=None, fileName=None, nodeTol=1e-4, edges = [] midpoints = [] - edgeLink = -1*np.ones(self.nFace*4, 'intc') - edgeDir = np.zeros((self.nFace, 4), 'intc') + edgeLink = -1 * np.ones(self.nFace * 4, "intc") + edgeDir = np.zeros((self.nFace, 4), "intc") for iface in range(self.nFace): for iedge in range(4): @@ -1975,20 +2082,20 @@ def __init__(self, coords=None, faceCon=None, fileName=None, nodeTol=1e-4, if len(edges) == 0: edges.append([n1, n2, -1, 0, 0]) midpoints.append(midpoint) - edgeLink[4*iface + iedge] = 0 - edgeDir [iface][iedge] = 1 + edgeLink[4 * iface + iedge] = 0 + edgeDir[iface][iedge] = 1 else: foundIt = False for i in range(len(edges)): if [n1, n2] == edges[i][0:2] and n1 != n2: if eDist(midpoint, midpoints[i]) < edgeTol: - edgeLink[4*iface + iedge] = i - edgeDir [iface][iedge] = 1 + edgeLink[4 * iface + iedge] = i + edgeDir[iface][iedge] = 1 foundIt = True elif [n2, n1] == edges[i][0:2] and n1 != n2: if eDist(midpoint, midpoints[i]) < edgeTol: - edgeLink[4*iface + iedge] = i + edgeLink[4 * iface + iedge] = i edgeDir[iface][iedge] = -1 foundIt = True # end for @@ -1998,8 +2105,8 @@ def __init__(self, coords=None, faceCon=None, fileName=None, nodeTol=1e-4, if not foundIt: edges.append([n1, n2, -1, 0, 0]) midpoints.append(midpoint) - edgeLink[4*iface + iedge] = i+1 - edgeDir [iface][iedge] = 1 + edgeLink[4 * iface + iedge] = i + 1 + edgeDir[iface][iedge] = 1 # end for (iFace) self.nEdge = len(edges) @@ -2009,7 +2116,7 @@ def __init__(self, coords=None, faceCon=None, fileName=None, nodeTol=1e-4, self.edgeDir = edgeDir edgeLinkSorted = np.sort(edgeLink.flatten()) - edgeLinkInd = np.argsort(edgeLink.flatten()) + edgeLinkInd = np.argsort(edgeLink.flatten()) # end if # Next Calculate the Design Group Information @@ -2017,18 +2124,14 @@ def __init__(self, coords=None, faceCon=None, fileName=None, nodeTol=1e-4, # Set the edge ojects self.edges = [] - for i in range(self.nEdge): # Create the edge objects - if midpoints: # If they exist - if edges[i][0] == edges[i][1] and \ - eDist(midpoints[i], nodeList[edges[i][0]]) < nodeTol: - self.edges.append(Edge(edges[i][0], edges[i][1], - 0, 1, 0, edges[i][2], edges[i][3])) + for i in range(self.nEdge): # Create the edge objects + if midpoints: # If they exist + if edges[i][0] == edges[i][1] and eDist(midpoints[i], nodeList[edges[i][0]]) < nodeTol: + self.edges.append(Edge(edges[i][0], edges[i][1], 0, 1, 0, edges[i][2], edges[i][3])) else: - self.edges.append(Edge(edges[i][0], edges[i][1], - 0, 0, 0, edges[i][2], edges[i][3])) + self.edges.append(Edge(edges[i][0], edges[i][1], 0, 0, 0, edges[i][2], edges[i][3])) else: - self.edges.append(Edge(edges[i][0], edges[i][1], - 0, 0, 0, edges[i][2], edges[i][3])) + self.edges.append(Edge(edges[i][0], edges[i][1], 0, 0, 0, edges[i][2], edges[i][3])) def calcGlobalNumberingDummy(self, sizes, surfaceList=None): """Internal function to calculate the global/local numbering @@ -2044,32 +2147,33 @@ def calcGlobalNumberingDummy(self, sizes, surfaceList=None): # ----------------- Start of Edge Computation --------------------- counter = 0 - assert len(sizes) == len(surfaceList), 'Error: The list of sizes and \ -the list of surfaces must be the same length' + assert len(sizes) == len( + surfaceList + ), "Error: The list of sizes and \ +the list of surfaces must be the same length" # Assign unique numbers to the corners -> Corners are indexed # sequentially nodeIndex = np.arange(self.nNode) counter = len(nodeIndex) - edgeIndex = [ [] for i in range(len(self.edges))] + edgeIndex = [[] for i in range(len(self.edges))] # Assign unique numbers to the edges for ii in range(len(surfaceList)): iSurf = surfaceList[ii] - curSize = [sizes[iSurf][0], sizes[iSurf][0], - sizes[iSurf][1], sizes[iSurf][1]] + curSize = [sizes[iSurf][0], sizes[iSurf][0], sizes[iSurf][1], sizes[iSurf][1]] for iedge in range(4): edge = self.edgeLink[ii][iedge] - if edgeIndex[edge] == []:# Not added yet + if edgeIndex[edge] == []: # Not added yet if self.edges[edge].degen == 1: # Get the counter value for this "node" index = nodeIndex[self.edges[edge].n1] - for jj in range(curSize[iedge]-2): + for jj in range(curSize[iedge] - 2): edgeIndex[edge].append(index) else: - for jj in range(curSize[iedge]-2): + for jj in range(curSize[iedge] - 2): edgeIndex[edge].append(counter) counter += 1 @@ -2079,7 +2183,7 @@ def calcGlobalNumberingDummy(self, sizes, surfaceList=None): isurf = surfaceList[ii] N = sizes[iSurf][0] M = sizes[iSurf][1] - lIndex.append(-1*np.ones((N, M), 'intc')) + lIndex.append(-1 * np.ones((N, M), "intc")) self.lIndex = lIndex @@ -2100,14 +2204,16 @@ def calcGlobalNumbering(self, sizes, surfaceList=None): gIndex = [] lIndex = [] - assert len(sizes) == len(surfaceList), 'Error: The list of sizes and \ -the list of surfaces must be the same length' + assert len(sizes) == len( + surfaceList + ), "Error: The list of sizes and \ +the list of surfaces must be the same length" # Assign unique numbers to the corners -> Corners are indexed # sequentially nodeIndex = np.arange(self.nNode) counter = len(nodeIndex) - edgeIndex = [ [] for i in range(len(self.edges))] + edgeIndex = [[] for i in range(len(self.edges))] # Assign unique numbers to the edges for ii in range(len(surfaceList)): @@ -2116,64 +2222,60 @@ def calcGlobalNumbering(self, sizes, surfaceList=None): for iedge in range(4): edge = self.edgeLink[ii][iedge] - if edgeIndex[edge] == []:# Not added yet + if edgeIndex[edge] == []: # Not added yet if self.edges[edge].degen == 1: # Get the counter value for this "node" index = nodeIndex[self.edges[edge].n1] - for jj in range(curSize[iedge]-2): + for jj in range(curSize[iedge] - 2): edgeIndex[edge].append(index) else: - for jj in range(curSize[iedge]-2): + for jj in range(curSize[iedge] - 2): edgeIndex[edge].append(counter) counter += 1 - gIndex = [ [] for i in range(counter)] # We must add [] for - # each global node + gIndex = [[] for i in range(counter)] # We must add [] for + # each global node lIndex = [] # Now actually fill everything up for ii in range(len(surfaceList)): isurf = surfaceList[ii] N = sizes[ii][0] M = sizes[ii][1] - lIndex.append(-1*np.ones((N, M), 'intc')) + lIndex.append(-1 * np.ones((N, M), "intc")) for i in range(N): for j in range(M): _type, edge, node, index = indexPosition2D(i, j, N, M) - if _type == 0: # Interior + if _type == 0: # Interior lIndex[ii][i, j] = counter gIndex.append([[isurf, i, j]]) counter += 1 - elif _type == 1: # Edge + elif _type == 1: # Edge if edge in [0, 1]: # Its a reverse dir if self.edgeDir[ii][edge] == -1: - curIndex = edgeIndex[ - self.edgeLink[ii][edge]][N-i-2] + curIndex = edgeIndex[self.edgeLink[ii][edge]][N - i - 2] else: - curIndex = edgeIndex[ - self.edgeLink[ii][edge]][i-1] - else: # edge in [2, 3] + curIndex = edgeIndex[self.edgeLink[ii][edge]][i - 1] + else: # edge in [2, 3] # Its a reverse dir if self.edgeDir[ii][edge] == -1: - curIndex = edgeIndex[ - self.edgeLink[ii][edge]][M-j-2] + curIndex = edgeIndex[self.edgeLink[ii][edge]][M - j - 2] else: - curIndex = edgeIndex[ - self.edgeLink[ii][edge]][j-1] + curIndex = edgeIndex[self.edgeLink[ii][edge]][j - 1] lIndex[ii][i, j] = curIndex gIndex[curIndex].append([isurf, i, j]) - else: # Node + else: # Node curNode = self.nodeLink[ii][node] lIndex[ii][i, j] = nodeIndex[curNode] gIndex[nodeIndex[curNode]].append([isurf, i, j]) # end for (surface loop) # Reorder the indices with a greedy scheme - newIndices = np.zeros(len(gIndex), 'intc') + newIndices = np.zeros(len(gIndex), "intc") newIndices[:] = -1 newGIndex = [[] for i in range(len(gIndex))] counter = 0 @@ -2195,8 +2297,8 @@ def calcGlobalNumbering(self, sizes, surfaceList=None): # Re-order the gIndex for ii in range(len(gIndex)): isurf = gIndex[ii][0][0] - i = gIndex[ii][0][1] - j = gIndex[ii][0][2] + i = gIndex[ii][0][1] + j = gIndex[ii][0][2] pt = lIndex[isurf][i, j] newGIndex[pt] = gIndex[ii] @@ -2206,7 +2308,7 @@ def calcGlobalNumbering(self, sizes, surfaceList=None): return - def getSurfaceFromEdge(self, edge): + def getSurfaceFromEdge(self, edge): """Determine the surfaces and their edgeLink index that points to edge iedge""" # Its not efficient but it works - scales with Nface not constant @@ -2228,14 +2330,14 @@ def makeSizesConsistent(self, sizes, order): """ # First determine how many "order" loops we have - nloops = max(order)+1 - edgeNumber = -1*np.ones(self.nDG, 'intc') + nloops = max(order) + 1 + edgeNumber = -1 * np.ones(self.nDG, "intc") for iedge in range(self.nEdge): self.edges[iedge].N = -1 for iloop in range(nloops): for iface in range(self.nFace): - if order[iface] == iloop: # Set this edge + if order[iface] == iloop: # Set this edge for iedge in range(4): dg = self.edges[self.edgeLink[iface][iedge]].dg if edgeNumber[dg] == -1: @@ -2247,7 +2349,7 @@ def makeSizesConsistent(self, sizes, order): # Now re-populate the sizes: for iface in range(self.nFace): for i in [0, 1]: - dg = self.edges[self.edgeLink[iface][i*2]].dg + dg = self.edges[self.edgeLink[iface][i * 2]].dg sizes[iface][i] = edgeNumber[dg] # And return the number of elements on each actual edge @@ -2258,6 +2360,7 @@ def makeSizesConsistent(self, sizes, order): return sizes, nEdge + class BlockTopology(Topology): """ See Topology base class for more information @@ -2270,8 +2373,8 @@ def __init__(self, coords=None, nodeTol=1e-4, edgeTol=1e-4, fileName=None): self.mNodeEnt = 8 self.mEdgeEnt = 12 self.mFaceEnt = 6 - self.mVolEnt = 1 - self.topoType = 'volume' + self.mVolEnt = 1 + self.topoType = "volume" self.gIndex = None self.lIndex = None self.nGlobal = None @@ -2282,9 +2385,9 @@ def __init__(self, coords=None, nodeTol=1e-4, edgeTol=1e-4, fileName=None): coords = np.atleast_2d(coords) nVol = len(coords) - if coords.shape[1] == 8: # Just the corners are given --- Just - # put in np.zeros for the edge and face - # mid points + if coords.shape[1] == 8: # Just the corners are given --- Just + # put in np.zeros for the edge and face + # mid points temp = np.zeros((nVol, (8 + 12 + 6), 3)) temp[:, 0:8, :] = coords coords = temp.copy() @@ -2294,14 +2397,13 @@ def __init__(self, coords=None, nodeTol=1e-4, edgeTol=1e-4, fileName=None): # ---------------------------------------------------------- # Do the pointReduce Agorithm on the corners - un, nodeLink = pointReduce(coords[:, 0:8, :].reshape((nVol*8, 3)), - nodeTol=nodeTol) + un, nodeLink = pointReduce(coords[:, 0:8, :].reshape((nVol * 8, 3)), nodeTol=nodeTol) nodeLink = nodeLink.reshape((nVol, 8)) # ---------------------------------------------------------- # Unique Edges # ---------------------------------------------------------- - # Now determine the unique edges: + # Now determine the unique edges: edgeObjs = [] origEdges = [] for ivol in range(nVol): @@ -2320,20 +2422,18 @@ def __init__(self, coords=None, nodeTol=1e-4, edgeTol=1e-4, fileName=None): ns = sorted([n1, n2]) # Append the new edgeCmp Object - edgeObjs.append(EdgeCmpObject( - ns[0], ns[1], n1, n2, midpoint, edgeTol)) + edgeObjs.append(EdgeCmpObject(ns[0], ns[1], n1, n2, midpoint, edgeTol)) # Keep track of original edge orientation---needed for # face direction origEdges.append([n1, n2]) # Generate unique set of edges - uniqueEdgeObjs, edgeLink = uniqueIndex(edgeObjs) + uniqueEdgeObjs, edgeLink = uniqueIndex(edgeObjs) edgeDir = [] - for i in range(len(edgeObjs)): # This is nVol * 12 - edgeDir.append(edgeOrientation( - origEdges[i], uniqueEdgeObjs[edgeLink[i]].nodes)) + for i in range(len(edgeObjs)): # This is nVol * 12 + edgeDir.append(edgeOrientation(origEdges[i], uniqueEdgeObjs[edgeLink[i]].nodes)) # ---------------------------------------------------------- # Unique Faces # ---------------------------------------------------------- @@ -2356,9 +2456,7 @@ def __init__(self, coords=None, nodeTol=1e-4, edgeTol=1e-4, fileName=None): # Sort the nodes before they go into the faceObject ns = sorted([n1, n2, n3, n4]) - faceObjs.append(FaceCmpObject(ns[0], ns[1], ns[2], ns[3], - n1, n2, n3, n4, - midpoint, 1e-4)) + faceObjs.append(FaceCmpObject(ns[0], ns[1], ns[2], ns[3], n1, n2, n3, n4, midpoint, 1e-4)) # Keep track of original face orientation---needed for # face direction origFaces.append([n1, n2, n3, n4]) @@ -2368,48 +2466,43 @@ def __init__(self, coords=None, nodeTol=1e-4, edgeTol=1e-4, fileName=None): faceDir = [] faceDirRev = [] - for i in range(len(faceObjs)): # This is nVol * 12 - faceDir.append(faceOrientation( - uniqueFaceObjs[faceLink[i]].nodes, origFaces[i])) - faceDirRev.append(faceOrientation( - origFaces[i], uniqueFaceObjs[faceLink[i]].nodes)) + for i in range(len(faceObjs)): # This is nVol * 12 + faceDir.append(faceOrientation(uniqueFaceObjs[faceLink[i]].nodes, origFaces[i])) + faceDirRev.append(faceOrientation(origFaces[i], uniqueFaceObjs[faceLink[i]].nodes)) # --------- Set the Requried Data for this class ------------ self.nNode = len(un) self.nEdge = len(uniqueEdgeObjs) self.nFace = len(uniqueFaceObjs) - self.nVol = len(coords) - self.nEnt = self.nVol + self.nVol = len(coords) + self.nEnt = self.nVol self.nodeLink = nodeLink self.edgeLink = np.array(edgeLink).reshape((nVol, 12)) self.faceLink = np.array(faceLink).reshape((nVol, 6)) - self.edgeDir = np.array(edgeDir).reshape((nVol, 12)) - self.faceDir = np.array(faceDir).reshape((nVol, 6)) - self.faceDirRev = np.array(faceDirRev).reshape((nVol, 6)) + self.edgeDir = np.array(edgeDir).reshape((nVol, 12)) + self.faceDir = np.array(faceDir).reshape((nVol, 6)) + self.faceDirRev = np.array(faceDirRev).reshape((nVol, 6)) # Next Calculate the Design Group Information edgeLinkSorted = np.sort(edgeLink.flatten()) - edgeLinkInd = np.argsort(edgeLink.flatten()) + edgeLinkInd = np.argsort(edgeLink.flatten()) ue = [] for i in range(len(uniqueEdgeObjs)): - ue.append([uniqueEdgeObjs[i].nodes[0], - uniqueEdgeObjs[i].nodes[1], -1, 0, 0]) + ue.append([uniqueEdgeObjs[i].nodes[0], uniqueEdgeObjs[i].nodes[1], -1, 0, 0]) self._calcDGs(ue, edgeLink, edgeLinkSorted, edgeLinkInd) # Set the edge ojects self.edges = [] - for i in range(self.nEdge): # Create the edge objects - self.edges.append(Edge( - ue[i][0], ue[i][1], 0, 0, 0, ue[i][2], ue[i][3])) + for i in range(self.nEdge): # Create the edge objects + self.edges.append(Edge(ue[i][0], ue[i][1], 0, 0, 0, ue[i][2], ue[i][3])) return - def calcGlobalNumbering(self, sizes=None, volumeList=None, - greedyReorder=False,gIndex=True): + def calcGlobalNumbering(self, sizes=None, volumeList=None, greedyReorder=False, gIndex=True): """Internal function to calculate the global/local numbering for each volume""" @@ -2425,12 +2518,12 @@ def calcGlobalNumbering(self, sizes=None, volumeList=None, self.edges[self.edgeLink[i][6]].N = sizes[i][1] self.edges[self.edgeLink[i][7]].N = sizes[i][1] - self.edges[self.edgeLink[i][8]].N = sizes[i][2] - self.edges[self.edgeLink[i][9]].N = sizes[i][2] + self.edges[self.edgeLink[i][8]].N = sizes[i][2] + self.edges[self.edgeLink[i][9]].N = sizes[i][2] self.edges[self.edgeLink[i][10]].N = sizes[i][2] self.edges[self.edgeLink[i][11]].N = sizes[i][2] - else: # N is already set in the edge objects, use them - sizes = np.zeros((self.nVol, 3), 'intc') + else: # N is already set in the edge objects, use them + sizes = np.zeros((self.nVol, 3), "intc") for ivol in range(self.nVol): sizes[ivol][0] = self.edges[self.edgeLink[ivol][0]].N sizes[ivol][1] = self.edges[self.edgeLink[ivol][2]].N @@ -2444,145 +2537,140 @@ def calcGlobalNumbering(self, sizes=None, volumeList=None, gIndex = [] lIndex = [] - assert len(sizes) == len(volumeList), 'Error: The list of sizes and \ -the list of volumes must be the same length' + assert len(sizes) == len( + volumeList + ), "Error: The list of sizes and \ +the list of volumes must be the same length" # Assign unique numbers to the corners -> Corners are indexed # sequentially nodeIndex = np.arange(self.nNode) counter = len(nodeIndex) - edgeIndex = [ np.empty((0), 'intc') for i in range(self.nEdge)] - faceIndex = [ np.empty((0, 0), 'intc') for i in range(self.nFace)] + edgeIndex = [np.empty((0), "intc") for i in range(self.nEdge)] + faceIndex = [np.empty((0, 0), "intc") for i in range(self.nFace)] # Assign unique numbers to the edges for ii in range(len(volumeList)): - curSizeE = [sizes[ii][0], sizes[ii][0], sizes[ii][1], - sizes[ii][1], sizes[ii][0], sizes[ii][0], - sizes[ii][1], sizes[ii][1], sizes[ii][2], - sizes[ii][2], sizes[ii][2], sizes[ii][2]] - - curSizeF = [[sizes[ii][0], sizes[ii][1]], - [sizes[ii][0], sizes[ii][1]], - [sizes[ii][1], sizes[ii][2]], - [sizes[ii][1], sizes[ii][2]], - [sizes[ii][0], sizes[ii][2]], - [sizes[ii][0], sizes[ii][2]]] + curSizeE = [ + sizes[ii][0], + sizes[ii][0], + sizes[ii][1], + sizes[ii][1], + sizes[ii][0], + sizes[ii][0], + sizes[ii][1], + sizes[ii][1], + sizes[ii][2], + sizes[ii][2], + sizes[ii][2], + sizes[ii][2], + ] + + curSizeF = [ + [sizes[ii][0], sizes[ii][1]], + [sizes[ii][0], sizes[ii][1]], + [sizes[ii][1], sizes[ii][2]], + [sizes[ii][1], sizes[ii][2]], + [sizes[ii][0], sizes[ii][2]], + [sizes[ii][0], sizes[ii][2]], + ] ivol = volumeList[ii] for iedge in range(12): edge = self.edgeLink[ii][iedge] - if edgeIndex[edge].shape == (0, ):# Not added yet - edgeIndex[edge] = np.resize( - edgeIndex[edge], curSizeE[iedge]-2) + if edgeIndex[edge].shape == (0,): # Not added yet + edgeIndex[edge] = np.resize(edgeIndex[edge], curSizeE[iedge] - 2) if self.edges[edge].degen == 1: # Get the counter value for this "node" index = nodeIndex[self.edges[edge].n1] - for jj in range(curSizeE[iedge]-2): + for jj in range(curSizeE[iedge] - 2): edgeIndex[edge][jj] = index else: - for jj in range(curSizeE[iedge]-2): + for jj in range(curSizeE[iedge] - 2): edgeIndex[edge][jj] = counter counter += 1 for iface in range(6): face = self.faceLink[ii][iface] if faceIndex[face].shape == (0, 0): - faceIndex[face] = np.resize(faceIndex[face], - [curSizeF[iface][0]-2, - curSizeF[iface][1]-2]) - for iii in range(curSizeF[iface][0]-2): - for jjj in range(curSizeF[iface][1]-2): + faceIndex[face] = np.resize(faceIndex[face], [curSizeF[iface][0] - 2, curSizeF[iface][1] - 2]) + for iii in range(curSizeF[iface][0] - 2): + for jjj in range(curSizeF[iface][1] - 2): faceIndex[face][iii, jjj] = counter counter += 1 # end for (volume list) - gIndex = [ [] for i in range(counter)] # We must add [] for - # each global node + gIndex = [[] for i in range(counter)] # We must add [] for + # each global node lIndex = [] def addNode(i, j, k, N, M, L): _type, number, index1, index2 = indexPosition3D(i, j, k, N, M, L) - if _type == 1: # Face + if _type == 1: # Face if number in [0, 1]: - icount = i;imax = N - jcount = j;jmax = M + icount = i + imax = N + jcount = j + jmax = M elif number in [2, 3]: - icount = j;imax = M - jcount = k;jmax = L + icount = j + imax = M + jcount = k + jmax = L elif number in [4, 5]: - icount = i;imax = N - jcount = k;jmax = L + icount = i + imax = N + jcount = k + jmax = L if self.faceDir[ii][number] == 0: - curIndex = faceIndex[ - self.faceLink[ii][number]][ - icount-1, jcount-1] + curIndex = faceIndex[self.faceLink[ii][number]][icount - 1, jcount - 1] elif self.faceDir[ii][number] == 1: - curIndex = faceIndex[ - self.faceLink[ii][number]][ - imax-icount-2, jcount-1] + curIndex = faceIndex[self.faceLink[ii][number]][imax - icount - 2, jcount - 1] elif self.faceDir[ii][number] == 2: - curIndex = faceIndex[ - self.faceLink[ii][number]][ - icount-1, jmax-jcount-2] + curIndex = faceIndex[self.faceLink[ii][number]][icount - 1, jmax - jcount - 2] elif self.faceDir[ii][number] == 3: - curIndex = faceIndex[ - self.faceLink[ii][number]][ - imax-icount-2, jmax-jcount-2] + curIndex = faceIndex[self.faceLink[ii][number]][imax - icount - 2, jmax - jcount - 2] elif self.faceDir[ii][number] == 4: - curIndex = faceIndex[ - self.faceLink[ii][number]][ - jcount-1, icount-1] + curIndex = faceIndex[self.faceLink[ii][number]][jcount - 1, icount - 1] elif self.faceDir[ii][number] == 5: - curIndex = faceIndex[ - self.faceLink[ii][number]][ - jmax-jcount-2, icount-1] + curIndex = faceIndex[self.faceLink[ii][number]][jmax - jcount - 2, icount - 1] elif self.faceDir[ii][number] == 6: - curIndex = faceIndex[ - self.faceLink[ii][number]][ - jcount-1, imax-icount-2] + curIndex = faceIndex[self.faceLink[ii][number]][jcount - 1, imax - icount - 2] elif self.faceDir[ii][number] == 7: - curIndex = faceIndex[ - self.faceLink[ii][number]][ - jmax-jcount-2, imax-icount-2] + curIndex = faceIndex[self.faceLink[ii][number]][jmax - jcount - 2, imax - icount - 2] lIndex[ii][i, j, k] = curIndex gIndex[curIndex].append([ivol, i, j, k]) - elif _type == 2: # Edge + elif _type == 2: # Edge if number in [0, 1, 4, 5]: - if self.edgeDir[ii][number] == -1: # Its a reverse dir - curIndex = \ - edgeIndex[self.edgeLink[ii][number]][N-i-2] + if self.edgeDir[ii][number] == -1: # Its a reverse dir + curIndex = edgeIndex[self.edgeLink[ii][number]][N - i - 2] else: - curIndex = \ - edgeIndex[self.edgeLink[ii][number]][i-1] + curIndex = edgeIndex[self.edgeLink[ii][number]][i - 1] elif number in [2, 3, 6, 7]: - if self.edgeDir[ii][number] == -1: # Its a reverse dir - curIndex = \ - edgeIndex[self.edgeLink[ii][number]][M-j-2] + if self.edgeDir[ii][number] == -1: # Its a reverse dir + curIndex = edgeIndex[self.edgeLink[ii][number]][M - j - 2] else: - curIndex = \ - edgeIndex[self.edgeLink[ii][number]][j-1] + curIndex = edgeIndex[self.edgeLink[ii][number]][j - 1] elif number in [8, 9, 10, 11]: - if self.edgeDir[ii][number] == -1: # Its a reverse dir - curIndex = \ - edgeIndex[self.edgeLink[ii][number]][L-k-2] + if self.edgeDir[ii][number] == -1: # Its a reverse dir + curIndex = edgeIndex[self.edgeLink[ii][number]][L - k - 2] else: - curIndex = \ - edgeIndex[self.edgeLink[ii][number]][k-1] + curIndex = edgeIndex[self.edgeLink[ii][number]][k - 1] lIndex[ii][i, j, k] = curIndex gIndex[curIndex].append([ivol, i, j, k]) - elif _type == 3: # Node + elif _type == 3: # Node curNode = self.nodeLink[ii][number] lIndex[ii][i, j, k] = nodeIndex[curNode] gIndex[nodeIndex[curNode]].append([ivol, i, j, k]) @@ -2595,21 +2683,21 @@ def addNode(i, j, k, N, M, L): N = sizes[ii][0] M = sizes[ii][1] L = sizes[ii][2] - lIndex.append(-1*np.ones((N, M, L), 'intc')) + lIndex.append(-1 * np.ones((N, M, L), "intc")) # DO the 6 planes - for k in [0, L-1]: + for k in [0, L - 1]: for i in range(N): for j in range(M): addNode(i, j, k, N, M, L) - for j in [0, M-1]: + for j in [0, M - 1]: for i in range(N): - for k in range(1, L-1): + for k in range(1, L - 1): addNode(i, j, k, N, M, L) - for i in [0, N-1]: - for j in range(1, M-1): - for k in range(1, L-1): + for i in [0, N - 1]: + for j in range(1, M - 1): + for k in range(1, L - 1): addNode(i, j, k, N, M, L) # Add the remainder @@ -2619,20 +2707,18 @@ def addNode(i, j, k, N, M, L): M = sizes[ii][1] L = sizes[ii][2] - NN = sizes[ii][0]-2 - MM = sizes[ii][1]-2 - LL = sizes[ii][2]-2 + NN = sizes[ii][0] - 2 + MM = sizes[ii][1] - 2 + LL = sizes[ii][2] - 2 - toAdd = NN*MM*LL + toAdd = NN * MM * LL - lIndex[ii][1:N-1,1:M-1,1:L-1] = \ - np.arange(counter,counter+toAdd).reshape((NN,MM,LL)) + lIndex[ii][1 : N - 1, 1 : M - 1, 1 : L - 1] = np.arange(counter, counter + toAdd).reshape((NN, MM, LL)) counter = counter + toAdd - A = np.zeros((toAdd,1,4),'intc') - A[:,0,0] = ivol - A[:,0,1:] = np.mgrid[1:N-1,1:M-1,1:L-1].transpose( - (1,2,3,0)).reshape((toAdd,3)) + A = np.zeros((toAdd, 1, 4), "intc") + A[:, 0, 0] = ivol + A[:, 0, 1:] = np.mgrid[1 : N - 1, 1 : M - 1, 1 : L - 1].transpose((1, 2, 3, 0)).reshape((toAdd, 3)) gIndex.extend(A) # Set the following as atributes @@ -2643,7 +2729,7 @@ def addNode(i, j, k, N, M, L): if greedyReorder: # Reorder the indices with a greedy scheme - newIndices = np.zeros(len(gIndex), 'intc') + newIndices = np.zeros(len(gIndex), "intc") newIndices[:] = -1 newGIndex = [[] for i in range(len(gIndex))] counter = 0 @@ -2662,15 +2748,14 @@ def addNode(i, j, k, N, M, L): lIndex[ii][i, j, k] = counter counter += 1 else: - lIndex[ii][i, j, k] = \ - newIndices[lIndex[ii][i, j, k]] + lIndex[ii][i, j, k] = newIndices[lIndex[ii][i, j, k]] # Re-order the gIndex for ii in range(len(gIndex)): - ivol = gIndex[ii][0][0] - i = gIndex[ii][0][1] - j = gIndex[ii][0][2] - k = gIndex[ii][0][3] + ivol = gIndex[ii][0][0] + i = gIndex[ii][0][1] + j = gIndex[ii][0][2] + k = gIndex[ii][0][3] pt = lIndex[ivol][i, j, k] newGIndex[pt] = gIndex[ii] @@ -2680,8 +2765,7 @@ def addNode(i, j, k, N, M, L): return - def calcGlobalNumbering2(self, sizes=None, gIndex=True, volumeList=None, - greedyReorder=False): + def calcGlobalNumbering2(self, sizes=None, gIndex=True, volumeList=None, greedyReorder=False): """Internal function to calculate the global/local numbering for each volume""" if sizes is not None: @@ -2696,12 +2780,12 @@ def calcGlobalNumbering2(self, sizes=None, gIndex=True, volumeList=None, self.edges[self.edgeLink[i][6]].N = sizes[i][1] self.edges[self.edgeLink[i][7]].N = sizes[i][1] - self.edges[self.edgeLink[i][8]].N = sizes[i][2] - self.edges[self.edgeLink[i][9]].N = sizes[i][2] + self.edges[self.edgeLink[i][8]].N = sizes[i][2] + self.edges[self.edgeLink[i][9]].N = sizes[i][2] self.edges[self.edgeLink[i][10]].N = sizes[i][2] self.edges[self.edgeLink[i][11]].N = sizes[i][2] - else: # N is already set in the edge objects, use them - sizes = np.zeros((self.nVol, 3), 'intc') + else: # N is already set in the edge objects, use them + sizes = np.zeros((self.nVol, 3), "intc") for ivol in range(self.nVol): sizes[ivol][0] = self.edges[self.edgeLink[ivol][0]].N sizes[ivol][1] = self.edges[self.edgeLink[ivol][2]].N @@ -2714,56 +2798,67 @@ def calcGlobalNumbering2(self, sizes=None, gIndex=True, volumeList=None, counter = 0 lIndex = [] - assert len(sizes) == len(volumeList), 'Error: The list of sizes and \ -the list of volumes must be the same length' + assert len(sizes) == len( + volumeList + ), "Error: The list of sizes and \ +the list of volumes must be the same length" # Assign unique numbers to the corners -> Corners are indexed # sequentially nodeIndex = np.arange(self.nNode) counter = len(nodeIndex) - edgeIndex = [ np.empty((0), 'intc') for i in range(self.nEdge)] - faceIndex = [ np.empty((0, 0), 'intc') for i in range(self.nFace)] + edgeIndex = [np.empty((0), "intc") for i in range(self.nEdge)] + faceIndex = [np.empty((0, 0), "intc") for i in range(self.nFace)] # Assign unique numbers to the edges for ii in range(len(volumeList)): - curSizeE = [sizes[ii][0], sizes[ii][0], sizes[ii][1], - sizes[ii][1], sizes[ii][0], sizes[ii][0], - sizes[ii][1], sizes[ii][1], sizes[ii][2], - sizes[ii][2], sizes[ii][2], sizes[ii][2]] - - curSizeF = [[sizes[ii][0], sizes[ii][1]], - [sizes[ii][0], sizes[ii][1]], - [sizes[ii][1], sizes[ii][2]], - [sizes[ii][1], sizes[ii][2]], - [sizes[ii][0], sizes[ii][2]], - [sizes[ii][0], sizes[ii][2]]] + curSizeE = [ + sizes[ii][0], + sizes[ii][0], + sizes[ii][1], + sizes[ii][1], + sizes[ii][0], + sizes[ii][0], + sizes[ii][1], + sizes[ii][1], + sizes[ii][2], + sizes[ii][2], + sizes[ii][2], + sizes[ii][2], + ] + + curSizeF = [ + [sizes[ii][0], sizes[ii][1]], + [sizes[ii][0], sizes[ii][1]], + [sizes[ii][1], sizes[ii][2]], + [sizes[ii][1], sizes[ii][2]], + [sizes[ii][0], sizes[ii][2]], + [sizes[ii][0], sizes[ii][2]], + ] ivol = volumeList[ii] for iedge in range(12): edge = self.edgeLink[ii][iedge] - if edgeIndex[edge].shape == (0, ):# Not added yet - edgeIndex[edge] = np.resize( - edgeIndex[edge], curSizeE[iedge]-2) + if edgeIndex[edge].shape == (0,): # Not added yet + edgeIndex[edge] = np.resize(edgeIndex[edge], curSizeE[iedge] - 2) if self.edges[edge].degen == 1: # Get the counter value for this "node" index = nodeIndex[self.edges[edge].n1] - for jj in range(curSizeE[iedge]-2): + for jj in range(curSizeE[iedge] - 2): edgeIndex[edge][jj] = index else: - edgeIndex[edge][:] = np.arange(counter,counter+curSizeE[iedge]-2) - counter += curSizeE[iedge]-2 + edgeIndex[edge][:] = np.arange(counter, counter + curSizeE[iedge] - 2) + counter += curSizeE[iedge] - 2 for iface in range(6): face = self.faceLink[ii][iface] if faceIndex[face].shape == (0, 0): - faceIndex[face] = np.resize(faceIndex[face], - [curSizeF[iface][0]-2, - curSizeF[iface][1]-2]) - N = curSizeF[iface][0]-2 - M = curSizeF[iface][1]-2 - faceIndex[face] = np.arange(counter,counter+N*M).reshape((N,M)) - counter += N*M + faceIndex[face] = np.resize(faceIndex[face], [curSizeF[iface][0] - 2, curSizeF[iface][1] - 2]) + N = curSizeF[iface][0] - 2 + M = curSizeF[iface][1] - 2 + faceIndex[face] = np.arange(counter, counter + N * M).reshape((N, M)) + counter += N * M # end for (volume list) lIndex = [] @@ -2774,7 +2869,7 @@ def calcGlobalNumbering2(self, sizes=None, gIndex=True, volumeList=None, N = sizes[ii][0] M = sizes[ii][1] L = sizes[ii][2] - lIndex.append(-1*np.ones((N, M, L), 'intc')) + lIndex.append(-1 * np.ones((N, M, L), "intc")) # 8 Corners for iNode in range(8): @@ -2785,25 +2880,24 @@ def calcGlobalNumbering2(self, sizes=None, gIndex=True, volumeList=None, for iEdge in range(12): curEdge = self.edgeLink[iVol][iEdge] edgeDir = self.edgeDir[iVol][iEdge] - lIndex[ii] = setEdgeValue(lIndex[ii], edgeIndex[curEdge], - edgeDir, iEdge) + lIndex[ii] = setEdgeValue(lIndex[ii], edgeIndex[curEdge], edgeDir, iEdge) # 6 Faces for iFace in range(6): curFace = self.faceLink[iVol][iFace] faceDir = self.faceDirRev[iVol][iFace] - lIndex[ii] = setFaceValue(lIndex[ii], faceIndex[curFace], - faceDir, iFace) + lIndex[ii] = setFaceValue(lIndex[ii], faceIndex[curFace], faceDir, iFace) # Interior - toAdd = (N-2)*(M-2)*(L-2) + toAdd = (N - 2) * (M - 2) * (L - 2) - lIndex[ii][1:N-1,1:M-1,1:L-1] = \ - np.arange(counter,counter+toAdd).reshape((N-2,M-2,L-2)) + lIndex[ii][1 : N - 1, 1 : M - 1, 1 : L - 1] = np.arange(counter, counter + toAdd).reshape( + (N - 2, M - 2, L - 2) + ) counter = counter + toAdd # end for if gIndex: # We must add [] for each global node - gIndex = [ [] for i in range(counter)] + gIndex = [[] for i in range(counter)] for ii in range(len(volumeList)): iVol = volumeList[ii] @@ -2814,7 +2908,7 @@ def calcGlobalNumbering2(self, sizes=None, gIndex=True, volumeList=None, for i in range(N): for j in range(M): for k in range(L): - gIndex[lIndex[ii][i,j,k]].append([iVol,i,j,k]) + gIndex[lIndex[ii][i, j, k]].append([iVol, i, j, k]) else: gIndex = None @@ -2825,7 +2919,7 @@ def calcGlobalNumbering2(self, sizes=None, gIndex=True, volumeList=None, if greedyReorder: # Reorder the indices with a greedy scheme - newIndices = np.zeros(len(gIndex), 'intc') + newIndices = np.zeros(len(gIndex), "intc") newIndices[:] = -1 newGIndex = [[] for i in range(len(gIndex))] counter = 0 @@ -2844,15 +2938,14 @@ def calcGlobalNumbering2(self, sizes=None, gIndex=True, volumeList=None, lIndex[ii][i, j, k] = counter counter += 1 else: - lIndex[ii][i, j, k] = \ - newIndices[lIndex[ii][i, j, k]] + lIndex[ii][i, j, k] = newIndices[lIndex[ii][i, j, k]] # Re-order the gIndex for ii in range(len(gIndex)): - ivol = gIndex[ii][0][0] - i = gIndex[ii][0][1] - j = gIndex[ii][0][2] - k = gIndex[ii][0][3] + ivol = gIndex[ii][0][0] + i = gIndex[ii][0][1] + j = gIndex[ii][0][2] + k = gIndex[ii][0][3] pt = lIndex[ivol][i, j, k] newGIndex[pt] = gIndex[ii] @@ -2880,25 +2973,27 @@ def reOrder(self, reOrderList): return + class Edge(object): """A class for edge objects""" def __init__(self, n1, n2, cont, degen, intersect, dg, N): - self.n1 = n1 # Integer for node 1 - self.n2 = n2 # Integer for node 2 - self.cont = cont # Integer: 0 for c0 continuity, 1 - # for c1 continuity - self.degen = degen # Integer: 1 for degenerate, 0 otherwise - self.intersect = intersect # Integer: 1 for an intersected - # edge, 0 otherwise - self.dg = dg # Design Group index - self.N = N # Number of control points for this edge + self.n1 = n1 # Integer for node 1 + self.n2 = n2 # Integer for node 2 + self.cont = cont # Integer: 0 for c0 continuity, 1 + # for c1 continuity + self.degen = degen # Integer: 1 for degenerate, 0 otherwise + self.intersect = intersect # Integer: 1 for an intersected + # edge, 0 otherwise + self.dg = dg # Design Group index + self.N = N # Number of control points for this edge def writeInfo(self, i, handle): - handle.write(' %5d | %5d | %5d | %5d | %5d | %5d |\ - %5d | %5d |\n'\ - %(i, self.n1, self.n2, self.cont, self.degen, - self.intersect, self.dg, self.N)) + handle.write( + " %5d | %5d | %5d | %5d | %5d | %5d |\ + %5d | %5d |\n" + % (i, self.n1, self.n2, self.cont, self.degen, self.intersect, self.dg, self.N) + ) class EdgeCmpObject(object): @@ -2912,8 +3007,7 @@ def __init__(self, n1, n2, n1o, n2o, midPt, tol): self.tol = tol def __repr__(self): - return 'Node1: %d Node2: %d MidPt: %f %f %f'% ( - self.n1, self.n2, self.midPt[0], self.midPt[1], self.midPt[2]) + return "Node1: %d Node2: %d MidPt: %f %f %f" % (self.n1, self.n2, self.midPt[0], self.midPt[1], self.midPt[2]) def __lt__(self, other): @@ -2935,8 +3029,7 @@ def __lt__(self, other): return False def __eq__(self, other): - if (self.n1 == other.n1 and self.n2 == other.n2 and - eDist(self.midPt, other.midPt) < self.tol): + if self.n1 == other.n1 and self.n2 == other.n2 and eDist(self.midPt, other.midPt) < self.tol: return True else: return False @@ -2944,6 +3037,7 @@ def __eq__(self, other): def __ne__(self, other): return not self.__eq__(other) + class FaceCmpObject(object): """A temporary class for sorting edge objects""" @@ -2957,8 +3051,15 @@ def __init__(self, n1, n2, n3, n4, n1o, n2o, n3o, n4o, midPt, tol): self.tol = tol def __repr__(self): - return 'n1: %d n2: %d n3: %d n4: %d MidPt: %f %f %f'%( - self.n1, self.n2, self.n3, self.n4, self.midPt[0], self.midPt[1], self.midPt[2]) + return "n1: %d n2: %d n3: %d n4: %d MidPt: %f %f %f" % ( + self.n1, + self.n2, + self.n3, + self.n4, + self.midPt[0], + self.midPt[1], + self.midPt[2], + ) def __lt__(self, other): @@ -2986,9 +3087,13 @@ def __lt__(self, other): return False def __eq__(self, other): - if (self.n1 == other.n1 and self.n2 == other.n2 and - self.n3 == other.n3 and self.n4 == other.n4 and - eDist(self.midPt, other.midPt) < self.tol): + if ( + self.n1 == other.n1 + and self.n2 == other.n2 + and self.n3 == other.n3 + and self.n4 == other.n4 + and eDist(self.midPt, other.midPt) < self.tol + ): return True else: return False @@ -2996,10 +3101,12 @@ def __eq__(self, other): def __ne__(self, other): return not self.__eq__(other) + # -------------------------------------------------------------- # Array Rotation and Flipping Functions # -------------------------------------------------------------- + def rotateCCW(inArray): """Rotate the inArray array 90 degrees CCW""" rows = inArray.shape[0] @@ -3008,10 +3115,11 @@ def rotateCCW(inArray): for row in range(rows): for col in range(cols): - output[cols-col-1][row] = inArray[row][col] + output[cols - col - 1][row] = inArray[row][col] return output + def rotateCW(inArray): """Rotate the inArray array 90 degrees CW""" rows = inArray.shape[0] @@ -3020,10 +3128,11 @@ def rotateCW(inArray): for row in range(rows): for col in range(cols): - output[col][rows-row-1] = inArray[row][col] + output[col][rows - row - 1] = inArray[row][col] return output + def reverseRows(inArray): """Flip Rows (horizontally)""" rows = inArray.shape[0] @@ -3034,6 +3143,7 @@ def reverseRows(inArray): return output + def reverseCols(inArray): """Flip Cols (vertically)""" rows = inArray.shape[0] @@ -3044,13 +3154,18 @@ def reverseCols(inArray): return output + def getBiLinearMap(edge0, edge1, edge2, edge3): """Get the UV coordinates on a square defined from spacing on the edges""" - assert len(edge0)==len(edge1), 'Error, getBiLinearMap:\ - The len of edge0 and edge1 are not the same' - assert len(edge2)==len(edge3), 'Error, getBiLinearMap:\ - The len of edge2 and edge3 are no the same' + assert len(edge0) == len( + edge1 + ), "Error, getBiLinearMap:\ + The len of edge0 and edge1 are not the same" + assert len(edge2) == len( + edge3 + ), "Error, getBiLinearMap:\ + The len of edge2 and edge3 are no the same" N = len(edge0) M = len(edge2) @@ -3069,47 +3184,49 @@ def getBiLinearMap(edge0, edge1, edge2, edge3): UV[-1, :, 0] = 1.0 UV[-1, :, 1] = edge3 - for i in range(1, N-1): + for i in range(1, N - 1): x1 = edge0[i] y1 = 0.0 x2 = edge1[i] y2 = 1.0 - for j in range(1, M-1): + for j in range(1, M - 1): x3 = 0 y3 = edge2[j] x4 = 1.0 y4 = edge3[j] UV[i, j] = calcIntersection(x1, y1, x2, y2, x3, y3, x4, y4) - return UV + def calcIntersection(x1, y1, x2, y2, x3, y3, x4, y4): # Calc the intersection between two line segments defined by # (x1,y1) to (x2,y2) and (x3,y3) to (x4,y4) - denom = (y4-y3)*(x2-x1) - (x4-x3)*(y2-y1) - ua = ((x4-x3)*(y1-y3)-(y4-y3)*(x1-x3))/denom - xi = x1 + ua*(x2-x1) - yi = y1 + ua*(y2-y1) + denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1) + ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom + xi = x1 + ua * (x2 - x1) + yi = y1 + ua * (y2 - y1) return xi, yi + def fillKnots(t, k, level): - t = t[k-1:-k+1] # Strip out the np.zeros - newT = np.zeros(len(t) + (len(t)-1)*level) + t = t[k - 1 : -k + 1] # Strip out the np.zeros + newT = np.zeros(len(t) + (len(t) - 1) * level) start = 0 - for i in range(len(t)-1): - tmp = np.linspace(t[i], t[i+1], level+2) - for j in range(level+2): + for i in range(len(t) - 1): + tmp = np.linspace(t[i], t[i + 1], level + 2) + for j in range(level + 2): newT[start + j] = tmp[j] start += level + 1 return newT + def projectNodePID(pt, upVec, p0, v1, v2, uv0, uv1, uv2, PID): """ Project a point pt onto a triagnulated surface and return the patchID @@ -3133,7 +3250,7 @@ def projectNodePID(pt, upVec, p0, v1, v2, uv0, uv1, uv2, PID): fail = 2 return None, None, fail - tmpSol,tmpPid, nSol = pySpline.libspline.line_plane(pt, upVec, p0.T, v1.T, v2.T) + tmpSol, tmpPid, nSol = pySpline.libspline.line_plane(pt, upVec, p0.T, v1.T, v2.T) tmpSol = tmpSol.T tmpPid -= 1 @@ -3145,11 +3262,11 @@ def projectNodePID(pt, upVec, p0, v1, v2, uv0, uv1, uv2, PID): if nSol > 1: tmp, link = pointReduce(points, nodeTol=1e-12) nUnique = np.max(link) + 1 - points = np.zeros((nUnique,3)) + points = np.zeros((nUnique, 3)) uu = np.zeros(nUnique) vv = np.zeros(nUnique) ss = np.zeros(nUnique) - pid = np.zeros(nUnique,'intc') + pid = np.zeros(nUnique, "intc") for i in range(nSol): points[link[i]] = tmpSol[i, 3:6] @@ -3161,11 +3278,11 @@ def projectNodePID(pt, upVec, p0, v1, v2, uv0, uv1, uv2, PID): nSol = len(points) else: nUnique = 1 - points = np.zeros((nUnique,3)) + points = np.zeros((nUnique, 3)) uu = np.zeros(nUnique) vv = np.zeros(nUnique) ss = np.zeros(nUnique) - pid = np.zeros(nUnique,'intc') + pid = np.zeros(nUnique, "intc") points[0] = tmpSol[0, 3:6] uu[0] = tmpSol[0, 1] @@ -3179,40 +3296,46 @@ def projectNodePID(pt, upVec, p0, v1, v2, uv0, uv1, uv2, PID): elif nSol == 1: fail = 1 - first = points[0] + first = points[0] firstPatchID = PID[pid[0]] - firstU = uv0[pid[0]][0] + uu[0]*(uv1[pid[0]][0] - uv0[pid[0]][0]) - firstV = uv0[pid[0]][1] + vv[0]*(uv2[pid[0]][1] - uv0[pid[0]][1]) + firstU = uv0[pid[0]][0] + uu[0] * (uv1[pid[0]][0] - uv0[pid[0]][0]) + firstV = uv0[pid[0]][1] + vv[0] * (uv2[pid[0]][1] - uv0[pid[0]][1]) firstS = ss[0] - return [first, firstPatchID, firstU, firstV, firstS], None, fail + return [first, firstPatchID, firstU, firstV, firstS], None, fail elif nSol == 2: fail = 0 # Determine the 'top' and 'bottom' solution - first = points[0] + first = points[0] second = points[1] - firstPatchID = PID[pid[0]-1] - secondPatchID = PID[pid[1]-1] + firstPatchID = PID[pid[0] - 1] + secondPatchID = PID[pid[1] - 1] - firstU = uv0[pid[0]][0] + uu[0]*(uv1[pid[0]][0] - uv0[pid[0]][0]) - firstV = uv0[pid[0]][1] + vv[0]*(uv2[pid[0]][1] - uv0[pid[0]][1]) + firstU = uv0[pid[0]][0] + uu[0] * (uv1[pid[0]][0] - uv0[pid[0]][0]) + firstV = uv0[pid[0]][1] + vv[0] * (uv2[pid[0]][1] - uv0[pid[0]][1]) firstS = ss[0] - secondU = uv0[pid[1]][0] + uu[1]*(uv1[pid[1]][0] - uv0[pid[1]][0]) - secondV = uv0[pid[1]][1] + vv[1]*(uv2[pid[1]][1] - uv0[pid[1]][1]) + secondU = uv0[pid[1]][0] + uu[1] * (uv1[pid[1]][0] - uv0[pid[1]][0]) + secondV = uv0[pid[1]][1] + vv[1] * (uv2[pid[1]][1] - uv0[pid[1]][1]) secondS = ss[1] if np.dot(first - pt, upVec) >= np.dot(second - pt, upVec): - return [first, firstPatchID, firstU, firstV, firstS],\ - [second, secondPatchID, secondU, secondV, secondS], fail + return ( + [first, firstPatchID, firstU, firstV, firstS], + [second, secondPatchID, secondU, secondV, secondS], + fail, + ) else: - return [second, secondPatchID, secondU, secondV, secondS],\ - [first, firstPatchID, firstU, firstV, firstS], fail + return ( + [second, secondPatchID, secondU, secondV, secondS], + [first, firstPatchID, firstU, firstV, firstS], + fail, + ) else: - print('This functionality is not implemtned in geoUtils yet') + print("This functionality is not implemtned in geoUtils yet") sys.exit(1) @@ -3244,18 +3367,17 @@ def projectNodePIDPosOnly(pt, upVec, p0, v1, v2, uv0, uv1, uv2, PID): if minIndex >= 0: patchID = PID[pid[minIndex]] - u = uv0[pid[minIndex]][0] + sol[minIndex, 1]*\ - (uv1[pid[minIndex]][0] - uv0[pid[minIndex]][0]) + u = uv0[pid[minIndex]][0] + sol[minIndex, 1] * (uv1[pid[minIndex]][0] - uv0[pid[minIndex]][0]) - v = uv0[pid[minIndex]][1] + sol[minIndex, 2]*\ - (uv2[pid[minIndex]][1] - uv0[pid[minIndex]][1]) - s = sol[minIndex,0] - tmp = [sol[minIndex,3], sol[minIndex,4], sol[minIndex,5]] + v = uv0[pid[minIndex]][1] + sol[minIndex, 2] * (uv2[pid[minIndex]][1] - uv0[pid[minIndex]][1]) + s = sol[minIndex, 0] + tmp = [sol[minIndex, 3], sol[minIndex, 4], sol[minIndex, 5]] return [tmp, patchID, u, v, s], fail fail = 1 return None, fail + def projectNode(pt, upVec, p0, v1, v2): """ Project a point pt onto a triagnulated surface and return two @@ -3275,7 +3397,7 @@ def projectNode(pt, upVec, p0, v1, v2): fail = 2 return None, None, fail - sol,pid, nSol = pySpline.libspline.line_plane(pt, upVec, p0.T, v1.T, v2.T) + sol, pid, nSol = pySpline.libspline.line_plane(pt, upVec, p0.T, v1.T, v2.T) sol = sol.T # Check to see if any of the solutions happen be identical. @@ -3296,12 +3418,12 @@ def projectNode(pt, upVec, p0, v1, v2): return None, None, fail elif nSol == 1: fail = 1 - return newPoints[0], None, fail + return newPoints[0], None, fail elif nSol == 2: fail = 0 # Determine the 'top' and 'bottom' solution - first = newPoints[0] + first = newPoints[0] second = newPoints[1] if np.dot(first - pt, upVec) >= np.dot(second - pt, upVec): @@ -3318,6 +3440,7 @@ def projectNode(pt, upVec, p0, v1, v2): return newPoints[minIndex[0]], newPoints[minIndex[1]], fail + def projectNodePosOnly(pt, upVec, p0, v1, v2): """ Project a point pt onto a triagnulated surface and the solution @@ -3360,6 +3483,7 @@ def projectNodePosOnly(pt, upVec, p0, v1, v2): fail = 1 return None, fail + def tfi_2d(e0, e1, e2, e3): # Input # e0: Nodes along edge 0. Size Nu x 3 @@ -3373,10 +3497,16 @@ def tfi_2d(e0, e1, e2, e3): Nu = len(e0) Nv = len(e2) - assert Nu == len(e1), 'Number of nodes on edge0 and edge1\ - are not the same, %d %d'%(len(e0), len(e1)) - assert Nv == len(e3), 'Number of nodes on edge2 and edge3\ - are not the same, %d %d'%(len(e2), len(e3)) + assert Nu == len(e1), ( + "Number of nodes on edge0 and edge1\ + are not the same, %d %d" + % (len(e0), len(e1)) + ) + assert Nv == len(e3), ( + "Number of nodes on edge2 and edge3\ + are not the same, %d %d" + % (len(e2), len(e3)) + ) U = np.linspace(0, 1, Nu) V = np.linspace(0, 1, Nv) @@ -3385,21 +3515,31 @@ def tfi_2d(e0, e1, e2, e3): for i in range(Nu): for j in range(Nv): - X[i, j] = (1-V[j])*e0[i] + V[j]*e1[i] +\ - (1-U[i])*e2[j] + U[i]*e3[j] - \ - (U[i]*V[j]*e1[-1] + U[i]*(1-V[j])*e0[-1] +\ - V[j]*(1-U[i])*e1[0] + (1-U[i])*(1-V[j])*e0[0]) + X[i, j] = ( + (1 - V[j]) * e0[i] + + V[j] * e1[i] + + (1 - U[i]) * e2[j] + + U[i] * e3[j] + - ( + U[i] * V[j] * e1[-1] + + U[i] * (1 - V[j]) * e0[-1] + + V[j] * (1 - U[i]) * e1[0] + + (1 - U[i]) * (1 - V[j]) * e0[0] + ) + ) return X + def linearEdge(pt1, pt2, N): # Return N points along line from pt1 to pt2 pts = np.zeros((N, len(pt1))) pt1 = np.array(pt1) pt2 = np.array(pt2) for i in range(N): - pts[i] = float(i)/(N-1)*(pt2-pt1) + pt1 + pts[i] = float(i) / (N - 1) * (pt2 - pt1) + pt1 return pts + def splitQuad(e0, e1, e2, e3, alpha, beta, NO): # This function takes the coordinates of a quad patch, and # creates an O-grid inside the quad making 4 quads and leaving @@ -3451,24 +3591,24 @@ def splitQuad(e0, e1, e2, e3, alpha, beta, NO): # Vector along edges 0->3 vec = np.zeros((4, 3)) - vec[0] = pts[1]-pts[0] - vec[1] = pts[3]-pts[2] - vec[2] = pts[2]-pts[0] - vec[3] = pts[3]-pts[1] + vec[0] = pts[1] - pts[0] + vec[1] = pts[3] - pts[2] + vec[2] = pts[2] - pts[0] + vec[3] = pts[3] - pts[1] - U = 0.5*(vec[0]+vec[1]) - V = 0.5*(vec[2]+vec[3]) - u = U/euclideanNorm(U) - v = V/euclideanNorm(V) + U = 0.5 * (vec[0] + vec[1]) + V = 0.5 * (vec[2] + vec[3]) + u = U / euclideanNorm(U) + v = V / euclideanNorm(V) - mid = np.average(pts, axis=0) + mid = np.average(pts, axis=0) - uBar = 0.5*(l[0]+l[1])*alpha - vBar = 0.5*(l[2]+l[3])*beta + uBar = 0.5 * (l[0] + l[1]) * alpha + vBar = 0.5 * (l[2] + l[3]) * beta - aspect = uBar/vBar + aspect = uBar / vBar - if aspect < 1: # its higher than wide, logically roate the element + if aspect < 1: # its higher than wide, logically roate the element v, u = u, -v vBar, uBar = uBar, vBar alpha, beta = beta, alpha @@ -3479,7 +3619,7 @@ def splitQuad(e0, e1, e2, e3, alpha, beta, NO): E2 = e1.copy() E3 = e0.copy() - #Also need to permute points + # Also need to permute points PTS = np.zeros((4, 3)) PTS[0] = pts[2].copy() PTS[1] = pts[0].copy() @@ -3495,66 +3635,58 @@ def splitQuad(e0, e1, e2, e3, alpha, beta, NO): rectCorners = np.zeros((4, 3)) # These are the output pactch object - P0 = np.zeros((Nu, 4, 3), 'd') - P1 = np.zeros((Nu, 4, 3), 'd') - P2 = np.zeros((Nv, 4, 3), 'd') - P3 = np.zeros((Nv, 4, 3), 'd') + P0 = np.zeros((Nu, 4, 3), "d") + P1 = np.zeros((Nu, 4, 3), "d") + P2 = np.zeros((Nv, 4, 3), "d") + P3 = np.zeros((Nv, 4, 3), "d") - rad = vBar*beta - rectLen = uBar-2*rad + rad = vBar * beta + rectLen = uBar - 2 * rad if rectLen < 0: rectLen = 0.0 # Determine 4 corners of rectangular part - rectCorners[0] = mid-u*(rectLen/2)-np.sin(np.pi/4)*\ - rad*v-np.cos(np.pi/4)*rad*u - rectCorners[1] = mid+u*(rectLen/2)-np.sin(np.pi/4)*\ - rad*v+np.cos(np.pi/4)*rad*u - rectCorners[2] = mid-u*(rectLen/2)+np.sin(np.pi/4)*\ - rad*v-np.cos(np.pi/4)*rad*u - rectCorners[3] = mid+u*(rectLen/2)+np.sin(np.pi/4)*\ - rad*v+np.cos(np.pi/4)*rad*u - - arcLen = np.pi*rad/2 + rectLen # Two quarter circles straight line - eighthArc = 0.25*np.pi*rad + rectCorners[0] = mid - u * (rectLen / 2) - np.sin(np.pi / 4) * rad * v - np.cos(np.pi / 4) * rad * u + rectCorners[1] = mid + u * (rectLen / 2) - np.sin(np.pi / 4) * rad * v + np.cos(np.pi / 4) * rad * u + rectCorners[2] = mid - u * (rectLen / 2) + np.sin(np.pi / 4) * rad * v - np.cos(np.pi / 4) * rad * u + rectCorners[3] = mid + u * (rectLen / 2) + np.sin(np.pi / 4) * rad * v + np.cos(np.pi / 4) * rad * u + + arcLen = np.pi * rad / 2 + rectLen # Two quarter circles straight line + eighthArc = 0.25 * np.pi * rad # We have to distribute Nu-2 nodes over this arc-length - spacing = arcLen/(Nu-1) + spacing = arcLen / (Nu - 1) - botEdge = np.zeros((Nu, 3), 'd') - topEdge = np.zeros((Nu, 3), 'd') + botEdge = np.zeros((Nu, 3), "d") + topEdge = np.zeros((Nu, 3), "d") botEdge[0] = rectCorners[0] botEdge[-1] = rectCorners[1] topEdge[0] = rectCorners[2] topEdge[-1] = rectCorners[3] - for i in range(Nu-2): - distAlongArc = (i+1)*spacing + for i in range(Nu - 2): + distAlongArc = (i + 1) * spacing if distAlongArc < eighthArc: - theta = distAlongArc/rad # Angle in radians - botEdge[i+1] = mid-u*(rectLen/2) - \ - np.sin(theta+np.pi/4)*rad*v - np.cos(theta+np.pi/4)*rad*u - topEdge[i+1] = mid-u*(rectLen/2) + \ - np.sin(theta+np.pi/4)*rad*v - np.cos(theta+np.pi/4)*rad*u - elif distAlongArc > rectLen+eighthArc: - theta = (distAlongArc-rectLen-eighthArc)/rad - botEdge[i+1] = mid+u*(rectLen/2) + \ - np.sin(theta)*rad*u - np.cos(theta)*rad*v - topEdge[i+1] = mid+u*(rectLen/2) + \ - np.sin(theta)*rad*u + np.cos(theta)*rad*v + theta = distAlongArc / rad # Angle in radians + botEdge[i + 1] = ( + mid - u * (rectLen / 2) - np.sin(theta + np.pi / 4) * rad * v - np.cos(theta + np.pi / 4) * rad * u + ) + topEdge[i + 1] = ( + mid - u * (rectLen / 2) + np.sin(theta + np.pi / 4) * rad * v - np.cos(theta + np.pi / 4) * rad * u + ) + elif distAlongArc > rectLen + eighthArc: + theta = (distAlongArc - rectLen - eighthArc) / rad + botEdge[i + 1] = mid + u * (rectLen / 2) + np.sin(theta) * rad * u - np.cos(theta) * rad * v + topEdge[i + 1] = mid + u * (rectLen / 2) + np.sin(theta) * rad * u + np.cos(theta) * rad * v else: - topEdge[i+1] = mid -u*rectLen/2 + rad*v + \ - (distAlongArc-eighthArc)*u - botEdge[i+1] = mid -u*rectLen/2 - rad*v + \ - (distAlongArc-eighthArc)*u + topEdge[i + 1] = mid - u * rectLen / 2 + rad * v + (distAlongArc - eighthArc) * u + botEdge[i + 1] = mid - u * rectLen / 2 - rad * v + (distAlongArc - eighthArc) * u - leftEdge = np.zeros((Nv, 3), 'd') - rightEdge = np.zeros((Nv, 3), 'd') - theta = np.linspace(-np.pi/4, np.pi/4, Nv) + leftEdge = np.zeros((Nv, 3), "d") + rightEdge = np.zeros((Nv, 3), "d") + theta = np.linspace(-np.pi / 4, np.pi / 4, Nv) for i in range(Nv): - leftEdge[i] = mid-u*(rectLen/2) + \ - np.sin(theta[i])*rad*v - np.cos(theta[i])*rad*u - rightEdge[i] = mid+u*(rectLen/2) + \ - np.sin(theta[i])*rad*v + np.cos(theta[i])*rad*u + leftEdge[i] = mid - u * (rectLen / 2) + np.sin(theta[i]) * rad * v - np.cos(theta[i]) * rad * u + rightEdge[i] = mid + u * (rectLen / 2) + np.sin(theta[i]) * rad * v + np.cos(theta[i]) * rad * u # Do the corner edges c0 = linearEdge(PTS[0], rectCorners[0], NO) @@ -3573,8 +3705,8 @@ def splitQuad(e0, e1, e2, e3, alpha, beta, NO): else: return P0, P1, P2, P3 -def createTriPanMesh(geo, tripanFile, wakeFile, - specsFile=None, defaultSize=0.1): + +def createTriPanMesh(geo, tripanFile, wakeFile, specsFile=None, defaultSize=0.1): """ Create a TriPan mesh from a pyGeo object. @@ -3595,21 +3727,21 @@ def createTriPanMesh(geo, tripanFile, wakeFile, nFace = topo.nFace # Face orientation - faceOrientation = [1]*nFace + faceOrientation = [1] * nFace # edgeNumber == number of panels along a given edge - edgeNumber = -1*np.ones(nEdge, 'intc') + edgeNumber = -1 * np.ones(nEdge, "intc") # edgeType == what type of parametrization to use along an edge - edgeType = ['linear']*nEdge + edgeType = ["linear"] * nEdge wakeEdges = [] - wakeDir = [] + wakeDir = [] if specsFile: - f = open(specsFile, 'r') + f = open(specsFile, "r") line = f.readline().split() if int(line[0]) != nFace: - print('Number of faces do not match in specs file') + print("Number of faces do not match in specs file") if int(line[1]) != nEdge: - print('Number of edges do not match in specs file') + print("Number of edges do not match in specs file") # Discard a line f.readline() # Read in the face info @@ -3638,99 +3770,111 @@ def createTriPanMesh(geo, tripanFile, wakeFile, # First check if we even have to do it if edgeNumber[topo.edgeLink[iface][iedge]] == -1: # Get the physical length of the edge - edgeLength = \ - geo.surfs[iface].edgeCurves[iedge].getLength() + edgeLength = geo.surfs[iface].edgeCurves[iedge].getLength() # Using defaultSize calculate the number of panels # along this edge - edgeNumber[topo.edgeLink[iface][iedge]] = \ - int(np.floor(edgeLength/defaultSize))+2 + edgeNumber[topo.edgeLink[iface][iedge]] = int(np.floor(edgeLength / defaultSize)) + 2 # end if # Create the sizes Geo for the make consistent function sizes = [] - order = [0]*nFace + order = [0] * nFace for iface in range(nFace): - sizes.append([edgeNumber[topo.edgeLink[iface][0]], - edgeNumber[topo.edgeLink[iface][2]]]) + sizes.append([edgeNumber[topo.edgeLink[iface][0]], edgeNumber[topo.edgeLink[iface][2]]]) sizes, edgeNumber = topo.makeSizesConsistent(sizes, order) # Now we need to get the edge parameter spacing for each edge - topo.calcGlobalNumbering(sizes) # This gets gIndex,lIndex and counter + topo.calcGlobalNumbering(sizes) # This gets gIndex,lIndex and counter # Now calculate the intrinsic spacing for each edge: edgePara = [] for iedge in range(nEdge): - if edgeType[iedge] == 'linear': + if edgeType[iedge] == "linear": spacing = np.linspace(0.0, 1.0, edgeNumber[iedge]) edgePara.append(spacing) - elif edgeType[iedge] == 'cos': - spacing = 0.5*(1.0 - np.cos(np.linspace( - 0, np.pi, edgeNumber[iedge]))) + elif edgeType[iedge] == "cos": + spacing = 0.5 * (1.0 - np.cos(np.linspace(0, np.pi, edgeNumber[iedge]))) edgePara.append(spacing) - elif edgeType[iedge] == 'hyperbolic': + elif edgeType[iedge] == "hyperbolic": x = np.linspace(0.0, 1.0, edgeNumber[iedge]) beta = 1.8 - spacing = x - beta*x*(x - 1.0)*(x - 0.5) + spacing = x - beta * x * (x - 1.0) * (x - 0.5) edgePara.append(spacing) else: - print('Warning: Edge type %s not understood. \ -Using a linear type'%(edgeType[iedge])) + print( + "Warning: Edge type %s not understood. \ +Using a linear type" + % (edgeType[iedge]) + ) edgePara.append(np.linspace(0, 1, edgeNumber[iedge])) # Get the number of panels nPanels = 0 nNodes = len(topo.gIndex) for iface in range(nFace): - nPanels += (sizes[iface][0]-1)*(sizes[iface][1]-1) + nPanels += (sizes[iface][0] - 1) * (sizes[iface][1] - 1) # Open the outputfile - fp = open(tripanFile, 'w') + fp = open(tripanFile, "w") # Write he number of points and panels - fp.write('%5d %5d\n'%(nNodes, nPanels)) + fp.write("%5d %5d\n" % (nNodes, nPanels)) # Output the Points First UV = [] for iface in range(nFace): - UV.append(getBiLinearMap( - edgePara[topo.edgeLink[iface][0]], - edgePara[topo.edgeLink[iface][1]], - edgePara[topo.edgeLink[iface][2]], - edgePara[topo.edgeLink[iface][3]])) + UV.append( + getBiLinearMap( + edgePara[topo.edgeLink[iface][0]], + edgePara[topo.edgeLink[iface][1]], + edgePara[topo.edgeLink[iface][2]], + edgePara[topo.edgeLink[iface][3]], + ) + ) for ipt in range(len(topo.gIndex)): iface = topo.gIndex[ipt][0][0] - i = topo.gIndex[ipt][0][1] - j = topo.gIndex[ipt][0][2] - pt = geo.surfs[iface].getValue(UV[iface][i, j][0], UV[iface][i, j][1]) - fp.write( '%12.10e %12.10e %12.10e \n'%(pt[0], pt[1], pt[2])) + i = topo.gIndex[ipt][0][1] + j = topo.gIndex[ipt][0][2] + pt = geo.surfs[iface].getValue(UV[iface][i, j][0], UV[iface][i, j][1]) + fp.write("%12.10e %12.10e %12.10e \n" % (pt[0], pt[1], pt[2])) # Output the connectivity Next for iface in range(nFace): if faceOrientation[iface] >= 0: - for i in range(sizes[iface][0]-1): - for j in range(sizes[iface][1]-1): - fp.write('%d %d %d %d \n'%(topo.lIndex[iface][i, j], - topo.lIndex[iface][i+1, j], - topo.lIndex[iface][i+1, j+1], - topo.lIndex[iface][i, j+1])) + for i in range(sizes[iface][0] - 1): + for j in range(sizes[iface][1] - 1): + fp.write( + "%d %d %d %d \n" + % ( + topo.lIndex[iface][i, j], + topo.lIndex[iface][i + 1, j], + topo.lIndex[iface][i + 1, j + 1], + topo.lIndex[iface][i, j + 1], + ) + ) else: - for i in range(sizes[iface][0]-1): - for j in range(sizes[iface][1]-1): - fp.write('%d %d %d %d \n'%(topo.lIndex[iface][i, j], - topo.lIndex[iface][i, j+1], - topo.lIndex[iface][i+1, j+1], - topo.lIndex[iface][i+1, j])) - - fp.write('\n') + for i in range(sizes[iface][0] - 1): + for j in range(sizes[iface][1] - 1): + fp.write( + "%d %d %d %d \n" + % ( + topo.lIndex[iface][i, j], + topo.lIndex[iface][i, j + 1], + topo.lIndex[iface][i + 1, j + 1], + topo.lIndex[iface][i + 1, j], + ) + ) + + fp.write("\n") fp.close() # Output the wake file - fp = open(wakeFile, 'w') - fp.write('%d\n'%(len(wakeEdges))) - print('wakeEdges:', wakeEdges) + fp = open(wakeFile, "w") + fp.write("%d\n" % (len(wakeEdges))) + print("wakeEdges:", wakeEdges) for k in range(len(wakeEdges)): # Get a surface/edge for this edge @@ -3746,17 +3890,17 @@ def createTriPanMesh(geo, tripanFile, wakeFile, elif iedge == 3: indices = topo.lIndex[iface][-1, :] - fp.write('%d\n'%(len(indices))) + fp.write("%d\n" % (len(indices))) if wakeDir[k] > 0: for i in range(len(indices)): # A constant in TriPan to indicate projected wake teNodeType = 3 - fp.write('%d %d\n'%(indices[i], teNodeType)) + fp.write("%d %d\n" % (indices[i], teNodeType)) else: for i in range(len(indices)): teNodeType = 3 - fp.write('%d %d\n'%(indices[len(indices)-1-i], teNodeType)) + fp.write("%d %d\n" % (indices[len(indices) - 1 - i], teNodeType)) # end for fp.close() @@ -3764,35 +3908,41 @@ def createTriPanMesh(geo, tripanFile, wakeFile, if specsFile is None: (dirName, fileName) = os.path.split(tripanFile) (fileBaseName, fileExtension) = os.path.splitext(fileName) - if dirName != '': - newSpecsFile = dirName+'/'+fileBaseName+'.specs' + if dirName != "": + newSpecsFile = dirName + "/" + fileBaseName + ".specs" else: - newSpecsFile = fileBaseName+'.specs' + newSpecsFile = fileBaseName + ".specs" specsFile = newSpecsFile if not os.path.isfile(specsFile): - f = open(specsFile, 'w') - f.write('%d %d Number of faces and number of edges\n'%(nFace, nEdge)) - f.write('Face number Normal (1 for regular, -1 for\ - reversed orientation\n') + f = open(specsFile, "w") + f.write("%d %d Number of faces and number of edges\n" % (nFace, nEdge)) + f.write( + "Face number Normal (1 for regular, -1 for\ + reversed orientation\n" + ) for iface in range(nFace): - f.write('%d %d\n'%(iface, faceOrientation[iface])) - f.write('Edge Number #Node Type Start Space End Space\ - WakeEdge\n') + f.write("%d %d\n" % (iface, faceOrientation[iface])) + f.write( + "Edge Number #Node Type Start Space End Space\ + WakeEdge\n" + ) for iedge in range(nEdge): if iedge in wakeEdges: - f.write( ' %4d %5d %10s %10.4f %10.4f %1d \n'%(\ - iedge, edgeNumber[iedge], edgeType[iedge], - .1, .1, 1)) + f.write( + " %4d %5d %10s %10.4f %10.4f %1d \n" % (iedge, edgeNumber[iedge], edgeType[iedge], 0.1, 0.1, 1) + ) else: - f.write( ' %4d %5d %10s %10.4f %10.4f %1d \n'%(\ - iedge, edgeNumber[iedge], edgeType[iedge], - .1, .1, 0)) + f.write( + " %4d %5d %10s %10.4f %10.4f %1d \n" % (iedge, edgeNumber[iedge], edgeType[iedge], 0.1, 0.1, 0) + ) f.close() + # 2D Doubly connected edge list implementation. -#Copyright 2008, Angel Yanguas-Gil +# Copyright 2008, Angel Yanguas-Gil + class DCELEdge(object): def __init__(self, v1, v2, X, PID, uv, tag): @@ -3803,7 +3953,7 @@ def __init__(self, v1, v2, X, PID, uv, tag): self.X = X self.PID = PID self.uv = uv - tmp = tag.split('-') + tmp = tag.split("-") self.tag = tmp[0] if len(tmp) > 1: self.seg = tmp[1] @@ -3813,20 +3963,20 @@ def __init__(self, v1, v2, X, PID, uv, tag): self.v1 = v1 self.v2 = v2 if X is not None: - self.x1 = 0.5*(X[0,0] + X[0,1]) - self.x2 = 0.5*(X[-1,0] + X[-1,1]) + self.x1 = 0.5 * (X[0, 0] + X[0, 1]) + self.x2 = 0.5 * (X[-1, 0] + X[-1, 1]) - self.con = [v1,v2] + self.con = [v1, v2] def __repr__(self): - str1 = 'v1: %f %f\nv2: %f %f'% (self.v1[0],self.v1[1], - self.v2[0],self.v2[1]) + str1 = "v1: %f %f\nv2: %f %f" % (self.v1[0], self.v1[1], self.v2[0], self.v2[1]) return str1 def midPt(self): - #return [0.5*(self.v1.x + self.v2.x), 0.5*(self.v1.y + self.v2.y)] - return 0.5*self.x1 + 0.5*self.x2 + # return [0.5*(self.v1.x + self.v2.x), 0.5*(self.v1.y + self.v2.y)] + return 0.5 * self.x1 + 0.5 * self.x2 + class DCELVertex: """Minimal implementation of a vertex of a 2D dcel""" @@ -3855,8 +4005,8 @@ def hsort(self, h1, h2): class DCELHedge: """Minimal implementation of a half-edge of a 2D dcel""" - def __init__(self,v1,v2,X,PID,uv,tag=None): - #The origin is defined as the vertex it points to + def __init__(self, v1, v2, X, PID, uv, tag=None): + # The origin is defined as the vertex it points to self.origin = v2 self.twin = None self.face = None @@ -3864,9 +4014,9 @@ def __init__(self,v1,v2,X,PID,uv,tag=None): self.uv = uv self.PID = PID self.nexthedge = None - self.angle = hangle(v2.x-v1.x, v2.y-v1.y) + self.angle = hangle(v2.x - v1.x, v2.y - v1.y) self.prevhedge = None - self.length = np.sqrt((v2.x-v1.x)**2 + (v2.y-v1.y)**2) + self.length = np.sqrt((v2.x - v1.x) ** 2 + (v2.y - v1.y) ** 2) self.tag = tag @@ -3877,34 +4027,34 @@ def __init__(self): self.wedge = None self.data = None self.external = None - self.tag = 'EXTERNAL' + self.tag = "EXTERNAL" self.id = None def area(self): h = self.wedge a = 0 - while(not h.nexthedge is self.wedge): + while not h.nexthedge is self.wedge: p1 = h.origin p2 = h.nexthedge.origin - a += p1.x*p2.y - p2.x*p1.y + a += p1.x * p2.y - p2.x * p1.y h = h.nexthedge p1 = h.origin p2 = self.wedge.origin - a = (a + p1.x*p2.y - p2.x*p1.y)/2.0 + a = (a + p1.x * p2.y - p2.x * p1.y) / 2.0 return a def calcCentroid(self): h = self.wedge center = np.zeros(2) - center += [h.origin.x,h.origin.y] + center += [h.origin.x, h.origin.y] counter = 1 - while(not h.nexthedge is self.wedge): + while not h.nexthedge is self.wedge: counter += 1 h = h.nexthedge - center += [h.origin.x,h.origin.y] + center += [h.origin.x, h.origin.y] - self.centroid = center/counter + self.centroid = center / counter def calcSpatialCentroid(self): @@ -3912,17 +4062,17 @@ def calcSpatialCentroid(self): center = np.zeros(3) center += h.origin.X counter = 1 - while(not h.nexthedge is self.wedge): + while not h.nexthedge is self.wedge: counter += 1 h = h.nexthedge center += h.origin.X - self.spatialCentroid = center/counter + self.spatialCentroid = center / counter def perimeter(self): h = self.wedge p = 0 - while (not h.nexthedge is self.wedge): + while not h.nexthedge is self.wedge: p += h.length h = h.nexthedge return p @@ -3930,38 +4080,37 @@ def perimeter(self): def vertexlist(self): h = self.wedge pl = [h.origin] - while(not h.nexthedge is self.wedge): + while not h.nexthedge is self.wedge: h = h.nexthedge pl.append(h.origin) return pl - - def isinside(self, P): """Determines whether a point is inside a face using a winding formula""" pl = self.vertexlist() V = [] for i in range(len(pl)): - V.append([pl[i].x,pl[i].y]) - V.append([pl[0].x,pl[0].y]) + V.append([pl[i].x, pl[i].y]) + V.append([pl[0].x, pl[0].y]) wn = 0 # loop through all edges of the polygon - for i in range(len(V)-1): # edge from V[i] to V[i+1] - if V[i][1] <= P[1]: # start y <= P[1] - if V[i+1][1] > P[1]: # an upward crossing - if isLeft(V[i], V[i+1], P) > 0: # P left of edge - wn += 1 # have a valid up intersect - else: # start y > P[1] (no test needed) - if V[i+1][1] <= P[1]: # a downward crossing - if isLeft(V[i], V[i+1], P) < 0: # P right of edge - wn -= 1 # have a valid down intersect + for i in range(len(V) - 1): # edge from V[i] to V[i+1] + if V[i][1] <= P[1]: # start y <= P[1] + if V[i + 1][1] > P[1]: # an upward crossing + if isLeft(V[i], V[i + 1], P) > 0: # P left of edge + wn += 1 # have a valid up intersect + else: # start y > P[1] (no test needed) + if V[i + 1][1] <= P[1]: # a downward crossing + if isLeft(V[i], V[i + 1], P) < 0: # P right of edge + wn -= 1 # have a valid down intersect if wn == 0: return False else: return True + class DCEL(object): """ Implements a doubly-connected edge list @@ -3992,10 +4141,10 @@ def buildDcel(self): # Do some pruning first: self.vertices = self.vl ii = 0 - while ii < 1000: # Trim at most 1000 edges + while ii < 1000: # Trim at most 1000 edges ii += 1 - mult = np.zeros(self.nvertices(),'intc') + mult = np.zeros(self.nvertices(), "intc") for e in self.el: mult[e.con[0]] += 1 mult[e.con[1]] += 1 @@ -4012,49 +4161,47 @@ def buildDcel(self): # First generate new mapping: count = 0 - mapping = -1*np.ones(self.nvertices(),'intc') + mapping = -1 * np.ones(self.nvertices(), "intc") deletedVertices = [] for i in range(self.nvertices()): - if multCheck[i]: + if multCheck[i]: # Vertex must be removed - self.vertices.pop(i-len(deletedVertices)) + self.vertices.pop(i - len(deletedVertices)) deletedVertices.append(i) else: - mapping[i] = count # Other wise get the mapping count: + mapping[i] = count # Other wise get the mapping count: count += 1 # Now prune the edges: nEdgeDeleted = 0 for i in range(len(self.el)): - if self.el[i-nEdgeDeleted].con[0] in deletedVertices or \ - self.el[i-nEdgeDeleted].con[1] in deletedVertices: + if ( + self.el[i - nEdgeDeleted].con[0] in deletedVertices + or self.el[i - nEdgeDeleted].con[1] in deletedVertices + ): # Edge must be deleted - self.el.pop(i-nEdgeDeleted) + self.el.pop(i - nEdgeDeleted) nEdgeDeleted += 1 else: # Mapping needs to be updated: - curCon = self.el[i-nEdgeDeleted].con - self.el[i-nEdgeDeleted].con[0] = mapping[curCon[0]] - self.el[i-nEdgeDeleted].con[1] = mapping[curCon[1]] + curCon = self.el[i - nEdgeDeleted].con + self.el[i - nEdgeDeleted].con[0] = mapping[curCon[0]] + self.el[i - nEdgeDeleted].con[1] = mapping[curCon[1]] else: break # end while -#Step 2: hedge list creation. Assignment of twins and -#vertices + # Step 2: hedge list creation. Assignment of twins and + # vertices self.hedges = [] appendCount = 0 for e in self.el: - h1 = DCELHedge(self.vertices[e.con[0]], - self.vertices[e.con[1]], - e.X, e.PID, e.uv, e.tag) - h2 = DCELHedge(self.vertices[e.con[1]], - self.vertices[e.con[0]], - e.X, e.PID, e.uv, e.tag) + h1 = DCELHedge(self.vertices[e.con[0]], self.vertices[e.con[1]], e.X, e.PID, e.uv, e.tag) + h2 = DCELHedge(self.vertices[e.con[1]], self.vertices[e.con[0]], e.X, e.PID, e.uv, e.tag) h1.twin = h2 h2.twin = h1 @@ -4064,20 +4211,19 @@ def buildDcel(self): self.hedges.append(h2) self.hedges.append(h1) - - #Step 3: Identification of next and prev hedges + # Step 3: Identification of next and prev hedges for v in self.vertices: v.sortincident() l = len(v.hedgelist) - for i in range(l-1): - v.hedgelist[i].nexthedge = v.hedgelist[i+1].twin - v.hedgelist[i+1].prevhedge = v.hedgelist[i] + for i in range(l - 1): + v.hedgelist[i].nexthedge = v.hedgelist[i + 1].twin + v.hedgelist[i + 1].prevhedge = v.hedgelist[i] - v.hedgelist[l-1].nexthedge = v.hedgelist[0].twin - v.hedgelist[0].prevhedge = v.hedgelist[l-1] + v.hedgelist[l - 1].nexthedge = v.hedgelist[0].twin + v.hedgelist[0].prevhedge = v.hedgelist[l - 1] - #Step 4: Face assignment + # Step 4: Face assignment provlist = self.hedges[:] nf = 0 nh = len(self.hedges) @@ -4086,19 +4232,19 @@ def buildDcel(self): h = provlist.pop() nh -= 1 - #We check if the hedge already points to a face + # We check if the hedge already points to a face if h.face is None: f = DCELFace() nf += 1 - #We link the hedge to the new face + # We link the hedge to the new face f.wedge = h f.wedge.face = f - #And we traverse the boundary of the new face - while (not h.nexthedge is f.wedge): + # And we traverse the boundary of the new face + while not h.nexthedge is f.wedge: h = h.nexthedge h.face = f self.faces.append(f) - #And finally we have to determine the external face + # And finally we have to determine the external face for f in self.faces: f.external = f.area() < 0 f.calcCentroid() @@ -4110,21 +4256,20 @@ def buildDcel(self): def writeTecplot(self, fileName): - f = open(fileName, 'w') - f.write ('VARIABLES = "X","Y"\n') + f = open(fileName, "w") + f.write('VARIABLES = "X","Y"\n') for i in range(len(self.el)): - f.write('Zone T=\"edge%d\" I=%d\n'%(i, 2)) - f.write('DATAPACKING=POINT\n') + f.write('Zone T="edge%d" I=%d\n' % (i, 2)) + f.write("DATAPACKING=POINT\n") v1 = self.el[i].con[0] v2 = self.el[i].con[1] - f.write('%g %g\n'%(self.vl[v1].x, - self.vl[v1].y)) + f.write("%g %g\n" % (self.vl[v1].x, self.vl[v1].y)) - f.write('%g %g\n'%(self.vl[v2].x, - self.vl[v2].y)) + f.write("%g %g\n" % (self.vl[v2].x, self.vl[v2].y)) f.close() + def findpoints(self, pl, onetoone=False): """Given a list of points pl, returns a list of with the corresponding face each point belongs to and @@ -4176,62 +4321,82 @@ def nvertices(self): return len(self.vertices) def nedges(self): - return len(self.hedges)//2 + return len(self.hedges) // 2 def saveDCEL(self, fileName): - f = open(fileName,'w') - f.write('%d %d %d\n'%( - self.nvertices(), self.nedges(), self.nfaces())) + f = open(fileName, "w") + f.write("%d %d %d\n" % (self.nvertices(), self.nedges(), self.nfaces())) for i in range(self.nvertices()): - f.write('%g %g %g %g %g \n'%( - self.vertices[i].x,self.vertices[i].y, + f.write( + "%g %g %g %g %g \n" + % ( + self.vertices[i].x, + self.vertices[i].y, self.vertices[i].X[0], self.vertices[i].X[1], - self.vertices[i].X[2])) + self.vertices[i].X[2], + ) + ) for i in range(self.nedges()): if self.el[i].seg is not None: - f.write('%d %d %g %g %g %g %g %g %s-%s\n'%( - self.el[i].con[0],self.el[i].con[1], - self.el[i].x1[0],self.el[i].x1[1],self.el[i].x1[2], - self.el[i].x2[0],self.el[i].x2[1],self.el[i].x2[2], - self.el[i].tag, self.el[i].seg)) + f.write( + "%d %d %g %g %g %g %g %g %s-%s\n" + % ( + self.el[i].con[0], + self.el[i].con[1], + self.el[i].x1[0], + self.el[i].x1[1], + self.el[i].x1[2], + self.el[i].x2[0], + self.el[i].x2[1], + self.el[i].x2[2], + self.el[i].tag, + self.el[i].seg, + ) + ) else: - f.write('%d %d %g %g %g %g %g %g %s\n'%( - self.el[i].con[0],self.el[i].con[1], - self.el[i].x1[0],self.el[i].x1[1],self.el[i].x1[2], - self.el[i].x2[0],self.el[i].x2[1],self.el[i].x2[2], - self.el[i].tag)) + f.write( + "%d %d %g %g %g %g %g %g %s\n" + % ( + self.el[i].con[0], + self.el[i].con[1], + self.el[i].x1[0], + self.el[i].x1[1], + self.el[i].x1[2], + self.el[i].x2[0], + self.el[i].x2[1], + self.el[i].x2[2], + self.el[i].tag, + ) + ) for i in range(self.nfaces()): - f.write('%s\n'%(self.faces[i].tag)) + f.write("%s\n" % (self.faces[i].tag)) f.close() def loadDCEL(self, fileName): - f = open(fileName,'r') + f = open(fileName, "r") # Read sizes tmp = f.readline().split() nvertices = int(tmp[0]) - nedges = int(tmp[1]) - nfaces = int(tmp[2]) + nedges = int(tmp[1]) + nfaces = int(tmp[2]) self.vl = [] self.el = [] self.faceInfo = [] for i in range(nvertices): a = f.readline().split() - self.vl.append(DCELVertex([float(a[0]),float(a[1])], - np.array([float(a[2]), - float(a[3]), - float(a[4])]))) + self.vl.append(DCELVertex([float(a[0]), float(a[1])], np.array([float(a[2]), float(a[3]), float(a[4])]))) for i in range(nedges): a = f.readline().split() - self.el.append(DCELEdge(int(a[0]),int(a[1]), None, None, None, a[8])) - self.el[-1].x1 = np.array([float(a[2]),float(a[3]),float(a[4])]) - self.el[-1].x2 = np.array([float(a[5]),float(a[6]),float(a[7])]) + self.el.append(DCELEdge(int(a[0]), int(a[1]), None, None, None, a[8])) + self.el[-1].x1 = np.array([float(a[2]), float(a[3]), float(a[4])]) + self.el[-1].x2 = np.array([float(a[5]), float(a[6]), float(a[7])]) for i in range(nfaces): a = f.readline().split() @@ -4239,7 +4404,8 @@ def loadDCEL(self, fileName): f.close() -#Misc. functions + +# Misc. functions def area2(hedge, point): """Determines the area of the triangle formed by a hedge and an external point""" @@ -4247,29 +4413,31 @@ def area2(hedge, point): pa = hedge.twin.origin pb = hedge.origin pc = point - return (pb.x - pa.x)*(pc[1] - pa.y) - (pc[0] - pa.x)*(pb.y - pa.y) + return (pb.x - pa.x) * (pc[1] - pa.y) - (pc[0] - pa.x) * (pb.y - pa.y) def isLeft(P0, P1, P2): return (P1[0] - P0[0]) * (P2[1] - P0[1]) - (P2[0] - P0[0]) * (P1[1] - P0[1]) + def lefton(hedge, point): """Determines if a point is to the left of a hedge""" return area2(hedge, point) >= 0 -def hangle(dx,dy): +def hangle(dx, dy): """Determines the angle with respect to the x axis of a segment of coordinates dx and dy """ - l = np.sqrt(dx*dx + dy*dy) + l = np.sqrt(dx * dx + dy * dy) if dy > 0: - return np.arccos(dx/l) + return np.arccos(dx / l) else: - return 2*np.pi - np.arccos(dx/l) + return 2 * np.pi - np.arccos(dx / l) + # --------------------- Polygon geometric functions ----------------- def areaPoly(nodes): @@ -4282,11 +4450,12 @@ def areaPoly(nodes): area = 0.0 for ii in range(len(nodes)): xi = nodes[ii] - xip1 = nodes[np.mod(ii+1, len(nodes))] - area = area + 0.5*np.linalg.norm(np.cross(xi-c,xip1-c)) + xip1 = nodes[np.mod(ii + 1, len(nodes))] + area = area + 0.5 * np.linalg.norm(np.cross(xi - c, xip1 - c)) return np.abs(area) + def volumePoly(lowerNodes, upperNodes): # Compute the volume of a 'polyhedreon' defined by a loop of nodes # on the 'bottom' and a loop on the 'top'. Like areaPoly, we use @@ -4297,7 +4466,7 @@ def volumePoly(lowerNodes, upperNodes): uc = np.average(upperNodes, axis=0) volume = 0.0 ln = len(lowerNodes) - n = np.zeros((6,3)) + n = np.zeros((6, 3)) for ii in range(len(lowerNodes)): # Each "wedge" can be sub-divided to 3 tetrahedra @@ -4320,23 +4489,24 @@ def volumePoly(lowerNodes, upperNodes): # + 1 n[0] = lowerNodes[ii] n[1] = lc - n[2] = lowerNodes[np.mod(ii+1, ln)] + n[2] = lowerNodes[np.mod(ii + 1, ln)] n[3] = upperNodes[ii] n[4] = uc - n[5] = upperNodes[np.mod(ii+1, ln)] - volume += volTetra([n[3],n[5],n[4],n[1]]) - volume += volTetra([n[5],n[2],n[1],n[0]]) - volume += volTetra([n[0],n[3],n[1],n[5]]) + n[5] = upperNodes[np.mod(ii + 1, ln)] + volume += volTetra([n[3], n[5], n[4], n[1]]) + volume += volTetra([n[5], n[2], n[1], n[0]]) + volume += volTetra([n[0], n[3], n[1], n[5]]) return volume + def volTetra(nodes): # Compute volume of tetrahedra given by 4 nodes a = nodes[1] - nodes[0] b = nodes[2] - nodes[0] c = nodes[3] - nodes[0] # Scalar triple product - V = (1.0/6.0)*np.linalg.norm(np.dot(a, np.cross(b,c))) + V = (1.0 / 6.0) * np.linalg.norm(np.dot(a, np.cross(b, c))) return V diff --git a/pygeo/pyBlock.py b/pygeo/pyBlock.py index b8dcfda6..b925c7de 100644 --- a/pygeo/pyBlock.py +++ b/pygeo/pyBlock.py @@ -8,26 +8,29 @@ from pyspline import pySpline from .geo_utils import readNValues, BlockTopology, blendKnotVectors + class Error(Exception): """ Format the error message in a box to make it clear this was a explicitly raised exception. """ + def __init__(self, message): - msg = '\n+'+'-'*78+'+'+'\n' + '| pyBlock Error: ' + msg = "\n+" + "-" * 78 + "+" + "\n" + "| pyBlock Error: " i = 16 for word in message.split(): - if len(word) + i + 1 > 78: # Finish line and start new one - msg += ' '*(78-i)+'|\n| ' + word + ' ' - i = 1 + len(word)+1 + if len(word) + i + 1 > 78: # Finish line and start new one + msg += " " * (78 - i) + "|\n| " + word + " " + i = 1 + len(word) + 1 else: - msg += word + ' ' - i += len(word)+1 - msg += ' '*(78-i) + '|\n' + '+'+'-'*78+'+'+'\n' + msg += word + " " + i += len(word) + 1 + msg += " " * (78 - i) + "|\n" + "+" + "-" * 78 + "+" + "\n" print(msg) Exception.__init__(self) -class pyBlock(): + +class pyBlock: """ pyBlock represents a collection of pySpline Volume objects. @@ -50,33 +53,35 @@ class pyBlock(): the plot 3d file explicitly become the control points and uniform (and symmetric) knot vectors are assumed everywhere. This ensures a seamless FFD. - """ + """ - def __init__(self, initType, fileName=None, FFD=False,symmPlane=None, **kwargs): + def __init__(self, initType, fileName=None, FFD=False, symmPlane=None, **kwargs): self.initType = initType self.FFD = False - self.topo = None # The topology of the volumes/surface - self.vols = [] # The list of volumes (pySpline volume) - self.nVol = None # The total number of volumessurfaces - self.coef = None # The global (reduced) set of control pts + self.topo = None # The topology of the volumes/surface + self.vols = [] # The list of volumes (pySpline volume) + self.nVol = None # The total number of volumessurfaces + self.coef = None # The global (reduced) set of control pts self.embededVolumes = {} self.symmPlane = symmPlane - if initType == 'plot3d': + if initType == "plot3d": self._readPlot3D(fileName, FFD=FFD, **kwargs) - elif initType == 'create': + elif initType == "create": pass else: - raise Error('initType must be one of "plot3d" or "create". \ - ("create" is only for expert debugging)') + raise Error( + 'initType must be one of "plot3d" or "create". \ + ("create" is only for expert debugging)' + ) -# ---------------------------------------------------------------------- -# Initialization Types -# ---------------------------------------------------------------------- + # ---------------------------------------------------------------------- + # Initialization Types + # ---------------------------------------------------------------------- - def _readPlot3D(self, fileName, order='f', FFD=False,symmTol=0.001): - """ Load a plot3D file and create the splines to go with each + def _readPlot3D(self, fileName, order="f", FFD=False, symmTol=0.001): + """Load a plot3D file and create the splines to go with each patch. See the pyBlock() docstring for more information. Parameters @@ -86,28 +91,27 @@ def _readPlot3D(self, fileName, order='f', FFD=False,symmTol=0.001): for fortran ordering. But could be 'c'. """ - binary = False # Binary read no longer supported. - f = open(fileName, 'r') - nVol = readNValues(f, 1, 'int', False)[0] - sizes = readNValues(f, nVol*3, 'int', False).reshape((nVol, 3)) + binary = False # Binary read no longer supported. + f = open(fileName, "r") + nVol = readNValues(f, 1, "int", False)[0] + sizes = readNValues(f, nVol * 3, "int", False).reshape((nVol, 3)) blocks = [] for i in range(nVol): - cur_size = sizes[i, 0]*sizes[i, 1]*sizes[i, 2] - blocks.append(numpy.zeros( - [sizes[i, 0], sizes[i, 1], sizes[i, 2], 3])) + cur_size = sizes[i, 0] * sizes[i, 1] * sizes[i, 2] + blocks.append(numpy.zeros([sizes[i, 0], sizes[i, 1], sizes[i, 2], 3])) for idim in range(3): - blocks[-1][:, :, :, idim] = readNValues( - f, cur_size, 'float', binary).reshape( - (sizes[i, 0], sizes[i, 1], sizes[i, 2]), order=order) + blocks[-1][:, :, :, idim] = readNValues(f, cur_size, "float", binary).reshape( + (sizes[i, 0], sizes[i, 1], sizes[i, 2]), order=order + ) f.close() def flip(axis, coords): """Flip coordinates by plane defined by 'axis'""" - if axis.lower() == 'x': + if axis.lower() == "x": index = 0 - elif axis.lower() == 'y': + elif axis.lower() == "y": index = 1 - elif axis.lower() == 'z': + elif axis.lower() == "z": index = 2 coords[:, :, :, index] = -coords[:, :, :, index] @@ -121,41 +125,41 @@ def flip(axis, coords): # for idim in range(3): # self.coords[:, j, k, idim] = self.coords[::-1, j, k, idim] - def symmZero(axis,coords,tol): + def symmZero(axis, coords, tol): """ set all coords within a certain tolerance of the symm plan to be exactly 0""" - if axis.lower() == 'x': + if axis.lower() == "x": index = 0 - elif axis.lower() == 'y': + elif axis.lower() == "y": index = 1 - elif axis.lower() == 'z': + elif axis.lower() == "z": index = 2 dims = coords.shape for k in range(dims[2]): for j in range(dims[1]): for i in range(dims[0]): - error = abs(coords[i,j,k,index]) + error = abs(coords[i, j, k, index]) if error <= tol: - coords[i,j,k,index]=0 + coords[i, j, k, index] = 0 if self.symmPlane is not None: - #duplicate and mirror the blocks. + # duplicate and mirror the blocks. newBlocks = [] for block in blocks: newBlock = copy.deepcopy(block) - symmZero(self.symmPlane,newBlock,symmTol) - flip(self.symmPlane,newBlock) + symmZero(self.symmPlane, newBlock, symmTol) + flip(self.symmPlane, newBlock) newBlocks.append(newBlock) # now create the appended list with double the blocks - blocks+=newBlocks - #Extend sizes - newSizes = numpy.zeros([nVol*2,3],'int') - newSizes[:nVol,:] = sizes - newSizes[nVol:,:] = sizes + blocks += newBlocks + # Extend sizes + newSizes = numpy.zeros([nVol * 2, 3], "int") + newSizes[:nVol, :] = sizes + newSizes[nVol:, :] = sizes sizes = newSizes - #increase the volume counter - nVol*=2 + # increase the volume counter + nVol *= 2 # Now create a list of spline volume objects: self.vols = [] @@ -164,13 +168,13 @@ def symmZero(axis,coords,tol): self.FFD = True def uniformKnots(N, k): - """ Simple function to generate N uniform knots of + """Simple function to generate N uniform knots of order k""" - knots = numpy.zeros(N+k) - knots[0:k-1] = 0.0 + knots = numpy.zeros(N + k) + knots[0 : k - 1] = 0.0 knots[-k:] = 1.0 - knots[k-1:-k+1] = numpy.linspace(0, 1, N-k+2) + knots[k - 1 : -k + 1] = numpy.linspace(0, 1, N - k + 2) return knots @@ -183,11 +187,17 @@ def uniformKnots(N, k): # propagate the vectors since they are by # construction symmetric - self.vols.append(pySpline.Volume( - ku=ku, kv=kv, kw=kw, coef=blocks[ivol], - tu=uniformKnots(sizes[ivol, 0], ku), - tv=uniformKnots(sizes[ivol, 1], kv), - tw=uniformKnots(sizes[ivol, 2], kw))) + self.vols.append( + pySpline.Volume( + ku=ku, + kv=kv, + kw=kw, + coef=blocks[ivol], + tu=uniformKnots(sizes[ivol, 0], ku), + tv=uniformKnots(sizes[ivol, 1], kv), + tw=uniformKnots(sizes[ivol, 2], kw), + ) + ) # Generate dummy original data: U = numpy.zeros((3, 3, 3)) @@ -197,9 +207,9 @@ def uniformKnots(N, k): for i in range(3): for j in range(3): for k in range(3): - U[i, j, k] = float(i)/2 - V[i, j, k] = float(j)/2 - W[i, j, k] = float(k)/2 + U[i, j, k] = float(i) / 2 + V[i, j, k] = float(j) / 2 + W[i, j, k] = float(k) / 2 # Evaluate the spline "original data" self.vols[-1].X = self.vols[-1](U, V, W) @@ -220,18 +230,16 @@ def uniformKnots(N, k): self.vols[ivol].setFaceSurfaces() self.vols[ivol].setEdgeCurves() - else: # (not FFD check --- must run fitGlobal after!) + else: # (not FFD check --- must run fitGlobal after!) # Note This doesn't actually fit the volumes...just produces # the parametrization and knot vectors for ivol in range(nVol): - self.vols.append(pySpline.Volume( - X=blocks[ivol], ku=4, kv=4, kw=4, - nCtlu=4, nCtlv=4, nCtlw=4, - recompute=False)) + self.vols.append( + pySpline.Volume(X=blocks[ivol], ku=4, kv=4, kw=4, nCtlu=4, nCtlv=4, nCtlw=4, recompute=False) + ) self.nVol = len(self.vols) # end if (FFD Check) - def fitGlobal(self, greedyReorder=False): """ Determine the set of b-spline coefficients that best fits the @@ -243,39 +251,35 @@ def fitGlobal(self, greedyReorder=False): greedyReorder : bool Flag to compute ordering of initial mesh in a greedy ordering sense. - """ + """ nCtl = self.topo.nGlobal origTopo = copy.deepcopy(self.topo) - print(' -> Creating global numbering') + print(" -> Creating global numbering") sizes = [] for ivol in range(self.nVol): - sizes.append([self.vols[ivol].Nu, - self.vols[ivol].Nv, - self.vols[ivol].Nw]) + sizes.append([self.vols[ivol].Nu, self.vols[ivol].Nv, self.vols[ivol].Nw]) # Get the Global number of the original data origTopo.calcGlobalNumbering(sizes, greedyReorder=greedyReorder) N = origTopo.nGlobal - print(' -> Creating global point list') + print(" -> Creating global point list") pts = numpy.zeros((N, 3)) for ii in range(N): pts[ii] = self.vols[origTopo.gIndex[ii][0][0]].X[ - origTopo.gIndex[ii][0][1], - origTopo.gIndex[ii][0][2], - origTopo.gIndex[ii][0][3]] + origTopo.gIndex[ii][0][1], origTopo.gIndex[ii][0][2], origTopo.gIndex[ii][0][3] + ] # Get the maximum k (ku, kv, kw for each vol) kmax = 2 for ivol in range(self.nVol): - kmax = max(kmax, self.vols[ivol].ku, self.vols[ivol].kv, - self.vols[ivol].kw) + kmax = max(kmax, self.vols[ivol].ku, self.vols[ivol].kv, self.vols[ivol].kw) - nnz = N*kmax*kmax*kmax + nnz = N * kmax * kmax * kmax vals = numpy.zeros(nnz) rowPtr = [0] - colInd = numpy.zeros(nnz, 'intc') + colInd = numpy.zeros(nnz, "intc") for ii in range(N): ivol = origTopo.gIndex[ii][0][0] i = origTopo.gIndex[ii][0][1] @@ -286,36 +290,34 @@ def fitGlobal(self, greedyReorder=False): v = self.vols[ivol].V[i, j, k] w = self.vols[ivol].W[i, j, k] - vals, colInd = self.vols[ivol].getBasisPt( - u, v, w, vals, rowPtr[ii], colInd, self.topo.lIndex[ivol]) - kinc = self.vols[ivol].ku*self.vols[ivol].kv*self.vols[ivol].kw + vals, colInd = self.vols[ivol].getBasisPt(u, v, w, vals, rowPtr[ii], colInd, self.topo.lIndex[ivol]) + kinc = self.vols[ivol].ku * self.vols[ivol].kv * self.vols[ivol].kw rowPtr.append(rowPtr[-1] + kinc) # Now we can crop out any additional values in colInd and vals - vals = vals[:rowPtr[-1]] - colInd = colInd[:rowPtr[-1]] + vals = vals[: rowPtr[-1]] + colInd = colInd[: rowPtr[-1]] # Now make a sparse matrix, the N, and N^T * N factors, sovle # and set: NN = sparse.csr_matrix((vals, colInd, rowPtr)) NNT = NN.T - NTN = NNT*NN + NTN = NNT * NN solve = linalg.dsolve.factorized(NTN) self.coef = numpy.zeros((nCtl, 3)) for idim in range(3): - self.coef[:, idim] = solve(NNT*pts[:, idim]) + self.coef[:, idim] = solve(NNT * pts[:, idim]) self._updateVolumeCoef() for ivol in range(self.nVol): self.vols[ivol].setFaceSurfaces() self.vols[ivol].setEdgeCurves() -# ---------------------------------------------------------------------- -# Topology Information Functions -# ---------------------------------------------------------------------- + # ---------------------------------------------------------------------- + # Topology Information Functions + # ---------------------------------------------------------------------- - def doConnectivity(self, fileName=None, nodeTol=1e-4, edgeTol=1e-4, - greedyReorder=False): + def doConnectivity(self, fileName=None, nodeTol=1e-4, edgeTol=1e-4, greedyReorder=False): """ This function is used if a separate fitting topology is required for non-FFD creations. The sequence of calls is given @@ -332,25 +334,24 @@ def doConnectivity(self, fileName=None, nodeTol=1e-4, edgeTol=1e-4, Tolerance for co-incidient mid points of edges greedyReorder : bool Flag to reorder numbering in a greedy form. - """ + """ if fileName is not None and os.path.isfile(fileName): - print(' ') - print('Reading Connectivity File: %s'%(fileName)) + print(" ") + print("Reading Connectivity File: %s" % (fileName)) self.topo = BlockTopology(file=fileName) self._propagateKnotVectors() else: - print(' ') + print(" ") self._calcConnectivity(nodeTol, edgeTol) self._propagateKnotVectors() if fileName is not None: - print('Writing Connectivity File: %s'%(fileName)) + print("Writing Connectivity File: %s" % (fileName)) self.topo.writeConnectivity(fileName) sizes = [] for ivol in range(self.nVol): - sizes.append([self.vols[ivol].nClu, self.vols[ivol].nCtlv, - self.vols[ivol].nCtlw]) + sizes.append([self.vols[ivol].nClu, self.vols[ivol].nCtlv, self.vols[ivol].nCtlw]) self.topo.calcGlobalNumbering(sizes, greedyReorder=greedyReorder) def _calcConnectivity(self, nodeTol, edgeTol): @@ -367,22 +368,18 @@ def _calcConnectivity(self, nodeTol, edgeTol): for ivol in range(self.nVol): for icorner in range(8): - coords[ivol, icorner] = \ - self.vols[ivol].getOrigValueCorner(icorner) + coords[ivol, icorner] = self.vols[ivol].getOrigValueCorner(icorner) for iedge in range(12): - coords[ivol, 8+iedge] = \ - self.vols[ivol].getMidPointEdge(iedge) + coords[ivol, 8 + iedge] = self.vols[ivol].getMidPointEdge(iedge) for iface in range(6): - coords[ivol, 20+iface] = \ - self.vols[ivol].getMidPointFace(iface) + coords[ivol, 20 + iface] = self.vols[ivol].getMidPointFace(iface) self.topo = BlockTopology(coords, nodeTol=nodeTol, edgeTol=edgeTol) sizes = [] for ivol in range(self.nVol): - sizes.append([self.vols[ivol].nCtlu, self.vols[ivol].nCtlv, - self.vols[ivol].nCtlw]) + sizes.append([self.vols[ivol].nCtlu, self.vols[ivol].nCtlv, self.vols[ivol].nCtlw]) self.topo.calcGlobalNumbering(sizes) def printConnectivity(self): @@ -437,8 +434,7 @@ def _propagateKnotVectors(self): flip = [] for ivol in range(self.nVol): for iedge in range(12): - if self.topo.edges[ - self.topo.edgeLink[ivol][iedge]].dg == idg: + if self.topo.edges[self.topo.edgeLink[ivol][iedge]].dg == idg: if self.topo.edgeDir[ivol][iedge] == -1: flip.append(True) @@ -453,20 +449,19 @@ def _propagateKnotVectors(self): knotVec = self.vols[ivol].tw if flip[-1]: - knotVectors.append((1-knotVec)[::-1].copy()) + knotVectors.append((1 - knotVec)[::-1].copy()) else: knotVectors.append(knotVec) # Now blend all the knot vectors newKnotVec = blendKnotVectors(knotVectors, False) - newKnotVecFlip = (1-newKnotVec)[::-1] + newKnotVecFlip = (1 - newKnotVec)[::-1] # And now reset them all: counter = 0 for ivol in range(self.nVol): for iedge in range(12): - if self.topo.edges[ - self.topo.edgeLink[ivol][iedge]].dg == idg: + if self.topo.edges[self.topo.edgeLink[ivol][iedge]].dg == idg: if iedge in [0, 1, 4, 5]: if flip[counter]: @@ -492,11 +487,12 @@ def _propagateKnotVectors(self): # end for (edge loop) # end for (dg loop) -# ---------------------------------------------------------------------- -# Output Functions -# ---------------------------------------------------------------------- - def writeTecplot(self, fileName, vols=True, coef=True, orig=False, - volLabels=False, edgeLabels=False, nodeLabels=False): + # ---------------------------------------------------------------------- + # Output Functions + # ---------------------------------------------------------------------- + def writeTecplot( + self, fileName, vols=True, coef=True, orig=False, volLabels=False, edgeLabels=False, nodeLabels=False + ): """Write a tecplot visualization of the pyBlock object. Parameters @@ -524,7 +520,7 @@ def writeTecplot(self, fileName, vols=True, coef=True, orig=False, nodeLabels: bool. Default is False Flag to write node labels in a separate tecplot file; filename is derived from the supplied fileName. - """ + """ # Open File and output header f = pySpline.openTecplot(fileName, 3) @@ -532,15 +528,14 @@ def writeTecplot(self, fileName, vols=True, coef=True, orig=False, if vols: for ivol in range(self.nVol): self.vols[ivol].computeData() - pySpline.writeTecplot3D(f, 'interpolated', - self.vols[ivol].data) + pySpline.writeTecplot3D(f, "interpolated", self.vols[ivol].data) if orig: for ivol in range(self.nVol): - pySpline.writeTecplot3D(f, 'orig_data', self.vols[ivol].X) + pySpline.writeTecplot3D(f, "orig_data", self.vols[ivol].X) if coef: for ivol in range(self.nVol): - pySpline.writeTecplot3D(f, 'control_pts', self.vols[ivol].coef) + pySpline.writeTecplot3D(f, "control_pts", self.vols[ivol].coef) # --------------------------------------------- # Write out labels: @@ -549,32 +544,33 @@ def writeTecplot(self, fileName, vols=True, coef=True, orig=False, # Split the filename off dirName, fileName = os.path.split(fileName) fileBaseName, fileExtension = os.path.splitext(fileName) - labelFilename = dirName+'./' + fileBaseName+'.vol_labels.dat' - f2 = open(labelFilename, 'w') + labelFilename = dirName + "./" + fileBaseName + ".vol_labels.dat" + f2 = open(labelFilename, "w") for ivol in range(self.nVol): - midu = self.vols[ivol].nCtlu//2 - midv = self.vols[ivol].nCtlv//2 - midw = self.vols[ivol].nCtlw//2 - textString = 'TEXT CS=GRID3D, X=%f, Y=%f, Z=%f, T=\"V%d\"\n'% ( + midu = self.vols[ivol].nCtlu // 2 + midv = self.vols[ivol].nCtlv // 2 + midw = self.vols[ivol].nCtlw // 2 + textString = 'TEXT CS=GRID3D, X=%f, Y=%f, Z=%f, T="V%d"\n' % ( self.vols[ivol].coef[midu, midv, midw, 0], self.vols[ivol].coef[midu, midv, midw, 1], - self.vols[ivol].coef[midu, midv, midw, 2], ivol) - f2.write('%s'%(textString)) + self.vols[ivol].coef[midu, midv, midw, 2], + ivol, + ) + f2.write("%s" % (textString)) f2.close() if edgeLabels: # Split the filename off dirName, fileName = os.path.split(fileName) fileBaseName, fileExtension = os.path.splitext(fileName) - labelFilename = dirName+'./' + fileBaseName+'.edge_labels.dat' - f2 = open(labelFilename, 'w') + labelFilename = dirName + "./" + fileBaseName + ".edge_labels.dat" + f2 = open(labelFilename, "w") for ivol in range(self.nVol): for iedge in range(12): pt = self.vols[ivol].edgeCurves[iedge](0.5) edgeID = self.topo.edgeLink[ivol][iedge] - textString = 'TEXT CS=GRID3D X=%f, Y=%f, Z=%f, T=\"E%d\"\n'% ( - pt[0], pt[1], pt[2], edgeID) - f2.write('%s'%(textString)) + textString = 'TEXT CS=GRID3D X=%f, Y=%f, Z=%f, T="E%d"\n' % (pt[0], pt[1], pt[2], edgeID) + f2.write("%s" % (textString)) f2.close() if nodeLabels: @@ -585,7 +581,7 @@ def writeTecplot(self, fileName, vols=True, coef=True, orig=False, for i in range(nNodes): # Try to find node i for ivol in range(self.nVol): - for inode in range(8): + for inode in range(8): if self.topo.nodeLink[ivol][inode] == i: coordinate = self.vols[ivol].getValueCorner(inode) @@ -594,12 +590,16 @@ def writeTecplot(self, fileName, vols=True, coef=True, orig=False, # Split the filename off dirName, fileName = os.path.split(fileName) fileBaseName, fileExtension = os.path.splitext(fileName) - labelFilename = dirName+'./' + fileBaseName+'.node_labels.dat' - f2 = open(labelFilename, 'w') + labelFilename = dirName + "./" + fileBaseName + ".node_labels.dat" + f2 = open(labelFilename, "w") for i in range(nNodes): - textString = 'TEXT CS=GRID3D, X=%f, Y=%f, Z=%f, T=\"n%d\"\n'% ( - nodeCoord[i][0], nodeCoord[i][1], nodeCoord[i][2], i) - f2.write('%s'%(textString)) + textString = 'TEXT CS=GRID3D, X=%f, Y=%f, Z=%f, T="n%d"\n' % ( + nodeCoord[i][0], + nodeCoord[i][1], + nodeCoord[i][2], + i, + ) + f2.write("%s" % (textString)) f2.close() pySpline.closeTecplot(f) @@ -620,19 +620,18 @@ def writePlot3d(self, fileName): sizes.append(self.vols[ivol].Nv) sizes.append(self.vols[ivol].Nw) - f = open(fileName, 'w') - f.write('%d\n'%(self.nVol)) + f = open(fileName, "w") + f.write("%d\n" % (self.nVol)) numpy.array(sizes).tofile(f, sep=" ") - f.write('\n') + f.write("\n") for ivol in range(self.nVol): - vals = self.vols[ivol](self.vols[ivol].U, self.vols[ivol].V, - self.vols[ivol].W) + vals = self.vols[ivol](self.vols[ivol].U, self.vols[ivol].V, self.vols[ivol].W) vals[:, :, :, 0].flatten(order="F").tofile(f, sep="\n") - f.write('\n') + f.write("\n") vals[:, :, :, 1].flatten(order="F").tofile(f, sep="\n") - f.write('\n') + f.write("\n") vals[:, :, :, 2].flatten(order="F").tofile(f, sep="\n") - f.write('\n') + f.write("\n") f.close() def writePlot3dCoef(self, fileName): @@ -651,32 +650,32 @@ def writePlot3dCoef(self, fileName): sizes.append(self.vols[ivol].nCtlv) sizes.append(self.vols[ivol].nCtlw) - f = open(fileName, 'w') - f.write('%d\n'% (self.nVol)) + f = open(fileName, "w") + f.write("%d\n" % (self.nVol)) numpy.array(sizes).tofile(f, sep=" ") - f.write('\n') + f.write("\n") for ivol in range(self.nVol): vals = self.vols[ivol].coef vals[:, :, :, 0].flatten(order="F").tofile(f, sep="\n") - f.write('\n') + f.write("\n") vals[:, :, :, 1].flatten(order="F").tofile(f, sep="\n") - f.write('\n') + f.write("\n") vals[:, :, :, 2].flatten(order="F").tofile(f, sep="\n") - f.write('\n') + f.write("\n") f.close() -# ---------------------------------------------------------------------- -# Update Functions -# ---------------------------------------------------------------------- + # ---------------------------------------------------------------------- + # Update Functions + # ---------------------------------------------------------------------- def _updateVolumeCoef(self): """Copy the pyBlock list of control points back to the volumes""" for ii in range(len(self.coef)): for jj in range(len(self.topo.gIndex[ii])): - ivol = self.topo.gIndex[ii][jj][0] - i = self.topo.gIndex[ii][jj][1] - j = self.topo.gIndex[ii][jj][2] - k = self.topo.gIndex[ii][jj][3] - self.vols[ivol].coef[i, j, k] = self.coef[ii].real.astype('d') + ivol = self.topo.gIndex[ii][jj][0] + i = self.topo.gIndex[ii][jj][1] + j = self.topo.gIndex[ii][jj][2] + k = self.topo.gIndex[ii][jj][3] + self.vols[ivol].coef[i, j, k] = self.coef[ii].real.astype("d") def _setVolumeCoef(self): """Set the global coefficient array self.coef from the @@ -689,8 +688,7 @@ def _setVolumeCoef(self): for i in range(vol.nCtlu): for j in range(vol.nCtlv): for k in range(vol.nCtlw): - self.coef[self.topo.lIndex[ivol][i, j, k]] = \ - vol.coef[i, j, k] + self.coef[self.topo.lIndex[ivol][i, j, k]] = vol.coef[i, j, k] def calcdPtdCoef(self, ptSetName): """Calculate the (fixed) derivative of a set of embedded @@ -713,35 +711,33 @@ def calcdPtdCoef(self, ptSetName): # Get the maximum k (ku or kv for each volume) kmax = 2 for ivol in range(self.nVol): - kmax = max(kmax, self.vols[ivol].ku, self.vols[ivol].kv, - self.vols[ivol].kw) + kmax = max(kmax, self.vols[ivol].ku, self.vols[ivol].kv, self.vols[ivol].kw) # Maximum number of non-zeros in jacobian - nnz = N*kmax*kmax*kmax + nnz = N * kmax * kmax * kmax vals = numpy.zeros(nnz) rowPtr = [0] - colInd = numpy.zeros(nnz, 'intc') + colInd = numpy.zeros(nnz, "intc") for i in range(N): - kinc = self.vols[volID[i]].ku*\ - self.vols[volID[i]].kv*\ - self.vols[volID[i]].kw - vals, colInd = self.vols[volID[i]].getBasisPt(\ - u[i], v[i], w[i], vals, rowPtr[i], colInd, - self.topo.lIndex[volID[i]]) + kinc = self.vols[volID[i]].ku * self.vols[volID[i]].kv * self.vols[volID[i]].kw + vals, colInd = self.vols[volID[i]].getBasisPt( + u[i], v[i], w[i], vals, rowPtr[i], colInd, self.topo.lIndex[volID[i]] + ) rowPtr.append(rowPtr[-1] + kinc) if self.embededVolumes[ptSetName].mask is not None: if not i in self.embededVolumes[ptSetName].mask: # Kill the values we just added - vals[rowPtr[-2]:rowPtr[-1]] = 0.0 + vals[rowPtr[-2] : rowPtr[-1]] = 0.0 # Now we can crop out any additional values in colInd and vals - vals = vals[:rowPtr[-1]] - colInd = colInd[:rowPtr[-1]] + vals = vals[: rowPtr[-1]] + colInd = colInd[: rowPtr[-1]] # Now make a sparse matrix iff we actually have coordinates if N > 0: self.embededVolumes[ptSetName].dPtdCoef = sparse.csr_matrix( - (vals, colInd, rowPtr), shape=[N, len(self.coef)]) + (vals, colInd, rowPtr), shape=[N, len(self.coef)] + ) def getAttachedPoints(self, ptSetName): """ @@ -758,20 +754,20 @@ def getAttachedPoints(self, ptSetName): The coordinates of the embedded points. If a mask was used, only the points corresponding to the indices in mask will be non-zero in the array. - """ + """ volID = self.embededVolumes[ptSetName].volID - u = self.embededVolumes[ptSetName].u - v = self.embededVolumes[ptSetName].v - w = self.embededVolumes[ptSetName].w - N = self.embededVolumes[ptSetName].N - mask = self.embededVolumes[ptSetName].mask + u = self.embededVolumes[ptSetName].u + v = self.embededVolumes[ptSetName].v + w = self.embededVolumes[ptSetName].w + N = self.embededVolumes[ptSetName].N + mask = self.embededVolumes[ptSetName].mask coordinates = numpy.zeros((N, 3)) # This evaluation is fast enough we don't really care about # only looping explictly over the mask values for iVol in self.embededVolumes[ptSetName].indices: - indices = self.embededVolumes[ptSetName].indices[iVol] + indices = self.embededVolumes[ptSetName].indices[iVol] u = self.embededVolumes[ptSetName].u[indices] v = self.embededVolumes[ptSetName].v[indices] w = self.embededVolumes[ptSetName].w[indices] @@ -781,18 +777,17 @@ def getAttachedPoints(self, ptSetName): if mask is not None: # Explictly zero anything not in mask to ensure no-one # accidently uses it when they should not - tmp = coordinates.copy() # Create copy - coordinates[:,:] = 0.0 # Completely zero - coordinates[mask, :] = tmp[mask, :] # Just put back the ones we wnat. + tmp = coordinates.copy() # Create copy + coordinates[:, :] = 0.0 # Completely zero + coordinates[mask, :] = tmp[mask, :] # Just put back the ones we wnat. return coordinates -# ---------------------------------------------------------------------- -# Embedded Geometry Functions -# ---------------------------------------------------------------------- + # ---------------------------------------------------------------------- + # Embedded Geometry Functions + # ---------------------------------------------------------------------- - def attachPoints(self, coordinates, ptSetName, interiorOnly=False, - faceFreeze=None, eps=1e-12, **kwargs): + def attachPoints(self, coordinates, ptSetName, interiorOnly=False, faceFreeze=None, eps=1e-12, **kwargs): """Embed a set of coordinates into the volumes. This is the main high level function that is used by DVGeometry when pyBlock is used as an FFD. @@ -821,17 +816,15 @@ def attachPoints(self, coordinates, ptSetName, interiorOnly=False, # Project Points, if some were actually passed in: if coordinates is not None: if not interiorOnly: - volID, u, v, w, D = self.projectPoints( - coordinates, checkErrors=True, eps=eps, **kwargs) + volID, u, v, w, D = self.projectPoints(coordinates, checkErrors=True, eps=eps, **kwargs) self.embededVolumes[ptSetName] = EmbeddedVolume(volID, u, v, w) else: - volID, u, v, w, D = self.projectPoints( - coordinates, checkErrors=False, eps=eps, **kwargs) + volID, u, v, w, D = self.projectPoints(coordinates, checkErrors=False, eps=eps, **kwargs) mask = [] for i in range(len(D)): Dnrm = numpy.linalg.norm(D[i]) - if Dnrm < 50*eps: # Sufficiently inside + if Dnrm < 50 * eps: # Sufficiently inside mask.append(i) # Now that we have the mask we can create the embedded volume @@ -840,9 +833,9 @@ def attachPoints(self, coordinates, ptSetName, interiorOnly=False, return -# ---------------------------------------------------------------------- -# Geometric Functions -# ---------------------------------------------------------------------- + # ---------------------------------------------------------------------- + # Geometric Functions + # ---------------------------------------------------------------------- def projectPoints(self, x0, eps=1e-12, checkErrors=True, nIter=100): """Project a set of points x0, into any one of the volumes. It @@ -876,11 +869,11 @@ def projectPoints(self, x0, eps=1e-12, checkErrors=True, nIter=100): # Make sure we are dealing with a 2D "Nx3" list of points x0 = numpy.atleast_2d(x0) N = len(x0) - volID = numpy.zeros(N, 'intc') - u = numpy.zeros(N) - v = numpy.zeros(N) - w = numpy.zeros(N) - D = 1e10*numpy.ones((N, 3)) + volID = numpy.zeros(N, "intc") + u = numpy.zeros(N) + v = numpy.zeros(N) + w = numpy.zeros(N) + D = 1e10 * numpy.ones((N, 3)) # Starting list is just [0, 1, 2, ..., nVol-1] volList = numpy.arange(self.nVol) @@ -891,8 +884,7 @@ def projectPoints(self, x0, eps=1e-12, checkErrors=True, nIter=100): for i in range(N): for j in range(self.nVol): iVol = volList[j] - u0, v0, w0, D0 = self.vols[iVol].projectPoint( - x0[i], eps=eps, nIter=nIter) + u0, v0, w0, D0 = self.vols[iVol].projectPoint(x0[i], eps=eps, nIter=nIter) D0Norm = numpy.linalg.norm(D0) # If the new distance is less than the previous best @@ -908,14 +900,14 @@ def projectPoints(self, x0, eps=1e-12, checkErrors=True, nIter=100): # Now, if D0 is close enough to our tolerance, we can # exit the loop since we know we won't do any better - if (D0Norm < eps*50): + if D0Norm < eps * 50: break # end for (volume loop) # Shuffle the order of the volList such that the last # volume used (iVol or volList[j]) is at the start of the # list and the remainder are shuffled towards the back - volList = numpy.hstack([iVol, volList[:j], volList[j+1:]]) + volList = numpy.hstack([iVol, volList[:j], volList[j + 1 :]]) # end for (length of x0) # If desired check the errors and print warnings: @@ -931,8 +923,8 @@ def projectPoints(self, x0, eps=1e-12, checkErrors=True, nIter=100): if nrm > DMax: DMax = nrm - DRms += nrm**2 - if nrm > eps*50: + DRms += nrm ** 2 + if nrm > eps * 50: counter += 1 badPts.append([x0[i], D[i]]) @@ -943,17 +935,24 @@ def projectPoints(self, x0, eps=1e-12, checkErrors=True, nIter=100): # Check to see if we have bad projections and print a warning: if counter > 0: - print(' -> Warning: %d point(s) not projected to tolerance: \ - %g\n. Max Error: %12.6g ; RMS Error: %12.6g'%(counter, eps, DMax, DRms)) - print('List of Points is: (pt, delta):') + print( + " -> Warning: %d point(s) not projected to tolerance: \ + %g\n. Max Error: %12.6g ; RMS Error: %12.6g" + % (counter, eps, DMax, DRms) + ) + print("List of Points is: (pt, delta):") for i in range(len(badPts)): - print('[%12.5g %12.5g %12.5g] [%12.5g %12.5g %12.5g]'%( - badPts[i][0][0], - badPts[i][0][1], - badPts[i][0][2], - badPts[i][1][0], - badPts[i][1][1], - badPts[i][1][2])) + print( + "[%12.5g %12.5g %12.5g] [%12.5g %12.5g %12.5g]" + % ( + badPts[i][0][0], + badPts[i][0][1], + badPts[i][0][2], + badPts[i][1][0], + badPts[i][1][1], + badPts[i][1][2], + ) + ) return volID, u, v, w, D @@ -966,7 +965,7 @@ def getBounds(self): Lower corner of the bounding box xMax : array of length 3 Upper corner of the bounding box - """ + """ Xmin, Xmax = self.vols[0].getBounds() for iVol in range(1, self.nVol): @@ -977,6 +976,7 @@ def getBounds(self): return Xmin, Xmax + class EmbeddedVolume(object): """A Container class for a set of embedded volume points @@ -991,7 +991,7 @@ class EmbeddedVolume(object): u,v,w,volID). It contains only a subset of the indices to be used. It is used for DVGeometry's children implementation. - """ + """ def __init__(self, volID, u, v, w, mask=None): self.volID = numpy.array(volID) @@ -1001,8 +1001,8 @@ def __init__(self, volID, u, v, w, mask=None): self.N = len(self.u) self.indices = {} self.dPtdCoef = None - self.dPtdX = None - self.mask = mask + self.dPtdX = None + self.mask = mask # Get the number of unique volumes this point set requires: uniqueVolIDs = numpy.unique(self.volID) diff --git a/pygeo/pyGeo.py b/pygeo/pyGeo.py index a22dc265..91ffaf03 100644 --- a/pygeo/pyGeo.py +++ b/pygeo/pyGeo.py @@ -8,26 +8,29 @@ from pyspline import pySpline from . import geo_utils + class Error(Exception): """ Format the error message in a box to make it clear this was a explicitly raised exception. """ + def __init__(self, message): - msg = '\n+'+'-'*78+'+'+'\n' + '| pyGeo Error: ' + msg = "\n+" + "-" * 78 + "+" + "\n" + "| pyGeo Error: " i = 14 for word in message.split(): - if len(word) + i + 1 > 78: # Finish line and start new one - msg += ' '*(78-i)+'|\n| ' + word + ' ' - i = 1 + len(word)+1 + if len(word) + i + 1 > 78: # Finish line and start new one + msg += " " * (78 - i) + "|\n| " + word + " " + i = 1 + len(word) + 1 else: - msg += word + ' ' - i += len(word)+1 - msg += ' '*(78-i) + '|\n' + '+'+'-'*78+'+'+'\n' + msg += word + " " + i += len(word) + 1 + msg += " " * (78 - i) + "|\n" + "+" + "-" * 78 + "+" + "\n" print(msg) Exception.__init__(self) -class pyGeo(): + +class pyGeo: """ pyGeo is a (fairly) complete geometry surfacing engine. It performs multiple functions including producing surfaces from @@ -71,37 +74,39 @@ class pyGeo(): kSpan : int The spline order in span-wise direction. 2 for linear, 3 for quadratic and 4 for cubic - """ + """ def __init__(self, initType, *args, **kwargs): self.initType = initType - print('pyGeo Initialization Type is: %s'%(initType)) + print("pyGeo Initialization Type is: %s" % (initType)) - #------------------- pyGeo Class Attributes ----------------- - self.topo = None # The topology of the surfaces - self.surfs = [] # The list of surface (pySpline surf) - # objects - self.nSurf = None # The total number of surfaces - self.coef = None # The global (reduced) set of control - # points + # ------------------- pyGeo Class Attributes ----------------- + self.topo = None # The topology of the surfaces + self.surfs = [] # The list of surface (pySpline surf) + # objects + self.nSurf = None # The total number of surfaces + self.coef = None # The global (reduced) set of control + # points - if initType == 'plot3d': + if initType == "plot3d": self._readPlot3D(*args, **kwargs) - elif initType == 'iges': + elif initType == "iges": self._readIges(*args, **kwargs) - elif initType == 'liftingSurface': + elif initType == "liftingSurface": self._init_lifting_surface(*args, **kwargs) - elif initType == 'create': # Don't do anything + elif initType == "create": # Don't do anything pass else: - raise Error('Unknown init type. Valid Init types are \'plot3d\', \ -\'iges\' and \'liftingSurface\'') + raise Error( + "Unknown init type. Valid Init types are 'plot3d', \ +'iges' and 'liftingSurface'" + ) -# ---------------------------------------------------------------------------- -# Initialization Type Functions -# ---------------------------------------------------------------------------- + # ---------------------------------------------------------------------------- + # Initialization Type Functions + # ---------------------------------------------------------------------------- - def _readPlot3D(self, fileName, order='f'): + def _readPlot3D(self, fileName, order="f"): """Load a plot3D file and create the splines to go with each patch Parameters @@ -111,16 +116,15 @@ def _readPlot3D(self, fileName, order='f'): order : str 'f' for fortran ordering (usual), 'c' for c ordering """ - f = open(fileName, 'r') + f = open(fileName, "r") binary = False - nSurf = geo_utils.readNValues(f, 1, 'int', binary)[0] - sizes = geo_utils.readNValues( - f, nSurf*3, 'int', binary).reshape((nSurf, 3)) + nSurf = geo_utils.readNValues(f, 1, "int", binary)[0] + sizes = geo_utils.readNValues(f, nSurf * 3, "int", binary).reshape((nSurf, 3)) # ONE of Patch Sizes index must be one nPts = 0 for i in range(nSurf): - if sizes[i, 0] == 1: # Compress back to indices 0 and 1 + if sizes[i, 0] == 1: # Compress back to indices 0 and 1 sizes[i, 0] = sizes[i, 1] sizes[i, 1] = sizes[i, 2] elif sizes[i, 1] == 1: @@ -128,18 +132,18 @@ def _readPlot3D(self, fileName, order='f'): elif sizes[i, 2] == 1: pass else: - raise Error('One of the plot3d indices must be 1') + raise Error("One of the plot3d indices must be 1") - nPts += sizes[i, 0]*sizes[i, 1] + nPts += sizes[i, 0] * sizes[i, 1] surfs = [] for i in range(nSurf): - curSize = sizes[i, 0]*sizes[i, 1] + curSize = sizes[i, 0] * sizes[i, 1] surfs.append(numpy.zeros([sizes[i, 0], sizes[i, 1], 3])) for idim in range(3): - surfs[-1][:, :, idim] = geo_utils.readNValues( - f, curSize, 'float', binary).reshape( - (sizes[i, 0], sizes[i, 1]), order=order) + surfs[-1][:, :, idim] = geo_utils.readNValues(f, curSize, "float", binary).reshape( + (sizes[i, 0], sizes[i, 1]), order=order + ) f.close() # Now create a list of spline surface objects: @@ -149,8 +153,7 @@ def _readPlot3D(self, fileName, order='f'): # the parametrization and knot vectors self.nSurf = nSurf for isurf in range(self.nSurf): - self.surfs.append(pySpline.Surface(X=surfs[isurf], ku=4, kv=4, - nCtlu=4, nCtlv=4)) + self.surfs.append(pySpline.Surface(X=surfs[isurf], ku=4, kv=4, nCtlu=4, nCtlv=4)) def _readIges(self, fileName): """Load a Iges file and create the splines to go with each patch @@ -160,34 +163,34 @@ def _readIges(self, fileName): fileName : str Name of file to load. """ - f = open(fileName, 'r') + f = open(fileName, "r") Ifile = [] for line in f: - line = line.replace(';', ',') #This is a bit of a hack... + line = line.replace(";", ",") # This is a bit of a hack... Ifile.append(line) f.close() - start_lines = int((Ifile[-1][1:8])) + start_lines = int((Ifile[-1][1:8])) general_lines = int((Ifile[-1][9:16])) directory_lines = int((Ifile[-1][17:24])) parameter_lines = int((Ifile[-1][25:32])) # Now we know how many lines we have to deal with - dir_offset = start_lines + general_lines + dir_offset = start_lines + general_lines para_offset = dir_offset + directory_lines surf_list = [] # Directory lines is ALWAYS a multiple of 2 - for i in range(directory_lines//2): + for i in range(directory_lines // 2): # 128 is bspline surface type - if int(Ifile[2*i + dir_offset][0:8]) == 128: - start = int(Ifile[2*i + dir_offset][8:16]) - num_lines = int(Ifile[2*i + 1 + dir_offset][24:32]) + if int(Ifile[2 * i + dir_offset][0:8]) == 128: + start = int(Ifile[2 * i + dir_offset][8:16]) + num_lines = int(Ifile[2 * i + 1 + dir_offset][24:32]) surf_list.append([start, num_lines]) self.nSurf = len(surf_list) - print('Found %d surfaces in Iges File.'%(self.nSurf)) + print("Found %d surfaces in Iges File." % (self.nSurf)) self.surfs = [] @@ -195,43 +198,45 @@ def _readIges(self, fileName): data = [] # Create a list of all data # -1 is for conversion from 1 based (iges) to python - para_offset = surf_list[isurf][0]+dir_offset+directory_lines-1 + para_offset = surf_list[isurf][0] + dir_offset + directory_lines - 1 for i in range(surf_list[isurf][1]): - aux = Ifile[i+para_offset][0:69].split(',') - for j in range(len(aux)-1): + aux = Ifile[i + para_offset][0:69].split(",") + for j in range(len(aux) - 1): data.append(float(aux[j])) # Now we extract what we need - Nctlu = int(data[1]+1) - Nctlv = int(data[2]+1) - ku = int(data[3]+1) - kv = int(data[4]+1) + Nctlu = int(data[1] + 1) + Nctlv = int(data[2] + 1) + ku = int(data[3] + 1) + kv = int(data[4] + 1) counter = 10 - tu = data[counter:counter+Nctlu+ku] - counter += (Nctlu + ku) + tu = data[counter : counter + Nctlu + ku] + counter += Nctlu + ku - tv = data[counter:counter+Nctlv+kv] - counter += (Nctlv + kv) + tv = data[counter : counter + Nctlv + kv] + counter += Nctlv + kv - weights = data[counter:counter+Nctlu*Nctlv] + weights = data[counter : counter + Nctlu * Nctlv] weights = numpy.array(weights) if weights.all() != 1: - print('WARNING: Not all weight in B-spline surface are\ - 1. A NURBS surface CANNOT be replicated exactly') - counter += Nctlu*Nctlv + print( + "WARNING: Not all weight in B-spline surface are\ + 1. A NURBS surface CANNOT be replicated exactly" + ) + counter += Nctlu * Nctlv coef = numpy.zeros([Nctlu, Nctlv, 3]) for j in range(Nctlv): for i in range(Nctlu): - coef[i, j, :] = data[counter:counter +3] + coef[i, j, :] = data[counter : counter + 3] counter += 3 # Last we need the ranges prange = numpy.zeros(4) - prange[0] = data[counter ] + prange[0] = data[counter] prange[1] = data[counter + 1] prange[2] = data[counter + 2] prange[3] = data[counter + 3] @@ -245,8 +250,7 @@ def _readIges(self, fileName): if not tv[-1] == 1.0: tv /= tv[-1] - self.surfs.append(pySpline.Surface( - ku=ku, kv=kv, tu=tu, tv=tv, coef=coef)) + self.surfs.append(pySpline.Surface(ku=ku, kv=kv, tu=tu, tv=tv, coef=coef)) # Generate dummy data for connectivity to work u = numpy.linspace(0, 1, 3) @@ -259,16 +263,37 @@ def _readIges(self, fileName): return - def _init_lifting_surface(self, xsections, X=None, x=None, y=None, z=None, - rot=None, rotX=None, rotY=None, rotZ=None, - scale=None, offset=None, nCtl=None, kSpan=3, - teHeight=None, teHeightScaled=None, - thickness=None, bluntTe=False, roundedTe=False, - bluntTaperRange=0.1, - squareTeTip=True, teScale=0.75, tip='rounded', - tipScale=0.25, leOffset=.001, teOffset=.001, - spanTang=0.5, upTang=0.5): - """ Create a lifting surface by distributing the cross + def _init_lifting_surface( + self, + xsections, + X=None, + x=None, + y=None, + z=None, + rot=None, + rotX=None, + rotY=None, + rotZ=None, + scale=None, + offset=None, + nCtl=None, + kSpan=3, + teHeight=None, + teHeightScaled=None, + thickness=None, + bluntTe=False, + roundedTe=False, + bluntTaperRange=0.1, + squareTeTip=True, + teScale=0.75, + tip="rounded", + tipScale=0.25, + leOffset=0.001, + teOffset=0.001, + spanTang=0.5, + upTang=0.5, + ): + """Create a lifting surface by distributing the cross sections. See pyGeo module documentation for information on the most commonly used options.""" @@ -303,19 +328,21 @@ def _init_lifting_surface(self, xsections, X=None, x=None, y=None, z=None, if bluntTe: if teHeight is None and teHeightScaled is None: - raise Error('teHeight OR teHeightScaled \ - must be supplied for bluntTe option') + raise Error( + "teHeight OR teHeightScaled \ + must be supplied for bluntTe option" + ) if teHeight: teHeight = numpy.atleast_1d(teHeight) if len(teHeight) == 1: - teHeight = numpy.ones(N)*teHeight + teHeight = numpy.ones(N) * teHeight teHeight /= scale if teHeightScaled: teHeight = numpy.atleast_1d(teHeightScaled) if len(teHeight) == 1: - teHeight = numpy.ones(N)*teHeight + teHeight = numpy.ones(N) * teHeight else: teHeight = [None for i in range(N)] @@ -324,9 +351,9 @@ def _init_lifting_surface(self, xsections, X=None, x=None, y=None, z=None, knots = [] for i in range(len(xsections)): if xsections[i] is not None: - x, y = geo_utils.readAirfoilFile(xsections[i], bluntTe, - bluntThickness=teHeight[i], - bluntTaperRange=bluntTaperRange) + x, y = geo_utils.readAirfoilFile( + xsections[i], bluntTe, bluntThickness=teHeight[i], bluntTaperRange=bluntTaperRange + ) weights = numpy.ones(len(x)) weights[0] = -1 weights[-1] = -1 @@ -349,10 +376,10 @@ def _init_lifting_surface(self, xsections, X=None, x=None, y=None, z=None, curves[i].recompute(100, computeKnots=False) # If we want a pinched tip will will zero everything here. - if tip == 'pinched': - # Just zero out the last section in y + if tip == "pinched": + # Just zero out the last section in y if curves[-1] is not None: - print('zeroing tip') + print("zeroing tip") curves[-1].coef[:, 1] = 0 else: @@ -371,7 +398,7 @@ def _init_lifting_surface(self, xsections, X=None, x=None, y=None, z=None, if curves[i] is not None: knots = origKnots[i] # Search for all indices - indices = numpy.searchsorted(baseKnots, knots, side='left') + indices = numpy.searchsorted(baseKnots, knots, side="left") toInsert = [] # Now go over the indices and see if we need to add @@ -393,7 +420,7 @@ def _init_lifting_surface(self, xsections, X=None, x=None, y=None, z=None, while i < len(baseKnots): curKnot = baseKnots[i] j = 1 - while i+j Copying Topology') + print(" -> Copying Topology") origTopo = copy.deepcopy(self.topo) - print(' -> Creating global numbering') + print(" -> Creating global numbering") sizes = [] for isurf in range(self.nSurf): sizes.append([self.surfs[isurf].Nu, self.surfs[isurf].Nv]) @@ -763,12 +774,10 @@ def fitGlobal(self): # Get the Global number of the original data origTopo.calcGlobalNumbering(sizes) N = origTopo.nGlobal - print(' -> Creating global point list') + print(" -> Creating global point list") pts = numpy.zeros((N, 3)) for ii in range(N): - pts[ii] = self.surfs[ - origTopo.gIndex[ii][0][0]].X[origTopo.gIndex[ii][0][1], - origTopo.gIndex[ii][0][2]] + pts[ii] = self.surfs[origTopo.gIndex[ii][0][0]].X[origTopo.gIndex[ii][0][1], origTopo.gIndex[ii][0][2]] # Get the maximum k (ku, kv for each surf) kmax = 2 @@ -778,10 +787,10 @@ def fitGlobal(self): if self.surfs[isurf].kv > kmax: kmax = self.surfs[isurf].kv - nnz = N*kmax*kmax + nnz = N * kmax * kmax vals = numpy.zeros(nnz) rowPtr = [0] - colInd = numpy.zeros(nnz, 'intc') + colInd = numpy.zeros(nnz, "intc") for ii in range(N): isurf = origTopo.gIndex[ii][0][0] @@ -791,34 +800,33 @@ def fitGlobal(self): u = self.surfs[isurf].U[i, j] v = self.surfs[isurf].V[i, j] - vals, colInd = self.surfs[isurf].getBasisPt( - u, v, vals, rowPtr[ii], colInd, self.topo.lIndex[isurf]) + vals, colInd = self.surfs[isurf].getBasisPt(u, v, vals, rowPtr[ii], colInd, self.topo.lIndex[isurf]) - kinc = self.surfs[isurf].ku*self.surfs[isurf].kv + kinc = self.surfs[isurf].ku * self.surfs[isurf].kv rowPtr.append(rowPtr[-1] + kinc) # Now we can crop out any additional values in col_ptr and vals - vals = vals[:rowPtr[-1]] - colInd = colInd[:rowPtr[-1]] + vals = vals[: rowPtr[-1]] + colInd = colInd[: rowPtr[-1]] # Now make a sparse matrix NN = sparse.csr_matrix((vals, colInd, rowPtr)) - print(' -> Multiplying N^T * N') + print(" -> Multiplying N^T * N") NNT = NN.T - NTN = NNT*NN - print(' -> Factorizing...') + NTN = NNT * NN + print(" -> Factorizing...") solve = factorized(NTN) - print(' -> Back Solving...') + print(" -> Back Solving...") self.coef = numpy.zeros((nCtl, 3)) for idim in range(3): - self.coef[:, idim] = solve(NNT*pts[:, idim]) + self.coef[:, idim] = solve(NNT * pts[:, idim]) - print(' -> Setting Surface Coefficients...') + print(" -> Setting Surface Coefficients...") self._updateSurfaceCoef() -# ---------------------------------------------------------------------- -# Topology Information Functions -# ---------------------------------------------------------------------- + # ---------------------------------------------------------------------- + # Topology Information Functions + # ---------------------------------------------------------------------- def doConnectivity(self, fileName=None, nodeTol=1e-4, edgeTol=1e-4): """ @@ -834,11 +842,11 @@ def doConnectivity(self, fileName=None, nodeTol=1e-4, edgeTol=1e-4): The tolerance for identical nodes edgeTol : float The tolerance for midpoint of edges being identical - """ + """ if fileName is not None and os.path.isfile(fileName): - print('Reading Connectivity File: %s'%(fileName)) + print("Reading Connectivity File: %s" % (fileName)) self.topo = geo_utils.SurfaceTopology(fileName=fileName) - if self.initType != 'iges': + if self.initType != "iges": self._propagateKnotVectors() sizes = [] @@ -852,13 +860,13 @@ def doConnectivity(self, fileName=None, nodeTol=1e-4, edgeTol=1e-4): for isurf in range(self.nSurf): sizes.append([self.surfs[isurf].nCtlu, self.surfs[isurf].nCtlv]) self.topo.calcGlobalNumbering(sizes) - if self.initType != 'iges': + if self.initType != "iges": self._propagateKnotVectors() if fileName is not None: - print('Writing Connectivity File: %s'%(fileName)) + print("Writing Connectivity File: %s" % (fileName)) self.topo.writeConnectivity(fileName) - if self.initType == 'iges': + if self.initType == "iges": self.setSurfaceCoef() def _calcConnectivity(self, nodeTol, edgeTol): @@ -883,8 +891,7 @@ def _calcConnectivity(self, nodeTol, edgeTol): beg, mid, end = self.surfs[isurf].getOrigValuesEdge(3) coords[isurf][7] = mid - self.topo = geo_utils.SurfaceTopology(coords=coords, nodeTol=nodeTol, - edgeTol=edgeTol) + self.topo = geo_utils.SurfaceTopology(coords=coords, nodeTol=nodeTol, edgeTol=edgeTol) def printConnectivity(self): """ @@ -930,8 +937,7 @@ def _propagateKnotVectors(self): flip = [] for isurf in range(self.nSurf): for iedge in range(4): - if self.topo.edges[ - self.topo.edgeLink[isurf][iedge]].dg == idg: + if self.topo.edges[self.topo.edgeLink[isurf][iedge]].dg == idg: if self.topo.edgeDir[isurf][iedge] == -1: flip.append(True) else: @@ -943,7 +949,7 @@ def _propagateKnotVectors(self): knotVec = self.surfs[isurf].tv if flip[-1]: - knotVectors.append((1-knotVec)[::-1].copy()) + knotVectors.append((1 - knotVec)[::-1].copy()) else: knotVectors.append(knotVec) @@ -951,13 +957,12 @@ def _propagateKnotVectors(self): # Now blend all the knot vectors newKnotVec = geo_utils.blendKnotVectors(knotVectors, False) - newKnotVecFlip = (1-newKnotVec)[::-1] + newKnotVecFlip = (1 - newKnotVec)[::-1] counter = 0 for isurf in range(self.nSurf): for iedge in range(4): - if self.topo.edges[ - self.topo.edgeLink[isurf][iedge]].dg == idg: + if self.topo.edges[self.topo.edgeLink[isurf][iedge]].dg == idg: if iedge in [0, 1]: if flip[counter]: self.surfs[isurf].tu = newKnotVecFlip.copy() @@ -971,13 +976,21 @@ def _propagateKnotVectors(self): self.surfs[isurf].tv = newKnotVec.copy() counter += 1 -# ---------------------------------------------------------------------- -# Surface Writing Output Functions -# ---------------------------------------------------------------------- - - def writeTecplot(self, fileName, orig=False, surfs=True, coef=True, - directions=False, surfLabels=False, edgeLabels=False, - nodeLabels=False): + # ---------------------------------------------------------------------- + # Surface Writing Output Functions + # ---------------------------------------------------------------------- + + def writeTecplot( + self, + fileName, + orig=False, + surfs=True, + coef=True, + directions=False, + surfLabels=False, + edgeLabels=False, + nodeLabels=False, + ): """Write the pyGeo Object to Tecplot dat file @@ -997,7 +1010,7 @@ def writeTecplot(self, fileName, orig=False, surfs=True, coef=True, Flag to write file with edge labels nodeLabels : bool Falg to write file with node labels - """ + """ f = pySpline.openTecplot(fileName, 3) @@ -1005,20 +1018,17 @@ def writeTecplot(self, fileName, orig=False, surfs=True, coef=True, if surfs: for isurf in range(self.nSurf): self.surfs[isurf].computeData() - pySpline.writeTecplot2D(f, 'interpolated', - self.surfs[isurf].data) + pySpline.writeTecplot2D(f, "interpolated", self.surfs[isurf].data) # Write out the Control Points if coef: for isurf in range(self.nSurf): - pySpline.writeTecplot2D(f, 'control_pts', - self.surfs[isurf].coef) + pySpline.writeTecplot2D(f, "control_pts", self.surfs[isurf].coef) # Write out the Original Data if orig: for isurf in range(self.nSurf): - pySpline.writeTecplot2D(f, 'control_pts', - self.surfs[isurf].X) + pySpline.writeTecplot2D(f, "control_pts", self.surfs[isurf].X) # Write out The Surface Directions if directions: @@ -1031,29 +1041,34 @@ def writeTecplot(self, fileName, orig=False, surfs=True, coef=True, if surfLabels: # Split the filename off - labelFilename = dirName+'./'+fileBaseName+'.surf_labels.dat' - f2 = open(labelFilename, 'w') + labelFilename = dirName + "./" + fileBaseName + ".surf_labels.dat" + f2 = open(labelFilename, "w") for isurf in range(self.nSurf): - midu = numpy.floor(self.surfs[isurf].nCtlu/2) - midv = numpy.floor(self.surfs[isurf].nCtlv/2) - textString = 'TEXT CS=GRID3D, X=%f, Y=%f, Z=%f, ZN=%d, \ - T=\"S%d\"\n'% (self.surfs[isurf].coef[midu, midv, 0], - self.surfs[isurf].coef[midu, midv, 1], - self.surfs[isurf].coef[midu, midv, 2], - isurf+1, isurf) - f2.write('%s'%(textString)) + midu = numpy.floor(self.surfs[isurf].nCtlu / 2) + midv = numpy.floor(self.surfs[isurf].nCtlv / 2) + textString = ( + 'TEXT CS=GRID3D, X=%f, Y=%f, Z=%f, ZN=%d, \ + T="S%d"\n' + % ( + self.surfs[isurf].coef[midu, midv, 0], + self.surfs[isurf].coef[midu, midv, 1], + self.surfs[isurf].coef[midu, midv, 2], + isurf + 1, + isurf, + ) + ) + f2.write("%s" % (textString)) f2.close() if edgeLabels: # Split the filename off - labelFilename = dirName+'./'+fileBaseName+'edge_labels.dat' - f2 = open(labelFilename, 'w') + labelFilename = dirName + "./" + fileBaseName + "edge_labels.dat" + f2 = open(labelFilename, "w") for iedge in range(self.topo.nEdge): - surfaces = self.topo.getSurfaceFromEdge(iedge) + surfaces = self.topo.getSurfaceFromEdge(iedge) pt = self.surfs[surfaces[0][0]].edgeCurves[surfaces[0][1]](0.5) - textString = 'TEXT CS=GRID3D X=%f, Y=%f, Z=%f, T=\"E%d\"\n'% ( - pt[0], pt[1], pt[2], iedge) - f2.write('%s'%(textString)) + textString = 'TEXT CS=GRID3D X=%f, Y=%f, Z=%f, T="E%d"\n' % (pt[0], pt[1], pt[2], iedge) + f2.write("%s" % (textString)) f2.close() if nodeLabels: @@ -1078,13 +1093,17 @@ def writeTecplot(self, fileName, orig=False, surfs=True, coef=True, nodeCoord[i] = coordinate # Split the filename off - labelFilename = dirName+'./'+fileBaseName+'.node_labels.dat' - f2 = open(labelFilename, 'w') + labelFilename = dirName + "./" + fileBaseName + ".node_labels.dat" + f2 = open(labelFilename, "w") for i in range(nNodes): - textString = 'TEXT CS=GRID3D, X=%f, Y=%f, Z=%f, T=\"n%d\"\n'% ( - nodeCoord[i][0], nodeCoord[i][1], nodeCoord[i][2], i) - f2.write('%s'%(textString)) + textString = 'TEXT CS=GRID3D, X=%f, Y=%f, Z=%f, T="n%d"\n' % ( + nodeCoord[i][0], + nodeCoord[i][1], + nodeCoord[i][2], + i, + ) + f2.write("%s" % (textString)) f2.close() # Close out the file @@ -1098,32 +1117,30 @@ def writeIGES(self, fileName): ---------- fileName : str File name of iges file. Should have .igs extension. - """ - f = open(fileName, 'w') + """ + f = open(fileName, "w") - #Note: Eventually we may want to put the CORRECT Data here - f.write(' S 1\n') - f.write('1H,,1H;,7H128-000,11H128-000.IGS,9H{unknown},9H{unknown},16,6,15,13,15, G 1\n') - f.write('7H128-000,1.,6,1HM,8,0.016,15H19970830.165254, 0.0001,0., G 2\n') - f.write('21Hdennette@wiz-worx.com,23HLegacy PDD AP Committee,11,3, G 3\n') - f.write('13H920717.080000,23HMIL-PRF-28000B0,CLASS 1; G 4\n') + # Note: Eventually we may want to put the CORRECT Data here + f.write(" S 1\n") + f.write("1H,,1H;,7H128-000,11H128-000.IGS,9H{unknown},9H{unknown},16,6,15,13,15, G 1\n") + f.write("7H128-000,1.,6,1HM,8,0.016,15H19970830.165254, 0.0001,0., G 2\n") + f.write("21Hdennette@wiz-worx.com,23HLegacy PDD AP Committee,11,3, G 3\n") + f.write("13H920717.080000,23HMIL-PRF-28000B0,CLASS 1; G 4\n") Dcount = 1 Pcount = 1 for isurf in range(self.nSurf): - Pcount, Dcount = self.surfs[isurf].writeIGES_directory( \ - f, Dcount, Pcount) + Pcount, Dcount = self.surfs[isurf].writeIGES_directory(f, Dcount, Pcount) - Pcount = 1 + Pcount = 1 counter = 1 for isurf in range(self.nSurf): - Pcount, counter = self.surfs[isurf].writeIGES_parameters(\ - f, Pcount, counter) + Pcount, counter = self.surfs[isurf].writeIGES_parameters(f, Pcount, counter) # Write the terminate statement - f.write('S%7dG%7dD%7dP%7d%40sT%6s1\n'%(1, 4, Dcount-1, counter-1, ' ', ' ')) + f.write("S%7dG%7dD%7dP%7d%40sT%6s1\n" % (1, 4, Dcount - 1, counter - 1, " ", " ")) f.close() def writeTin(self, fileName): @@ -1134,46 +1151,44 @@ def writeTin(self, fileName): ---------- fileName : str File name of tin file. Should have .tin extension. - """ - f = open(fileName, 'w') + """ + f = open(fileName, "w") import datetime # Write the required header info here: - f.write('// tetin file version 1.1\n') - f.write('// written by pyLayoutGeo - on %s\n'%(datetime.datetime.now())) - f.write('set_triangulation_tolerance 0.001\n') + f.write("// tetin file version 1.1\n") + f.write("// written by pyLayoutGeo - on %s\n" % (datetime.datetime.now())) + f.write("set_triangulation_tolerance 0.001\n") # Now loop over the componets and each will write the info it # has to the .tin file: for i in range(self.nSurf): - if self.surfs[i].name==None: - name = 'surface_%d'%i + if self.surfs[i].name == None: + name = "surface_%d" % i else: name = self.surfs[i].name - str = 'define_surface name surf.%d family %s tetra_size %f\n'%( - i, name, 1.0) + str = "define_surface name surf.%d family %s tetra_size %f\n" % (i, name, 1.0) f.write(str) self.surfs[i].writeTin(f) # Write the closing info: - f.write('affix 0\n') - f.write('define_model 1e+10 reference_size 1\n') - f.write('return\n') + f.write("affix 0\n") + f.write("define_model 1e+10 reference_size 1\n") + f.write("return\n") f.close() - -# ---------------------------------------------------------------------- -# Update and Derivative Functions -# ---------------------------------------------------------------------- + # ---------------------------------------------------------------------- + # Update and Derivative Functions + # ---------------------------------------------------------------------- def _updateSurfaceCoef(self): """Copy the pyGeo list of control points back to the surfaces""" for ii in range(len(self.coef)): for jj in range(len(self.topo.gIndex[ii])): isurf = self.topo.gIndex[ii][jj][0] - i = self.topo.gIndex[ii][jj][1] - j = self.topo.gIndex[ii][jj][2] - self.surfs[isurf].coef[i, j] = self.coef[ii].astype('d') + i = self.topo.gIndex[ii][jj][1] + j = self.topo.gIndex[ii][jj][2] + self.surfs[isurf].coef[i, j] = self.coef[ii].astype("d") for isurf in range(self.nSurf): self.surfs[isurf].setEdgeCurves() @@ -1202,7 +1217,7 @@ def getBounds(self, surfs=None): Lower corner of the bounding box xMax : array of length 3 Upper corner of the bounding box - """ + """ if surfs == None: surfs = numpy.arange(self.nSurf) @@ -1254,9 +1269,9 @@ def projectCurve(self, curve, surfs=None, *args, **kwargs): if surfs == None: surfs = numpy.arange(self.nSurf) - temp = numpy.zeros((len(surfs), 4)) - result = numpy.zeros((len(surfs), 4)) - patchID = numpy.zeros(len(surfs), 'intc') + temp = numpy.zeros((len(surfs), 4)) + result = numpy.zeros((len(surfs), 4)) + patchID = numpy.zeros(len(surfs), "intc") for i in range(len(surfs)): isurf = surfs[i] @@ -1273,7 +1288,7 @@ def projectCurve(self, curve, surfs=None, *args, **kwargs): return result, patchID def projectPoints(self, points, surfs=None, *args, **kwargs): - """ Project on or more points onto the nearest surface. + """Project on or more points onto the nearest surface. Parameters ---------- @@ -1293,23 +1308,22 @@ def projectPoints(self, points, surfs=None, *args, **kwargs): v parameter values of closest point PID : int or int array Patch index corresponding to the u,v parameter values - """ + """ if surfs == None: surfs = numpy.arange(self.nSurf) N = len(points) - U = numpy.zeros((N, len(surfs))) - V = numpy.zeros((N, len(surfs))) - D = numpy.zeros((N, len(surfs), 3)) + U = numpy.zeros((N, len(surfs))) + V = numpy.zeros((N, len(surfs))) + D = numpy.zeros((N, len(surfs), 3)) for i in range(len(surfs)): isurf = surfs[i] - U[:, i], V[:, i], D[:, i, :] = self.surfs[isurf].projectPoint( - points, *args, **kwargs) + U[:, i], V[:, i], D[:, i, :] = self.surfs[isurf].projectPoint(points, *args, **kwargs) u = numpy.zeros(N) v = numpy.zeros(N) - patchID = numpy.zeros(N, 'intc') + patchID = numpy.zeros(N, "intc") # Now post-process to get the lowest one for i in range(N): diff --git a/pygeo/pyNetwork.py b/pygeo/pyNetwork.py index c55e4545..f0884996 100644 --- a/pygeo/pyNetwork.py +++ b/pygeo/pyNetwork.py @@ -7,7 +7,7 @@ from .geo_utils import CurveTopology -class pyNetwork(): +class pyNetwork: """ A class for manipulating a collection of curve objects. @@ -20,7 +20,7 @@ class pyNetwork(): ---------- curves : list of pySpline.Curve objects Individual curves to form the network. - """ + """ def __init__(self, curves): self.curves = curves @@ -51,12 +51,11 @@ def _doConnectivity(self): ii = self.topo.gIndex[i][0][1] self.coef[i] = self.curves[icurve].coef[ii] -# ---------------------------------------------------------------------- -# Curve Writing Output Functions -# ---------------------------------------------------------------------- + # ---------------------------------------------------------------------- + # Curve Writing Output Functions + # ---------------------------------------------------------------------- - def writeTecplot(self, fileName, orig=False, curves=True, coef=True, - curveLabels=False, nodeLabels=False): + def writeTecplot(self, fileName, orig=False, curves=True, coef=True, curveLabels=False, nodeLabels=False): """Write the pyNetwork Object to Tecplot .dat file Parameters @@ -71,22 +70,19 @@ def writeTecplot(self, fileName, orig=False, curves=True, coef=True, Flag to write a separate label file with the curve indices nodeLabels : bool Flag to write a separate node label file with the node indices - """ + """ f = pySpline.openTecplot(fileName, 3) if curves: for icurve in range(self.nCurve): self.curves[icurve].computeData() - pySpline.writeTecplot1D(f, 'interpolated', - self.curves[icurve].data) + pySpline.writeTecplot1D(f, "interpolated", self.curves[icurve].data) if coef: for icurve in range(self.nCurve): - pySpline.writeTecplot1D(f, 'coef', - self.curves[icurve].coef) + pySpline.writeTecplot1D(f, "coef", self.curves[icurve].coef) if orig: for icurve in range(self.nCurve): - pySpline.writeTecplot1D(f, 'coef', - self.curves[icurve].X) + pySpline.writeTecplot1D(f, "coef", self.curves[icurve].X) # Write out The Curve and Node Labels dirName, fileName = os.path.split(fileName) @@ -94,15 +90,18 @@ def writeTecplot(self, fileName, orig=False, curves=True, coef=True, if curveLabels: # Split the filename off - labelFilename = dirName+'./'+fileBaseName+'.curve_labels.dat' - f2 = open(labelFilename, 'w') + labelFilename = dirName + "./" + fileBaseName + ".curve_labels.dat" + f2 = open(labelFilename, "w") for icurve in range(self.nCurve): - mid = numpy.floor(self.curves[icurve].nCtl/2) - textString = 'TEXT CS=GRID3D, X=%f,Y=%f,Z=%f,ZN=%d,T=\"S%d\"\n' % ( + mid = numpy.floor(self.curves[icurve].nCtl / 2) + textString = 'TEXT CS=GRID3D, X=%f,Y=%f,Z=%f,ZN=%d,T="S%d"\n' % ( self.curves[icurve].coef[mid, 0], self.curves[icurve].coef[mid, 1], - self.curves[icurve].coef[mid, 2], icurve+1, icurve) - f2.write('%s' % (textString)) + self.curves[icurve].coef[mid, 2], + icurve + 1, + icurve, + ) + f2.write("%s" % (textString)) f2.close() if nodeLabels: @@ -127,13 +126,17 @@ def writeTecplot(self, fileName, orig=False, curves=True, coef=True, nodeCoord[i] = coordinate # Split the filename off - labelFilename = dirName+'./'+fileBaseName+'.node_labels.dat' - f2 = open(labelFilename, 'w') + labelFilename = dirName + "./" + fileBaseName + ".node_labels.dat" + f2 = open(labelFilename, "w") for i in range(nNodes): - textString = 'TEXT CS=GRID3D, X=%f, Y=%f, Z=%f, T=\"n%d\"\n' % ( - nodeCoord[i][0], nodeCoord[i][1], nodeCoord[i][2], i) - f2.write('%s' % (textString)) + textString = 'TEXT CS=GRID3D, X=%f, Y=%f, Z=%f, T="n%d"\n' % ( + nodeCoord[i][0], + nodeCoord[i][1], + nodeCoord[i][2], + i, + ) + f2.write("%s" % (textString)) f2.close() pySpline.closeTecplot(f) @@ -161,7 +164,7 @@ def getBounds(self, curves=None): Lower corner of the bounding box xMax : array of length 3 Upper corner of the bounding box - """ + """ if curves is None: curves = numpy.arange(self.nCurve) @@ -186,7 +189,7 @@ def getBounds(self, curves=None): return Xmin0, Xmax0 def projectRays(self, points, axis, curves=None, raySize=1.5, **kwargs): - """ Given a set of points and a vector defining a direction, + """Given a set of points and a vector defining a direction, i.e. a ray, determine the minimum distance between these rays and any of the curves this object has. @@ -228,9 +231,9 @@ def projectRays(self, points, axis, curves=None, raySize=1.5, **kwargs): # that we know how large to make the line representing the ray. curveID0, s0 = self.projectPoints(points, curves=curves, **kwargs) - D0 = numpy.zeros((len(s0), 3), 'd') + D0 = numpy.zeros((len(s0), 3), "d") for i in range(len(s0)): - D0[i, :] = self.curves[curveID0[i]](s0[i])-points[i] + D0[i, :] = self.curves[curveID0[i]](s0[i]) - points[i] if curves == None: curves = numpy.arange(self.nCurve) @@ -244,19 +247,21 @@ def projectRays(self, points, axis, curves=None, raySize=1.5, **kwargs): icurve = curves[i] for j in range(N): ray = pySpline.line( - points[j]-axis*raySize*numpy.linalg.norm(D0[j]), - points[j]+axis*raySize*numpy.linalg.norm(D0[j])) + points[j] - axis * raySize * numpy.linalg.norm(D0[j]), + points[j] + axis * raySize * numpy.linalg.norm(D0[j]), + ) - S[j, i], t, D[j, i, :] = self.curves[icurve].projectCurve( - ray, nIter=2000) + S[j, i], t, D[j, i, :] = self.curves[icurve].projectCurve(ray, nIter=2000) if t == 0.0 or t == 1.0: - print('Warning: The link for attached point {:d} was drawn' - 'from the curve to the end of the ray,' - 'indicating that the ray might not have been long' - 'enough to intersect the nearest curve.'.format(j)) + print( + "Warning: The link for attached point {:d} was drawn" + "from the curve to the end of the ray," + "indicating that the ray might not have been long" + "enough to intersect the nearest curve.".format(j) + ) s = numpy.zeros(N) - curveID = numpy.zeros(N, 'intc') + curveID = numpy.zeros(N, "intc") # Now post-process to get the lowest one for i in range(N): @@ -272,7 +277,7 @@ def projectRays(self, points, axis, curves=None, raySize=1.5, **kwargs): return curveID, s def projectPoints(self, points, curves=None, *args, **kwargs): - """ Project one or more points onto the nearest curve. This + """Project one or more points onto the nearest curve. This algorihm isn't exactly efficient: We simply project the nodes on each of the curves and take the lowest one. @@ -293,7 +298,7 @@ def projectPoints(self, points, curves=None, *args, **kwargs): s : float or array The curve parameter on self.curves[curveID] that is cloested to the point(s). - """ + """ if curves is None: curves = numpy.arange(self.nCurve) @@ -303,11 +308,10 @@ def projectPoints(self, points, curves=None, *args, **kwargs): D = numpy.zeros((N, len(curves), 3)) for i in range(len(curves)): icurve = curves[i] - S[:, i], D[:, i, :] = self.curves[icurve].projectPoint( - points, *args, **kwargs) + S[:, i], D[:, i, :] = self.curves[icurve].projectPoint(points, *args, **kwargs) s = numpy.zeros(N) - curveID = numpy.zeros(N, 'intc') + curveID = numpy.zeros(N, "intc") # Now post-process to get the lowest one for i in range(N): diff --git a/setup.py b/setup.py index b92eda63..6401041d 100644 --- a/setup.py +++ b/setup.py @@ -3,15 +3,14 @@ __version__ = re.findall( r"""__version__ = ["']+([0-9\.]*)["']+""", - open('pygeo/__init__.py').read(), + open("pygeo/__init__.py").read(), )[0] -setup(name='pygeo', - version=__version__, - - - description="pyGeo is an object oriented geometry manipulation framework for multidisciplinary design optimization", - long_description="""It provides a free form deformation (FFD) based geometry manipulation object, an interface to NASA's Vehicle Sketch Pad geometry engine, a simple geometric constraint formulation object, and some utility functions for geometry manipulation. +setup( + name="pygeo", + version=__version__, + description="pyGeo is an object oriented geometry manipulation framework for multidisciplinary design optimization", + long_description="""It provides a free form deformation (FFD) based geometry manipulation object, an interface to NASA's Vehicle Sketch Pad geometry engine, a simple geometric constraint formulation object, and some utility functions for geometry manipulation. ![](images/DPW4_FFD-27745.gif) @@ -45,28 +44,17 @@ } """, - long_description_content_type="text/markdown", - keywords='geometry FFD optimization', - author='', - author_email='', - url='https://github.com/mdolab/pygeo', - license='Apache License Version 2.0', - packages=[ - 'pygeo', - ], - package_data={ - 'pygeo': ['*.so'] - }, - install_requires=[ - 'numpy>=1.16', - 'pyspline>=1.1', - 'scipy>=1.2', - 'mpi4py>=3.0' - ], - extras_require = { - 'testing': ["numpy-stl"] - }, - classifiers=[ - "Operating System :: OS Independent", - "Programming Language :: Python"] - ) + long_description_content_type="text/markdown", + keywords="geometry FFD optimization", + author="", + author_email="", + url="https://github.com/mdolab/pygeo", + license="Apache License Version 2.0", + packages=[ + "pygeo", + ], + package_data={"pygeo": ["*.so"]}, + install_requires=["numpy>=1.16", "pyspline>=1.1", "scipy>=1.2", "mpi4py>=3.0"], + extras_require={"testing": ["numpy-stl"]}, + classifiers=["Operating System :: OS Independent", "Programming Language :: Python"], +) diff --git a/tests/inputFiles/generateFFD.py b/tests/inputFiles/generateFFD.py index cde1c4a9..a4d90059 100644 --- a/tests/inputFiles/generateFFD.py +++ b/tests/inputFiles/generateFFD.py @@ -1,41 +1,42 @@ import numpy as np import sys -def writeFFDFile(fileName,nBlocks,nx,ny,nz,points): - ''' + +def writeFFDFile(fileName, nBlocks, nx, ny, nz, points): + """ Take in a set of points and write the plot 3dFile - ''' + """ - f = open(fileName,'w') + f = open(fileName, "w") - f.write('%d\n'%nBlocks) + f.write("%d\n" % nBlocks) for i in range(nBlocks): - f.write('%d %d %d '%(nx[i],ny[i],nz[i])) + f.write("%d %d %d " % (nx[i], ny[i], nz[i])) # end - f.write('\n') + f.write("\n") for block in range(nBlocks): for k in range(nz[block]): for j in range(ny[block]): for i in range(nx[block]): - f.write('%f '%points[block][i,j,k,0]) + f.write("%f " % points[block][i, j, k, 0]) # end # end # end - f.write('\n') + f.write("\n") for k in range(nz[block]): for j in range(ny[block]): for i in range(nx[block]): - f.write('%f '%points[block][i,j,k,1]) + f.write("%f " % points[block][i, j, k, 1]) # end # end # end - f.write('\n') + f.write("\n") for k in range(nz[block]): for j in range(ny[block]): for i in range(nx[block]): - f.write('%f '%points[block][i,j,k,2]) + f.write("%f " % points[block][i, j, k, 2]) # end # end # end @@ -43,114 +44,116 @@ def writeFFDFile(fileName,nBlocks,nx,ny,nz,points): f.close() return -def returnBlockPoints(corners,nx,ny,nz): - ''' + +def returnBlockPoints(corners, nx, ny, nz): + """ corners needs to be 8 x 3 - ''' - points = np.zeros([nx,ny,nz,3]) + """ + points = np.zeros([nx, ny, nz, 3]) # points 1 - 4 are the iMin face # points 5 - 8 are the iMax face for idim in range(3): - edge1 = np.linspace(corners[0][idim],corners[4][idim],nx) - edge2 = np.linspace(corners[1][idim],corners[5][idim],nx) - edge3 = np.linspace(corners[2][idim],corners[6][idim],nx) - edge4 = np.linspace(corners[3][idim],corners[7][idim],nx) + edge1 = np.linspace(corners[0][idim], corners[4][idim], nx) + edge2 = np.linspace(corners[1][idim], corners[5][idim], nx) + edge3 = np.linspace(corners[2][idim], corners[6][idim], nx) + edge4 = np.linspace(corners[3][idim], corners[7][idim], nx) for i in range(nx): - edge5 = np.linspace(edge1[i],edge3[i],ny) - edge6 = np.linspace(edge2[i],edge4[i],ny) + edge5 = np.linspace(edge1[i], edge3[i], ny) + edge6 = np.linspace(edge2[i], edge4[i], ny) for j in range(ny): - edge7 = np.linspace(edge5[j],edge6[j],nz) - points[i,j,:,idim] = edge7 + edge7 = np.linspace(edge5[j], edge6[j], nz) + points[i, j, :, idim] = edge7 # end # end # end - + return points + nBlocks = 2 -nx = [2,2]#4 -ny = [2,2] -nz = [2,2] - -corners = np.zeros([nBlocks,8,3]) - -corners[0,0,:] = [-1.,-1.,-1.] -corners[0,1,:] = [-1.,-1.,1.] -corners[0,2,:] = [-1.,1.,-1.] -corners[0,3,:] = [-1.,1.,1] -corners[0,4,:] = [1.,-1.,-1.] -corners[0,5,:] = [1.,-1.,1.] -corners[0,6,:] = [1.,1.,-1.] -corners[0,7,:] = [1.,1.,1.] - -corners[1,0,:] = [1.,-1.,-1.] -corners[1,1,:] = [1.,-1.,1.] -corners[1,2,:] = [1.,1.,-1.] -corners[1,3,:] = [1.,1.,1.] -corners[1,4,:] = [2.,-1.,-1.] -corners[1,5,:] = [2.,-1.,1.] -corners[1,6,:] = [2.,1.,-1.] -corners[1,7,:] = [2.,1.,1.] +nx = [2, 2] # 4 +ny = [2, 2] +nz = [2, 2] + +corners = np.zeros([nBlocks, 8, 3]) + +corners[0, 0, :] = [-1.0, -1.0, -1.0] +corners[0, 1, :] = [-1.0, -1.0, 1.0] +corners[0, 2, :] = [-1.0, 1.0, -1.0] +corners[0, 3, :] = [-1.0, 1.0, 1] +corners[0, 4, :] = [1.0, -1.0, -1.0] +corners[0, 5, :] = [1.0, -1.0, 1.0] +corners[0, 6, :] = [1.0, 1.0, -1.0] +corners[0, 7, :] = [1.0, 1.0, 1.0] + +corners[1, 0, :] = [1.0, -1.0, -1.0] +corners[1, 1, :] = [1.0, -1.0, 1.0] +corners[1, 2, :] = [1.0, 1.0, -1.0] +corners[1, 3, :] = [1.0, 1.0, 1.0] +corners[1, 4, :] = [2.0, -1.0, -1.0] +corners[1, 5, :] = [2.0, -1.0, 1.0] +corners[1, 6, :] = [2.0, 1.0, -1.0] +corners[1, 7, :] = [2.0, 1.0, 1.0] points = [] for i in range(nBlocks): - points.append(returnBlockPoints(corners[i],nx[i],ny[i],nz[i])) + points.append(returnBlockPoints(corners[i], nx[i], ny[i], nz[i])) # end -fileName = 'outerBoxFFD.xyz' -writeFFDFile(fileName,nBlocks,nx,ny,nz,points) +fileName = "outerBoxFFD.xyz" +writeFFDFile(fileName, nBlocks, nx, ny, nz, points) -nBlocks = 1#3 +nBlocks = 1 # 3 nx = [5] ny = [5] nz = [5] -corners = np.zeros([nBlocks,8,3]) +corners = np.zeros([nBlocks, 8, 3]) -corners[0,0,:] = [-0.5,-0.5,-0.5] -corners[0,1,:] = [-0.5, 0.5,-0.5] -corners[0,2,:] = [-0.5,-0.5, 0.5] -corners[0,3,:] = [-0.5, 0.5, 0.5] -corners[0,4,:] = [ 0.5,-0.5,-0.5] -corners[0,5,:] = [ 0.5, 0.5,-0.5] -corners[0,6,:] = [ 0.5,-0.5, 0.5] -corners[0,7,:] = [ 0.5, 0.5, 0.5] +corners[0, 0, :] = [-0.5, -0.5, -0.5] +corners[0, 1, :] = [-0.5, 0.5, -0.5] +corners[0, 2, :] = [-0.5, -0.5, 0.5] +corners[0, 3, :] = [-0.5, 0.5, 0.5] +corners[0, 4, :] = [0.5, -0.5, -0.5] +corners[0, 5, :] = [0.5, 0.5, -0.5] +corners[0, 6, :] = [0.5, -0.5, 0.5] +corners[0, 7, :] = [0.5, 0.5, 0.5] points = [] for block in range(nBlocks): - points.append(returnBlockPoints(corners[block],nx[block],ny[block],nz[block])) - + points.append(returnBlockPoints(corners[block], nx[block], ny[block], nz[block])) + -fileName = 'innerFFD.xyz' -writeFFDFile(fileName,nBlocks,nx,ny,nz,points) -nBlocks = 1#3 +fileName = "innerFFD.xyz" +writeFFDFile(fileName, nBlocks, nx, ny, nz, points) +nBlocks = 1 # 3 nx = [2] ny = [2] nz = [2] -corners = np.zeros([nBlocks,8,3]) +corners = np.zeros([nBlocks, 8, 3]) -corners[0,0,:] = [-0.5,-0.5,-0.5] -corners[0,1,:] = [-0.5, 0.5,-0.5] -corners[0,2,:] = [-0.5,-0.5, 0.5] -corners[0,3,:] = [-0.5, 0.5, 0.5] -corners[0,4,:] = [ 0.5,-0.5,-0.5] -corners[0,5,:] = [ 0.5, 0.5,-0.5] -corners[0,6,:] = [ 0.5,-0.5, 0.5] -corners[0,7,:] = [ 0.5, 0.5, 0.5] +corners[0, 0, :] = [-0.5, -0.5, -0.5] +corners[0, 1, :] = [-0.5, 0.5, -0.5] +corners[0, 2, :] = [-0.5, -0.5, 0.5] +corners[0, 3, :] = [-0.5, 0.5, 0.5] +corners[0, 4, :] = [0.5, -0.5, -0.5] +corners[0, 5, :] = [0.5, 0.5, -0.5] +corners[0, 6, :] = [0.5, -0.5, 0.5] +corners[0, 7, :] = [0.5, 0.5, 0.5] points = [] for block in range(nBlocks): - points.append(returnBlockPoints(corners[block],nx[block],ny[block],nz[block])) - + points.append(returnBlockPoints(corners[block], nx[block], ny[block], nz[block])) + -fileName = 'simpleInnerFFD.xyz' -writeFFDFile(fileName,nBlocks,nx,ny,nz,points) +fileName = "simpleInnerFFD.xyz" +writeFFDFile(fileName, nBlocks, nx, ny, nz, points) diff --git a/tests/inputFiles/generatec172FFD.py b/tests/inputFiles/generatec172FFD.py index 9374c907..e142259b 100644 --- a/tests/inputFiles/generatec172FFD.py +++ b/tests/inputFiles/generatec172FFD.py @@ -9,7 +9,7 @@ # Bounding box for tip airfoil x_tip_range = [-0.05, 1.7] y_tip_range = [-0.25, 0.25] -z_tip = 11/2 +z_tip = 11 / 2 # Number of FFD control points per dimension nX = 4 # streamwise diff --git a/tests/inputFiles/generaterectFFD.py b/tests/inputFiles/generaterectFFD.py index 87465e8f..e2d2d7be 100644 --- a/tests/inputFiles/generaterectFFD.py +++ b/tests/inputFiles/generaterectFFD.py @@ -2,7 +2,7 @@ # rst Dimensions # Bounding box for root airfoil -x_root_range = [-1.0,1.0] +x_root_range = [-1.0, 1.0] y_root_range = [-0.5, 0.5] z_root = 0.0 diff --git a/tests/reg_tests/commonUtils.py b/tests/reg_tests/commonUtils.py index bb83380c..0beb1eb4 100644 --- a/tests/reg_tests/commonUtils.py +++ b/tests/reg_tests/commonUtils.py @@ -5,170 +5,178 @@ from pyspline import Curve - def printHeader(testName): if MPI.COMM_WORLD.rank == 0: - print('+' + '-'*78 + '+') - print('| Test Name: ' + '%-66s'%testName + '|') - print('+' + '-'*78 + '+') + print("+" + "-" * 78 + "+") + print("| Test Name: " + "%-66s" % testName + "|") + print("+" + "-" * 78 + "+") + ################## # DVGeometry Tests ################## + def setupDVGeo(base_path, rotType=None): - #create the Parent FFD - FFDFile = os.path.join(base_path,'../inputFiles/outerBoxFFD.xyz') + # create the Parent FFD + FFDFile = os.path.join(base_path, "../inputFiles/outerBoxFFD.xyz") DVGeo = DVGeometry(FFDFile) # create a reference axis for the parent - axisPoints = [[ -1.0, 0. , 0.],[ 1.5, 0., 0.]] - c1 = Curve(X=axisPoints,k=2) + axisPoints = [[-1.0, 0.0, 0.0], [1.5, 0.0, 0.0]] + c1 = Curve(X=axisPoints, k=2) if rotType is not None: - DVGeo.addRefAxis('mainAxis',curve=c1, axis='y', rotType=rotType) + DVGeo.addRefAxis("mainAxis", curve=c1, axis="y", rotType=rotType) else: - DVGeo.addRefAxis('mainAxis',curve=c1, axis='y') + DVGeo.addRefAxis("mainAxis", curve=c1, axis="y") # create the child FFD - FFDFile = os.path.join(base_path,'../inputFiles/simpleInnerFFD.xyz') - DVGeoChild = DVGeometry(FFDFile,child=True) + FFDFile = os.path.join(base_path, "../inputFiles/simpleInnerFFD.xyz") + DVGeoChild = DVGeometry(FFDFile, child=True) # create a reference axis for the child - axisPoints = [[ -0.5, 0. , 0.],[ 0.5, 0., 0.]] - c1 = Curve(X=axisPoints,k=2) - DVGeoChild.addRefAxis('nestedAxis',curve=c1, axis='y') + axisPoints = [[-0.5, 0.0, 0.0], [0.5, 0.0, 0.0]] + c1 = Curve(X=axisPoints, k=2) + DVGeoChild.addRefAxis("nestedAxis", curve=c1, axis="y") + + return DVGeo, DVGeoChild - return DVGeo,DVGeoChild def setupDVGeoD8(base_path, isComplex): - #create the Parent FFD - FFDFile = os.path.join(base_path,'../inputFiles/bodyFFD.xyz') - DVGeo = DVGeometry(FFDFile,complex=isComplex) + # create the Parent FFD + FFDFile = os.path.join(base_path, "../inputFiles/bodyFFD.xyz") + DVGeo = DVGeometry(FFDFile, complex=isComplex) # create a reference axis for the parent - axisPoints = [[0.,0.,0.],[26.,0.,0.],[30.5,0.,0.9], - [ 32.5, 0., 1.01],[ 34.0, 0., 0.95]] - c1 = Curve(X=axisPoints,k=2) - DVGeo.addRefAxis('mainAxis',curve=c1, axis='y') + axisPoints = [[0.0, 0.0, 0.0], [26.0, 0.0, 0.0], [30.5, 0.0, 0.9], [32.5, 0.0, 1.01], [34.0, 0.0, 0.95]] + c1 = Curve(X=axisPoints, k=2) + DVGeo.addRefAxis("mainAxis", curve=c1, axis="y") # create the child FFD - FFDFile = os.path.join(base_path,'../inputFiles/nozzleFFD.xyz') - DVGeoChild = DVGeometry(FFDFile,child=True,complex=isComplex) + FFDFile = os.path.join(base_path, "../inputFiles/nozzleFFD.xyz") + DVGeoChild = DVGeometry(FFDFile, child=True, complex=isComplex) # create a reference axis for the child - axisPoints = [[32.4, 1. , 1.],[ 34, 1., 0.9]] - c1 = Curve(X=axisPoints,k=2) - DVGeoChild.addRefAxis('nestedAxis',curve=c1, axis='y') + axisPoints = [[32.4, 1.0, 1.0], [34, 1.0, 0.9]] + c1 = Curve(X=axisPoints, k=2) + DVGeoChild.addRefAxis("nestedAxis", curve=c1, axis="y") return DVGeo, DVGeoChild + def setupDVGeoAxi(base_path): - FFDFile = os.path.join(base_path,"../inputFiles/axiTestFFD.xyz") - DVGeo = DVGeometryAxi(FFDFile, center=(0., 0., 0.), collapse_into=("x", "z")) - axisPoints = [[ 0, 0. , 0.],[ 0, 0., 1.]] - c1 = Curve(X=axisPoints,k=2) - DVGeo.addRefAxis('stretch',curve=c1, axis='z') + FFDFile = os.path.join(base_path, "../inputFiles/axiTestFFD.xyz") + DVGeo = DVGeometryAxi(FFDFile, center=(0.0, 0.0, 0.0), collapse_into=("x", "z")) + axisPoints = [[0, 0.0, 0.0], [0, 0.0, 1.0]] + c1 = Curve(X=axisPoints, k=2) + DVGeo.addRefAxis("stretch", curve=c1, axis="z") return DVGeo # define a nested global design variable -def childAxisPoints(val,geo): - C = geo.extractCoef('nestedAxis') +def childAxisPoints(val, geo): + C = geo.extractCoef("nestedAxis") # Set the coefficients - C[0,0] = val[0] + C[0, 0] = val[0] - geo.restoreCoef(C, 'nestedAxis') + geo.restoreCoef(C, "nestedAxis") return -#define a nested global design variable -def mainAxisPoints(val,geo): - C = geo.extractCoef('mainAxis') + +# define a nested global design variable +def mainAxisPoints(val, geo): + C = geo.extractCoef("mainAxis") # Set the coefficients - C[0,0] = val[0] + C[0, 0] = val[0] - geo.restoreCoef(C, 'mainAxis') + geo.restoreCoef(C, "mainAxis") return -#define a nested global design variable -def childAxisPointsD8(val,geo): - C = geo.extractCoef('nestedAxis') + +# define a nested global design variable +def childAxisPointsD8(val, geo): + C = geo.extractCoef("nestedAxis") # Set the coefficients for i in range(len(val)): - C[i,0] = val[i] + C[i, 0] = val[i] - geo.restoreCoef(C, 'nestedAxis') + geo.restoreCoef(C, "nestedAxis") return -#define a nested global design variable -def mainAxisPointsD8(val,geo): - C = geo.extractCoef('mainAxis') + +# define a nested global design variable +def mainAxisPointsD8(val, geo): + C = geo.extractCoef("mainAxis") # Set the coefficients for i in range(len(val)): - C[i,0] = val[i] + C[i, 0] = val[i] - geo.restoreCoef(C, 'mainAxis') + geo.restoreCoef(C, "mainAxis") return + def mainAxisPointAxi(val, DVgeo): - C = DVgeo.extractCoef('stretch') - C[0,2] = val[0] + C = DVgeo.extractCoef("stretch") + C[0, 2] = val[0] - DVgeo.restoreCoef(C, 'stretch') + DVgeo.restoreCoef(C, "stretch") return -def totalSensitivityFD(DVGeo,nPt,ptName,step=1e-1): + +def totalSensitivityFD(DVGeo, nPt, ptName, step=1e-1): xDV = DVGeo.getValues() refPoints = DVGeo.update(ptName) - #now get FD Sensitivity + # now get FD Sensitivity dIdxFD = {} - #step = 1e-1#8 + # step = 1e-1#8 for key in xDV: baseVar = xDV[key].copy() nDV = len(baseVar) - dIdxFD[key] = numpy.zeros([nPt,nDV]) + dIdxFD[key] = numpy.zeros([nPt, nDV]) for i in range(nDV): - #print('perturbing',key) - xDV[key][i] = baseVar[i]+step - #print('setting design vars') + # print('perturbing',key) + xDV[key][i] = baseVar[i] + step + # print('setting design vars') DVGeo.setDesignVars(xDV) - #print('calling top level update') + # print('calling top level update') newPoints = DVGeo.update(ptName) - deriv = (newPoints-refPoints)/step - dIdxFD[key][:,i] = deriv.flatten() - #print('Deriv',key, i,deriv) + deriv = (newPoints - refPoints) / step + dIdxFD[key][:, i] = deriv.flatten() + # print('Deriv',key, i,deriv) xDV[key][i] = baseVar[i] return dIdxFD -def totalSensitivityCS(DVGeo,nPt,ptName): + +def totalSensitivityCS(DVGeo, nPt, ptName): xDV = DVGeo.getValues() - #now get CS Sensitivity + # now get CS Sensitivity dIdxCS = {} step = 1e-40j for key in xDV: baseVar = xDV[key].copy() - dIdxCS[key] = numpy.zeros([nPt,len(baseVar)]) + dIdxCS[key] = numpy.zeros([nPt, len(baseVar)]) for i in range(len(baseVar)): - xDV[key][i] = baseVar[i]+step + xDV[key][i] = baseVar[i] + step DVGeo.setDesignVars(xDV) newPoints = DVGeo.update(ptName) - deriv = numpy.imag(newPoints)/numpy.imag(step) - dIdxCS[key][:,i] = deriv.flatten() - #print 'Deriv',key, i,deriv + deriv = numpy.imag(newPoints) / numpy.imag(step) + dIdxCS[key][:, i] = deriv.flatten() + # print 'Deriv',key, i,deriv xDV[key][i] = baseVar[i] # Before we exit make sure we have reset the DVs @@ -176,12 +184,13 @@ def totalSensitivityCS(DVGeo,nPt,ptName): return dIdxCS -def testSensitivities(DVGeo,refDeriv,handler,pointset=1): - #create test points - points = numpy.zeros([2,3]) + +def testSensitivities(DVGeo, refDeriv, handler, pointset=1): + # create test points + points = numpy.zeros([2, 3]) if pointset == 1: - points[0,:] = [0.25,0,0] - points[1,:] = [-0.25,0,0] + points[0, :] = [0.25, 0, 0] + points[1, :] = [-0.25, 0, 0] elif pointset == 2: points[0, :] = [0.25, 0.4, 4] points[1, :] = [-0.8, 0.2, 7] @@ -189,78 +198,83 @@ def testSensitivities(DVGeo,refDeriv,handler,pointset=1): raise Warning("Enter a valid pointset") # add points to the geometry object - ptName = 'testPoints' - DVGeo.addPointSet(points,ptName) + ptName = "testPoints" + DVGeo.addPointSet(points, ptName) # generate dIdPt nPt = 6 - dIdPt = numpy.zeros([nPt,2,3]) - dIdPt[0,0,0] = 1.0 - dIdPt[1,0,1] = 1.0 - dIdPt[2,0,2] = 1.0 - dIdPt[3,1,0] = 1.0 - dIdPt[4,1,1] = 1.0 - dIdPt[5,1,2] = 1.0 - #get analytic sensitivity + dIdPt = numpy.zeros([nPt, 2, 3]) + dIdPt[0, 0, 0] = 1.0 + dIdPt[1, 0, 1] = 1.0 + dIdPt[2, 0, 2] = 1.0 + dIdPt[3, 1, 0] = 1.0 + dIdPt[4, 1, 1] = 1.0 + dIdPt[5, 1, 2] = 1.0 + # get analytic sensitivity if refDeriv: - dIdx = totalSensitivityFD(DVGeo,nPt,ptName) + dIdx = totalSensitivityFD(DVGeo, nPt, ptName) else: - dIdx = DVGeo.totalSensitivity(dIdPt,ptName) + dIdx = DVGeo.totalSensitivity(dIdPt, ptName) - handler.root_add_dict('dIdx',dIdx,rtol=1e-7,atol=1e-7) + handler.root_add_dict("dIdx", dIdx, rtol=1e-7, atol=1e-7) -def testSensitivitiesD8(DVGeo,refDeriv,handler): - #create test points + +def testSensitivitiesD8(DVGeo, refDeriv, handler): + # create test points nPoints = 50 - points = numpy.zeros([nPoints,3]) + points = numpy.zeros([nPoints, 3]) for i in range(nPoints): nose = 0.01 tail = 34.0 - delta = (tail-nose)/nPoints - points[i,:] = [nose+i*delta,1.0,0.5] + delta = (tail - nose) / nPoints + points[i, :] = [nose + i * delta, 1.0, 0.5] - #print('points',points) + # print('points',points) # add points to the geometry object - ptName = 'testPoints' - DVGeo.addPointSet(points,ptName,faceFreeze={}) + ptName = "testPoints" + DVGeo.addPointSet(points, ptName, faceFreeze={}) # generate dIdPt - nPt = nPoints*3 - dIdPt = numpy.zeros([nPt,nPoints,3]) + nPt = nPoints * 3 + dIdPt = numpy.zeros([nPt, nPoints, 3]) counter = 0 for i in range(nPoints): for j in range(3): - dIdPt[counter,i,j] = 1.0 - counter+=1 - #get analytic sensitivity + dIdPt[counter, i, j] = 1.0 + counter += 1 + # get analytic sensitivity if refDeriv: # dIdx = totalSensitivityFD(DVGeo,nPt,ptName) - dIdx = totalSensitivityCS(DVGeo,nPt,ptName) + dIdx = totalSensitivityCS(DVGeo, nPt, ptName) else: - dIdx = DVGeo.totalSensitivity(dIdPt,ptName) + dIdx = DVGeo.totalSensitivity(dIdPt, ptName) + + handler.root_add_dict("dIdx", dIdx, rtol=1e-7, atol=1e-7) - handler.root_add_dict("dIdx",dIdx,rtol=1e-7,atol=1e-7) # --- Adding standard twist and single axis scaling functions --- # These functions are added for Test 24 but could be extended to other tests -fix_root_sect=1 +fix_root_sect = 1 nRefAxPts = 4 + def twist(val, geo): axis_key = list(geo.axis.keys())[0] for i in range(fix_root_sect, nRefAxPts): geo.rot_theta[axis_key].coef[i] = val[i - fix_root_sect] + def thickness(val, geo): axis_key = list(geo.axis.keys())[0] for i in range(1, nRefAxPts): geo.scale_z[axis_key].coef[i] = val[i - fix_root_sect] + def chord(val, geo): axis_key = list(geo.axis.keys())[0] for i in range(1, nRefAxPts): - geo.scale_x[axis_key].coef[i] = val[i - fix_root_sect] \ No newline at end of file + geo.scale_x[axis_key].coef[i] = val[i - fix_root_sect] diff --git a/tests/reg_tests/test_Blocks.py b/tests/reg_tests/test_Blocks.py index 123a2e92..e670698e 100644 --- a/tests/reg_tests/test_Blocks.py +++ b/tests/reg_tests/test_Blocks.py @@ -20,15 +20,15 @@ def setUp(self): def make_cube_ffd(self, file_name, x0, y0, z0, dx, dy, dz): # Write cube ffd with i along x-axis, j along y-axis, and k along z-axis - axes = ['k', 'j', 'i'] + axes = ["k", "j", "i"] slices = numpy.array( # Slice 1 - [[[[x0, y0, z0], [x0+dx, y0, z0]], - [[x0, y0+dy, z0], [x0+dx, y0+dy, z0]]], - # Slice 2 - [[[x0, y0, z0+dz], [x0+dx, y0, z0+dz]], - [[x0, y0+dy, z0+dz], [x0+dx, y0+dy, z0+dz]]]], - dtype='d' + [ + [[[x0, y0, z0], [x0 + dx, y0, z0]], [[x0, y0 + dy, z0], [x0 + dx, y0 + dy, z0]]], + # Slice 2 + [[[x0, y0, z0 + dz], [x0 + dx, y0, z0 + dz]], [[x0, y0 + dy, z0 + dz], [x0 + dx, y0 + dy, z0 + dz]]], + ], + dtype="d", ) N0 = [2] @@ -39,114 +39,114 @@ def make_cube_ffd(self, file_name, x0, y0, z0, dx, dy, dz): def setup_blocks(self, testID, isComplex=False): # Make tiny FFD - ffd_name = '../inputFiles/tiny_cube_{:02d}.xyz'.format(testID) + ffd_name = "../inputFiles/tiny_cube_{:02d}.xyz".format(testID) file_name = os.path.join(self.base_path, ffd_name) self.make_cube_ffd(file_name, 1, 1, 1, 1, 1, 1) tiny = DVGeometry(file_name, child=True, complex=isComplex) os.remove(file_name) - tiny.addRefAxis('ref', xFraction=0.5, alignIndex='j', rotType=7) + tiny.addRefAxis("ref", xFraction=0.5, alignIndex="j", rotType=7) # Make tiny FFD - ffd_name = '../inputFiles/small_cube_{:02d}.xyz'.format(testID) + ffd_name = "../inputFiles/small_cube_{:02d}.xyz".format(testID) file_name = os.path.join(self.base_path, ffd_name) self.make_cube_ffd(file_name, 0, 0, 0, 2, 2, 2) small = DVGeometry(file_name, child=True, complex=isComplex) os.remove(file_name) - small.addRefAxis('ref', xFraction=0.5, alignIndex='j') + small.addRefAxis("ref", xFraction=0.5, alignIndex="j") # Make big FFD - ffd_name = '../inputFiles/big_cube_{:02d}.xyz'.format(testID) + ffd_name = "../inputFiles/big_cube_{:02d}.xyz".format(testID) file_name = os.path.join(self.base_path, ffd_name) self.make_cube_ffd(file_name, 0, 0, 0, 3, 3, 3) big = DVGeometry(file_name, complex=isComplex) os.remove(file_name) - big.addRefAxis('ref', xFraction=0.5, alignIndex='i') + big.addRefAxis("ref", xFraction=0.5, alignIndex="i") big.addChild(small) small.addChild(tiny) # Add point set - points = numpy.array([ + points = numpy.array( + [ [0.5, 0.5, 0.5], [1.25, 1.25, 1.25], [1.5, 1.5, 1.5], [2.0, 2.5, 0.5], - ]) - big.addPointSet(points, 'X') + ] + ) + big.addPointSet(points, "X") return big, small, tiny def compute_values(self, DVGeo, handler, refDeriv): # Calculate updated point coordinates - Xnew = DVGeo.update('X') - handler.root_add_val('pointvals', Xnew, rtol=1e-12, atol=1e-12, msg='Updated points') + Xnew = DVGeo.update("X") + handler.root_add_val("pointvals", Xnew, rtol=1e-12, atol=1e-12, msg="Updated points") # Need to get design variables so that we can reset the Jacobians # for each call x = DVGeo.getValues() # Calculate Jacobians DVGeo.setDesignVars(x) - DVGeo.update('X') - DVGeo.computeTotalJacobian('X') - Jac = DVGeo.JT['X'].toarray() + DVGeo.update("X") + DVGeo.computeTotalJacobian("X") + Jac = DVGeo.JT["X"].toarray() DVGeo.setDesignVars(x) - DVGeo.update('X') - DVGeo.computeTotalJacobianCS('X') - JacCS = DVGeo.JT['X'] + DVGeo.update("X") + DVGeo.computeTotalJacobianCS("X") + JacCS = DVGeo.JT["X"] DVGeo.setDesignVars(x) - DVGeo.update('X') - DVGeo.computeTotalJacobianFD('X') - JacFD = DVGeo.JT['X'] + DVGeo.update("X") + DVGeo.computeTotalJacobianFD("X") + JacFD = DVGeo.JT["X"] if refDeriv: - handler.root_add_val('jacobian', JacCS, rtol=1e-12, atol=1e-12, msg='Check jacobian') + handler.root_add_val("jacobian", JacCS, rtol=1e-12, atol=1e-12, msg="Check jacobian") else: - handler.root_add_val('jacobian', Jac, rtol=1e-12, atol=1e-12, msg='Check jacobian') + handler.root_add_val("jacobian", Jac, rtol=1e-12, atol=1e-12, msg="Check jacobian") # Test that they are equal to eachother - numpy.testing.assert_allclose(Jac, JacCS, rtol=1e-12, atol=1e-12, - err_msg='Analytic vs complex-step') - numpy.testing.assert_allclose(Jac, JacFD, rtol=1e-6, atol=1e-6, - err_msg='Analytic vs finite difference') + numpy.testing.assert_allclose(Jac, JacCS, rtol=1e-12, atol=1e-12, err_msg="Analytic vs complex-step") + numpy.testing.assert_allclose(Jac, JacFD, rtol=1e-6, atol=1e-6, err_msg="Analytic vs finite difference") # Make sure we reset everything DVGeo.setDesignVars(x) - DVGeo.update('X') + DVGeo.update("X") # Create dIdPt with one function for each point coordinate Npt = 4 - dIdPt = numpy.zeros([Npt*3, Npt,3]) + dIdPt = numpy.zeros([Npt * 3, Npt, 3]) for i in range(Npt): - dIdPt[i*3:(i+1)*3,i] = numpy.eye(3) + dIdPt[i * 3 : (i + 1) * 3, i] = numpy.eye(3) # Test sensitivity dictionaries if refDeriv: # Generate reference from finite differences - sens = commonUtils.totalSensitivityFD(DVGeo, Npt*3, 'X', step=1e-6) - handler.root_add_dict('dIdx', sens, rtol=1e-6, atol=1e-6, msg='Check sens dict') + sens = commonUtils.totalSensitivityFD(DVGeo, Npt * 3, "X", step=1e-6) + handler.root_add_dict("dIdx", sens, rtol=1e-6, atol=1e-6, msg="Check sens dict") else: # Compute the analytic derivatives - sens = DVGeo.totalSensitivity(dIdPt, 'X') - handler.root_add_dict('dIdx', sens, rtol=1e-6, atol=1e-6, msg='Check sens dict') + sens = DVGeo.totalSensitivity(dIdPt, "X") + handler.root_add_dict("dIdx", sens, rtol=1e-6, atol=1e-6, msg="Check sens dict") def train_1(self, train=True, refDeriv=True): self.test_1(train=train, refDeriv=refDeriv) def test_1(self, train=False, refDeriv=False): - refFile = os.path.join(self.base_path,'ref/test_Blocks_01.ref') + refFile = os.path.join(self.base_path, "ref/test_Blocks_01.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 1") big, small, tiny = self.setup_blocks(testID=1) - add_vars(small, 'small', rotate='y') - add_vars(tiny, 'tiny', rotate='y') + add_vars(small, "small", rotate="y") + add_vars(tiny, "tiny", rotate="y") # Rotate small cube by 45 and then rotate tiny cube by -45 x = {} - x['rotate_y_small'] = 45 - x['rotate_y_tiny'] = -45 + x["rotate_y_small"] = 45 + x["rotate_y_tiny"] = -45 big.setDesignVars(x) # Compute tests @@ -156,21 +156,21 @@ def train_2(self, train=True, refDeriv=True): self.test_2(train=train, refDeriv=refDeriv) def test_2(self, train=False, refDeriv=False): - refFile = os.path.join(self.base_path,'ref/test_Blocks_02.ref') + refFile = os.path.join(self.base_path, "ref/test_Blocks_02.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 2") big, small, tiny = self.setup_blocks(testID=2) - add_vars(big, 'big', rotate='x') - add_vars(small, 'small', translate=True) - add_vars(tiny, 'tiny', rotate='y') + add_vars(big, "big", rotate="x") + add_vars(small, "small", translate=True) + add_vars(tiny, "tiny", rotate="y") # Modify design variables x = {} - x['rotate_x_big'] = 10 - x['translate_small'] = [0.5, -1, 0.7] - x['rotate_y_tiny'] = -20 + x["rotate_x_big"] = 10 + x["translate_small"] = [0.5, -1, 0.7] + x["rotate_y_tiny"] = -20 big.setDesignVars(x) # Compute tests @@ -180,21 +180,21 @@ def train_3(self, train=True, refDeriv=True): self.test_3(train=train, refDeriv=refDeriv) def test_3(self, train=False, refDeriv=False): - refFile = os.path.join(self.base_path,'ref/test_Blocks_03.ref') + refFile = os.path.join(self.base_path, "ref/test_Blocks_03.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 3") big, small, tiny = self.setup_blocks(testID=3) - add_vars(small, 'small', rotate='y') - add_vars(tiny, 'tiny', rotate='y', slocal=True) + add_vars(small, "small", rotate="y") + add_vars(tiny, "tiny", rotate="y", slocal=True) # Modify design variables x = big.getValues() - x['rotate_y_small'] = 10 - x['rotate_y_tiny'] = -20 + x["rotate_y_small"] = 10 + x["rotate_y_tiny"] = -20 numpy.random.seed(11) - x['sectionlocal_tiny'] = numpy.random.random(*x['sectionlocal_tiny'].shape) + x["sectionlocal_tiny"] = numpy.random.random(*x["sectionlocal_tiny"].shape) big.setDesignVars(x) # Compute tests @@ -204,7 +204,7 @@ def train_4(self, train=True, refDeriv=True): self.test_4(train=train, refDeriv=refDeriv) def test_4(self, train=False, refDeriv=False): - refFile = os.path.join(self.base_path,'ref/test_Blocks_04.ref') + refFile = os.path.join(self.base_path, "ref/test_Blocks_04.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 4") @@ -212,16 +212,16 @@ def test_4(self, train=False, refDeriv=False): big, small, tiny = self.setup_blocks(testID=4) # Add only translation variables - add_vars(big, 'big', translate=True) - add_vars(small, 'small', translate=True) - add_vars(tiny, 'tiny', translate=True) + add_vars(big, "big", translate=True) + add_vars(small, "small", translate=True) + add_vars(tiny, "tiny", translate=True) # Modify design variables x = big.getValues() numpy.random.seed(11) - x['translate_big'] = numpy.random.random(3) - x['translate_small'] = numpy.random.random(3) - x['translate_tiny'] = numpy.random.random(3) + x["translate_big"] = numpy.random.random(3) + x["translate_small"] = numpy.random.random(3) + x["translate_tiny"] = numpy.random.random(3) big.setDesignVars(x) # Compute tests @@ -231,7 +231,7 @@ def train_5(self, train=True, refDeriv=True): self.test_5(train=train, refDeriv=refDeriv) def test_5(self, train=False, refDeriv=False): - refFile = os.path.join(self.base_path,'ref/test_Blocks_05.ref') + refFile = os.path.join(self.base_path, "ref/test_Blocks_05.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 5") @@ -243,88 +243,91 @@ def test_5(self, train=False, refDeriv=False): big, small, tiny = self.setup_blocks(testID=5, isComplex=isComplex) # Add only translation variables - add_vars(big, 'big', translate=True) - add_vars(small, 'small', rotate='y') - add_vars(tiny, 'tiny', rotate='y') + add_vars(big, "big", translate=True) + add_vars(small, "small", rotate="y") + add_vars(tiny, "tiny", rotate="y") # Modify design variables x = big.getValues() numpy.random.seed(11) - x['translate_big'] = numpy.random.random(3) - x['rotate_y_small'] = 45 - x['rotate_y_tiny'] = -45 + x["translate_big"] = numpy.random.random(3) + x["rotate_y_small"] = 45 + x["rotate_y_tiny"] = -45 big.setDesignVars(x) # Compute tests big.setDesignVars(x) - big.update('X') + big.update("X") # Create dIdPt with one function for each point coordinate Npt = 4 - dIdPt = numpy.zeros([Npt*3, Npt,3]) + dIdPt = numpy.zeros([Npt * 3, Npt, 3]) for i in range(Npt): - dIdPt[i*3:(i+1)*3,i] = numpy.eye(3) + dIdPt[i * 3 : (i + 1) * 3, i] = numpy.eye(3) # Test sensitivity dictionaries if refDeriv: # Generate reference from finite differences - sens = commonUtils.totalSensitivityCS(big, Npt*3, 'X') - handler.root_add_dict('dIdx', sens, rtol=1e-12, atol=1e-12, msg='Check sens dict') + sens = commonUtils.totalSensitivityCS(big, Npt * 3, "X") + handler.root_add_dict("dIdx", sens, rtol=1e-12, atol=1e-12, msg="Check sens dict") else: # Compute the analytic derivatives - sens = big.totalSensitivity(dIdPt, 'X') - handler.root_add_dict('dIdx', sens, rtol=1e-12, atol=1e-12, msg='Check sens dict') + sens = big.totalSensitivity(dIdPt, "X") + handler.root_add_dict("dIdx", sens, rtol=1e-12, atol=1e-12, msg="Check sens dict") + -''' +""" The following are some helper functions for setting up the design variables for the different test cases. -''' +""" + + def add_vars(geo, name, translate=False, rotate=None, scale=None, local=None, slocal=False): if translate: - dvName = 'translate_{}'.format(name) - geo.addGeoDVGlobal(dvName=dvName, value=[0]*3, func=f_translate) + dvName = "translate_{}".format(name) + geo.addGeoDVGlobal(dvName=dvName, value=[0] * 3, func=f_translate) if rotate is not None: - rot_funcs = { - 'x':f_rotate_x, - 'y':f_rotate_y, - 'z':f_rotate_z, - 'theta':f_rotate_theta - } - assert(rotate in rot_funcs.keys()) - - dvName = 'rotate_{}_{}'.format(rotate, name) + rot_funcs = {"x": f_rotate_x, "y": f_rotate_y, "z": f_rotate_z, "theta": f_rotate_theta} + assert rotate in rot_funcs.keys() + + dvName = "rotate_{}_{}".format(rotate, name) dvFunc = rot_funcs[rotate] geo.addGeoDVGlobal(dvName=dvName, value=0, func=dvFunc) if local is not None: - assert(local in ['x', 'y', 'z']) - dvName = 'local_{}_{}'.format(local, name) + assert local in ["x", "y", "z"] + dvName = "local_{}_{}".format(local, name) geo.addGeoDVLocal(dvName, axis=local) if slocal: - dvName = 'sectionlocal_{}'.format(name) - geo.addGeoDVSectionLocal(dvName, secIndex='j', axis=1, orient0='i', orient2='ffd') + dvName = "sectionlocal_{}".format(name) + geo.addGeoDVSectionLocal(dvName, secIndex="j", axis=1, orient0="i", orient2="ffd") + def f_translate(val, geo): - C = geo.extractCoef('ref') + C = geo.extractCoef("ref") for i in range(len(val)): - C[:,i] += val[i] - geo.restoreCoef(C, 'ref') + C[:, i] += val[i] + geo.restoreCoef(C, "ref") + def f_rotate_x(val, geo): - geo.rot_x['ref'].coef[:] = val[0] + geo.rot_x["ref"].coef[:] = val[0] + def f_rotate_y(val, geo): - geo.rot_y['ref'].coef[:] = val[0] + geo.rot_y["ref"].coef[:] = val[0] + def f_rotate_z(val, geo): - geo.rot_z['ref'].coef[:] = val[0] + geo.rot_z["ref"].coef[:] = val[0] + def f_rotate_theta(val, geo): - geo.rot_theta['ref'].coef[:] = val[0] + geo.rot_theta["ref"].coef[:] = val[0] -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/reg_tests/test_Cylinder.py b/tests/reg_tests/test_Cylinder.py index 0197d5ea..99aba3de 100644 --- a/tests/reg_tests/test_Cylinder.py +++ b/tests/reg_tests/test_Cylinder.py @@ -22,7 +22,7 @@ def make_cylinder_mesh(self, radius=1.0, height=2.0): Nextrude = 100 Npts = Nazimuth * Nextrude - theta = numpy.linspace(0, 2*numpy.pi, Nazimuth) + theta = numpy.linspace(0, 2 * numpy.pi, Nazimuth) z = numpy.linspace(0, height, Nextrude) pts = numpy.zeros((Npts, 3)) @@ -33,7 +33,7 @@ def make_cylinder_mesh(self, radius=1.0, height=2.0): x = radius * numpy.cos(theta[j]) y = radius * numpy.sin(theta[j]) - k = i*Nazimuth + j + k = i * Nazimuth + j pts[k] = [x, y, z[i]] p0 = [] @@ -41,8 +41,8 @@ def make_cylinder_mesh(self, radius=1.0, height=2.0): v2 = [] # Now create the triangulation - for i in range(Nextrude-1): - for j in range(Nazimuth-1): + for i in range(Nextrude - 1): + for j in range(Nazimuth - 1): cur_level = i * Nazimuth next_level = (i + 1) * Nazimuth @@ -69,18 +69,18 @@ def make_cylinder_mesh(self, radius=1.0, height=2.0): def make_ffd(self, file_name, radius=1.0, height=2.0): # Write duplicate of outerbox FFD - axes = ['i', 'k', 'j'] + axes = ["i", "k", "j"] r = radius h = height dh = 0.01 - slices = numpy.array([ - # Slice 1 - [[[-r, -r, -dh], [r, -r, -dh]], - [[-r, r, -dh], [r, r, -dh]]], - # Slice 2 - [[[-r, -r, h+dh], [r, -r, h+dh]], - [[-r, r, h+dh], [r, r, h+dh]]], - ]) + slices = numpy.array( + [ + # Slice 1 + [[[-r, -r, -dh], [r, -r, -dh]], [[-r, r, -dh], [r, r, -dh]]], + # Slice 2 + [[[-r, -r, h + dh], [r, -r, h + dh]], [[-r, r, h + dh], [r, r, h + dh]]], + ] + ) N0 = [5] N1 = [2] @@ -92,7 +92,7 @@ def train_1(self, train=True, refDeriv=True): self.test_1(train=train, refDeriv=refDeriv) def test_1(self, train=False, refDeriv=False): - refFile = os.path.join(self.base_path,'ref/test_Cylinder_01.ref') + refFile = os.path.join(self.base_path, "ref/test_Cylinder_01.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 1: Basic FFD, global DVs") @@ -104,50 +104,47 @@ def test_1(self, train=False, refDeriv=False): DVCon.setSurface(surf) # DVCon.writeSurfaceTecplot('cylinder_surface.dat') - ffd_name = os.path.join(self.base_path,'../inputFiles/cylinder_ffd.xyz') + ffd_name = os.path.join(self.base_path, "../inputFiles/cylinder_ffd.xyz") self.make_ffd(ffd_name, radius, height) DVGeo = DVGeometry(ffd_name) - nAxPts = DVGeo.addRefAxis('thru', xFraction=0.5, alignIndex='i', raySize=1.0) + nAxPts = DVGeo.addRefAxis("thru", xFraction=0.5, alignIndex="i", raySize=1.0) def scale_circle(val, geo): for i in range(nAxPts): - geo.scale['thru'].coef[i] = val[0] + geo.scale["thru"].coef[i] = val[0] - DVGeo.addGeoDVGlobal('scale_circle', func=scale_circle, value=[1]) + DVGeo.addGeoDVGlobal("scale_circle", func=scale_circle, value=[1]) DVCon.setDVGeo(DVGeo) - leList = [[0, 0, 0 ], [-radius/2, 0, height]] + leList = [[0, 0, 0], [-radius / 2, 0, height]] xAxis = [-1, 0, 0] yAxis = [0, 1, 0] - DVCon.addLERadiusConstraints(leList, nSpan=5, axis=yAxis, - chordDir=xAxis, scaled=False) + DVCon.addLERadiusConstraints(leList, nSpan=5, axis=yAxis, chordDir=xAxis, scaled=False) # DVCon.writeTecplot('cylinder_constraints.dat') funcs = {} DVCon.evalFunctions(funcs) print(funcs) - handler.root_add_dict('funcs1', funcs, rtol=1e-6, atol=1e-6) + handler.root_add_dict("funcs1", funcs, rtol=1e-6, atol=1e-6) - DVGeo.setDesignVars({'scale_circle':0.5}) + DVGeo.setDesignVars({"scale_circle": 0.5}) funcs = {} DVCon.evalFunctions(funcs) - handler.root_add_dict('funcs2', funcs, rtol=1e-6, atol=1e-6) + handler.root_add_dict("funcs2", funcs, rtol=1e-6, atol=1e-6) print(funcs) funcsSens = {} DVCon.evalFunctionsSens(funcsSens) print(funcsSens) - handler.root_add_dict('funcsSens', funcsSens, rtol=1e-6, atol=1e-6) + handler.root_add_dict("funcsSens", funcsSens, rtol=1e-6, atol=1e-6) print(funcsSens) - def train_spanwise_dvs(self, train=True, refDeriv=True): self.test_spanwise_dvs(train=train, refDeriv=refDeriv) - def test_spanwise_dvs(self, train=False, refDeriv=False): - refFile = os.path.join(self.base_path,'ref/test_Cylinder_spanwise_dvs.ref') + refFile = os.path.join(self.base_path, "ref/test_Cylinder_spanwise_dvs.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 1: Basic FFD, global DVs") @@ -159,43 +156,40 @@ def test_spanwise_dvs(self, train=False, refDeriv=False): DVCon.setSurface(surf) # DVCon.writeSurfaceTecplot('cylinder_surface.dat') - ffd_name = os.path.join(self.base_path,'../inputFiles/cylinder_ffd.xyz') + ffd_name = os.path.join(self.base_path, "../inputFiles/cylinder_ffd.xyz") self.make_ffd(ffd_name, radius, height) DVGeo = DVGeometry(ffd_name) - DVGeo.addGeoDVSpanwiseLocal("shape", 'i', lower=-0.5, upper=0.5, axis="y", scale=1.0) + DVGeo.addGeoDVSpanwiseLocal("shape", "i", lower=-0.5, upper=0.5, axis="y", scale=1.0) size = DVGeo._getNDVSpanwiseLocal() DVCon.setDVGeo(DVGeo) - - leList = [[0, 0, 0 ], [-radius/2, 0, height]] + leList = [[0, 0, 0], [-radius / 2, 0, height]] xAxis = [-1, 0, 0] yAxis = [0, 1, 0] - DVCon.addLERadiusConstraints(leList, nSpan=5, axis=yAxis, - chordDir=xAxis, scaled=False) + DVCon.addLERadiusConstraints(leList, nSpan=5, axis=yAxis, chordDir=xAxis, scaled=False) # DVCon.writeTecplot('cylinder_constraints.dat') funcs = {} DVCon.evalFunctions(funcs) print(funcs) - handler.root_add_dict('funcs1', funcs, rtol=1e-6, atol=1e-6) + handler.root_add_dict("funcs1", funcs, rtol=1e-6, atol=1e-6) numpy.random.seed(0) - DVGeo.setDesignVars({'shape':(numpy.random.rand(size) - 0.5)}) + DVGeo.setDesignVars({"shape": (numpy.random.rand(size) - 0.5)}) funcs = {} DVCon.evalFunctions(funcs) - handler.root_add_dict('funcs2', funcs, rtol=1e-6, atol=1e-6) + handler.root_add_dict("funcs2", funcs, rtol=1e-6, atol=1e-6) print(funcs) funcsSens = {} DVCon.evalFunctionsSens(funcsSens) print(funcsSens) - handler.root_add_dict('funcsSens', funcsSens, rtol=1e-6, atol=1e-6) + handler.root_add_dict("funcsSens", funcsSens, rtol=1e-6, atol=1e-6) print(funcsSens) - -if __name__ == '__main__': - unittest.main() \ No newline at end of file +if __name__ == "__main__": + unittest.main() diff --git a/tests/reg_tests/test_DVConstraints.py b/tests/reg_tests/test_DVConstraints.py index e3beb82f..c4f5ea12 100644 --- a/tests/reg_tests/test_DVConstraints.py +++ b/tests/reg_tests/test_DVConstraints.py @@ -6,8 +6,10 @@ import commonUtils from pygeo import geo_utils, DVGeometry, DVConstraints from stl import mesh + try: import geograd + missing_geograd = False except ImportError: missing_geograd = True @@ -66,15 +68,15 @@ def evalFunctionsSensFD(self, DVGeo, DVCon, fdstep=1e-2): temp_b = funcs[outkey] diff = temp_a - temp_b deriv_temp = diff / fdstep - funcsSens[outkey][inkey][:,array_ind] = deriv_temp + funcsSens[outkey][inkey][:, array_ind] = deriv_temp xDV[inkey][array_ind] = baseVar[array_ind] DVGeo.setDesignVars(xDV) DVCon.evalFunctions(dict()) return funcsSens def generate_dvgeo_dvcon_rect(self, addToDVGeo=False): - meshfile = os.path.join(self.base_path, '../inputFiles/2x1x8_rectangle.stl') - ffdfile = os.path.join(self.base_path, '../inputFiles/2x1x8_rectangle.xyz') + meshfile = os.path.join(self.base_path, "../inputFiles/2x1x8_rectangle.stl") + ffdfile = os.path.join(self.base_path, "../inputFiles/2x1x8_rectangle.xyz") testmesh = mesh.Mesh.from_file(meshfile) # test mesh dim 0 is triangle index # dim 1 is each vertex of the triangle @@ -84,25 +86,27 @@ def generate_dvgeo_dvcon_rect(self, addToDVGeo=False): DVGeo = DVGeometry(ffdfile) nRefAxPts = DVGeo.addRefAxis("wing", xFraction=0.5, alignIndex="k") self.nTwist = nRefAxPts - 1 + def twist(val, geo): for i in range(1, nRefAxPts): geo.rot_z["wing"].coef[i] = val[i - 1] + DVGeo.addGeoDVGlobal(dvName="twist", value=[0] * self.nTwist, func=twist, lower=-10, upper=10, scale=1) DVGeo.addGeoDVLocal("local", lower=-0.5, upper=0.5, axis="y", scale=1) # create a DVConstraints object for the wing - DVCon =DVConstraints() + DVCon = DVConstraints() DVCon.setDVGeo(DVGeo) - p0 = testmesh.vectors[:,0,:] - v1 = testmesh.vectors[:,1,:] - p0 - v2 = testmesh.vectors[:,2,:] - p0 + p0 = testmesh.vectors[:, 0, :] + v1 = testmesh.vectors[:, 1, :] - p0 + v2 = testmesh.vectors[:, 2, :] - p0 DVCon.setSurface([p0, v1, v2], addToDVGeo=addToDVGeo) return DVGeo, DVCon def generate_dvgeo_dvcon_c172(self): - meshfile = os.path.join(self.base_path, '../inputFiles/c172.stl') - ffdfile = os.path.join(self.base_path, '../inputFiles/c172.xyz') + meshfile = os.path.join(self.base_path, "../inputFiles/c172.stl") + ffdfile = os.path.join(self.base_path, "../inputFiles/c172.xyz") testmesh = mesh.Mesh.from_file(meshfile) # test mesh dim 0 is triangle index # dim 1 is each vertex of the triangle @@ -112,40 +116,41 @@ def generate_dvgeo_dvcon_c172(self): DVGeo = DVGeometry(ffdfile) nRefAxPts = DVGeo.addRefAxis("wing", xFraction=0.25, alignIndex="k") self.nTwist = nRefAxPts - 1 + def twist(val, geo): for i in range(1, nRefAxPts): geo.rot_z["wing"].coef[i] = val[i - 1] + DVGeo.addGeoDVGlobal(dvName="twist", value=[0] * self.nTwist, func=twist, lower=-10, upper=10, scale=1) DVGeo.addGeoDVLocal("local", lower=-0.5, upper=0.5, axis="y", scale=1) # create a DVConstraints object for the wing - DVCon =DVConstraints() + DVCon = DVConstraints() DVCon.setDVGeo(DVGeo) - p0 = testmesh.vectors[:,0,:] / 1000 - v1 = testmesh.vectors[:,1,:] / 1000 - p0 - v2 = testmesh.vectors[:,2,:] / 1000 - p0 + p0 = testmesh.vectors[:, 0, :] / 1000 + v1 = testmesh.vectors[:, 1, :] / 1000 - p0 + v2 = testmesh.vectors[:, 2, :] / 1000 - p0 DVCon.setSurface([p0, v1, v2]) return DVGeo, DVCon def generic_test_base(self, DVGeo, DVCon, handler, checkDerivs=True, fdstep=1e-4): - linear_constraint_keywords = ['lete', 'monotonic', 'linear_constraint'] + linear_constraint_keywords = ["lete", "monotonic", "linear_constraint"] funcs = dict() DVCon.evalFunctions(funcs, includeLinear=True) - handler.root_add_dict('funcs_base', funcs, rtol=1e-6, atol=1e-6) - funcsSens=dict() + handler.root_add_dict("funcs_base", funcs, rtol=1e-6, atol=1e-6) + funcsSens = dict() DVCon.evalFunctionsSens(funcsSens, includeLinear=True) # regress the derivatives if checkDerivs: - handler.root_add_dict('derivs_base', funcsSens, rtol=1e-6, atol=1e-6) + handler.root_add_dict("derivs_base", funcsSens, rtol=1e-6, atol=1e-6) funcsSensFD = self.evalFunctionsSensFD(DVGeo, DVCon, fdstep=fdstep) for outkey in funcs.keys(): for inkey in DVGeo.getValues().keys(): try: analytic = funcsSens[outkey][inkey] fd = funcsSensFD[outkey][inkey] - handler.assert_allclose(analytic, fd, - name='finite_diff_check', rtol=1e-3, atol=1e-3) + handler.assert_allclose(analytic, fd, name="finite_diff_check", rtol=1e-3, atol=1e-3) except KeyError: if any(sbstr in outkey for sbstr in linear_constraint_keywords): # linear constraints only have their affected DVs in the dict @@ -159,16 +164,16 @@ def c172_test_twist(self, DVGeo, DVCon, handler): funcsSens = dict() # change the DVs xDV = DVGeo.getValues() - xDV['twist'] = np.linspace(0, 10, self.nTwist) + xDV["twist"] = np.linspace(0, 10, self.nTwist) DVGeo.setDesignVars(xDV) # check the constraint values changed DVCon.evalFunctions(funcs, includeLinear=True) - handler.root_add_dict('funcs_twisted', funcs, rtol=1e-6, atol=1e-6) + handler.root_add_dict("funcs_twisted", funcs, rtol=1e-6, atol=1e-6) # check the derivatives are still right DVCon.evalFunctionsSens(funcsSens, includeLinear=True) # regress the derivatives - handler.root_add_dict('derivs_twisted', funcsSens, rtol=1e-6, atol=1e-6) + handler.root_add_dict("derivs_twisted", funcsSens, rtol=1e-6, atol=1e-6) return funcs, funcsSens def c172_test_deformed(self, DVGeo, DVCon, handler): @@ -176,37 +181,38 @@ def c172_test_deformed(self, DVGeo, DVCon, handler): funcsSens = dict() xDV = DVGeo.getValues() np.random.seed(37) - xDV['local'] = np.random.normal(0.0, 0.05, 32) + xDV["local"] = np.random.normal(0.0, 0.05, 32) DVGeo.setDesignVars(xDV) DVCon.evalFunctions(funcs, includeLinear=True) DVCon.evalFunctionsSens(funcsSens, includeLinear=True) - handler.root_add_dict('funcs_deformed', funcs, rtol=1e-6, atol=1e-6) - handler.root_add_dict('derivs_deformed', funcsSens, rtol=1e-6, atol=1e-6) + handler.root_add_dict("funcs_deformed", funcs, rtol=1e-6, atol=1e-6) + handler.root_add_dict("derivs_deformed", funcsSens, rtol=1e-6, atol=1e-6) return funcs, funcsSens def test_1(self, train=False, refDeriv=False): """ Test 1: 1D Thickness Constraint """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_01.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_01.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 1: 1D thickness constraint, C172 wing") DVGeo, DVCon = self.generate_dvgeo_dvcon_c172() - ptList = [[0.8, 0.0, 0.1],[0.8, 0.0, 5.0]] - DVCon.addThicknessConstraints1D(ptList, nCon=10, axis=[0,1,0]) - + ptList = [[0.8, 0.0, 0.1], [0.8, 0.0, 5.0]] + DVCon.addThicknessConstraints1D(ptList, nCon=10, axis=[0, 1, 0]) funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler, checkDerivs=True) # 1D thickness should be all ones at the start - handler.assert_allclose(funcs['DVCon1_thickness_constraints_0'], np.ones(10), - name='thickness_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_thickness_constraints_0"], np.ones(10), name="thickness_base", rtol=1e-7, atol=1e-7 + ) funcs, funcsSens = self.c172_test_twist(DVGeo, DVCon, handler) # 1D thickness shouldn't change much under only twist - handler.assert_allclose(funcs['DVCon1_thickness_constraints_0'], np.ones(10), - name='thickness_twisted', rtol=1e-2, atol=1e-2) + handler.assert_allclose( + funcs["DVCon1_thickness_constraints_0"], np.ones(10), name="thickness_twisted", rtol=1e-2, atol=1e-2 + ) funcs, funcsSens = self.c172_test_deformed(DVGeo, DVCon, handler) @@ -214,52 +220,56 @@ def test_1b(self, train=False, refDeriv=False): """ Test 1b: 1D Thickness Constraint """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_01b.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_01b.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 1b: 1D thickness constraint, rectangular box") DVGeo, DVCon = self.generate_dvgeo_dvcon_rect() - ptList = [[0.0, 0.0, 0.1],[0.0, 0.0, 5.0]] - ptList2 = [[-0.5, 0.0, 2.0],[0.5, 0.0, 2.0]] - DVCon.addThicknessConstraints1D(ptList, nCon=3, axis=[0,1,0], scaled=False) - DVCon.addThicknessConstraints1D(ptList, nCon=3, axis=[1,0,0], scaled=False) - DVCon.addThicknessConstraints1D(ptList2, nCon=3, axis=[0,0,1], scaled=False) + ptList = [[0.0, 0.0, 0.1], [0.0, 0.0, 5.0]] + ptList2 = [[-0.5, 0.0, 2.0], [0.5, 0.0, 2.0]] + DVCon.addThicknessConstraints1D(ptList, nCon=3, axis=[0, 1, 0], scaled=False) + DVCon.addThicknessConstraints1D(ptList, nCon=3, axis=[1, 0, 0], scaled=False) + DVCon.addThicknessConstraints1D(ptList2, nCon=3, axis=[0, 0, 1], scaled=False) funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) # check that unscaled thicknesses are being computed correctly at baseline - handler.assert_allclose(funcs['DVCon1_thickness_constraints_0'], np.ones(3), - name='thickness_base', rtol=1e-7, atol=1e-7) - handler.assert_allclose(funcs['DVCon1_thickness_constraints_1'], 2.0*np.ones(3), - name='thickness_base', rtol=1e-7, atol=1e-7) - handler.assert_allclose(funcs['DVCon1_thickness_constraints_2'], 8.0*np.ones(3), - name='thickness_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_thickness_constraints_0"], np.ones(3), name="thickness_base", rtol=1e-7, atol=1e-7 + ) + handler.assert_allclose( + funcs["DVCon1_thickness_constraints_1"], 2.0 * np.ones(3), name="thickness_base", rtol=1e-7, atol=1e-7 + ) + handler.assert_allclose( + funcs["DVCon1_thickness_constraints_2"], 8.0 * np.ones(3), name="thickness_base", rtol=1e-7, atol=1e-7 + ) def test_2(self, train=False, refDeriv=False): """ Test 2: 2D Thickness Constraint """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_02.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_02.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 2: 2D thickness constraint, C172 wing") DVGeo, DVCon = self.generate_dvgeo_dvcon_c172() - leList = [[0.7, 0.0, 0.1],[0.7, 0.0, 5.0]] - teList = [[0.9, 0.0, 0.1],[0.9, 0.0, 5.0]] + leList = [[0.7, 0.0, 0.1], [0.7, 0.0, 5.0]] + teList = [[0.9, 0.0, 0.1], [0.9, 0.0, 5.0]] DVCon.addThicknessConstraints2D(leList, teList, 5, 5) - funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) # 2D thickness should be all ones at the start - handler.assert_allclose(funcs['DVCon1_thickness_constraints_0'], np.ones(25), - name='thickness_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_thickness_constraints_0"], np.ones(25), name="thickness_base", rtol=1e-7, atol=1e-7 + ) funcs, funcsSens = self.c172_test_twist(DVGeo, DVCon, handler) # 2D thickness shouldn't change much under only twist - handler.assert_allclose(funcs['DVCon1_thickness_constraints_0'], np.ones(25), - name='thickness_twisted', rtol=1e-2, atol=1e-2) + handler.assert_allclose( + funcs["DVCon1_thickness_constraints_0"], np.ones(25), name="thickness_twisted", rtol=1e-2, atol=1e-2 + ) funcs, funcsSens = self.c172_test_deformed(DVGeo, DVCon, handler) @@ -267,20 +277,20 @@ def test_2b(self, train=False, refDeriv=False): """ Test 2b: 2D Thickness Constraint """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_02b.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_02b.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 2: 2D thickness constraint, rectangular box") DVGeo, DVCon = self.generate_dvgeo_dvcon_rect() - leList = [[-0.25, 0.0, 0.1],[-0.25, 0.0, 7.9]] - teList = [[0.75, 0.0, 0.1],[0.75, 0.0, 7.9]] + leList = [[-0.25, 0.0, 0.1], [-0.25, 0.0, 7.9]] + teList = [[0.75, 0.0, 0.1], [0.75, 0.0, 7.9]] - leList2 = [[0.0, -0.25, 0.1],[0.0, -0.25, 7.9]] - teList2 = [[0.0, 0.25, 0.1],[0.0, 0.25, 7.9]] + leList2 = [[0.0, -0.25, 0.1], [0.0, -0.25, 7.9]] + teList2 = [[0.0, 0.25, 0.1], [0.0, 0.25, 7.9]] - leList3 = [[-0.5, -0.25, 0.1],[0.5, -0.25, 0.1]] - teList3 = [[-0.5, 0.25, 0.1],[0.5, 0.25, 0.1]] + leList3 = [[-0.5, -0.25, 0.1], [0.5, -0.25, 0.1]] + teList3 = [[-0.5, 0.25, 0.1], [0.5, 0.25, 0.1]] DVCon.addThicknessConstraints2D(leList, teList, 2, 2, scaled=False) DVCon.addThicknessConstraints2D(leList2, teList2, 2, 2, scaled=False) @@ -288,38 +298,42 @@ def test_2b(self, train=False, refDeriv=False): funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) # 2D thickness should be all ones at the start - handler.assert_allclose(funcs['DVCon1_thickness_constraints_0'], np.ones(4), - name='thickness_base', rtol=1e-7, atol=1e-7) - handler.assert_allclose(funcs['DVCon1_thickness_constraints_1'], 2.0*np.ones(4), - name='thickness_base', rtol=1e-7, atol=1e-7) - handler.assert_allclose(funcs['DVCon1_thickness_constraints_2'], 8.0*np.ones(4), - name='thickness_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_thickness_constraints_0"], np.ones(4), name="thickness_base", rtol=1e-7, atol=1e-7 + ) + handler.assert_allclose( + funcs["DVCon1_thickness_constraints_1"], 2.0 * np.ones(4), name="thickness_base", rtol=1e-7, atol=1e-7 + ) + handler.assert_allclose( + funcs["DVCon1_thickness_constraints_2"], 8.0 * np.ones(4), name="thickness_base", rtol=1e-7, atol=1e-7 + ) def test_3(self, train=False, refDeriv=False): """ Test 3: Volume Constraint """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_03.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_03.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 3: Volume constraint, C172 wing") DVGeo, DVCon = self.generate_dvgeo_dvcon_c172() - leList = [[0.7, 0.0, 0.1],[0.7, 0.0, 5.0]] - teList = [[0.9, 0.0, 0.1],[0.9, 0.0, 5.0]] + leList = [[0.7, 0.0, 0.1], [0.7, 0.0, 5.0]] + teList = [[0.9, 0.0, 0.1], [0.9, 0.0, 5.0]] DVCon.addVolumeConstraint(leList, teList, 5, 5) - funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) # Volume should be normalized to 1 at the start - handler.assert_allclose(funcs['DVCon1_volume_constraint_0'], np.ones(1), - name='volume_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_volume_constraint_0"], np.ones(1), name="volume_base", rtol=1e-7, atol=1e-7 + ) funcs, funcsSens = self.c172_test_twist(DVGeo, DVCon, handler) # Volume shouldn't change much with twist only - handler.assert_allclose(funcs['DVCon1_volume_constraint_0'], np.ones(1), - name='volume_twisted', rtol=1e-2, atol=1e-2) + handler.assert_allclose( + funcs["DVCon1_volume_constraint_0"], np.ones(1), name="volume_twisted", rtol=1e-2, atol=1e-2 + ) funcs, funcsSens = self.c172_test_deformed(DVGeo, DVCon, handler) @@ -327,7 +341,7 @@ def test_3b(self, train=False, refDeriv=False): """ Test 3b: Volume Constraint """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_03b.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_03b.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 3b: Volume constraint, rectangular box") @@ -335,15 +349,16 @@ def test_3b(self, train=False, refDeriv=False): # this projects in the z direction which is of dimension 8 # 1x0.5x8 = 4 - leList = [[-0.5, -0.25, 0.1],[0.5, -0.25, 0.1]] - teList = [[-0.5, 0.25, 0.1],[0.5, 0.25, 0.1]] + leList = [[-0.5, -0.25, 0.1], [0.5, -0.25, 0.1]] + teList = [[-0.5, 0.25, 0.1], [0.5, 0.25, 0.1]] DVCon.addVolumeConstraint(leList, teList, 4, 4, scaled=False) funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) # Volume should be normalized to 1 at the start - handler.assert_allclose(funcs['DVCon1_volume_constraint_0'], 4.0*np.ones(1), - name='volume_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_volume_constraint_0"], 4.0 * np.ones(1), name="volume_base", rtol=1e-7, atol=1e-7 + ) def test_4(self, train=False, refDeriv=False): """ @@ -352,27 +367,32 @@ def test_4(self, train=False, refDeriv=False): There's no need to test this with the rectangular box because it doesn't depend on a projected pointset (only the FFD) """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_04.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_04.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 4: LETE constraint, C172 wing") DVGeo, DVCon = self.generate_dvgeo_dvcon_c172() - DVCon.addLeTeConstraints(0, 'iLow') - DVCon.addLeTeConstraints(0, 'iHigh') - + DVCon.addLeTeConstraints(0, "iLow") + DVCon.addLeTeConstraints(0, "iHigh") funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) # LeTe constraints should be all zero at the start for i in range(2): - handler.assert_allclose(funcs['DVCon1_lete_constraint_'+str(i)], np.zeros(4), - name='lete_'+str(i), rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_lete_constraint_" + str(i)], np.zeros(4), name="lete_" + str(i), rtol=1e-7, atol=1e-7 + ) funcs, funcsSens = self.c172_test_twist(DVGeo, DVCon, handler) # Global DVs should produce no change, especially twist for i in range(2): - handler.assert_allclose(funcs['DVCon1_lete_constraint_'+str(i)], np.zeros(4), - name='lete_twisted_'+str(i), rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_lete_constraint_" + str(i)], + np.zeros(4), + name="lete_twisted_" + str(i), + rtol=1e-7, + atol=1e-7, + ) funcs, funcsSens = self.c172_test_deformed(DVGeo, DVCon, handler) def test_5(self, train=False, refDeriv=False): @@ -382,22 +402,28 @@ def test_5(self, train=False, refDeriv=False): There's no need to test this with the rectangular box because it doesn't depend on a projected pointset (only the FFD) """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_05.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_05.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 5: t/c constraint, C172 wing") DVGeo, DVCon = self.generate_dvgeo_dvcon_c172() - ptList = [[0.8, 0.0, 0.1],[0.8, 0.0, 5.0]] - DVCon.addThicknessToChordConstraints1D(ptList, nCon=10, axis=[0,1,0], chordDir=[1,0,0]) + ptList = [[0.8, 0.0, 0.1], [0.8, 0.0, 5.0]] + DVCon.addThicknessToChordConstraints1D(ptList, nCon=10, axis=[0, 1, 0], chordDir=[1, 0, 0]) funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) - handler.assert_allclose(funcs['DVCon1_thickness_to_chord_constraints_0'], np.ones(10), - name='toverc_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_thickness_to_chord_constraints_0"], np.ones(10), name="toverc_base", rtol=1e-7, atol=1e-7 + ) funcs, funcsSens = self.c172_test_twist(DVGeo, DVCon, handler) - handler.assert_allclose(funcs['DVCon1_thickness_to_chord_constraints_0'], np.ones(10), - name='toverc_twisted', rtol=1e-3, atol=1e-3) + handler.assert_allclose( + funcs["DVCon1_thickness_to_chord_constraints_0"], + np.ones(10), + name="toverc_twisted", + rtol=1e-3, + atol=1e-3, + ) funcs, funcsSens = self.c172_test_deformed(DVGeo, DVCon, handler) @@ -405,7 +431,7 @@ def test_6(self, train=False, refDeriv=False): """ Test 6: Surface area constraint """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_06.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_06.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 6: surface area constraint, C172 wing") @@ -414,12 +440,14 @@ def test_6(self, train=False, refDeriv=False): DVCon.addSurfaceAreaConstraint() funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) - handler.assert_allclose(funcs['DVCon1_surfaceArea_constraints_0'], np.ones(1), - name='surface_area_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_surfaceArea_constraints_0"], np.ones(1), name="surface_area_base", rtol=1e-7, atol=1e-7 + ) funcs, funcsSens = self.c172_test_twist(DVGeo, DVCon, handler) - handler.assert_allclose(funcs['DVCon1_surfaceArea_constraints_0'], np.ones(1), - name='surface_area_twisted', rtol=1e-3, atol=1e-3) + handler.assert_allclose( + funcs["DVCon1_surfaceArea_constraints_0"], np.ones(1), name="surface_area_twisted", rtol=1e-3, atol=1e-3 + ) funcs, funcsSens = self.c172_test_deformed(DVGeo, DVCon, handler) @@ -427,7 +455,7 @@ def test_6b(self, train=False, refDeriv=False): """ Test 6b: Surface area constraint """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_06b.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_06b.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 6: surface area constraint, rectangular box") @@ -436,14 +464,19 @@ def test_6b(self, train=False, refDeriv=False): DVCon.addSurfaceAreaConstraint(scaled=False) # 2x1x8 box has surface area 2*(8*2+1*2+8*1) = 52 funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) - handler.assert_allclose(funcs['DVCon1_surfaceArea_constraints_0'], 52.*np.ones(1), - name='surface_area_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_surfaceArea_constraints_0"], + 52.0 * np.ones(1), + name="surface_area_base", + rtol=1e-7, + atol=1e-7, + ) def test_7(self, train=False, refDeriv=False): """ Test 7: Projected area constraint """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_07.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_07.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 7: projected area constraint, C172 wing") @@ -452,8 +485,13 @@ def test_7(self, train=False, refDeriv=False): DVCon.addProjectedAreaConstraint() funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) - handler.assert_allclose(funcs['DVCon1_projectedArea_constraints_0'], np.ones(1), - name='projected_area_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_projectedArea_constraints_0"], + np.ones(1), + name="projected_area_base", + rtol=1e-7, + atol=1e-7, + ) funcs, funcsSens = self.c172_test_twist(DVGeo, DVCon, handler) @@ -463,23 +501,38 @@ def test_7b(self, train=False, refDeriv=False): """ Test 7b: Projected area constraint """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_07b.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_07b.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 7b: projected area constraint, rectangular box") DVGeo, DVCon = self.generate_dvgeo_dvcon_rect() DVCon.addProjectedAreaConstraint(scaled=False) - DVCon.addProjectedAreaConstraint(axis='z', scaled=False) - DVCon.addProjectedAreaConstraint(axis='x', scaled=False) + DVCon.addProjectedAreaConstraint(axis="z", scaled=False) + DVCon.addProjectedAreaConstraint(axis="x", scaled=False) funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler, checkDerivs=False) - handler.assert_allclose(funcs['DVCon1_projectedArea_constraints_0'], 8*2*np.ones(1), - name='projected_area_base', rtol=1e-7, atol=1e-7) - handler.assert_allclose(funcs['DVCon1_projectedArea_constraints_1'], 1*2*np.ones(1), - name='projected_area_base', rtol=1e-7, atol=1e-7) - handler.assert_allclose(funcs['DVCon1_projectedArea_constraints_2'], 8*1*np.ones(1), - name='projected_area_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_projectedArea_constraints_0"], + 8 * 2 * np.ones(1), + name="projected_area_base", + rtol=1e-7, + atol=1e-7, + ) + handler.assert_allclose( + funcs["DVCon1_projectedArea_constraints_1"], + 1 * 2 * np.ones(1), + name="projected_area_base", + rtol=1e-7, + atol=1e-7, + ) + handler.assert_allclose( + funcs["DVCon1_projectedArea_constraints_2"], + 8 * 1 * np.ones(1), + name="projected_area_base", + rtol=1e-7, + atol=1e-7, + ) def test_8(self, train=False, refDeriv=False): """ @@ -488,23 +541,31 @@ def test_8(self, train=False, refDeriv=False): No need to test this with the rectangular box because it only depends on the FFD, no projected points """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_08.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_08.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 8: Circularity constraint, C172 wing") DVGeo, DVCon = self.generate_dvgeo_dvcon_c172() - DVCon.addCircularityConstraint(origin=[0.8, 0.0, 2.5], rotAxis=[0., 0., 1.], - radius=0.1, zeroAxis=[0.,1.,0.], angleCW=180., angleCCW=180., - nPts=10) + DVCon.addCircularityConstraint( + origin=[0.8, 0.0, 2.5], + rotAxis=[0.0, 0.0, 1.0], + radius=0.1, + zeroAxis=[0.0, 1.0, 0.0], + angleCW=180.0, + angleCCW=180.0, + nPts=10, + ) funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) - handler.assert_allclose(funcs['DVCon1_circularity_constraints_0'], np.ones(9), - name='circularity_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_circularity_constraints_0"], np.ones(9), name="circularity_base", rtol=1e-7, atol=1e-7 + ) funcs, funcsSens = self.c172_test_twist(DVGeo, DVCon, handler) - handler.assert_allclose(funcs['DVCon1_circularity_constraints_0'], np.ones(9), - name='circularity_twisted', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_circularity_constraints_0"], np.ones(9), name="circularity_twisted", rtol=1e-7, atol=1e-7 + ) funcs, funcsSens = self.c172_test_deformed(DVGeo, DVCon, handler) def test_9(self, train=False, refDeriv=False): @@ -514,19 +575,21 @@ def test_9(self, train=False, refDeriv=False): No need to test this with the rectangular box because it only depends on the FFD, no projected points """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_09.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_09.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 9: Colinearity constraint, C172 wing") DVGeo, DVCon = self.generate_dvgeo_dvcon_c172() - DVCon.addColinearityConstraint(np.array([0.7, 0.0, 1.0]), lineAxis=np.array([0.,0.,1.]), - distances=[0., 1., 2.5]) + DVCon.addColinearityConstraint( + np.array([0.7, 0.0, 1.0]), lineAxis=np.array([0.0, 0.0, 1.0]), distances=[0.0, 1.0, 2.5] + ) # Skip derivatives check here because true zero values cause difficulties for the partials funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler, checkDerivs=False) - handler.assert_allclose(funcs['DVCon1_colinearity_constraints_0'], np.zeros(3), - name='colinearity_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_colinearity_constraints_0"], np.zeros(3), name="colinearity_base", rtol=1e-7, atol=1e-7 + ) funcs, funcsSens = self.c172_test_twist(DVGeo, DVCon, handler) funcs, funcsSens = self.c172_test_deformed(DVGeo, DVCon, handler) @@ -538,130 +601,139 @@ def test_10(self, train=False, refDeriv=False): No need to test this with the rectangular box because it only depends on the FFD, no projected points """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_10.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_10.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 10: LinearConstraintShape, C172 wing") DVGeo, DVCon = self.generate_dvgeo_dvcon_c172() lIndex = DVGeo.getLocalIndex(0) - indSetA = []; indSetB = []; + indSetA = [] + indSetB = [] for i in range(lIndex.shape[0]): indSetA.append(lIndex[i, 0, 0]) indSetB.append(lIndex[i, 0, 1]) - DVCon.addLinearConstraintsShape(indSetA, indSetB, - factorA=1.0, factorB=-1.0, - lower=0, upper=0) + DVCon.addLinearConstraintsShape(indSetA, indSetB, factorA=1.0, factorB=-1.0, lower=0, upper=0) funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) funcs, funcsSens = self.c172_test_twist(DVGeo, DVCon, handler) funcs, funcsSens = self.c172_test_deformed(DVGeo, DVCon, handler) def test_11(self, train=False, refDeriv=False): - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_11.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_11.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 11: CompositeVolumeConstraint, rectangular box") DVGeo, DVCon = self.generate_dvgeo_dvcon_rect() # this projects in the z direction which is of dimension 8 # 1x0.5x8 = 4 - leList = [[-0.5, -0.25, 0.1],[0.5, -0.25, 0.1]] - teList = [[-0.5, 0.25, 0.1],[0.5, 0.25, 0.1]] + leList = [[-0.5, -0.25, 0.1], [0.5, -0.25, 0.1]] + teList = [[-0.5, 0.25, 0.1], [0.5, 0.25, 0.1]] # this projects in the x direction which is of dimension 2 # 2x0.6x7.8 = 9.36 - leList2 = [[0., -0.25, 0.1],[0., -0.25, 7.9]] - teList2 = [[0., 0.35, 0.1],[0., 0.35, 7.9]] + leList2 = [[0.0, -0.25, 0.1], [0.0, -0.25, 7.9]] + teList2 = [[0.0, 0.35, 0.1], [0.0, 0.35, 7.9]] DVCon.addVolumeConstraint(leList, teList, 4, 4, scaled=False, addToPyOpt=False) DVCon.addVolumeConstraint(leList2, teList2, 4, 4, scaled=False, addToPyOpt=False) - vols = ['DVCon1_volume_constraint_0', - 'DVCon1_volume_constraint_1'] + vols = ["DVCon1_volume_constraint_0", "DVCon1_volume_constraint_1"] DVCon.addCompositeVolumeConstraint(vols=vols, scaled=False) - funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) # Volume should be normalized to 1 at the start - handler.assert_allclose(funcs['DVCon1_volume_constraint_0'], 4.0*np.ones(1), - name='volume1_base', rtol=1e-7, atol=1e-7) - handler.assert_allclose(funcs['DVCon1_volume_constraint_1'], 9.36*np.ones(1), - name='volume2_base', rtol=1e-7, atol=1e-7) - handler.assert_allclose(funcs['DVCon1_composite_volume_constraint_2'], 13.36*np.ones(1), - name='volume_composite_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_volume_constraint_0"], 4.0 * np.ones(1), name="volume1_base", rtol=1e-7, atol=1e-7 + ) + handler.assert_allclose( + funcs["DVCon1_volume_constraint_1"], 9.36 * np.ones(1), name="volume2_base", rtol=1e-7, atol=1e-7 + ) + handler.assert_allclose( + funcs["DVCon1_composite_volume_constraint_2"], + 13.36 * np.ones(1), + name="volume_composite_base", + rtol=1e-7, + atol=1e-7, + ) def test_12(self, train=False, refDeriv=False): - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_12.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_12.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 12: LocationConstraints1D, rectangular box") DVGeo, DVCon = self.generate_dvgeo_dvcon_rect() - ptList = [[0.0, 0.0, 0.0],[0.0, 0.0, 8.0]] - ptList2 = [[0.0, 0.2, 0.0],[0.0, -0.2, 8.0]] + ptList = [[0.0, 0.0, 0.0], [0.0, 0.0, 8.0]] + ptList2 = [[0.0, 0.2, 0.0], [0.0, -0.2, 8.0]] # TODO this constraint seems buggy. for example, when scaled, returns a bunch of NaNs DVCon.addLocationConstraints1D(ptList=ptList, nCon=10, scaled=False) - DVCon.addProjectedLocationConstraints1D(ptList=ptList2, nCon=10, scaled=False, axis=[0.,1.,0.]) + DVCon.addProjectedLocationConstraints1D(ptList=ptList2, nCon=10, scaled=False, axis=[0.0, 1.0, 0.0]) funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) exact_vals = np.zeros((30,)) - exact_vals[2::3] = np.linspace(0,8,10) + exact_vals[2::3] = np.linspace(0, 8, 10) # should be 10 evenly spaced points along the z axis originating from 0,0,0 - handler.assert_allclose(funcs['DVCon1_location_constraints_0'], - exact_vals, - name='locations_match', rtol=1e-7, atol=1e-7) - handler.assert_allclose(funcs['DVCon1_location_constraints_1'], - exact_vals, - name='projected_locations_match', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_location_constraints_0"], exact_vals, name="locations_match", rtol=1e-7, atol=1e-7 + ) + handler.assert_allclose( + funcs["DVCon1_location_constraints_1"], + exact_vals, + name="projected_locations_match", + rtol=1e-7, + atol=1e-7, + ) def test_13(self, train=False, refDeriv=False): - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_13.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_13.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 13: PlanarityConstraint, rectangular box") DVGeo, DVCon = self.generate_dvgeo_dvcon_rect() - DVCon.addPlanarityConstraint(origin=[0.,0.5,0.0], planeAxis=[0.,1.,0.]) + DVCon.addPlanarityConstraint(origin=[0.0, 0.5, 0.0], planeAxis=[0.0, 1.0, 0.0]) funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) def test_13b(self, train=False, refDeriv=False): - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_13b.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_13b.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 13: PlanarityConstraint, rectangular box") - ffdfile = os.path.join(self.base_path, '../inputFiles/2x1x8_rectangle.xyz') + ffdfile = os.path.join(self.base_path, "../inputFiles/2x1x8_rectangle.xyz") DVGeo = DVGeometry(ffdfile) DVGeo.addGeoDVLocal("local", lower=-0.5, upper=0.5, axis="y", scale=1) # create a DVConstraints object with a simple plane consisting of 2 triangles - DVCon =DVConstraints() + DVCon = DVConstraints() DVCon.setDVGeo(DVGeo) - p0 = np.zeros(shape=(2,3)) - p1 = np.zeros(shape=(2,3)) - p2 = np.zeros(shape=(2,3)) + p0 = np.zeros(shape=(2, 3)) + p1 = np.zeros(shape=(2, 3)) + p2 = np.zeros(shape=(2, 3)) vertex1 = np.array([0.5, -0.25, 0.0]) vertex2 = np.array([0.5, -0.25, 4.0]) vertex3 = np.array([-0.5, -0.25, 0.0]) vertex4 = np.array([-0.5, -0.25, 4.0]) - p0[:,:] = vertex1 - p2[:,:] = vertex4 - p1[0,:] = vertex2 - p1[1,:] = vertex3 + p0[:, :] = vertex1 + p2[:, :] = vertex4 + p1[0, :] = vertex2 + p1[1, :] = vertex3 v1 = p1 - p0 v2 = p2 - p0 DVCon.setSurface([p0, v1, v2]) - DVCon.addPlanarityConstraint(origin=[0.,-0.25,2.0], planeAxis=[0.,1.,0.]) + DVCon.addPlanarityConstraint(origin=[0.0, -0.25, 2.0], planeAxis=[0.0, 1.0, 0.0]) funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler, checkDerivs=False) # this should be coplanar and the planarity constraint shoudl be zero - handler.assert_allclose(funcs['DVCon1_planarity_constraints_0'], np.zeros(1), - name='planarity', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_planarity_constraints_0"], np.zeros(1), name="planarity", rtol=1e-7, atol=1e-7 + ) def test_14(self, train=False, refDeriv=False): """ Test 14: Monotonic constraint """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_14.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_14.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 14: Monotonic constraint, C172 wing") @@ -670,46 +742,61 @@ def test_14(self, train=False, refDeriv=False): DVCon.addMonotonicConstraints("twist") DVCon.addMonotonicConstraints("twist", start=1, stop=2) - funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) - handler.assert_allclose(funcs['DVCon1_monotonic_constraint_0'], np.zeros(2), - name='monotonicity', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_monotonic_constraint_0"], np.zeros(2), name="monotonicity", rtol=1e-7, atol=1e-7 + ) funcs, funcsSens = self.c172_test_twist(DVGeo, DVCon, handler) - handler.assert_allclose(funcs['DVCon1_monotonic_constraint_0'], -5.0*np.ones(2), - name='monotonicity_twisted', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_monotonic_constraint_0"], + -5.0 * np.ones(2), + name="monotonicity_twisted", + rtol=1e-7, + atol=1e-7, + ) funcs = dict() funcsSens = dict() # change the DVs arbitrarily xDV = DVGeo.getValues() - xDV['twist'][0] = 1.0 - xDV['twist'][1] = -3.5 - xDV['twist'][2] = -2.5 + xDV["twist"][0] = 1.0 + xDV["twist"][1] = -3.5 + xDV["twist"][2] = -2.5 DVGeo.setDesignVars(xDV) # check the constraint values changed DVCon.evalFunctions(funcs, includeLinear=True) - handler.root_add_dict('funcs_arb_twist', funcs, rtol=1e-6, atol=1e-6) + handler.root_add_dict("funcs_arb_twist", funcs, rtol=1e-6, atol=1e-6) # check the derivatives are still right DVCon.evalFunctionsSens(funcsSens, includeLinear=True) # regress the derivatives - handler.root_add_dict('derivs_arb_twist', funcsSens, rtol=1e-6, atol=1e-6) - handler.assert_allclose(funcs['DVCon1_monotonic_constraint_0'], np.array([4.5, -1.0]), - name='monotonicity_arb_twist', rtol=1e-7, atol=1e-7) - handler.assert_allclose(funcs['DVCon1_monotonic_constraint_1'], np.array([-1.0]), - name='monotonicity_arb_twist_1', rtol=1e-7, atol=1e-7) - - @unittest.skipIf(missing_geograd, 'requires geograd') + handler.root_add_dict("derivs_arb_twist", funcsSens, rtol=1e-6, atol=1e-6) + handler.assert_allclose( + funcs["DVCon1_monotonic_constraint_0"], + np.array([4.5, -1.0]), + name="monotonicity_arb_twist", + rtol=1e-7, + atol=1e-7, + ) + handler.assert_allclose( + funcs["DVCon1_monotonic_constraint_1"], + np.array([-1.0]), + name="monotonicity_arb_twist_1", + rtol=1e-7, + atol=1e-7, + ) + + @unittest.skipIf(missing_geograd, "requires geograd") def test_15(self, train=False, refDeriv=False): """ Test 15: Triangulated surface constraint """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_15.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_15.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 15: Triangulated surface constraint, BWB") - meshfile = os.path.join(self.base_path, '../inputFiles/bwb.stl') - objfile = os.path.join(self.base_path, '../inputFiles/blob_bwb_wing.stl') - ffdfile = os.path.join(self.base_path, '../inputFiles/bwb.xyz') + meshfile = os.path.join(self.base_path, "../inputFiles/bwb.stl") + objfile = os.path.join(self.base_path, "../inputFiles/blob_bwb_wing.stl") + ffdfile = os.path.join(self.base_path, "../inputFiles/bwb.xyz") testmesh = mesh.Mesh.from_file(meshfile) testobj = mesh.Mesh.from_file(objfile) # test mesh dim 0 is triangle index @@ -720,49 +807,49 @@ def test_15(self, train=False, refDeriv=False): DVGeo = DVGeometry(ffdfile) nRefAxPts = DVGeo.addRefAxis("wing", xFraction=0.25, alignIndex="k") self.nTwist = nRefAxPts - 1 + def twist(val, geo): for i in range(1, nRefAxPts): geo.rot_z["wing"].coef[i] = val[i - 1] + DVGeo.addGeoDVGlobal(dvName="twist", value=[0] * self.nTwist, func=twist, lower=-10, upper=10, scale=1) DVGeo.addGeoDVLocal("local", lower=-0.5, upper=0.5, axis="y", scale=1) # create a DVConstraints object for the wing - DVCon =DVConstraints() + DVCon = DVConstraints() DVCon.setDVGeo(DVGeo) - p0 = testmesh.vectors[:,0,:] - v1 = testmesh.vectors[:,1,:] - p0 - v2 = testmesh.vectors[:,2,:] - p0 + p0 = testmesh.vectors[:, 0, :] + v1 = testmesh.vectors[:, 1, :] - p0 + v2 = testmesh.vectors[:, 2, :] - p0 DVCon.setSurface([p0, v1, v2], addToDVGeo=True) - p0b = testobj.vectors[:,0,:] - v1b = testobj.vectors[:,1,:] - p0b - v2b = testobj.vectors[:,2,:] - p0b - DVCon.setSurface([p0b, v1b, v2b], name='blob') - - - DVCon.addTriangulatedSurfaceConstraint('default','default','blob',None,rho=10.,addToPyOpt=True) - DVCon.addTriangulatedSurfaceConstraint('default','default','blob',None,rho=1000.,addToPyOpt=True) + p0b = testobj.vectors[:, 0, :] + v1b = testobj.vectors[:, 1, :] - p0b + v2b = testobj.vectors[:, 2, :] - p0b + DVCon.setSurface([p0b, v1b, v2b], name="blob") + DVCon.addTriangulatedSurfaceConstraint("default", "default", "blob", None, rho=10.0, addToPyOpt=True) + DVCon.addTriangulatedSurfaceConstraint("default", "default", "blob", None, rho=1000.0, addToPyOpt=True) funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler, fdstep=1e-3) - handler.assert_allclose(funcs['DVCon1_trisurf_constraint_0_KS'], 0.34660627481696404, - name='KS', rtol=1e-7, atol=1e-7) - handler.assert_allclose(funcs['DVCon1_trisurf_constraint_0_perim'], 0.0, - name='perim', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_trisurf_constraint_0_KS"], 0.34660627481696404, name="KS", rtol=1e-7, atol=1e-7 + ) + handler.assert_allclose(funcs["DVCon1_trisurf_constraint_0_perim"], 0.0, name="perim", rtol=1e-7, atol=1e-7) funcs, funcsSens = self.c172_test_twist(DVGeo, DVCon, handler) funcs, funcsSens = self.c172_test_deformed(DVGeo, DVCon, handler) - @unittest.skipIf(missing_geograd, 'requires geograd') + @unittest.skipIf(missing_geograd, "requires geograd") def test_16(self, train=False, refDeriv=False): """ Test 16: Triangulated surface constraint, intersected """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_16.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_16.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 16: Triangulated surface constraint, intersected") - meshfile = os.path.join(self.base_path, '../inputFiles/bwb.stl') - objfile = os.path.join(self.base_path, '../inputFiles/blob_bwb_wing.stl') - ffdfile = os.path.join(self.base_path, '../inputFiles/bwb.xyz') + meshfile = os.path.join(self.base_path, "../inputFiles/bwb.stl") + objfile = os.path.join(self.base_path, "../inputFiles/blob_bwb_wing.stl") + ffdfile = os.path.join(self.base_path, "../inputFiles/bwb.xyz") testmesh = mesh.Mesh.from_file(meshfile) testobj = mesh.Mesh.from_file(objfile) # test mesh dim 0 is triangle index @@ -773,43 +860,44 @@ def test_16(self, train=False, refDeriv=False): DVGeo = DVGeometry(ffdfile) nRefAxPts = DVGeo.addRefAxis("wing", xFraction=0.25, alignIndex="k") self.nTwist = nRefAxPts - 1 + def twist(val, geo): for i in range(1, nRefAxPts): geo.rot_z["wing"].coef[i] = val[i - 1] + DVGeo.addGeoDVGlobal(dvName="twist", value=[0] * self.nTwist, func=twist, lower=-10, upper=10, scale=1) DVGeo.addGeoDVLocal("local", lower=-0.5, upper=0.5, axis="y", scale=1) # create a DVConstraints object for the wing - DVCon =DVConstraints() + DVCon = DVConstraints() DVCon.setDVGeo(DVGeo) - p0 = testmesh.vectors[:,0,:] - v1 = testmesh.vectors[:,1,:] - p0 - v2 = testmesh.vectors[:,2,:] - p0 + p0 = testmesh.vectors[:, 0, :] + v1 = testmesh.vectors[:, 1, :] - p0 + v2 = testmesh.vectors[:, 2, :] - p0 DVCon.setSurface([p0, v1, v2], addToDVGeo=True) - p0b = testobj.vectors[:,0,:] - v1b = testobj.vectors[:,1,:] - p0b - v2b = testobj.vectors[:,2,:] - p0b + p0b = testobj.vectors[:, 0, :] + v1b = testobj.vectors[:, 1, :] - p0b + v2b = testobj.vectors[:, 2, :] - p0b p0b = p0b + np.array([0.0, 0.3, 0.0]) - DVCon.setSurface([p0b, v1b, v2b], name='blob') - + DVCon.setSurface([p0b, v1b, v2b], name="blob") - DVCon.addTriangulatedSurfaceConstraint('default','default','blob',None,rho=10.,addToPyOpt=True) + DVCon.addTriangulatedSurfaceConstraint("default", "default", "blob", None, rho=10.0, addToPyOpt=True) funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) - np.testing.assert_array_less(np.zeros(1), funcs['DVCon1_trisurf_constraint_0_perim']) + np.testing.assert_array_less(np.zeros(1), funcs["DVCon1_trisurf_constraint_0_perim"]) - @unittest.skipIf(missing_geograd, 'requires geograd') + @unittest.skipIf(missing_geograd, "requires geograd") def test_17(self, train=False, refDeriv=False): """ Test 17: Triangulated surface constraint, intersected, two DVGeos """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_17.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_17.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 17: Triangulated surface constraint, intersected, 2 DVGeos") - meshfile = os.path.join(self.base_path, '../inputFiles/bwb.stl') - objfile = os.path.join(self.base_path, '../inputFiles/blob_bwb_wing.stl') - ffdfile = os.path.join(self.base_path, '../inputFiles/bwb.xyz') + meshfile = os.path.join(self.base_path, "../inputFiles/bwb.stl") + objfile = os.path.join(self.base_path, "../inputFiles/blob_bwb_wing.stl") + ffdfile = os.path.join(self.base_path, "../inputFiles/bwb.xyz") testmesh = mesh.Mesh.from_file(meshfile) testobj = mesh.Mesh.from_file(objfile) # test mesh dim 0 is triangle index @@ -820,14 +908,16 @@ def test_17(self, train=False, refDeriv=False): DVGeo1 = DVGeometry(ffdfile) nRefAxPts = DVGeo1.addRefAxis("wing", xFraction=0.25, alignIndex="k") self.nTwist = nRefAxPts - 1 + def twist(val, geo): for i in range(1, nRefAxPts): geo.rot_z["wing"].coef[i] = val[i - 1] + DVGeo1.addGeoDVGlobal(dvName="twist", value=[0] * self.nTwist, func=twist, lower=-10, upper=10, scale=1) DVGeo1.addGeoDVLocal("local", lower=-0.5, upper=0.5, axis="y", scale=1) # create a DVGeo object with a few local thickness variables - DVGeo2 = DVGeometry(ffdfile, name='blobdvgeo') + DVGeo2 = DVGeometry(ffdfile, name="blobdvgeo") DVGeo2.addGeoDVLocal("local_2", lower=-0.5, upper=0.5, axis="y", scale=1) # check that DVGeos with duplicate var names are not allowed @@ -835,32 +925,31 @@ def twist(val, geo): DVGeo3.addGeoDVLocal("local", lower=-0.5, upper=0.5, axis="y", scale=1) # create a DVConstraints object for the wing - DVCon =DVConstraints() + DVCon = DVConstraints() DVCon.setDVGeo(DVGeo1) - DVCon.setDVGeo(DVGeo2, name='second') + DVCon.setDVGeo(DVGeo2, name="second") with self.assertRaises(ValueError): - DVCon.setDVGeo(DVGeo3, name='third') + DVCon.setDVGeo(DVGeo3, name="third") - p0 = testmesh.vectors[:,0,:] - v1 = testmesh.vectors[:,1,:] - p0 - v2 = testmesh.vectors[:,2,:] - p0 + p0 = testmesh.vectors[:, 0, :] + v1 = testmesh.vectors[:, 1, :] - p0 + v2 = testmesh.vectors[:, 2, :] - p0 DVCon.setSurface([p0, v1, v2], addToDVGeo=True) - p0b = testobj.vectors[:,0,:] - v1b = testobj.vectors[:,1,:] - p0b - v2b = testobj.vectors[:,2,:] - p0b + p0b = testobj.vectors[:, 0, :] + v1b = testobj.vectors[:, 1, :] - p0b + v2b = testobj.vectors[:, 2, :] - p0b p0b = p0b + np.array([0.0, 0.3, 0.0]) - DVCon.setSurface([p0b, v1b, v2b], name='blob', addToDVGeo=True, DVGeoName='second') + DVCon.setSurface([p0b, v1b, v2b], name="blob", addToDVGeo=True, DVGeoName="second") - - DVCon.addTriangulatedSurfaceConstraint('default','default','blob','second',rho=10.,addToPyOpt=True) + DVCon.addTriangulatedSurfaceConstraint("default", "default", "blob", "second", rho=10.0, addToPyOpt=True) funcs = dict() DVCon.evalFunctions(funcs, includeLinear=True) - handler.root_add_dict('funcs_base', funcs, rtol=1e-6, atol=1e-6) - funcsSens=dict() + handler.root_add_dict("funcs_base", funcs, rtol=1e-6, atol=1e-6) + funcsSens = dict() DVCon.evalFunctionsSens(funcsSens, includeLinear=True) # regress the derivatives - handler.root_add_dict('derivs_base', funcsSens, rtol=1e-6, atol=1e-6) + handler.root_add_dict("derivs_base", funcsSens, rtol=1e-6, atol=1e-6) # FD check DVGeo1 funcsSensFD = self.evalFunctionsSensFD(DVGeo1, DVCon, fdstep=1e-3) @@ -869,10 +958,9 @@ def twist(val, geo): for inkey in DVGeo1.getValues().keys(): analytic = funcsSens[outkey][inkey] fd = funcsSensFD[outkey][inkey] - handler.assert_allclose(analytic, fd, - name='finite_diff_check', rtol=1e-3, atol=1e-3) + handler.assert_allclose(analytic, fd, name="finite_diff_check", rtol=1e-3, atol=1e-3) # make sure there are actually checks happening - self.assertTrue(np.abs(np.sum(fd))>1e-10) + self.assertTrue(np.abs(np.sum(fd)) > 1e-10) at_least_one_var = True self.assertTrue(at_least_one_var) @@ -883,9 +971,8 @@ def twist(val, geo): for inkey in DVGeo2.getValues().keys(): analytic = funcsSens[outkey][inkey] fd = funcsSensFD[outkey][inkey] - handler.assert_allclose(analytic, fd, - name='finite_diff_check', rtol=1e-3, atol=1e-3) - self.assertTrue(np.abs(np.sum(fd))>1e-10) + handler.assert_allclose(analytic, fd, name="finite_diff_check", rtol=1e-3, atol=1e-3) + self.assertTrue(np.abs(np.sum(fd)) > 1e-10) at_least_one_var = True self.assertTrue(at_least_one_var) @@ -893,32 +980,32 @@ def test_18(self, train=False, refDeriv=False): """ Test 18: Triangulated volume constraint, rectangle """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_18.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_18.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 18: Triangulated volume constraint, rectangle") DVGeo, DVCon = self.generate_dvgeo_dvcon_rect(addToDVGeo=True) - DVCon.addTriangulatedVolumeConstraint(scaled=False, name='unscaled_vol_con') + DVCon.addTriangulatedVolumeConstraint(scaled=False, name="unscaled_vol_con") DVCon.addTriangulatedVolumeConstraint(scaled=True) funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler) # check that unscaled thicknesses are being computed correctly at baseline - handler.assert_allclose(funcs['DVCon1_trivolume_constraint_1'], 1.0, - name='scaled_volume_base', rtol=1e-7, atol=1e-7) - handler.assert_allclose(funcs['unscaled_vol_con'], 16.0, - name='unscaled_volume_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_trivolume_constraint_1"], 1.0, name="scaled_volume_base", rtol=1e-7, atol=1e-7 + ) + handler.assert_allclose(funcs["unscaled_vol_con"], 16.0, name="unscaled_volume_base", rtol=1e-7, atol=1e-7) def test_19(self, train=False, refDeriv=False): """ Test 19: Triangulated volume constraint, bwb """ - refFile = os.path.join(self.base_path,'ref/test_DVConstraints_19.ref') + refFile = os.path.join(self.base_path, "ref/test_DVConstraints_19.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 17: Triangulated surface constraint, bwb") - meshfile = os.path.join(self.base_path, '../inputFiles/bwb.stl') - ffdfile = os.path.join(self.base_path, '../inputFiles/bwb.xyz') + meshfile = os.path.join(self.base_path, "../inputFiles/bwb.stl") + ffdfile = os.path.join(self.base_path, "../inputFiles/bwb.xyz") testmesh = mesh.Mesh.from_file(meshfile) # test mesh dim 0 is triangle index # dim 1 is each vertex of the triangle @@ -928,39 +1015,43 @@ def test_19(self, train=False, refDeriv=False): DVGeo1 = DVGeometry(ffdfile) nRefAxPts = DVGeo1.addRefAxis("wing", xFraction=0.25, alignIndex="k") self.nTwist = nRefAxPts - 1 + def twist(val, geo): for i in range(1, nRefAxPts): geo.rot_z["wing"].coef[i] = val[i - 1] + DVGeo1.addGeoDVGlobal(dvName="twist", value=[0] * self.nTwist, func=twist, lower=-10, upper=10, scale=1) DVGeo1.addGeoDVLocal("local", lower=-0.5, upper=0.5, axis="y", scale=1) # create a DVConstraints object for the wing - DVCon =DVConstraints() + DVCon = DVConstraints() DVCon.setDVGeo(DVGeo1) - p0 = testmesh.vectors[:,0,:] - v1 = testmesh.vectors[:,1,:] - p0 - v2 = testmesh.vectors[:,2,:] - p0 + p0 = testmesh.vectors[:, 0, :] + v1 = testmesh.vectors[:, 1, :] - p0 + v2 = testmesh.vectors[:, 2, :] - p0 DVCon.setSurface([p0, v1, v2], addToDVGeo=True) - DVCon.addTriangulatedVolumeConstraint(scaled=False, name='unscaled_vol_con') + DVCon.addTriangulatedVolumeConstraint(scaled=False, name="unscaled_vol_con") DVCon.addTriangulatedVolumeConstraint(scaled=True) funcs = dict() DVCon.evalFunctions(funcs, includeLinear=True) - handler.root_add_dict('funcs_base', funcs, rtol=1e-6, atol=1e-6) + handler.root_add_dict("funcs_base", funcs, rtol=1e-6, atol=1e-6) - handler.assert_allclose(funcs['DVCon1_trivolume_constraint_1'], 1.0, - name='scaled_volume_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["DVCon1_trivolume_constraint_1"], 1.0, name="scaled_volume_base", rtol=1e-7, atol=1e-7 + ) # BWB volume computed with meshmixer - handler.assert_allclose(funcs['unscaled_vol_con'], 1103.57, - name='unscaled_volume_base', rtol=1e-7, atol=1e-7) + handler.assert_allclose( + funcs["unscaled_vol_con"], 1103.57, name="unscaled_volume_base", rtol=1e-7, atol=1e-7 + ) - funcsSens=dict() + funcsSens = dict() DVCon.evalFunctionsSens(funcsSens, includeLinear=True) # regress the derivatives - handler.root_add_dict('derivs_base', funcsSens, rtol=1e-6, atol=1e-6) + handler.root_add_dict("derivs_base", funcsSens, rtol=1e-6, atol=1e-6) # FD check DVGeo1 funcsSensFD = self.evalFunctionsSensFD(DVGeo1, DVCon, fdstep=1e-6) @@ -969,18 +1060,15 @@ def twist(val, geo): for inkey in DVGeo1.getValues().keys(): analytic = funcsSens[outkey][inkey] fd = funcsSensFD[outkey][inkey] - handler.assert_allclose(analytic, fd, - name='finite_diff_check', rtol=1e-5, atol=1e-5) + handler.assert_allclose(analytic, fd, name="finite_diff_check", rtol=1e-5, atol=1e-5) # make sure there are actually checks happening - self.assertTrue(np.sum(np.abs(fd))>1e-10) + self.assertTrue(np.sum(np.abs(fd)) > 1e-10) at_least_one_var = True self.assertTrue(at_least_one_var) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() - #import xmlrunner - #unittest.main(testRunner=xmlrunner.XMLTestRunner(output='test-reports')) - - + # import xmlrunner + # unittest.main(testRunner=xmlrunner.XMLTestRunner(output='test-reports')) diff --git a/tests/reg_tests/test_DVGeometry.py b/tests/reg_tests/test_DVGeometry.py index 41f30656..7023008b 100644 --- a/tests/reg_tests/test_DVGeometry.py +++ b/tests/reg_tests/test_DVGeometry.py @@ -26,14 +26,13 @@ def test_1(self, train=False, refDeriv=False): """ Test 1: Basic FFD, global DVs """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_01.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_01.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 1: Basic FFD, global DVs") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path) - #create global DVs on the parent - DVGeo.addGeoDVGlobal('mainX', -1.0, commonUtils.mainAxisPoints, - lower=-1., upper=0., scale=1.0) - + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path) + # create global DVs on the parent + DVGeo.addGeoDVGlobal("mainX", -1.0, commonUtils.mainAxisPoints, lower=-1.0, upper=0.0, scale=1.0) + commonUtils.testSensitivities(DVGeo, refDeriv, handler) def train_2(self, train=True, refDeriv=True): @@ -43,22 +42,20 @@ def test_2(self, train=False, refDeriv=False): """ Test 2: Basic FFD, global DVs and local DVs """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_02.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_02.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 2: Basic FFD, global DVs and local DVs") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path) - #create global DVs on the parent - DVGeo.addGeoDVGlobal('mainX', -1.0, commonUtils.mainAxisPoints, - lower=-1., upper=0., scale=1.0) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) + # create global DVs on the parent + DVGeo.addGeoDVGlobal("mainX", -1.0, commonUtils.mainAxisPoints, lower=-1.0, upper=0.0, scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) commonUtils.testSensitivities(DVGeo, refDeriv, handler) - def train_3(self, train=True, refDeriv=True): self.test_3(train=train, refDeriv=refDeriv) @@ -66,22 +63,19 @@ def test_3(self, train=False, refDeriv=False): """ Test 3: Basic + Nested FFD, global DVs only """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_03.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_03.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 3: Basic + Nested FFD, global DVs only") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path) - - #create global DVs on the parent - DVGeo.addGeoDVGlobal('mainX', -1.0, commonUtils.mainAxisPoints, - lower=-1., upper=0., scale=1.0) - #create global DVs on the child - DVGeoChild.addGeoDVGlobal('nestedX', -0.5, commonUtils.childAxisPoints, - lower=-1., upper=0., scale=1.0) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path) + + # create global DVs on the parent + DVGeo.addGeoDVGlobal("mainX", -1.0, commonUtils.mainAxisPoints, lower=-1.0, upper=0.0, scale=1.0) + # create global DVs on the child + DVGeoChild.addGeoDVGlobal("nestedX", -0.5, commonUtils.childAxisPoints, lower=-1.0, upper=0.0, scale=1.0) DVGeo.addChild(DVGeoChild) commonUtils.testSensitivities(DVGeo, refDeriv, handler) - def train_4(self, train=True, refDeriv=True): self.test_4(train=train, refDeriv=refDeriv) @@ -89,27 +83,23 @@ def test_4(self, train=False, refDeriv=False): """ Test 4: Basic + Nested FFD, global DVs and local DVs on parent global on child """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_04.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_04.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 4: Basic + Nested FFD, global DVs and local DVs on parent global on child") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path) - - #create global DVs on the parent - DVGeo.addGeoDVGlobal('mainX', -1.0, commonUtils.mainAxisPoints, - lower=-1., upper=0., scale=1.0) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) - - #create global DVs on the child - DVGeoChild.addGeoDVGlobal('nestedX', -0.5, commonUtils.childAxisPoints, - lower=-1., upper=0., scale=1.0) - DVGeo.addChild(DVGeoChild) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path) - commonUtils.testSensitivities(DVGeo, refDeriv, handler) + # create global DVs on the parent + DVGeo.addGeoDVGlobal("mainX", -1.0, commonUtils.mainAxisPoints, lower=-1.0, upper=0.0, scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) + # create global DVs on the child + DVGeoChild.addGeoDVGlobal("nestedX", -0.5, commonUtils.childAxisPoints, lower=-1.0, upper=0.0, scale=1.0) + DVGeo.addChild(DVGeoChild) + commonUtils.testSensitivities(DVGeo, refDeriv, handler) def train_5(self, train=True, refDeriv=True): self.test_5(train=train, refDeriv=refDeriv) @@ -118,30 +108,27 @@ def test_5(self, train=False, refDeriv=False): """ Test 5: Basic + Nested FFD, global DVs and local DVs on both parent and child """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_05.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_05.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 5: Basic + Nested FFD, global DVs and local DVs on both parent and child") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path) - - #create global DVs on the parent - DVGeo.addGeoDVGlobal('mainX', -1.0, commonUtils.mainAxisPoints, - lower=-1., upper=0., scale=1.0) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) - #create global DVs on the child - DVGeoChild.addGeoDVGlobal('nestedX', -0.5, commonUtils.childAxisPoints, - lower=-1., upper=0., scale=1.0) - DVGeoChild.addGeoDVLocal('childxdir', lower=-1.1, upper=1.1, axis='x', scale=1.0) - DVGeoChild.addGeoDVLocal('childydir', lower=-1.1, upper=1.1, axis='y', scale=1.0) - DVGeoChild.addGeoDVLocal('childzdir', lower=-1.1, upper=1.1, axis='z', scale=1.0) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path) + + # create global DVs on the parent + DVGeo.addGeoDVGlobal("mainX", -1.0, commonUtils.mainAxisPoints, lower=-1.0, upper=0.0, scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) + # create global DVs on the child + DVGeoChild.addGeoDVGlobal("nestedX", -0.5, commonUtils.childAxisPoints, lower=-1.0, upper=0.0, scale=1.0) + DVGeoChild.addGeoDVLocal("childxdir", lower=-1.1, upper=1.1, axis="x", scale=1.0) + DVGeoChild.addGeoDVLocal("childydir", lower=-1.1, upper=1.1, axis="y", scale=1.0) + DVGeoChild.addGeoDVLocal("childzdir", lower=-1.1, upper=1.1, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) commonUtils.testSensitivities(DVGeo, refDeriv, handler) - def train_6(self, train=True, refDeriv=True): self.test_6(train=train, refDeriv=refDeriv) @@ -149,25 +136,24 @@ def test_6(self, train=False, refDeriv=False): """ Test 6: Basic + Nested FFD, local DVs only """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_06.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_06.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 6: Basic + Nested FFD, local DVs only") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) - DVGeoChild.addGeoDVLocal('childxdir', lower=-1.1, upper=1.1, axis='x', scale=1.0) - DVGeoChild.addGeoDVLocal('childydir', lower=-1.1, upper=1.1, axis='y', scale=1.0) - DVGeoChild.addGeoDVLocal('childzdir', lower=-1.1, upper=1.1, axis='z', scale=1.0) + DVGeoChild.addGeoDVLocal("childxdir", lower=-1.1, upper=1.1, axis="x", scale=1.0) + DVGeoChild.addGeoDVLocal("childydir", lower=-1.1, upper=1.1, axis="y", scale=1.0) + DVGeoChild.addGeoDVLocal("childzdir", lower=-1.1, upper=1.1, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) commonUtils.testSensitivities(DVGeo, refDeriv, handler) - def train_7(self, train=True, refDeriv=True): self.test_7(train=train, refDeriv=refDeriv) @@ -175,15 +161,15 @@ def test_7(self, train=False, refDeriv=False): """ Test 7: Basic + Nested FFD, local DVs only on parent """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_07.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_07.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 7: Basic + Nested FFD, local DVs only on parent") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) @@ -196,20 +182,19 @@ def test_8(self, train=False, refDeriv=False): """ Test 8: Basic + Nested FFD, local DVs only on child """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_08.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_08.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 8: Basic + Nested FFD, local DVs only on child") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path) - DVGeoChild.addGeoDVLocal('childxdir', lower=-1.1, upper=1.1, axis='x', scale=1.0) - DVGeoChild.addGeoDVLocal('childydir', lower=-1.1, upper=1.1, axis='y', scale=1.0) - DVGeoChild.addGeoDVLocal('childzdir', lower=-1.1, upper=1.1, axis='z', scale=1.0) + DVGeoChild.addGeoDVLocal("childxdir", lower=-1.1, upper=1.1, axis="x", scale=1.0) + DVGeoChild.addGeoDVLocal("childydir", lower=-1.1, upper=1.1, axis="y", scale=1.0) + DVGeoChild.addGeoDVLocal("childzdir", lower=-1.1, upper=1.1, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) commonUtils.testSensitivities(DVGeo, refDeriv, handler) - def train_9(self, train=True, refDeriv=True): self.test_9(train=train, refDeriv=refDeriv) @@ -217,24 +202,22 @@ def test_9(self, train=False, refDeriv=False): """ Test 9: Basic + Nested FFD, local DVs only on parent, global on child """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_09.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_09.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 9: Basic + Nested FFD, local DVs only on parent, global on child") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) - DVGeoChild.addGeoDVGlobal('nestedX', -0.5, commonUtils.childAxisPoints, - lower=-1., upper=0., scale=1.0) + DVGeoChild.addGeoDVGlobal("nestedX", -0.5, commonUtils.childAxisPoints, lower=-1.0, upper=0.0, scale=1.0) DVGeo.addChild(DVGeoChild) commonUtils.testSensitivities(DVGeo, refDeriv, handler) - def train_10(self, train=True, refDeriv=True): self.test_10(train=train, refDeriv=refDeriv) @@ -242,21 +225,20 @@ def test_10(self, train=False, refDeriv=False): """ Test 10: Basic + Nested FFD, local DVs only on parent, global and local on child """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_10.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_10.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 10: Basic + Nested FFD, local DVs only on parent, global and local on child") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) - DVGeoChild.addGeoDVGlobal('nestedX', -0.5, commonUtils.childAxisPoints, - lower=-1., upper=0., scale=1.0) - DVGeoChild.addGeoDVLocal('childxdir', lower=-1.1, upper=1.1, axis='x', scale=1.0) - DVGeoChild.addGeoDVLocal('childydir', lower=-1.1, upper=1.1, axis='y', scale=1.0) - DVGeoChild.addGeoDVLocal('childzdir', lower=-1.1, upper=1.1, axis='z', scale=1.0) + DVGeoChild.addGeoDVGlobal("nestedX", -0.5, commonUtils.childAxisPoints, lower=-1.0, upper=0.0, scale=1.0) + DVGeoChild.addGeoDVLocal("childxdir", lower=-1.1, upper=1.1, axis="x", scale=1.0) + DVGeoChild.addGeoDVLocal("childydir", lower=-1.1, upper=1.1, axis="y", scale=1.0) + DVGeoChild.addGeoDVLocal("childzdir", lower=-1.1, upper=1.1, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) @@ -266,21 +248,20 @@ def test_10_rot0(self, train=False, refDeriv=False): """ Test 10: Basic + Nested FFD, local DVs only on parent, global and local on child """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_10.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_10.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 10: Basic + Nested FFD, local DVs only on parent, global and local on child") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path, rotType=0) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path, rotType=0) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) - DVGeoChild.addGeoDVGlobal('nestedX', -0.5, commonUtils.childAxisPoints, - lower=-1., upper=0., scale=1.0) - DVGeoChild.addGeoDVLocal('childxdir', lower=-1.1, upper=1.1, axis='x', scale=1.0) - DVGeoChild.addGeoDVLocal('childydir', lower=-1.1, upper=1.1, axis='y', scale=1.0) - DVGeoChild.addGeoDVLocal('childzdir', lower=-1.1, upper=1.1, axis='z', scale=1.0) + DVGeoChild.addGeoDVGlobal("nestedX", -0.5, commonUtils.childAxisPoints, lower=-1.0, upper=0.0, scale=1.0) + DVGeoChild.addGeoDVLocal("childxdir", lower=-1.1, upper=1.1, axis="x", scale=1.0) + DVGeoChild.addGeoDVLocal("childydir", lower=-1.1, upper=1.1, axis="y", scale=1.0) + DVGeoChild.addGeoDVLocal("childzdir", lower=-1.1, upper=1.1, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) @@ -290,27 +271,25 @@ def test_10_rot7(self, train=False, refDeriv=False): """ Test 10: Basic + Nested FFD, local DVs only on parent, global and local on child """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_10.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_10.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 10: Basic + Nested FFD, local DVs only on parent, global and local on child") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path, rotType=7) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path, rotType=7) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) - DVGeoChild.addGeoDVGlobal('nestedX', -0.5, commonUtils.childAxisPoints, - lower=-1., upper=0., scale=1.0) - DVGeoChild.addGeoDVLocal('childxdir', lower=-1.1, upper=1.1, axis='x', scale=1.0) - DVGeoChild.addGeoDVLocal('childydir', lower=-1.1, upper=1.1, axis='y', scale=1.0) - DVGeoChild.addGeoDVLocal('childzdir', lower=-1.1, upper=1.1, axis='z', scale=1.0) + DVGeoChild.addGeoDVGlobal("nestedX", -0.5, commonUtils.childAxisPoints, lower=-1.0, upper=0.0, scale=1.0) + DVGeoChild.addGeoDVLocal("childxdir", lower=-1.1, upper=1.1, axis="x", scale=1.0) + DVGeoChild.addGeoDVLocal("childydir", lower=-1.1, upper=1.1, axis="y", scale=1.0) + DVGeoChild.addGeoDVLocal("childzdir", lower=-1.1, upper=1.1, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) commonUtils.testSensitivities(DVGeo, refDeriv, handler) - def train_11(self, train=True, refDeriv=True): self.test_11(train=train, refDeriv=refDeriv) @@ -318,23 +297,22 @@ def test_11(self, train=False, refDeriv=False): """ Test 11: Basic + Nested FFD, global DVs and local DVs on parent local on child """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_11.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_11.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 11: Basic + Nested FFD, global DVs and local DVs on parent local on child") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path) - #create global DVs on the parent - DVGeo.addGeoDVGlobal('mainX', -1.0, commonUtils.mainAxisPoints, - lower=-1., upper=0., scale=1.0) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) + # create global DVs on the parent + DVGeo.addGeoDVGlobal("mainX", -1.0, commonUtils.mainAxisPoints, lower=-1.0, upper=0.0, scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) - #create global DVs on the child - DVGeoChild.addGeoDVLocal('childxdir', lower=-1.1, upper=1.1, axis='x', scale=1.0) - DVGeoChild.addGeoDVLocal('childydir', lower=-1.1, upper=1.1, axis='y', scale=1.0) - DVGeoChild.addGeoDVLocal('childzdir', lower=-1.1, upper=1.1, axis='z', scale=1.0) + # create global DVs on the child + DVGeoChild.addGeoDVLocal("childxdir", lower=-1.1, upper=1.1, axis="x", scale=1.0) + DVGeoChild.addGeoDVLocal("childydir", lower=-1.1, upper=1.1, axis="y", scale=1.0) + DVGeoChild.addGeoDVLocal("childzdir", lower=-1.1, upper=1.1, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) @@ -344,23 +322,24 @@ def test_11_rot0(self, train=False, refDeriv=False): """ Test 11: Basic + Nested FFD, global DVs and local DVs on parent local on child """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_11.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_11.ref") with BaseRegTest(refFile, train=train) as handler: - handler.root_print("Test 11: Basic + Nested FFD, global DVs and local DVs on parent local on child, using rotType=0") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path,rotType=0) - - #create global DVs on the parent - DVGeo.addGeoDVGlobal('mainX', -1.0, commonUtils.mainAxisPoints, - lower=-1., upper=0., scale=1.0) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) - - #create global DVs on the child - DVGeoChild.addGeoDVLocal('childxdir', lower=-1.1, upper=1.1, axis='x', scale=1.0) - DVGeoChild.addGeoDVLocal('childydir', lower=-1.1, upper=1.1, axis='y', scale=1.0) - DVGeoChild.addGeoDVLocal('childzdir', lower=-1.1, upper=1.1, axis='z', scale=1.0) + handler.root_print( + "Test 11: Basic + Nested FFD, global DVs and local DVs on parent local on child, using rotType=0" + ) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path, rotType=0) + + # create global DVs on the parent + DVGeo.addGeoDVGlobal("mainX", -1.0, commonUtils.mainAxisPoints, lower=-1.0, upper=0.0, scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) + + # create global DVs on the child + DVGeoChild.addGeoDVLocal("childxdir", lower=-1.1, upper=1.1, axis="x", scale=1.0) + DVGeoChild.addGeoDVLocal("childydir", lower=-1.1, upper=1.1, axis="y", scale=1.0) + DVGeoChild.addGeoDVLocal("childzdir", lower=-1.1, upper=1.1, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) @@ -370,31 +349,32 @@ def test_11_rot7(self, train=False, refDeriv=False): """ Test 11: Basic + Nested FFD, global DVs and local DVs on parent local on child """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_11.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_11.ref") with BaseRegTest(refFile, train=train) as handler: - handler.root_print("Test 11: Basic + Nested FFD, global DVs and local DVs on parent local on child, using rotType=7") - DVGeo,DVGeoChild = commonUtils.setupDVGeo(self.base_path,rotType=7) - - #create global DVs on the parent - DVGeo.addGeoDVGlobal('mainX', -1.0, commonUtils.mainAxisPoints, - lower=-1., upper=0., scale=1.0) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) - - #create global DVs on the child - DVGeoChild.addGeoDVLocal('childxdir', lower=-1.1, upper=1.1, axis='x', scale=1.0) - DVGeoChild.addGeoDVLocal('childydir', lower=-1.1, upper=1.1, axis='y', scale=1.0) - DVGeoChild.addGeoDVLocal('childzdir', lower=-1.1, upper=1.1, axis='z', scale=1.0) + handler.root_print( + "Test 11: Basic + Nested FFD, global DVs and local DVs on parent local on child, using rotType=7" + ) + DVGeo, DVGeoChild = commonUtils.setupDVGeo(self.base_path, rotType=7) + + # create global DVs on the parent + DVGeo.addGeoDVGlobal("mainX", -1.0, commonUtils.mainAxisPoints, lower=-1.0, upper=0.0, scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) + + # create global DVs on the child + DVGeoChild.addGeoDVLocal("childxdir", lower=-1.1, upper=1.1, axis="x", scale=1.0) + DVGeoChild.addGeoDVLocal("childydir", lower=-1.1, upper=1.1, axis="y", scale=1.0) + DVGeoChild.addGeoDVLocal("childzdir", lower=-1.1, upper=1.1, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) commonUtils.testSensitivities(DVGeo, refDeriv, handler) -# ------------------- -# D8 Tests -# ------------------- + # ------------------- + # D8 Tests + # ------------------- def train_12(self, train=True, refDeriv=True): self.test_12(train=train, refDeriv=refDeriv) @@ -402,23 +382,22 @@ def test_12(self, train=False, refDeriv=False): """ Test 12: D8 FFD, global DVs """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_12.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_12.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 12: D8 FFD, global DVs") - DVGeo,DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) + DVGeo, DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) - #create global DVs on the parent - axisX = [0.,26.,30.5,32.5, 34.0] - DVGeo.addGeoDVGlobal('mainX', axisX , commonUtils.mainAxisPoints, - lower=0., upper=35., scale=1.0) + # create global DVs on the parent + axisX = [0.0, 26.0, 30.5, 32.5, 34.0] + DVGeo.addGeoDVGlobal("mainX", axisX, commonUtils.mainAxisPoints, lower=0.0, upper=35.0, scale=1.0) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - + handler.root_print("Test 12b: D8 FFD, random DV perturbation on test 10") xDV = DVGeo.getValues() for key in xDV: numpy.random.seed(42) - xDV[key]+=numpy.random.rand(len(xDV[key])) + xDV[key] += numpy.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) @@ -430,34 +409,31 @@ def test_13(self, train=False, refDeriv=False): """ Test 13: D8 FFD, global DVs and local DVs """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_13.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_13.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 13: D8 FFD, global DVs and local DVs") - DVGeo,DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) + DVGeo, DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) - #create global DVs on the parent - axisX = [0.,26.,30.5,32.5, 34.0] - DVGeo.addGeoDVGlobal('mainX', axisX , commonUtils.mainAxisPoints, - lower=0., upper=35., scale=1.0) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) + # create global DVs on the parent + axisX = [0.0, 26.0, 30.5, 32.5, 34.0] + DVGeo.addGeoDVGlobal("mainX", axisX, commonUtils.mainAxisPoints, lower=0.0, upper=35.0, scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - + handler.root_print("Test 13b: D8 FFD, random DV perturbation on test 11") xDV = DVGeo.getValues() - + for key in xDV: numpy.random.seed(42) - xDV[key]+=numpy.random.rand(len(xDV[key])) - + xDV[key] += numpy.random.rand(len(xDV[key])) + DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - - def train_14(self, train=True, refDeriv=True): self.test_14(train=train, refDeriv=refDeriv) @@ -465,32 +441,31 @@ def test_14(self, train=False, refDeriv=False): """ Test 14 """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_14.ref') - with BaseRegTest(refFile, train=train) as handler: + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_14.ref") + with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 14: D8 + Nozzle FFD, global DVs only") - DVGeo,DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) + DVGeo, DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) - #create global DVs on the parent - axisX = [0.,26.,30.5,32.5, 34.0] - DVGeo.addGeoDVGlobal('mainX', axisX , commonUtils.mainAxisPointsD8, - lower=0., upper=35., scale=1.0) - #create global DVs on the child + # create global DVs on the parent + axisX = [0.0, 26.0, 30.5, 32.5, 34.0] + DVGeo.addGeoDVGlobal("mainX", axisX, commonUtils.mainAxisPointsD8, lower=0.0, upper=35.0, scale=1.0) + # create global DVs on the child childAxisX = [32.4, 34] - DVGeoChild.addGeoDVGlobal('nestedX',childAxisX, commonUtils.childAxisPointsD8, - lower=0., upper=35., scale=1.0) + DVGeoChild.addGeoDVGlobal( + "nestedX", childAxisX, commonUtils.childAxisPointsD8, lower=0.0, upper=35.0, scale=1.0 + ) DVGeo.addChild(DVGeoChild) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - + handler.root_print("Test 14b: D8 + Nozzle FFD, random DV perturbation on test 12") xDV = DVGeo.getValues() for key in xDV: numpy.random.seed(42) - xDV[key]+=numpy.random.rand(len(xDV[key])) + xDV[key] += numpy.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - def train_15(self, train=True, refDeriv=True): self.test_15(train=train, refDeriv=refDeriv) @@ -499,38 +474,37 @@ def test_15(self, train=False, refDeriv=False): """ Test 15 """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_15.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_15.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 15: D8 + Nozzle FFD, global DVs and local DVs on parent global on child") - DVGeo,DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) - - #create global DVs on the parent - axisX = [0.,26.,30.5,32.5, 34.0] - DVGeo.addGeoDVGlobal('mainX', axisX , commonUtils.mainAxisPoints, - lower=0., upper=35., scale=1.0) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) - - #create global DVs on the child + DVGeo, DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) + + # create global DVs on the parent + axisX = [0.0, 26.0, 30.5, 32.5, 34.0] + DVGeo.addGeoDVGlobal("mainX", axisX, commonUtils.mainAxisPoints, lower=0.0, upper=35.0, scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) + + # create global DVs on the child childAxisX = [32.4, 34] - DVGeoChild.addGeoDVGlobal('nestedX',childAxisX, commonUtils.childAxisPoints, - lower=0., upper=35., scale=1.0) + DVGeoChild.addGeoDVGlobal( + "nestedX", childAxisX, commonUtils.childAxisPoints, lower=0.0, upper=35.0, scale=1.0 + ) DVGeo.addChild(DVGeoChild) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - + handler.root_print("Test 15b: D8 + Nozzle FFD, random DV perturbation on test 13") xDV = DVGeo.getValues() for key in xDV: numpy.random.seed(42) - xDV[key]+=numpy.random.rand(len(xDV[key])) + xDV[key] += numpy.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - def train_16(self, train=True, refDeriv=True): self.test_16(train=train, refDeriv=refDeriv) @@ -538,36 +512,36 @@ def test_16(self, train=False, refDeriv=False): """ Test 16 """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_16.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_16.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 16: D8 + Nozzle FFD, global DVs and local DVs on both parent and child") - DVGeo,DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) - - #create global DVs on the parent - axisX = [0.,26.,30.5,32.5, 34.0] - DVGeo.addGeoDVGlobal('mainX', axisX , commonUtils.mainAxisPoints, - lower=0., upper=35., scale=1.0) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) - #create global DVs on the child + DVGeo, DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) + + # create global DVs on the parent + axisX = [0.0, 26.0, 30.5, 32.5, 34.0] + DVGeo.addGeoDVGlobal("mainX", axisX, commonUtils.mainAxisPoints, lower=0.0, upper=35.0, scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) + # create global DVs on the child childAxisX = [32.4, 34] - DVGeoChild.addGeoDVGlobal('nestedX',childAxisX, commonUtils.childAxisPoints, - lower=0., upper=35., scale=1.0) - DVGeoChild.addGeoDVLocal('childxdir', lower=-1.1, upper=1.1, axis='x', scale=1.0) - DVGeoChild.addGeoDVLocal('childydir', lower=-1.1, upper=1.1, axis='y', scale=1.0) - DVGeoChild.addGeoDVLocal('childzdir', lower=-1.1, upper=1.1, axis='z', scale=1.0) + DVGeoChild.addGeoDVGlobal( + "nestedX", childAxisX, commonUtils.childAxisPoints, lower=0.0, upper=35.0, scale=1.0 + ) + DVGeoChild.addGeoDVLocal("childxdir", lower=-1.1, upper=1.1, axis="x", scale=1.0) + DVGeoChild.addGeoDVLocal("childydir", lower=-1.1, upper=1.1, axis="y", scale=1.0) + DVGeoChild.addGeoDVLocal("childzdir", lower=-1.1, upper=1.1, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - + handler.root_print("Test 14b: D8 + Nozzle FFD, random DV perturbation on test 14") xDV = DVGeo.getValues() for key in xDV: numpy.random.seed(42) - xDV[key]+=numpy.random.rand(len(xDV[key])) + xDV[key] += numpy.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) @@ -579,35 +553,33 @@ def test_17(self, train=False, refDeriv=False): """ Test 17 """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_17.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_17.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 17: D8 + Nozzle FFD, local DVs only") - DVGeo,DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) + DVGeo, DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) - DVGeoChild.addGeoDVLocal('childxdir', lower=-1.1, upper=1.1, axis='x', scale=1.0) - DVGeoChild.addGeoDVLocal('childydir', lower=-1.1, upper=1.1, axis='y', scale=1.0) - DVGeoChild.addGeoDVLocal('childzdir', lower=-1.1, upper=1.1, axis='z', scale=1.0) + DVGeoChild.addGeoDVLocal("childxdir", lower=-1.1, upper=1.1, axis="x", scale=1.0) + DVGeoChild.addGeoDVLocal("childydir", lower=-1.1, upper=1.1, axis="y", scale=1.0) + DVGeoChild.addGeoDVLocal("childzdir", lower=-1.1, upper=1.1, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - + handler.root_print("Test 17b: D8 + Nozzle FFD, random DV perturbationon test 15") xDV = DVGeo.getValues() for key in xDV: numpy.random.seed(42) - xDV[key]+=numpy.random.rand(len(xDV[key])) + xDV[key] += numpy.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - - def train_18(self, train=True, refDeriv=True): self.test_18(train=train, refDeriv=refDeriv) @@ -615,19 +587,20 @@ def test_18(self, train=False, refDeriv=False): """ Test 18 """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_18.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_18.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 18: D8 + Nozzle FFD, local DVs only on parent, global on child") - DVGeo,DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) + DVGeo, DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) childAxisX = [32.4, 34] - DVGeoChild.addGeoDVGlobal('nestedX',childAxisX, commonUtils.childAxisPoints, - lower=0., upper=35., scale=1.0) + DVGeoChild.addGeoDVGlobal( + "nestedX", childAxisX, commonUtils.childAxisPoints, lower=0.0, upper=35.0, scale=1.0 + ) DVGeo.addChild(DVGeoChild) @@ -637,12 +610,11 @@ def test_18(self, train=False, refDeriv=False): xDV = DVGeo.getValues() for key in xDV: numpy.random.seed(42) - xDV[key]+=numpy.random.rand(len(xDV[key])) + xDV[key] += numpy.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - def train_19(self, train=True, refDeriv=True): self.test_19(train=train, refDeriv=refDeriv) @@ -650,22 +622,23 @@ def test_19(self, train=False, refDeriv=False): """ Test 19 """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_19.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_19.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 19: D8 + Nozzle FFD, local DVs only on parent, global and local on child") - DVGeo,DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) + DVGeo, DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) childAxisX = [32.4, 34] - DVGeoChild.addGeoDVGlobal('nestedX',childAxisX, commonUtils.childAxisPoints, - lower=0., upper=35., scale=1.0) - DVGeoChild.addGeoDVLocal('childxdir', lower=-1.1, upper=1.1, axis='x', scale=1.0) - DVGeoChild.addGeoDVLocal('childydir', lower=-1.1, upper=1.1, axis='y', scale=1.0) - DVGeoChild.addGeoDVLocal('childzdir', lower=-1.1, upper=1.1, axis='z', scale=1.0) + DVGeoChild.addGeoDVGlobal( + "nestedX", childAxisX, commonUtils.childAxisPoints, lower=0.0, upper=35.0, scale=1.0 + ) + DVGeoChild.addGeoDVLocal("childxdir", lower=-1.1, upper=1.1, axis="x", scale=1.0) + DVGeoChild.addGeoDVLocal("childydir", lower=-1.1, upper=1.1, axis="y", scale=1.0) + DVGeoChild.addGeoDVLocal("childzdir", lower=-1.1, upper=1.1, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) @@ -675,12 +648,10 @@ def test_19(self, train=False, refDeriv=False): xDV = DVGeo.getValues() for key in xDV: numpy.random.seed(42) - xDV[key]+=numpy.random.rand(len(xDV[key])) + xDV[key] += numpy.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - - def train_20(self, train=True, refDeriv=True): self.test_20(train=train, refDeriv=refDeriv) @@ -689,39 +660,37 @@ def test_20(self, train=False, refDeriv=False): """ Test 20 """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_20.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_20.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 20: D8 + Nozzle FFD, global DVs and local DVs on parent local on child") - DVGeo,DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) - - #create global DVs on the parent - axisX = [0.,26.,30.5,32.5, 34.0] - DVGeo.addGeoDVGlobal('mainX', axisX , commonUtils.mainAxisPoints, - lower=0., upper=35., scale=1.0) - #create local DVs on the parent - DVGeo.addGeoDVLocal('xdir', lower=-1.0, upper=1.0, axis='x', scale=1.0) - DVGeo.addGeoDVLocal('ydir', lower=-1.0, upper=1.0, axis='y', scale=1.0) - DVGeo.addGeoDVLocal('zdir', lower=-1.0, upper=1.0, axis='z', scale=1.0) - - #create global DVs on the child - DVGeoChild.addGeoDVLocal('childxdir', lower=-1.1, upper=1.1, axis='x', scale=1.0) - DVGeoChild.addGeoDVLocal('childydir', lower=-1.1, upper=1.1, axis='y', scale=1.0) - DVGeoChild.addGeoDVLocal('childzdir', lower=-1.1, upper=1.1, axis='z', scale=1.0) + DVGeo, DVGeoChild = commonUtils.setupDVGeoD8(self.base_path, refDeriv) + + # create global DVs on the parent + axisX = [0.0, 26.0, 30.5, 32.5, 34.0] + DVGeo.addGeoDVGlobal("mainX", axisX, commonUtils.mainAxisPoints, lower=0.0, upper=35.0, scale=1.0) + # create local DVs on the parent + DVGeo.addGeoDVLocal("xdir", lower=-1.0, upper=1.0, axis="x", scale=1.0) + DVGeo.addGeoDVLocal("ydir", lower=-1.0, upper=1.0, axis="y", scale=1.0) + DVGeo.addGeoDVLocal("zdir", lower=-1.0, upper=1.0, axis="z", scale=1.0) + + # create global DVs on the child + DVGeoChild.addGeoDVLocal("childxdir", lower=-1.1, upper=1.1, axis="x", scale=1.0) + DVGeoChild.addGeoDVLocal("childydir", lower=-1.1, upper=1.1, axis="y", scale=1.0) + DVGeoChild.addGeoDVLocal("childzdir", lower=-1.1, upper=1.1, axis="z", scale=1.0) DVGeo.addChild(DVGeoChild) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - + handler.root_print("Test 20b: D8 + Nozzle FFD, random DV perturbationon test 18") xDV = DVGeo.getValues() for key in xDV: numpy.random.seed(42) - xDV[key]+=numpy.random.rand(len(xDV[key])) + xDV[key] += numpy.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) - def train_21(self, train=True, refDeriv=True): self.test_21(train=train, refDeriv=refDeriv) @@ -729,43 +698,47 @@ def test_21(self, train=False, refDeriv=False): """ Test 21 """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_21.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_21.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 21: Axisymmetric FFD, global and local DVs") - # Test with a single point along the 45 ` degree theta direction + # Test with a single point along the 45 ` degree theta direction DVGeo = commonUtils.setupDVGeoAxi(self.base_path) - - DVGeo.addGeoDVGlobal('mainAxis', numpy.zeros(1), commonUtils.mainAxisPointAxi) - DVGeo.addGeoDVLocal('x_axis', lower=-2, upper=2, axis="x") - DVGeo.addGeoDVLocal('z_axis', lower=-2, upper=2, axis="z") - DVGeo.addGeoDVLocal('y_axis', lower=-2, upper=2, axis="y") + DVGeo.addGeoDVGlobal("mainAxis", numpy.zeros(1), commonUtils.mainAxisPointAxi) + + DVGeo.addGeoDVLocal("x_axis", lower=-2, upper=2, axis="x") + DVGeo.addGeoDVLocal("z_axis", lower=-2, upper=2, axis="z") + DVGeo.addGeoDVLocal("y_axis", lower=-2, upper=2, axis="y") ptName = "point" - s_pts = numpy.array([[0, .5, .5],], dtype="float") + s_pts = numpy.array( + [ + [0, 0.5, 0.5], + ], + dtype="float", + ) DVGeo.addPointSet(points=s_pts, ptName=ptName) - # generate dIdPt + # generate dIdPt nPt = 3 - dIdPt = numpy.zeros([nPt,1,3]) - dIdPt[0,0,0] = 1.0 - dIdPt[1,0,1] = 1.0 - dIdPt[2,0,2] = 1.0 + dIdPt = numpy.zeros([nPt, 1, 3]) + dIdPt[0, 0, 0] = 1.0 + dIdPt[1, 0, 1] = 1.0 + dIdPt[2, 0, 2] = 1.0 if refDeriv: # Generate reference derivatives refPoints = DVGeo.update(ptName) - nPt = 3*refPoints.shape[0] + nPt = 3 * refPoints.shape[0] step = 1e-5 - J_fd = commonUtils.totalSensitivityFD(DVGeo,nPt,ptName,step) - handler.root_add_dict(J_fd,rtol=1e-7,atol=1e-7) + J_fd = commonUtils.totalSensitivityFD(DVGeo, nPt, ptName, step) + handler.root_add_dict(J_fd, rtol=1e-7, atol=1e-7) else: # Compute the analytic derivatives - dIdx = DVGeo.totalSensitivity(dIdPt,ptName) - handler.root_add_dict('dIdx',dIdx,rtol=1e-7,atol=1e-7) - + dIdx = DVGeo.totalSensitivity(dIdPt, ptName) + handler.root_add_dict("dIdx", dIdx, rtol=1e-7, atol=1e-7) def train_22(self, train=True, refDeriv=True): self.test_22(train=train, refDeriv=refDeriv) @@ -774,39 +747,37 @@ def test_22(self, train=False, refDeriv=False): """ Test 22 """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_22.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_22.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test FFD writing function") # Write duplicate of outerbox FFD - axes = ['i', 'k', 'j'] - slices = numpy.array([ - # Slice 1 - [[[-1, -1, -1], [-1, 1, -1]], - [[-1, -1, 1], [-1, 1, 1]]], - # Slice 2 - [[[1, -1, -1], [1, 1, -1]], - [[1, -1, 1], [1, 1, 1]]], - # Slice 3 - [[[2, -1, -1], [2, 1, -1]], - [[2, -1, 1], [2, 1, 1]]], - ]) - - N0 = [2,2] - N1 = [2,2] - N2 = [2,2] - - copyName = os.path.join(self.base_path,'../inputFiles/test1.xyz') + axes = ["i", "k", "j"] + slices = numpy.array( + [ + # Slice 1 + [[[-1, -1, -1], [-1, 1, -1]], [[-1, -1, 1], [-1, 1, 1]]], + # Slice 2 + [[[1, -1, -1], [1, 1, -1]], [[1, -1, 1], [1, 1, 1]]], + # Slice 3 + [[[2, -1, -1], [2, 1, -1]], [[2, -1, 1], [2, 1, 1]]], + ] + ) + + N0 = [2, 2] + N1 = [2, 2] + N2 = [2, 2] + + copyName = os.path.join(self.base_path, "../inputFiles/test1.xyz") geo_utils.write_wing_FFD_file(copyName, slices, N0, N1, N2, axes=axes) # Load original and duplicate - origFFD = DVGeometry(os.path.join(self.base_path,'../inputFiles/outerBoxFFD.xyz')) + origFFD = DVGeometry(os.path.join(self.base_path, "../inputFiles/outerBoxFFD.xyz")) copyFFD = DVGeometry(copyName) norm_diff = numpy.linalg.norm(origFFD.FFD.coef - copyFFD.FFD.coef) - handler.par_add_norm('norm', norm_diff, rtol=1e-7, atol=1e-7) + handler.par_add_norm("norm", norm_diff, rtol=1e-7, atol=1e-7) os.remove(copyName) - def test_spanwise_dvs(self, train=False, refDeriv=False): """ Test spanwise_dvs @@ -815,8 +786,8 @@ def test_spanwise_dvs(self, train=False, refDeriv=False): # with BaseRegTest(refFile, train=train) as handler: # handler.root_print("Test spanwise local variables writing function") - meshfile = os.path.join(self.base_path, '../inputFiles/c172.stl') - ffdfile = os.path.join(self.base_path, '../inputFiles/c172.xyz') + meshfile = os.path.join(self.base_path, "../inputFiles/c172.stl") + ffdfile = os.path.join(self.base_path, "../inputFiles/c172.xyz") testmesh = mesh.Mesh.from_file(meshfile) # test mesh dim 0 is triangle index # dim 1 is each vertex of the triangle @@ -824,21 +795,19 @@ def test_spanwise_dvs(self, train=False, refDeriv=False): # create a DVGeo object with a few local thickness variables DVGeo = DVGeometry(ffdfile) - DVGeo.addGeoDVSpanwiseLocal("shape", 'i', lower=-0.5, upper=0.5, axis="y", scale=1.0) - + DVGeo.addGeoDVSpanwiseLocal("shape", "i", lower=-0.5, upper=0.5, axis="y", scale=1.0) # create a DVConstraints object for the wing - DVCon =DVConstraints() + DVCon = DVConstraints() DVCon.setDVGeo(DVGeo) - p0 = testmesh.vectors[:,0,:] / 1000 - v1 = testmesh.vectors[:,1,:] / 1000 - p0 - v2 = testmesh.vectors[:,2,:] / 1000 - p0 + p0 = testmesh.vectors[:, 0, :] / 1000 + v1 = testmesh.vectors[:, 1, :] / 1000 - p0 + v2 = testmesh.vectors[:, 2, :] / 1000 - p0 DVCon.setSurface([p0, v1, v2]) + leList = [[0.7, 0.0, 0.1], [0.7, 0.0, 2.4]] + teList = [[0.9, 0.0, 0.1], [0.9, 0.0, 2.4]] - leList = [[0.7, 0.0, 0.1],[0.7, 0.0, 2.4]] - teList = [[0.9, 0.0, 0.1],[0.9, 0.0, 2.4]] - nSpan = 10 nChord = 10 name = "thickness_con" @@ -847,18 +816,16 @@ def test_spanwise_dvs(self, train=False, refDeriv=False): size = DVGeo._getNDVSpanwiseLocal() numpy.random.seed(0) - DVGeo.setDesignVars({'shape':(numpy.random.rand(size) - 0.5)}) - + DVGeo.setDesignVars({"shape": (numpy.random.rand(size) - 0.5)}) + funcs = {} DVCon.evalFunctions(funcs) # print(funcs) - + for i in range(nChord): - for j in range(nSpan-1): - numpy.testing.assert_allclose(funcs[name][i*nChord + j+1], funcs[name][i*nChord + j], rtol=2e-15) - + for j in range(nSpan - 1): + numpy.testing.assert_allclose(funcs[name][i * nChord + j + 1], funcs[name][i * nChord + j], rtol=2e-15) - def train_23_xyzFraction(self, train=True): self.test_23_xyzFraction(train=train) @@ -871,17 +838,17 @@ def test_23_xyzFraction(self, train=False): xFraction = 0.3, FFD x interval [-1,1] ---> 0.6 displacement from x min (% displ calculated from LE=xmin) --> x = -0.4 yFraction = 0.6, FFD y interval [-0.5,0.5] ---> 0.6 displacement from y max (% displ calculated from top of the box=ymax) --> x = -0.1 """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_23.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_23.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test generalized axis node location section in plane") - DVGeo = DVGeometry(os.path.join(self.base_path,'../inputFiles/2x1x8_rectangle.xyz')) + DVGeo = DVGeometry(os.path.join(self.base_path, "../inputFiles/2x1x8_rectangle.xyz")) xfraction = 0.3 yfraction = 0.6 rotType = 0 DVGeo.addRefAxis("RefAx", xFraction=xfraction, yFraction=yfraction, alignIndex="k", rotType=rotType) - nodes_loc = DVGeo.axis['RefAx']['curve'].X + nodes_loc = DVGeo.axis["RefAx"]["curve"].X - handler.root_add_val("RefAxis_nodes_coord",nodes_loc,rtol=1e-12,atol=1e-12) + handler.root_add_val("RefAxis_nodes_coord", nodes_loc, rtol=1e-12, atol=1e-12) def train_24_rot0_nonaligned(self, train=True, refDeriv=False): self.test_24_rot0_nonaligned(train=train, refDeriv=refDeriv) @@ -898,10 +865,10 @@ def test_24_rot0_nonaligned(self, train=False, refDeriv=False): The twist is added to ensure that the operation order is maintained, and the scaling preserves the orthogonality of the FFD in the section plane. This is a particular case as the FFD box is already aligned with the main axis and we "flip" the y and z axes, but the same criteria can be applied to a general rotation. """ - refFile = os.path.join(self.base_path,'ref/test_DVGeometry_24.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometry_24.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test twist and scaling for FFDs non-aligned to main system of reference") - DVGeo = DVGeometry(os.path.join(self.base_path,'../inputFiles/2x1x8_rectangle.xyz')) + DVGeo = DVGeometry(os.path.join(self.base_path, "../inputFiles/2x1x8_rectangle.xyz")) rotType = 0 xfraction = 0.5 nRefAxPts = DVGeo.addRefAxis("RefAx", xFraction=xfraction, alignIndex="k", rotType=rotType, rot0ang=-90) @@ -909,9 +876,15 @@ def test_24_rot0_nonaligned(self, train=False, refDeriv=False): fix_root_sect = 1 nTwist = nRefAxPts - fix_root_sect - DVGeo.addGeoDVGlobal(dvName="twist", value=[0] * nTwist, func=commonUtils.twist, lower=-90, upper=90, scale=1) - DVGeo.addGeoDVGlobal(dvName="thickness", value=[1.0] * nTwist, func=commonUtils.thickness, lower=0.7, upper=5., scale=1) - DVGeo.addGeoDVGlobal(dvName="chord", value=[1.0] * nTwist, func=commonUtils.chord, lower=0.7, upper=5., scale=1) + DVGeo.addGeoDVGlobal( + dvName="twist", value=[0] * nTwist, func=commonUtils.twist, lower=-90, upper=90, scale=1 + ) + DVGeo.addGeoDVGlobal( + dvName="thickness", value=[1.0] * nTwist, func=commonUtils.thickness, lower=0.7, upper=5.0, scale=1 + ) + DVGeo.addGeoDVGlobal( + dvName="chord", value=[1.0] * nTwist, func=commonUtils.chord, lower=0.7, upper=5.0, scale=1 + ) commonUtils.testSensitivities(DVGeo, refDeriv, handler, pointset=2) @@ -934,17 +907,14 @@ def test_24_rot0_nonaligned(self, train=False, refDeriv=False): DVGeo.setDesignVars(x) - DVGeo.update('testPoints') + DVGeo.update("testPoints") FFD_coords = DVGeo.FFD.coef.copy() - handler.root_add_val("Updated FFD coordinates",FFD_coords,rtol=1e-12,atol=1e-12) - + handler.root_add_val("Updated FFD coordinates", FFD_coords, rtol=1e-12, atol=1e-12) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() - #import xmlrunner - #unittest.main(testRunner=xmlrunner.XMLTestRunner(output='test-reports')) - - + # import xmlrunner + # unittest.main(testRunner=xmlrunner.XMLTestRunner(output='test-reports')) diff --git a/tests/reg_tests/test_DVGeometryESP.py b/tests/reg_tests/test_DVGeometryESP.py index fe1653b8..837fe5e9 100644 --- a/tests/reg_tests/test_DVGeometryESP.py +++ b/tests/reg_tests/test_DVGeometryESP.py @@ -5,7 +5,7 @@ from stl import mesh from baseclasses import BaseRegTest from parameterized import parameterized_class -import time +import time try: from mpi4py import MPI @@ -21,8 +21,8 @@ pyOCSM = None -test_params = [ {"N_PROCS": 1, "name":"serial"}, - {"N_PROCS": 4, "name":"parallel_4procs"}] +test_params = [{"N_PROCS": 1, "name": "serial"}, {"N_PROCS": 4, "name": "parallel_4procs"}] + @unittest.skipUnless(MPI and pyOCSM, "MPI and pyOCSM are required.") @parameterized_class(test_params) @@ -32,14 +32,14 @@ class TestPyGeoESP_BasicCube(unittest.TestCase): N_PROCS = 1 def setUp(self): - # Store the path where this current script lives + # Store the path where this current script lives # This all paths in the script are relative to this path # This is needed to support testflo running directories and files as inputs self.input_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - + def setup_cubemodel(self): # load the box model and build the box model - csmFile = os.path.join(self.input_path,'inputFiles/esp/box.csm') + csmFile = os.path.join(self.input_path, "inputFiles/esp/box.csm") DVGeo = DVGeometryESP(csmFile) self.assertIsNotNone(DVGeo) @@ -53,54 +53,78 @@ def setup_cubemodel(self): top = np.array([0.0, 0.1, 1.5]) bottom = np.array([-1.9, -1.1, -2.0]) initpts = np.vstack([vertex1, vertex2, left, right, front, back, top, bottom, left, right]) - distglobal = DVGeo.addPointSet(initpts, 'mypts', cache_projections=False) + distglobal = DVGeo.addPointSet(initpts, "mypts", cache_projections=False) self.assertAlmostEqual(distglobal, 0.0, 8) # evaluate the points and check that they match DVGeo._updateESPModel() DVGeo._updateProjectedPts() self.assertTrue(DVGeo.pointSetUpToDate) - self.assertAlmostEqual(np.linalg.norm(initpts - DVGeo.pointSets['mypts'].proj_pts), 0.0, 10) + self.assertAlmostEqual(np.linalg.norm(initpts - DVGeo.pointSets["mypts"].proj_pts), 0.0, 10) return DVGeo, initpts - + def setup_cubemodel_analytic_jac(self): - jacpt0 = np.array([[1., 0., 0., 0., 0., 0.], #x - [0., 1., 0., 0., 0., 0.], #y - [0., 0., 1., 0., 0., 0.]]) #z - jacpt1 = np.array([[1., 0., 0., 1., 0., 0.], #x - [0., 1., 0., 0., 1., 0.], #y - [0., 0., 1., 0., 0., 1.]]) #z - jacpt2 = np.array([[1., 0., 0., 0., 0., 0.], #x - [0., 1., 0., 0., 0.9 / 3.5, 0.], #y - [0., 0., 1., 0., 0., 0.9 / 3.5]]) #z - jacpt3 = np.array([[1., 0., 0., 1., 0., 0.], #x - [0., 1., 0., 0., 0.8 / 3.5, 0.], #y - [0., 0., 1., 0., 0., 1.9 / 3.5]]) #z - jacpt4 = np.array([[1., 0., 0., 2.25 / 3.50, 0., 0.], #x - [0., 1., 0., 0., 1., 0.], #y - [0., 0., 1., 0., 0., 2.30 / 3.50]]) #z - jacpt5 = np.array([[1., 0., 0., 3.20 / 3.50, 0., 0.], #x - [0., 1., 0., 0., 0., 0.], #y - [0., 0., 1., 0., 0., 1.70 / 3.50]]) #z - jacpt6 = np.array([[1., 0., 0., 2.0 / 3.5, 0., 0.], #x - [0., 1., 0., 0., 2.1 / 3.5, 0.], #y - [0., 0., 1., 0., 0., 1.]]) #z - jacpt7 = np.array([[1., 0., 0., 0.1 / 3.5, 0., 0.], #x - [0., 1., 0., 0., 0.9 / 3.5, 0.], #y - [0., 0., 1., 0., 0., 0.]]) #z - ordered_analytic_jac = np.concatenate([jacpt0, jacpt1, jacpt2, jacpt3, jacpt4, - jacpt5, jacpt6, jacpt7, jacpt2, jacpt3], axis=0).reshape(10, 3, 6) + jacpt0 = np.array( + [[1.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0, 0.0, 0.0]] # x # y + ) # z + jacpt1 = np.array( + [[1.0, 0.0, 0.0, 1.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 1.0, 0.0, 0.0, 1.0]] # x # y + ) # z + jacpt2 = np.array( + [ + [1.0, 0.0, 0.0, 0.0, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 0.9 / 3.5, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 0.9 / 3.5], + ] + ) # z + jacpt3 = np.array( + [ + [1.0, 0.0, 0.0, 1.0, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 0.8 / 3.5, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 1.9 / 3.5], + ] + ) # z + jacpt4 = np.array( + [ + [1.0, 0.0, 0.0, 2.25 / 3.50, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 1.0, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 2.30 / 3.50], + ] + ) # z + jacpt5 = np.array( + [ + [1.0, 0.0, 0.0, 3.20 / 3.50, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 0.0, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 1.70 / 3.50], + ] + ) # z + jacpt6 = np.array( + [ + [1.0, 0.0, 0.0, 2.0 / 3.5, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 2.1 / 3.5, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 1.0], + ] + ) # z + jacpt7 = np.array( + [ + [1.0, 0.0, 0.0, 0.1 / 3.5, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 0.9 / 3.5, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + ] + ) # z + ordered_analytic_jac = np.concatenate( + [jacpt0, jacpt1, jacpt2, jacpt3, jacpt4, jacpt5, jacpt6, jacpt7, jacpt2, jacpt3], axis=0 + ).reshape(10, 3, 6) return ordered_analytic_jac def test_load_a_model(self): # load the box model and build the box model - csmFile = os.path.join(self.input_path,'inputFiles/esp/box.csm') + csmFile = os.path.join(self.input_path, "inputFiles/esp/box.csm") DVGeo = DVGeometryESP(csmFile) - def test_save_cadfile(self): - write_fullpath = os.path.join(self.input_path,'reg_tests/fullpath_'+str(self.N_PROCS)+'.step') + write_fullpath = os.path.join(self.input_path, "reg_tests/fullpath_" + str(self.N_PROCS) + ".step") DVGeo, initpts = self.setup_cubemodel() if DVGeo.comm.rank == 0: try: @@ -111,14 +135,14 @@ def test_save_cadfile(self): DVGeo.comm.barrier() time.sleep(0.1) self.assertTrue(os.path.exists(write_fullpath)) - + # check that bad file extension raises a Python error with self.assertRaises(IOError): - DVGeo.writeCADFile('relpath.wrongext') + DVGeo.writeCADFile("relpath.wrongext") def test_write_csmfile(self): DVGeo, initpts = self.setup_cubemodel() - write_fullpath = os.path.join(self.input_path,'reg_tests/fullpath_'+str(self.N_PROCS)+'.csm') + write_fullpath = os.path.join(self.input_path, "reg_tests/fullpath_" + str(self.N_PROCS) + ".csm") if DVGeo.comm.rank == 0: try: os.remove(write_fullpath) @@ -130,76 +154,75 @@ def test_write_csmfile(self): self.assertTrue(os.path.exists(write_fullpath)) # check that bad file extension raises a Python error with self.assertRaises(IOError): - DVGeo.writeCADFile('relpath.wrongext') + DVGeo.writeCADFile("relpath.wrongext") def test_add_desvars(self): # load the box model and build the box model - csmFile = os.path.join(self.input_path,'inputFiles/esp/box.csm') + csmFile = os.path.join(self.input_path, "inputFiles/esp/box.csm") DVGeo = DVGeometryESP(csmFile) self.assertIsNotNone(DVGeo) - + # add variables with a mix of optional arguments - DVGeo.addVariable('cubex0', lower=np.array([-10.0]), upper=np.array([10.0]), scale=0.1, dh=0.0001) + DVGeo.addVariable("cubex0", lower=np.array([-10.0]), upper=np.array([10.0]), scale=0.1, dh=0.0001) self.assertEqual(DVGeo.getNDV(), 1) - DVGeo.addVariable('cubey0') + DVGeo.addVariable("cubey0") self.assertEqual(DVGeo.getNDV(), 2) - DVGeo.addVariable('cubez0', lower=np.array([-10.0]), upper=np.array([10.0])) + DVGeo.addVariable("cubez0", lower=np.array([-10.0]), upper=np.array([10.0])) self.assertEqual(DVGeo.getNDV(), 3) # try to add a variable that isn't in the CSM file with self.assertRaises(Error): - DVGeo.addVariable('cubew0') - + DVGeo.addVariable("cubew0") + def test_add_pointset(self): DVGeo, initpts = self.setup_cubemodel() def test_updated_points(self): DVGeo, initpts = self.setup_cubemodel() - DVGeo.addVariable('cubey0') - DVGeo.setDesignVars({'cubey0': np.array([4.2000])}, updateJacobian=False) + DVGeo.addVariable("cubey0") + DVGeo.setDesignVars({"cubey0": np.array([4.2000])}, updateJacobian=False) npts = initpts.shape[0] - self.assertAlmostEqual(np.sum(DVGeo.pointSets['mypts'].proj_pts[:,1] - initpts[:,1]) / npts, 6.2, 10) - DVGeo.addVariable('cubedz') - DVGeo.setDesignVars({'cubedz': np.array([9.5])}, updateJacobian=False) - self.assertAlmostEqual(DVGeo.pointSets['mypts'].proj_pts[1,2], 7.5) - self.assertAlmostEqual(DVGeo.pointSets['mypts'].proj_pts[0,2], -2.0) + self.assertAlmostEqual(np.sum(DVGeo.pointSets["mypts"].proj_pts[:, 1] - initpts[:, 1]) / npts, 6.2, 10) + DVGeo.addVariable("cubedz") + DVGeo.setDesignVars({"cubedz": np.array([9.5])}, updateJacobian=False) + self.assertAlmostEqual(DVGeo.pointSets["mypts"].proj_pts[1, 2], 7.5) + self.assertAlmostEqual(DVGeo.pointSets["mypts"].proj_pts[0, 2], -2.0) def test_finite_precision(self): DVGeo, initpts = self.setup_cubemodel() - DVGeo.addVariable('cubey0') - DVGeo.setDesignVars({'cubey0': np.array([4.2+1e-12])}, updateJacobian=False) + DVGeo.addVariable("cubey0") + DVGeo.setDesignVars({"cubey0": np.array([4.2 + 1e-12])}, updateJacobian=False) npts = initpts.shape[0] - self.assertAlmostEqual(DVGeo.pointSets['mypts'].proj_pts[0,1] - 4.2, 1e-12, 15) - DVGeo.addVariable('cubedz') - DVGeo.setDesignVars({'cubedz': np.array([9.5-1e-12])}, updateJacobian=False) - self.assertAlmostEqual(DVGeo.pointSets['mypts'].proj_pts[1,2] - 7.5, -1e-12, 15) + self.assertAlmostEqual(DVGeo.pointSets["mypts"].proj_pts[0, 1] - 4.2, 1e-12, 15) + DVGeo.addVariable("cubedz") + DVGeo.setDesignVars({"cubedz": np.array([9.5 - 1e-12])}, updateJacobian=False) + self.assertAlmostEqual(DVGeo.pointSets["mypts"].proj_pts[1, 2] - 7.5, -1e-12, 15) def test_serial_finite_difference(self): # this test checks the underlying jacobian itself, not the public API # TODO write tests for the public API DVGeo, initpts = self.setup_cubemodel() - for designvarname in ['cubex0', 'cubey0', 'cubez0', - 'cubedx', 'cubedy', 'cubedz']: + for designvarname in ["cubex0", "cubey0", "cubez0", "cubedx", "cubedy", "cubedz"]: DVGeo.addVariable(designvarname) # check the FD derivatives initpts_cache = initpts.copy() dvdict_cache = DVGeo.DVs.copy() - self.assertFalse(DVGeo.updatedJac['mypts']) + self.assertFalse(DVGeo.updatedJac["mypts"]) DVGeo._computeSurfJacobian(fd=True) - self.assertTrue(DVGeo.updatedJac['mypts']) + self.assertTrue(DVGeo.updatedJac["mypts"]) npts = initpts.shape[0] ndvs = DVGeo.getNDV() # check the jacobian results match analytic result - testjac = DVGeo.pointSets['mypts'].jac.reshape(npts, 3, ndvs) + testjac = DVGeo.pointSets["mypts"].jac.reshape(npts, 3, ndvs) analyticjac = self.setup_cubemodel_analytic_jac() - + for ipt in range(npts): self.assertAlmostEqual(np.sum(np.abs(testjac[ipt, :, :] - analyticjac[ipt, :, :])), 0) # check that the point set hasn't changed after running the FDs - self.assertAlmostEqual(np.sum(np.abs(initpts_cache - DVGeo.pointSets['mypts'].proj_pts)), 0.0) + self.assertAlmostEqual(np.sum(np.abs(initpts_cache - DVGeo.pointSets["mypts"].proj_pts)), 0.0) # check that the DV dict hasn't changed for key in dvdict_cache: self.assertAlmostEqual(np.sum(np.abs(DVGeo.DVs[key].value - dvdict_cache[key].value)), 0.0) @@ -208,45 +231,44 @@ def test_jacobian_arbitrary_added_order(self): # this test checks the underlying jacobian itself, not the public API DVGeo, initpts = self.setup_cubemodel() # switch up the order of DVs added - for designvarname in ['cubey0', 'cubedx', 'cubedy', - 'cubex0', 'cubedz', 'cubez0']: + for designvarname in ["cubey0", "cubedx", "cubedy", "cubex0", "cubedz", "cubez0"]: DVGeo.addVariable(designvarname) # check the FD derivatives DVGeo._computeSurfJacobian(fd=True) npts = initpts.shape[0] ndvs = DVGeo.getNDV() # check the jacobian results match analytic result - testjac = DVGeo.pointSets['mypts'].jac.reshape(npts, 3, ndvs) + testjac = DVGeo.pointSets["mypts"].jac.reshape(npts, 3, ndvs) ordered_analyticjac = self.setup_cubemodel_analytic_jac() analyticjac = np.zeros((npts, 3, ndvs)) - + # get original variable ordering - orig_var_order = ['cubex0', 'cubey0', 'cubez0', - 'cubedx', 'cubedy', 'cubedz'] + orig_var_order = ["cubex0", "cubey0", "cubez0", "cubedx", "cubedy", "cubedz"] # reorder the analytic jacobian for idv, designvarname in enumerate(orig_var_order): dv_ind = DVGeo.DVs[designvarname].globalStartInd - analyticjac[:,:,dv_ind] = ordered_analyticjac[:,:,idv] + analyticjac[:, :, dv_ind] = ordered_analyticjac[:, :, idv] self.assertNotEqual(dv_ind, idv) for ipt in range(npts): self.assertAlmostEqual(np.sum(np.abs(testjac[ipt, :, :] - analyticjac[ipt, :, :])), 0) + @unittest.skipUnless(MPI and pyOCSM, "MPI and pyOCSM are required.") class TestPyGeoESP_BasicCube_Distributed(unittest.TestCase): - N_PROCS = 3 + N_PROCS = 3 def setUp(self): - # Store the path where this current script lives + # Store the path where this current script lives # This all paths in the script are relative to this path # This is needed to support testflo running directories and files as inputs self.input_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) self.comm = MPI.COMM_WORLD - + def setup_cubemodel(self): # load the box model and build the box model - csmFile = os.path.join(self.input_path,'inputFiles/esp/box.csm') + csmFile = os.path.join(self.input_path, "inputFiles/esp/box.csm") DVGeo = DVGeometryESP(csmFile) self.assertIsNotNone(DVGeo) @@ -268,46 +290,70 @@ def setup_cubemodel(self): elif self.comm.rank == 2: initpts = np.vstack([bottom, left, right]) else: - raise ValueError('Too many procs') + raise ValueError("Too many procs") - distglobal = DVGeo.addPointSet(initpts, 'mypts', cache_projections=False) + distglobal = DVGeo.addPointSet(initpts, "mypts", cache_projections=False) self.assertAlmostEqual(distglobal, 0.0, 8) # evaluate the points and check that they match DVGeo._updateESPModel() DVGeo._updateProjectedPts() self.assertTrue(DVGeo.pointSetUpToDate) - self.assertAlmostEqual(np.linalg.norm(initpts - DVGeo.pointSets['mypts'].proj_pts), 0.0, 10) + self.assertAlmostEqual(np.linalg.norm(initpts - DVGeo.pointSets["mypts"].proj_pts), 0.0, 10) return DVGeo, initpts - + def setup_cubemodel_analytic_jac(self): - jacpt0 = np.array([[1., 0., 0., 0., 0., 0.], #x - [0., 1., 0., 0., 0., 0.], #y - [0., 0., 1., 0., 0., 0.]]) #z - jacpt1 = np.array([[1., 0., 0., 1., 0., 0.], #x - [0., 1., 0., 0., 1., 0.], #y - [0., 0., 1., 0., 0., 1.]]) #z - jacpt2 = np.array([[1., 0., 0., 0., 0., 0.], #x - [0., 1., 0., 0., 0.9 / 3.5, 0.], #y - [0., 0., 1., 0., 0., 0.9 / 3.5]]) #z - jacpt3 = np.array([[1., 0., 0., 1., 0., 0.], #x - [0., 1., 0., 0., 0.8 / 3.5, 0.], #y - [0., 0., 1., 0., 0., 1.9 / 3.5]]) #z - jacpt4 = np.array([[1., 0., 0., 2.25 / 3.50, 0., 0.], #x - [0., 1., 0., 0., 1., 0.], #y - [0., 0., 1., 0., 0., 2.30 / 3.50]]) #z - jacpt5 = np.array([[1., 0., 0., 3.20 / 3.50, 0., 0.], #x - [0., 1., 0., 0., 0., 0.], #y - [0., 0., 1., 0., 0., 1.70 / 3.50]]) #z - jacpt6 = np.array([[1., 0., 0., 2.0 / 3.5, 0., 0.], #x - [0., 1., 0., 0., 2.1 / 3.5, 0.], #y - [0., 0., 1., 0., 0., 1.]]) #z - jacpt7 = np.array([[1., 0., 0., 0.1 / 3.5, 0., 0.], #x - [0., 1., 0., 0., 0.9 / 3.5, 0.], #y - [0., 0., 1., 0., 0., 0.]]) #z + jacpt0 = np.array( + [[1.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0, 0.0, 0.0]] # x # y + ) # z + jacpt1 = np.array( + [[1.0, 0.0, 0.0, 1.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 1.0, 0.0, 0.0, 1.0]] # x # y + ) # z + jacpt2 = np.array( + [ + [1.0, 0.0, 0.0, 0.0, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 0.9 / 3.5, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 0.9 / 3.5], + ] + ) # z + jacpt3 = np.array( + [ + [1.0, 0.0, 0.0, 1.0, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 0.8 / 3.5, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 1.9 / 3.5], + ] + ) # z + jacpt4 = np.array( + [ + [1.0, 0.0, 0.0, 2.25 / 3.50, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 1.0, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 2.30 / 3.50], + ] + ) # z + jacpt5 = np.array( + [ + [1.0, 0.0, 0.0, 3.20 / 3.50, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 0.0, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 1.70 / 3.50], + ] + ) # z + jacpt6 = np.array( + [ + [1.0, 0.0, 0.0, 2.0 / 3.5, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 2.1 / 3.5, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 1.0], + ] + ) # z + jacpt7 = np.array( + [ + [1.0, 0.0, 0.0, 0.1 / 3.5, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 0.9 / 3.5, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + ] + ) # z if self.comm.rank == 0: - ordered_analytic_jac = np.concatenate([jacpt0, jacpt1, jacpt2, jacpt3], axis=0).reshape(4, 3, 6) + ordered_analytic_jac = np.concatenate([jacpt0, jacpt1, jacpt2, jacpt3], axis=0).reshape(4, 3, 6) elif self.comm.rank == 1: ordered_analytic_jac = np.concatenate([jacpt4, jacpt5, jacpt6], axis=0).reshape(3, 3, 6) elif self.comm.rank == 2: @@ -316,67 +362,66 @@ def setup_cubemodel_analytic_jac(self): def test_load_a_model(self): # load the box model and build the box model - csmFile = os.path.join(self.input_path,'inputFiles/esp/box.csm') + csmFile = os.path.join(self.input_path, "inputFiles/esp/box.csm") DVGeo = DVGeometryESP(csmFile) def test_add_desvars(self): # load the box model and build the box model - csmFile = os.path.join(self.input_path,'inputFiles/esp/box.csm') + csmFile = os.path.join(self.input_path, "inputFiles/esp/box.csm") DVGeo = DVGeometryESP(csmFile) self.assertIsNotNone(DVGeo) - + # add variables with a mix of optional arguments - DVGeo.addVariable('cubex0', lower=np.array([-10.0]), upper=np.array([10.0]), scale=0.1, dh=0.0001) + DVGeo.addVariable("cubex0", lower=np.array([-10.0]), upper=np.array([10.0]), scale=0.1, dh=0.0001) self.assertEqual(DVGeo.getNDV(), 1) - DVGeo.addVariable('cubey0') + DVGeo.addVariable("cubey0") self.assertEqual(DVGeo.getNDV(), 2) - DVGeo.addVariable('cubez0', lower=np.array([-10.0]), upper=np.array([10.0])) + DVGeo.addVariable("cubez0", lower=np.array([-10.0]), upper=np.array([10.0])) self.assertEqual(DVGeo.getNDV(), 3) # try to add a variable that isn't in the CSM file with self.assertRaises(Error): - DVGeo.addVariable('cubew0') - + DVGeo.addVariable("cubew0") + def test_add_pointset(self): DVGeo, initpts = self.setup_cubemodel() def test_updated_points(self): DVGeo, initpts = self.setup_cubemodel() - DVGeo.addVariable('cubey0') - DVGeo.setDesignVars({'cubey0': np.array([4.2000])}, updateJacobian=False) + DVGeo.addVariable("cubey0") + DVGeo.setDesignVars({"cubey0": np.array([4.2000])}, updateJacobian=False) npts = initpts.shape[0] - self.assertAlmostEqual(np.sum(DVGeo.pointSets['mypts'].proj_pts[:,1] - initpts[:,1]) / npts, 6.2, 10) - DVGeo.addVariable('cubedz') - DVGeo.setDesignVars({'cubedz': np.array([9.5])}, updateJacobian=False) + self.assertAlmostEqual(np.sum(DVGeo.pointSets["mypts"].proj_pts[:, 1] - initpts[:, 1]) / npts, 6.2, 10) + DVGeo.addVariable("cubedz") + DVGeo.setDesignVars({"cubedz": np.array([9.5])}, updateJacobian=False) if self.comm.rank == 0: - self.assertAlmostEqual(DVGeo.pointSets['mypts'].proj_pts[1,2], 7.5) - self.assertAlmostEqual(DVGeo.pointSets['mypts'].proj_pts[0,2], -2.0) + self.assertAlmostEqual(DVGeo.pointSets["mypts"].proj_pts[1, 2], 7.5) + self.assertAlmostEqual(DVGeo.pointSets["mypts"].proj_pts[0, 2], -2.0) def test_parallel_finite_difference(self): # this test checks the underlying jacobian itself, not the public API # TODO write tests for the public API DVGeo, initpts = self.setup_cubemodel() - for designvarname in ['cubex0', 'cubey0', 'cubez0', - 'cubedx', 'cubedy', 'cubedz']: + for designvarname in ["cubex0", "cubey0", "cubez0", "cubedx", "cubedy", "cubedz"]: DVGeo.addVariable(designvarname) # check the FD derivatives initpts_cache = initpts.copy() dvdict_cache = DVGeo.DVs.copy() - self.assertFalse(DVGeo.updatedJac['mypts']) + self.assertFalse(DVGeo.updatedJac["mypts"]) DVGeo._computeSurfJacobian(fd=True) - self.assertTrue(DVGeo.updatedJac['mypts']) + self.assertTrue(DVGeo.updatedJac["mypts"]) npts = initpts.shape[0] ndvs = DVGeo.getNDV() # check the jacobian results match analytic result - testjac = DVGeo.pointSets['mypts'].jac.reshape(npts, 3, ndvs) + testjac = DVGeo.pointSets["mypts"].jac.reshape(npts, 3, ndvs) analyticjac = self.setup_cubemodel_analytic_jac() - + for ipt in range(npts): self.assertAlmostEqual(np.sum(np.abs(testjac[ipt, :, :] - analyticjac[ipt, :, :])), 0) # check that the point set hasn't changed after running the FDs - self.assertAlmostEqual(np.sum(np.abs(initpts_cache - DVGeo.pointSets['mypts'].proj_pts)), 0.0) + self.assertAlmostEqual(np.sum(np.abs(initpts_cache - DVGeo.pointSets["mypts"].proj_pts)), 0.0) # check that the DV dict hasn't changed for key in dvdict_cache: self.assertAlmostEqual(np.sum(np.abs(DVGeo.DVs[key].value - dvdict_cache[key].value)), 0.0) @@ -385,45 +430,44 @@ def test_jacobian_arbitrary_added_order(self): # this test checks the underlying jacobian itself, not the public API DVGeo, initpts = self.setup_cubemodel() # switch up the order of DVs added - for designvarname in ['cubey0', 'cubedx', 'cubedy', - 'cubex0', 'cubedz', 'cubez0']: + for designvarname in ["cubey0", "cubedx", "cubedy", "cubex0", "cubedz", "cubez0"]: DVGeo.addVariable(designvarname) # check the FD derivatives DVGeo._computeSurfJacobian(fd=True) npts = initpts.shape[0] ndvs = DVGeo.getNDV() # check the jacobian results match analytic result - testjac = DVGeo.pointSets['mypts'].jac.reshape(npts, 3, ndvs) + testjac = DVGeo.pointSets["mypts"].jac.reshape(npts, 3, ndvs) ordered_analyticjac = self.setup_cubemodel_analytic_jac() analyticjac = np.zeros((npts, 3, ndvs)) - + # get original variable ordering - orig_var_order = ['cubex0', 'cubey0', 'cubez0', - 'cubedx', 'cubedy', 'cubedz'] + orig_var_order = ["cubex0", "cubey0", "cubez0", "cubedx", "cubedy", "cubedz"] # reorder the analytic jacobian for idv, designvarname in enumerate(orig_var_order): dv_ind = DVGeo.DVs[designvarname].globalStartInd - analyticjac[:,:,dv_ind] = ordered_analyticjac[:,:,idv] + analyticjac[:, :, dv_ind] = ordered_analyticjac[:, :, idv] self.assertNotEqual(dv_ind, idv) for ipt in range(npts): self.assertAlmostEqual(np.sum(np.abs(testjac[ipt, :, :] - analyticjac[ipt, :, :])), 0) + @unittest.skipUnless(MPI and pyOCSM, "MPI and pyOCSM are required.") class TestPyGeoESP_BasicCube_Distributed_OneProcBlank(unittest.TestCase): - N_PROCS = 4 + N_PROCS = 4 def setUp(self): - # Store the path where this current script lives + # Store the path where this current script lives # This all paths in the script are relative to this path # This is needed to support testflo running directories and files as inputs self.input_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) self.comm = MPI.COMM_WORLD - + def setup_cubemodel(self): # load the box model and build the box model - csmFile = os.path.join(self.input_path,'inputFiles/esp/box.csm') + csmFile = os.path.join(self.input_path, "inputFiles/esp/box.csm") DVGeo = DVGeometryESP(csmFile) self.assertIsNotNone(DVGeo) @@ -443,12 +487,12 @@ def setup_cubemodel(self): elif self.comm.rank == 1: initpts = np.vstack([front, back, top]) elif self.comm.rank == 2: - initpts = np.array([]).reshape((0,3)) + initpts = np.array([]).reshape((0, 3)) elif self.comm.rank == 3: initpts = np.vstack([bottom, left, right]) else: - raise ValueError('Too many procs') - distglobal = DVGeo.addPointSet(initpts, 'mypts', cache_projections=False) + raise ValueError("Too many procs") + distglobal = DVGeo.addPointSet(initpts, "mypts", cache_projections=False) self.assertAlmostEqual(distglobal, 0.0, 8) @@ -456,41 +500,65 @@ def setup_cubemodel(self): DVGeo._updateESPModel() DVGeo._updateProjectedPts() self.assertTrue(DVGeo.pointSetUpToDate) - self.assertAlmostEqual(np.linalg.norm(initpts - DVGeo.pointSets['mypts'].proj_pts), 0.0, 10) + self.assertAlmostEqual(np.linalg.norm(initpts - DVGeo.pointSets["mypts"].proj_pts), 0.0, 10) return DVGeo, initpts - + def setup_cubemodel_analytic_jac(self): - jacpt0 = np.array([[1., 0., 0., 0., 0., 0.], #x - [0., 1., 0., 0., 0., 0.], #y - [0., 0., 1., 0., 0., 0.]]) #z - jacpt1 = np.array([[1., 0., 0., 1., 0., 0.], #x - [0., 1., 0., 0., 1., 0.], #y - [0., 0., 1., 0., 0., 1.]]) #z - jacpt2 = np.array([[1., 0., 0., 0., 0., 0.], #x - [0., 1., 0., 0., 0.9 / 3.5, 0.], #y - [0., 0., 1., 0., 0., 0.9 / 3.5]]) #z - jacpt3 = np.array([[1., 0., 0., 1., 0., 0.], #x - [0., 1., 0., 0., 0.8 / 3.5, 0.], #y - [0., 0., 1., 0., 0., 1.9 / 3.5]]) #z - jacpt4 = np.array([[1., 0., 0., 2.25 / 3.50, 0., 0.], #x - [0., 1., 0., 0., 1., 0.], #y - [0., 0., 1., 0., 0., 2.30 / 3.50]]) #z - jacpt5 = np.array([[1., 0., 0., 3.20 / 3.50, 0., 0.], #x - [0., 1., 0., 0., 0., 0.], #y - [0., 0., 1., 0., 0., 1.70 / 3.50]]) #z - jacpt6 = np.array([[1., 0., 0., 2.0 / 3.5, 0., 0.], #x - [0., 1., 0., 0., 2.1 / 3.5, 0.], #y - [0., 0., 1., 0., 0., 1.]]) #z - jacpt7 = np.array([[1., 0., 0., 0.1 / 3.5, 0., 0.], #x - [0., 1., 0., 0., 0.9 / 3.5, 0.], #y - [0., 0., 1., 0., 0., 0.]]) #z + jacpt0 = np.array( + [[1.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0, 0.0, 0.0]] # x # y + ) # z + jacpt1 = np.array( + [[1.0, 0.0, 0.0, 1.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 1.0, 0.0, 0.0, 1.0]] # x # y + ) # z + jacpt2 = np.array( + [ + [1.0, 0.0, 0.0, 0.0, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 0.9 / 3.5, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 0.9 / 3.5], + ] + ) # z + jacpt3 = np.array( + [ + [1.0, 0.0, 0.0, 1.0, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 0.8 / 3.5, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 1.9 / 3.5], + ] + ) # z + jacpt4 = np.array( + [ + [1.0, 0.0, 0.0, 2.25 / 3.50, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 1.0, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 2.30 / 3.50], + ] + ) # z + jacpt5 = np.array( + [ + [1.0, 0.0, 0.0, 3.20 / 3.50, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 0.0, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 1.70 / 3.50], + ] + ) # z + jacpt6 = np.array( + [ + [1.0, 0.0, 0.0, 2.0 / 3.5, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 2.1 / 3.5, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 1.0], + ] + ) # z + jacpt7 = np.array( + [ + [1.0, 0.0, 0.0, 0.1 / 3.5, 0.0, 0.0], # x + [0.0, 1.0, 0.0, 0.0, 0.9 / 3.5, 0.0], # y + [0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + ] + ) # z if self.comm.rank == 0: - ordered_analytic_jac = np.concatenate([jacpt0, jacpt1, jacpt2, jacpt3], axis=0).reshape(4, 3, 6) + ordered_analytic_jac = np.concatenate([jacpt0, jacpt1, jacpt2, jacpt3], axis=0).reshape(4, 3, 6) elif self.comm.rank == 1: ordered_analytic_jac = np.concatenate([jacpt4, jacpt5, jacpt6], axis=0).reshape(3, 3, 6) elif self.comm.rank == 2: - ordered_analytic_jac = np.array([]).reshape(0,3,6) + ordered_analytic_jac = np.array([]).reshape(0, 3, 6) elif self.comm.rank == 3: ordered_analytic_jac = np.concatenate([jacpt7, jacpt2, jacpt3], axis=0).reshape(3, 3, 6) return ordered_analytic_jac @@ -501,53 +569,52 @@ def test_add_pointset(self): def test_updated_points(self): DVGeo, initpts = self.setup_cubemodel() - DVGeo.addVariable('cubey0') - DVGeo.setDesignVars({'cubey0': np.array([4.2000])}, updateJacobian=False) + DVGeo.addVariable("cubey0") + DVGeo.setDesignVars({"cubey0": np.array([4.2000])}, updateJacobian=False) npts = initpts.shape[0] if self.comm.rank != 2: - self.assertAlmostEqual(np.sum(DVGeo.pointSets['mypts'].proj_pts[:,1] - initpts[:,1]) / npts, 6.2, 10) - DVGeo.addVariable('cubedz') - DVGeo.setDesignVars({'cubedz': np.array([9.5])}, updateJacobian=False) + self.assertAlmostEqual(np.sum(DVGeo.pointSets["mypts"].proj_pts[:, 1] - initpts[:, 1]) / npts, 6.2, 10) + DVGeo.addVariable("cubedz") + DVGeo.setDesignVars({"cubedz": np.array([9.5])}, updateJacobian=False) if self.comm.rank == 0: - self.assertAlmostEqual(DVGeo.pointSets['mypts'].proj_pts[1,2], 7.5) - self.assertAlmostEqual(DVGeo.pointSets['mypts'].proj_pts[0,2], -2.0) + self.assertAlmostEqual(DVGeo.pointSets["mypts"].proj_pts[1, 2], 7.5) + self.assertAlmostEqual(DVGeo.pointSets["mypts"].proj_pts[0, 2], -2.0) elif self.comm.rank == 1: - self.assertAlmostEqual(DVGeo.pointSets['mypts'].proj_pts[0,2], -2.0 + (0.3+2.0)*(9.5/3.5)) - self.assertAlmostEqual(DVGeo.pointSets['mypts'].proj_pts[1,2], -2.0 + (-0.3+2.0)*(9.5/3.5)) + self.assertAlmostEqual(DVGeo.pointSets["mypts"].proj_pts[0, 2], -2.0 + (0.3 + 2.0) * (9.5 / 3.5)) + self.assertAlmostEqual(DVGeo.pointSets["mypts"].proj_pts[1, 2], -2.0 + (-0.3 + 2.0) * (9.5 / 3.5)) elif self.comm.rank == 3: - self.assertAlmostEqual(DVGeo.pointSets['mypts'].proj_pts[0,2], -2.0) - self.assertAlmostEqual(DVGeo.pointSets['mypts'].proj_pts[1,2], -2.0 + (-1.1+2.0)*(9.5/3.5)) - + self.assertAlmostEqual(DVGeo.pointSets["mypts"].proj_pts[0, 2], -2.0) + self.assertAlmostEqual(DVGeo.pointSets["mypts"].proj_pts[1, 2], -2.0 + (-1.1 + 2.0) * (9.5 / 3.5)) def test_parallel_finite_difference(self): # this test checks the underlying jacobian itself, not the public API # TODO write tests for the public API DVGeo, initpts = self.setup_cubemodel() - for designvarname in ['cubex0', 'cubey0', 'cubez0', - 'cubedx', 'cubedy', 'cubedz']: + for designvarname in ["cubex0", "cubey0", "cubez0", "cubedx", "cubedy", "cubedz"]: DVGeo.addVariable(designvarname) # check the FD derivatives initpts_cache = initpts.copy() dvdict_cache = DVGeo.DVs.copy() - self.assertFalse(DVGeo.updatedJac['mypts']) + self.assertFalse(DVGeo.updatedJac["mypts"]) DVGeo._computeSurfJacobian(fd=True) - self.assertTrue(DVGeo.updatedJac['mypts']) + self.assertTrue(DVGeo.updatedJac["mypts"]) npts = initpts.shape[0] ndvs = DVGeo.getNDV() # check the jacobian results match analytic result - testjac = DVGeo.pointSets['mypts'].jac.reshape(npts, 3, ndvs) + testjac = DVGeo.pointSets["mypts"].jac.reshape(npts, 3, ndvs) analyticjac = self.setup_cubemodel_analytic_jac() - + if self.comm.rank != 2: for ipt in range(npts): self.assertAlmostEqual(np.sum(np.abs(testjac[ipt, :, :] - analyticjac[ipt, :, :])), 0) # check that the point set hasn't changed after running the FDs - self.assertAlmostEqual(np.sum(np.abs(initpts_cache - DVGeo.pointSets['mypts'].proj_pts)), 0.0) + self.assertAlmostEqual(np.sum(np.abs(initpts_cache - DVGeo.pointSets["mypts"].proj_pts)), 0.0) # check that the DV dict hasn't changed for key in dvdict_cache: self.assertAlmostEqual(np.sum(np.abs(DVGeo.DVs[key].value - dvdict_cache[key].value)), 0.0) + @unittest.skipUnless(MPI and pyOCSM, "MPI and pyOCSM are required.") @parameterized_class(test_params) class TestPyGeoESP_NACAFoil(unittest.TestCase): @@ -556,21 +623,21 @@ class TestPyGeoESP_NACAFoil(unittest.TestCase): N_PROCS = 1 def setUp(self): - # Store the path where this current script lives + # Store the path where this current script lives # This all paths in the script are relative to this path # This is needed to support testflo running directories and files as inputs self.input_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) self.comm = MPI.COMM_WORLD - + def setup_airfoilmodel(self, kulfan=False, projtol=0.01): # load the csm file and pointset file if kulfan: - csmFile = os.path.join(self.input_path,'inputFiles/esp/naca0012_kulfan.csm') + csmFile = os.path.join(self.input_path, "inputFiles/esp/naca0012_kulfan.csm") max_dist_tol = 2 else: - csmFile = os.path.join(self.input_path,'inputFiles/esp/naca0012.csm') + csmFile = os.path.join(self.input_path, "inputFiles/esp/naca0012.csm") max_dist_tol = 3 - stlFile = os.path.join(self.input_path,'inputFiles/esp/naca0012_esp.stl') + stlFile = os.path.join(self.input_path, "inputFiles/esp/naca0012_esp.stl") DVGeo = DVGeometryESP(csmFile, projTol=projtol) self.assertIsNotNone(DVGeo) @@ -579,12 +646,12 @@ def setup_airfoilmodel(self, kulfan=False, projtol=0.01): # test mesh dim 0 is triangle index # dim 1 is each vertex of the triangle # dim 2 is x, y, z dimension - p0 = testobj.vectors[:,0,:] - p1 = testobj.vectors[:,1,:] - p2 = testobj.vectors[:,2,:] - distglobal1 = DVGeo.addPointSet(p0, 'airfoil_p0') - distglobal2 = DVGeo.addPointSet(p1, 'airfoil_p1') - distglobal3 = DVGeo.addPointSet(p2, 'airfoil_p2') + p0 = testobj.vectors[:, 0, :] + p1 = testobj.vectors[:, 1, :] + p2 = testobj.vectors[:, 2, :] + distglobal1 = DVGeo.addPointSet(p0, "airfoil_p0") + distglobal2 = DVGeo.addPointSet(p1, "airfoil_p1") + distglobal3 = DVGeo.addPointSet(p2, "airfoil_p2") distglobal = np.max(np.array([distglobal1, distglobal2, distglobal3])) self.assertAlmostEqual(distglobal, 0.0, max_dist_tol) @@ -593,11 +660,11 @@ def setup_airfoilmodel(self, kulfan=False, projtol=0.01): DVGeo._updateESPModel() DVGeo._updateProjectedPts() self.assertTrue(DVGeo.pointSetUpToDate) - updated_dist_max = np.max(np.sqrt(np.sum((p0-DVGeo.pointSets['airfoil_p0'].proj_pts)**2, axis=1))) + updated_dist_max = np.max(np.sqrt(np.sum((p0 - DVGeo.pointSets["airfoil_p0"].proj_pts) ** 2, axis=1))) self.assertAlmostEqual(updated_dist_max, 0.0, max_dist_tol) - updated_dist_max = np.max(np.sqrt(np.sum((p1-DVGeo.pointSets['airfoil_p1'].proj_pts)**2, axis=1))) + updated_dist_max = np.max(np.sqrt(np.sum((p1 - DVGeo.pointSets["airfoil_p1"].proj_pts) ** 2, axis=1))) self.assertAlmostEqual(updated_dist_max, 0.0, max_dist_tol) - updated_dist_max = np.max(np.sqrt(np.sum((p2-DVGeo.pointSets['airfoil_p2'].proj_pts)**2, axis=1))) + updated_dist_max = np.max(np.sqrt(np.sum((p2 - DVGeo.pointSets["airfoil_p2"].proj_pts) ** 2, axis=1))) self.assertAlmostEqual(updated_dist_max, 0.0, max_dist_tol) return DVGeo, [p0, p1, p2] @@ -610,13 +677,13 @@ def test_add_pointset_tighter_tolerance(self): def test_add_desvars(self): DVGeo, initpts = self.setup_airfoilmodel() - DVGeo.addVariable('nacacode', lower=np.array([8]), upper=np.array([15]), scale=1, dh=0.001) + DVGeo.addVariable("nacacode", lower=np.array([8]), upper=np.array([15]), scale=1, dh=0.001) self.assertEqual(DVGeo.getNDV(), 1) def test_point_mismatch(self): # load the wrong pointset on purpose - csmFile = os.path.join(self.input_path,'inputFiles/esp/naca0010.csm') - stlFile = os.path.join(self.input_path,'inputFiles/esp/naca0012_esp.stl') + csmFile = os.path.join(self.input_path, "inputFiles/esp/naca0010.csm") + stlFile = os.path.join(self.input_path, "inputFiles/esp/naca0012_esp.stl") DVGeo = DVGeometryESP(csmFile) self.assertIsNotNone(DVGeo) @@ -625,35 +692,35 @@ def test_point_mismatch(self): # test mesh dim 0 is triangle index # dim 1 is each vertex of the triangle # dim 2 is x, y, z dimension - p0 = testobj.vectors[:,0,:] - p1 = testobj.vectors[:,1,:] - p2 = testobj.vectors[:,2,:] + p0 = testobj.vectors[:, 0, :] + p1 = testobj.vectors[:, 1, :] + p2 = testobj.vectors[:, 2, :] with self.assertRaises(ValueError): - distglobal1 = DVGeo.addPointSet(p0, 'airfoil_p0') + distglobal1 = DVGeo.addPointSet(p0, "airfoil_p0") self.assertGreater(distglobal1, 0.01) def test_parallel_finite_difference(self, train=False): np.random.seed(1) DVGeo, initpts = self.setup_airfoilmodel(kulfan=True) - DVGeo.addVariable('cst_u', lower=np.zeros((13,)), upper=np.ones((13,)), scale=1, dh=0.0001) - DVGeo.addVariable('cst_l', lower=-np.ones((13,)), upper=np.zeros((13,)), scale=1, dh=0.0001) + DVGeo.addVariable("cst_u", lower=np.zeros((13,)), upper=np.ones((13,)), scale=1, dh=0.0001) + DVGeo.addVariable("cst_l", lower=-np.ones((13,)), upper=np.zeros((13,)), scale=1, dh=0.0001) - refFile = os.path.join(self.input_path,'reg_tests/ref/test_DVGeometryESP_01.ref') - pointset_names = ['airfoil_p0', 'airfoil_p1', 'airfoil_p2'] + refFile = os.path.join(self.input_path, "reg_tests/ref/test_DVGeometryESP_01.ref") + pointset_names = ["airfoil_p0", "airfoil_p1", "airfoil_p2"] for pointset_name in pointset_names: self.assertFalse(DVGeo.updatedJac[pointset_name]) DVGeo._computeSurfJacobian(fd=True) for pointset_name in pointset_names: self.assertTrue(DVGeo.updatedJac[pointset_name]) - + with BaseRegTest(refFile, train=train) as handler: handler.root_print("ESP NACA 0012 derivative test") npts = initpts[0].shape[0] dIdpt = np.random.rand(1, npts, 3) for pointset_name in pointset_names: dIdx = DVGeo.totalSensitivity(dIdpt, pointset_name) - handler.root_add_dict('dIdx_'+pointset_name, dIdx, rtol=1e-7, atol=1e-7) - + handler.root_add_dict("dIdx_" + pointset_name, dIdx, rtol=1e-7, atol=1e-7) + # TODO test pointset caching? # TODO test total derivative API on an actual distributed pointset? diff --git a/tests/reg_tests/test_DVGeometryVSP.py b/tests/reg_tests/test_DVGeometryVSP.py index e045b8f1..460369cc 100644 --- a/tests/reg_tests/test_DVGeometryVSP.py +++ b/tests/reg_tests/test_DVGeometryVSP.py @@ -10,6 +10,7 @@ try: import openvsp + missing_openvsp = False except ImportError: missing_openvsp = True @@ -19,19 +20,18 @@ test_params = [ # # Tutorial scalar JST - { "N_PROCS": 1, "name":'serial'}, - { "N_PROCS": 4, "name":'parallel_4procs'}, + {"N_PROCS": 1, "name": "serial"}, + {"N_PROCS": 4, "name": "parallel_4procs"}, ] -@unittest.skipIf(missing_openvsp, 'requires openvsp Python API') + +@unittest.skipIf(missing_openvsp, "requires openvsp Python API") @parameterized_class(test_params) class RegTestPyGeoVSP(unittest.TestCase): # this will be tested in serial and parallel automatically N_PROCS = 1 - - def setUp(self): # Store the path where this current script lives # This all paths in the script are relative to this path @@ -47,6 +47,7 @@ def test_1(self, train=False, refDeriv=False): A sphere centered at 1, 0, 0 but strech scales from the origin 0, 0, 0 """ + def sample_uv(nu, nv): # function to create sample uv from the surface and save these points. u = numpy.linspace(0, 1, nu) @@ -55,11 +56,10 @@ def sample_uv(nu, nv): uv = numpy.array((uu.flatten(), vv.flatten())) return uv - - refFile = os.path.join(self.base_path,'ref/test_DVGeometryVSP_01.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometryVSP_01.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 1: Basic OpenVSP sphere") - vspFile = os.path.join(self.base_path, '../inputFiles/simpleEll_med.vsp3') + vspFile = os.path.join(self.base_path, "../inputFiles/simpleEll_med.vsp3") DVGeo = DVGeometryVSP(vspFile) dh = 0.1 # we have a sphere centered at x,y,z = 1, 0, 0 with radius 1 @@ -75,16 +75,21 @@ def sample_uv(nu, nv): dvList = list(x.keys()) # add some known points to the sphere - points = [[0.0, 0.0, 0.0], [2.0, 0.0, 0.0], [1.0, 1.0, 0.0], [1.0, -1.0, 0.0], [1.0, 0.0, 1.0], [1.0, 0.0, -1.0]] + points = [ + [0.0, 0.0, 0.0], + [2.0, 0.0, 0.0], + [1.0, 1.0, 0.0], + [1.0, -1.0, 0.0], + [1.0, 0.0, 1.0], + [1.0, 0.0, -1.0], + ] pointSet1 = numpy.array(points) nPts = len(points) - dMax_global = DVGeo.addPointSet(pointSet1, 'known_points') - handler.assert_allclose(dMax_global, 0.0, - name='pointset1_projection_tol', rtol=1e0, atol=1e-10) - + dMax_global = DVGeo.addPointSet(pointSet1, "known_points") + handler.assert_allclose(dMax_global, 0.0, name="pointset1_projection_tol", rtol=1e0, atol=1e-10) - # add some random points - # randomly generate points + # add some random points + # randomly generate points nPts = 100 # just get nPts ^2 points uv = sample_uv(10, 10) @@ -102,15 +107,13 @@ def sample_uv(nu, nv): radius = ((pt.x() - 1.0) ** 2 + pt.y() ** 2 + pt.z() ** 2) ** 0.5 radii.append(radius) pointSet2 = numpy.array(points) - handler.assert_allclose(numpy.array(radii), 1.0, - name='pointset2_diff_from_sphere', rtol=1e-3, atol=1e-3) + handler.assert_allclose(numpy.array(radii), 1.0, name="pointset2_diff_from_sphere", rtol=1e-3, atol=1e-3) dim = 3 # add this point set since our points EXACTLY lie on the sphere, we should get 0 distance in the # projections to machine precision - dMax_global = DVGeo.addPointSet(pointSet2, 'generated_points') - handler.assert_allclose(dMax_global, 0.0, - name='pointset1_projection_tol', rtol=1e0, atol=1e-15) + dMax_global = DVGeo.addPointSet(pointSet2, "generated_points") + handler.assert_allclose(dMax_global, 0.0, name="pointset1_projection_tol", rtol=1e0, atol=1e-15) # lets get the gradients wrt design variables. For this we can define our dummy jacobian for dIdpt # that is an (N, nPts, 3) array. We will just monitor how each component in each point changes so @@ -124,7 +127,7 @@ def sample_uv(nu, nv): dIdpt[dim * i + j, i, j] = 1.0 # get the total sensitivities - funcSens = DVGeo.totalSensitivity(dIdpt, 'generated_points') + funcSens = DVGeo.totalSensitivity(dIdpt, "generated_points") # lets read variables from the total sensitivities and check maxError = 1e-20 @@ -147,9 +150,7 @@ def sample_uv(nu, nv): # print('Error for dv %s on the %d th coordinate of point at (%1.1f, %1.1f, %1.1f) is = %1.16f'%(dv, k+1, point[0],point[1],point[2], error )) maxError = max(error, maxError) - handler.assert_allclose(maxError, 0.0, 'sphere_derivs', rtol=1e0, atol=1e-14) - - + handler.assert_allclose(maxError, 0.0, "sphere_derivs", rtol=1e0, atol=1e-14) def train_2(self, train=True, refDeriv=True): self.test_2(train=train, refDeriv=refDeriv) @@ -158,6 +159,7 @@ def test_2(self, train=False, refDeriv=False): """ Test 2: OpenVSP wing test """ + def sample_uv(nu, nv): # function to create sample uv from the surface and save these points. u = numpy.linspace(0, 1, nu + 1) @@ -167,14 +169,13 @@ def sample_uv(nu, nv): uv = numpy.array((uu.flatten(), vv.flatten())) return uv - refFile = os.path.join(self.base_path,'ref/test_DVGeometryVSP_02.ref') + refFile = os.path.join(self.base_path, "ref/test_DVGeometryVSP_02.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 2: OpenVSP NACA 0012 wing") - vspFile = os.path.join(self.base_path, '../inputFiles/naca0012.vsp3') + vspFile = os.path.join(self.base_path, "../inputFiles/naca0012.vsp3") DVGeo = DVGeometryVSP(vspFile) dh = 1e-6 - openvsp.ClearVSPModel() openvsp.ReadVSPFile(vspFile) geoms = openvsp.FindGeoms() @@ -188,7 +189,9 @@ def sample_uv(nu, nv): # to have it run faster, we just pick 2 sections for i in [0, 5]: # Twist - DVGeo.addVariable(comp, "XSec_%d" % i, "Twist", lower=-10.0, upper=10.0, scale=1e-2, scaledStep=False, dh=dh) + DVGeo.addVariable( + comp, "XSec_%d" % i, "Twist", lower=-10.0, upper=10.0, scale=1e-2, scaledStep=False, dh=dh + ) # loop over coefs # normally, there are 7 coeffs so we should loop over range(7) for the full test @@ -291,18 +294,12 @@ def sample_uv(nu, nv): normalized_error = err / normalizer if maxderiv > biggest_deriv: biggest_deriv = maxderiv - handler.assert_allclose(normalized_error, 0.0, - name='{}_grad_normalized_error'.format(x), rtol=1e0, atol=5e-5) + handler.assert_allclose( + normalized_error, 0.0, name="{}_grad_normalized_error".format(x), rtol=1e0, atol=5e-5 + ) # make sure that at least one derivative is nonzero self.assertGreater(biggest_deriv, 0.005) - - - - - -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() - - From cf08a6e99e6ee824abf29fa8c6429f5c33b6a00d Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Tue, 30 Mar 2021 13:42:05 -0400 Subject: [PATCH 02/18] fixed imports --- pygeo/DVConstraints.py | 13 +++---------- pygeo/DVGeometry.py | 11 ++--------- pygeo/DVGeometryESP.py | 12 +----------- pygeo/DVGeometryVSP.py | 8 +------- pygeo/pyBlock.py | 3 ++- pygeo/pyGeo.py | 20 +++++++++----------- tests/inputFiles/generateFFD.py | 1 - tests/reg_tests/commonUtils.py | 1 - tests/reg_tests/test_Blocks.py | 2 -- tests/reg_tests/test_Cylinder.py | 2 -- tests/reg_tests/test_DVConstraints.py | 6 ++---- tests/reg_tests/test_DVGeometry.py | 2 -- tests/reg_tests/test_DVGeometryVSP.py | 3 --- tests/reg_tests/warning_childFFD.py | 7 +------ 14 files changed, 21 insertions(+), 70 deletions(-) diff --git a/pygeo/DVConstraints.py b/pygeo/DVConstraints.py index 84201d22..b2f75326 100644 --- a/pygeo/DVConstraints.py +++ b/pygeo/DVConstraints.py @@ -1,20 +1,13 @@ # ====================================================================== # Imports # ====================================================================== -import numpy, copy +import numpy from . import geo_utils, pyGeo from pyspline import pySpline from mpi4py import MPI from scipy.sparse import csr_matrix import numpy as np - -try: - from collections import OrderedDict -except ImportError: - try: - from ordereddict import OrderedDict - except ImportError: - print("Could not find any OrderedDict class. For 2.6 and earlier, " "use:\n pip install ordereddict") +from collections import OrderedDict class Error(Exception): @@ -1512,7 +1505,7 @@ def addTriangulatedSurfaceConstraint( meaningless """ try: - import geograd + import geograd # noqa except ImportError: raise ImportError("Geograd package must be installed to use triangulated surface constraint") if DVGeo_1_name is not None: diff --git a/pygeo/DVGeometry.py b/pygeo/DVGeometry.py index 4f98c291..4151a701 100644 --- a/pygeo/DVGeometry.py +++ b/pygeo/DVGeometry.py @@ -1,15 +1,8 @@ # ====================================================================== # Imports # ====================================================================== -import copy, time - -try: - from collections import OrderedDict -except ImportError: - try: - from ordereddict import OrderedDict - except ImportError: - print("Could not find any OrderedDict class. For 2.6 and earlier, " "use:\n pip install ordereddict") +import copy +from collections import OrderedDict import numpy from scipy import sparse from mpi4py import MPI diff --git a/pygeo/DVGeometryESP.py b/pygeo/DVGeometryESP.py index 51da1ebe..9c23c2a1 100644 --- a/pygeo/DVGeometryESP.py +++ b/pygeo/DVGeometryESP.py @@ -1,23 +1,13 @@ # ====================================================================== # Imports # ====================================================================== -from __future__ import print_function -import copy -import tempfile -import shutil import os import sys import time import numpy from collections import OrderedDict -from scipy import sparse -from scipy.spatial import cKDTree from mpi4py import MPI from pyOCSM import pyOCSM -import pickle - -import os -import sys from contextlib import contextmanager @@ -601,7 +591,7 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, edgeIDg = edgeIDArray uvlimitsg = uvlimArray tlimitsg = tlimArray - sizes = np.array([len(ug)]) + sizes = numpy.array([len(ug)]) if self.comm.rank == 0: numpy.savez_compressed( cache_projections, diff --git a/pygeo/DVGeometryVSP.py b/pygeo/DVGeometryVSP.py index 269a8101..4e33e888 100644 --- a/pygeo/DVGeometryVSP.py +++ b/pygeo/DVGeometryVSP.py @@ -1,13 +1,7 @@ # ====================================================================== # Imports # ====================================================================== -try: - from collections import OrderedDict -except ImportError: - try: - from ordereddict import OrderedDict - except ImportError: - print("Could not find any OrderedDict class. For 2.6 and earlier, " "use:\n pip install ordereddict") +from collections import OrderedDict import time import numpy from mpi4py import MPI diff --git a/pygeo/pyBlock.py b/pygeo/pyBlock.py index b925c7de..38d36332 100644 --- a/pygeo/pyBlock.py +++ b/pygeo/pyBlock.py @@ -1,7 +1,8 @@ # ====================================================================== # Imports # ====================================================================== -import os, copy +import os +import copy import numpy from scipy import sparse from scipy.sparse import linalg diff --git a/pygeo/pyGeo.py b/pygeo/pyGeo.py index 91ffaf03..2ad3f02b 100644 --- a/pygeo/pyGeo.py +++ b/pygeo/pyGeo.py @@ -1,7 +1,8 @@ # ====================================================================== # Imports # ====================================================================== -import os, copy +import os +import copy import numpy from scipy import sparse from scipy.sparse.linalg.dsolve import factorized @@ -1046,16 +1047,13 @@ def writeTecplot( for isurf in range(self.nSurf): midu = numpy.floor(self.surfs[isurf].nCtlu / 2) midv = numpy.floor(self.surfs[isurf].nCtlv / 2) - textString = ( - 'TEXT CS=GRID3D, X=%f, Y=%f, Z=%f, ZN=%d, \ - T="S%d"\n' - % ( - self.surfs[isurf].coef[midu, midv, 0], - self.surfs[isurf].coef[midu, midv, 1], - self.surfs[isurf].coef[midu, midv, 2], - isurf + 1, - isurf, - ) + textString = 'TEXT CS=GRID3D, X=%f, Y=%f, Z=%f, ZN=%d, \ + T="S%d"\n' % ( + self.surfs[isurf].coef[midu, midv, 0], + self.surfs[isurf].coef[midu, midv, 1], + self.surfs[isurf].coef[midu, midv, 2], + isurf + 1, + isurf, ) f2.write("%s" % (textString)) f2.close() diff --git a/tests/inputFiles/generateFFD.py b/tests/inputFiles/generateFFD.py index a4d90059..4b090eeb 100644 --- a/tests/inputFiles/generateFFD.py +++ b/tests/inputFiles/generateFFD.py @@ -1,5 +1,4 @@ import numpy as np -import sys def writeFFDFile(fileName, nBlocks, nx, ny, nz, points): diff --git a/tests/reg_tests/commonUtils.py b/tests/reg_tests/commonUtils.py index 0beb1eb4..fe392c3c 100644 --- a/tests/reg_tests/commonUtils.py +++ b/tests/reg_tests/commonUtils.py @@ -1,4 +1,3 @@ -from __future__ import print_function import os import numpy from pygeo import DVGeometry, DVGeometryAxi diff --git a/tests/reg_tests/test_Blocks.py b/tests/reg_tests/test_Blocks.py index e670698e..2b077033 100644 --- a/tests/reg_tests/test_Blocks.py +++ b/tests/reg_tests/test_Blocks.py @@ -1,8 +1,6 @@ -from __future__ import print_function import os import unittest import numpy -import copy from baseclasses import BaseRegTest import commonUtils from pygeo import DVGeometry, geo_utils diff --git a/tests/reg_tests/test_Cylinder.py b/tests/reg_tests/test_Cylinder.py index 99aba3de..208a9384 100644 --- a/tests/reg_tests/test_Cylinder.py +++ b/tests/reg_tests/test_Cylinder.py @@ -1,9 +1,7 @@ -from __future__ import print_function import os import unittest import numpy from baseclasses import BaseRegTest -import commonUtils from pygeo import DVGeometry, DVConstraints, geo_utils diff --git a/tests/reg_tests/test_DVConstraints.py b/tests/reg_tests/test_DVConstraints.py index c4f5ea12..a15b3939 100644 --- a/tests/reg_tests/test_DVConstraints.py +++ b/tests/reg_tests/test_DVConstraints.py @@ -1,14 +1,12 @@ -from __future__ import print_function import os import unittest import numpy as np from baseclasses import BaseRegTest -import commonUtils -from pygeo import geo_utils, DVGeometry, DVConstraints +from pygeo import DVGeometry, DVConstraints from stl import mesh try: - import geograd + import geograd # noqa missing_geograd = False except ImportError: diff --git a/tests/reg_tests/test_DVGeometry.py b/tests/reg_tests/test_DVGeometry.py index 7023008b..cfe2135c 100644 --- a/tests/reg_tests/test_DVGeometry.py +++ b/tests/reg_tests/test_DVGeometry.py @@ -1,11 +1,9 @@ -from __future__ import print_function import os import unittest import numpy from baseclasses import BaseRegTest import commonUtils from pygeo import geo_utils, DVGeometry, DVConstraints -from parameterized import parameterized from stl import mesh diff --git a/tests/reg_tests/test_DVGeometryVSP.py b/tests/reg_tests/test_DVGeometryVSP.py index 460369cc..f5cc919d 100644 --- a/tests/reg_tests/test_DVGeometryVSP.py +++ b/tests/reg_tests/test_DVGeometryVSP.py @@ -1,10 +1,7 @@ -from __future__ import print_function import os import unittest import numpy from baseclasses import BaseRegTest -import commonUtils -from pygeo import geo_utils from parameterized import parameterized_class from mpi4py import MPI diff --git a/tests/reg_tests/warning_childFFD.py b/tests/reg_tests/warning_childFFD.py index f59f666d..002f4b78 100644 --- a/tests/reg_tests/warning_childFFD.py +++ b/tests/reg_tests/warning_childFFD.py @@ -1,12 +1,7 @@ -from __future__ import print_function -import os import unittest import numpy -import copy -from baseclasses import BaseRegTest from pygeo import DVGeometry, geo_utils - -from test_Blocks import add_vars, f_translate, f_rotate_x, f_rotate_y, f_rotate_z, f_rotate_theta +from test_Blocks import add_vars class RegTestPyGeo(unittest.TestCase): From 457b9f82f34e752102ef315b5140bc0b797e9b3c Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Tue, 30 Mar 2021 13:50:58 -0400 Subject: [PATCH 03/18] fixed bare exceptions --- pygeo/DVConstraints.py | 6 +++--- pygeo/DVGeometry.py | 8 ++++---- pygeo/geo_utils.py | 7 ++++--- tests/reg_tests/test_DVGeometryESP.py | 7 +++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pygeo/DVConstraints.py b/pygeo/DVConstraints.py index b2f75326..da244dcf 100644 --- a/pygeo/DVConstraints.py +++ b/pygeo/DVConstraints.py @@ -519,7 +519,7 @@ def writeSurfaceSTL(self, fileName, surfaceName="default", fromDVGeo=None): try: from stl import mesh - except: + except ImportError: raise ImportError("numpy-stl package must be installed") if fromDVGeo is None: p0, p1, p2 = self._getSurfaceVertices(surfaceName=surfaceName) @@ -1519,7 +1519,7 @@ def addTriangulatedSurfaceConstraint( else: DVGeo2 = None if DVGeo1 is None and DVGeo2 is None: - raise UserError("At least one DVGeo object must be specified") + raise ValueError("At least one DVGeo object must be specified") typeName = "triSurfCon" if not typeName in self.constraints: @@ -3721,7 +3721,7 @@ def __init__( self.surface_1_name = surface_1_name self.surface_2_name = surface_2_name if DVGeo1 is None and DVGeo2 is None: - raise UserError("Must include at least one geometric parametrization in constraint " + str(name)) + raise ValueError("Must include at least one geometric parametrization in constraint " + str(name)) self.DVGeo1 = DVGeo1 self.DVGeo2 = DVGeo2 diff --git a/pygeo/DVGeometry.py b/pygeo/DVGeometry.py index 4151a701..3f0d5187 100644 --- a/pygeo/DVGeometry.py +++ b/pygeo/DVGeometry.py @@ -145,8 +145,8 @@ def __init__(self, fileName, complex=False, child=False, faceFreeze=None, name=N self.nDVL_T = None self.nDVSL_T = None self.nDVSW_T = None - self.nDVG_count = 0 # number of global (G) variables - self.nDVL_count = 0 # number of local (L) variables + self.nDVG_count = 0 # number of global (G) variables + self.nDVL_count = 0 # number of local (L) variables self.nDVSL_count = 0 # number of section (SL) local variables self.nDVSW_count = 0 # number of spanwise (SW) local variables @@ -1258,7 +1258,7 @@ def getSymmetricCoefList(self, volList=None, pointSelect=None, tol=1e-8): # now use the baseCoords to create a KD tree try: from scipy.spatial import cKDTree - except: + except ImportError: raise Error("scipy.spatial " "must be available to use detect symmetry") # Now make a KD-tree so we can use it to find the unique nodes @@ -1438,7 +1438,7 @@ def _getAxisNumber(self, axisID): """Get the sequential axis number from the name tag axisID""" try: return list(self.axis.keys()).index(axisID) - except: + except IndexError: raise Error("'The 'axisID' was invalid!") def updateCalculations(self, new_pts, isComplex, config): diff --git a/pygeo/geo_utils.py b/pygeo/geo_utils.py index e44f19be..f4486346 100644 --- a/pygeo/geo_utils.py +++ b/pygeo/geo_utils.py @@ -3,7 +3,8 @@ # and pyLayout # ============================================================================= import numpy as np -import sys, os +import sys +import os import functools from pyspline import pySpline @@ -252,7 +253,7 @@ def readAirfoilFile(fileName, bluntTe=False, bluntTaperRange=0.1, bluntThickness r = [] try: r.append([float(s) for s in line.split()]) - except: + except Exception: r = [] while 1: @@ -3493,7 +3494,7 @@ def tfi_2d(e0, e1, e2, e3): try: X = pySpline.libspline.tfi2d(e0.T, e1.T, e2.T, e3.T).T - except: + except Exception: Nu = len(e0) Nv = len(e2) diff --git a/tests/reg_tests/test_DVGeometryESP.py b/tests/reg_tests/test_DVGeometryESP.py index 837fe5e9..29f8d301 100644 --- a/tests/reg_tests/test_DVGeometryESP.py +++ b/tests/reg_tests/test_DVGeometryESP.py @@ -1,7 +1,6 @@ import unittest import os import numpy as np -import os from stl import mesh from baseclasses import BaseRegTest from parameterized import parameterized_class @@ -9,7 +8,7 @@ try: from mpi4py import MPI -except: +except ImportError: MPI = None if MPI: @@ -129,7 +128,7 @@ def test_save_cadfile(self): if DVGeo.comm.rank == 0: try: os.remove(write_fullpath) - except: + except OSError: pass DVGeo.writeCADFile(write_fullpath) DVGeo.comm.barrier() @@ -146,7 +145,7 @@ def test_write_csmfile(self): if DVGeo.comm.rank == 0: try: os.remove(write_fullpath) - except: + except OSError: pass DVGeo.writeCSMFile(write_fullpath) DVGeo.comm.barrier() From ad3e4da4d8c79c50d6fa93b73a2baa4e35087e88 Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Tue, 30 Mar 2021 13:57:01 -0400 Subject: [PATCH 04/18] linting fixes --- pygeo/DVConstraints.py | 38 +++++++++++++++++----------------- pygeo/DVGeometry.py | 16 +++++++------- pygeo/geo_utils.py | 12 +++++------ pygeo/pyBlock.py | 2 +- pygeo/pyGeo.py | 8 +++---- pygeo/pyNetwork.py | 2 +- tests/reg_tests/commonUtils.py | 7 ------- 7 files changed, 39 insertions(+), 46 deletions(-) diff --git a/pygeo/DVConstraints.py b/pygeo/DVConstraints.py index da244dcf..913d4da5 100644 --- a/pygeo/DVConstraints.py +++ b/pygeo/DVConstraints.py @@ -703,7 +703,7 @@ def addThicknessConstraints2D( coords = coords.reshape((nSpan * nChord * 2, 3)) typeName = "thickCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() # Create a name @@ -846,7 +846,7 @@ def addThicknessConstraints1D( coords = coords.reshape((nCon * 2, 3)) typeName = "thickCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: @@ -1033,7 +1033,7 @@ def addLERadiusConstraints( # Create the thickness constraint object typeName = "radiusCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: @@ -1137,7 +1137,7 @@ def addLocationConstraints1D( # Create the location constraint object typeName = "locCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: @@ -1274,7 +1274,7 @@ def addProjectedLocationConstraints1D( # Create the location constraint object typeName = "locCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: @@ -1414,7 +1414,7 @@ def addThicknessToChordConstraints1D( coords = coords.reshape((nCon * 4, 3)) typeName = "thickCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: conName = "%s_thickness_to_chord_constraints_%d" % (self.name, len(self.constraints[typeName])) @@ -1522,7 +1522,7 @@ def addTriangulatedSurfaceConstraint( raise ValueError("At least one DVGeo object must be specified") typeName = "triSurfCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: @@ -1631,7 +1631,7 @@ def addTriangulatedVolumeConstraint( DVGeo = self.DVGeometries[DVGeoName] typeName = "triVolCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: @@ -1770,7 +1770,7 @@ def addVolumeConstraint( self._checkDVGeo(DVGeoName) typeName = "volCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: @@ -1858,7 +1858,7 @@ def addCompositeVolumeConstraint( self._checkDVGeo(DVGeoName) typeName = "volCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: @@ -2255,7 +2255,7 @@ def addGearPostConstraint( p0, p1, p2 = self._getSurfaceVertices(surfaceName=surfaceName) typeName = "gearCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: @@ -2378,7 +2378,7 @@ def addCircularityConstraint( origin = numpy.array(origin).reshape((1, 3)) typeName = "circCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() # Create a name @@ -2458,7 +2458,7 @@ def addSurfaceAreaConstraint( p0, p1, p2 = self._getSurfaceVertices(surfaceName=surfaceName) typeName = "surfAreaCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() # Create a name @@ -2549,7 +2549,7 @@ def addProjectedAreaConstraint( axis = numpy.array([0, 0, 1]) typeName = "projAreaCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() # Create a name @@ -2632,7 +2632,7 @@ def addPlanarityConstraint( # Create a name typeName = "planeCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: @@ -2731,7 +2731,7 @@ def addColinearityConstraint( # Create a name typeName = "coLinCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() if name is None: @@ -2842,7 +2842,7 @@ def addCurvatureConstraint( geo._calcConnectivity(node_tol, edge_tol) surfs = geo.surfs typeName = "curveCon" - if not typeName in self.constraints: + if typeName not in self.constraints: self.constraints[typeName] = OrderedDict() # Create a name if name is None: @@ -3937,7 +3937,7 @@ def evalTriangulatedSurfConstraint(self): if self.perim_length > self.max_perim: failflag = True - if mpi4py.COMM_WORLD.rank == 0: + if MPI.COMM_WORLD.rank == 0: print("Intersection length ", str(perim_length), " exceeds tol, returning fail flag") else: failflag = False @@ -5692,7 +5692,7 @@ def __init__(self, name, surfs, curvatureType, lower, upper, scaled, scale, KSCo self.scaled = scaled self.scale = scale self.KSCoeff = KSCoeff - if self.KSCoeff == None: + if self.KSCoeff is None: # set KSCoeff to be the number of points in the plot 3D files self.KSCoeff = 0.0 for i in range(len(self.coords)): diff --git a/pygeo/DVGeometry.py b/pygeo/DVGeometry.py index 3f0d5187..afb5c927 100644 --- a/pygeo/DVGeometry.py +++ b/pygeo/DVGeometry.py @@ -2081,7 +2081,7 @@ def totalSensitivityTransProd(self, vec, ptSetName, comm=None, child=False, nDVS self.computeTotalJacobian(ptSetName, config=config) # perform the product - if self.JT[ptSetName] == None: + if self.JT[ptSetName] is None: xsdot = numpy.zeros((0, 3)) else: xsdot = self.JT[ptSetName].dot(numpy.ravel(vec)) @@ -2237,7 +2237,7 @@ def computeTotalJacobianCS(self, ptSetName, config=None): refFFDCoef = copy.copy(self.FFD.coef) refCoef = copy.copy(self.coef) - if self.nPts[ptSetName] == None: + if self.nPts[ptSetName] is None: self.nPts[ptSetName] = len(self.update(ptSetName).flatten()) for child in self.children: child.nPts[ptSetName] = self.nPts[ptSetName] @@ -3043,11 +3043,11 @@ def _getDVOffsets(self): # get the global and local DV numbers on the parents if we don't have them if ( - self.nDV_T == None - or self.nDVG_T == None - or self.nDVL_T == None - or self.nDVSL_T == None - or self.nDVSW_T == None + self.nDV_T is None + or self.nDVG_T is None + or self.nDVL_T is None + or self.nDVSL_T is None + or self.nDVSW_T is None ): self.nDV_T = self._getNDV() self.nDVG_T = self._getNDVGlobal() @@ -3316,7 +3316,7 @@ def computeTotalJacobianFD(self, ptSetName, config=None): # out in the end. coords0 = self.update(ptSetName, childDelta=False, config=config).flatten() - if self.nPts[ptSetName] == None: + if self.nPts[ptSetName] is None: self.nPts[ptSetName] = len(coords0.flatten()) for child in self.children: child.nPts[ptSetName] = self.nPts[ptSetName] diff --git a/pygeo/geo_utils.py b/pygeo/geo_utils.py index f4486346..bdad3be4 100644 --- a/pygeo/geo_utils.py +++ b/pygeo/geo_utils.py @@ -4034,7 +4034,7 @@ def __init__(self): def area(self): h = self.wedge a = 0 - while not h.nexthedge is self.wedge: + while h.nexthedge is not self.wedge: p1 = h.origin p2 = h.nexthedge.origin a += p1.x * p2.y - p2.x * p1.y @@ -4050,7 +4050,7 @@ def calcCentroid(self): center = np.zeros(2) center += [h.origin.x, h.origin.y] counter = 1 - while not h.nexthedge is self.wedge: + while h.nexthedge is not self.wedge: counter += 1 h = h.nexthedge center += [h.origin.x, h.origin.y] @@ -4063,7 +4063,7 @@ def calcSpatialCentroid(self): center = np.zeros(3) center += h.origin.X counter = 1 - while not h.nexthedge is self.wedge: + while h.nexthedge is not self.wedge: counter += 1 h = h.nexthedge center += h.origin.X @@ -4073,7 +4073,7 @@ def calcSpatialCentroid(self): def perimeter(self): h = self.wedge p = 0 - while not h.nexthedge is self.wedge: + while h.nexthedge is not self.wedge: p += h.length h = h.nexthedge return p @@ -4081,7 +4081,7 @@ def perimeter(self): def vertexlist(self): h = self.wedge pl = [h.origin] - while not h.nexthedge is self.wedge: + while h.nexthedge is not self.wedge: h = h.nexthedge pl.append(h.origin) return pl @@ -4241,7 +4241,7 @@ def buildDcel(self): f.wedge = h f.wedge.face = f # And we traverse the boundary of the new face - while not h.nexthedge is f.wedge: + while h.nexthedge is not f.wedge: h = h.nexthedge h.face = f self.faces.append(f) diff --git a/pygeo/pyBlock.py b/pygeo/pyBlock.py index 38d36332..2a30d25e 100644 --- a/pygeo/pyBlock.py +++ b/pygeo/pyBlock.py @@ -727,7 +727,7 @@ def calcdPtdCoef(self, ptSetName): rowPtr.append(rowPtr[-1] + kinc) if self.embededVolumes[ptSetName].mask is not None: - if not i in self.embededVolumes[ptSetName].mask: + if i not in self.embededVolumes[ptSetName].mask: # Kill the values we just added vals[rowPtr[-2] : rowPtr[-1]] = 0.0 diff --git a/pygeo/pyGeo.py b/pygeo/pyGeo.py index 2ad3f02b..3b8e1b16 100644 --- a/pygeo/pyGeo.py +++ b/pygeo/pyGeo.py @@ -1161,7 +1161,7 @@ def writeTin(self, fileName): # Now loop over the componets and each will write the info it # has to the .tin file: for i in range(self.nSurf): - if self.surfs[i].name == None: + if self.surfs[i].name is None: name = "surface_%d" % i else: name = self.surfs[i].name @@ -1216,7 +1216,7 @@ def getBounds(self, surfs=None): xMax : array of length 3 Upper corner of the bounding box """ - if surfs == None: + if surfs is None: surfs = numpy.arange(self.nSurf) Xmin0, Xmax0 = self.surfs[surfs[0]].getBounds() @@ -1264,7 +1264,7 @@ def projectCurve(self, curve, surfs=None, *args, **kwargs): one of the surfaces. """ - if surfs == None: + if surfs is None: surfs = numpy.arange(self.nSurf) temp = numpy.zeros((len(surfs), 4)) @@ -1308,7 +1308,7 @@ def projectPoints(self, points, surfs=None, *args, **kwargs): Patch index corresponding to the u,v parameter values """ - if surfs == None: + if surfs is None: surfs = numpy.arange(self.nSurf) N = len(points) diff --git a/pygeo/pyNetwork.py b/pygeo/pyNetwork.py index f0884996..09787b9f 100644 --- a/pygeo/pyNetwork.py +++ b/pygeo/pyNetwork.py @@ -235,7 +235,7 @@ def projectRays(self, points, axis, curves=None, raySize=1.5, **kwargs): for i in range(len(s0)): D0[i, :] = self.curves[curveID0[i]](s0[i]) - points[i] - if curves == None: + if curves is None: curves = numpy.arange(self.nCurve) # Now do the same calc as before diff --git a/tests/reg_tests/commonUtils.py b/tests/reg_tests/commonUtils.py index fe392c3c..aaf24ba2 100644 --- a/tests/reg_tests/commonUtils.py +++ b/tests/reg_tests/commonUtils.py @@ -4,13 +4,6 @@ from pyspline import Curve -def printHeader(testName): - if MPI.COMM_WORLD.rank == 0: - print("+" + "-" * 78 + "+") - print("| Test Name: " + "%-66s" % testName + "|") - print("+" + "-" * 78 + "+") - - ################## # DVGeometry Tests ################## From 68706c7c9043238e708cc528c6085083a81171d1 Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Tue, 30 Mar 2021 14:16:25 -0400 Subject: [PATCH 05/18] fixed F841 unused variable --- pygeo/DVConstraints.py | 6 ++---- pygeo/DVGeometry.py | 8 ++++---- pygeo/DVGeometryESP.py | 12 +++++------- pygeo/geo_utils.py | 5 +---- pygeo/pyBlock.py | 2 -- pygeo/pyGeo.py | 2 +- tests/reg_tests/test_DVGeometryESP.py | 7 ++----- tests/reg_tests/test_DVGeometryVSP.py | 4 ---- 8 files changed, 15 insertions(+), 31 deletions(-) diff --git a/pygeo/DVConstraints.py b/pygeo/DVConstraints.py index 913d4da5..df41eced 100644 --- a/pygeo/DVConstraints.py +++ b/pygeo/DVConstraints.py @@ -2933,7 +2933,6 @@ def _readPlot3DSurfFile(self, fileName): an unstructured mesh format""" pts = None - conn = None f = open(fileName, "r") nSurf = numpy.fromfile(f, "int", count=1, sep=" ")[0] @@ -4058,7 +4057,6 @@ def evalFunctionsSens(self, funcsSens, config): # assume evalFunctions was called just prior and grad was stashed on rank=0 grad_vol = self.compute_volume_sens(self.surf_p0, self.surf_p1, self.surf_p2) - nDV = self.DVGeo.getNDV() if self.scaled: tmp_p0 = self.DVGeo.totalSensitivity(grad_vol[0] / self.vol_0, self.surface_name + "_p0", config=config) tmp_p1 = self.DVGeo.totalSensitivity(grad_vol[1] / self.vol_0, self.surface_name + "_p1", config=config) @@ -5964,12 +5962,12 @@ def evalCurvAreaSens(self, iSurf): if self.curvatureType == "Gaussian": # Now compute integral (K**2) over S, equivelent to sum(K**2*dS) - kS = numpy.dot(one, K * K * dS) + # kS = numpy.dot(one, K * K * dS) DkSDX = (self.diags(2 * K * dS).dot(DKDX) + self.diags(K * K).dot(DdSDX)).T.dot(one) return DkSDX elif self.curvatureType == "mean": # Now compute integral (H**2) over S, equivelent to sum(H**2*dS) - hS = numpy.dot(one, H * H * dS) + # hS = numpy.dot(one, H * H * dS) DhSDX = (self.diags(2 * H * dS).dot(DHDX) + self.diags(H * H).dot(DdSDX)).T.dot(one) return DhSDX elif self.curvatureType == "combined": diff --git a/pygeo/DVGeometry.py b/pygeo/DVGeometry.py index afb5c927..9e6e95c7 100644 --- a/pygeo/DVGeometry.py +++ b/pygeo/DVGeometry.py @@ -909,8 +909,8 @@ def addGeoDVSpanwiseLocal( volList = numpy.arange(self.FFD.nVol) ind = numpy.arange(len(self.FFD.coef)) - secLink = numpy.zeros(self.FFD.coef.shape[0], dtype=int) - secTransform = [numpy.eye(3)] + # secLink = numpy.zeros(self.FFD.coef.shape[0], dtype=int) + # secTransform = [numpy.eye(3)] if type(spanIndex) is str: spanIndex = [spanIndex] * len(volList) @@ -2723,7 +2723,7 @@ def demoDesignVars(self, directory, includeLocal=True, includeGlobal=True, point x[j] = val dvDict.update({key: x}) self.setDesignVars(dvDict) - X = self.update(pointSet) + self.update(pointSet) # Write FFD self.writeTecplot("{}/ffd/iter_{:03d}.dat".format(directory, count)) @@ -4134,7 +4134,7 @@ def sectionFrame(self, sectionIndex, sectionTransform, sectionLink, ivol=0, orie List of transformation matrices for the sections of a given volume. Transformations are set up from local section frame to global frame. """ - xyz_2_idx = {"x": 0, "y": 1, "z": 2} + # xyz_2_idx = {"x": 0, "y": 1, "z": 2} ijk_2_idx = {"i": 0, "j": 1, "k": 2} lIndex = self.FFD.topo.lIndex[ivol] diff --git a/pygeo/DVGeometryESP.py b/pygeo/DVGeometryESP.py index 9c23c2a1..c607d65c 100644 --- a/pygeo/DVGeometryESP.py +++ b/pygeo/DVGeometryESP.py @@ -213,7 +213,7 @@ def __init__( pmtrIndex = 0 pmtrsleft = True ocsmExternal = 500 - ocsmIllegalPmtrIndex = -262 + # ocsmIllegalPmtrIndex = -262 while pmtrsleft: try: pmtrIndex += 1 @@ -375,7 +375,7 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, if distributed: # displacements for scatter disp = numpy.array([numpy.sum(sizes[:i]) for i in range(self.comm.size)], dtype="intc") - nptsg = numpy.sum(sizes) + # nptsg = numpy.sum(sizes) if self.comm.rank == 0: sendbuf1 = [bodyIDg, sizes, disp, MPI.INT] sendbuf2 = [faceIDg, sizes, disp, MPI.INT] @@ -401,7 +401,7 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, # nondistributed pointset # read on proc 0 and bcast to all # then check that the points are correct - nptsg = points.shape[0] + # nptsg = points.shape[0] if self.comm.rank == 0: faceIDl[:] = faceIDg[:] bodyIDl[:] = bodyIDg[:] @@ -654,7 +654,6 @@ def setDesignVars(self, dvDict, updateJacobian=True): def writeCADFile(self, filename): valid_filetypes = ["brep", "bstl", "egads", "egg", "iges", "igs", "sens", "step", "stl", "stp", "tess", "grid"] - splitfile = filename.split(".") file_extension = filename.split(".")[-1] if file_extension.lower() not in valid_filetypes: raise IOError( @@ -803,8 +802,7 @@ def totalSensitivity(self, dIdpt, ptSetName, comm=None, config=None): if len(dIdpt.shape) == 2: dIdpt = numpy.array([dIdpt]) N = dIdpt.shape[0] - - nDV = self.getNDV() + nPt = dIdpt.shape[1] # The following code computes the final sensitivity product: # @@ -820,7 +818,7 @@ def totalSensitivity(self, dIdpt, ptSetName, comm=None, config=None): # a copy because we may need to modify it. # reshape the dIdpt array from [N] * [nPt] * [3] to [N] * [nPt*3] - dIdpt = dIdpt.reshape((dIdpt.shape[0], dIdpt.shape[1] * 3)) + dIdpt = dIdpt.reshape((N, nPt * 3)) # # transpose dIdpt and vstack; # # Now vstack the result with seamBar as that is far as the diff --git a/pygeo/geo_utils.py b/pygeo/geo_utils.py index bdad3be4..a766aeed 100644 --- a/pygeo/geo_utils.py +++ b/pygeo/geo_utils.py @@ -174,8 +174,6 @@ def calculateAverageNormal(p0, v1, v2): take in a triangulated surface and calculate the centroid """ p0 = np.array(p0) - p1 = np.array(v1) + p0 - p2 = np.array(v2) + p0 # compute the normal of each triangle normal = np.cross(v1, v2) @@ -270,7 +268,6 @@ def readAirfoilFile(fileName, bluntTe=False, bluntTaperRange=0.1, bluntThickness npt = len(x) xMin = min(x) - xMax = max(x) # There are 4 possibilites we have to deal with: # a. Given a sharp TE -- User wants a sharp TE @@ -2181,7 +2178,7 @@ def calcGlobalNumberingDummy(self, sizes, surfaceList=None): lIndex = [] # Now actually fill everything up for ii in range(len(surfaceList)): - isurf = surfaceList[ii] + iSurf = surfaceList[ii] N = sizes[iSurf][0] M = sizes[iSurf][1] lIndex.append(-1 * np.ones((N, M), "intc")) diff --git a/pygeo/pyBlock.py b/pygeo/pyBlock.py index 2a30d25e..4cde9c70 100644 --- a/pygeo/pyBlock.py +++ b/pygeo/pyBlock.py @@ -756,8 +756,6 @@ def getAttachedPoints(self, ptSetName): only the points corresponding to the indices in mask will be non-zero in the array. """ - - volID = self.embededVolumes[ptSetName].volID u = self.embededVolumes[ptSetName].u v = self.embededVolumes[ptSetName].v w = self.embededVolumes[ptSetName].w diff --git a/pygeo/pyGeo.py b/pygeo/pyGeo.py index 3b8e1b16..fb28d898 100644 --- a/pygeo/pyGeo.py +++ b/pygeo/pyGeo.py @@ -174,7 +174,7 @@ def _readIges(self, fileName): start_lines = int((Ifile[-1][1:8])) general_lines = int((Ifile[-1][9:16])) directory_lines = int((Ifile[-1][17:24])) - parameter_lines = int((Ifile[-1][25:32])) + # parameter_lines = int((Ifile[-1][25:32])) # Now we know how many lines we have to deal with dir_offset = start_lines + general_lines diff --git a/tests/reg_tests/test_DVGeometryESP.py b/tests/reg_tests/test_DVGeometryESP.py index 29f8d301..a5d6bb61 100644 --- a/tests/reg_tests/test_DVGeometryESP.py +++ b/tests/reg_tests/test_DVGeometryESP.py @@ -120,7 +120,7 @@ def setup_cubemodel_analytic_jac(self): def test_load_a_model(self): # load the box model and build the box model csmFile = os.path.join(self.input_path, "inputFiles/esp/box.csm") - DVGeo = DVGeometryESP(csmFile) + DVGeometryESP(csmFile) def test_save_cadfile(self): write_fullpath = os.path.join(self.input_path, "reg_tests/fullpath_" + str(self.N_PROCS) + ".step") @@ -193,7 +193,6 @@ def test_finite_precision(self): DVGeo.addVariable("cubey0") DVGeo.setDesignVars({"cubey0": np.array([4.2 + 1e-12])}, updateJacobian=False) - npts = initpts.shape[0] self.assertAlmostEqual(DVGeo.pointSets["mypts"].proj_pts[0, 1] - 4.2, 1e-12, 15) DVGeo.addVariable("cubedz") DVGeo.setDesignVars({"cubedz": np.array([9.5 - 1e-12])}, updateJacobian=False) @@ -362,7 +361,7 @@ def setup_cubemodel_analytic_jac(self): def test_load_a_model(self): # load the box model and build the box model csmFile = os.path.join(self.input_path, "inputFiles/esp/box.csm") - DVGeo = DVGeometryESP(csmFile) + DVGeometryESP(csmFile) def test_add_desvars(self): # load the box model and build the box model @@ -692,8 +691,6 @@ def test_point_mismatch(self): # dim 1 is each vertex of the triangle # dim 2 is x, y, z dimension p0 = testobj.vectors[:, 0, :] - p1 = testobj.vectors[:, 1, :] - p2 = testobj.vectors[:, 2, :] with self.assertRaises(ValueError): distglobal1 = DVGeo.addPointSet(p0, "airfoil_p0") self.assertGreater(distglobal1, 0.01) diff --git a/tests/reg_tests/test_DVGeometryVSP.py b/tests/reg_tests/test_DVGeometryVSP.py index f5cc919d..a04f6acd 100644 --- a/tests/reg_tests/test_DVGeometryVSP.py +++ b/tests/reg_tests/test_DVGeometryVSP.py @@ -96,7 +96,6 @@ def sample_uv(nu, nv): # convert the ptvec into list of coordinates points = [] - radError = 1e-20 radii = [] for pt in ptvec: # print (pt) @@ -177,8 +176,6 @@ def sample_uv(nu, nv): openvsp.ReadVSPFile(vspFile) geoms = openvsp.FindGeoms() - comps = [] - DVGeo = DVGeometryVSP(vspFile) comp = "WingGeom" # loop over sections @@ -232,7 +229,6 @@ def sample_uv(nu, nv): # get the coordinates nNodes = len(uv[0, :]) - ptVecA = openvsp.CompVecPnt01(geoms[0], 0, uv[0, :], uv[1, :]) # extract node coordinates and save them in a numpy array coor = numpy.zeros((nNodes, 3)) From 74ec082508407a41ec4f1c27dfbe9bee6207c881 Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Tue, 30 Mar 2021 14:25:20 -0400 Subject: [PATCH 06/18] fixed undefined vars --- pygeo/DVConstraints.py | 6 +++--- pygeo/DVGeometry.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pygeo/DVConstraints.py b/pygeo/DVConstraints.py index df41eced..568b520c 100644 --- a/pygeo/DVConstraints.py +++ b/pygeo/DVConstraints.py @@ -5254,7 +5254,7 @@ def addVariablesPyOpt(self, optProb): """ if self.addVarToPyOpt: - optProb.addVarGroup(dv.name, dv.nVal, "c", value=dv.value, lower=dv.lower, upper=dv.upper, scale=dv.scale) + optProb.addVarGroup(self.name, self.nVal, "c", value=self.value, lower=self.lower, upper=self.upper, scale=self.scale) def writeTecplot(self, handle): """ @@ -5835,7 +5835,7 @@ def evalCurvArea(self, iSurf): else: raise Error( "The curvatureType parameter should be Gaussian, mean, or combined, " - "%s is not supported!" % curvatureType + "%s is not supported!" % self.curvatureType ) def evalCurvAreaSens(self, iSurf): @@ -5987,7 +5987,7 @@ def evalCurvAreaSens(self, iSurf): else: raise Error( "The curvatureType parameter should be Gaussian, mean, or combined, " - "%s is not supported!" % curvatureType + "%s is not supported!" % self.curvatureType ) def evalCross(self, iSurf, u, v): diff --git a/pygeo/DVGeometry.py b/pygeo/DVGeometry.py index 9e6e95c7..2dca7b7f 100644 --- a/pygeo/DVGeometry.py +++ b/pygeo/DVGeometry.py @@ -3571,8 +3571,8 @@ def _spanwiselocalDVJacobian(self, config=None): # TODO: the += here is to allow recursion check this with multiple nesting # levels - self.children[iChild].dXrefdXdvl[:, iDVLocal] += dXrefdXdvl - self.children[iChild].dCcdXdvl[:, iDVLocal] += dCcdXdvl + self.children[iChild].dXrefdXdvl[:, iDVSpanwiseLocal] += dXrefdXdvl + self.children[iChild].dCcdXdvl[:, iDVSpanwiseLocal] += dCcdXdvl iDVSpanwiseLocal += 1 else: From f0e3a34a59740db3a8e809984cae1fb3e561f21e Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Tue, 30 Mar 2021 14:32:53 -0400 Subject: [PATCH 07/18] renamed ambiguous var names --- pygeo/geo_utils.py | 65 +++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/pygeo/geo_utils.py b/pygeo/geo_utils.py index a766aeed..18449aa7 100644 --- a/pygeo/geo_utils.py +++ b/pygeo/geo_utils.py @@ -441,13 +441,13 @@ def write_wing_FFD_file(fileName, slices, N0, N1, N2, axes=None, dist=None): # Make sure the sizes are the right type in each dimension. If an integer is # given, use that same size for every volume. size = [N0, N1, N2] - for i, item in enumerate(size): + for iVol, item in enumerate(size): if type(item) is int: - size[i] = [item] * Nvol + size[iVol] = [item] * Nvol elif type(item) is not list: print("Incorrect type for N0, N1, or N2.") - assert len(size[i]) == Nvol + assert len(size[iVol]) == Nvol N0, N1, N2 = size f = open(fileName, "w") @@ -474,24 +474,24 @@ def getDistribution(distIn, N): Nk = size[axes.index("k")] f.write("%d\t%d\t%d\n" % (Ni, Nj, Nk)) - for i in range(Nvol): - size = [N0[i], N1[i], N2[i]] + for iVol in range(Nvol): + size = [N0[iVol], N1[iVol], N2[iVol]] Ni = size[axes.index("i")] Nj = size[axes.index("j")] Nk = size[axes.index("k")] # Get distributions for each axis - d0 = getDistribution(dist[i][0], size[0]) - d1 = getDistribution(dist[i][1], size[1]) - d2 = getDistribution(dist[i][2], size[2]) + d0 = getDistribution(dist[iVol][0], size[0]) + d1 = getDistribution(dist[iVol][1], size[1]) + d2 = getDistribution(dist[iVol][2], size[2]) # Initialize coordinate arrays X = np.zeros(size + [3]) for j in range(size[0]): - P = slices[i, 0, 0] + np.outer(d0, (slices[i + 1, 0, 0] - slices[i, 0, 0]))[j] - Q = slices[i, 0, 1] + np.outer(d0, (slices[i + 1, 0, 1] - slices[i, 0, 1]))[j] - R = slices[i, 1, 0] + np.outer(d0, (slices[i + 1, 1, 0] - slices[i, 1, 0]))[j] - S = slices[i, 1, 1] + np.outer(d0, (slices[i + 1, 1, 1] - slices[i, 1, 1]))[j] + P = slices[iVol, 0, 0] + np.outer(d0, (slices[iVol + 1, 0, 0] - slices[iVol, 0, 0]))[j] + Q = slices[iVol, 0, 1] + np.outer(d0, (slices[iVol + 1, 0, 1] - slices[iVol, 0, 1]))[j] + R = slices[iVol, 1, 0] + np.outer(d0, (slices[iVol + 1, 1, 0] - slices[iVol, 1, 0]))[j] + S = slices[iVol, 1, 1] + np.outer(d0, (slices[iVol + 1, 1, 1] - slices[iVol, 1, 1]))[j] for k in range(size[1]): U = P + np.outer(d1, (R - P))[k] V = Q + np.outer(d1, (S - Q))[k] @@ -499,13 +499,13 @@ def getDistribution(distIn, N): for dim in range(3): line = "" - for j in range(Nk): - for k in range(Nj): - for l in range(Ni): + for k in range(Nk): + for j in range(Nj): + for i in range(Ni): idc = [-1, -1, -1] - idc[axes.index("i")] = l - idc[axes.index("j")] = k - idc[axes.index("k")] = j + idc[axes.index("i")] = i + idc[axes.index("j")] = j + idc[axes.index("k")] = k line += "{: .4e}\t".format(X[idc[0], idc[1], idc[2], dim]) if len(line) + 11 > 80: f.write(line + "\n") @@ -3581,11 +3581,11 @@ def splitQuad(e0, e1, e2, e3, alpha, beta, NO): pts[3] = e1[-1] # First generate edge lengths - l = np.zeros(4) - l[0] = eDist(pts[0], pts[1]) - l[1] = eDist(pts[2], pts[3]) - l[2] = eDist(pts[0], pts[2]) - l[3] = eDist(pts[1], pts[3]) + length = np.zeros(4) + length[0] = eDist(pts[0], pts[1]) + length[1] = eDist(pts[2], pts[3]) + length[2] = eDist(pts[0], pts[2]) + length[3] = eDist(pts[1], pts[3]) # Vector along edges 0->3 vec = np.zeros((4, 3)) @@ -3601,8 +3601,8 @@ def splitQuad(e0, e1, e2, e3, alpha, beta, NO): mid = np.average(pts, axis=0) - uBar = 0.5 * (l[0] + l[1]) * alpha - vBar = 0.5 * (l[2] + l[3]) * beta + uBar = 0.5 * (length[0] + length[1]) * alpha + vBar = 0.5 * (length[2] + length[3]) * beta aspect = uBar / vBar @@ -4212,14 +4212,14 @@ def buildDcel(self): # Step 3: Identification of next and prev hedges for v in self.vertices: v.sortincident() - l = len(v.hedgelist) + length = len(v.hedgelist) - for i in range(l - 1): + for i in range(length - 1): v.hedgelist[i].nexthedge = v.hedgelist[i + 1].twin v.hedgelist[i + 1].prevhedge = v.hedgelist[i] - v.hedgelist[l - 1].nexthedge = v.hedgelist[0].twin - v.hedgelist[0].prevhedge = v.hedgelist[l - 1] + v.hedgelist[length - 1].nexthedge = v.hedgelist[0].twin + v.hedgelist[0].prevhedge = v.hedgelist[length - 1] # Step 4: Face assignment provlist = self.hedges[:] @@ -4428,13 +4428,12 @@ def hangle(dx, dy): """Determines the angle with respect to the x axis of a segment of coordinates dx and dy """ - - l = np.sqrt(dx * dx + dy * dy) + length = np.sqrt(dx * dx + dy * dy) if dy > 0: - return np.arccos(dx / l) + return np.arccos(dx / length) else: - return 2 * np.pi - np.arccos(dx / l) + return 2 * np.pi - np.arccos(dx / length) # --------------------- Polygon geometric functions ----------------- From 248e7f47251b02341efed41e8567910ae0119f0c Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Tue, 30 Mar 2021 14:46:27 -0400 Subject: [PATCH 08/18] cast numpy bool array to python bool --- pygeo/DVGeometry.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pygeo/DVGeometry.py b/pygeo/DVGeometry.py index 2dca7b7f..80e35a08 100644 --- a/pygeo/DVGeometry.py +++ b/pygeo/DVGeometry.py @@ -2832,7 +2832,8 @@ def _finalize(self): for j in range(self.FFD.vols[iVol].nCtlv): for k in range(self.FFD.vols[iVol].nCtlw): ind = self.FFD.topo.lIndex[iVol][i, j, k] - if coefMask[ind] == False and ind not in self.axis[key]["ignoreInd"]: + # we have to cast to bool to compare using "is" + if bool(coefMask[ind]) is False and ind not in self.axis[key]["ignoreInd"]: temp.append(ind) # Unique the values and append to the master list @@ -4278,7 +4279,8 @@ def __init__(self, dvName, lower, upper, scale, axis, coefListIn, mask, config): coefList = [] # create a new coefficent list that excludes any values that are masked for i in range(len(coefListIn)): - if mask[coefListIn[i]] == False: + # we have to cast to bool to compare using "is" + if bool(mask[coefListIn[i]]) is False: coefList.append(coefListIn[i]) N = len(axis) @@ -4389,7 +4391,8 @@ def __init__(self, dvName, lower, upper, scale, axis, vol_dv_to_coefs, mask, con # loop through each of coefs to see if it is masked for coef in coefs: - if mask[coef] == False: + # we have to cast to bool to compare using "is" + if bool(mask[coef]) is False: loc_dv_to_coefs.append(coef) self.dv_to_coefs.append(loc_dv_to_coefs) @@ -4473,7 +4476,8 @@ def __init__(self, dvName, lower, upper, scale, axis, coefListIn, mask, config, self.coefList = [] # create a new coefficent list that excludes any values that are masked for i in range(len(coefListIn)): - if mask[coefListIn[i]] == False: + # we have to cast to bool to compare using "is" + if bool(mask[coefListIn[i]]) is False: self.coefList.append(coefListIn[i]) self.nVal = len(self.coefList) From 540518899740e63e607876e2152fe9abf5d1c340 Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Tue, 30 Mar 2021 15:15:08 -0400 Subject: [PATCH 09/18] minor formatting --- pygeo/DVConstraints.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pygeo/DVConstraints.py b/pygeo/DVConstraints.py index 568b520c..8922136c 100644 --- a/pygeo/DVConstraints.py +++ b/pygeo/DVConstraints.py @@ -5254,7 +5254,9 @@ def addVariablesPyOpt(self, optProb): """ if self.addVarToPyOpt: - optProb.addVarGroup(self.name, self.nVal, "c", value=self.value, lower=self.lower, upper=self.upper, scale=self.scale) + optProb.addVarGroup( + self.name, self.nVal, "c", value=self.value, lower=self.lower, upper=self.upper, scale=self.scale + ) def writeTecplot(self, handle): """ From 7fc53ca2ea8df4ed8b68cdea8379892ad3cb9acc Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Tue, 30 Mar 2021 15:16:21 -0400 Subject: [PATCH 10/18] added git blame ignore --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..8687c926 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1 @@ +8ebf48deefbee52560197721d02d7f2cc8408c15 From 495bf84abcac345d6df3ef89a2e108839ffeb627 Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Tue, 30 Mar 2021 17:22:45 -0400 Subject: [PATCH 11/18] updated azure yaml file --- .github/azure-pipelines.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/azure-pipelines.yaml b/.github/azure-pipelines.yaml index 0a9108e6..700dc770 100644 --- a/.github/azure-pipelines.yaml +++ b/.github/azure-pipelines.yaml @@ -15,5 +15,4 @@ extends: template: azure/azure_template.yaml@azure_template parameters: REPO_NAME: pygeo - IGNORE_STYLE: true IMAGE: auto From 52055764e33341b18949e9d905397baaa8fc1fcd Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Wed, 31 Mar 2021 09:54:58 -0400 Subject: [PATCH 12/18] addressed comments --- pygeo/DVGeometry.py | 12 ++++-------- pygeo/geo_utils.py | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/pygeo/DVGeometry.py b/pygeo/DVGeometry.py index 80e35a08..18f2701e 100644 --- a/pygeo/DVGeometry.py +++ b/pygeo/DVGeometry.py @@ -2832,8 +2832,7 @@ def _finalize(self): for j in range(self.FFD.vols[iVol].nCtlv): for k in range(self.FFD.vols[iVol].nCtlw): ind = self.FFD.topo.lIndex[iVol][i, j, k] - # we have to cast to bool to compare using "is" - if bool(coefMask[ind]) is False and ind not in self.axis[key]["ignoreInd"]: + if (not coefMask[ind]) and (ind not in self.axis[key]["ignoreInd"]): temp.append(ind) # Unique the values and append to the master list @@ -4279,8 +4278,7 @@ def __init__(self, dvName, lower, upper, scale, axis, coefListIn, mask, config): coefList = [] # create a new coefficent list that excludes any values that are masked for i in range(len(coefListIn)): - # we have to cast to bool to compare using "is" - if bool(mask[coefListIn[i]]) is False: + if not mask[coefListIn[i]]: coefList.append(coefListIn[i]) N = len(axis) @@ -4391,8 +4389,7 @@ def __init__(self, dvName, lower, upper, scale, axis, vol_dv_to_coefs, mask, con # loop through each of coefs to see if it is masked for coef in coefs: - # we have to cast to bool to compare using "is" - if bool(mask[coef]) is False: + if not mask[coef]: loc_dv_to_coefs.append(coef) self.dv_to_coefs.append(loc_dv_to_coefs) @@ -4476,8 +4473,7 @@ def __init__(self, dvName, lower, upper, scale, axis, coefListIn, mask, config, self.coefList = [] # create a new coefficent list that excludes any values that are masked for i in range(len(coefListIn)): - # we have to cast to bool to compare using "is" - if bool(mask[coefListIn[i]]) is False: + if not mask[coefListIn[i]]: self.coefList.append(coefListIn[i]) self.nVal = len(self.coefList) diff --git a/pygeo/geo_utils.py b/pygeo/geo_utils.py index 18449aa7..c41ffb26 100644 --- a/pygeo/geo_utils.py +++ b/pygeo/geo_utils.py @@ -252,7 +252,7 @@ def readAirfoilFile(fileName, bluntTe=False, bluntTaperRange=0.1, bluntThickness try: r.append([float(s) for s in line.split()]) except Exception: - r = [] + pass while 1: line = f.readline() From b192604451ac9427ddccfc2ca24a6796a22e4cc1 Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Wed, 31 Mar 2021 10:39:59 -0400 Subject: [PATCH 13/18] renamed numpy to np --- examples/bwb/bwb.py | 20 +- examples/c172_wing/c172.py | 4 +- pygeo/DVConstraints.py | 657 +++++++++++++------------- pygeo/DVGeometry.py | 430 ++++++++--------- pygeo/DVGeometryAxi.py | 10 +- pygeo/DVGeometryESP.py | 192 ++++---- pygeo/DVGeometryVSP.py | 104 ++-- pygeo/geo_utils.py | 2 +- pygeo/pyBlock.py | 82 ++-- pygeo/pyGeo.py | 166 +++---- pygeo/pyNetwork.py | 52 +- tests/reg_tests/commonUtils.py | 16 +- tests/reg_tests/test_Blocks.py | 34 +- tests/reg_tests/test_Cylinder.py | 24 +- tests/reg_tests/test_DVGeometry.py | 54 +-- tests/reg_tests/test_DVGeometryVSP.py | 42 +- tests/reg_tests/warning_childFFD.py | 20 +- 17 files changed, 950 insertions(+), 959 deletions(-) diff --git a/examples/bwb/bwb.py b/examples/bwb/bwb.py index d85bf8b8..8b942c51 100644 --- a/examples/bwb/bwb.py +++ b/examples/bwb/bwb.py @@ -1,4 +1,4 @@ -import numpy +import numpy as np from pygeo import pyGeo from pyspline import pySpline @@ -13,10 +13,10 @@ airfoil_list[i] = None # Use the digitize it data for the planform: -le = numpy.array(numpy.loadtxt("bwb_le.out")) -te = numpy.array(numpy.loadtxt("bwb_te.out")) -front_up = numpy.array(numpy.loadtxt("bwb_front_up.out")) -front_low = numpy.array(numpy.loadtxt("bwb_front_low.out")) +le = np.array(np.loadtxt("bwb_le.out")) +te = np.array(np.loadtxt("bwb_te.out")) +front_up = np.array(np.loadtxt("bwb_front_up.out")) +front_low = np.array(np.loadtxt("bwb_front_low.out")) le[0, :] = 0 te[0, 0] = 0 @@ -30,7 +30,7 @@ low_spline = pySpline.curve(X=front_low[:, 1], s=front_low[:, 0], nCtl=11, k=4) # Generate consistent equally spaced spline data -span = numpy.linspace(0, 1, naf) +span = np.linspace(0, 1, naf) le = le_spline(span) te = te_spline(span) @@ -48,10 +48,10 @@ toc = -(up - low) / chord thickness = toc / 0.12 -rot_x = numpy.zeros(naf) -rot_y = numpy.zeros(naf) -rot_z = numpy.zeros(naf) -offset = numpy.zeros((naf, 2)) +rot_x = np.zeros(naf) +rot_y = np.zeros(naf) +rot_z = np.zeros(naf) +offset = np.zeros((naf, 2)) bwb = pyGeo( "liftingSurface", diff --git a/examples/c172_wing/c172.py b/examples/c172_wing/c172.py index 63b59fed..316755d0 100644 --- a/examples/c172_wing/c172.py +++ b/examples/c172_wing/c172.py @@ -1,4 +1,4 @@ -import numpy +import numpy as np from pygeo import pyGeo # ============================================================================== @@ -13,7 +13,7 @@ rot_x = [0, 0, 0] rot_y = [0, 0, 0] rot_z = [0, 0, 2] -offset = numpy.zeros((naf, 2)) +offset = np.zeros((naf, 2)) # There are several examples that follow showing many of the different # combinations of tip/trailing edge options that are available. diff --git a/pygeo/DVConstraints.py b/pygeo/DVConstraints.py index 8922136c..810612f7 100644 --- a/pygeo/DVConstraints.py +++ b/pygeo/DVConstraints.py @@ -1,12 +1,11 @@ # ====================================================================== # Imports # ====================================================================== -import numpy +import numpy as np from . import geo_utils, pyGeo from pyspline import pySpline from mpi4py import MPI from scipy.sparse import csr_matrix -import numpy as np from collections import OrderedDict @@ -243,9 +242,9 @@ def setSurface(self, surf, name="default", addToDVGeo=False, DVGeoName="default" if format == "point-vector": if type(surf) == list: # Data from ADflow - p0 = numpy.array(surf[0]) - v1 = numpy.array(surf[1]) - v2 = numpy.array(surf[2]) + p0 = np.array(surf[0]) + v1 = np.array(surf[1]) + v2 = np.array(surf[2]) elif isinstance(surf, str): # Load the surf as a plot3d file p0, v1, v2 = self._readPlot3DSurfFile(surf) @@ -263,16 +262,16 @@ def setSurface(self, surf, name="default", addToDVGeo=False, DVGeoName="default" raise NotImplementedError elif type(surf) == list: # for now, do NOT add the object geometry to dvgeo - p0 = numpy.array(surf[0]) - p1 = numpy.array(surf[1]) - p2 = numpy.array(surf[2]) - elif type(surf) == numpy.ndarray: + p0 = np.array(surf[0]) + p1 = np.array(surf[1]) + p2 = np.array(surf[2]) + elif type(surf) == np.ndarray: surf_length = surf[:, 0, :].shape[0] p0 = surf[:, 0, :].reshape(surf_length, 3) p1 = surf[:, 1, :].reshape(surf_length, 3) p2 = surf[:, 2, :].reshape(surf_length, 3) else: - raise TypeError("surf given is not supported [list, numpy.ndarray]") + raise TypeError("surf given is not supported [list, np.ndarray]") self.surfaces[name].append(p0) self.surfaces[name].append(p1) @@ -515,7 +514,7 @@ def writeSurfaceSTL(self, fileName, surfaceName="default", fromDVGeo=None): fromDVGeo : str or None Name of the DVGeo object to obtain the surface from (default is 'None') """ - import numpy as np + import np as np try: from stl import mesh @@ -827,9 +826,9 @@ def addThicknessConstraints1D( # Create mesh of itersections constr_line = pySpline.Curve(X=ptList, k=2) - s = numpy.linspace(0, 1, nCon) + s = np.linspace(0, 1, nCon) X = constr_line(s) - coords = numpy.zeros((nCon, 2, 3)) + coords = np.zeros((nCon, 2, 3)) # Project all the points for i in range(nCon): # Project actual node: @@ -982,9 +981,9 @@ def addLERadiusConstraints( # Create mesh of itersections constr_line = pySpline.Curve(X=leList, k=2) - s = numpy.linspace(0, 1, nSpan) + s = np.linspace(0, 1, nSpan) X = constr_line(s) - coords = numpy.zeros((nSpan, 3, 3)) + coords = np.zeros((nSpan, 3, 3)) p0, p1, p2 = self._getSurfaceVertices(surfaceName=surfaceName) # Project all the points for i in range(nSpan): @@ -1002,9 +1001,9 @@ def addLERadiusConstraints( midPts = (coords[:, 0, :] + coords[:, 1, :]) / 2.0 # Project to get leading edge point - lePts = numpy.zeros((nSpan, 3)) - chordDir = numpy.array(chordDir, dtype="d").flatten() - chordDir /= numpy.linalg.norm(chordDir) + lePts = np.zeros((nSpan, 3)) + chordDir = np.array(chordDir, dtype="d").flatten() + chordDir /= np.linalg.norm(chordDir) for i in range(nSpan): # Project actual node: up, down, fail = geo_utils.projectNode(X[i], chordDir, p0, p1 - p0, p2 - p0) @@ -1017,8 +1016,8 @@ def addLERadiusConstraints( lePts[i] = up # Check that points can form radius - d = numpy.linalg.norm(coords[:, 0, :] - coords[:, 1, :], axis=1) - r = numpy.linalg.norm(midPts - lePts, axis=1) + d = np.linalg.norm(coords[:, 0, :] - coords[:, 1, :], axis=1) + r = np.linalg.norm(midPts - lePts, axis=1) for i in range(nSpan): if d[i] < 2 * r[i]: raise Error( @@ -1029,7 +1028,7 @@ def addLERadiusConstraints( # Add leading edge points and stack points into shape accepted by DVGeo coords[:, 2, :] = lePts - coords = numpy.vstack((coords[:, 0, :], coords[:, 1, :], coords[:, 2, :])) + coords = np.vstack((coords[:, 0, :], coords[:, 1, :], coords[:, 2, :])) # Create the thickness constraint object typeName = "radiusCon" @@ -1126,7 +1125,7 @@ def addLocationConstraints1D( self._checkDVGeo(DVGeoName) # Create the points to constrain constr_line = pySpline.Curve(X=ptList, k=2) - s = numpy.linspace(0, 1, nCon) + s = np.linspace(0, 1, nCon) X = constr_line(s) # X shouls now be in the shape we need @@ -1248,10 +1247,10 @@ def addProjectedLocationConstraints1D( p0, p1, p2 = self._getSurfaceVertices(surfaceName=surfaceName) constr_line = pySpline.Curve(X=ptList, k=2) - s = numpy.linspace(0, 1, nCon) + s = np.linspace(0, 1, nCon) X = constr_line(s) - coords = numpy.zeros((nCon, 2, 3)) + coords = np.zeros((nCon, 2, 3)) # Project all the points for i in range(nCon): # Project actual node: @@ -1387,10 +1386,10 @@ def addThicknessToChordConstraints1D( p0, p1, p2 = self._getSurfaceVertices(surfaceName=surfaceName) constr_line = pySpline.Curve(X=ptList, k=2) - s = numpy.linspace(0, 1, nCon) + s = np.linspace(0, 1, nCon) X = constr_line(s) - coords = numpy.zeros((nCon, 4, 3)) - chordDir /= numpy.linalg.norm(numpy.array(chordDir, "d")) + coords = np.zeros((nCon, 4, 3)) + chordDir /= np.linalg.norm(np.array(chordDir, "d")) # Project all the points for i in range(nCon): # Project actual node: @@ -1403,7 +1402,7 @@ def addThicknessToChordConstraints1D( coords[i, 0] = up coords[i, 1] = down - height = numpy.linalg.norm(coords[i, 0] - coords[i, 1]) + height = np.linalg.norm(coords[i, 0] - coords[i, 1]) # Third point is the mid-point of thsoe coords[i, 2] = 0.5 * (up + down) @@ -2063,7 +2062,7 @@ def addLeTeConstraints( # Finally add the volume constraint object n = len(indSetA) self.linearCon[conName] = LinearConstraint( - conName, indSetA, indSetB, numpy.ones(n), numpy.ones(n), lower=0, upper=0, DVGeo=DVGeo, config=config + conName, indSetA, indSetB, np.ones(n), np.ones(n), lower=0, upper=0, DVGeo=DVGeo, config=config ) def addLinearConstraintsShape( @@ -2139,29 +2138,29 @@ def addLinearConstraintsShape( conName = name # Process the inputs to be arrays of length n if necessary. - factorA = numpy.atleast_1d(factorA) - factorB = numpy.atleast_1d(factorB) - lower = numpy.atleast_1d(lower) - upper = numpy.atleast_1d(upper) + factorA = np.atleast_1d(factorA) + factorB = np.atleast_1d(factorB) + lower = np.atleast_1d(lower) + upper = np.atleast_1d(upper) n = len(indSetA) if len(factorA) == 1: - factorA = factorA[0] * numpy.ones(n) + factorA = factorA[0] * np.ones(n) elif len(factorA) != n: raise Error("Length of factorA invalid!") if len(factorB) == 1: - factorB = factorB[0] * numpy.ones(n) + factorB = factorB[0] * np.ones(n) elif len(factorB) != n: raise Error("Length of factorB invalid!") if len(lower) == 1: - lower = lower[0] * numpy.ones(n) + lower = lower[0] * np.ones(n) elif len(lower) != n: raise Error("Length of lower invalid!") if len(upper) == 1: - upper = upper[0] * numpy.ones(n) + upper = upper[0] * np.ones(n) elif len(upper) != n: raise Error("Length of upper invalid!") @@ -2375,7 +2374,7 @@ def addCircularityConstraint( # Create the circularity constraint object: coords = coords.reshape((nPts, 3)) - origin = numpy.array(origin).reshape((1, 3)) + origin = np.array(origin).reshape((1, 3)) typeName = "circCon" if typeName not in self.constraints: @@ -2542,11 +2541,11 @@ def addProjectedAreaConstraint( p0, p1, p2 = self._getSurfaceVertices(surfaceName=surfaceName) if axis == "x": - axis = numpy.array([1, 0, 0]) + axis = np.array([1, 0, 0]) elif axis == "y": - axis = numpy.array([0, 1, 0]) + axis = np.array([0, 1, 0]) elif axis == "z": - axis = numpy.array([0, 0, 1]) + axis = np.array([0, 0, 1]) typeName = "projAreaCon" if typeName not in self.constraints: @@ -2627,8 +2626,8 @@ def addPlanarityConstraint( p0, p1, p2 = self._getSurfaceVertices(surfaceName=surfaceName) # Create the circularity constraint object: - origin = numpy.array(origin).reshape((1, 3)) - planeAxis = numpy.array(planeAxis).reshape((1, 3)) + origin = np.array(origin).reshape((1, 3)) + planeAxis = np.array(planeAxis).reshape((1, 3)) # Create a name typeName = "planeCon" @@ -2725,9 +2724,9 @@ def addColinearityConstraint( coords.append(dist * lineAxis + origin) # Create the circularity constraint object: - coords = numpy.array(coords).reshape((nPts, 3)) - origin = numpy.array(origin).reshape((1, 3)) - lineAxis = numpy.array(lineAxis).reshape((1, 3)) + coords = np.array(coords).reshape((nPts, 3)) + origin = np.array(origin).reshape((1, 3)) + lineAxis = np.array(lineAxis).reshape((1, 3)) # Create a name typeName = "coLinCon" @@ -2935,24 +2934,24 @@ def _readPlot3DSurfFile(self, fileName): pts = None f = open(fileName, "r") - nSurf = numpy.fromfile(f, "int", count=1, sep=" ")[0] - sizes = numpy.fromfile(f, "int", count=3 * nSurf, sep=" ").reshape((nSurf, 3)) + nSurf = np.fromfile(f, "int", count=1, sep=" ")[0] + sizes = np.fromfile(f, "int", count=3 * nSurf, sep=" ").reshape((nSurf, 3)) nElem = 0 for i in range(nSurf): nElem += (sizes[i, 0] - 1) * (sizes[i, 1] - 1) # Generate the uncompacted point and connectivity list: - p0 = numpy.zeros((nElem * 2, 3)) - v1 = numpy.zeros((nElem * 2, 3)) - v2 = numpy.zeros((nElem * 2, 3)) + p0 = np.zeros((nElem * 2, 3)) + v1 = np.zeros((nElem * 2, 3)) + v2 = np.zeros((nElem * 2, 3)) elemCount = 0 for iSurf in range(nSurf): curSize = sizes[iSurf, 0] * sizes[iSurf, 1] - pts = numpy.zeros((curSize, 3)) + pts = np.zeros((curSize, 3)) for idim in range(3): - pts[:, idim] = numpy.fromfile(f, "float", curSize, sep=" ") + pts[:, idim] = np.fromfile(f, "float", curSize, sep=" ") pts = pts.reshape((sizes[iSurf, 0], sizes[iSurf, 1], 3), order="f") for j in range(sizes[iSurf, 1] - 1): @@ -2997,10 +2996,10 @@ def _convertTo2D(self, value, dim1, dim2): scalar will be 'upcast' to that size """ - if numpy.isscalar: - return value * numpy.ones((dim1, dim2)) + if np.isscalar: + return value * np.ones((dim1, dim2)) else: - temp = numpy.atleast_2d(value) + temp = np.atleast_2d(value) if temp.shape[0] == dim1 and temp.shape[1] == dim2: return value else: @@ -3013,10 +3012,10 @@ def _convertTo1D(self, value, dim1): otherwise, a scalar will be 'upcast' to that size """ - if numpy.isscalar: - return value * numpy.ones(dim1) + if np.isscalar: + return value * np.ones(dim1) else: - temp = numpy.atleast_1d(value) + temp = np.atleast_1d(value) if temp.shape[0] == dim1: return value else: @@ -3039,12 +3038,12 @@ def _generateIntersections(self, leList, teList, nSpan, nChord, surfaceName): tip_s = pySpline.Curve(X=[leList[-1], teList[-1]], k=2) # Generate parametric distances - span_s = numpy.linspace(0.0, 1.0, nSpan) - chord_s = numpy.linspace(0.0, 1.0, nChord) + span_s = np.linspace(0.0, 1.0, nSpan) + chord_s = np.linspace(0.0, 1.0, nChord) # Generate a 2D region of intersections X = geo_utils.tfi_2d(le_s(span_s), te_s(span_s), root_s(chord_s), tip_s(chord_s)) - coords = numpy.zeros((nSpan, nChord, 2, 3)) + coords = np.zeros((nSpan, nChord, 2, 3)) for i in range(nSpan): for j in range(nChord): # Generate the 'up_vec' from taking the cross product @@ -3063,7 +3062,7 @@ def _generateIntersections(self, leList, teList, nSpan, nChord, surfaceName): else: vVec = X[i, j + 1] - X[i, j - 1] - upVec = numpy.cross(uVec, vVec) + upVec = np.cross(uVec, vVec) # Project actual node: up, down, fail = geo_utils.projectNode(X[i, j], upVec, p0, p1 - p0, p2 - p0) @@ -3120,7 +3119,7 @@ def _generateDiscreteSurface(self, wing): v1.append(P2 - P3) v2.append(P1 - P3) - return numpy.array(p0), numpy.array(v1), numpy.array(v2) + return np.array(p0), np.array(v1), np.array(v2) def _generateCircle(self, origin, rotAxis, radius, zeroAxis, angleCW, angleCCW, nPts): """ @@ -3154,10 +3153,10 @@ def _generateCircle(self, origin, rotAxis, radius, zeroAxis, angleCW, angleCCW, """ # enforce the shape of the origin - origin = numpy.array(origin).reshape((3,)) + origin = np.array(origin).reshape((3,)) # Create the coordinate array - coords = numpy.zeros((nPts, 3)) + coords = np.zeros((nPts, 3)) # get the angles about the zero axis for the points if angleCW < 0: @@ -3165,25 +3164,25 @@ def _generateCircle(self, origin, rotAxis, radius, zeroAxis, angleCW, angleCCW, if angleCCW < 0: raise Error("Negative angle specified. angleCCW should be positive.") - angles = numpy.linspace(numpy.deg2rad(-angleCW), numpy.deg2rad(angleCCW), nPts) + angles = np.linspace(np.deg2rad(-angleCW), np.deg2rad(angleCCW), nPts) # --------- # Generate a unit vector in the zero axis direction # ---- # get the third axis by taking the cross product of rotAxis and zeroAxis - axis = numpy.cross(zeroAxis, rotAxis) + axis = np.cross(zeroAxis, rotAxis) # now use these axis to regenerate the orthogonal zero axis - zeroAxisOrtho = numpy.cross(rotAxis, axis) + zeroAxisOrtho = np.cross(rotAxis, axis) # now normalize the length of the zeroAxisOrtho - length = numpy.linalg.norm(zeroAxisOrtho) + length = np.linalg.norm(zeroAxisOrtho) zeroAxisOrtho /= length # ------- # Normalize the rotation axis # ------- - length = numpy.linalg.norm(rotAxis) + length = np.linalg.norm(rotAxis) rotAxis /= length # --------- @@ -3226,9 +3225,9 @@ def __init__(self, name, coords, lower, upper, scaled, scale, DVGeo, addToPyOpt) self.DVGeo.addPointSet(self.coords, self.name) # Now get the reference lengths - self.D0 = numpy.zeros(self.nCon) + self.D0 = np.zeros(self.nCon) for i in range(self.nCon): - self.D0[i] = numpy.linalg.norm(self.coords[2 * i] - self.coords[2 * i + 1]) + self.D0[i] = np.linalg.norm(self.coords[2 * i] - self.coords[2 * i + 1]) def evalFunctions(self, funcs, config): """ @@ -3241,9 +3240,9 @@ def evalFunctions(self, funcs, config): """ # Pull out the most recent set of coordinates: self.coords = self.DVGeo.update(self.name, config=config) - D = numpy.zeros(self.nCon) + D = np.zeros(self.nCon) for i in range(self.nCon): - D[i] = numpy.linalg.norm(self.coords[2 * i] - self.coords[2 * i + 1]) + D[i] = np.linalg.norm(self.coords[2 * i] - self.coords[2 * i + 1]) if self.scaled: D[i] /= self.D0[i] funcs[self.name] = D @@ -3261,7 +3260,7 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dTdPt = numpy.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) + dTdPt = np.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) for i in range(self.nCon): p1b, p2b = geo_utils.eDist_b(self.coords[2 * i, :], self.coords[2 * i + 1, :]) @@ -3337,8 +3336,8 @@ def computeReferenceFrames(self, coords): neta[i] /= geo_utils.euclideanNorm(neta[i]) # Compute component of eta in the xi direction - eta_on_xi = numpy.einsum("ij,ij->i", nxi, neta) - xi_of_eta = numpy.einsum("ij,i->ij", nxi, eta_on_xi) + eta_on_xi = np.einsum("ij,ij->i", nxi, neta) + xi_of_eta = np.einsum("ij,i->ij", nxi, eta_on_xi) # Remove component of eta in the xi direction neta = neta - xi_of_eta @@ -3371,14 +3370,14 @@ def computeCircle(self, coords): origin, nxi, neta = self.computeReferenceFrames(coords) # Compute xi component of p1, p2, and p3 - xi1 = numpy.einsum("ij,ij->i", p1 - origin, nxi) - xi2 = numpy.einsum("ij,ij->i", p2 - origin, nxi) - xi3 = numpy.einsum("ij,ij->i", p3 - origin, nxi) + xi1 = np.einsum("ij,ij->i", p1 - origin, nxi) + xi2 = np.einsum("ij,ij->i", p2 - origin, nxi) + xi3 = np.einsum("ij,ij->i", p3 - origin, nxi) # Compute eta component of p1, p2, and p3 - eta1 = numpy.einsum("ij,ij->i", p1 - origin, neta) - eta2 = numpy.einsum("ij,ij->i", p2 - origin, neta) - eta3 = numpy.einsum("ij,ij->i", p3 - origin, neta) + eta1 = np.einsum("ij,ij->i", p1 - origin, neta) + eta2 = np.einsum("ij,ij->i", p2 - origin, neta) + eta3 = np.einsum("ij,ij->i", p3 - origin, neta) # Compute the radius of curvature A = xi1 * (eta2 - eta3) - eta1 * (xi2 - xi3) + xi2 * eta3 - xi3 * eta2 @@ -3400,7 +3399,7 @@ def computeCircle(self, coords): xiC = -B / 2 / A etaC = -C / 2 / A - r = numpy.sqrt((B ** 2 + C ** 2 - 4 * A * D) / 4 / A ** 2) + r = np.sqrt((B ** 2 + C ** 2 - 4 * A * D) / 4 / A ** 2) # Convert center coordinates back center = origin + nxi * xiC[:, None] + neta * etaC[:, None] @@ -3441,7 +3440,7 @@ def evalFunctionsSens(self, funcsSens, config): # row 0: dr0dp0x dr0dp0y dr0dp0z dr0dp1x dr0dp1y dr0dp1z dr0dp2x ... # row 1: dr1dp0x dr1dp0y dr1dp0z dr1dp1x dr1dp1y dr1dp1z dr1dp2x ... # : - drdPt = numpy.zeros((self.nCon, 9)) + drdPt = np.zeros((self.nCon, 9)) coords = self.coords.astype("D") for i in range(3): # loop over pts at given slice @@ -3459,12 +3458,12 @@ def evalFunctionsSens(self, funcsSens, config): # We also have to scale the sensitivities if scale is True. if self.scaled: - eye = numpy.diag(1 / self.r0) + eye = np.diag(1 / self.r0) else: - eye = numpy.eye(self.nCon) - drdPt_sparse = numpy.einsum("ij,jk->ijk", eye, drdPt) + eye = np.eye(self.nCon) + drdPt_sparse = np.einsum("ij,jk->ijk", eye, drdPt) drdPt_sparse = drdPt_sparse.reshape(self.nCon, self.nCon * 3, 3) - drdPt_sparse = numpy.hstack( + drdPt_sparse = np.hstack( [ drdPt_sparse[:, ::3, :], drdPt_sparse[:, 1::3, :], @@ -3485,13 +3484,13 @@ def writeTecplot(self, handle): origin, nxi, neta = self.computeReferenceFrames(self.coords) nres = 50 - theta = numpy.linspace(0, 2 * numpy.pi, nres + 1)[:-1] + theta = np.linspace(0, 2 * np.pi, nres + 1)[:-1] handle.write("Zone T=%s\n" % self.name) handle.write("Nodes = %d, Elements = %d ZONETYPE=FELINESEG\n" % (self.nCon * nres, self.nCon * nres)) handle.write("DATAPACKING=POINT\n") for i in range(self.nCon): - cos_part = numpy.outer(numpy.cos(theta), nxi * r[i]) - sin_part = numpy.outer(numpy.sin(theta), neta * r[i]) + cos_part = np.outer(np.cos(theta), nxi * r[i]) + sin_part = np.outer(np.sin(theta), neta * r[i]) x = c[i, 0] + cos_part[:, 0] + sin_part[:, 0] y = c[i, 1] + cos_part[:, 1] + sin_part[:, 1] z = c[i, 2] + cos_part[:, 2] + sin_part[:, 2] @@ -3532,7 +3531,7 @@ def __init__(self, name, coords, lower, upper, scaled, scale, DVGeo, addToPyOpt) self.DVGeo.addPointSet(self.coords, self.name) # Now get the reference lengths - self.X0 = numpy.zeros(self.nCon) + self.X0 = np.zeros(self.nCon) X = self.coords.flatten() for i in range(self.nCon): self.X0[i] = X[i] @@ -3568,7 +3567,7 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dTdPt = numpy.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) + dTdPt = np.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) counter = 0 for i in range(self.coords.shape[0]): for j in range(self.coords.shape[1]): @@ -3623,10 +3622,10 @@ def __init__(self, name, coords, lower, upper, scale, DVGeo, addToPyOpt): self.DVGeo.addPointSet(self.coords, self.name) # Now get the reference lengths - self.ToC0 = numpy.zeros(self.nCon) + self.ToC0 = np.zeros(self.nCon) for i in range(self.nCon): - t = numpy.linalg.norm(self.coords[4 * i] - self.coords[4 * i + 1]) - c = numpy.linalg.norm(self.coords[4 * i + 2] - self.coords[4 * i + 3]) + t = np.linalg.norm(self.coords[4 * i] - self.coords[4 * i + 1]) + c = np.linalg.norm(self.coords[4 * i + 2] - self.coords[4 * i + 3]) self.ToC0[i] = t / c def evalFunctions(self, funcs, config): @@ -3640,7 +3639,7 @@ def evalFunctions(self, funcs, config): """ # Pull out the most recent set of coordinates: self.coords = self.DVGeo.update(self.name, config=config) - ToC = numpy.zeros(self.nCon) + ToC = np.zeros(self.nCon) for i in range(self.nCon): t = geo_utils.eDist(self.coords[4 * i], self.coords[4 * i + 1]) c = geo_utils.eDist(self.coords[4 * i + 2], self.coords[4 * i + 3]) @@ -3661,7 +3660,7 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dToCdPt = numpy.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) + dToCdPt = np.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) for i in range(self.nCon): t = geo_utils.eDist(self.coords[4 * i], self.coords[4 * i + 1]) @@ -4255,7 +4254,7 @@ def evalVolumeSens(self): coordinates """ x = self.coords.reshape((self.nSpan, self.nChord, 2, 3)) - xb = numpy.zeros_like(x) + xb = np.zeros_like(x) for j in range(self.nChord - 1): for i in range(self.nSpan - 1): self.evalVolumeHex_b( @@ -4298,7 +4297,7 @@ def evalVolumeHex(self, x0, x1, x2, x3, x4, x5, x6, x7): Array of defining the coordinates of the volume """ - p = numpy.average([x0, x1, x2, x3, x4, x5, x6, x7], axis=0) + p = np.average([x0, x1, x2, x3, x4, x5, x6, x7], axis=0) V = 0.0 V += self.volpym(x0, x1, x3, x2, p) V += self.volpym(x0, x2, x6, x4, p) @@ -4343,8 +4342,8 @@ def evalVolumeHex_b(self, x0, x1, x2, x3, x4, x5, x6, x7, x0b, x1b, x2b, x3b, x4 Derivatives of the volume wrt the points. """ - p = numpy.average([x0, x1, x2, x3, x4, x5, x6, x7], axis=0) - pb = numpy.zeros(3) + p = np.average([x0, x1, x2, x3, x4, x5, x6, x7], axis=0) + pb = np.zeros(3) self.volpym_b(x0, x1, x3, x2, p, x0b, x1b, x3b, x2b, pb) self.volpym_b(x0, x2, x6, x4, p, x0b, x2b, x6b, x4b, pb) self.volpym_b(x0, x4, x5, x1, p, x0b, x4b, x5b, x1b, pb) @@ -4528,7 +4527,7 @@ def evalFunctions(self, funcs): cons.extend(self.jac[key].dot(self.DVGeo.DV_listSpanwiseLocal[key].value)) else: raise Error(f"con {self.name} diffined wrt {key}, but {key} not found in DVGeo") - funcs[self.name] = numpy.array(cons).real.astype("d") + funcs[self.name] = np.array(cons).real.astype("d") def evalFunctionsSens(self, funcsSens): """ @@ -4579,7 +4578,7 @@ def _finalize(self): if ncon > 0: # Now form the jacobian: ndv = self.DVGeo.DV_listLocal[key].nVal - jacobian = numpy.zeros((ncon, ndv)) + jacobian = np.zeros((ncon, ndv)) for i in range(ncon): jacobian[i, cons[i][0]] = self.factorA[i] jacobian[i, cons[i][1]] = self.factorB[i] @@ -4600,7 +4599,7 @@ def _finalize(self): if ncon > 0: # Now form the jacobian: ndv = self.DVGeo.DV_listSectionLocal[key].nVal - jacobian = numpy.zeros((ncon, ndv)) + jacobian = np.zeros((ncon, ndv)) for i in range(ncon): jacobian[i, cons[i][0]] = self.factorA[i] jacobian[i, cons[i][1]] = self.factorB[i] @@ -4621,7 +4620,7 @@ def _finalize(self): if ncon > 0: # Now form the jacobian: ndv = self.DVGeo.DV_listSpanwiseLocal[key].nVal - jacobian = numpy.zeros((ncon, ndv)) + jacobian = np.zeros((ncon, ndv)) for i in range(ncon): jacobian[i, cons[i][0]] = self.factorA[i] jacobian[i, cons[i][1]] = self.factorB[i] @@ -4643,7 +4642,7 @@ def writeTecplot(self, handle): for key in self.vizConIndices: ncon = len(self.vizConIndices[key]) - nodes = numpy.zeros((ncon * 2, 3)) + nodes = np.zeros((ncon * 2, 3)) for i in range(ncon): nodes[2 * i] = self.DVGeo.FFD.coef[self.indSetA[i]] nodes[2 * i + 1] = self.DVGeo.FFD.coef[self.indSetB[i]] @@ -4687,7 +4686,7 @@ def __init__( self.thickScaled = thickScaled self.MACFracLower = MACFracLower self.MACFracUpper = MACFracUpper - self.coords = numpy.array([up, down]) + self.coords = np.array([up, down]) self.DVGeo = DVGeo self.addToPyOpt = addToPyOpt @@ -4697,7 +4696,7 @@ def __init__( self.DVGeo.addPointSet(self.coords, self.name) # Compute the reference length - self.D0 = numpy.linalg.norm(self.coords[0] - self.coords[1]) + self.D0 = np.linalg.norm(self.coords[0] - self.coords[1]) def evalFunctions(self, funcs, config): @@ -4705,7 +4704,7 @@ def evalFunctions(self, funcs, config): self.coords = self.DVGeo.update(self.name, config=config) # Compute the thickness constraint - D = numpy.linalg.norm(self.coords[0] - self.coords[1]) + D = np.linalg.norm(self.coords[0] - self.coords[1]) if self.thickScaled: D = D / self.D0 @@ -4747,7 +4746,7 @@ def evalFunctionsSens(self, funcsSens, config): p2b /= self.D0 funcsSens[self.name + "_thick"] = self.DVGeo.totalSensitivity( - numpy.array([[p1b, p2b]]), self.name, config=config + np.array([[p1b, p2b]]), self.name, config=config ) # And now we need the sensitivty of the conLoc calc @@ -4756,7 +4755,7 @@ def evalFunctionsSens(self, funcsSens, config): p1b[0] += 0.5 / wfuncs["MAC"] p2b[0] += 0.5 / wfuncs["MAC"] - tmpSens = self.DVGeo.totalSensitivity(numpy.array([[p1b, p2b]]), self.name, config=config) + tmpSens = self.DVGeo.totalSensitivity(np.array([[p1b, p2b]]), self.name, config=config) # And we need the sensitity of conLoc wrt 'xLEMAC' and 'MAC' postLoc = 0.5 * (self.coords[0, 0] + self.coords[1, 0]) @@ -4790,7 +4789,7 @@ class CircularityConstraint(GeometricConstraint): def __init__(self, name, center, coords, lower, upper, scale, DVGeo, addToPyOpt): self.name = name - self.center = numpy.array(center).reshape((1, 3)) + self.center = np.array(center).reshape((1, 3)) self.coords = coords self.nCon = self.coords.shape[0] - 1 self.lower = lower @@ -4803,7 +4802,7 @@ def __init__(self, name, center, coords, lower, upper, scale, DVGeo, addToPyOpt) self, self.name, self.nCon, self.lower, self.upper, self.scale, self.DVGeo, self.addToPyOpt ) - self.X = numpy.zeros(self.nCon) + self.X = np.zeros(self.nCon) # First thing we can do is embed the coordinates into DVGeo # with the name provided: @@ -4840,10 +4839,10 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dLndPt = numpy.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) - dLndCn = numpy.zeros((self.nCon, self.center.shape[0], self.center.shape[1])) + dLndPt = np.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) + dLndCn = np.zeros((self.nCon, self.center.shape[0], self.center.shape[1])) - xb = numpy.zeros(self.nCon) + xb = np.zeros(self.nCon) for con in range(self.nCon): centerb = dLndCn[con, 0, :] coordsb = dLndPt[con, :, :] @@ -4852,18 +4851,18 @@ def evalFunctionsSens(self, funcsSens, config): # reflength2 = 0 # for i in range(3): # reflength2 = reflength2 + (center[i]-coords[0,i])**2 - reflength2 = numpy.sum((self.center - self.coords[0, :]) ** 2) + reflength2 = np.sum((self.center - self.coords[0, :]) ** 2) reflength2b = 0.0 for i in range(self.nCon): # length2 = 0 # for j in range(3): # length2 = length2 + (center[j]-coords[i+1, j])**2 - length2 = numpy.sum((self.center - self.coords[i + 1, :]) ** 2) + length2 = np.sum((self.center - self.coords[i + 1, :]) ** 2) if length2 / reflength2 == 0.0: tempb1 = 0.0 else: - tempb1 = xb[i] / (2.0 * numpy.sqrt(length2 / reflength2) * reflength2) + tempb1 = xb[i] / (2.0 * np.sqrt(length2 / reflength2) * reflength2) length2b = tempb1 reflength2b = reflength2b - length2 * tempb1 / reflength2 xb[i] = 0.0 @@ -4888,10 +4887,10 @@ def _computeLengths(self, center, coords, X): """ compute the lengths from the center and coordinates """ - reflength2 = numpy.sum((center - coords[0, :]) ** 2) + reflength2 = np.sum((center - coords[0, :]) ** 2) for i in range(self.nCon): - length2 = numpy.sum((self.center - self.coords[i + 1, :]) ** 2) - X[i] = numpy.sqrt(length2 / reflength2) + length2 = np.sum((self.center - self.coords[i + 1, :]) ** 2) + X[i] = np.sqrt(length2 / reflength2) def writeTecplot(self, handle): """ @@ -4939,7 +4938,7 @@ def __init__(self, name, axis, origin, p0, v1, v2, lower, upper, scale, DVGeo, a ) # create the output array - self.X = numpy.zeros(self.nCon) + self.X = np.zeros(self.nCon) self.n = len(p0) # The first thing we do is convert v1 and v2 to coords @@ -4973,7 +4972,7 @@ def evalFunctions(self, funcs, config): self.p2 = self.DVGeo.update(self.name + "p2", config=config) self.origin = self.DVGeo.update(self.name + "origin", config=config) - allPoints = numpy.vstack([self.p0, self.p1, self.p2]) + allPoints = np.vstack([self.p0, self.p1, self.p2]) # Compute the distance from the origin to each point dist = allPoints - self.origin @@ -4981,8 +4980,8 @@ def evalFunctions(self, funcs, config): # project it onto the axis self.X[0] = 0 for i in range(self.n * 3): - self.X[0] += numpy.dot(self.axis, dist[i, :]) ** 2 - self.X[0] = numpy.sqrt(self.X[0]) + self.X[0] += np.dot(self.axis, dist[i, :]) ** 2 + self.X[0] = np.sqrt(self.X[0]) funcs[self.name] = self.X def evalFunctionsSens(self, funcsSens, config): @@ -4998,18 +4997,18 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dPdp0 = numpy.zeros((self.nCon, self.p0.shape[0], self.p0.shape[1])) - dPdp1 = numpy.zeros((self.nCon, self.p1.shape[0], self.p1.shape[1])) + dPdp0 = np.zeros((self.nCon, self.p0.shape[0], self.p0.shape[1])) + dPdp1 = np.zeros((self.nCon, self.p1.shape[0], self.p1.shape[1])) - dPdp2 = numpy.zeros((self.nCon, self.p2.shape[0], self.p2.shape[1])) + dPdp2 = np.zeros((self.nCon, self.p2.shape[0], self.p2.shape[1])) - dPdO = numpy.zeros((self.nCon, self.origin.shape[0], self.origin.shape[1])) + dPdO = np.zeros((self.nCon, self.origin.shape[0], self.origin.shape[1])) # copy data into all points array # allpoints(1:n) = p0 # allpoints(n:2*n) = p1 # allpoints(2*n:3*n) = p2 - allPoints = numpy.vstack([self.p0, self.p1, self.p2]) + allPoints = np.vstack([self.p0, self.p1, self.p2]) # Compute the distance from the origin to each point # for i in range(n*3):#DO i=1,n*3 @@ -5017,18 +5016,18 @@ def evalFunctionsSens(self, funcsSens, config): # dist(i, j) = allpoints(i, j) - origin(j) dist = allPoints - self.origin - scalardist = numpy.zeros(self.n * 3) + scalardist = np.zeros(self.n * 3) tmpX = 0 for i in range(self.n * 3): - scalardist[i] = numpy.dot(self.axis, dist[i, :]) + scalardist[i] = np.dot(self.axis, dist[i, :]) tmpX += scalardist[i] ** 2 - xb = numpy.zeros(self.nCon) - axisb = numpy.zeros(3) + xb = np.zeros(self.nCon) + axisb = np.zeros(3) - scalardistb = numpy.zeros((self.n * 3)) - allpointsb = numpy.zeros((self.n * 3, 3)) - distb = numpy.zeros((self.n * 3, 3)) + scalardistb = np.zeros((self.n * 3)) + allpointsb = np.zeros((self.n * 3, 3)) + distb = np.zeros((self.n * 3, 3)) for con in range(self.nCon): p0b = dPdp0[con, :, :] p1b = dPdp1[con, :, :] @@ -5044,7 +5043,7 @@ def evalFunctionsSens(self, funcsSens, config): if self.X[0] == 0.0: xb[con] = 0.0 else: - xb[con] = xb[con] / (2.0 * numpy.sqrt(tmpX)) + xb[con] = xb[con] / (2.0 * np.sqrt(tmpX)) for i in reversed(range(self.n * 3)): # DO i=3*n,1,-1 scalardistb[i] = scalardistb[i] + 2.0 * scalardist[i] * xb[con] # /(self.n*3) @@ -5130,7 +5129,7 @@ def __init__(self, name, axis, origin, coords, lower, upper, scale, DVGeo, addTo ) # create the output array - self.X = numpy.zeros(self.nCon) + self.X = np.zeros(self.nCon) # The first thing we do is convert v1 and v2 to coords self.axis = axis @@ -5160,7 +5159,7 @@ def evalFunctions(self, funcs, config): # # compute the cross product with the desired axis. Cross product # # will be zero if the direction vector is the same as the axis - # resultDir = numpy.cross(self.axis,dirVec) + # resultDir = np.cross(self.axis,dirVec) # for i in range(len(resultDir)): # self.X[i] = geo_utils.euclideanNorm(resultDir[i,:]) @@ -5181,9 +5180,9 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dCdPt = numpy.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) - dCdOrigin = numpy.zeros((self.nCon, self.origin.shape[0], self.origin.shape[1])) - dCdAxis = numpy.zeros((self.nCon, self.axis.shape[0], self.axis.shape[1])) + dCdPt = np.zeros((self.nCon, self.coords.shape[0], self.coords.shape[1])) + dCdOrigin = np.zeros((self.nCon, self.origin.shape[0], self.origin.shape[1])) + dCdAxis = np.zeros((self.nCon, self.axis.shape[0], self.axis.shape[1])) # Compute the direction from each point to the origin # for i in range(n): @@ -5194,20 +5193,20 @@ def evalFunctionsSens(self, funcsSens, config): # axisb = 0.0 # dirvecb = 0.0 # for i in range(self.nCon): - # resultdir = numpy.cross(axis, dirvec[i, :]) + # resultdir = np.cross(axis, dirvec[i, :]) # self.X[i] = 0 # for j in range(3): # self.X[i] = self.X[i] + resultdir[j]**2 - resultDir = numpy.cross(self.axis, dirVec) - tmpX = numpy.zeros(self.nCon) + resultDir = np.cross(self.axis, dirVec) + tmpX = np.zeros(self.nCon) for i in range(len(resultDir)): # self.X[i] = geo_utils.euclideanNorm(resultDir[i,:]) for j in range(3): tmpX[i] += resultDir[i, j] ** 2 - resultdirb = numpy.zeros(3) - dirvecb = numpy.zeros_like(dirVec) - xb = numpy.zeros(self.nCon) + resultdirb = np.zeros(3) + dirvecb = np.zeros_like(dirVec) + xb = np.zeros(self.nCon) for con in range(self.nCon): originb = dCdOrigin[con, 0, :] coordsb = dCdPt[con, :, :] @@ -5219,7 +5218,7 @@ def evalFunctionsSens(self, funcsSens, config): if tmpX[i] == 0.0: xb[i] = 0.0 else: - xb[i] = xb[i] / (2.0 * numpy.sqrt(tmpX[i])) + xb[i] = xb[i] / (2.0 * np.sqrt(tmpX[i])) resultdirb[:] = 0.0 for j in reversed(range(3)): # DO j=3,1,-1 @@ -5282,9 +5281,9 @@ def _computeDist(self, origin, coords, axis, dtype="d"): # compute the cross product with the desired axis. Cross product # will be zero if the direction vector is the same as the axis - resultDir = numpy.cross(axis, dirVec) + resultDir = np.cross(axis, dirVec) - X = numpy.zeros(len(coords), dtype) + X = np.zeros(len(coords), dtype) for i in range(len(resultDir)): X[i] = geo_utils.euclideanNorm(resultDir[i, :]) @@ -5314,7 +5313,7 @@ def __init__(self, name, p0, v1, v2, lower, upper, scale, scaled, DVGeo, addToPy ) # create output array - self.X = numpy.zeros(self.nCon) + self.X = np.zeros(self.nCon) self.n = len(p0) # The first thing we do is convert v1 and v2 to coords @@ -5364,10 +5363,10 @@ def evalFunctionsSens(self, funcsSens, config): nDV = self.DVGeo.getNDV() if nDV > 0: - dAdp0 = numpy.zeros((self.nCon, self.p0.shape[0], self.p0.shape[1])) - dAdp1 = numpy.zeros((self.nCon, self.p1.shape[0], self.p1.shape[1])) + dAdp0 = np.zeros((self.nCon, self.p0.shape[0], self.p0.shape[1])) + dAdp1 = np.zeros((self.nCon, self.p1.shape[0], self.p1.shape[1])) - dAdp2 = numpy.zeros((self.nCon, self.p2.shape[0], self.p2.shape[1])) + dAdp2 = np.zeros((self.nCon, self.p2.shape[0], self.p2.shape[1])) p0 = self.p0 p1 = self.p1 @@ -5377,10 +5376,10 @@ def evalFunctionsSens(self, funcsSens, config): p1b = dAdp1[con, :, :] p2b = dAdp2[con, :, :] areab = 1 - areasb = numpy.empty(self.n) - crossesb = numpy.empty((self.n, 3)) - v1b = numpy.empty((self.n, 3)) - v2b = numpy.empty((self.n, 3)) + areasb = np.empty(self.n) + crossesb = np.empty((self.n, 3)) + v1b = np.empty((self.n, 3)) + v2b = np.empty((self.n, 3)) if self.scaled: areab = areab / self.X0 areasb[:] = areab / 2.0 @@ -5388,16 +5387,16 @@ def evalFunctionsSens(self, funcsSens, config): v1 = p1 - p0 v2 = p2 - p0 - crosses = numpy.cross(v1, v2) + crosses = np.cross(v1, v2) # for j in range(3): # areas(i) = areas(i) + crosses(i, j)**2 - # areas[i] = numpy.sum(crosses[i, :]**2) - areas = numpy.sum(crosses ** 2, axis=1) + # areas[i] = np.sum(crosses[i, :]**2) + areas = np.sum(crosses ** 2, axis=1) for i in range(self.n): # DO i=1,n if areas[i] == 0.0: areasb[i] = 0.0 else: - areasb[i] = areasb[i] / (2.0 * numpy.sqrt(areas[i])) + areasb[i] = areasb[i] / (2.0 * np.sqrt(areas[i])) # for j in reversed(range(3)):#DO j=3,1,-1 # crossesb(i, j) = crossesb(i, j) + 2*crosses(i, j)*areasb(i) @@ -5433,14 +5432,14 @@ def _computeArea(self, p0, p1, p2): v2 = p2 - p0 # compute the areas - areaVec = numpy.cross(v1, v2) + areaVec = np.cross(v1, v2) - # area = numpy.linalg.norm(areaVec,axis=1) + # area = np.linalg.norm(areaVec,axis=1) area = 0 for i in range(len(areaVec)): area += geo_utils.euclideanNorm(areaVec[i, :]) - # return numpy.sum(area)/2.0 + # return np.sum(area)/2.0 return area / 2.0 def writeTecplot(self, handle): @@ -5487,10 +5486,10 @@ def __init__(self, name, p0, v1, v2, axis, lower, upper, scale, scaled, DVGeo, a ) # create output array - self.X = numpy.zeros(self.nCon) + self.X = np.zeros(self.nCon) self.n = len(p0) self.axis = axis - self.activeTris = numpy.zeros(self.n) + self.activeTris = np.zeros(self.n) # The first thing we do is convert v1 and v2 to coords self.p0 = p0 @@ -5538,10 +5537,10 @@ def evalFunctionsSens(self, funcsSens, config): """ nDV = self.DVGeo.getNDV() if nDV > 0: - dAdp0 = numpy.zeros((self.nCon, self.p0.shape[0], self.p0.shape[1])) - dAdp1 = numpy.zeros((self.nCon, self.p1.shape[0], self.p1.shape[1])) + dAdp0 = np.zeros((self.nCon, self.p0.shape[0], self.p0.shape[1])) + dAdp1 = np.zeros((self.nCon, self.p1.shape[0], self.p1.shape[1])) - dAdp2 = numpy.zeros((self.nCon, self.p2.shape[0], self.p2.shape[1])) + dAdp2 = np.zeros((self.nCon, self.p2.shape[0], self.p2.shape[1])) p0 = self.p0 p1 = self.p1 p2 = self.p2 @@ -5550,7 +5549,7 @@ def evalFunctionsSens(self, funcsSens, config): p1b = dAdp1[con, :, :] p2b = dAdp2[con, :, :] areab = 1 - areasb = numpy.empty(self.n) + areasb = np.empty(self.n) if self.scaled: areab = areab / self.X0 areasb[:] = areab / 2.0 @@ -5558,8 +5557,8 @@ def evalFunctionsSens(self, funcsSens, config): for i in range(self.n): v1 = p1[i, :] - p0[i, :] v2 = p2[i, :] - p0[i, :] - SAvec = numpy.cross(v1, v2) - PA = numpy.dot(SAvec, self.axis) + SAvec = np.cross(v1, v2) + PA = np.dot(SAvec, self.axis) if PA > 0: PAb = areasb[i] else: @@ -5589,10 +5588,10 @@ def _computeArea(self, p0, p1, p2, axis, plot=False): v2 = p2 - p0 # Compute the surface area vectors for each triangle patch - surfaceAreas = numpy.cross(v1, v2) + surfaceAreas = np.cross(v1, v2) # Compute the projected area of each triangle patch - projectedAreas = numpy.dot(surfaceAreas, axis) + projectedAreas = np.dot(surfaceAreas, axis) # Cut out negative projected areas to get one side of surface if plot: @@ -5605,7 +5604,7 @@ def _computeArea(self, p0, p1, p2, axis, plot=False): projectedAreas[projectedAreas < 0] = 0.0 # Sum projected areas and divide by two for triangle area - totalProjectedArea = numpy.sum(projectedAreas) / 2.0 + totalProjectedArea = np.sum(projectedAreas) / 2.0 return totalProjectedArea @@ -5615,22 +5614,22 @@ def writeTecplot(self, handle): to the open file handle """ self._computeArea(self.p0, self.p1, self.p2, self.axis, plot=True) - nActiveTris = int(numpy.sum(self.activeTris)) + nActiveTris = int(np.sum(self.activeTris)) p0 = self.p0.copy() p1 = self.p1.copy() p2 = self.p2.copy() if self.axis[0] == 1.0: - p0[:, 0] = numpy.zeros(self.n) - p1[:, 0] = numpy.zeros(self.n) - p2[:, 0] = numpy.zeros(self.n) + p0[:, 0] = np.zeros(self.n) + p1[:, 0] = np.zeros(self.n) + p2[:, 0] = np.zeros(self.n) if self.axis[1] == 1.0: - p0[:, 1] = numpy.zeros(self.n) - p1[:, 1] = numpy.zeros(self.n) - p2[:, 1] = numpy.zeros(self.n) + p0[:, 1] = np.zeros(self.n) + p1[:, 1] = np.zeros(self.n) + p2[:, 1] = np.zeros(self.n) if self.axis[2] == 1.0: - p0[:, 2] = numpy.zeros(self.n) - p1[:, 2] = numpy.zeros(self.n) - p2[:, 2] = numpy.zeros(self.n) + p0[:, 2] = np.zeros(self.n) + p1[:, 2] = np.zeros(self.n) + p2[:, 2] = np.zeros(self.n) handle.write("Zone T=%s_surface\n" % self.name) handle.write("Nodes = %d, Elements = %d ZONETYPE=FETRIANGLE\n" % (3 * nActiveTris, nActiveTris)) @@ -5668,23 +5667,23 @@ def __init__(self, name, surfs, curvatureType, lower, upper, scaled, scale, KSCo for iSurf in range(self.nSurfs): # A list of the coordinates arrays for each surface, flattened in order # to vectorize operations - self.X += [numpy.reshape(surfs[iSurf].X, -1)] + self.X += [np.reshape(surfs[iSurf].X, -1)] # A list of maping arrays used to translate from the structured index # to the flatten index number of X # For example: X[iSurf][X_map[iSurf][i,j,2]] gives the z coordinate # of the node in the i-th row and j-th column on surface iSurf - self.X_map += [numpy.reshape(numpy.array(range(surfs[iSurf].X.size)), surfs[iSurf].X.shape)] + self.X_map += [np.reshape(np.array(range(surfs[iSurf].X.size)), surfs[iSurf].X.shape)] # A list of maping arrays used to provide a unique node number for # every node on each surface # For example: node_map[iSurf][i,j] gives the node number # of the node in the i-th row and j-th column on surface iSurf self.node_map += [ - numpy.reshape( - numpy.array(range(surfs[iSurf].X.size // 3)), (surfs[iSurf].X.shape[0], surfs[iSurf].X.shape[1]) + np.reshape( + np.array(range(surfs[iSurf].X.size // 3)), (surfs[iSurf].X.shape[0], surfs[iSurf].X.shape[1]) ) ] # A list of the coordinates arrays for each surface, in the shape that DVGeo expects (N_nodes,3) - self.coords += [numpy.reshape(self.X[iSurf], (surfs[iSurf].X.shape[0] * surfs[iSurf].X.shape[1], 3))] + self.coords += [np.reshape(self.X[iSurf], (surfs[iSurf].X.shape[0] * surfs[iSurf].X.shape[1], 3))] self.nCon = 1 self.curvatureType = curvatureType self.lower = lower @@ -5730,7 +5729,7 @@ def evalFunctions(self, funcs, config): funcs[self.name] = 0 for iSurf in range(self.nSurfs): self.coords[iSurf] = self.DVGeo.update(self.name + "%d" % (iSurf), config=config) - self.X[iSurf] = numpy.reshape(self.coords[iSurf], -1) + self.X[iSurf] = np.reshape(self.coords[iSurf], -1) if self.scaled: funcs[self.name] += self.evalCurvArea(iSurf)[0] / self.curvatureRef else: @@ -5755,7 +5754,7 @@ def evalFunctionsSens(self, funcsSens, config): if self.scaled: DkSDX /= self.curvatureRef # Reshape the Xpt sensitivity to the shape DVGeo is expecting - DkSDpt = numpy.reshape(DkSDX, self.coords[iSurf].shape) + DkSDpt = np.reshape(DkSDX, self.coords[iSurf].shape) if iSurf == 0: funcsSens[self.name] = self.DVGeo.totalSensitivity( DkSDpt, self.name + "%d" % (iSurf), config=config @@ -5779,7 +5778,7 @@ def evalCurvArea(self, iSurf): # Compute the norm of tu_ x tv n_norm = self.evalNorm(iSurf, n) # Normalize the normal vector - n_hat = numpy.zeros_like(n) + n_hat = np.zeros_like(n) n_hat[self.X_map[iSurf][:, :, 0]] = n[self.X_map[iSurf][:, :, 0]] / n_norm[self.node_map[iSurf][:, :]] n_hat[self.X_map[iSurf][:, :, 1]] = n[self.X_map[iSurf][:, :, 1]] / n_norm[self.node_map[iSurf][:, :]] n_hat[self.X_map[iSurf][:, :, 2]] = n[self.X_map[iSurf][:, :, 2]] / n_norm[self.node_map[iSurf][:, :]] @@ -5806,31 +5805,31 @@ def evalCurvArea(self, iSurf): # 1 for center nodes # 1/2 for edge nodes # 1/4 for corner nodes - wt = numpy.zeros_like(n_norm) + 1 + wt = np.zeros_like(n_norm) + 1 wt[self.node_map[iSurf][0, :]] *= 0.5 wt[self.node_map[iSurf][-1, :]] *= 0.5 wt[self.node_map[iSurf][:, 0]] *= 0.5 wt[self.node_map[iSurf][:, -1]] *= 0.5 # Compute discrete area associated with each node dS = wt * n_norm - one = numpy.ones(self.node_map[iSurf].size) + one = np.ones(self.node_map[iSurf].size) if self.curvatureType == "Gaussian": # Now compute integral (K**2) over S, equivelent to sum(K**2*dS) - kS = numpy.dot(one, K * K * dS) + kS = np.dot(one, K * K * dS) return [kS, K, H, C] elif self.curvatureType == "mean": # Now compute integral (H**2) over S, equivelent to sum(H**2*dS) - hS = numpy.dot(one, H * H * dS) + hS = np.dot(one, H * H * dS) return [hS, K, H, C] elif self.curvatureType == "combined": # Now compute integral C over S, equivelent to sum(C*dS) - cS = numpy.dot(one, C * dS) + cS = np.dot(one, C * dS) return [cS, K, H, C] elif self.curvatureType == "KSmean": # Now compute the KS function for mean curvature, equivelent to KS(H*H*dS) - sigmaH = numpy.dot(one, numpy.exp(self.KSCoeff * H * H * dS)) - KSmean = numpy.log(sigmaH) / self.KSCoeff + sigmaH = np.dot(one, np.exp(self.KSCoeff * H * H * dS)) + KSmean = np.log(sigmaH) / self.KSCoeff if MPI.COMM_WORLD.rank == 0: print("Max curvature: ", max(H * H * dS)) return [KSmean, K, H, C] @@ -5860,7 +5859,7 @@ def evalCurvAreaSens(self, iSurf): Dn_normDn = self.evalNormSens(iSurf, n) Dn_normDX = Dn_normDn.dot(DnDX) # Normalize the normal vector - n_hat = numpy.zeros_like(n) + n_hat = np.zeros_like(n) n_hat[self.X_map[iSurf][:, :, 0]] = n[self.X_map[iSurf][:, :, 0]] / n_norm[self.node_map[iSurf][:, :]] n_hat[self.X_map[iSurf][:, :, 1]] = n[self.X_map[iSurf][:, :, 1]] / n_norm[self.node_map[iSurf][:, :]] n_hat[self.X_map[iSurf][:, :, 2]] = n[self.X_map[iSurf][:, :, 2]] / n_norm[self.node_map[iSurf][:, :]] @@ -5869,8 +5868,8 @@ def evalCurvAreaSens(self, iSurf): data = [] for i in range(3): # Dn_hat[self.X_map[iSurf][:,:,i]]/Dn[self.X_map[iSurf][:,:,i]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, i], -1)) - data += list(numpy.reshape(n_norm[self.node_map[iSurf][:, :]] ** -1, -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, i], -1)) + data += list(np.reshape(n_norm[self.node_map[iSurf][:, :]] ** -1, -1)) Dn_hatDn = csr_matrix((data, [ii, ii]), shape=(self.X[iSurf].size, self.X[iSurf].size)) ii = [] @@ -5878,9 +5877,9 @@ def evalCurvAreaSens(self, iSurf): data = [] for i in range(3): # Dn_hat[self.X_map[iSurf][:,:,i]]/Dn_norm[self.node_map[iSurf][:,:]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, i], -1)) - jj += list(numpy.reshape(self.node_map[iSurf][:, :], -1)) - data += list(numpy.reshape(-n[self.X_map[iSurf][:, :, i]] / (n_norm[self.node_map[iSurf][:, :]] ** 2), -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, i], -1)) + jj += list(np.reshape(self.node_map[iSurf][:, :], -1)) + data += list(np.reshape(-n[self.X_map[iSurf][:, :, i]] / (n_norm[self.node_map[iSurf][:, :]] ** 2), -1)) Dn_hatDn_norm = csr_matrix((data, [ii, jj]), shape=(n_hat.size, n_norm.size)) Dn_hatDX = Dn_hatDn.dot(DnDX) + Dn_hatDn_norm.dot(Dn_normDX) @@ -5951,7 +5950,7 @@ def evalCurvAreaSens(self, iSurf): # 1 for center nodes # 1/2 for edge nodes # 1/4 for corner nodes - wt = numpy.zeros_like(n_norm) + 1 + wt = np.zeros_like(n_norm) + 1 wt[self.node_map[iSurf][0, :]] *= 0.5 wt[self.node_map[iSurf][-1, :]] *= 0.5 wt[self.node_map[iSurf][:, 0]] *= 0.5 @@ -5960,16 +5959,16 @@ def evalCurvAreaSens(self, iSurf): dS = wt * n_norm DdSDX = self.diags(wt).dot(Dn_normDX) - one = numpy.ones(self.node_map[iSurf].size) + one = np.ones(self.node_map[iSurf].size) if self.curvatureType == "Gaussian": # Now compute integral (K**2) over S, equivelent to sum(K**2*dS) - # kS = numpy.dot(one, K * K * dS) + # kS = np.dot(one, K * K * dS) DkSDX = (self.diags(2 * K * dS).dot(DKDX) + self.diags(K * K).dot(DdSDX)).T.dot(one) return DkSDX elif self.curvatureType == "mean": # Now compute integral (H**2) over S, equivelent to sum(H**2*dS) - # hS = numpy.dot(one, H * H * dS) + # hS = np.dot(one, H * H * dS) DhSDX = (self.diags(2 * H * dS).dot(DHDX) + self.diags(H * H).dot(DdSDX)).T.dot(one) return DhSDX elif self.curvatureType == "combined": @@ -5980,10 +5979,10 @@ def evalCurvAreaSens(self, iSurf): DcSDX = term1 - term2 return DcSDX elif self.curvatureType == "KSmean": - sigmaH = numpy.dot(one, numpy.exp(self.KSCoeff * H * H * dS)) + sigmaH = np.dot(one, np.exp(self.KSCoeff * H * H * dS)) DhSDX = ( - self.diags(2 * H * dS / sigmaH * numpy.exp(self.KSCoeff * H * H * dS)).dot(DHDX) - + self.diags(H * H / sigmaH * numpy.exp(self.KSCoeff * H * H * dS)).dot(DdSDX) + self.diags(2 * H * dS / sigmaH * np.exp(self.KSCoeff * H * H * dS)).dot(DHDX) + + self.diags(H * H / sigmaH * np.exp(self.KSCoeff * H * H * dS)).dot(DdSDX) ).T.dot(one) return DhSDX else: @@ -5997,7 +5996,7 @@ def evalCross(self, iSurf, u, v): Evaluate the cross product of two vector fields on the surface (n = u x v) """ - n = numpy.zeros_like(self.X[iSurf]) + n = np.zeros_like(self.X[iSurf]) n[self.X_map[iSurf][:, :, 0]] = ( u[self.X_map[iSurf][:, :, 1]] * v[self.X_map[iSurf][:, :, 2]] - u[self.X_map[iSurf][:, :, 2]] * v[self.X_map[iSurf][:, :, 1]] @@ -6022,29 +6021,29 @@ def evalCrossSens(self, iSurf, u, v): jj = [] data = [] # Dn[self.X_map[iSurf][:,:,0]]/Dv[self.X_map[iSurf][:,:,2]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:, :, 1]], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, 0], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 2], -1)) + data += list(np.reshape(u[self.X_map[iSurf][:, :, 1]], -1)) # Dn[self.X_map[iSurf][:,:,0]]/Dv[self.X_map[iSurf][:,:,1]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) - data += list(numpy.reshape(-u[self.X_map[iSurf][:, :, 2]], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, 0], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 1], -1)) + data += list(np.reshape(-u[self.X_map[iSurf][:, :, 2]], -1)) # Dn[self.X_map[iSurf][:,:,1]]/Dv[self.X_map[iSurf][:,:,2]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) - data += list(numpy.reshape(-u[self.X_map[iSurf][:, :, 0]], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, 1], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 2], -1)) + data += list(np.reshape(-u[self.X_map[iSurf][:, :, 0]], -1)) # Dn[self.X_map[iSurf][:,:,1]]/Dv[self.X_map[iSurf][:,:,0]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:, :, 2]], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, 1], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 0], -1)) + data += list(np.reshape(u[self.X_map[iSurf][:, :, 2]], -1)) # Dn[self.X_map[iSurf][:,:,2]]/Dv[self.X_map[iSurf][:,:,1]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:, :, 0]], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, 2], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 1], -1)) + data += list(np.reshape(u[self.X_map[iSurf][:, :, 0]], -1)) # Dn[self.X_map[iSurf][:,:,2]]/Dv[self.X_map[iSurf][:,:,0]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) - data += list(numpy.reshape(-u[self.X_map[iSurf][:, :, 1]], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, 2], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 0], -1)) + data += list(np.reshape(-u[self.X_map[iSurf][:, :, 1]], -1)) DnDv = csr_matrix((data, [ii, jj]), shape=(self.X[iSurf].size, self.X[iSurf].size)) # Now wrt v @@ -6052,29 +6051,29 @@ def evalCrossSens(self, iSurf, u, v): jj = [] data = [] # Dn[self.X_map[iSurf][:,:,0]]/Du[self.X_map[iSurf][:,:,1]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) - data += list(numpy.reshape(v[self.X_map[iSurf][:, :, 2]], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, 0], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 1], -1)) + data += list(np.reshape(v[self.X_map[iSurf][:, :, 2]], -1)) # Dn[self.X_map[iSurf][:,:,0]]/Du[self.X_map[iSurf][:,:,2]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) - data += list(numpy.reshape(-v[self.X_map[iSurf][:, :, 1]], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, 0], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 2], -1)) + data += list(np.reshape(-v[self.X_map[iSurf][:, :, 1]], -1)) # Dn[self.X_map[iSurf][:,:,1]]/Du[self.X_map[iSurf][:,:,0]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) - data += list(numpy.reshape(-v[self.X_map[iSurf][:, :, 2]], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, 1], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 0], -1)) + data += list(np.reshape(-v[self.X_map[iSurf][:, :, 2]], -1)) # Dn[self.X_map[iSurf][:,:,1]]/Du[self.X_map[iSurf][:,:,2]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) - data += list(numpy.reshape(v[self.X_map[iSurf][:, :, 0]], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, 1], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 2], -1)) + data += list(np.reshape(v[self.X_map[iSurf][:, :, 0]], -1)) # Dn[self.X_map[iSurf][:,:,2]]/Du[self.X_map[iSurf][:,:,0]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) - data += list(numpy.reshape(v[self.X_map[iSurf][:, :, 1]], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, 2], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 0], -1)) + data += list(np.reshape(v[self.X_map[iSurf][:, :, 1]], -1)) # Dn[self.X_map[iSurf][:,:,2]]/Du[self.X_map[iSurf][:,:,1]] - ii += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) - data += list(numpy.reshape(-v[self.X_map[iSurf][:, :, 0]], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, :, 2], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 1], -1)) + data += list(np.reshape(-v[self.X_map[iSurf][:, :, 0]], -1)) DnDu = csr_matrix((data, [ii, jj]), shape=(self.X[iSurf].size, self.X[iSurf].size)) return [DnDu, DnDv] @@ -6084,8 +6083,8 @@ def evalNorm(self, iSurf, u): Evaluate the norm of vector field on the surface (u o u)**1/2 """ - u_norm = numpy.zeros(self.X[iSurf].size // 3) - u_norm[self.node_map[iSurf][:, :]] = numpy.sqrt( + u_norm = np.zeros(self.X[iSurf].size // 3) + u_norm[self.node_map[iSurf][:, :]] = np.sqrt( u[self.X_map[iSurf][:, :, 0]] ** 2 + u[self.X_map[iSurf][:, :, 1]] ** 2 + u[self.X_map[iSurf][:, :, 2]] ** 2 ) return u_norm @@ -6094,27 +6093,27 @@ def evalNormSens(self, iSurf, u): """ Evaluate the sensitivity of the norm wrt input vector u """ - u_norm = numpy.zeros(self.X[iSurf].size // 3) - u_norm[self.node_map[iSurf][:, :]] = numpy.sqrt( + u_norm = np.zeros(self.X[iSurf].size // 3) + u_norm[self.node_map[iSurf][:, :]] = np.sqrt( u[self.X_map[iSurf][:, :, 0]] ** 2 + u[self.X_map[iSurf][:, :, 1]] ** 2 + u[self.X_map[iSurf][:, :, 2]] ** 2 ) ii = [] jj = [] data = [] # Du_norm[self.node_map[iSurf][:,:]]Du[self.X_map[iSurf][:,:,0]] - ii += list(numpy.reshape(self.node_map[iSurf][:, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 0], -1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:, :, 0]] / u_norm[self.node_map[iSurf][:, :]], -1)) + ii += list(np.reshape(self.node_map[iSurf][:, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 0], -1)) + data += list(np.reshape(u[self.X_map[iSurf][:, :, 0]] / u_norm[self.node_map[iSurf][:, :]], -1)) # Du_norm[self.node_map[iSurf][:,:]]Du[self.X_map[iSurf][:,:,1]] - ii += list(numpy.reshape(self.node_map[iSurf][:, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 1], -1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:, :, 1]] / u_norm[self.node_map[iSurf][:, :]], -1)) + ii += list(np.reshape(self.node_map[iSurf][:, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 1], -1)) + data += list(np.reshape(u[self.X_map[iSurf][:, :, 1]] / u_norm[self.node_map[iSurf][:, :]], -1)) # Du_norm[self.node_map[iSurf][:,:]]Du[self.X_map[iSurf][:,:,2]] - ii += list(numpy.reshape(self.node_map[iSurf][:, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, 2], -1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:, :, 2]] / u_norm[self.node_map[iSurf][:, :]], -1)) + ii += list(np.reshape(self.node_map[iSurf][:, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, 2], -1)) + data += list(np.reshape(u[self.X_map[iSurf][:, :, 2]] / u_norm[self.node_map[iSurf][:, :]], -1)) Du_normDu = csr_matrix((data, [ii, jj]), shape=(u_norm.size, self.X[iSurf].size)) return Du_normDu @@ -6124,7 +6123,7 @@ def evalInProd(self, iSurf, u, v): Evaluate the inner product of two vector fields on the surface (ip = u o v) """ - ip = numpy.zeros(self.node_map[iSurf].size) + ip = np.zeros(self.node_map[iSurf].size) for i in range(3): ip[self.node_map[iSurf][:, :]] += u[self.X_map[iSurf][:, :, i]] * v[self.X_map[iSurf][:, :, i]] return ip @@ -6139,18 +6138,18 @@ def evalInProdSens(self, iSurf, u, v): data = [] for i in range(3): # Dip[node_map[:,:]]/Du[self.X_map[iSurf][:,:,i]] - ii += list(numpy.reshape(self.node_map[iSurf][:, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, i], -1)) - data += list(numpy.reshape(v[self.X_map[iSurf][:, :, i]], -1)) + ii += list(np.reshape(self.node_map[iSurf][:, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, i], -1)) + data += list(np.reshape(v[self.X_map[iSurf][:, :, i]], -1)) DipDu = csr_matrix((data, [ii, jj]), shape=(self.node_map[iSurf].size, self.X_map[iSurf].size)) ii = [] jj = [] data = [] for i in range(3): # Dip[node_map[:,:]]/Dv[self.X_map[iSurf][:,:,i]] - ii += list(numpy.reshape(self.node_map[iSurf][:, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, :, i], -1)) - data += list(numpy.reshape(u[self.X_map[iSurf][:, :, i]], -1)) + ii += list(np.reshape(self.node_map[iSurf][:, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, :, i], -1)) + data += list(np.reshape(u[self.X_map[iSurf][:, :, i]], -1)) DipDv = csr_matrix((data, [ii, jj]), shape=(self.node_map[iSurf].size, self.X_map[iSurf].size)) return [DipDu, DipDv] @@ -6160,7 +6159,7 @@ def evalDiff(self, iSurf, v, wrt): Second order accurate. Central difference for nodes in the center forward/backward difference for nodes on the edge """ - v_wrt = numpy.zeros_like(v) + v_wrt = np.zeros_like(v) if wrt == "u": v_wrt[self.X_map[iSurf][1:-1, :, :]] = ( v[self.X_map[iSurf][2:, :, :]] - v[self.X_map[iSurf][0:-2, :, :]] @@ -6209,95 +6208,95 @@ def evalDiffSens(self, iSurf, wrt): # Central Difference # Dt_u[X_map[1:-1,:,:]]/DX[X_map[2:,:,:]] = 1/2 - ii += list(numpy.reshape(self.X_map[iSurf][1:-1, :, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][2:, :, :], -1)) - data += [0.5] * len(numpy.reshape(self.X_map[iSurf][1:-1, :, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][1:-1, :, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][2:, :, :], -1)) + data += [0.5] * len(np.reshape(self.X_map[iSurf][1:-1, :, :], -1)) # Dt_u[X_map[1:-1,:,:]]/DX[X_map[0:-2,:,:]] = -1/2 - ii += list(numpy.reshape(self.X_map[iSurf][1:-1, :, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][0:-2, :, :], -1)) - data += [-0.5] * len(numpy.reshape(self.X_map[iSurf][1:-1, :, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][1:-1, :, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][0:-2, :, :], -1)) + data += [-0.5] * len(np.reshape(self.X_map[iSurf][1:-1, :, :], -1)) # Forward Difference # Dt_u[X_map[0,:,:]]/DX[X_map[2,:,:]] = -1/2 - ii += list(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][2, :, :], -1)) - data += [-0.5] * len(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][0, :, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][2, :, :], -1)) + data += [-0.5] * len(np.reshape(self.X_map[iSurf][0, :, :], -1)) # Dt_u[X_map[0,:,:]]/DX[X_map[1,:,:]] = 4/2 - ii += list(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][1, :, :], -1)) - data += [2] * len(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][0, :, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][1, :, :], -1)) + data += [2] * len(np.reshape(self.X_map[iSurf][0, :, :], -1)) # Dt_u[X_map[0,:,:]]/DX[X_map[0,:,:]] = -3/2 - ii += list(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) - data += [-1.5] * len(numpy.reshape(self.X_map[iSurf][0, :, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][0, :, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][0, :, :], -1)) + data += [-1.5] * len(np.reshape(self.X_map[iSurf][0, :, :], -1)) # Backward Difference # Dt_u[X_map[-1,:,:]]/DX[X_map[-3,:,:]] = 1/2 - ii += list(numpy.reshape(self.X_map[iSurf][-1, :, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][-3, :, :], -1)) - data += [0.5] * len(numpy.reshape(self.X_map[iSurf][-1, :, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][-1, :, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][-3, :, :], -1)) + data += [0.5] * len(np.reshape(self.X_map[iSurf][-1, :, :], -1)) # Dt_u[X_map[-1,:,:]]/DX[X_map[-2,:,:]] = -4/2 - ii += list(numpy.reshape(self.X_map[iSurf][-1, :, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][-2, :, :], -1)) - data += [-2.0] * len(numpy.reshape(self.X_map[iSurf][-2, :, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][-1, :, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][-2, :, :], -1)) + data += [-2.0] * len(np.reshape(self.X_map[iSurf][-2, :, :], -1)) # Dt_u[X_map[-1,:,:]]/DX[X_map[-1,:,:]] = 3/2 - ii += list(numpy.reshape(self.X_map[iSurf][-1, :, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][-1, :, :], -1)) - data += [1.5] * len(numpy.reshape(self.X_map[iSurf][-1, :, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][-1, :, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][-1, :, :], -1)) + data += [1.5] * len(np.reshape(self.X_map[iSurf][-1, :, :], -1)) elif wrt == "v": # Central Difference # Dt_u[X_map[:,1:-1,:]]/DX[X_map[:,2:,:]] = 1/2 - ii += list(numpy.reshape(self.X_map[iSurf][:, 1:-1, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, 2:, :], -1)) - data += [0.5] * len(numpy.reshape(self.X_map[iSurf][:, 1:-1, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, 1:-1, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, 2:, :], -1)) + data += [0.5] * len(np.reshape(self.X_map[iSurf][:, 1:-1, :], -1)) # Dt_u[X_map[:,1:-1,:]]/DX[X_map[:,0:-2,:]] = -1/2 - ii += list(numpy.reshape(self.X_map[iSurf][:, 1:-1, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, 0:-2, :], -1)) - data += [-0.5] * len(numpy.reshape(self.X_map[iSurf][:, 1:-1, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, 1:-1, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, 0:-2, :], -1)) + data += [-0.5] * len(np.reshape(self.X_map[iSurf][:, 1:-1, :], -1)) # Forward Difference # Dt_u[X_map[:,0,:]]/DX[X_map[:,2,:]] = -1/2 - ii += list(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, 2, :], -1)) - data += [-0.5] * len(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, 0, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, 2, :], -1)) + data += [-0.5] * len(np.reshape(self.X_map[iSurf][:, 0, :], -1)) # Dt_u[X_map[:,0,:]]/DX[X_map[:,1,:]] = 4/2 - ii += list(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, 1, :], -1)) - data += [2] * len(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, 0, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, 1, :], -1)) + data += [2] * len(np.reshape(self.X_map[iSurf][:, 0, :], -1)) # Dt_u[X_map[:,0,:]]/DX[X_map[:,0,:]] = -3/2 - ii += list(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) - data += [-1.5] * len(numpy.reshape(self.X_map[iSurf][:, 0, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, 0, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, 0, :], -1)) + data += [-1.5] * len(np.reshape(self.X_map[iSurf][:, 0, :], -1)) # Backward Difference # Dt_u[X_map[:,-1,:]]/DX[X_map[:,-3,:]] = 1/2 - ii += list(numpy.reshape(self.X_map[iSurf][:, -1, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, -3, :], -1)) - data += [0.5] * len(numpy.reshape(self.X_map[iSurf][:, -1, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, -1, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, -3, :], -1)) + data += [0.5] * len(np.reshape(self.X_map[iSurf][:, -1, :], -1)) # Dt_u[X_map[:,-1,:]]/DX[X_map[:,-2,:]] = -4/2 - ii += list(numpy.reshape(self.X_map[iSurf][:, -1, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, -2, :], -1)) - data += [-2.0] * len(numpy.reshape(self.X_map[iSurf][:, -2, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, -1, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, -2, :], -1)) + data += [-2.0] * len(np.reshape(self.X_map[iSurf][:, -2, :], -1)) # Dt_u[X_map[:,-1,:]]/DX[X_map[:,-1,:]] = 3/2 - ii += list(numpy.reshape(self.X_map[iSurf][:, -1, :], -1)) - jj += list(numpy.reshape(self.X_map[iSurf][:, -1, :], -1)) - data += [1.5] * len(numpy.reshape(self.X_map[iSurf][:, -1, :], -1)) + ii += list(np.reshape(self.X_map[iSurf][:, -1, :], -1)) + jj += list(np.reshape(self.X_map[iSurf][:, -1, :], -1)) + data += [1.5] * len(np.reshape(self.X_map[iSurf][:, -1, :], -1)) Dv_uDX = csr_matrix((data, [ii, jj]), shape=(self.X[iSurf].size, self.X[iSurf].size)) @@ -6404,7 +6403,7 @@ def evalFunctions(self, funcs): for key in self.jac: cons.extend(self.jac[key].dot(self.DVGeo.DV_listGlobal[key].value)) - funcs[self.name] = numpy.array(cons).real.astype("d") + funcs[self.name] = np.array(cons).real.astype("d") def evalFunctionsSens(self, funcsSens): """ @@ -6452,9 +6451,9 @@ def setMonotonic(self, options): # Since start and stop are inclusive, we need to add one to stop to # account for python indexing stop += 1 - ncon = len(numpy.zeros(ndv)[start:stop]) - 1 + ncon = len(np.zeros(ndv)[start:stop]) - 1 - jacobian = numpy.zeros((ncon, ndv)) + jacobian = np.zeros((ncon, ndv)) slope = options["slope"] for i in range(ncon): jacobian[i, start + i] = 1.0 * slope diff --git a/pygeo/DVGeometry.py b/pygeo/DVGeometry.py index 18f2701e..58b562b1 100644 --- a/pygeo/DVGeometry.py +++ b/pygeo/DVGeometry.py @@ -3,7 +3,7 @@ # ====================================================================== import copy from collections import OrderedDict -import numpy +import numpy as np from scipy import sparse from mpi4py import MPI from pyspline import pySpline @@ -157,7 +157,7 @@ def __init__(self, fileName, complex=False, child=False, faceFreeze=None, name=N coefMask = [] for iVol in range(self.FFD.nVol): coefMask.append( - numpy.zeros( + np.zeros( (self.FFD.vols[iVol].nCtlu, self.FFD.vols[iVol].nCtlv, self.FFD.vols[iVol].nCtlw), dtype=bool ) ) @@ -187,7 +187,7 @@ def __init__(self, fileName, complex=False, child=False, faceFreeze=None, name=N # Finally we need to convert coefMask to the flattened global # coef type: - tmp = numpy.zeros(len(self.FFD.coef), dtype=bool) + tmp = np.zeros(len(self.FFD.coef), dtype=bool) for iVol in range(self.FFD.nVol): for i in range(coefMask[iVol].shape[0]): for j in range(coefMask[iVol].shape[1]): @@ -342,17 +342,17 @@ def addRefAxis( if axis is None: pass elif axis.lower() == "x": - axis = numpy.array([1, 0, 0], "d") + axis = np.array([1, 0, 0], "d") elif axis.lower() == "y": - axis = numpy.array([0, 1, 0], "d") + axis = np.array([0, 1, 0], "d") elif axis.lower() == "z": - axis = numpy.array([0, 0, 1], "d") + axis = np.array([0, 0, 1], "d") if curve is not None: # Explicit curve has been supplied: if self.FFD.symmPlane is None: if volumes is None: - volumes = numpy.arange(self.FFD.nVol) + volumes = np.arange(self.FFD.nVol) self.axis[name] = { "curve": curve, "volumes": volumes, @@ -373,7 +373,7 @@ def addRefAxis( # mirror the axis and attach the mirrored vols if volumes is None: - volumes = numpy.arange(self.FFD.nVol / 2) + volumes = np.arange(self.FFD.nVol / 2) volumesSymm = [] for volume in volumes: @@ -461,13 +461,13 @@ def addRefAxis( else: nSections.append(lIndex[volOrd[i]].shape[alignIndex] - 1) - refaxisNodes = numpy.zeros((sum(nSections), 3)) + refaxisNodes = np.zeros((sum(nSections), 3)) # Loop through sections and compute node location place = 0 for j, vol in enumerate(volOrd): # sectionArr: indices of FFD points grouped by section - sectionArr = numpy.rollaxis(lIndex[vol], alignIndex, 0) + sectionArr = np.rollaxis(lIndex[vol], alignIndex, 0) skip = 0 if j > 0: skip = 1 @@ -476,46 +476,46 @@ def addRefAxis( pts_tens = self.FFD.coef[sectionArr[i + skip, :, :], :] # shape=(xAxisNodes,yAxisnodes,3) # reshaping into vector to allow rotation (if needed) - leveraging on pts_tens.shape[2]=3 (FFD cp coordinates) - pts_vec = numpy.copy(pts_tens.reshape(-1, 3)) # new shape=(xAxisNodes*yAxisnodes,3) + pts_vec = np.copy(pts_tens.reshape(-1, 3)) # new shape=(xAxisNodes*yAxisnodes,3) if rot0ang: # rotating the FFD to be aligned with main axes - for ct_ in range(numpy.shape(pts_vec)[0]): + for ct_ in range(np.shape(pts_vec)[0]): # here we loop over the pts_vec, rotate them and insert them inplace in pts_vec again - p_ = numpy.copy(pts_vec[ct_, :]) - p_rot = geo_utils.rotVbyW(p_, rot0axis, numpy.pi / 180 * (rot0ang)) + p_ = np.copy(pts_vec[ct_, :]) + p_rot = geo_utils.rotVbyW(p_, rot0axis, np.pi / 180 * (rot0ang)) pts_vec[ct_, :] = p_rot # Temporary ref axis node coordinates - aligned with main system of reference if xFraction: # getting the bounds of the FFD section - x_min = numpy.min(pts_vec[:, 0]) - x_max = numpy.max(pts_vec[:, 0]) + x_min = np.min(pts_vec[:, 0]) + x_max = np.max(pts_vec[:, 0]) x_node = xFraction * (x_max - x_min) + x_min # chordwise else: - x_node = numpy.mean(pts_vec[:, 0]) + x_node = np.mean(pts_vec[:, 0]) if yFraction: - y_min = numpy.min(pts_vec[:, 1]) - y_max = numpy.max(pts_vec[:, 1]) + y_min = np.min(pts_vec[:, 1]) + y_max = np.max(pts_vec[:, 1]) y_node = y_max - yFraction * (y_max - y_min) # top-bottom else: - y_node = numpy.mean(pts_vec[:, 1]) + y_node = np.mean(pts_vec[:, 1]) if zFraction: - z_min = numpy.min(pts_vec[:, 2]) - z_max = numpy.max(pts_vec[:, 2]) + z_min = np.min(pts_vec[:, 2]) + z_max = np.max(pts_vec[:, 2]) z_node = z_max - zFraction * (z_max - z_min) # top-bottom else: - z_node = numpy.mean(pts_vec[:, 2]) + z_node = np.mean(pts_vec[:, 2]) # This is the FFD ref axis node - if the block has not been rotated nd = [x_node, y_node, z_node] - nd_final = numpy.copy(nd) + nd_final = np.copy(nd) if rot0ang: # rotating the non-aligned FFDs back in position - nd_final[:] = geo_utils.rotVbyW(nd, rot0axis, numpy.pi / 180 * (-rot0ang)) + nd_final[:] = geo_utils.rotVbyW(nd, rot0axis, np.pi / 180 * (-rot0ang)) # insert the final coordinates in the var to be passed to pySpline: refaxisNodes[place + i, 0] = nd_final[0] @@ -580,7 +580,7 @@ def addPointSet(self, points, ptName, origConfig=True, **kwargs): self.zeroJacobians([ptName]) self.nPts[ptName] = None - points = numpy.array(points).real.astype("d") + points = np.array(points).real.astype("d") self.points[ptName] = points # Ensure we project into the undeformed geometry @@ -781,14 +781,14 @@ def addGeoDVLocal( volListTmp.append(vol + self.FFD.nVol / 2) volList = volListTmp - volList = numpy.atleast_1d(volList).astype("int") + volList = np.atleast_1d(volList).astype("int") ind = [] for iVol in volList: ind.extend(self.FFD.topo.lIndex[iVol].flatten()) ind = geo_utils.unique(ind) else: # Just take'em all - ind = numpy.arange(len(self.FFD.coef)) + ind = np.arange(len(self.FFD.coef)) self.DV_listLocal[dvName] = geoDVLocal(dvName, lower, upper, scale, axis, ind, self.masks, config) @@ -899,18 +899,18 @@ def addGeoDVSpanwiseLocal( volListTmp.append(vol + self.FFD.nVol / 2) volList = volListTmp - volList = numpy.atleast_1d(volList).astype("int") + volList = np.atleast_1d(volList).astype("int") ind = [] for iVol in volList: ind.extend(self.FFD.topo.lIndex[iVol].flatten()) ind = geo_utils.unique(ind) else: # Just take'em all - volList = numpy.arange(self.FFD.nVol) - ind = numpy.arange(len(self.FFD.coef)) + volList = np.arange(self.FFD.nVol) + ind = np.arange(len(self.FFD.coef)) - # secLink = numpy.zeros(self.FFD.coef.shape[0], dtype=int) - # secTransform = [numpy.eye(3)] + # secLink = np.zeros(self.FFD.coef.shape[0], dtype=int) + # secTransform = [np.eye(3)] if type(spanIndex) is str: spanIndex = [spanIndex] * len(volList) @@ -930,14 +930,14 @@ def addGeoDVSpanwiseLocal( # remove the span axis since all dv in that axis are linked n_linked_coef = topo_shape[spanIdx] - dvs_shape = numpy.delete(topo_shape, spanIdx) + dvs_shape = np.delete(topo_shape, spanIdx) # get total number of dvs - n_dvs = numpy.product(dvs_shape) + n_dvs = np.product(dvs_shape) # make a map from dvs to the ind that are controlled by that dv. # (phrased another way) map from dv to all ind in the same span size position - dv_to_coef_ind = numpy.zeros((n_dvs, n_linked_coef), dtype="intc") + dv_to_coef_ind = np.zeros((n_dvs, n_linked_coef), dtype="intc") # slice lIndex to get the indices of the coeffs that are in the same # spanwise position @@ -1120,7 +1120,7 @@ class in geo_utils. Using pointSelect discards everything in volList. if pointSelect is not None: if pointSelect.type != "ijkBounds": pts, ind = pointSelect.getPoints(self.FFD.coef) - volList = numpy.arange(self.FFD.nVol) # Select all volumes + volList = np.arange(self.FFD.nVol) # Select all volumes else: pts, ind = pointSelect.getPoints_ijk(self) volList = pointSelect.ijkBounds.keys() # Select only volumes used by pointSelect @@ -1133,18 +1133,18 @@ class in geo_utils. Using pointSelect discards everything in volList. volListTmp.append(vol + self.FFD.nVol / 2) volList = volListTmp - volList = numpy.atleast_1d(volList).astype("int") + volList = np.atleast_1d(volList).astype("int") ind = [] for iVol in volList: ind.extend(self.FFD.topo.lIndex[iVol].flatten()) # Get all indices from this block ind = geo_utils.unique(ind) else: # Just take'em all - volList = numpy.arange(self.FFD.nVol) - ind = numpy.arange(len(self.FFD.coef)) + volList = np.arange(self.FFD.nVol) + ind = np.arange(len(self.FFD.coef)) - secLink = numpy.zeros(self.FFD.coef.shape[0], dtype=int) - secTransform = [numpy.eye(3)] + secLink = np.zeros(self.FFD.coef.shape[0], dtype=int) + secTransform = [np.eye(3)] if type(secIndex) is str: secIndex = [secIndex] * len(volList) @@ -1160,14 +1160,14 @@ class in geo_utils. Using pointSelect discards everything in volList. elif type(orient0) is list: if len(orient0) != len(volList): raise Error("If a list is given for orient0, the length must" " be equal to the length of volList.") - # numpy.array([1.0, 0.0, 0.0]) - elif type(orient0) is numpy.ndarray: + # np.array([1.0, 0.0, 0.0]) + elif type(orient0) is np.ndarray: # vector if len(orient0.shape) == 1: - orient0 = numpy.reshape(orient0, (1, 3)) - orient0 = numpy.repeat(orient0, len(volList), 0) + orient0 = np.reshape(orient0, (1, 3)) + orient0 = np.repeat(orient0, len(volList), 0) elif orient0.shape[0] == 1: - orient0 = numpy.repeat(orient0, len(volList), 0) + orient0 = np.repeat(orient0, len(volList), 0) elif orient0.shape[0] != len(volList): raise Error( "If an array is given for orient0, the row dimension" " must be equal to the length of volList." @@ -1238,7 +1238,7 @@ def getSymmetricCoefList(self, volList=None, pointSelect=None, tol=1e-8): volListTmp.append(vol + self.FFD.nVol / 2) volList = volListTmp - volList = numpy.atleast_1d(volList).astype("int") + volList = np.atleast_1d(volList).astype("int") ind = [] for iVol in volList: ind.extend(self.FFD.topo.lIndex[iVol].flatten()) @@ -1246,7 +1246,7 @@ def getSymmetricCoefList(self, volList=None, pointSelect=None, tol=1e-8): pts = self.FFD.coef[ind] else: # Just take'em all - ind = numpy.arange(len(self.FFD.coef)) + ind = np.arange(len(self.FFD.coef)) pts = self.FFD.coef # Create the base points for the KD tree search. We will take the abs @@ -1301,7 +1301,7 @@ def setDesignVars(self, dvDict): for key in dvDict: if key in self.DV_listGlobal: - vals_to_set = numpy.atleast_1d(dvDict[key]).astype("D") + vals_to_set = np.atleast_1d(dvDict[key]).astype("D") if len(vals_to_set) != self.DV_listGlobal[key].nVal: raise Error( "Incorrect number of design variables " @@ -1312,7 +1312,7 @@ def setDesignVars(self, dvDict): self.DV_listGlobal[key].value = vals_to_set if key in self.DV_listLocal: - vals_to_set = numpy.atleast_1d(dvDict[key]).astype("D") + vals_to_set = np.atleast_1d(dvDict[key]).astype("D") if len(vals_to_set) != self.DV_listLocal[key].nVal: raise Error( "Incorrect number of design variables \ @@ -1323,7 +1323,7 @@ def setDesignVars(self, dvDict): self.DV_listLocal[key].value = vals_to_set if key in self.DV_listSectionLocal: - vals_to_set = numpy.atleast_1d(dvDict[key]).astype("D") + vals_to_set = np.atleast_1d(dvDict[key]).astype("D") if len(vals_to_set) != self.DV_listSectionLocal[key].nVal: raise Error( "Incorrect number of design variables \ @@ -1334,7 +1334,7 @@ def setDesignVars(self, dvDict): self.DV_listSectionLocal[key].value = vals_to_set if key in self.DV_listSpanwiseLocal: - vals_to_set = numpy.atleast_1d(dvDict[key]).astype("D") + vals_to_set = np.atleast_1d(dvDict[key]).astype("D") if len(vals_to_set) != self.DV_listSpanwiseLocal[key].nVal: raise Error( "Incorrect number of design variables \ @@ -1410,11 +1410,11 @@ def extractCoef(self, axisID): axis. This should be used only inside design variable functions""" axisNumber = self._getAxisNumber(axisID) - C = numpy.zeros((len(self.refAxis.topo.lIndex[axisNumber]), 3), self.coef.dtype) + C = np.zeros((len(self.refAxis.topo.lIndex[axisNumber]), 3), self.coef.dtype) - C[:, 0] = numpy.take(self.coef[:, 0], self.refAxis.topo.lIndex[axisNumber]) - C[:, 1] = numpy.take(self.coef[:, 1], self.refAxis.topo.lIndex[axisNumber]) - C[:, 2] = numpy.take(self.coef[:, 2], self.refAxis.topo.lIndex[axisNumber]) + C[:, 0] = np.take(self.coef[:, 0], self.refAxis.topo.lIndex[axisNumber]) + C[:, 1] = np.take(self.coef[:, 1], self.refAxis.topo.lIndex[axisNumber]) + C[:, 2] = np.take(self.coef[:, 2], self.refAxis.topo.lIndex[axisNumber]) return C @@ -1424,9 +1424,9 @@ def restoreCoef(self, coef, axisID): # Reset axisNumber = self._getAxisNumber(axisID) - numpy.put(self.coef[:, 0], self.refAxis.topo.lIndex[axisNumber], coef[:, 0]) - numpy.put(self.coef[:, 1], self.refAxis.topo.lIndex[axisNumber], coef[:, 1]) - numpy.put(self.coef[:, 2], self.refAxis.topo.lIndex[axisNumber], coef[:, 2]) + np.put(self.coef[:, 0], self.refAxis.topo.lIndex[axisNumber], coef[:, 0]) + np.put(self.coef[:, 1], self.refAxis.topo.lIndex[axisNumber], coef[:, 1]) + np.put(self.coef[:, 2], self.refAxis.topo.lIndex[axisNumber], coef[:, 2]) def extractS(self, axisID): """Extract the parametric positions of the control @@ -1483,23 +1483,23 @@ def updateCalculations(self, new_pts, isComplex, config): rotType = self.axis[self.curveIDNames[ipt]]["rotType"] if rotType == 0: - bp_ = numpy.copy(base_pt) # copy of original pointset - will not be rotated + bp_ = np.copy(base_pt) # copy of original pointset - will not be rotated if isinstance(ang, (float, int)): # rotation active only if a non-default value is provided - ang *= numpy.pi / 180 # conv to [rad] + ang *= np.pi / 180 # conv to [rad] # Rotating the FFD according to inputs # The FFD points should now be aligned with the main system of reference base_pt = geo_utils.rotVbyW(bp_, ax_dir, ang) deriv = self.refAxis.curves[self.curveIDs[ipt]].getDerivative(self.links_s[ipt]) deriv /= geo_utils.euclideanNorm(deriv) # Normalize - new_vec = -numpy.cross(deriv, self.links_n[ipt]) + new_vec = -np.cross(deriv, self.links_n[ipt]) if isComplex: new_pts[ipt] = bp_ + new_vec * scale # using "unrotated" bp_ vector else: - new_pts[ipt] = numpy.real(bp_ + new_vec * scale) + new_pts[ipt] = np.real(bp_ + new_vec * scale) if isinstance(ang, (float, int)): # Rotating to be aligned with main sys ref - nv_ = numpy.copy(new_vec) + nv_ = np.copy(new_vec) new_vec = geo_utils.rotVbyW(nv_, ax_dir, ang) # Apply scaling @@ -1509,17 +1509,17 @@ def updateCalculations(self, new_pts, isComplex, config): if isinstance(ang, (float, int)): # Rotating back the scaled pointset to its original position - nv_rot = numpy.copy(new_vec) # nv_rot is scaled and rotated + nv_rot = np.copy(new_vec) # nv_rot is scaled and rotated new_vec = geo_utils.rotVbyW(nv_rot, ax_dir, -ang) new_vec = geo_utils.rotVbyW( - new_vec, deriv, self.rot_theta[self.curveIDNames[ipt]](self.links_s[ipt]) * numpy.pi / 180 + new_vec, deriv, self.rot_theta[self.curveIDNames[ipt]](self.links_s[ipt]) * np.pi / 180 ) if isComplex: new_pts[ipt] = bp_ + new_vec else: - new_pts[ipt] = numpy.real(bp_ + new_vec) + new_pts[ipt] = np.real(bp_ + new_vec) else: rotX = geo_utils.rotxM(self.rot_x[self.curveIDNames[ipt]](self.links_s[ipt])) @@ -1536,15 +1536,15 @@ def updateCalculations(self, new_pts, isComplex, config): if isComplex: self.coefRotM[attachedPoint] = rotM else: - self.coefRotM[attachedPoint] = numpy.real(rotM) + self.coefRotM[attachedPoint] = np.real(rotM) - D = numpy.dot(rotM, D) + D = np.dot(rotM, D) if rotType == 7: # only apply the theta rotations in certain cases deriv = self.refAxis.curves[self.curveIDs[ipt]].getDerivative(self.links_s[ipt]) deriv /= geo_utils.euclideanNorm(deriv) # Normalize D = geo_utils.rotVbyW( - D, deriv, numpy.pi / 180 * self.rot_theta[self.curveIDNames[ipt]](self.links_s[ipt]) + D, deriv, np.pi / 180 * self.rot_theta[self.curveIDNames[ipt]](self.links_s[ipt]) ) elif rotType == 8: @@ -1553,7 +1553,7 @@ def updateCalculations(self, new_pts, isComplex, config): attachedPoint = self.ptAttachInd[ipt] W = slVar.sectionTransform[slVar.sectionLink[attachedPoint]][:, 2] D = geo_utils.rotVbyW( - D, W, numpy.pi / 180 * self.rot_theta[self.curveIDNames[ipt]](self.links_s[ipt]) + D, W, np.pi / 180 * self.rot_theta[self.curveIDNames[ipt]](self.links_s[ipt]) ) D[0] *= scale_x @@ -1563,7 +1563,7 @@ def updateCalculations(self, new_pts, isComplex, config): if isComplex: new_pts[ipt] = base_pt + D * scale else: - new_pts[ipt] = numpy.real(base_pt + D * scale) + new_pts[ipt] = np.real(base_pt + D * scale) def update(self, ptSetName, childDelta=True, config=None): """ @@ -1609,7 +1609,7 @@ def update(self, ptSetName, childDelta=True, config=None): # Now we have to propagate the complex part through Xstart tempCoef = self.FFD.coef.copy().astype("D") Xstart = Xstart.astype("D") - imag_part = numpy.imag(tempCoef) + imag_part = np.imag(tempCoef) imag_j = 1j dPtdCoef = self.FFD.embededVolumes[ptSetName].dPtdCoef @@ -1620,18 +1620,18 @@ def update(self, ptSetName, childDelta=True, config=None): # Step 1: Call all the design variables IFF we have ref axis: if len(self.axis) > 0: if self.complex: - new_pts = numpy.zeros((self.nPtAttach, 3), "D") + new_pts = np.zeros((self.nPtAttach, 3), "D") else: - new_pts = numpy.zeros((self.nPtAttach, 3), "d") + new_pts = np.zeros((self.nPtAttach, 3), "d") # Apply the global design variables self.updateCalculations(new_pts, isComplex=self.complex, config=config) # Put the update FFD points in their proper place - temp = numpy.real(new_pts) - numpy.put(self.FFD.coef[:, 0], self.ptAttachInd, temp[:, 0]) - numpy.put(self.FFD.coef[:, 1], self.ptAttachInd, temp[:, 1]) - numpy.put(self.FFD.coef[:, 2], self.ptAttachInd, temp[:, 2]) + temp = np.real(new_pts) + np.put(self.FFD.coef[:, 0], self.ptAttachInd, temp[:, 0]) + np.put(self.FFD.coef[:, 1], self.ptAttachInd, temp[:, 1]) + np.put(self.FFD.coef[:, 2], self.ptAttachInd, temp[:, 2]) # Now add in the spanwise local DVs for key in self.DV_listSpanwiseLocal: @@ -1658,9 +1658,9 @@ def update(self, ptSetName, childDelta=True, config=None): # the complex part because we want to propagate it through tempCoef = self.FFD.coef.copy().astype("D") if len(self.axis) > 0: - numpy.put(tempCoef[:, 0], self.ptAttachInd, new_pts[:, 0]) - numpy.put(tempCoef[:, 1], self.ptAttachInd, new_pts[:, 1]) - numpy.put(tempCoef[:, 2], self.ptAttachInd, new_pts[:, 2]) + np.put(tempCoef[:, 0], self.ptAttachInd, new_pts[:, 0]) + np.put(tempCoef[:, 1], self.ptAttachInd, new_pts[:, 1]) + np.put(tempCoef[:, 2], self.ptAttachInd, new_pts[:, 2]) # Apply just the complex part of the local varibales for key in self.DV_listSpanwiseLocal: @@ -1671,7 +1671,7 @@ def update(self, ptSetName, childDelta=True, config=None): self.DV_listLocal[key].updateComplex(tempCoef, config) Xfinal = Xfinal.astype("D") - imag_part = numpy.imag(tempCoef) + imag_part = np.imag(tempCoef) imag_j = 1j dPtdCoef = self.FFD.embededVolumes[ptSetName].dPtdCoef @@ -1782,7 +1782,7 @@ def convertSensitivityToDict(self, dIdx, out1D=False): for key in self.DV_listGlobal: dv = self.DV_listGlobal[key] if out1D: - dIdxDict[dv.name] = numpy.ravel(dIdx[:, i : i + dv.nVal]) + dIdxDict[dv.name] = np.ravel(dIdx[:, i : i + dv.nVal]) else: dIdxDict[dv.name] = dIdx[:, i : i + dv.nVal] i += dv.nVal @@ -1791,7 +1791,7 @@ def convertSensitivityToDict(self, dIdx, out1D=False): for key in self.DV_listSpanwiseLocal: dv = self.DV_listSpanwiseLocal[key] if out1D: - dIdxDict[dv.name] = numpy.ravel(dIdx[:, i : i + dv.nVal]) + dIdxDict[dv.name] = np.ravel(dIdx[:, i : i + dv.nVal]) else: dIdxDict[dv.name] = dIdx[:, i : i + dv.nVal] i += dv.nVal @@ -1800,7 +1800,7 @@ def convertSensitivityToDict(self, dIdx, out1D=False): for key in self.DV_listSectionLocal: dv = self.DV_listSectionLocal[key] if out1D: - dIdxDict[dv.name] = numpy.ravel(dIdx[:, i : i + dv.nVal]) + dIdxDict[dv.name] = np.ravel(dIdx[:, i : i + dv.nVal]) else: dIdxDict[dv.name] = dIdx[:, i : i + dv.nVal] i += dv.nVal @@ -1809,7 +1809,7 @@ def convertSensitivityToDict(self, dIdx, out1D=False): for key in self.DV_listLocal: dv = self.DV_listLocal[key] if out1D: - dIdxDict[dv.name] = numpy.ravel(dIdx[:, i : i + dv.nVal]) + dIdxDict[dv.name] = np.ravel(dIdx[:, i : i + dv.nVal]) else: dIdxDict[dv.name] = dIdx[:, i : i + dv.nVal] @@ -1846,7 +1846,7 @@ def convertDictToSensitivity(self, dIdxDict): Flattened array of length getNDV(). """ DVCountGlobal, DVCountLocal, DVCountSecLoc, DVCountSpanLoc = self._getDVOffsets() - dIdx = numpy.zeros(self.nDV_T, self.dtype) + dIdx = np.zeros(self.nDV_T, self.dtype) i = DVCountGlobal for key in self.DV_listGlobal: dv = self.DV_listGlobal[key] @@ -1943,7 +1943,7 @@ def totalSensitivity(self, dIdpt, ptSetName, comm=None, config=None): # Make dIdpt at least 3D if len(dIdpt.shape) == 2: - dIdpt = numpy.array([dIdpt]) + dIdpt = np.array([dIdpt]) N = dIdpt.shape[0] # generate the total Jacobian self.JT @@ -1951,7 +1951,7 @@ def totalSensitivity(self, dIdpt, ptSetName, comm=None, config=None): # now that we have self.JT compute the Mat-Mat multiplication nDV = self._getNDV() - dIdx_local = numpy.zeros((N, nDV), "d") + dIdx_local = np.zeros((N, nDV), "d") for i in range(N): if self.JT[ptSetName] is not None: dIdx_local[i, :] = self.JT[ptSetName].dot(dIdpt[i, :, :].flatten()) @@ -2006,7 +2006,7 @@ def totalSensitivityProd(self, vec, ptSetName, comm=None, child=False, nDVStore= self.computeTotalJacobian(ptSetName, config=config) names = self.getVarNames() - newvec = numpy.zeros(self.getNDV(), self.dtype) + newvec = np.zeros(self.getNDV(), self.dtype) i = 0 for key in names: if key in self.DV_listGlobal: @@ -2025,7 +2025,7 @@ def totalSensitivityProd(self, vec, ptSetName, comm=None, child=False, nDVStore= # perform the product if self.JT[ptSetName] is None: - xsdot = numpy.zeros((0, 3)) + xsdot = np.zeros((0, 3)) else: xsdot = self.JT[ptSetName].T.dot(newvec) xsdot.reshape(len(xsdot) // 3, 3) @@ -2082,9 +2082,9 @@ def totalSensitivityTransProd(self, vec, ptSetName, comm=None, child=False, nDVS # perform the product if self.JT[ptSetName] is None: - xsdot = numpy.zeros((0, 3)) + xsdot = np.zeros((0, 3)) else: - xsdot = self.JT[ptSetName].dot(numpy.ravel(vec)) + xsdot = self.JT[ptSetName].dot(np.ravel(vec)) # Pack result into dictionary xsdict = {} @@ -2187,9 +2187,9 @@ def computeTotalJacobian(self, ptSetName, config=None): col = dPtdCoef.col data = dPtdCoef.data - new_row = numpy.zeros(3 * len(row), "int") - new_col = numpy.zeros(3 * len(row), "int") - new_data = numpy.zeros(3 * len(row)) + new_row = np.zeros(3 * len(row), "int") + new_col = np.zeros(3 * len(row), "int") + new_data = np.zeros(3 * len(row)) # Loop over each entry and expand: for j in range(3): @@ -2246,7 +2246,7 @@ def computeTotalJacobianCS(self, ptSetName, config=None): h = 1e-40j - self.JT[ptSetName] = numpy.zeros([self.nDV_T, self.nPts[ptSetName]]) + self.JT[ptSetName] = np.zeros([self.nDV_T, self.nPts[ptSetName]]) self._complexifyCoef() for key in self.DV_listGlobal: for j in range(self.DV_listGlobal[key].nVal): @@ -2260,7 +2260,7 @@ def computeTotalJacobianCS(self, ptSetName, config=None): self.DV_listGlobal[key].value[j] += h - deriv = numpy.imag(self._update_deriv_cs(ptSetName, config=config).flatten()) / numpy.imag(h) + deriv = np.imag(self._update_deriv_cs(ptSetName, config=config).flatten()) / np.imag(h) self.JT[ptSetName][DVGlobalCount, :] = deriv @@ -2279,7 +2279,7 @@ def computeTotalJacobianCS(self, ptSetName, config=None): refVal = self.DV_listSpanwiseLocal[key].value[j] self.DV_listSpanwiseLocal[key].value[j] += h - deriv = numpy.imag(self._update_deriv_cs(ptSetName, config=config).flatten()) / numpy.imag(h) + deriv = np.imag(self._update_deriv_cs(ptSetName, config=config).flatten()) / np.imag(h) self.JT[ptSetName][DVSpanLocCount, :] = deriv @@ -2297,7 +2297,7 @@ def computeTotalJacobianCS(self, ptSetName, config=None): refVal = self.DV_listSectionLocal[key].value[j] self.DV_listSectionLocal[key].value[j] += h - deriv = numpy.imag(self._update_deriv_cs(ptSetName, config=config).flatten()) / numpy.imag(h) + deriv = np.imag(self._update_deriv_cs(ptSetName, config=config).flatten()) / np.imag(h) self.JT[ptSetName][DVSecLocCount, :] = deriv @@ -2315,7 +2315,7 @@ def computeTotalJacobianCS(self, ptSetName, config=None): refVal = self.DV_listLocal[key].value[j] self.DV_listLocal[key].value[j] += h - deriv = numpy.imag(self._update_deriv_cs(ptSetName, config=config).flatten()) / numpy.imag(h) + deriv = np.imag(self._update_deriv_cs(ptSetName, config=config).flatten()) / np.imag(h) self.JT[ptSetName][DVLocalCount, :] = deriv @@ -2553,14 +2553,14 @@ def updatePyGeo(self, geo, outputType, fileName, nRefU=0, nRefV=0): # (set to 1e-12 to match pySpline mult. tolerance) def check_mult(val, knots): for iKnot in range(len(knots)): - if numpy.isclose(val, knots[iKnot], atol=1e-12): + if np.isclose(val, knots[iKnot], atol=1e-12): return True return False # Refine Surface -- U-Direction if isinstance(nRefU, int): # Refine BSplines by adding knot points - Refine_U = numpy.linspace(0.0, 1.0, nRefU + 2) + Refine_U = np.linspace(0.0, 1.0, nRefU + 2) for iSurf in range(geo.nSurf): for iX in Refine_U: if not check_mult(iX, geo.surfs[iSurf].tu): @@ -2570,7 +2570,7 @@ def check_mult(val, knots): raise RuntimeError("Length of nRefU does not match number of surfaces in object") # Refine BSplines by adding knot points for iSurf in range(geo.nSurf): - Refine_U = numpy.linspace(0.0, 1.0, nRefU[iSurf] + 2) + Refine_U = np.linspace(0.0, 1.0, nRefU[iSurf] + 2) for iX in Refine_U: if not check_mult(iX, geo.surfs[iSurf].tu): geo.surfs[iSurf].insertKnot("u", iX, 1) @@ -2580,7 +2580,7 @@ def check_mult(val, knots): # Refine Surface -- V-Direction if isinstance(nRefV, int): # Refine BSplines by adding knot points - Refine_V = numpy.linspace(0.0, 1.0, nRefV + 2) + Refine_V = np.linspace(0.0, 1.0, nRefV + 2) for iSurf in range(geo.nSurf): for iY in Refine_V: if not check_mult(iY, geo.surfs[iSurf].tv): @@ -2590,7 +2590,7 @@ def check_mult(val, knots): raise RuntimeError("Length of nRefV does not match number of surfaces in object") # Refine BSplines by adding knot points for iSurf in range(geo.nSurf): - Refine_V = numpy.linspace(0.0, 1.0, nRefV[iSurf] + 2) + Refine_V = np.linspace(0.0, 1.0, nRefV[iSurf] + 2) for iY in Refine_V: if not check_mult(iY, geo.surfs[iSurf].tv): geo.surfs[iSurf].insertKnot("v", iY, 1) @@ -2712,10 +2712,10 @@ def demoDesignVars(self, directory, includeLocal=True, includeGlobal=True, point if freq == 2: stops = [lower[j], upper[j]] elif freq > 2: - sinusoid = numpy.sin(numpy.linspace(0, numpy.pi, freq)) + sinusoid = np.sin(np.linspace(0, np.pi, freq)) down_swing = x[j] + (lower[j] - x[j]) * sinusoid up_swing = x[j] + (upper[j] - x[j]) * sinusoid - stops = numpy.concatenate((down_swing[:-1], up_swing[:-1])) + stops = np.concatenate((down_swing[:-1], up_swing[:-1])) for val in stops: # Add perturbation to the design variable and update @@ -2781,8 +2781,8 @@ def _finalizeAxis(self): t = self.refAxis.curves[i].t k = self.refAxis.curves[i].k N = len(self.refAxis.curves[i].coef) - z = numpy.zeros((N, 1), self.dtype) - o = numpy.ones((N, 1), self.dtype) + z = np.zeros((N, 1), self.dtype) + o = np.ones((N, 1), self.dtype) self.rot_x[key] = pySpline.Curve(t=t, k=k, coef=z.copy()) self.rot_y[key] = pySpline.Curve(t=t, k=k, coef=z.copy()) self.rot_z[key] = pySpline.Curve(t=t, k=k, coef=z.copy()) @@ -2825,7 +2825,7 @@ def _finalize(self): curveID = 0 # Loop over the axis we have: for key in self.axis: - vol_list = numpy.atleast_1d(self.axis[key]["volumes"]).astype("intc") + vol_list = np.atleast_1d(self.axis[key]["volumes"]).astype("intc") temp = [] for iVol in vol_list: for i in range(self.FFD.vols[iVol].nCtlu): @@ -2865,7 +2865,7 @@ def _finalize(self): for i in range(len(curveIDs)): self.curveIDNames.append(axisKeys[self.curveIDs[i]]) - self.links_s = numpy.array(s) + self.links_s = np.array(s) self.links_x = [] self.links_n = [] @@ -2873,10 +2873,10 @@ def _finalize(self): self.links_x.append(self.ptAttach[i] - self.refAxis.curves[self.curveIDs[i]](s[i])) deriv = self.refAxis.curves[self.curveIDs[i]].getDerivative(self.links_s[i]) deriv /= geo_utils.euclideanNorm(deriv) # Normalize - self.links_n.append(numpy.cross(deriv, self.links_x[-1])) + self.links_n.append(np.cross(deriv, self.links_x[-1])) - self.links_x = numpy.array(self.links_x) - self.links_s = numpy.array(self.links_s) + self.links_x = np.array(self.links_x) + self.links_s = np.array(self.links_s) self.finalized = True def _setInitialValues(self): @@ -2894,21 +2894,21 @@ def _setInitialValues(self): def _getRotMatrix(self, rotX, rotY, rotZ, rotType): if rotType == 1: - D = numpy.dot(rotZ, numpy.dot(rotY, rotX)) + D = np.dot(rotZ, np.dot(rotY, rotX)) elif rotType == 2: - D = numpy.dot(rotY, numpy.dot(rotZ, rotX)) + D = np.dot(rotY, np.dot(rotZ, rotX)) elif rotType == 3: - D = numpy.dot(rotX, numpy.dot(rotZ, rotY)) + D = np.dot(rotX, np.dot(rotZ, rotY)) elif rotType == 4: - D = numpy.dot(rotZ, numpy.dot(rotX, rotY)) + D = np.dot(rotZ, np.dot(rotX, rotY)) elif rotType == 5: - D = numpy.dot(rotY, numpy.dot(rotX, rotZ)) + D = np.dot(rotY, np.dot(rotX, rotZ)) elif rotType == 6: - D = numpy.dot(rotX, numpy.dot(rotY, rotZ)) + D = np.dot(rotX, np.dot(rotY, rotZ)) elif rotType == 7: - D = numpy.dot(rotY, numpy.dot(rotX, rotZ)) + D = np.dot(rotY, np.dot(rotX, rotZ)) elif rotType == 8: - D = numpy.dot(rotY, numpy.dot(rotX, rotZ)) + D = np.dot(rotY, np.dot(rotX, rotZ)) return D def _getNDV(self): @@ -3088,7 +3088,7 @@ def _getDVOffsets(self): def _update_deriv(self, iDV=0, h=1.0e-40j, oneoverh=1.0 / 1e-40, config=None, localDV=False): """Copy of update function for derivative calc""" - new_pts = numpy.zeros((self.nPtAttach, 3), "D") + new_pts = np.zeros((self.nPtAttach, 3), "D") # Step 1: Call all the design variables IFF we have ref axis: if len(self.axis) > 0: @@ -3097,9 +3097,9 @@ def _update_deriv(self, iDV=0, h=1.0e-40j, oneoverh=1.0 / 1e-40, config=None, lo self.updateCalculations(new_pts, isComplex=True, config=config) # create a vector of the size of the full FFD - numpy.put(self.FFD.coef[:, 0], self.ptAttachInd, new_pts[:, 0]) - numpy.put(self.FFD.coef[:, 1], self.ptAttachInd, new_pts[:, 1]) - numpy.put(self.FFD.coef[:, 2], self.ptAttachInd, new_pts[:, 2]) + np.put(self.FFD.coef[:, 0], self.ptAttachInd, new_pts[:, 0]) + np.put(self.FFD.coef[:, 1], self.ptAttachInd, new_pts[:, 1]) + np.put(self.FFD.coef[:, 2], self.ptAttachInd, new_pts[:, 2]) # Add dependence of section variables on the global dv rotations for key in self.DV_listSectionLocal: @@ -3120,15 +3120,15 @@ def _update_deriv(self, iDV=0, h=1.0e-40j, oneoverh=1.0 / 1e-40, config=None, lo # create a vector with the derivative of the parent control points wrt the # parent global variables - tmp = numpy.zeros(self.FFD.coef.shape, dtype="d") - numpy.put(tmp[:, 0], self.ptAttachInd, numpy.imag(new_pts[:, 0]) * oneoverh) - numpy.put(tmp[:, 1], self.ptAttachInd, numpy.imag(new_pts[:, 1]) * oneoverh) - numpy.put(tmp[:, 2], self.ptAttachInd, numpy.imag(new_pts[:, 2]) * oneoverh) + tmp = np.zeros(self.FFD.coef.shape, dtype="d") + np.put(tmp[:, 0], self.ptAttachInd, np.imag(new_pts[:, 0]) * oneoverh) + np.put(tmp[:, 1], self.ptAttachInd, np.imag(new_pts[:, 1]) * oneoverh) + np.put(tmp[:, 2], self.ptAttachInd, np.imag(new_pts[:, 2]) * oneoverh) # create variables for the total derivative of the child axis and control # points wrt the parent global variables - dXrefdXdv = numpy.zeros((dXrefdCoef.shape[0] * 3), "d") - dCcdXdv = numpy.zeros((dCcdCoef.shape[0] * 3), "d") + dXrefdXdv = np.zeros((dXrefdCoef.shape[0] * 3), "d") + dCcdXdv = np.zeros((dCcdCoef.shape[0] * 3), "d") # multiply the derivative of the child axis wrt the parent control points # by the derivative of the parent control points wrt the parent global vars. @@ -3154,7 +3154,7 @@ def _update_deriv_cs(self, ptSetName, config=None): """ A version of the update_deriv function specifically for use in the computeTotalJacobianCS function.""" - new_pts = numpy.zeros((self.nPtAttachFull, 3), "D") + new_pts = np.zeros((self.nPtAttachFull, 3), "D") # Make sure coefficients are complex self._complexifyCoef() @@ -3174,7 +3174,7 @@ def _update_deriv_cs(self, ptSetName, config=None): # Now we have to propagate the complex part through Xstart tempCoef = self.FFD.coef.copy().astype("D") Xstart = Xstart.astype("D") - imag_part = numpy.imag(tempCoef) + imag_part = np.imag(tempCoef) imag_j = 1j dPtdCoef = self.FFD.embededVolumes[ptSetName].dPtdCoef @@ -3189,9 +3189,9 @@ def _update_deriv_cs(self, ptSetName, config=None): self.updateCalculations(new_pts, isComplex=True, config=config) # Put the update FFD points in their proper place - numpy.put(self.FFD.coef[:, 0], self.ptAttachInd, new_pts[:, 0]) - numpy.put(self.FFD.coef[:, 1], self.ptAttachInd, new_pts[:, 1]) - numpy.put(self.FFD.coef[:, 2], self.ptAttachInd, new_pts[:, 2]) + np.put(self.FFD.coef[:, 0], self.ptAttachInd, new_pts[:, 0]) + np.put(self.FFD.coef[:, 1], self.ptAttachInd, new_pts[:, 1]) + np.put(self.FFD.coef[:, 2], self.ptAttachInd, new_pts[:, 2]) # Apply the real and complex parts separately for key in self.DV_listSpanwiseLocal: @@ -3214,7 +3214,7 @@ def _update_deriv_cs(self, ptSetName, config=None): # now project derivs through from the coef to the pts Xfinal = Xfinal.astype("D") - imag_part = numpy.imag(self.FFD.coef) + imag_part = np.imag(self.FFD.coef) imag_j = 1j dPtdCoef = self.FFD.embededVolumes[ptSetName].dPtdCoef @@ -3325,7 +3325,7 @@ def computeTotalJacobianFD(self, ptSetName, config=None): h = 1e-6 - self.JT[ptSetName] = numpy.zeros([self.nDV_T, self.nPts[ptSetName]]) + self.JT[ptSetName] = np.zeros([self.nDV_T, self.nPts[ptSetName]]) for key in self.DV_listGlobal: for j in range(self.DV_listGlobal[key].nVal): @@ -3435,18 +3435,18 @@ def _attachedPtJacobian(self, config): if nDV != 0: # check this # create a jacobian the size of nPtAttached full by self.nDV_T, the total number of # dvs - Jacobian = numpy.zeros((self.nPtAttachFull * 3, self.nDV_T)) + Jacobian = np.zeros((self.nPtAttachFull * 3, self.nDV_T)) # Create the storage arrays for the information that must be # passed to the children for iChild in range(len(self.children)): N = self.FFD.embededVolumes["child%d_axis" % (iChild)].N # Derivative of reference axis points wrt global DVs at this level - self.children[iChild].dXrefdXdvg = numpy.zeros((N * 3, self.nDV_T)) + self.children[iChild].dXrefdXdvg = np.zeros((N * 3, self.nDV_T)) N = self.FFD.embededVolumes["child%d_coef" % (iChild)].N # derivative of the control points wrt the global DVs at this level - self.children[iChild].dCcdXdvg = numpy.zeros((N * 3, self.nDV_T)) + self.children[iChild].dCcdXdvg = np.zeros((N * 3, self.nDV_T)) # We need to save the reference state so that we can always start # from the same place when calling _update_deriv @@ -3474,14 +3474,14 @@ def _attachedPtJacobian(self, config): self._complexifyCoef() # Make sure coefficients are complex self.refAxis._updateCurveCoef() - deriv = oneoverh * numpy.imag(self._update_deriv(iDV, h, oneoverh, config=config)).flatten() + deriv = oneoverh * np.imag(self._update_deriv(iDV, h, oneoverh, config=config)).flatten() # reset the FFD and axis self._unComplexifyCoef() self.FFD.coef = self.FFD.coef.real.astype("d") - numpy.put(Jacobian[0::3, iDV], self.ptAttachInd, deriv[0::3]) - numpy.put(Jacobian[1::3, iDV], self.ptAttachInd, deriv[1::3]) - numpy.put(Jacobian[2::3, iDV], self.ptAttachInd, deriv[2::3]) + np.put(Jacobian[0::3, iDV], self.ptAttachInd, deriv[0::3]) + np.put(Jacobian[1::3, iDV], self.ptAttachInd, deriv[1::3]) + np.put(Jacobian[2::3, iDV], self.ptAttachInd, deriv[2::3]) iDV += 1 @@ -3511,10 +3511,10 @@ def _spanwiselocalDVJacobian(self, config=None): for iChild in range(len(self.children)): N = self.FFD.embededVolumes["child%d_axis" % (iChild)].N - self.children[iChild].dXrefdXdvl = numpy.zeros((N * 3, self.nDV_T)) + self.children[iChild].dXrefdXdvl = np.zeros((N * 3, self.nDV_T)) N = self.FFD.embededVolumes["child%d_coef" % (iChild)].N - self.children[iChild].dCcdXdvl = numpy.zeros((N * 3, self.nDV_T)) + self.children[iChild].dCcdXdvl = np.zeros((N * 3, self.nDV_T)) iDVSpanwiseLocal = self.nDVSW_count for key in self.DV_listSpanwiseLocal: @@ -3553,13 +3553,13 @@ def _spanwiselocalDVJacobian(self, config=None): # derivative of Change in the FFD coef due to DVs # same as Jacobian above, but differnt ordering - dCoefdXdvl = numpy.zeros(self.FFD.coef.shape, dtype="d") + dCoefdXdvl = np.zeros(self.FFD.coef.shape, dtype="d") for coef in coefs: dCoefdXdvl[coef, dv.axis] = 1.0 - dXrefdXdvl = numpy.zeros((dXrefdCoef.shape[0] * 3), "d") - dCcdXdvl = numpy.zeros((dCcdCoef.shape[0] * 3), "d") + dXrefdXdvl = np.zeros((dXrefdCoef.shape[0] * 3), "d") + dCcdXdvl = np.zeros((dCcdCoef.shape[0] * 3), "d") dXrefdXdvl[0::3] = dXrefdCoef.dot(dCoefdXdvl[:, 0]) dXrefdXdvl[1::3] = dXrefdCoef.dot(dCoefdXdvl[:, 1]) @@ -3603,10 +3603,10 @@ def _sectionlocalDVJacobian(self, config=None): for iChild in range(len(self.children)): N = self.FFD.embededVolumes["child%d_axis" % (iChild)].N - self.children[iChild].dXrefdXdvl = numpy.zeros((N * 3, self.nDV_T)) + self.children[iChild].dXrefdXdvl = np.zeros((N * 3, self.nDV_T)) N = self.FFD.embededVolumes["child%d_coef" % (iChild)].N - self.children[iChild].dCcdXdvl = numpy.zeros((N * 3, self.nDV_T)) + self.children[iChild].dCcdXdvl = np.zeros((N * 3, self.nDV_T)) iDVSectionLocal = self.nDVSL_count for key in self.DV_listSectionLocal: @@ -3619,11 +3619,11 @@ def _sectionlocalDVJacobian(self, config=None): for j in range(nVal): coef = dv.coefList[j] # affected control point T = dv.sectionTransform[dv.sectionLink[coef]] - inFrame = numpy.zeros((3, 1)) + inFrame = np.zeros((3, 1)) # Set axis that is being perturbed to 1.0 inFrame[dv.axis] = 1.0 - R = numpy.real(self.coefRotM[coef]) + R = np.real(self.coefRotM[coef]) # this is a bug fix for scipy 1.3+ related to fancy indexing # the original was: # rows = range(coef*3,(coef+1)*3) @@ -3634,12 +3634,12 @@ def _sectionlocalDVJacobian(self, config=None): dXrefdCoef = self.FFD.embededVolumes["child%d_axis" % (iChild)].dPtdCoef dCcdCoef = self.FFD.embededVolumes["child%d_coef" % (iChild)].dPtdCoef - tmp = numpy.zeros(self.FFD.coef.shape, dtype="d") + tmp = np.zeros(self.FFD.coef.shape, dtype="d") tmp[coef, :] = R.dot(T.dot(inFrame)).flatten() - dXrefdXdvl = numpy.zeros((dXrefdCoef.shape[0] * 3), "d") - dCcdXdvl = numpy.zeros((dCcdCoef.shape[0] * 3), "d") + dXrefdXdvl = np.zeros((dXrefdCoef.shape[0] * 3), "d") + dCcdXdvl = np.zeros((dCcdCoef.shape[0] * 3), "d") dXrefdXdvl[0::3] = dXrefdCoef.dot(tmp[:, 0]) dXrefdXdvl[1::3] = dXrefdCoef.dot(tmp[:, 1]) @@ -3682,10 +3682,10 @@ def _localDVJacobian(self, config=None): # passed to the children for iChild in range(len(self.children)): N = self.FFD.embededVolumes["child%d_axis" % (iChild)].N - self.children[iChild].dXrefdXdvl = numpy.zeros((N * 3, self.nDV_T)) + self.children[iChild].dXrefdXdvl = np.zeros((N * 3, self.nDV_T)) N = self.FFD.embededVolumes["child%d_coef" % (iChild)].N - self.children[iChild].dCcdXdvl = numpy.zeros((N * 3, self.nDV_T)) + self.children[iChild].dCcdXdvl = np.zeros((N * 3, self.nDV_T)) iDVLocal = self.nDVL_count for key in self.DV_listLocal: @@ -3709,12 +3709,12 @@ def _localDVJacobian(self, config=None): dXrefdCoef = self.FFD.embededVolumes["child%d_axis" % (iChild)].dPtdCoef dCcdCoef = self.FFD.embededVolumes["child%d_coef" % (iChild)].dPtdCoef - tmp = numpy.zeros(self.FFD.coef.shape, dtype="d") + tmp = np.zeros(self.FFD.coef.shape, dtype="d") tmp[pt_dv[0], pt_dv[1]] = 1.0 - dXrefdXdvl = numpy.zeros((dXrefdCoef.shape[0] * 3), "d") - dCcdXdvl = numpy.zeros((dCcdCoef.shape[0] * 3), "d") + dXrefdXdvl = np.zeros((dXrefdCoef.shape[0] * 3), "d") + dCcdXdvl = np.zeros((dCcdCoef.shape[0] * 3), "d") dXrefdXdvl[0::3] = dXrefdCoef.dot(tmp[:, 0]) dXrefdXdvl[1::3] = dXrefdCoef.dot(tmp[:, 1]) @@ -3760,8 +3760,8 @@ def _cascadedDVJacobian(self, config=None): oneoverh = 1.0 / 1e-40 if self.dXrefdXdvg is not None: for iDV in range(self.dXrefdXdvg.shape[1]): - nz1 = numpy.count_nonzero(self.dXrefdXdvg[:, iDV]) - nz2 = numpy.count_nonzero(self.dCcdXdvg[:, iDV]) + nz1 = np.count_nonzero(self.dXrefdXdvg[:, iDV]) + nz2 = np.count_nonzero(self.dCcdXdvg[:, iDV]) if nz1 + nz2 == 0: continue @@ -3781,7 +3781,7 @@ def _cascadedDVJacobian(self, config=None): self.refAxis._updateCurveCoef() # Complexify the child FFD coords - tmp1 = numpy.zeros_like(self.FFD.coef, dtype="D") + tmp1 = np.zeros_like(self.FFD.coef, dtype="D") # add the effect of the global coordinates on the actual control points tmp1[:, 0] = self.dCcdXdvg[0::3, iDV] * h @@ -3799,9 +3799,9 @@ def _cascadedDVJacobian(self, config=None): # insert this result in the the correct locations of a vector the correct # size - numpy.put(self.FFD.coef[:, 0], self.ptAttachInd, new_pts[:, 0]) - numpy.put(self.FFD.coef[:, 1], self.ptAttachInd, new_pts[:, 1]) - numpy.put(self.FFD.coef[:, 2], self.ptAttachInd, new_pts[:, 2]) + np.put(self.FFD.coef[:, 0], self.ptAttachInd, new_pts[:, 0]) + np.put(self.FFD.coef[:, 1], self.ptAttachInd, new_pts[:, 1]) + np.put(self.FFD.coef[:, 2], self.ptAttachInd, new_pts[:, 2]) # We have to subtract off the oldCoefLocations because we only # want the cascading effect on the current design variables. The @@ -3810,9 +3810,9 @@ def _cascadedDVJacobian(self, config=None): self.FFD.coef -= oldCoefLocations # sum up all of the various influences - Jacobian[0::3, iDV] += oneoverh * numpy.imag(self.FFD.coef[:, 0:1]) - Jacobian[1::3, iDV] += oneoverh * numpy.imag(self.FFD.coef[:, 1:2]) - Jacobian[2::3, iDV] += oneoverh * numpy.imag(self.FFD.coef[:, 2:3]) + Jacobian[0::3, iDV] += oneoverh * np.imag(self.FFD.coef[:, 0:1]) + Jacobian[1::3, iDV] += oneoverh * np.imag(self.FFD.coef[:, 1:2]) + Jacobian[2::3, iDV] += oneoverh * np.imag(self.FFD.coef[:, 2:3]) # decomplexify the coefficients self.coef = self.coef.real.astype("d") @@ -3823,8 +3823,8 @@ def _cascadedDVJacobian(self, config=None): # Now repeat for the local variables for iDV in range(self.dXrefdXdvl.shape[1]): # check if there is any dependence on this DV - nz1 = numpy.count_nonzero(self.dXrefdXdvl[:, iDV]) - nz2 = numpy.count_nonzero(self.dCcdXdvl[:, iDV]) + nz1 = np.count_nonzero(self.dXrefdXdvl[:, iDV]) + nz2 = np.count_nonzero(self.dCcdXdvl[:, iDV]) if nz1 + nz2 == 0: continue @@ -3844,7 +3844,7 @@ def _cascadedDVJacobian(self, config=None): self.refAxis._updateCurveCoef() # Complexify the child FFD coords - tmp1 = numpy.zeros_like(self.FFD.coef, dtype="D") + tmp1 = np.zeros_like(self.FFD.coef, dtype="D") # add the effect of the global coordinates on the actual control points tmp1[:, 0] = self.dCcdXdvl[0::3, iDV] * h @@ -3859,9 +3859,9 @@ def _cascadedDVJacobian(self, config=None): # compute the deriv of the child FFD coords wrt the parent by processing # the above CS perturbation new_pts = self._update_deriv(iDV, h, oneoverh, config=config, localDV=True) - numpy.put(self.FFD.coef[:, 0], self.ptAttachInd, new_pts[:, 0]) - numpy.put(self.FFD.coef[:, 1], self.ptAttachInd, new_pts[:, 1]) - numpy.put(self.FFD.coef[:, 2], self.ptAttachInd, new_pts[:, 2]) + np.put(self.FFD.coef[:, 0], self.ptAttachInd, new_pts[:, 0]) + np.put(self.FFD.coef[:, 1], self.ptAttachInd, new_pts[:, 1]) + np.put(self.FFD.coef[:, 2], self.ptAttachInd, new_pts[:, 2]) # We have to subtract off the oldCoefLocations because we only # want the cascading effect on the current design variables. The @@ -3870,9 +3870,9 @@ def _cascadedDVJacobian(self, config=None): self.FFD.coef -= oldCoefLocations # sum up all of the various influences - Jacobian[0::3, iDV] += oneoverh * numpy.imag(self.FFD.coef[:, 0:1]) - Jacobian[1::3, iDV] += oneoverh * numpy.imag(self.FFD.coef[:, 1:2]) - Jacobian[2::3, iDV] += oneoverh * numpy.imag(self.FFD.coef[:, 2:3]) + Jacobian[0::3, iDV] += oneoverh * np.imag(self.FFD.coef[:, 0:1]) + Jacobian[1::3, iDV] += oneoverh * np.imag(self.FFD.coef[:, 1:2]) + Jacobian[2::3, iDV] += oneoverh * np.imag(self.FFD.coef[:, 2:3]) # decomplexify the coefficients self.coef = self.coef.real.astype("d") @@ -4145,7 +4145,7 @@ def sectionFrame(self, sectionIndex, sectionTransform, sectionLink, ivol=0, orie if type(orient0) is str: orient0 = ijk_2_idx[orient0.lower()] orient0idx = True - elif type(orient0) is numpy.ndarray: + elif type(orient0) is np.ndarray: orient0vec = True else: raise Error("orient0 must be an index (i, j, or k) or a " "vector.") @@ -4154,11 +4154,11 @@ def sectionFrame(self, sectionIndex, sectionTransform, sectionLink, ivol=0, orie nSections = lIndex.shape[sectionIndex] # Roll lIndex so that 0th index is sectionIndex and 1st index is orient0 - rolledlIndex = numpy.rollaxis(lIndex, sectionIndex, 0) + rolledlIndex = np.rollaxis(lIndex, sectionIndex, 0) if orient0idx: if orient0 != 2: orient0 += 1 - rolledlIndex = numpy.rollaxis(rolledlIndex, orient0, 1) + rolledlIndex = np.rollaxis(rolledlIndex, orient0, 1) # Length of sectionTransform Tcount = len(sectionTransform) @@ -4169,10 +4169,10 @@ def sectionFrame(self, sectionIndex, sectionTransform, sectionLink, ivol=0, orie # of the transformation matrix) pts = self.FFD.coef[rolledlIndex[i, :, :]] nJ, nI = pts.shape[:-1] - X = numpy.reshape(pts, (nI * nJ, 3)) - c = numpy.mean(X, 0) + X = np.reshape(pts, (nI * nJ, 3)) + c = np.mean(X, 0) A = X - c - U, S, V = numpy.linalg.svd(A.T) + U, S, V = np.linalg.svd(A.T) # Choose section plane normal axis if orient2 == "svd": @@ -4180,18 +4180,18 @@ def sectionFrame(self, sectionIndex, sectionTransform, sectionLink, ivol=0, orie elif orient2 == "ffd": # Use a centered FD approximation (first order at the boundaries) if i == 0: - pt = numpy.mean(self.FFD.coef[rolledlIndex[i, :, :]].reshape(nI * nJ, 3), 0) - ptp = numpy.mean(self.FFD.coef[rolledlIndex[i + 1, :, :]].reshape(nI * nJ, 3), 0) + pt = np.mean(self.FFD.coef[rolledlIndex[i, :, :]].reshape(nI * nJ, 3), 0) + ptp = np.mean(self.FFD.coef[rolledlIndex[i + 1, :, :]].reshape(nI * nJ, 3), 0) ax2 = ptp - pt elif i == nSections - 1: - pt = numpy.mean(self.FFD.coef[rolledlIndex[i, :, :]].reshape(nI * nJ, 3), 0) - ptm = numpy.mean(self.FFD.coef[rolledlIndex[i - 1, :, :]].reshape(nI * nJ, 3), 0) + pt = np.mean(self.FFD.coef[rolledlIndex[i, :, :]].reshape(nI * nJ, 3), 0) + ptm = np.mean(self.FFD.coef[rolledlIndex[i - 1, :, :]].reshape(nI * nJ, 3), 0) ax2 = pt - ptm else: - ptp = numpy.mean(self.FFD.coef[rolledlIndex[i + 1, :, :]].reshape(nI * nJ, 3), 0) - ptm = numpy.mean(self.FFD.coef[rolledlIndex[i - 1, :, :]].reshape(nI * nJ, 3), 0) + ptp = np.mean(self.FFD.coef[rolledlIndex[i + 1, :, :]].reshape(nI * nJ, 3), 0) + ptm = np.mean(self.FFD.coef[rolledlIndex[i - 1, :, :]].reshape(nI * nJ, 3), 0) ax2 = ptp - ptm - ax2 /= numpy.linalg.norm(ax2) + ax2 /= np.linalg.norm(ax2) else: raise Error("orient2 must be 'svd' or 'ffd'") @@ -4206,17 +4206,17 @@ def sectionFrame(self, sectionIndex, sectionTransform, sectionLink, ivol=0, orie # through the section points. if orient0vec or orient0idx: if orient0vec: - u = orient0 / numpy.linalg.norm(orient0) + u = orient0 / np.linalg.norm(orient0) else: - u = numpy.mean((pts[-1, :] - pts[0, :]), axis=0) - u = u / numpy.linalg.norm(u) + u = np.mean((pts[-1, :] - pts[0, :]), axis=0) + u = u / np.linalg.norm(u) ax0 = u - u.dot(ax2) * ax2 - ax1 = numpy.cross(ax2, ax0) + ax1 = np.cross(ax2, ax0) else: ax0 = U[:, 0] ax1 = U[:, 1] - T = numpy.vstack((ax0, ax1, ax2)).T + T = np.vstack((ax0, ax1, ax2)).T sectionTransform.append(T) # Designate section transformation matrix for each control point in # section @@ -4227,7 +4227,7 @@ def sectionFrame(self, sectionIndex, sectionTransform, sectionLink, ivol=0, orie # global design variables for slice in rolledlIndex[i, :, :]: for coef in slice: - self.coefRotM[coef] = numpy.eye(3) + self.coefRotM[coef] = np.eye(3) return nSections @@ -4238,7 +4238,7 @@ def __init__(self, dv_name, value, lower, upper, scale, function, config): See addGeoDVGlobal in DVGeometry class for more information """ self.name = dv_name - self.value = numpy.atleast_1d(numpy.array(value)).astype("D") + self.value = np.atleast_1d(np.array(value)).astype("D") self.nVal = len(self.value) self.lower = None self.upper = None @@ -4254,7 +4254,7 @@ def __init__(self, dv_name, value, lower, upper, scale, function, config): def __call__(self, geo, config): """When the object is called, actually apply the function""" # Run the user-supplied function - d = numpy.dtype(complex) + d = np.dtype(complex) if self.config is None or config is None or any(c0 == config for c0 in self.config): # If the geo object is complex, which is indicated by .coef @@ -4263,7 +4263,7 @@ def __call__(self, geo, config): if geo.coef.dtype == d or geo.complex: return self.function(self.value, geo) else: - return self.function(numpy.real(self.value), geo) + return self.function(np.real(self.value), geo) class geoDVLocal(object): @@ -4283,7 +4283,7 @@ def __init__(self, dvName, lower, upper, scale, axis, coefListIn, mask, config): N = len(axis) self.nVal = len(coefList) * N - self.value = numpy.zeros(self.nVal, "D") + self.value = np.zeros(self.nVal, "D") self.name = dvName self.lower = None self.upper = None @@ -4295,7 +4295,7 @@ def __init__(self, dvName, lower, upper, scale, axis, coefListIn, mask, config): if scale is not None: self.scale = _convertTo1D(scale, self.nVal) - self.coefList = numpy.zeros((self.nVal, 2), "intc") + self.coefList = np.zeros((self.nVal, 2), "intc") j = 0 for i in range(len(coefList)): @@ -4359,10 +4359,10 @@ def _convertTo1D(value, dim1): otherwise, a scalar will be 'upcast' to that size """ - if numpy.isscalar: - return value * numpy.ones(dim1) + if np.isscalar: + return value * np.ones(dim1) else: - temp = numpy.atleast_1d(value) + temp = np.atleast_1d(value) if temp.shape[0] == dim1: return value else: @@ -4404,7 +4404,7 @@ def __init__(self, dvName, lower, upper, scale, axis, vol_dv_to_coefs, mask, con raise NotImplementedError self.nVal = len(self.dv_to_coefs) - self.value = numpy.zeros(self.nVal, "D") + self.value = np.zeros(self.nVal, "D") self.name = dvName self.lower = None @@ -4477,7 +4477,7 @@ def __init__(self, dvName, lower, upper, scale, axis, coefListIn, mask, config, self.coefList.append(coefListIn[i]) self.nVal = len(self.coefList) - self.value = numpy.zeros(self.nVal, "D") + self.value = np.zeros(self.nVal, "D") self.name = dvName self.lower = None self.upper = None @@ -4500,7 +4500,7 @@ def __call__(self, coef, coefRotM, config): if self.config is None or config is None or any(c0 == config for c0 in self.config): for i in range(len(self.coefList)): T = self.sectionTransform[self.sectionLink[self.coefList[i]]] - inFrame = numpy.zeros(3) + inFrame = np.zeros(3) inFrame[self.axis] = self.value[i].real R = coefRotM[self.coefList[i]].real @@ -4511,7 +4511,7 @@ def updateComplex(self, coef, coefRotM, config): if self.config is None or config is None or any(c0 == config for c0 in self.config): for i in range(len(self.coefList)): T = self.sectionTransform[self.sectionLink[self.coefList[i]]] - inFrame = numpy.zeros(3, "D") + inFrame = np.zeros(3, "D") inFrame[self.axis] = self.value[i] R = coefRotM[self.coefList[i]] diff --git a/pygeo/DVGeometryAxi.py b/pygeo/DVGeometryAxi.py index 375731c6..8e24f382 100644 --- a/pygeo/DVGeometryAxi.py +++ b/pygeo/DVGeometryAxi.py @@ -1,14 +1,6 @@ import numpy as np from scipy import sparse - -try: - from collections import OrderedDict -except ImportError: - try: - from ordereddict import OrderedDict - except ImportError: - print("Could not find any OrderedDict class. For 2.6 and earlier, " "use:\n pip install ordereddict") - +from collections import OrderedDict from . import DVGeometry AXES_2_IDX = {"x": 0, "y": 1, "z": 2} diff --git a/pygeo/DVGeometryESP.py b/pygeo/DVGeometryESP.py index c607d65c..ef239ddd 100644 --- a/pygeo/DVGeometryESP.py +++ b/pygeo/DVGeometryESP.py @@ -4,7 +4,7 @@ import os import sys import time -import numpy +import numpy as np from collections import OrderedDict from mpi4py import MPI from pyOCSM import pyOCSM @@ -154,11 +154,11 @@ def __init__( if ulimits is not None: self.ulimits = ulimits else: - self.ulimits = numpy.array([-99999.0, 99999.0]) + self.ulimits = np.array([-99999.0, 99999.0]) if vlimits is not None: self.vlimits = vlimits else: - self.vlimits = numpy.array([-99999.0, 99999.0]) + self.vlimits = np.array([-99999.0, 99999.0]) self.comm = comm self.espFile = espFile self.debug = debug @@ -218,7 +218,7 @@ def __init__( try: pmtrIndex += 1 pmtrType, numRow, numCol, pmtrName = self.espModel.GetPmtr(pmtrIndex) - baseValue = numpy.zeros(numRow * numCol) + baseValue = np.zeros(numRow * numCol) for rowIdx in range(numRow): for colIdx in range(numCol): try: @@ -278,12 +278,12 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, # save this name so that we can zero out the jacobians properly self.points[ptName] = True # ADFlow checks self.points to see # if something is added or not. - points = numpy.array(points).real.astype("d") + points = np.array(points).real.astype("d") # check that duplicated pointsets are actually the same length - sizes = numpy.array(self.comm.allgather(points.shape[0]), dtype="intc") + sizes = np.array(self.comm.allgather(points.shape[0]), dtype="intc") if not distributed: - all_same_length = numpy.all(sizes == sizes[0]) + all_same_length = np.all(sizes == sizes[0]) if not all_same_length: raise ValueError( "Nondistributed pointsets must be identical on each proc, but these pointsets vary in length per proc. Lengths: ", @@ -300,7 +300,7 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, if os.path.isfile(cache_projections): cache_loaded = True if self.comm.rank == 0: - cached_pt_arrays = numpy.load(cache_projections) + cached_pt_arrays = np.load(cache_projections) cached_sizes = cached_pt_arrays["sizes"] cached_nprocs = cached_pt_arrays["nprocs"] cached_distrib = cached_pt_arrays["distributed"] @@ -337,7 +337,7 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, cache_projections, " is invalid because the cache was saved with different num procs", ) - if not numpy.all(cached_sizes == sizes): + if not np.all(cached_sizes == sizes): raise ValueError( "Cached pointset file ", cache_projections, @@ -355,14 +355,14 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, nptsl = points.shape[0] # set up recieve buffers for all procs - faceIDl = numpy.zeros(nptsl, dtype="intc") - bodyIDl = numpy.zeros(nptsl, dtype="intc") - edgeIDl = numpy.zeros(nptsl, dtype="intc") - ul = numpy.zeros(nptsl) - vl = numpy.zeros(nptsl) - tl = numpy.zeros(nptsl) - uvliml = numpy.zeros((nptsl, 4)) - tliml = numpy.zeros((nptsl, 2)) + faceIDl = np.zeros(nptsl, dtype="intc") + bodyIDl = np.zeros(nptsl, dtype="intc") + edgeIDl = np.zeros(nptsl, dtype="intc") + ul = np.zeros(nptsl) + vl = np.zeros(nptsl) + tl = np.zeros(nptsl) + uvliml = np.zeros((nptsl, 4)) + tliml = np.zeros((nptsl, 2)) recvbuf1 = [bodyIDl, MPI.INT] recvbuf2 = [faceIDl, MPI.INT] @@ -374,8 +374,8 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, recvbuf8 = [tliml, MPI.DOUBLE] if distributed: # displacements for scatter - disp = numpy.array([numpy.sum(sizes[:i]) for i in range(self.comm.size)], dtype="intc") - # nptsg = numpy.sum(sizes) + disp = np.array([np.sum(sizes[:i]) for i in range(self.comm.size)], dtype="intc") + # nptsg = np.sum(sizes) if self.comm.rank == 0: sendbuf1 = [bodyIDg, sizes, disp, MPI.INT] sendbuf2 = [faceIDg, sizes, disp, MPI.INT] @@ -431,12 +431,12 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, # empty pointset can occur for some distributed pointsets dMax_local = 0.0 else: - dMax_local = numpy.max(numpy.sqrt(numpy.sum((points - proj_pts) ** 2, axis=1))) + dMax_local = np.max(np.sqrt(np.sum((points - proj_pts) ** 2, axis=1))) dMax_global = self.comm.allreduce(dMax_local, op=MPI.MAX) if (dMax_global - cached_dmax) / cached_dmax >= 1e-3: raise ValueError("The cached point projections appear to no longer be valid for this geometry") - uvl = numpy.column_stack([ul, vl]) + uvl = np.column_stack([ul, vl]) self.pointSets[ptName] = PointSet( points, proj_pts, bodyIDl, faceIDl, edgeIDl, uvl, tl, uvliml, tliml, distributed ) @@ -451,17 +451,17 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, # then calculate the self.offset variable using the projected points. # coordinates to store the physical coords (xyz) of the projected points - proj_pts_esp = numpy.zeros_like(points) + proj_pts_esp = np.zeros_like(points) npoints = len(points) - bodyIDArray = numpy.zeros(npoints, dtype="intc") - faceIDArray = numpy.zeros(npoints, dtype="intc") - edgeIDArray = numpy.zeros(npoints, dtype="intc") - uv = numpy.zeros((npoints, 2)) - t = numpy.zeros(npoints) - uvlimArray = numpy.zeros((npoints, 4)) - tlimArray = numpy.zeros((npoints, 2)) - dists = numpy.ones((npoints), dtype="float_") * 999999.0 + bodyIDArray = np.zeros(npoints, dtype="intc") + faceIDArray = np.zeros(npoints, dtype="intc") + edgeIDArray = np.zeros(npoints, dtype="intc") + uv = np.zeros((npoints, 2)) + t = np.zeros(npoints) + uvlimArray = np.zeros((npoints, 4)) + tlimArray = np.zeros((npoints, 2)) + dists = np.ones((npoints), dtype="float_") * 999999.0 t1 = time.time() # TODO parallelize projections for nondistributed pointsets? @@ -490,8 +490,8 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, # get the parametric coordinate along the edge ttemp = self.espModel.GetUV(bodyIndex, pyOCSM.EDGE, edgeIndex, 1, truexyz.tolist()) # get the xyz location of the newly projected point - xyztemp = numpy.array(self.espModel.GetXYZ(bodyIndex, pyOCSM.EDGE, edgeIndex, 1, ttemp)) - dist_temp = numpy.sum((truexyz - xyztemp) ** 2) + xyztemp = np.array(self.espModel.GetXYZ(bodyIndex, pyOCSM.EDGE, edgeIndex, 1, ttemp)) + dist_temp = np.sum((truexyz - xyztemp) ** 2) ttemp = ttemp[0] tlimits = self._getUVLimits(bodyIndex, pyOCSM.EDGE, edgeIndex) if not (ttemp < tlimits[0] - rejectuvtol or ttemp > tlimits[1] + rejectuvtol): @@ -508,8 +508,8 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, # get the projected points on the ESP surface in UV coordinates uvtemp = self.espModel.GetUV(bodyIndex, pyOCSM.FACE, faceIndex, 1, truexyz.tolist()) # get the XYZ location of the newly projected points - xyztemp = numpy.array(self.espModel.GetXYZ(bodyIndex, pyOCSM.FACE, faceIndex, 1, uvtemp)) - dist_temp = numpy.sum((truexyz - xyztemp) ** 2) + xyztemp = np.array(self.espModel.GetXYZ(bodyIndex, pyOCSM.FACE, faceIndex, 1, uvtemp)) + dist_temp = np.sum((truexyz - xyztemp) ** 2) # validate u and v utemp = uvtemp[0] vtemp = uvtemp[1] @@ -543,8 +543,8 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, faceIDArray[ptidx] = fi_best edgeIDArray[ptidx] = ei_best bodyIDArray[ptidx] = bi_best - uvlimArray[ptidx, :] = numpy.array(uvlimits_best) - tlimArray[ptidx, :] = numpy.array(tlimits_best) + uvlimArray[ptidx, :] = np.array(uvlimits_best) + tlimArray[ptidx, :] = np.array(tlimits_best) uv[ptidx, 0] = uv_best[0] uv[ptidx, 1] = uv_best[1] t[ptidx] = t_best @@ -553,7 +553,7 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, proj_pts = proj_pts_esp * self.espScale if points.shape[0] != 0: - dMax = numpy.max(numpy.sqrt(numpy.sum((points - proj_pts) ** 2, axis=1))) + dMax = np.max(np.sqrt(np.sum((points - proj_pts) ** 2, axis=1))) else: dMax = 0.0 @@ -591,9 +591,9 @@ def addPointSet(self, points, ptName, distributed=True, cache_projections=False, edgeIDg = edgeIDArray uvlimitsg = uvlimArray tlimitsg = tlimArray - sizes = numpy.array([len(ug)]) + sizes = np.array([len(ug)]) if self.comm.rank == 0: - numpy.savez_compressed( + np.savez_compressed( cache_projections, distributed=distributed, sizes=sizes, @@ -800,7 +800,7 @@ def totalSensitivity(self, dIdpt, ptSetName, comm=None, config=None): # Make dIdpt at least 3D if len(dIdpt.shape) == 2: - dIdpt = numpy.array([dIdpt]) + dIdpt = np.array([dIdpt]) N = dIdpt.shape[0] nPt = dIdpt.shape[1] @@ -823,7 +823,7 @@ def totalSensitivity(self, dIdpt, ptSetName, comm=None, config=None): # # transpose dIdpt and vstack; # # Now vstack the result with seamBar as that is far as the # # forward FD jacobian went. - # tmp = numpy.vstack([dIdpt.T, dIdSeam.T]) + # tmp = np.vstack([dIdpt.T, dIdSeam.T]) tmp = dIdpt.T # we also stack the pointset jacobian @@ -843,7 +843,7 @@ def totalSensitivity(self, dIdpt, ptSetName, comm=None, config=None): dv = self.DVs[dvName] jac_start = dv.globalStartInd jac_end = jac_start + dv.nVal - # dIdxDict[dvName] = numpy.array([dIdx[:, i]]).T + # dIdxDict[dvName] = np.array([dIdx[:, i]]).T dIdxDict[dvName] = dIdx[:, jac_start:jac_end] return dIdxDict @@ -879,7 +879,7 @@ def totalSensitivityProd(self, vec, ptSetName, comm=None, config=None): self._computeSurfJacobian() # vector that has all the derivative seeds of the design vars - newvec = numpy.zeros(self.getNDV()) + newvec = np.zeros(self.getNDV()) for dvName in self.DVs: dv = self.DVs[dvName] @@ -985,7 +985,7 @@ def addVariable( if upper is not None: if isinstance(upper, (float, int)): - upper = numpy.ones((len(rows) * len(cols),)) * upper + upper = np.ones((len(rows) * len(cols),)) * upper if len(upper) != len(rows) * len(cols): raise Error( "User-specified DV upper bound does not match the dimensionality" @@ -997,7 +997,7 @@ def addVariable( if lower is not None: if isinstance(lower, (float, int)): - lower = numpy.ones((len(rows) * len(cols),)) * lower + lower = np.ones((len(rows) * len(cols),)) * lower if len(lower) != len(rows) * len(cols): raise Error( "User-specified DV lower bound does not match the dimensionality" @@ -1066,7 +1066,7 @@ def _csmToFlat(self, value, rows, cols, numRow, numCol): # early exit for non-sliced arrays valOut = value else: - valOut = numpy.zeros(len(rows) * len(cols)) + valOut = np.zeros(len(rows) * len(cols)) irow = 0 for rowInd in rows: icol = 0 @@ -1080,8 +1080,8 @@ def _validateRowCol(self, rows, cols, numRow, numCol, dvName): # check that all rows, cols specified are within desmptr bounds # check for duplicate rows, cols if rows is not None: - rowArr = numpy.array(rows) - if numpy.max(rowArr) > numRow: + rowArr = np.array(rows) + if np.max(rowArr) > numRow: raise Error( "Design variable " + dvName @@ -1089,11 +1089,11 @@ def _validateRowCol(self, rows, cols, numRow, numCol, dvName): + "Design var has " + str(numRow) + " rows and index up to " - + str(numpy.max(rowArr)) + + str(np.max(rowArr)) + " was specified: " + str(rows) ) - if numpy.min(rowArr) < 1: + if np.min(rowArr) < 1: raise Error( "Design variable " + dvName @@ -1106,8 +1106,8 @@ def _validateRowCol(self, rows, cols, numRow, numCol, dvName): raise Error("Duplicate indices specified in the rows of design variable " + dvName + ": " + str(rows)) if cols is not None: - colArr = numpy.array(cols) - if numpy.max(colArr) > numCol: + colArr = np.array(cols) + if np.max(colArr) > numCol: raise Error( "Design variable " + dvName @@ -1115,11 +1115,11 @@ def _validateRowCol(self, rows, cols, numRow, numCol, dvName): + "Design var has " + str(numCol) + " cols and index up to " - + str(numpy.max(colArr)) + + str(np.max(colArr)) + " was specified: " + str(cols) ) - if numpy.min(colArr) < 1: + if np.min(colArr) < 1: raise Error( "Design variable " + dvName @@ -1160,7 +1160,7 @@ def _updateESPModel(self): return True def _evaluatePoints(self, u, v, t, uvlimits0, tlimits0, bodyID, faceID, edgeID, nPts): - points = numpy.zeros((nPts, 3)) + points = np.zeros((nPts, 3)) for ptidx in range(nPts): # check if on an edge or surface bid = bodyID[ptidx] @@ -1216,23 +1216,23 @@ def _updateProjectedPts(self): def _allgatherCoordinates(self, ul, vl, tl, faceIDl, bodyIDl, edgeIDl, uvlimitsl, tlimitsl): # create the arrays to receive the global info # now figure out which proc has how many points. - sizes = numpy.array(self.comm.allgather(len(ul)), dtype="intc") + sizes = np.array(self.comm.allgather(len(ul)), dtype="intc") # displacements for allgather - disp = numpy.array([numpy.sum(sizes[:i]) for i in range(self.comm.size)], dtype="intc") + disp = np.array([np.sum(sizes[:i]) for i in range(self.comm.size)], dtype="intc") # global number of points - nptsg = numpy.sum(sizes) - ug = numpy.zeros(nptsg) - vg = numpy.zeros(nptsg) - tg = numpy.zeros(nptsg) - faceIDg = numpy.zeros(nptsg, dtype="intc") - bodyIDg = numpy.zeros(nptsg, dtype="intc") - edgeIDg = numpy.zeros(nptsg, dtype="intc") - ulower0g = numpy.zeros(nptsg) - uupper0g = numpy.zeros(nptsg) - vlower0g = numpy.zeros(nptsg) - vupper0g = numpy.zeros(nptsg) - tlower0g = numpy.zeros(nptsg) - tupper0g = numpy.zeros(nptsg) + nptsg = np.sum(sizes) + ug = np.zeros(nptsg) + vg = np.zeros(nptsg) + tg = np.zeros(nptsg) + faceIDg = np.zeros(nptsg, dtype="intc") + bodyIDg = np.zeros(nptsg, dtype="intc") + edgeIDg = np.zeros(nptsg, dtype="intc") + ulower0g = np.zeros(nptsg) + uupper0g = np.zeros(nptsg) + vlower0g = np.zeros(nptsg) + vupper0g = np.zeros(nptsg) + tlower0g = np.zeros(nptsg) + tupper0g = np.zeros(nptsg) ulowerl = uvlimitsl[:, 0].copy() uupperl = uvlimitsl[:, 1].copy() vlowerl = uvlimitsl[:, 2].copy() @@ -1255,8 +1255,8 @@ def _allgatherCoordinates(self, ul, vl, tl, faceIDl, bodyIDl, edgeIDl, uvlimitsl self.comm.Allgatherv([tlowerl, len(tlowerl)], [tlower0g, sizes, disp, MPI.DOUBLE]) self.comm.Allgatherv([tupperl, len(tupperl)], [tupper0g, sizes, disp, MPI.DOUBLE]) - uvlimitsg = numpy.column_stack((ulower0g, uupper0g, vlower0g, vupper0g)) - tlimitsg = numpy.column_stack((tlower0g, tupper0g)) + uvlimitsg = np.column_stack((ulower0g, uupper0g, vlower0g, vupper0g)) + tlimitsg = np.column_stack((tlower0g, tupper0g)) return ug, vg, tg, faceIDg, bodyIDg, edgeIDg, uvlimitsg, tlimitsg, sizes @@ -1285,19 +1285,19 @@ def _computeSurfJacobian(self, fd=True): rank = self.comm.rank # arrays to collect local pointset info - ul = numpy.zeros(0) # local u coordinates - vl = numpy.zeros(0) # local v coordinates - tl = numpy.zeros(0) # local t coordinates - faceIDl = numpy.zeros(0, dtype="intc") # surface index - bodyIDl = numpy.zeros(0, dtype="intc") # body index - edgeIDl = numpy.zeros(0, dtype="intc") # edge index - uvlimitsl = numpy.zeros((0, 4)) - tlimitsl = numpy.zeros((0, 2)) + ul = np.zeros(0) # local u coordinates + vl = np.zeros(0) # local v coordinates + tl = np.zeros(0) # local t coordinates + faceIDl = np.zeros(0, dtype="intc") # surface index + bodyIDl = np.zeros(0, dtype="intc") # body index + edgeIDl = np.zeros(0, dtype="intc") # edge index + uvlimitsl = np.zeros((0, 4)) + tlimitsl = np.zeros((0, 2)) any_ptset_nondistributed = False any_ptset_distributed = False for ptSetName in self.pointSets: # initialize the Jacobians - self.pointSets[ptSetName].jac = numpy.zeros((3 * self.pointSets[ptSetName].nPts, nDV)) + self.pointSets[ptSetName].jac = np.zeros((3 * self.pointSets[ptSetName].nPts, nDV)) if self.pointSets[ptSetName].distributed: any_ptset_distributed = True else: @@ -1305,14 +1305,14 @@ def _computeSurfJacobian(self, fd=True): # first, we need to vstack all the point set info we have # counts of these are also important, saved in ptSet.nPts - ul = numpy.concatenate((ul, self.pointSets[ptSetName].u)) - vl = numpy.concatenate((vl, self.pointSets[ptSetName].v)) - tl = numpy.concatenate((tl, self.pointSets[ptSetName].t)) - faceIDl = numpy.concatenate((faceIDl, self.pointSets[ptSetName].faceID)) - bodyIDl = numpy.concatenate((bodyIDl, self.pointSets[ptSetName].bodyID)) - edgeIDl = numpy.concatenate((edgeIDl, self.pointSets[ptSetName].edgeID)) - uvlimitsl = numpy.concatenate((uvlimitsl, self.pointSets[ptSetName].uvlimits0)) - tlimitsl = numpy.concatenate((tlimitsl, self.pointSets[ptSetName].tlimits0)) + ul = np.concatenate((ul, self.pointSets[ptSetName].u)) + vl = np.concatenate((vl, self.pointSets[ptSetName].v)) + tl = np.concatenate((tl, self.pointSets[ptSetName].t)) + faceIDl = np.concatenate((faceIDl, self.pointSets[ptSetName].faceID)) + bodyIDl = np.concatenate((bodyIDl, self.pointSets[ptSetName].bodyID)) + edgeIDl = np.concatenate((edgeIDl, self.pointSets[ptSetName].edgeID)) + uvlimitsl = np.concatenate((uvlimitsl, self.pointSets[ptSetName].uvlimits0)) + tlimitsl = np.concatenate((tlimitsl, self.pointSets[ptSetName].tlimits0)) if any_ptset_distributed and any_ptset_nondistributed: raise ValueError( "Both nondistributed and distributed pointsets were added to this DVGeoESP which is not yet supported" @@ -1323,11 +1323,11 @@ def _computeSurfJacobian(self, fd=True): if self.maxproc is not None: raise ValueError("Max processor limit is not usable with distributed pointsets") # now figure out which proc has how many points. - sizes = numpy.array(self.comm.allgather(len(ul)), dtype="intc") + sizes = np.array(self.comm.allgather(len(ul)), dtype="intc") # displacements for allgather - disp = numpy.array([numpy.sum(sizes[:i]) for i in range(nproc)], dtype="intc") + disp = np.array([np.sum(sizes[:i]) for i in range(nproc)], dtype="intc") # global number of points - nptsg = numpy.sum(sizes) + nptsg = np.sum(sizes) ug, vg, tg, faceIDg, bodyIDg, edgeIDg, uvlimitsg, tlimitsg, sizes = self._allgatherCoordinates( ul, vl, tl, faceIDl, bodyIDl, edgeIDl, uvlimitsl, tlimitsl ) @@ -1344,7 +1344,7 @@ def _computeSurfJacobian(self, fd=True): # create a local new point array. We will use this to get the new # coordinates as we perturb DVs. We just need one (instead of nDV times the size) # because we get the new points, calculate the jacobian and save it right after - ptsNewL = numpy.zeros(len(ul) * 3) + ptsNewL = np.zeros(len(ul) * 3) # we now have all the point info on all procs. tcomm += time.time() - t1 @@ -1361,7 +1361,7 @@ def _computeSurfJacobian(self, fd=True): # evaluate all the points pts0 = self._evaluatePoints(ug, vg, tg, uvlimitsg, tlimitsg, bodyIDg, faceIDg, edgeIDg, nptsg) # allocate the approriate sized numpy array for the perturbed points - ptsNew = numpy.zeros((n, nptsg, 3)) + ptsNew = np.zeros((n, nptsg, 3)) # perturb the DVs on different procs and compute the new point coordinates. i = 0 # Counter on local Jac @@ -1431,7 +1431,7 @@ def _computeSurfJacobian(self, fd=True): if root_proc == rank: sendbuf = [ptsNew[ii, :, :].flatten(), sizes * 3, disp * 3, MPI.DOUBLE] else: - sendbuf = [numpy.zeros((0, 3)), sizes * 3, disp * 3, MPI.DOUBLE] + sendbuf = [np.zeros((0, 3)), sizes * 3, disp * 3, MPI.DOUBLE] recvbuf = [ptsNewL, MPI.DOUBLE] # scatter the info from the proc that perturbed this DV to all procs self.comm.Scatterv(sendbuf, recvbuf, root=root_proc) @@ -1497,7 +1497,7 @@ def __init__(self, csmDesPmtr, name, value, lower, upper, scale, rows, cols, dh, """Internal class for storing ESP design variable information""" self.csmDesPmtr = csmDesPmtr self.name = name - self.value = numpy.array(value) + self.value = np.array(value) self.lower = lower self.upper = upper self.scale = scale diff --git a/pygeo/DVGeometryVSP.py b/pygeo/DVGeometryVSP.py index 4e33e888..345306f5 100644 --- a/pygeo/DVGeometryVSP.py +++ b/pygeo/DVGeometryVSP.py @@ -3,7 +3,7 @@ # ====================================================================== from collections import OrderedDict import time -import numpy +import numpy as np from mpi4py import MPI # mdolab packages @@ -193,7 +193,7 @@ def addPointSet(self, points, ptName, **kwargs): # ADFlow checks self.points to see if something is added or not. self.points[ptName] = True - points = numpy.array(points).real.astype("d") + points = np.array(points).real.astype("d") # we need to project each of these points onto the VSP geometry, # get geometry and surface IDs, u, v values, and coordinates of the projections. @@ -211,30 +211,30 @@ def addPointSet(self, points, ptName, **kwargs): # after this point we should have the projected points. else: - faceID = numpy.zeros((0), "intc") - uv = numpy.zeros((0, 2), "intc") + faceID = np.zeros((0), "intc") + uv = np.zeros((0, 2), "intc") # now we need to figure out which surfaces the points got projected to # From the faceID we can back out what component each one is # connected to. This way if we have intersecting components we # only change the ones that are apart of the two surfaces. - cumFaceSizes = numpy.zeros(len(self.sizes) + 1, "intc") + cumFaceSizes = np.zeros(len(self.sizes) + 1, "intc") for i in range(len(self.sizes)): nCellI = self.sizes[i][0] - 1 nCellJ = self.sizes[i][1] - 1 cumFaceSizes[i + 1] = cumFaceSizes[i] + nCellI * nCellJ - compIDs = numpy.searchsorted(cumFaceSizes, faceID, side="right") - 1 + compIDs = np.searchsorted(cumFaceSizes, faceID, side="right") - 1 # coordinates to store the projected points - pts = numpy.zeros(points.shape) + pts = np.zeros(points.shape) # npoints * 3 list containing the geomID, u and v values # this can be improved if we can group points that get # projected to the same geometry. npoints = len(points) - geom = numpy.zeros(npoints, dtype="intc") - u = numpy.zeros(npoints) - v = numpy.zeros(npoints) + geom = np.zeros(npoints, dtype="intc") + u = np.zeros(npoints) + v = np.zeros(npoints) # initialize one 3dvec for projections pnt = openvsp.vec3d() @@ -259,8 +259,8 @@ def addPointSet(self, points, ptName, **kwargs): nn = nodeInd - self.cumSizes[gind] # figure out the i and j indices of the first point of the element # we projected this point to - ii = numpy.mod(nn, self.sizes[gind, 0]) - jj = numpy.floor_divide(nn, self.sizes[gind, 0]) + ii = np.mod(nn, self.sizes[gind, 0]) + jj = np.floor_divide(nn, self.sizes[gind, 0]) # calculate the global u and v change in this element du = self.uv[gind][0][ii + 1] - self.uv[gind][0][ii] @@ -510,7 +510,7 @@ def totalSensitivity(self, dIdpt, ptSetName, comm=None, config=None): # Make dIdpt at least 3D if len(dIdpt.shape) == 2: - dIdpt = numpy.array([dIdpt]) + dIdpt = np.array([dIdpt]) # reshape the dIdpt array from [N] * [nPt] * [3] to [N] * [nPt*3] dIdpt = dIdpt.reshape((dIdpt.shape[0], dIdpt.shape[1] * 3)) @@ -534,7 +534,7 @@ def totalSensitivity(self, dIdpt, ptSetName, comm=None, config=None): dIdxDict = {} i = 0 for dvName in self.DVs: - dIdxDict[dvName] = numpy.array(dIdx[:, i]).T + dIdxDict[dvName] = np.array(dIdx[:, i]).T i += 1 return dIdxDict @@ -577,7 +577,7 @@ def totalSensitivityProd(self, vec, ptSetName, comm=None, config=None): self._computeSurfJacobian() # vector that has all the derivative seeds of the design vars - newvec = numpy.zeros(self.getNDV()) + newvec = np.zeros(self.getNDV()) # populate newvec for i, dv in enumerate(self.DVs): @@ -644,7 +644,7 @@ def totalSensitivityTransProd(self, dIdpt, ptSetName, comm=None, config=None): # Make dIdpt at least 3D if len(dIdpt.shape) == 2: - dIdpt = numpy.array([dIdpt]) + dIdpt = np.array([dIdpt]) # reshape the dIdpt array from [N] * [nPt] * [3] to [N] * [nPt*3] dIdpt = dIdpt.reshape((dIdpt.shape[0], dIdpt.shape[1] * 3)) @@ -662,7 +662,7 @@ def totalSensitivityTransProd(self, dIdpt, ptSetName, comm=None, config=None): dIdxDict = {} i = 0 for dvName in self.DVs: - dIdxDict[dvName] = numpy.array(dIdx[:, i]).T + dIdxDict[dvName] = np.array(dIdx[:, i]).T i += 1 return dIdxDict @@ -827,7 +827,7 @@ def _updateProjectedPts(self): for ptSetName in self.pointSets: # get the current coordinates of projection points n = len(self.pointSets[ptSetName].points) - newPts = numpy.zeros((n, 3)) + newPts = np.zeros((n, 3)) # newPts should get the new projected coords @@ -858,14 +858,14 @@ def _getBBox(self, comp): """ # initialize the array - bbox = numpy.zeros((3, 2)) + bbox = np.zeros((3, 2)) # we need to get the number of main surfaces on this geometry nSurf = openvsp.GetNumMainSurfs(comp) nuv = self.bboxuv.shape[0] # allocate the arrays - nodes = numpy.zeros((nSurf * nuv, 3)) + nodes = np.zeros((nSurf * nuv, 3)) # loop over the surfaces for iSurf in range(nSurf): @@ -901,14 +901,14 @@ def _getuv(self): nv = 20 # define the points on the parametric domain to sample - ul = numpy.linspace(0, 1, nu + 1) - vl = numpy.linspace(0, 1, nv + 1) - uu, vv = numpy.meshgrid(ul, vl) + ul = np.linspace(0, 1, nu + 1) + vl = np.linspace(0, 1, nv + 1) + uu, vv = np.meshgrid(ul, vl) uu = uu.flatten() vv = vv.flatten() # now create a concentrated uv array - uv = numpy.dstack((uu, vv)).squeeze() + uv = np.dstack((uu, vv)).squeeze() return uv.copy() @@ -945,35 +945,35 @@ def _computeSurfJacobian(self): rank = self.comm.rank # arrays to collect local pointset info - ul = numpy.zeros(0) - vl = numpy.zeros(0) - gl = numpy.zeros(0, dtype="intc") + ul = np.zeros(0) + vl = np.zeros(0) + gl = np.zeros(0, dtype="intc") for ptSetName in self.pointSets: # initialize the Jacobians - self.pointSets[ptSetName].jac = numpy.zeros((3 * self.pointSets[ptSetName].nPts, nDV)) + self.pointSets[ptSetName].jac = np.zeros((3 * self.pointSets[ptSetName].nPts, nDV)) # first, we need to vstack all the point set info we have # counts of these are also important, saved in ptSet.nPts - ul = numpy.concatenate((ul, self.pointSets[ptSetName].u)) - vl = numpy.concatenate((vl, self.pointSets[ptSetName].v)) - gl = numpy.concatenate((gl, self.pointSets[ptSetName].geom)) + ul = np.concatenate((ul, self.pointSets[ptSetName].u)) + vl = np.concatenate((vl, self.pointSets[ptSetName].v)) + gl = np.concatenate((gl, self.pointSets[ptSetName].geom)) # now figure out which proc has how many points. - sizes = numpy.array(self.comm.allgather(len(ul)), dtype="intc") + sizes = np.array(self.comm.allgather(len(ul)), dtype="intc") # displacements for allgather - disp = numpy.array([numpy.sum(sizes[:i]) for i in range(nproc)], dtype="intc") + disp = np.array([np.sum(sizes[:i]) for i in range(nproc)], dtype="intc") # global number of points - nptsg = numpy.sum(sizes) + nptsg = np.sum(sizes) # create a local new point array. We will use this to get the new # coordinates as we perturb DVs. We just need one (instead of nDV times the size) # because we get the new points, calculate the jacobian and save it right after - ptsNewL = numpy.zeros(len(ul) * 3) + ptsNewL = np.zeros(len(ul) * 3) # create the arrays to receive the global info - ug = numpy.zeros(nptsg) - vg = numpy.zeros(nptsg) - gg = numpy.zeros(nptsg, dtype="intc") + ug = np.zeros(nptsg) + vg = np.zeros(nptsg) + gg = np.zeros(nptsg, dtype="intc") # Now we do an allGatherv to get a long list of all pointset information self.comm.Allgatherv([ul, len(ul)], [ug, sizes, disp, MPI.DOUBLE]) @@ -986,7 +986,7 @@ def _computeSurfJacobian(self): # We need to evaluate all the points on respective procs for FD computations # allocate memory - pts0 = numpy.zeros((nptsg, 3)) + pts0 = np.zeros((nptsg, 3)) # evaluate the points for j in range(nptsg): @@ -1001,7 +1001,7 @@ def _computeSurfJacobian(self): n += 1 # allocate the approriate sized numpy array for the perturbed points - ptsNew = numpy.zeros((n, nptsg, 3)) + ptsNew = np.zeros((n, nptsg, 3)) # perturb the DVs on different procs and compute the new point coordinates. i = 0 # Counter on local Jac @@ -1061,7 +1061,7 @@ def _computeSurfJacobian(self): if iDV % nproc == rank: sendbuf = [ptsNew[ii, :, :].flatten(), sizes * 3, disp * 3, MPI.DOUBLE] else: - sendbuf = [numpy.zeros((0, 3)), sizes * 3, disp * 3, MPI.DOUBLE] + sendbuf = [np.zeros((0, 3)), sizes * 3, disp * 3, MPI.DOUBLE] recvbuf = [ptsNewL, MPI.DOUBLE] # scatter the info from the proc that perturbed this DV to all procs @@ -1110,10 +1110,10 @@ def _getQuads(self): # build the quad mesh using the internal vsp geometry nSurf = len(self.allComps) - pts = numpy.zeros((0, 3)) - conn = numpy.zeros((0, 4), dtype="intc") - sizes = numpy.zeros((nSurf, 2), "intc") - cumSizes = numpy.zeros(nSurf + 1, "intc") + pts = np.zeros((0, 3)) + conn = np.zeros((0, 4), dtype="intc") + sizes = np.zeros((nSurf, 2), "intc") + cumSizes = np.zeros(nSurf + 1, "intc") uv = [] # this will hold tessalation points offset = 0 @@ -1124,13 +1124,13 @@ def _getQuads(self): # check if these values are good, otherwise, do it yourself! # save these values - uv.append([numpy.array(utess), numpy.array(wtess)]) + uv.append([np.array(utess), np.array(wtess)]) nu = len(utess) nv = len(wtess) nElem = (nu - 1) * (nv - 1) # get u,v combinations of nodes - uu, vv = numpy.meshgrid(utess, wtess) + uu, vv = np.meshgrid(utess, wtess) utess = uu.flatten() wtess = vv.flatten() @@ -1141,8 +1141,8 @@ def _getQuads(self): curSize = len(ptvec) # initialize coordinate and connectivity arrays - compPts = numpy.zeros((curSize, 3)) - compConn = numpy.zeros((nElem, 4), dtype="intc") + compPts = np.zeros((curSize, 3)) + compConn = np.zeros((nElem, 4), dtype="intc") # get the coordinates of the points for i in range(curSize): @@ -1162,8 +1162,8 @@ def _getQuads(self): compConn += offset # stack the results - pts = numpy.vstack((pts, compPts)) - conn = numpy.vstack((conn, compConn)) + pts = np.vstack((pts, compPts)) + conn = np.vstack((conn, compConn)) # number of u and v point count sizes[gind, :] = (nu, nv) @@ -1191,7 +1191,7 @@ def __init__(self, parmID, component, group, parm, value, lower, upper, scale, d self.component = component self.group = group self.parm = parm - self.value = numpy.array(value) + self.value = np.array(value) self.lower = lower self.upper = upper self.dh = dh diff --git a/pygeo/geo_utils.py b/pygeo/geo_utils.py index c41ffb26..288d3e22 100644 --- a/pygeo/geo_utils.py +++ b/pygeo/geo_utils.py @@ -406,7 +406,7 @@ def write_wing_FFD_file(fileName, slices, N0, N1, N2, axes=None, dist=None): Example of two volumes ------- axes = ['k', 'j', 'i'] - slices = numpy.array([ + slices = np.array([ # Slice 1 [[[0, 0, 0], [1, 0, 0]], [[0, 0.2, 0], [1, 0.2, 0]]], diff --git a/pygeo/pyBlock.py b/pygeo/pyBlock.py index 4cde9c70..7f0d8db7 100644 --- a/pygeo/pyBlock.py +++ b/pygeo/pyBlock.py @@ -3,7 +3,7 @@ # ====================================================================== import os import copy -import numpy +import numpy as np from scipy import sparse from scipy.sparse import linalg from pyspline import pySpline @@ -99,7 +99,7 @@ def _readPlot3D(self, fileName, order="f", FFD=False, symmTol=0.001): blocks = [] for i in range(nVol): cur_size = sizes[i, 0] * sizes[i, 1] * sizes[i, 2] - blocks.append(numpy.zeros([sizes[i, 0], sizes[i, 1], sizes[i, 2], 3])) + blocks.append(np.zeros([sizes[i, 0], sizes[i, 1], sizes[i, 2], 3])) for idim in range(3): blocks[-1][:, :, :, idim] = readNValues(f, cur_size, "float", binary).reshape( (sizes[i, 0], sizes[i, 1], sizes[i, 2]), order=order @@ -155,7 +155,7 @@ def symmZero(axis, coords, tol): # now create the appended list with double the blocks blocks += newBlocks # Extend sizes - newSizes = numpy.zeros([nVol * 2, 3], "int") + newSizes = np.zeros([nVol * 2, 3], "int") newSizes[:nVol, :] = sizes newSizes[nVol:, :] = sizes sizes = newSizes @@ -172,10 +172,10 @@ def uniformKnots(N, k): """Simple function to generate N uniform knots of order k""" - knots = numpy.zeros(N + k) + knots = np.zeros(N + k) knots[0 : k - 1] = 0.0 knots[-k:] = 1.0 - knots[k - 1 : -k + 1] = numpy.linspace(0, 1, N - k + 2) + knots[k - 1 : -k + 1] = np.linspace(0, 1, N - k + 2) return knots @@ -201,9 +201,9 @@ def uniformKnots(N, k): ) # Generate dummy original data: - U = numpy.zeros((3, 3, 3)) - V = numpy.zeros((3, 3, 3)) - W = numpy.zeros((3, 3, 3)) + U = np.zeros((3, 3, 3)) + V = np.zeros((3, 3, 3)) + W = np.zeros((3, 3, 3)) for i in range(3): for j in range(3): @@ -224,7 +224,7 @@ def uniformKnots(N, k): self.nVol = len(self.vols) self._calcConnectivity(1e-4, 1e-4) nCtl = self.topo.nGlobal - self.coef = numpy.zeros((nCtl, 3)) + self.coef = np.zeros((nCtl, 3)) self._setVolumeCoef() for ivol in range(self.nVol): @@ -266,7 +266,7 @@ def fitGlobal(self, greedyReorder=False): origTopo.calcGlobalNumbering(sizes, greedyReorder=greedyReorder) N = origTopo.nGlobal print(" -> Creating global point list") - pts = numpy.zeros((N, 3)) + pts = np.zeros((N, 3)) for ii in range(N): pts[ii] = self.vols[origTopo.gIndex[ii][0][0]].X[ origTopo.gIndex[ii][0][1], origTopo.gIndex[ii][0][2], origTopo.gIndex[ii][0][3] @@ -278,9 +278,9 @@ def fitGlobal(self, greedyReorder=False): kmax = max(kmax, self.vols[ivol].ku, self.vols[ivol].kv, self.vols[ivol].kw) nnz = N * kmax * kmax * kmax - vals = numpy.zeros(nnz) + vals = np.zeros(nnz) rowPtr = [0] - colInd = numpy.zeros(nnz, "intc") + colInd = np.zeros(nnz, "intc") for ii in range(N): ivol = origTopo.gIndex[ii][0][0] i = origTopo.gIndex[ii][0][1] @@ -305,7 +305,7 @@ def fitGlobal(self, greedyReorder=False): NNT = NN.T NTN = NNT * NN solve = linalg.dsolve.factorized(NTN) - self.coef = numpy.zeros((nCtl, 3)) + self.coef = np.zeros((nCtl, 3)) for idim in range(3): self.coef[:, idim] = solve(NNT * pts[:, idim]) @@ -365,7 +365,7 @@ def _calcConnectivity(self, nodeTol, edgeTol): edgeTol :float Tolerance for midpoint of edges to determine if they are the same """ - coords = numpy.zeros((self.nVol, 26, 3)) + coords = np.zeros((self.nVol, 26, 3)) for ivol in range(self.nVol): for icorner in range(8): @@ -576,8 +576,8 @@ def writeTecplot( if nodeLabels: # First we need to figure out where the corners actually *are* - nNodes = len(numpy.unique(self.topo.nodeLink.flatten())) - nodeCoord = numpy.zeros((nNodes, 3)) + nNodes = len(np.unique(self.topo.nodeLink.flatten())) + nodeCoord = np.zeros((nNodes, 3)) for i in range(nNodes): # Try to find node i @@ -623,7 +623,7 @@ def writePlot3d(self, fileName): f = open(fileName, "w") f.write("%d\n" % (self.nVol)) - numpy.array(sizes).tofile(f, sep=" ") + np.array(sizes).tofile(f, sep=" ") f.write("\n") for ivol in range(self.nVol): vals = self.vols[ivol](self.vols[ivol].U, self.vols[ivol].V, self.vols[ivol].W) @@ -653,7 +653,7 @@ def writePlot3dCoef(self, fileName): f = open(fileName, "w") f.write("%d\n" % (self.nVol)) - numpy.array(sizes).tofile(f, sep=" ") + np.array(sizes).tofile(f, sep=" ") f.write("\n") for ivol in range(self.nVol): vals = self.vols[ivol].coef @@ -683,7 +683,7 @@ def _setVolumeCoef(self): coefficients on the volumes. This typically needs only to be called once when the object is created""" - self.coef = numpy.zeros((self.topo.nGlobal, 3)) + self.coef = np.zeros((self.topo.nGlobal, 3)) for ivol in range(self.nVol): vol = self.vols[ivol] for i in range(vol.nCtlu): @@ -716,9 +716,9 @@ def calcdPtdCoef(self, ptSetName): # Maximum number of non-zeros in jacobian nnz = N * kmax * kmax * kmax - vals = numpy.zeros(nnz) + vals = np.zeros(nnz) rowPtr = [0] - colInd = numpy.zeros(nnz, "intc") + colInd = np.zeros(nnz, "intc") for i in range(N): kinc = self.vols[volID[i]].ku * self.vols[volID[i]].kv * self.vols[volID[i]].kw vals, colInd = self.vols[volID[i]].getBasisPt( @@ -761,7 +761,7 @@ def getAttachedPoints(self, ptSetName): w = self.embededVolumes[ptSetName].w N = self.embededVolumes[ptSetName].N mask = self.embededVolumes[ptSetName].mask - coordinates = numpy.zeros((N, 3)) + coordinates = np.zeros((N, 3)) # This evaluation is fast enough we don't really care about # only looping explictly over the mask values @@ -822,7 +822,7 @@ def attachPoints(self, coordinates, ptSetName, interiorOnly=False, faceFreeze=No mask = [] for i in range(len(D)): - Dnrm = numpy.linalg.norm(D[i]) + Dnrm = np.linalg.norm(D[i]) if Dnrm < 50 * eps: # Sufficiently inside mask.append(i) @@ -866,16 +866,16 @@ def projectPoints(self, x0, eps=1e-12, checkErrors=True, nIter=100): """ # Make sure we are dealing with a 2D "Nx3" list of points - x0 = numpy.atleast_2d(x0) + x0 = np.atleast_2d(x0) N = len(x0) - volID = numpy.zeros(N, "intc") - u = numpy.zeros(N) - v = numpy.zeros(N) - w = numpy.zeros(N) - D = 1e10 * numpy.ones((N, 3)) + volID = np.zeros(N, "intc") + u = np.zeros(N) + v = np.zeros(N) + w = np.zeros(N) + D = 1e10 * np.ones((N, 3)) # Starting list is just [0, 1, 2, ..., nVol-1] - volList = numpy.arange(self.nVol) + volList = np.arange(self.nVol) u0 = 0.0 v0 = 0.0 w0 = 0.0 @@ -885,11 +885,11 @@ def projectPoints(self, x0, eps=1e-12, checkErrors=True, nIter=100): iVol = volList[j] u0, v0, w0, D0 = self.vols[iVol].projectPoint(x0[i], eps=eps, nIter=nIter) - D0Norm = numpy.linalg.norm(D0) + D0Norm = np.linalg.norm(D0) # If the new distance is less than the previous best # distance, set the volID, u, v, w, since this may be # best we can do: - if D0Norm < numpy.linalg.norm(D[i]): + if D0Norm < np.linalg.norm(D[i]): volID[i] = iVol u[i] = u0 @@ -906,7 +906,7 @@ def projectPoints(self, x0, eps=1e-12, checkErrors=True, nIter=100): # Shuffle the order of the volList such that the last # volume used (iVol or volList[j]) is at the start of the # list and the remainder are shuffled towards the back - volList = numpy.hstack([iVol, volList[:j], volList[j + 1 :]]) + volList = np.hstack([iVol, volList[:j], volList[j + 1 :]]) # end for (length of x0) # If desired check the errors and print warnings: @@ -918,7 +918,7 @@ def projectPoints(self, x0, eps=1e-12, checkErrors=True, nIter=100): DRms = 0.0 badPts = [] for i in range(len(x0)): - nrm = numpy.linalg.norm(D[i]) + nrm = np.linalg.norm(D[i]) if nrm > DMax: DMax = nrm @@ -928,7 +928,7 @@ def projectPoints(self, x0, eps=1e-12, checkErrors=True, nIter=100): badPts.append([x0[i], D[i]]) if len(x0) > 0: - DRms = numpy.sqrt(DRms / len(x0)) + DRms = np.sqrt(DRms / len(x0)) else: DRms = None @@ -993,10 +993,10 @@ class EmbeddedVolume(object): """ def __init__(self, volID, u, v, w, mask=None): - self.volID = numpy.array(volID) - self.u = numpy.array(u) - self.v = numpy.array(v) - self.w = numpy.array(w) + self.volID = np.array(volID) + self.u = np.array(u) + self.v = np.array(v) + self.w = np.array(w) self.N = len(self.u) self.indices = {} self.dPtdCoef = None @@ -1004,7 +1004,7 @@ def __init__(self, volID, u, v, w, mask=None): self.mask = mask # Get the number of unique volumes this point set requires: - uniqueVolIDs = numpy.unique(self.volID) + uniqueVolIDs = np.unique(self.volID) for iVol in uniqueVolIDs: - self.indices[iVol] = numpy.where(self.volID == iVol)[0] + self.indices[iVol] = np.where(self.volID == iVol)[0] diff --git a/pygeo/pyGeo.py b/pygeo/pyGeo.py index fb28d898..a5ec2fb9 100644 --- a/pygeo/pyGeo.py +++ b/pygeo/pyGeo.py @@ -3,7 +3,7 @@ # ====================================================================== import os import copy -import numpy +import numpy as np from scipy import sparse from scipy.sparse.linalg.dsolve import factorized from pyspline import pySpline @@ -140,7 +140,7 @@ def _readPlot3D(self, fileName, order="f"): surfs = [] for i in range(nSurf): curSize = sizes[i, 0] * sizes[i, 1] - surfs.append(numpy.zeros([sizes[i, 0], sizes[i, 1], 3])) + surfs.append(np.zeros([sizes[i, 0], sizes[i, 1], 3])) for idim in range(3): surfs[-1][:, :, idim] = geo_utils.readNValues(f, curSize, "float", binary).reshape( (sizes[i, 0], sizes[i, 1]), order=order @@ -220,7 +220,7 @@ def _readIges(self, fileName): counter += Nctlv + kv weights = data[counter : counter + Nctlu * Nctlv] - weights = numpy.array(weights) + weights = np.array(weights) if weights.all() != 1: print( "WARNING: Not all weight in B-spline surface are\ @@ -228,14 +228,14 @@ def _readIges(self, fileName): ) counter += Nctlu * Nctlv - coef = numpy.zeros([Nctlu, Nctlv, 3]) + coef = np.zeros([Nctlu, Nctlv, 3]) for j in range(Nctlv): for i in range(Nctlu): coef[i, j, :] = data[counter : counter + 3] counter += 3 # Last we need the ranges - prange = numpy.zeros(4) + prange = np.zeros(4) prange[0] = data[counter] prange[1] = data[counter + 1] @@ -243,8 +243,8 @@ def _readIges(self, fileName): prange[3] = data[counter + 3] # Re-scale the knot vectors in case the upper bound is not 1 - tu = numpy.array(tu) - tv = numpy.array(tv) + tu = np.array(tu) + tv = np.array(tv) if not tu[-1] == 1.0: tu /= tu[-1] @@ -254,9 +254,9 @@ def _readIges(self, fileName): self.surfs.append(pySpline.Surface(ku=ku, kv=kv, tu=tu, tv=tv, coef=coef)) # Generate dummy data for connectivity to work - u = numpy.linspace(0, 1, 3) - v = numpy.linspace(0, 1, 3) - [V, U] = numpy.meshgrid(v, u) + u = np.linspace(0, 1, 3) + v = np.linspace(0, 1, 3) + [V, U] = np.meshgrid(v, u) self.surfs[-1].X = self.surfs[-1](U, V) self.surfs[-1].Nu = 3 self.surfs[-1].Nv = 3 @@ -299,29 +299,29 @@ def _init_lifting_surface( the most commonly used options.""" if X is not None: - Xsec = numpy.array(X) + Xsec = np.array(X) else: # We have to use x, y, z - Xsec = numpy.vstack([x, y, z]).T + Xsec = np.vstack([x, y, z]).T N = len(Xsec) if rot is not None: - rot = numpy.array(rot) + rot = np.array(rot) else: if rotX is None: - rotX = numpy.zeros(N) + rotX = np.zeros(N) if rotY is None: - rotY = numpy.zeros(N) + rotY = np.zeros(N) if rotZ is None: - rotZ = numpy.zeros(N) - rot = numpy.vstack([rotX, rotY, rotZ]).T + rotZ = np.zeros(N) + rot = np.vstack([rotX, rotY, rotZ]).T if offset is None: - offset = numpy.zeros((N, 2)) + offset = np.zeros((N, 2)) if scale is None: - scale = numpy.ones(N) + scale = np.ones(N) # Limit kSpan to 2 if we only have two cross section if len(Xsec) == 2: @@ -335,15 +335,15 @@ def _init_lifting_surface( ) if teHeight: - teHeight = numpy.atleast_1d(teHeight) + teHeight = np.atleast_1d(teHeight) if len(teHeight) == 1: - teHeight = numpy.ones(N) * teHeight + teHeight = np.ones(N) * teHeight teHeight /= scale if teHeightScaled: - teHeight = numpy.atleast_1d(teHeightScaled) + teHeight = np.atleast_1d(teHeightScaled) if len(teHeight) == 1: - teHeight = numpy.ones(N) * teHeight + teHeight = np.ones(N) * teHeight else: teHeight = [None for i in range(N)] @@ -355,7 +355,7 @@ def _init_lifting_surface( x, y = geo_utils.readAirfoilFile( xsections[i], bluntTe, bluntThickness=teHeight[i], bluntTaperRange=bluntTaperRange ) - weights = numpy.ones(len(x)) + weights = np.ones(len(x)) weights[0] = -1 weights[-1] = -1 if nCtl is not None: @@ -399,7 +399,7 @@ def _init_lifting_surface( if curves[i] is not None: knots = origKnots[i] # Search for all indices - indices = numpy.searchsorted(baseKnots, knots, side="left") + indices = np.searchsorted(baseKnots, knots, side="left") toInsert = [] # Now go over the indices and see if we need to add @@ -487,9 +487,9 @@ def _init_lifting_surface( # airfoil coordinates. if thickness is not None: - thickness = numpy.atleast_1d(thickness) + thickness = np.atleast_1d(thickness) if len(thickness) == 1: - thickness = numpy.ones(len(thickness)) * thickness + thickness = np.ones(len(thickness)) * thickness for i in range(N): # Only scale the interior control points; not the first and last curves[i].coef[1:-1, 1] *= thickness[i] @@ -546,8 +546,8 @@ def _init_lifting_surface( # Now we can set the surfaces ncoef = topCurves[0].nCtl - coefTop = numpy.zeros((ncoef, len(xsections), 3)) - coefBot = numpy.zeros((ncoef, len(xsections), 3)) + coefTop = np.zeros((ncoef, len(xsections), 3)) + coefBot = np.zeros((ncoef, len(xsections), 3)) for i in range(len(xsections)): # Scale, rotate and translate the coefficients @@ -560,13 +560,13 @@ def _init_lifting_surface( coefBot[:, i, 2] = 0 for j in range(ncoef): - coefTop[j, i, :] = geo_utils.rotzV(coefTop[j, i, :], rot[i, 2] * numpy.pi / 180) - coefTop[j, i, :] = geo_utils.rotxV(coefTop[j, i, :], rot[i, 0] * numpy.pi / 180) - coefTop[j, i, :] = geo_utils.rotyV(coefTop[j, i, :], rot[i, 1] * numpy.pi / 180) + coefTop[j, i, :] = geo_utils.rotzV(coefTop[j, i, :], rot[i, 2] * np.pi / 180) + coefTop[j, i, :] = geo_utils.rotxV(coefTop[j, i, :], rot[i, 0] * np.pi / 180) + coefTop[j, i, :] = geo_utils.rotyV(coefTop[j, i, :], rot[i, 1] * np.pi / 180) - coefBot[j, i, :] = geo_utils.rotzV(coefBot[j, i, :], rot[i, 2] * numpy.pi / 180) - coefBot[j, i, :] = geo_utils.rotxV(coefBot[j, i, :], rot[i, 0] * numpy.pi / 180) - coefBot[j, i, :] = geo_utils.rotyV(coefBot[j, i, :], rot[i, 1] * numpy.pi / 180) + coefBot[j, i, :] = geo_utils.rotzV(coefBot[j, i, :], rot[i, 2] * np.pi / 180) + coefBot[j, i, :] = geo_utils.rotxV(coefBot[j, i, :], rot[i, 0] * np.pi / 180) + coefBot[j, i, :] = geo_utils.rotyV(coefBot[j, i, :], rot[i, 1] * np.pi / 180) # Finally translate according to positions specified coefTop[:, i, :] += Xsec[i, :] @@ -580,12 +580,12 @@ def _init_lifting_surface( if bluntTe: if not roundedTe: - coef = numpy.zeros((len(xsections), 2, 3), "d") + coef = np.zeros((len(xsections), 2, 3), "d") coef[:, 0, :] = coefTop[0, :, :] coef[:, 1, :] = coefBot[0, :, :] self.surfs.append(pySpline.Surface(coef=coef, ku=kSpan, kv=2, tu=Xcurve.t, tv=[0, 0, 1, 1])) else: - coef = numpy.zeros((len(xsections), 4, 3), "d") + coef = np.zeros((len(xsections), 4, 3), "d") coef[:, 0, :] = coefTop[0, :, :] coef[:, 3, :] = coefBot[0, :, :] @@ -596,9 +596,9 @@ def _init_lifting_surface( for j in range((len(xsections))): projTop = coefTop[0, j] - coefTop[1, j] projBot = coefBot[0, j] - coefBot[1, j] - projTop /= numpy.linalg.norm(projTop) - projBot /= numpy.linalg.norm(projBot) - curTeThick = numpy.linalg.norm(coefTop[0, j] - coefBot[0, j]) + projTop /= np.linalg.norm(projTop) + projBot /= np.linalg.norm(projBot) + curTeThick = np.linalg.norm(coefTop[0, j] - coefBot[0, j]) coef[j, 1] = coef[j, 0] + projTop * 0.5 * curTeThick * teScale coef[j, 2] = coef[j, 3] + projBot * 0.5 * curTeThick * teScale @@ -611,29 +611,29 @@ def _init_lifting_surface( if tip == "rounded": # Generate the midpoint of the coefficients - midPts = numpy.zeros([ncoef, 3]) - upVec = numpy.zeros([ncoef, 3]) - dsNorm = numpy.zeros([ncoef, 3]) + midPts = np.zeros([ncoef, 3]) + upVec = np.zeros([ncoef, 3]) + dsNorm = np.zeros([ncoef, 3]) for j in range(ncoef): midPts[j] = 0.5 * (coefTop[j, -1] + coefBot[j, -1]) upVec[j] = coefTop[j, -1] - coefBot[j, -1] ds = 0.5 * ((coefTop[j, -1] - coefTop[j, -2]) + (coefBot[j, -1] - coefBot[j, -2])) - dsNorm[j] = ds / numpy.linalg.norm(ds) + dsNorm[j] = ds / np.linalg.norm(ds) # Generate "average" projection Vector - projVec = numpy.zeros((ncoef, 3), "d") + projVec = np.zeros((ncoef, 3), "d") for j in range(ncoef): offset = teOffset + (float(j) / (ncoef - 1)) * (leOffset - teOffset) - projVec[j] = dsNorm[j] * (numpy.linalg.norm(upVec[j] * tipScale + offset)) + projVec[j] = dsNorm[j] * (np.linalg.norm(upVec[j] * tipScale + offset)) # Generate the tip "line" - tipLine = numpy.zeros([ncoef, 3]) + tipLine = np.zeros([ncoef, 3]) for j in range(ncoef): tipLine[j] = midPts[j] + projVec[j] # Generate a k=4 (cubic) surface - coefTopTip = numpy.zeros([ncoef, 4, 3]) - coefBotTip = numpy.zeros([ncoef, 4, 3]) + coefTopTip = np.zeros([ncoef, 4, 3]) + coefBotTip = np.zeros([ncoef, 4, 3]) for j in range(ncoef): coefTopTip[j, 0] = coefTop[j, -1] @@ -697,7 +697,7 @@ def _init_lifting_surface( # surface results. if not roundedTe and not squareTeTip: - coef = numpy.zeros((4, 2, 3), "d") + coef = np.zeros((4, 2, 3), "d") coef[:, 0] = coefTopTip[0, :] coef[:, 1] = coefBotTip[0, :] @@ -706,7 +706,7 @@ def _init_lifting_surface( ) self.nSurf += 1 elif roundedTe: - coef = numpy.zeros((4, 4, 3), "d") + coef = np.zeros((4, 4, 3), "d") coef[:, 0] = coefTopTip[0, :] coef[:, 3] = coefBotTip[0, :] @@ -716,9 +716,9 @@ def _init_lifting_surface( for i in range(4): projTop = coefTopTip[0, i] - coefTopTip[1, i] projBot = coefBotTip[0, i] - coefBotTip[1, i] - projTop /= numpy.linalg.norm(projTop) - projBot /= numpy.linalg.norm(projBot) - curTeThick = numpy.linalg.norm(coefTopTip[0, i] - coefBotTip[0, i]) + projTop /= np.linalg.norm(projTop) + projBot /= np.linalg.norm(projBot) + curTeThick = np.linalg.norm(coefTopTip[0, i] - coefBotTip[0, i]) coef[i, 1] = coef[i, 0] + projTop * 0.5 * curTeThick * teScale coef[i, 2] = coef[i, 3] + projBot * 0.5 * curTeThick * teScale @@ -736,9 +736,9 @@ def _init_lifting_surface( print("No tip specified") # Cheat and make "original data" so that the edge connectivity works - u = numpy.linspace(0, 1, 3) - v = numpy.linspace(0, 1, 3) - [V, U] = numpy.meshgrid(u, v) + u = np.linspace(0, 1, 3) + v = np.linspace(0, 1, 3) + [V, U] = np.meshgrid(u, v) for i in range(self.nSurf): self.surfs[i].origData = True self.surfs[i].X = self.surfs[i](U, V) @@ -776,7 +776,7 @@ def fitGlobal(self): origTopo.calcGlobalNumbering(sizes) N = origTopo.nGlobal print(" -> Creating global point list") - pts = numpy.zeros((N, 3)) + pts = np.zeros((N, 3)) for ii in range(N): pts[ii] = self.surfs[origTopo.gIndex[ii][0][0]].X[origTopo.gIndex[ii][0][1], origTopo.gIndex[ii][0][2]] @@ -789,9 +789,9 @@ def fitGlobal(self): kmax = self.surfs[isurf].kv nnz = N * kmax * kmax - vals = numpy.zeros(nnz) + vals = np.zeros(nnz) rowPtr = [0] - colInd = numpy.zeros(nnz, "intc") + colInd = np.zeros(nnz, "intc") for ii in range(N): isurf = origTopo.gIndex[ii][0][0] @@ -818,7 +818,7 @@ def fitGlobal(self): print(" -> Factorizing...") solve = factorized(NTN) print(" -> Back Solving...") - self.coef = numpy.zeros((nCtl, 3)) + self.coef = np.zeros((nCtl, 3)) for idim in range(3): self.coef[:, idim] = solve(NNT * pts[:, idim]) @@ -876,7 +876,7 @@ def _calcConnectivity(self, nodeTol, edgeTol): # Calculate the 4 corners and 4 midpoints for each surface - coords = numpy.zeros((self.nSurf, 8, 3)) + coords = np.zeros((self.nSurf, 8, 3)) for isurf in range(self.nSurf): beg, mid, end = self.surfs[isurf].getOrigValuesEdge(0) @@ -1045,8 +1045,8 @@ def writeTecplot( labelFilename = dirName + "./" + fileBaseName + ".surf_labels.dat" f2 = open(labelFilename, "w") for isurf in range(self.nSurf): - midu = numpy.floor(self.surfs[isurf].nCtlu / 2) - midv = numpy.floor(self.surfs[isurf].nCtlv / 2) + midu = np.floor(self.surfs[isurf].nCtlu / 2) + midv = np.floor(self.surfs[isurf].nCtlv / 2) textString = 'TEXT CS=GRID3D, X=%f, Y=%f, Z=%f, ZN=%d, \ T="S%d"\n' % ( self.surfs[isurf].coef[midu, midv, 0], @@ -1072,7 +1072,7 @@ def writeTecplot( if nodeLabels: # First we need to figure out where the corners actually *are* nNodes = len(geo_utils.unique(self.topo.nodeLink.flatten())) - nodeCoord = numpy.zeros((nNodes, 3)) + nodeCoord = np.zeros((nNodes, 3)) for i in range(nNodes): # Try to find node i for isurf in range(self.nSurf): @@ -1193,7 +1193,7 @@ def _updateSurfaceCoef(self): def setSurfaceCoef(self): """Set the surface coef list from the pyspline surfaces""" - self.coef = numpy.zeros((self.topo.nGlobal, 3)) + self.coef = np.zeros((self.topo.nGlobal, 3)) for isurf in range(self.nSurf): surf = self.surfs[isurf] for i in range(surf.nCtlu): @@ -1217,7 +1217,7 @@ def getBounds(self, surfs=None): Upper corner of the bounding box """ if surfs is None: - surfs = numpy.arange(self.nSurf) + surfs = np.arange(self.nSurf) Xmin0, Xmax0 = self.surfs[surfs[0]].getBounds() for i in range(1, len(surfs)): @@ -1265,19 +1265,19 @@ def projectCurve(self, curve, surfs=None, *args, **kwargs): """ if surfs is None: - surfs = numpy.arange(self.nSurf) + surfs = np.arange(self.nSurf) - temp = numpy.zeros((len(surfs), 4)) - result = numpy.zeros((len(surfs), 4)) - patchID = numpy.zeros(len(surfs), "intc") + temp = np.zeros((len(surfs), 4)) + result = np.zeros((len(surfs), 4)) + patchID = np.zeros(len(surfs), "intc") for i in range(len(surfs)): isurf = surfs[i] u, v, s, d = self.surfs[isurf].projectCurve(curve, *args, **kwargs) - temp[i, :] = [u, v, s, numpy.linalg.norm(d)] + temp[i, :] = [u, v, s, np.linalg.norm(d)] # Sort the results by distance - index = numpy.argsort(temp[:, 3]) + index = np.argsort(temp[:, 3]) for i in range(len(surfs)): result[i] = temp[index[i]] @@ -1309,29 +1309,29 @@ def projectPoints(self, points, surfs=None, *args, **kwargs): """ if surfs is None: - surfs = numpy.arange(self.nSurf) + surfs = np.arange(self.nSurf) N = len(points) - U = numpy.zeros((N, len(surfs))) - V = numpy.zeros((N, len(surfs))) - D = numpy.zeros((N, len(surfs), 3)) + U = np.zeros((N, len(surfs))) + V = np.zeros((N, len(surfs))) + D = np.zeros((N, len(surfs), 3)) for i in range(len(surfs)): isurf = surfs[i] U[:, i], V[:, i], D[:, i, :] = self.surfs[isurf].projectPoint(points, *args, **kwargs) - u = numpy.zeros(N) - v = numpy.zeros(N) - patchID = numpy.zeros(N, "intc") + u = np.zeros(N) + v = np.zeros(N) + patchID = np.zeros(N, "intc") # Now post-process to get the lowest one for i in range(N): - d0 = numpy.linalg.norm((D[i, 0])) + d0 = np.linalg.norm((D[i, 0])) u[i] = U[i, 0] v[i] = V[i, 0] patchID[i] = surfs[0] for j in range(len(surfs)): - if numpy.linalg.norm(D[i, j]) < d0: - d0 = numpy.linalg.norm(D[i, j]) + if np.linalg.norm(D[i, j]) < d0: + d0 = np.linalg.norm(D[i, j]) u[i] = U[i, j] v[i] = V[i, j] patchID[i] = surfs[j] diff --git a/pygeo/pyNetwork.py b/pygeo/pyNetwork.py index 09787b9f..cd552fdf 100644 --- a/pygeo/pyNetwork.py +++ b/pygeo/pyNetwork.py @@ -2,7 +2,7 @@ # Imports # ====================================================================== import os -import numpy +import numpy as np from pyspline import pySpline from .geo_utils import CurveTopology @@ -33,7 +33,7 @@ def _doConnectivity(self): """ Compute the connectivity of the set of curve objects. """ - coords = numpy.zeros((self.nCurve, 2, 3)) + coords = np.zeros((self.nCurve, 2, 3)) for icurve in range(self.nCurve): coords[icurve][0] = self.curves[icurve](0) coords[icurve][1] = self.curves[icurve](1) @@ -45,7 +45,7 @@ def _doConnectivity(self): sizes.append(self.curves[icurve].nCtl) self.topo.calcGlobalNumbering(sizes) - self.coef = numpy.zeros((self.topo.nGlobal, 3)) + self.coef = np.zeros((self.topo.nGlobal, 3)) for i in range(len(self.coef)): icurve = self.topo.gIndex[i][0][0] ii = self.topo.gIndex[i][0][1] @@ -93,7 +93,7 @@ def writeTecplot(self, fileName, orig=False, curves=True, coef=True, curveLabels labelFilename = dirName + "./" + fileBaseName + ".curve_labels.dat" f2 = open(labelFilename, "w") for icurve in range(self.nCurve): - mid = numpy.floor(self.curves[icurve].nCtl / 2) + mid = np.floor(self.curves[icurve].nCtl / 2) textString = 'TEXT CS=GRID3D, X=%f,Y=%f,Z=%f,ZN=%d,T="S%d"\n' % ( self.curves[icurve].coef[mid, 0], self.curves[icurve].coef[mid, 1], @@ -106,8 +106,8 @@ def writeTecplot(self, fileName, orig=False, curves=True, coef=True, curveLabels if nodeLabels: # First we need to figure out where the corners actually *are* - nNodes = len(numpy.unique(self.topo.nodeLink.flatten())) - nodeCoord = numpy.zeros((nNodes, 3)) + nNodes = len(np.unique(self.topo.nodeLink.flatten())) + nodeCoord = np.zeros((nNodes, 3)) for i in range(nNodes): # Try to find node i for icurve in range(self.nCurve): @@ -166,7 +166,7 @@ def getBounds(self, curves=None): Upper corner of the bounding box """ if curves is None: - curves = numpy.arange(self.nCurve) + curves = np.arange(self.nCurve) Xmin0, Xmax0 = self.curves[curves[0]].getBounds() for i in range(1, len(curves)): @@ -231,24 +231,24 @@ def projectRays(self, points, axis, curves=None, raySize=1.5, **kwargs): # that we know how large to make the line representing the ray. curveID0, s0 = self.projectPoints(points, curves=curves, **kwargs) - D0 = numpy.zeros((len(s0), 3), "d") + D0 = np.zeros((len(s0), 3), "d") for i in range(len(s0)): D0[i, :] = self.curves[curveID0[i]](s0[i]) - points[i] if curves is None: - curves = numpy.arange(self.nCurve) + curves = np.arange(self.nCurve) # Now do the same calc as before N = len(points) - S = numpy.zeros((N, len(curves))) - D = numpy.zeros((N, len(curves), 3)) + S = np.zeros((N, len(curves))) + D = np.zeros((N, len(curves), 3)) for i in range(len(curves)): icurve = curves[i] for j in range(N): ray = pySpline.line( - points[j] - axis * raySize * numpy.linalg.norm(D0[j]), - points[j] + axis * raySize * numpy.linalg.norm(D0[j]), + points[j] - axis * raySize * np.linalg.norm(D0[j]), + points[j] + axis * raySize * np.linalg.norm(D0[j]), ) S[j, i], t, D[j, i, :] = self.curves[icurve].projectCurve(ray, nIter=2000) @@ -260,17 +260,17 @@ def projectRays(self, points, axis, curves=None, raySize=1.5, **kwargs): "enough to intersect the nearest curve.".format(j) ) - s = numpy.zeros(N) - curveID = numpy.zeros(N, "intc") + s = np.zeros(N) + curveID = np.zeros(N, "intc") # Now post-process to get the lowest one for i in range(N): - d0 = numpy.linalg.norm((D[i, 0])) + d0 = np.linalg.norm((D[i, 0])) s[i] = S[i, 0] curveID[i] = curves[0] for j in range(len(curves)): - if numpy.linalg.norm(D[i, j]) < d0: - d0 = numpy.linalg.norm(D[i, j]) + if np.linalg.norm(D[i, j]) < d0: + d0 = np.linalg.norm(D[i, j]) s[i] = S[i, j] curveID[i] = curves[j] @@ -301,26 +301,26 @@ def projectPoints(self, points, curves=None, *args, **kwargs): """ if curves is None: - curves = numpy.arange(self.nCurve) + curves = np.arange(self.nCurve) N = len(points) - S = numpy.zeros((N, len(curves))) - D = numpy.zeros((N, len(curves), 3)) + S = np.zeros((N, len(curves))) + D = np.zeros((N, len(curves), 3)) for i in range(len(curves)): icurve = curves[i] S[:, i], D[:, i, :] = self.curves[icurve].projectPoint(points, *args, **kwargs) - s = numpy.zeros(N) - curveID = numpy.zeros(N, "intc") + s = np.zeros(N) + curveID = np.zeros(N, "intc") # Now post-process to get the lowest one for i in range(N): - d0 = numpy.linalg.norm((D[i, 0])) + d0 = np.linalg.norm((D[i, 0])) s[i] = S[i, 0] curveID[i] = curves[0] for j in range(len(curves)): - if numpy.linalg.norm(D[i, j]) < d0: - d0 = numpy.linalg.norm(D[i, j]) + if np.linalg.norm(D[i, j]) < d0: + d0 = np.linalg.norm(D[i, j]) s[i] = S[i, j] curveID[i] = curves[j] diff --git a/tests/reg_tests/commonUtils.py b/tests/reg_tests/commonUtils.py index aaf24ba2..08c509c4 100644 --- a/tests/reg_tests/commonUtils.py +++ b/tests/reg_tests/commonUtils.py @@ -1,5 +1,5 @@ import os -import numpy +import numpy as np from pygeo import DVGeometry, DVGeometryAxi from pyspline import Curve @@ -134,7 +134,7 @@ def totalSensitivityFD(DVGeo, nPt, ptName, step=1e-1): for key in xDV: baseVar = xDV[key].copy() nDV = len(baseVar) - dIdxFD[key] = numpy.zeros([nPt, nDV]) + dIdxFD[key] = np.zeros([nPt, nDV]) for i in range(nDV): # print('perturbing',key) xDV[key][i] = baseVar[i] + step @@ -159,14 +159,14 @@ def totalSensitivityCS(DVGeo, nPt, ptName): step = 1e-40j for key in xDV: baseVar = xDV[key].copy() - dIdxCS[key] = numpy.zeros([nPt, len(baseVar)]) + dIdxCS[key] = np.zeros([nPt, len(baseVar)]) for i in range(len(baseVar)): xDV[key][i] = baseVar[i] + step DVGeo.setDesignVars(xDV) newPoints = DVGeo.update(ptName) - deriv = numpy.imag(newPoints) / numpy.imag(step) + deriv = np.imag(newPoints) / np.imag(step) dIdxCS[key][:, i] = deriv.flatten() # print 'Deriv',key, i,deriv xDV[key][i] = baseVar[i] @@ -179,7 +179,7 @@ def totalSensitivityCS(DVGeo, nPt, ptName): def testSensitivities(DVGeo, refDeriv, handler, pointset=1): # create test points - points = numpy.zeros([2, 3]) + points = np.zeros([2, 3]) if pointset == 1: points[0, :] = [0.25, 0, 0] points[1, :] = [-0.25, 0, 0] @@ -195,7 +195,7 @@ def testSensitivities(DVGeo, refDeriv, handler, pointset=1): # generate dIdPt nPt = 6 - dIdPt = numpy.zeros([nPt, 2, 3]) + dIdPt = np.zeros([nPt, 2, 3]) dIdPt[0, 0, 0] = 1.0 dIdPt[1, 0, 1] = 1.0 dIdPt[2, 0, 2] = 1.0 @@ -214,7 +214,7 @@ def testSensitivities(DVGeo, refDeriv, handler, pointset=1): def testSensitivitiesD8(DVGeo, refDeriv, handler): # create test points nPoints = 50 - points = numpy.zeros([nPoints, 3]) + points = np.zeros([nPoints, 3]) for i in range(nPoints): nose = 0.01 tail = 34.0 @@ -229,7 +229,7 @@ def testSensitivitiesD8(DVGeo, refDeriv, handler): # generate dIdPt nPt = nPoints * 3 - dIdPt = numpy.zeros([nPt, nPoints, 3]) + dIdPt = np.zeros([nPt, nPoints, 3]) counter = 0 for i in range(nPoints): for j in range(3): diff --git a/tests/reg_tests/test_Blocks.py b/tests/reg_tests/test_Blocks.py index 2b077033..d4a1a1d8 100644 --- a/tests/reg_tests/test_Blocks.py +++ b/tests/reg_tests/test_Blocks.py @@ -1,6 +1,6 @@ import os import unittest -import numpy +import numpy as np from baseclasses import BaseRegTest import commonUtils from pygeo import DVGeometry, geo_utils @@ -19,7 +19,7 @@ def setUp(self): def make_cube_ffd(self, file_name, x0, y0, z0, dx, dy, dz): # Write cube ffd with i along x-axis, j along y-axis, and k along z-axis axes = ["k", "j", "i"] - slices = numpy.array( + slices = np.array( # Slice 1 [ [[[x0, y0, z0], [x0 + dx, y0, z0]], [[x0, y0 + dy, z0], [x0 + dx, y0 + dy, z0]]], @@ -63,7 +63,7 @@ def setup_blocks(self, testID, isComplex=False): small.addChild(tiny) # Add point set - points = numpy.array( + points = np.array( [ [0.5, 0.5, 0.5], [1.25, 1.25, 1.25], @@ -105,8 +105,8 @@ def compute_values(self, DVGeo, handler, refDeriv): handler.root_add_val("jacobian", Jac, rtol=1e-12, atol=1e-12, msg="Check jacobian") # Test that they are equal to eachother - numpy.testing.assert_allclose(Jac, JacCS, rtol=1e-12, atol=1e-12, err_msg="Analytic vs complex-step") - numpy.testing.assert_allclose(Jac, JacFD, rtol=1e-6, atol=1e-6, err_msg="Analytic vs finite difference") + np.testing.assert_allclose(Jac, JacCS, rtol=1e-12, atol=1e-12, err_msg="Analytic vs complex-step") + np.testing.assert_allclose(Jac, JacFD, rtol=1e-6, atol=1e-6, err_msg="Analytic vs finite difference") # Make sure we reset everything DVGeo.setDesignVars(x) @@ -114,9 +114,9 @@ def compute_values(self, DVGeo, handler, refDeriv): # Create dIdPt with one function for each point coordinate Npt = 4 - dIdPt = numpy.zeros([Npt * 3, Npt, 3]) + dIdPt = np.zeros([Npt * 3, Npt, 3]) for i in range(Npt): - dIdPt[i * 3 : (i + 1) * 3, i] = numpy.eye(3) + dIdPt[i * 3 : (i + 1) * 3, i] = np.eye(3) # Test sensitivity dictionaries if refDeriv: @@ -191,8 +191,8 @@ def test_3(self, train=False, refDeriv=False): x = big.getValues() x["rotate_y_small"] = 10 x["rotate_y_tiny"] = -20 - numpy.random.seed(11) - x["sectionlocal_tiny"] = numpy.random.random(*x["sectionlocal_tiny"].shape) + np.random.seed(11) + x["sectionlocal_tiny"] = np.random.random(*x["sectionlocal_tiny"].shape) big.setDesignVars(x) # Compute tests @@ -216,10 +216,10 @@ def test_4(self, train=False, refDeriv=False): # Modify design variables x = big.getValues() - numpy.random.seed(11) - x["translate_big"] = numpy.random.random(3) - x["translate_small"] = numpy.random.random(3) - x["translate_tiny"] = numpy.random.random(3) + np.random.seed(11) + x["translate_big"] = np.random.random(3) + x["translate_small"] = np.random.random(3) + x["translate_tiny"] = np.random.random(3) big.setDesignVars(x) # Compute tests @@ -247,8 +247,8 @@ def test_5(self, train=False, refDeriv=False): # Modify design variables x = big.getValues() - numpy.random.seed(11) - x["translate_big"] = numpy.random.random(3) + np.random.seed(11) + x["translate_big"] = np.random.random(3) x["rotate_y_small"] = 45 x["rotate_y_tiny"] = -45 big.setDesignVars(x) @@ -259,9 +259,9 @@ def test_5(self, train=False, refDeriv=False): # Create dIdPt with one function for each point coordinate Npt = 4 - dIdPt = numpy.zeros([Npt * 3, Npt, 3]) + dIdPt = np.zeros([Npt * 3, Npt, 3]) for i in range(Npt): - dIdPt[i * 3 : (i + 1) * 3, i] = numpy.eye(3) + dIdPt[i * 3 : (i + 1) * 3, i] = np.eye(3) # Test sensitivity dictionaries if refDeriv: diff --git a/tests/reg_tests/test_Cylinder.py b/tests/reg_tests/test_Cylinder.py index 208a9384..807dda8f 100644 --- a/tests/reg_tests/test_Cylinder.py +++ b/tests/reg_tests/test_Cylinder.py @@ -1,6 +1,6 @@ import os import unittest -import numpy +import numpy as np from baseclasses import BaseRegTest from pygeo import DVGeometry, DVConstraints, geo_utils @@ -20,16 +20,16 @@ def make_cylinder_mesh(self, radius=1.0, height=2.0): Nextrude = 100 Npts = Nazimuth * Nextrude - theta = numpy.linspace(0, 2 * numpy.pi, Nazimuth) - z = numpy.linspace(0, height, Nextrude) + theta = np.linspace(0, 2 * np.pi, Nazimuth) + z = np.linspace(0, height, Nextrude) - pts = numpy.zeros((Npts, 3)) + pts = np.zeros((Npts, 3)) # First populate the points for i in range(Nextrude): for j in range(Nazimuth): - x = radius * numpy.cos(theta[j]) - y = radius * numpy.sin(theta[j]) + x = radius * np.cos(theta[j]) + y = radius * np.sin(theta[j]) k = i * Nazimuth + j pts[k] = [x, y, z[i]] @@ -59,9 +59,9 @@ def make_cylinder_mesh(self, radius=1.0, height=2.0): v1.append(pC - pA) v2.append(pD - pA) - p0 = numpy.vstack(p0) - v1 = numpy.vstack(v1) - v2 = numpy.vstack(v2) + p0 = np.vstack(p0) + v1 = np.vstack(v1) + v2 = np.vstack(v2) return [p0, v1, v2] @@ -71,7 +71,7 @@ def make_ffd(self, file_name, radius=1.0, height=2.0): r = radius h = height dh = 0.01 - slices = numpy.array( + slices = np.array( [ # Slice 1 [[[-r, -r, -dh], [r, -r, -dh]], [[-r, r, -dh], [r, r, -dh]]], @@ -174,8 +174,8 @@ def test_spanwise_dvs(self, train=False, refDeriv=False): print(funcs) handler.root_add_dict("funcs1", funcs, rtol=1e-6, atol=1e-6) - numpy.random.seed(0) - DVGeo.setDesignVars({"shape": (numpy.random.rand(size) - 0.5)}) + np.random.seed(0) + DVGeo.setDesignVars({"shape": (np.random.rand(size) - 0.5)}) funcs = {} DVCon.evalFunctions(funcs) diff --git a/tests/reg_tests/test_DVGeometry.py b/tests/reg_tests/test_DVGeometry.py index cfe2135c..564f49ce 100644 --- a/tests/reg_tests/test_DVGeometry.py +++ b/tests/reg_tests/test_DVGeometry.py @@ -1,6 +1,6 @@ import os import unittest -import numpy +import numpy as np from baseclasses import BaseRegTest import commonUtils from pygeo import geo_utils, DVGeometry, DVConstraints @@ -394,8 +394,8 @@ def test_12(self, train=False, refDeriv=False): handler.root_print("Test 12b: D8 FFD, random DV perturbation on test 10") xDV = DVGeo.getValues() for key in xDV: - numpy.random.seed(42) - xDV[key] += numpy.random.rand(len(xDV[key])) + np.random.seed(42) + xDV[key] += np.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) @@ -426,8 +426,8 @@ def test_13(self, train=False, refDeriv=False): xDV = DVGeo.getValues() for key in xDV: - numpy.random.seed(42) - xDV[key] += numpy.random.rand(len(xDV[key])) + np.random.seed(42) + xDV[key] += np.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) @@ -459,8 +459,8 @@ def test_14(self, train=False, refDeriv=False): handler.root_print("Test 14b: D8 + Nozzle FFD, random DV perturbation on test 12") xDV = DVGeo.getValues() for key in xDV: - numpy.random.seed(42) - xDV[key] += numpy.random.rand(len(xDV[key])) + np.random.seed(42) + xDV[key] += np.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) @@ -497,8 +497,8 @@ def test_15(self, train=False, refDeriv=False): handler.root_print("Test 15b: D8 + Nozzle FFD, random DV perturbation on test 13") xDV = DVGeo.getValues() for key in xDV: - numpy.random.seed(42) - xDV[key] += numpy.random.rand(len(xDV[key])) + np.random.seed(42) + xDV[key] += np.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) @@ -538,8 +538,8 @@ def test_16(self, train=False, refDeriv=False): handler.root_print("Test 14b: D8 + Nozzle FFD, random DV perturbation on test 14") xDV = DVGeo.getValues() for key in xDV: - numpy.random.seed(42) - xDV[key] += numpy.random.rand(len(xDV[key])) + np.random.seed(42) + xDV[key] += np.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) @@ -572,8 +572,8 @@ def test_17(self, train=False, refDeriv=False): handler.root_print("Test 17b: D8 + Nozzle FFD, random DV perturbationon test 15") xDV = DVGeo.getValues() for key in xDV: - numpy.random.seed(42) - xDV[key] += numpy.random.rand(len(xDV[key])) + np.random.seed(42) + xDV[key] += np.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) @@ -607,8 +607,8 @@ def test_18(self, train=False, refDeriv=False): handler.root_print("Test 18b: D8 + Nozzle FFD, random DV perturbationon test 16") xDV = DVGeo.getValues() for key in xDV: - numpy.random.seed(42) - xDV[key] += numpy.random.rand(len(xDV[key])) + np.random.seed(42) + xDV[key] += np.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) @@ -645,8 +645,8 @@ def test_19(self, train=False, refDeriv=False): handler.root_print("Test 19b: D8 + Nozzle FFD, random DV perturbationon test 17") xDV = DVGeo.getValues() for key in xDV: - numpy.random.seed(42) - xDV[key] += numpy.random.rand(len(xDV[key])) + np.random.seed(42) + xDV[key] += np.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) @@ -683,8 +683,8 @@ def test_20(self, train=False, refDeriv=False): handler.root_print("Test 20b: D8 + Nozzle FFD, random DV perturbationon test 18") xDV = DVGeo.getValues() for key in xDV: - numpy.random.seed(42) - xDV[key] += numpy.random.rand(len(xDV[key])) + np.random.seed(42) + xDV[key] += np.random.rand(len(xDV[key])) DVGeo.setDesignVars(xDV) commonUtils.testSensitivitiesD8(DVGeo, refDeriv, handler) @@ -703,14 +703,14 @@ def test_21(self, train=False, refDeriv=False): # Test with a single point along the 45 ` degree theta direction DVGeo = commonUtils.setupDVGeoAxi(self.base_path) - DVGeo.addGeoDVGlobal("mainAxis", numpy.zeros(1), commonUtils.mainAxisPointAxi) + DVGeo.addGeoDVGlobal("mainAxis", np.zeros(1), commonUtils.mainAxisPointAxi) DVGeo.addGeoDVLocal("x_axis", lower=-2, upper=2, axis="x") DVGeo.addGeoDVLocal("z_axis", lower=-2, upper=2, axis="z") DVGeo.addGeoDVLocal("y_axis", lower=-2, upper=2, axis="y") ptName = "point" - s_pts = numpy.array( + s_pts = np.array( [ [0, 0.5, 0.5], ], @@ -720,7 +720,7 @@ def test_21(self, train=False, refDeriv=False): # generate dIdPt nPt = 3 - dIdPt = numpy.zeros([nPt, 1, 3]) + dIdPt = np.zeros([nPt, 1, 3]) dIdPt[0, 0, 0] = 1.0 dIdPt[1, 0, 1] = 1.0 dIdPt[2, 0, 2] = 1.0 @@ -751,7 +751,7 @@ def test_22(self, train=False, refDeriv=False): # Write duplicate of outerbox FFD axes = ["i", "k", "j"] - slices = numpy.array( + slices = np.array( [ # Slice 1 [[[-1, -1, -1], [-1, 1, -1]], [[-1, -1, 1], [-1, 1, 1]]], @@ -772,7 +772,7 @@ def test_22(self, train=False, refDeriv=False): # Load original and duplicate origFFD = DVGeometry(os.path.join(self.base_path, "../inputFiles/outerBoxFFD.xyz")) copyFFD = DVGeometry(copyName) - norm_diff = numpy.linalg.norm(origFFD.FFD.coef - copyFFD.FFD.coef) + norm_diff = np.linalg.norm(origFFD.FFD.coef - copyFFD.FFD.coef) handler.par_add_norm("norm", norm_diff, rtol=1e-7, atol=1e-7) os.remove(copyName) @@ -813,8 +813,8 @@ def test_spanwise_dvs(self, train=False, refDeriv=False): size = DVGeo._getNDVSpanwiseLocal() - numpy.random.seed(0) - DVGeo.setDesignVars({"shape": (numpy.random.rand(size) - 0.5)}) + np.random.seed(0) + DVGeo.setDesignVars({"shape": (np.random.rand(size) - 0.5)}) funcs = {} DVCon.evalFunctions(funcs) @@ -822,7 +822,7 @@ def test_spanwise_dvs(self, train=False, refDeriv=False): for i in range(nChord): for j in range(nSpan - 1): - numpy.testing.assert_allclose(funcs[name][i * nChord + j + 1], funcs[name][i * nChord + j], rtol=2e-15) + np.testing.assert_allclose(funcs[name][i * nChord + j + 1], funcs[name][i * nChord + j], rtol=2e-15) def train_23_xyzFraction(self, train=True): self.test_23_xyzFraction(train=train) diff --git a/tests/reg_tests/test_DVGeometryVSP.py b/tests/reg_tests/test_DVGeometryVSP.py index a04f6acd..fdd97438 100644 --- a/tests/reg_tests/test_DVGeometryVSP.py +++ b/tests/reg_tests/test_DVGeometryVSP.py @@ -1,6 +1,6 @@ import os import unittest -import numpy +import numpy as np from baseclasses import BaseRegTest from parameterized import parameterized_class from mpi4py import MPI @@ -47,10 +47,10 @@ def test_1(self, train=False, refDeriv=False): def sample_uv(nu, nv): # function to create sample uv from the surface and save these points. - u = numpy.linspace(0, 1, nu) - v = numpy.linspace(0, 1, nv) - uu, vv = numpy.meshgrid(u, v) - uv = numpy.array((uu.flatten(), vv.flatten())) + u = np.linspace(0, 1, nu) + v = np.linspace(0, 1, nv) + uu, vv = np.meshgrid(u, v) + uv = np.array((uu.flatten(), vv.flatten())) return uv refFile = os.path.join(self.base_path, "ref/test_DVGeometryVSP_01.ref") @@ -80,7 +80,7 @@ def sample_uv(nu, nv): [1.0, 0.0, 1.0], [1.0, 0.0, -1.0], ] - pointSet1 = numpy.array(points) + pointSet1 = np.array(points) nPts = len(points) dMax_global = DVGeo.addPointSet(pointSet1, "known_points") handler.assert_allclose(dMax_global, 0.0, name="pointset1_projection_tol", rtol=1e0, atol=1e-10) @@ -102,8 +102,8 @@ def sample_uv(nu, nv): points.append([pt.x(), pt.y(), pt.z()]) radius = ((pt.x() - 1.0) ** 2 + pt.y() ** 2 + pt.z() ** 2) ** 0.5 radii.append(radius) - pointSet2 = numpy.array(points) - handler.assert_allclose(numpy.array(radii), 1.0, name="pointset2_diff_from_sphere", rtol=1e-3, atol=1e-3) + pointSet2 = np.array(points) + handler.assert_allclose(np.array(radii), 1.0, name="pointset2_diff_from_sphere", rtol=1e-3, atol=1e-3) dim = 3 # add this point set since our points EXACTLY lie on the sphere, we should get 0 distance in the @@ -114,7 +114,7 @@ def sample_uv(nu, nv): # lets get the gradients wrt design variables. For this we can define our dummy jacobian for dIdpt # that is an (N, nPts, 3) array. We will just monitor how each component in each point changes so # we will need nDV*dim*nPts functions of interest. - dIdpt = numpy.zeros((nPts * dim, nPts, dim)) + dIdpt = np.zeros((nPts * dim, nPts, dim)) # first 3*nDV entries will correspond to the first point's x,y,z direction for i in range(nPts): @@ -158,11 +158,11 @@ def test_2(self, train=False, refDeriv=False): def sample_uv(nu, nv): # function to create sample uv from the surface and save these points. - u = numpy.linspace(0, 1, nu + 1) - v = numpy.linspace(0, 1, nv + 1) - uu, vv = numpy.meshgrid(u, v) + u = np.linspace(0, 1, nu + 1) + v = np.linspace(0, 1, nv + 1) + uu, vv = np.meshgrid(u, v) # print (uu.flatten(), vv.flatten()) - uv = numpy.array((uu.flatten(), vv.flatten())) + uv = np.array((uu.flatten(), vv.flatten())) return uv refFile = os.path.join(self.base_path, "ref/test_DVGeometryVSP_02.ref") @@ -215,7 +215,7 @@ def sample_uv(nu, nv): nuv += 1 # allocate the uv array on this proc - uv = numpy.zeros((2, nuv)) + uv = np.zeros((2, nuv)) # print how mant points we have MPI.COMM_WORLD.Barrier() @@ -231,7 +231,7 @@ def sample_uv(nu, nv): nNodes = len(uv[0, :]) # extract node coordinates and save them in a numpy array - coor = numpy.zeros((nNodes, 3)) + coor = np.zeros((nNodes, 3)) for i in range(nNodes): pnt = openvsp.CompPnt01(geoms[0], 0, uv[0, i], uv[1, i]) coor[i, :] = (pnt.x(), pnt.y(), pnt.z()) @@ -240,7 +240,7 @@ def sample_uv(nu, nv): DVGeo.addPointSet(coor, "test_points") # We will have nNodes*3 many functions of interest... - dIdpt = numpy.zeros((nNodes * 3, nNodes, 3)) + dIdpt = np.zeros((nNodes * 3, nNodes, 3)) # set the seeds to one in the following fashion: # first function of interest gets the first coordinate of the first point @@ -279,11 +279,11 @@ def sample_uv(nu, nv): # this issue does not come up if this tests is ran with a single proc biggest_deriv = 1e-16 for x in DVs: - err = numpy.array(funcSens[x].squeeze()) - numpy.array(funcSensFD[x]) - maxderiv = numpy.max(numpy.abs(funcSens[x].squeeze())) - normalizer = numpy.median(numpy.abs(funcSensFD[x].squeeze())) - if numpy.abs(normalizer) < 1: - normalizer = numpy.ones(1) + err = np.array(funcSens[x].squeeze()) - np.array(funcSensFD[x]) + maxderiv = np.max(np.abs(funcSens[x].squeeze())) + normalizer = np.median(np.abs(funcSensFD[x].squeeze())) + if np.abs(normalizer) < 1: + normalizer = np.ones(1) normalized_error = err / normalizer if maxderiv > biggest_deriv: biggest_deriv = maxderiv diff --git a/tests/reg_tests/warning_childFFD.py b/tests/reg_tests/warning_childFFD.py index 002f4b78..ea6834fe 100644 --- a/tests/reg_tests/warning_childFFD.py +++ b/tests/reg_tests/warning_childFFD.py @@ -1,5 +1,5 @@ import unittest -import numpy +import numpy as np from pygeo import DVGeometry, geo_utils from test_Blocks import add_vars @@ -11,7 +11,7 @@ class RegTestPyGeo(unittest.TestCase): def make_cube_ffd(self, file_name, x0, y0, z0, dx, dy, dz): # Write cube ffd with i along x-axis, j along y-axis, and k along z-axis axes = ["k", "j", "i"] - slices = numpy.array( + slices = np.array( # Slice 1 [ [[[x0, y0, z0], [x0 + dx, y0, z0]], [[x0, y0 + dy, z0], [x0 + dx, y0 + dy, z0]]], @@ -41,7 +41,7 @@ def test_parent_shape_child_rot(self, train=False, refDeriv=False): dz = 1.0 axes = ["k", "j", "i"] - slices = numpy.array( + slices = np.array( # Slice 1 [ [ @@ -68,7 +68,7 @@ def test_parent_shape_child_rot(self, train=False, refDeriv=False): big.addChild(small) # Add point set - points = numpy.array([[0.5, 0.5, 0.5]]) + points = np.array([[0.5, 0.5, 0.5]]) big.addPointSet(points, "X") # Add only translation variables @@ -76,13 +76,13 @@ def test_parent_shape_child_rot(self, train=False, refDeriv=False): add_vars(small, "small", rotate="y") ang = 45 - ang_r = numpy.deg2rad(ang) + ang_r = np.deg2rad(ang) # Modify design variables x = big.getValues() # add a local shape change - x["local_z_big"] = numpy.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.5]) + x["local_z_big"] = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.5]) big.setDesignVars(x) Xs = big.update("X") @@ -93,12 +93,12 @@ def test_parent_shape_child_rot(self, train=False, refDeriv=False): # the modification caused by the child FFD should be the same as rotating the deformed point of the parent # (you would think) - rot_mat = numpy.array( - [[numpy.cos(ang_r), 0, numpy.sin(ang_r)], [0, 1, 0], [-numpy.sin(ang_r), 0, numpy.cos(ang_r)]] + rot_mat = np.array( + [[np.cos(ang_r), 0, np.sin(ang_r)], [0, 1, 0], [-np.sin(ang_r), 0, np.cos(ang_r)]] ) - Xrot = numpy.dot(rot_mat, (Xs - points).T) + points.T + Xrot = np.dot(rot_mat, (Xs - points).T) + points.T - numpy.testing.assert_array_almost_equal(Xrot_ffd.T, Xrot) + np.testing.assert_array_almost_equal(Xrot_ffd.T, Xrot) if __name__ == "__main__": From 3401e2253f2ade510f6d0577b7fc2edbe11fde8f Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Wed, 31 Mar 2021 10:50:22 -0400 Subject: [PATCH 14/18] another minor reformat --- pygeo/DVGeometry.py | 8 ++------ tests/reg_tests/warning_childFFD.py | 4 +--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/pygeo/DVGeometry.py b/pygeo/DVGeometry.py index 58b562b1..aef59602 100644 --- a/pygeo/DVGeometry.py +++ b/pygeo/DVGeometry.py @@ -157,9 +157,7 @@ def __init__(self, fileName, complex=False, child=False, faceFreeze=None, name=N coefMask = [] for iVol in range(self.FFD.nVol): coefMask.append( - np.zeros( - (self.FFD.vols[iVol].nCtlu, self.FFD.vols[iVol].nCtlv, self.FFD.vols[iVol].nCtlw), dtype=bool - ) + np.zeros((self.FFD.vols[iVol].nCtlu, self.FFD.vols[iVol].nCtlv, self.FFD.vols[iVol].nCtlw), dtype=bool) ) # Now do the faceFreeze if faceFreeze is not None: @@ -1552,9 +1550,7 @@ def updateCalculations(self, new_pts, isComplex, config): slVar = self.DV_listSectionLocal[varname] attachedPoint = self.ptAttachInd[ipt] W = slVar.sectionTransform[slVar.sectionLink[attachedPoint]][:, 2] - D = geo_utils.rotVbyW( - D, W, np.pi / 180 * self.rot_theta[self.curveIDNames[ipt]](self.links_s[ipt]) - ) + D = geo_utils.rotVbyW(D, W, np.pi / 180 * self.rot_theta[self.curveIDNames[ipt]](self.links_s[ipt])) D[0] *= scale_x D[1] *= scale_y diff --git a/tests/reg_tests/warning_childFFD.py b/tests/reg_tests/warning_childFFD.py index ea6834fe..2fadeeb9 100644 --- a/tests/reg_tests/warning_childFFD.py +++ b/tests/reg_tests/warning_childFFD.py @@ -93,9 +93,7 @@ def test_parent_shape_child_rot(self, train=False, refDeriv=False): # the modification caused by the child FFD should be the same as rotating the deformed point of the parent # (you would think) - rot_mat = np.array( - [[np.cos(ang_r), 0, np.sin(ang_r)], [0, 1, 0], [-np.sin(ang_r), 0, np.cos(ang_r)]] - ) + rot_mat = np.array([[np.cos(ang_r), 0, np.sin(ang_r)], [0, 1, 0], [-np.sin(ang_r), 0, np.cos(ang_r)]]) Xrot = np.dot(rot_mat, (Xs - points).T) + points.T np.testing.assert_array_almost_equal(Xrot_ffd.T, Xrot) From b9409629c5ddcf51847d75fc521d9a46a69801c2 Mon Sep 17 00:00:00 2001 From: Neil Wu <602725+nwu63@users.noreply.github.com> Date: Wed, 31 Mar 2021 22:28:41 -0400 Subject: [PATCH 15/18] added back the CompVecPnt01 call --- tests/reg_tests/test_DVGeometryVSP.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/reg_tests/test_DVGeometryVSP.py b/tests/reg_tests/test_DVGeometryVSP.py index fdd97438..d111678a 100644 --- a/tests/reg_tests/test_DVGeometryVSP.py +++ b/tests/reg_tests/test_DVGeometryVSP.py @@ -229,6 +229,7 @@ def sample_uv(nu, nv): # get the coordinates nNodes = len(uv[0, :]) + openvsp.CompVecPnt01(geoms[0], 0, uv[0, :], uv[1, :]) # extract node coordinates and save them in a numpy array coor = np.zeros((nNodes, 3)) From 0d245c179ece4f3ed7792102870b5817654af26a Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Thu, 1 Apr 2021 09:45:36 -0400 Subject: [PATCH 16/18] skip parallel test 2 for VSP --- tests/reg_tests/test_DVGeometryVSP.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/reg_tests/test_DVGeometryVSP.py b/tests/reg_tests/test_DVGeometryVSP.py index d111678a..5fdcc487 100644 --- a/tests/reg_tests/test_DVGeometryVSP.py +++ b/tests/reg_tests/test_DVGeometryVSP.py @@ -155,6 +155,9 @@ def test_2(self, train=False, refDeriv=False): """ Test 2: OpenVSP wing test """ + # we skip parallel tests for now + if not train and self.N_PROCS > 1: + return def sample_uv(nu, nv): # function to create sample uv from the surface and save these points. From 0faf9e785f9787039ff0bb61487ee48f92a12b98 Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Thu, 1 Apr 2021 10:02:59 -0400 Subject: [PATCH 17/18] switched to skiptest rather than pass --- tests/reg_tests/test_DVGeometryVSP.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/reg_tests/test_DVGeometryVSP.py b/tests/reg_tests/test_DVGeometryVSP.py index 5fdcc487..234975df 100644 --- a/tests/reg_tests/test_DVGeometryVSP.py +++ b/tests/reg_tests/test_DVGeometryVSP.py @@ -157,7 +157,7 @@ def test_2(self, train=False, refDeriv=False): """ # we skip parallel tests for now if not train and self.N_PROCS > 1: - return + self.skipTest("Skipping the parallel test for now.") def sample_uv(nu, nv): # function to create sample uv from the surface and save these points. From 8820eb9f3422db50dc254e4db609f6ddea6dbfeb Mon Sep 17 00:00:00 2001 From: Neil Wu Date: Fri, 2 Apr 2021 13:38:36 -0400 Subject: [PATCH 18/18] bugfix and added numpy name change to git revs ignore file --- .git-blame-ignore-revs | 1 + pygeo/DVConstraints.py | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 8687c926..cae8806b 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1 +1,2 @@ 8ebf48deefbee52560197721d02d7f2cc8408c15 +b192604451ac9427ddccfc2ca24a6796a22e4cc1 diff --git a/pygeo/DVConstraints.py b/pygeo/DVConstraints.py index 810612f7..6f8d6fa7 100644 --- a/pygeo/DVConstraints.py +++ b/pygeo/DVConstraints.py @@ -514,8 +514,6 @@ def writeSurfaceSTL(self, fileName, surfaceName="default", fromDVGeo=None): fromDVGeo : str or None Name of the DVGeo object to obtain the surface from (default is 'None') """ - import np as np - try: from stl import mesh except ImportError: