Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

BladeStiffenedShellConstitutive and documentation improvements #226

Merged
merged 13 commits into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
unit_test_and_docs:
# Run on Ubuntu
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 40
# Necessary to prevent mpi tests failing due to lack of slots
env:
OMPI_MCA_btl: self,tcp
Expand Down
4 changes: 2 additions & 2 deletions docs/source/pytacs/buckling.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
BucklingProblem
------------
---------------
.. automodule:: tacs.problems.buckling

Options
Expand All @@ -16,4 +16,4 @@ API Reference
^^^^^^^^^^^^^
.. autoclass:: tacs.problems.BucklingProblem
:members:
:inherited-members:
:inherited-members:
8 changes: 4 additions & 4 deletions src/constitutive/TACSBladeStiffenedShellConstitutive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ TACSBladeStiffenedShellConstitutive::TACSBladeStiffenedShellConstitutive(
this->numDesignVars++;
this->numPanelDV++;
}
this->panelPlyFracLowerBounds[ii] = 0.1;
this->panelPlyFracUpperBounds[ii] = 0.9;
this->panelPlyFracLowerBounds[ii] = 0.0;
this->panelPlyFracUpperBounds[ii] = 1.0;
}

// --- Stiffener DVs ---
Expand Down Expand Up @@ -154,8 +154,8 @@ TACSBladeStiffenedShellConstitutive::TACSBladeStiffenedShellConstitutive(
this->numDesignVars++;
this->numStiffenerDV++;
}
this->stiffenerPlyFracLowerBounds[ii] = 0.1;
this->stiffenerPlyFracUpperBounds[ii] = 0.9;
this->stiffenerPlyFracLowerBounds[ii] = 0.0;
this->stiffenerPlyFracUpperBounds[ii] = 1.0;
}

// --- Stiffener flange fraction ---
Expand Down
10 changes: 10 additions & 0 deletions src/constitutive/TACSBladeStiffenedShellConstitutive.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,16 @@ class TACSBladeStiffenedShellConstitutive : public TACSShellConstitutive {
int getDesignVarRange(int elemIndex, int dvLen, TacsScalar lb[],
TacsScalar ub[]);

/**
* @brief Get the number of panel plies
*/
int getNumPanelPlies() { return this->numPanelPlies; }

/**
* @brief Get the number of stiffener plies
*/
int getNumStiffenerPlies() { return this->numStiffenerPlies; }

// ==============================================================================
// Evaluate mass properties
// ==============================================================================
Expand Down
2 changes: 2 additions & 0 deletions tacs/constitutive.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ cdef extern from "TACSBladeStiffenedShellConstitutive.h":
int[], # stiffenerPlyFracNums
TacsScalar # flangeFraction
)
int getNumPanelPlies()
int getNumStiffenerPlies()
void setKSWeight(double ksWeight)
void setStiffenerPitchBounds(TacsScalar lowerBound, TacsScalar upperBound)
void setStiffenerHeightBounds(TacsScalar lowerBound, TacsScalar upperBound)
Expand Down
203 changes: 173 additions & 30 deletions tacs/constitutive.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -764,10 +764,89 @@ cdef class CompositeShellConstitutive(ShellConstitutive):

self.props = [prop.getMaterialProperties() for prop in ply_list]

def generateBDFCard(self):
"""
Generate pyNASTRAN card class based on current design variable values.

Returns:
card (pyNastran.bdf.cards.properties.shell.PCOMP): pyNastran card holding property information
"""
num_plies = len(self.props)
cdef TACSCompositeShellConstitutive* comp_ptr = <TACSCompositeShellConstitutive*>self.cptr
cdef np.ndarray ply_thicknesses = np.zeros(num_plies, dtype)
cdef np.ndarray ply_angles = np.zeros(num_plies, dtype)

comp_ptr.getPlyThicknesses(<TacsScalar*>ply_thicknesses.data)
comp_ptr.getPlyAngles(<TacsScalar*>ply_angles.data)

mat_ids = []
for i in range(num_plies):
ply_id = self.props[i].getNastranID()
mat_ids.append(ply_id)

prop = nastran_cards.properties.shell.PCOMP(self.nastranID, mat_ids,
ply_thicknesses.astype(float),
np.rad2deg(ply_angles, dtype=float))
return prop

