Commit f6a30949 authored by Salko Jr, Robert's avatar Salko Jr, Robert
Browse files

Add ability to connect gaps in multiple sections

CTF will not be able to transport lateral momentum across section boundaries
if this information is not specified by the user.
This adds the ability to do that along with some error checks on the model and
expands an existing test to cover the feature.
parent 73c153ea
Loading
Loading
Loading
Loading
+87 −4
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ class Model:
      me.cha = {}
      me.chb = {}
      # List of all gap objets in the model
      me.gaps = []
      me.gaps = {}
      # Takes the solid ID (user defined) and returns the solid type ID (user defined)
      me.solidTypeIDs = {}
      # Takes the solid type ID (user defined) and returns the solid geometry object it refers to
@@ -293,7 +293,7 @@ class Model:
         else:
            me.chb[chID].append(chb)

   def setGap(me, ii, jj, width, length, k=DEFAULT_GAP_FORM_LOSS, mult=1.0):
   def setGap(me, ii, jj, width, length, k=DEFAULT_GAP_FORM_LOSS, mult=1.0, gapID=None, gapBelow=0, gapAbove=0):
      """ Defines a lateral connection between two channels in the same axial section

      Args:
@@ -303,9 +303,25 @@ class Model:
         length (float): Lateral distance between the centroids of the two connected channels
         k (float): Form loss applied to the lateral momentum equation solved in the gap
         mult (float): Number of physical gaps in the model represented by this gap
         gapID (int) : ID of the gap.  If not assigned, an unused one will be created and returned.
         gapBelow (int): ID of gap below this one.  This is used for transporting lateral momentum
            accross section boundaries and therefore must be specified for multisection models where
            gaps are connected.  Enter 0 or omit if no gap below.
         gapAbove (int): ID of gap above this one.  Enter 0 or omit if no gap above.

      """
      me.gaps.append(Gap(ii, jj, width, length, k, mult))
      if gapID is None:
         gapIDs = sorted(me.gaps.keys())
         if len(gapIDs)>0:
            gapID = gapIDs[-1]+1
         else:
            gapID = 1
      else:
         assert isinstance(gapID, int)

      me.gaps[gapID] = Gap(ii, jj, width, length, k, mult, gapBelow, gapAbove)

      return gapID

   def solidQuickAdd(me, solidID, geoObj, solidObj=None):
       """ Used to add a single instance of a solid object
@@ -945,6 +961,22 @@ class Model:
         me.channelsInDomain[domain].append(IDsInDomain)
      me.solver = 5

   def getSectionOfGap(me, gapID):
      """ Returns the secID of the section that owns the passed gapID

      Args:
         gapID (int) : Gap ID

      """
      assert gapID in me.gaps
      sec1 = me.getSectionOfChannel(me.gaps[gapID].ii)
      sec2 = me.getSectionOfChannel(me.gaps[gapID].jj)
      if sec1!=sec2:
         raise RuntimeError("Gap {:d} connects Channels {:d} and {:d} which are in different sections "+
            "{:d} and {:d}.  This is not allowed".format(gapID, me.gaps[gapID].ii, me.gaps[gapID].jj, sec1, sec2))
      return sec1


   def getSectionOfChannel(me, chID):
      """ Returns the secID of the section that owns the passed chID

@@ -1246,6 +1278,8 @@ class Model:

      me._rodConnectionsValid()

      me._gapChecks()



   def _rodsInValidSections(me):