cdef class BladeStiffenedShellConstitutive(ShellConstitutive):
"""This constitutive class models a shell stiffened with T-shaped stiffeners.
The stiffeners are not explicitly modelled.
Instead, their stiffness is "smeared" across the shell.

Parameters
----------
panelPly : tacs.constitutive.OrthotropicPly
Ply model to use for the panel
stiffenerPly : tacs.constitutive.OrthotropicPly
Ply model to use for the stiffener
kcorr : float or complex
Shear correction factor, usually 5.0/6.0
panelLength : float or complex
Panel length DV value
panelLengthNum : int
Panel lenth DV number, passing a negative value tells TACS not to treat this as a DV
stiffenerPitch : float or complex
Stiffener pitch DV value
stiffenerPitchNum : int
DV number, passing a negative value tells TACS not to treat this as a DV
panelThick : float or complex
Panel thickness DV value
panelThickNum : int
DV number, passing a negative value tells TACS not to treat this as a DV
numPanelPlies : int
Number of distinct ply angles in the panel
panelPlyAngles : numpy.ndarray[float or complex]
Array of ply angles in the panel
panelPlyFracs : numpy.ndarray[float or complex]
Array of ply fractions in the panel
panelPlyFracNums : numpy.ndarray[np.intc]
Array of ply fraction DV numbers in the panel, passing negative values tells TACS not to treat that ply fraction as a DV
stiffenerHeight : float or complex
Stiffener height DV value
stiffenerHeightNum : int
DV number, passing a negative value tells TACS not to treat this as a DV
stiffenerThick : float or complex
Stiffener thickness DV value
stiffenerThickNum : int
DV number, passing a negative value tells TACS not to treat this as a DV
numStiffenerPlies : int
Number of distinct ply angles in the stiffener
stiffenerPlyAngles : numpy.ndarray[float or complex]
Array of ply angles for the stiffener
stiffenerPlyFracs : numpy.ndarray[float or complex]
Array of ply fractions for the stiffener
stiffenerPlyFracNums : numpy.ndarray[numpy.intc]
Array of ply fraction DV numbers for the stiffener, passing negative values tells TACS not to treat that ply fraction as a DV
flangeFraction : float, optional
Ratio of the stiffener base width to the stiffener height, by default 1.0

Raises
------
ValueError
Raises error if panelPlyAngles, panelPlyFracs, or panelPlyFracNums do not have numPanelPlies entries
ValueError
Raises error if stiffenerPlyAngles, stiffenerPlyFracs, or stiffenerPlyFracNums do not have numStiffenerPlies entries
"""
def __cinit__(
self,
Expand Down Expand Up @@ -797,19 +876,22 @@ cdef class BladeStiffenedShellConstitutive(ShellConstitutive):

if len(panelPlyAngles) != numPanelPlies:
raise ValueError('panelPlyAngles must have length numPanelPlies')
if len(panelPlyAngles) != numPanelPlies:
raise ValueError('panelPlyNums must have length numPanelPlies')
if len(panelPlyFracs) != numPanelPlies:
raise ValueError('panelPlyFracs must have length numPanelPlies')
if len(panelPlyFracNums) != numPanelPlies:
raise ValueError('panelPlyFracNums must have length numPanelPlies')
if len(stiffenerPlyAngles) != numStiffenerPlies:
raise ValueError('stiffenerPlyAngles must have length numStiffenerPlies')
if len(stiffenerPlyAngles) != numStiffenerPlies:
raise ValueError('stiffenerPlyNums must have length numStiffenerPlies')
if len(stiffenerPlyFracs) != numStiffenerPlies:
raise ValueError('stiffenerPlyFracs must have length numStiffenerPlies')
if len(stiffenerPlyFracNums) != numStiffenerPlies:
raise ValueError('stiffenerPlyFracNums must have length numStiffenerPlies')

# Numpy's default int type is int64, but this is interpreted by Cython as a long.
if panelPlyFracNums.dtype != np.intc:
panelPlyFracNums = panelPlyFracNums.astype(np.intc)
if stiffenerPlyFracNums.dtype != np.intc:
stiffenerPlyFracNums = stiffenerPlyFracNums.astype(np.intc)
# raise ValueError('panelPlyFracNums must be of type int32')

self.blade_ptr = new TACSBladeStiffenedShellConstitutive(
panelPly.ptr,
Expand Down Expand Up @@ -842,27 +924,73 @@ cdef class BladeStiffenedShellConstitutive(ShellConstitutive):
"""
Update the ks weight used for aggregating the different failure modes

Args:
ksWeight (float): KS weight
Parameters
----------
ksWeight : float
KS aggregation weight
"""
if self.blade_ptr:
self.blade_ptr.setKSWeight(ksWeight)

def setStiffenerPitchBounds(self, TacsScalar lowerBound, TacsScalar upperBound):
"""Set the lower and upper bounds for the stiffener pitch design variable

The default bounds are 1e-3 and 1e20

Parameters
----------
lowerBound : float or complex
Lower bound
upperBound : float or complex
Upper bound
"""
if self.blade_ptr:
self.blade_ptr.setStiffenerPitchBounds(lowerBound, upperBound)

def setStiffenerHeightBounds(self, TacsScalar lowerBound, TacsScalar upperBound):
"""Set the lower and upper bounds for the stiffener height design variable

The default bounds are 1e-3 and 1e20

Parameters
----------
lowerBound : float or complex
Lower bound
upperBound : float or complex
Upper bound
"""

if self.blade_ptr:
self.blade_ptr.setStiffenerHeightBounds(lowerBound, upperBound)

def setStiffenerThicknessBounds(self, TacsScalar lowerBound, TacsScalar upperBound):
"""Set the lower and upper bounds for the stiffener thickness design variable

The default bounds are 1e-4 and 1e20

Parameters
----------
lowerBound : float or complex
Lower bound
upperBound : float or complex
Upper bound
"""

if self.blade_ptr:
self.blade_ptr.setStiffenerThicknessBounds(lowerBound, upperBound)

def setPanelThicknessBounds(self, TacsScalar lowerBound, TacsScalar upperBound):
"""Set the lower and upper bounds for the panel thickness design variable

The default bounds are 1e-4 and 1e20

Parameters
----------
lowerBound : float or complex
Lower bound
upperBound : float or complex
Upper bound
"""

if self.blade_ptr:
self.blade_ptr.setPanelThicknessBounds(lowerBound, upperBound)
Expand All @@ -872,43 +1000,58 @@ cdef class BladeStiffenedShellConstitutive(ShellConstitutive):
np.ndarray[TacsScalar, ndim=1, mode='c'] lowerBound,
np.ndarray[TacsScalar, ndim=1, mode='c'] upperBound
):
"""Set the lower and upper bounds for the stiffener ply fraction design variables

The default bounds are 0 and 1

Parameters
----------
lowerBound : numpy.ndarray[float or complex]
Lower bound
upperBound : numpy.ndarray[float or complex]
Upper bounds

Raises
------
ValueError
Raises error if the length of lowerBound or upperBound is not equal to the number of stiffener plies
"""

if self.blade_ptr:
if len(lowerBound) != self.blade_ptr.getNumStiffenerPlies():
raise ValueError('lowerBound must have length numStiffenerPlies')
if len(upperBound) != self.blade_ptr.getNumStiffenerPlies():
raise ValueError('upperBound must have length numStiffenerPlies')
self.blade_ptr.setStiffenerPlyFractionBounds(<TacsScalar*>lowerBound.data, <TacsScalar*>upperBound.data)

def setPanelPlyFractionBounds(
self,
np.ndarray[TacsScalar, ndim=1, mode='c'] lowerBound,
np.ndarray[TacsScalar, ndim=1, mode='c'] upperBound
):
"""Set the lower and upper bounds for the panel ply fraction design variables

if self.blade_ptr:
self.blade_ptr.setPanelPlyFractionBounds(<TacsScalar*>lowerBound.data, <TacsScalar*>upperBound.data)
The default bounds are 0 and 1

def generateBDFCard(self):
"""
Generate pyNASTRAN card class based on current design variable values.
Parameters
----------
lowerBound : numpy.ndarray[float or complex]
Lower bound
upperBound : numpy.ndarray[float or complex]
Upper bounds

Returns:
card (pyNastran.bdf.cards.properties.shell.PCOMP): pyNastran card holding property information
Raises
------
ValueError
Raises error if the length of lowerBound or upperBound is not equal to the number of panel plies
"""
num_plies = len(self.props)
cdef TACSCompositeShellConstitutive* comp_ptr = <TACSCompositeShellConstitutive*>self.cptr
cdef np.ndarray ply_thicknesses = np.zeros(num_plies, dtype)
cdef np.ndarray ply_angles = np.zeros(num_plies, dtype)

comp_ptr.getPlyThicknesses(<TacsScalar*>ply_thicknesses.data)
comp_ptr.getPlyAngles(<TacsScalar*>ply_angles.data)

mat_ids = []
for i in range(num_plies):
ply_id = self.props[i].getNastranID()
mat_ids.append(ply_id)

prop = nastran_cards.properties.shell.PCOMP(self.nastranID, mat_ids,
ply_thicknesses.astype(float),
np.rad2deg(ply_angles, dtype=float))
return prop
if self.blade_ptr:
if len(lowerBound) != self.blade_ptr.getNumPanelPlies():
raise ValueError('lowerBound must have length numPanelPlies')
if len(upperBound) != self.blade_ptr.getNumPanelPlies():
raise ValueError('upperBound must have length numPanelPlies')
self.blade_ptr.setPanelPlyFractionBounds(<TacsScalar*>lowerBound.data, <TacsScalar*>upperBound.data)

cdef class LamParamShellConstitutive(ShellConstitutive):
def __cinit__(self, OrthotropicPly ply, **kwargs):
Expand Down
Loading