@@ -1352,6 +1386,51 @@ class Model:
               if chID not in me.cha[below]:
                   me.cha[below].append(chID)

   def _gapChecks(me):
      """ Ensure gaps defined in model are valid"""
      if len(me.gaps)==0:
         return
      # Gap IDs must start at 1 and run sequentially to num gaps
      gapIDs = sorted(me.gaps.keys())
      errMsg = "Gap IDs must start at 1 and run continuously to total number of gaps"
      if gapIDs[0]!=1:
         raise RuntimeError(errMsg)
      for gapCount in range(1, len(gapIDs)):
         if gapIDs[gapCount]!=gapIDs[gapCount-1]+1:
            raise RuntimeError(errMsg)
      # gaps that connect across section bounds must be connected to valid indices
      for gapID in me.gaps.keys():
         gapSection = me.getSectionOfGap(gapID)
         gapBelow = me.gaps[gapID].gapBelow
         if gapBelow!=0:
            gapSectionBelow = me.getSectionOfGap(gapBelow)
            # Make sure the section of the gap below is actually the section below this gap's section
            if gapSectionBelow!=gapSection-1:
               raise RuntimeError("Gap {:d} connects to Gap {:d} below, but Gap {:d} is in Section {:d} and "+
                     "Gap {:d} is in Section {:d}, which are not correctly axially aligned".format(gapID,
                     gapBelow, gapID, gapSection, gapBelow, gapSectionBelow))
            # If the gap below does not have gapAbove set to be consistent with this one, set it
            if me.gaps[gapBelow].gapAbove==0:
               me.gaps[gapBelow].gapAbove = gapID
            # If the gap below was set, but is not equal to this gapID, throw an error
            if me.gaps[gapBelow].gapAbove!=gapID:
               raise RuntimeError("Gap {:d} had gapAbove set to {:d}, but this is not consistent with what "+
                     "gapBelow was set to for {:d}".format(gapBelow, me.gaps[gapBelow].gapAbove, gapID))
         gapAbove = me.gaps[gapID].gapAbove
         if gapAbove!=0:
            gapSectionAbove = me.getSectionOfGap(gapAbove)
            if gapSectionAbove!=gapSection+1:
               raise RuntimeError("Gap {:d} connects to Gap {:d} above, but Gap {:d} is in Section {:d} and "+
                     "Gap {:d} is in Section {:d}, which are not correctly axially aligned".format(gapID,
                     gapAbove, gapID, gapSection, gapAbove, gapSectionAbove))
            # If the gap above does not have gapAbove set to be consistent with this one, set it
            if me.gaps[gapAbove].gapBelow==0:
               me.gaps[gapAbove].gapBelow = gapID
            # If the gap above was set, but is not equal to this gapID, throw an error
            if me.gaps[gapAbove].gapBelow!=gapID:
               raise RuntimeError("Gap {:d} had gapBelow set to {:d}, but this is not consistent with what "+
                     "gapAbove was set to for {:d}".format(gapAbove, me.gaps[gapAbove].gapBelow, gapID))

   def _validateBoundaryConditions(me):
       """ Ensure boundary conditions were setup correctly"""
       # Ensure all were defined where expected
@@ -1409,12 +1488,16 @@ class Gap(object):
      length (float): Lateral distance between the centroids of the two connected channels
      k (float): Form loss applied to the lateral momentum equation solved in the gap
      mult (float): Number of physical gaps in the model represented by this gap
      gapBelow (int) : ID of gap below this one.  Enter 0 or omit if no gap below.
      gapAbove (int) : ID of gap above this one.  Enter 0 or omit if no gap above.

   """
   def __init__(me, ii, jj, width, length, k=DEFAULT_GAP_FORM_LOSS, mult=1.0):
   def __init__(me, ii, jj, width, length, k=DEFAULT_GAP_FORM_LOSS, mult=1.0, gapBelow=0, gapAbove=0):
      me.ii = ii
      me.jj = jj
      me.width = width
      me.length = length
      me.k = k
      me.mult = mult
      me.gapBelow = gapBelow
      me.gapAbove = gapAbove
+5 −4
Original line number Diff line number Diff line
@@ -156,12 +156,13 @@ def writeDeck(model, filename):
   group3Data.append("**   K    IK    JK             GAP            LNGT            WKR  FWAL IGPB IGPA FACT IGAP JGAP IGAP JGAP IGAP JGAP\n")
   group3Data.append("*Card 3.3\n")
   group3Data.append("**GMULT ETNR\n")
   for k, gap in enumerate(model.gaps):
      group3Data.append("{0:6d}{1:6d}{2:6d}{3:16.6e}{4:16.6e}{5:15.5e}   0.0    0    0 1.0     0    0    0    0    0    0\n".format(k+1, chMap.getIndex(gap.ii), chMap.getIndex(gap.jj), gap.width, gap.length, gap.k))
   for k in model.gaps.keys():
      gap = model.gaps[k]
      group3Data.append("{:6d}{:6d}{:6d}{:16.6e}{:16.6e}{:15.5e}   0.0{:5d}{:5d} 1.0     0    0    0    0    0    0\n".format(k, chMap.getIndex(gap.ii), chMap.getIndex(gap.jj), gap.width, gap.length, gap.k, gap.gapBelow, gap.gapAbove))
      group3Data.append("{:6.4f}   0.0\n".format(gap.mult))
   group3Data.append("*Card 3.3.5\n")
   for k, gap in enumerate(model.gaps):
      group3Data.append("{0:6d}{1:>6s}\n".format(k+1, 'x'))
   for k in model.gaps.keys():
      group3Data.append("{0:6d}{1:>6s}\n".format(k, 'x'))
   group3Data.append("*Card 3.4\n")
   group3Data.append("**NLGP\n")
   group3Data.append("     0\n")
+5 −5
Original line number Diff line number Diff line
@@ -57,19 +57,19 @@ ctf model
**   K    IK    JK             GAP            LNGT            WKR  FWAL IGPB IGPA FACT IGAP JGAP IGAP JGAP IGAP JGAP
*Card 3.3
**GMULT ETNR
     1     1     2    1.000000e-01    1.000000e-01    5.00000e-01   0.0    0    0 1.0     0    0    0    0    0    0
     1     1     2    1.000000e-01    1.000000e-01    5.00000e-01   0.0    0    5 1.0     0    0    0    0    0    0
1.0000   0.0
     2     2     3    1.000000e-01    1.000000e-01    5.00000e-01   0.0    0    0 1.0     0    0    0    0    0    0
     2     2     3    1.000000e-01    1.000000e-01    5.00000e-01   0.0    0    6 1.0     0    0    0    0    0    0
1.0000   0.0
     3     3     4    1.000000e-01    1.000000e-01    5.00000e-01   0.0    0    0 1.0     0    0    0    0    0    0
1.0000   0.0
     4     4     5    1.000000e-01    1.000000e-01    5.00000e-01   0.0    0    0 1.0     0    0    0    0    0    0
1.0000   0.0
     5     6     7    1.000000e-01    1.000000e-01    5.00000e-01   0.0    0    0 1.0     0    0    0    0    0    0
     5     6     7    1.000000e-01    1.000000e-01    5.00000e-01   0.0    1    0 1.0     0    0    0    0    0    0
1.0000   0.0
     6     7     8    1.000000e-01    1.000000e-01    5.00000e-01   0.0    0    0 1.0     0    0    0    0    0    0
     6     7     8    1.000000e-01    1.000000e-01    5.00000e-01   0.0    2    7 1.0     0    0    0    0    0    0
1.0000   0.0
     7     9    10    1.000000e-01    1.000000e-01    5.00000e-01   0.0    0    0 1.0     0    0    0    0    0    0
     7     9    10    1.000000e-01    1.000000e-01    5.00000e-01   0.0    6    0 1.0     0    0    0    0    0    0
1.0000   0.0
*Card 3.3.5
     1     x
+7 −7
Original line number Diff line number Diff line
@@ -48,10 +48,10 @@ sec.addChannel(chID=4, area=area, pw=pw)
sec.addChannel(chID=5, area=area, pw=pw)
model.addSection(secID=1, section=sec)

model.setGap(1, 2, 0.1, 0.1)
model.setGap(2, 3, 0.1, 0.1)
model.setGap(3, 4, 0.1, 0.1)
model.setGap(4, 5, 0.1, 0.1)
model.setGap(1, 2, 0.1, 0.1, gapID=1, gapAbove=5)
model.setGap(2, 3, 0.1, 0.1, gapID=2, gapAbove=6)
model.setGap(3, 4, 0.1, 0.1, gapID=3)
model.setGap(4, 5, 0.1, 0.1, gapID=4)

model.setConnection(1, cha=6)
model.setConnection(2, cha=7)
@@ -71,8 +71,8 @@ model.setConnection(6, cha=9)
model.setConnection(7, cha=9)
model.setConnection(8, cha=10)

model.setGap(6, 7, 0.1, 0.1)
model.setGap(7, 8, 0.1, 0.1)
model.setGap(6, 7, 0.1, 0.1, gapID=5)
model.setGap(7, 8, 0.1, 0.1, gapID=6, gapAbove=7)

# Section 3
# ---------
@@ -81,7 +81,7 @@ sec.addChannel(chID=9, area=2*area, pw=2*pw)
sec.addChannel(chID=10, area=2*area, pw=2*pw)
model.addSection(secID=3, section=sec)

model.setGap(9, 10, 0.1, 0.1)
model.setGap(9, 10, 0.1, 0.1, gapID=7)


# Rod 1