Beispiel #1
0
def addKernels(generator, aderdg, matricesDir, PlasticityMethod):
  # Load matrices
  db = parseXMLMatrixFile('{}/plasticity_{}_matrices_{}.xml'.format(matricesDir, PlasticityMethod, aderdg.order), clones=dict(), alignStride=aderdg.alignStride)
  numberOfNodes = db.v.shape()[0]

  sShape = (aderdg.numberOf3DBasisFunctions(), 6)
  QStress = OptionalDimTensor('QStress', aderdg.Q.optName(), aderdg.Q.optSize(), aderdg.Q.optPos(), sShape, alignStride=True)
  initialLoading = Tensor('initialLoading', (6,))

  replicateIniLShape = (numberOfNodes,)
  replicateIniLSpp = np.ones(aderdg.Q.insertOptDim(replicateIniLShape, (aderdg.Q.optSize(),)))
  replicateInitialLoading = OptionalDimTensor('replicateInitialLoading', aderdg.Q.optName(), aderdg.Q.optSize(), aderdg.Q.optPos(), replicateIniLShape, spp=replicateIniLSpp, alignStride=True)

  iShape = (numberOfNodes, 6)
  QStressNodal = OptionalDimTensor('QStressNodal', aderdg.Q.optName(), aderdg.Q.optSize(), aderdg.Q.optPos(), iShape, alignStride=True)
  meanStress = OptionalDimTensor('meanStress', aderdg.Q.optName(), aderdg.Q.optSize(), aderdg.Q.optPos(), (numberOfNodes,), alignStride=True)
  secondInvariant = OptionalDimTensor('secondInvariant', aderdg.Q.optName(), aderdg.Q.optSize(), aderdg.Q.optPos(), (numberOfNodes,), alignStride=True)

  selectBulkAverage = Tensor('selectBulkAverage', (6,), spp={(i,): str(1.0/3.0) for i in range(3)})
  selectBulkNegative = Tensor('selectBulkNegative', (6,), spp={(i,): '-1.0' for i in range(3)})
  weightSecondInvariant = Tensor('weightSecondInvariant', (6,), spp={(i,): str(1.0/2.0) if i < 3 else '1.0' for i in range(6)})
  yieldFactor = Tensor('yieldFactor', (numberOfNodes,))

  generator.add('plConvertToNodal', QStressNodal['kp'] <= db.v['kl'] * QStress['lp'] + replicateInitialLoading['k'] * initialLoading['p'])
  generator.add('plComputeMean', meanStress['k'] <= QStressNodal['kq'] * selectBulkAverage['q'])
  generator.add('plSubtractMean', QStressNodal['kp'] <= QStressNodal['kp'] + meanStress['k'] * selectBulkNegative['p'])
  generator.add('plComputeSecondInvariant', secondInvariant['k'] <= QStressNodal['kq'] * QStressNodal['kq'] * weightSecondInvariant['q'])
  generator.add('plAdjustStresses', QStress['kp'] <= QStress['kp'] + db.vInv['kl'] * QStressNodal['lp'] * yieldFactor['l'])
Beispiel #2
0
    def __init__(self, order, multipleSimulations, matricesDir):
        self.order = order

        self.alignStride = lambda name: True
        if multipleSimulations > 1:
            self.alignStride = lambda name: name.startswith('fP')
        transpose = multipleSimulations > 1
        self.transpose = lambda name: transpose
        self.t = (lambda x: x[::-1]) if transpose else (lambda x: x)

        self.db = parseXMLMatrixFile('{}/matrices_{}.xml'.format(
            matricesDir, self.numberOf3DBasisFunctions()),
                                     transpose=self.transpose,
                                     alignStride=self.alignStride)
        clonesQP = {'v': ['evalAtQP'], 'vInv': ['projectQP']}
        self.db.update(
            parseXMLMatrixFile('{}/plasticity_ip_matrices_{}.xml'.format(
                matricesDir, order),
                               clonesQP,
                               transpose=self.transpose,
                               alignStride=self.alignStride))

        qShape = (self.numberOf3DBasisFunctions(), self.numberOfQuantities())
        self.Q = OptionalDimTensor('Q',
                                   's',
                                   multipleSimulations,
                                   0,
                                   qShape,
                                   alignStride=True)
        self.I = OptionalDimTensor('I',
                                   's',
                                   multipleSimulations,
                                   0,
                                   qShape,
                                   alignStride=True)

        Aplusminus_spp = self.flux_solver_spp()
        self.AplusT = Tensor('AplusT',
                             Aplusminus_spp.shape,
                             spp=Aplusminus_spp)
        self.AminusT = Tensor('AminusT',
                              Aplusminus_spp.shape,
                              spp=Aplusminus_spp)
        Tshape = (self.numberOfExtendedQuantities(),
                  self.numberOfExtendedQuantities())
        trans_spp = self.transformation_spp()
        self.T = Tensor('T', trans_spp.shape, spp=trans_spp)
        trans_inv_spp = self.transformation_inv_spp()
        self.Tinv = Tensor('Tinv', trans_inv_spp.shape, spp=trans_inv_spp)
        godunov_spp = self.godunov_spp()
        self.QgodLocal = Tensor('QgodLocal',
                                godunov_spp.shape,
                                spp=godunov_spp)
        self.QgodNeighbor = Tensor('QgodNeighbor',
                                   godunov_spp.shape,
                                   spp=godunov_spp)

        self.oneSimToMultSim = Tensor('oneSimToMultSim', (self.Q.optSize(), ),
                                      spp={(i, ): '1.0'
                                           for i in range(self.Q.optSize())})
Beispiel #3
0
  def addTime(self, generator):
    qShape = (self.numberOf3DBasisFunctions(), self.numberOfQuantities())
    dQ = [OptionalDimTensor('dQ({})'.format(d), self.Q.optName(), self.Q.optSize(), self.Q.optPos(), qShape, alignStride=True) for d in range(self.order)]
    dQext = [OptionalDimTensor('dQext({})'.format(d), self.Q.optName(), self.Q.optSize(), self.Q.optPos(), self._qShapeExtended, alignStride=True) for d in range(self.order)]
    dQane = [OptionalDimTensor('dQane({})'.format(d), self.Q.optName(), self.Q.optSize(), self.Q.optPos(), self._qShapeAnelastic, alignStride=True) for d in range(self.order)]

    power = Scalar('power')

    derivativeTaylorExpansionEla = lambda d: (self.I['kp'] <= self.I['kp'] + power * dQ[d]['kp']) if d > 0 else (self.I['kp'] <= power * dQ[0]['kp'])
    derivativeTaylorExpansionAne = lambda d: (self.Iane['kpm'] <= self.Iane['kpm'] + power * dQane[d]['kpm']) if d > 0 else (self.Iane['kpm'] <= power * dQane[0]['kpm'])

    def derivative(kthDer):
      derivativeSum = Add()
      for j in range(3):
        derivativeSum += self.db.kDivMT[j][self.t('kl')] * dQ[kthDer-1]['lq'] * self.db.star[j]['qp']
      return derivativeSum

    generator.addFamily('derivative', parameterSpaceFromRanges(range(1,self.order)), lambda d: [
      dQext[d]['kp'] <= derivative(d),
      dQ[d]['kp'] <= dQext[d]['kq'] * self.selectEla['qp'] + dQane[d-1]['kqm'] * self.E['qmp'],
      dQane[d]['kpm'] <= self.w['m'] * dQext[d]['kq'] * self.selectAne['qp'] + dQane[d-1]['kpl'] * self.W['lm']
    ])
    generator.addFamily('derivativeTaylorExpansion', simpleParameterSpace(self.order), lambda d: [
      derivativeTaylorExpansionEla(d),
      derivativeTaylorExpansionAne(d)
    ])
    generator.addFamily('derivativeTaylorExpansionEla', simpleParameterSpace(self.order), derivativeTaylorExpansionEla)
Beispiel #4
0
 def addTime(self, generator):
     qShape = (self.numberOf3DBasisFunctions(), self.numberOfQuantities())
     dQ0 = OptionalDimTensor('dQ(0)',
                             self.Q.optName(),
                             self.Q.optSize(),
                             self.Q.optPos(),
                             qShape,
                             alignStride=True)
     power = Scalar('power')
     derivatives = [dQ0]
     generator.add('derivativeTaylorExpansion(0)',
                   self.I['kp'] <= power * dQ0['kp'])
     for i in range(1, self.order):
         derivativeSum = Add()
         if self.sourceMatrix():
             derivativeSum += derivatives[-1]['kq'] * self.sourceMatrix(
             )['qp']
         for j in range(3):
             derivativeSum += self.db.kDivMT[j][self.t(
                 'kl')] * derivatives[-1]['lq'] * self.starMatrix(j)['qp']
         derivativeSum = DeduceIndices(
             self.Q['kp'].indices).visit(derivativeSum)
         derivativeSum = EquivalentSparsityPattern().visit(derivativeSum)
         dQ = OptionalDimTensor('dQ({})'.format(i),
                                self.Q.optName(),
                                self.Q.optSize(),
                                self.Q.optPos(),
                                qShape,
                                spp=derivativeSum.eqspp(),
                                alignStride=True)
         generator.add('derivative({})'.format(i),
                       dQ['kp'] <= derivativeSum)
         generator.add('derivativeTaylorExpansion({})'.format(i),
                       self.I['kp'] <= self.I['kp'] + power * dQ['kp'])
         derivatives.append(dQ)
Beispiel #5
0
  def addInit(self, generator):
    super().addInit(generator)

    iniShape = (self.numberOf3DQuadraturePoints(), self.numberOfQuantities())
    iniCond = OptionalDimTensor('iniCond', self.Q.optName(), self.Q.optSize(), self.Q.optPos(), iniShape, alignStride=True)
    dofsQP = OptionalDimTensor('dofsQP', self.Q.optName(), self.Q.optSize(), self.Q.optPos(), iniShape, alignStride=True)

    generator.add('projectIniCond', self.Q['kp'] <= self.db.projectQP[self.t('kl')] * iniCond['lp'])
    generator.add('evalAtQP', dofsQP['kp'] <= self.db.evalAtQP[self.t('kl')] * self.Q['lp'])
Beispiel #6
0
    def addInit(self, generator):
        super().addInit(generator)

        selectElaFullSpp = np.zeros(
            (self.numberOfFullQuantities(), self.numberOfQuantities()))
        selectElaFullSpp[0:self.numberOfQuantities(),
                         0:self.numberOfQuantities()] = np.eye(
                             self.numberOfQuantities())
        selectElaFull = Tensor(
            'selectElaFull',
            (self.numberOfFullQuantities(), self.numberOfQuantities()),
            selectElaFullSpp, CSCMemoryLayout)

        selectAneFullSpp = np.zeros(
            (self.numberOfFullQuantities(), self.numberOfAnelasticQuantities(),
             self.numberOfMechanisms))
        for mech in range(self.numberOfMechanisms):
            q1 = self.numberOfQuantities(
            ) + mech * self.numberOfAnelasticQuantities()
            q2 = q1 + self.numberOfAnelasticQuantities()
            selectAneFullSpp[q1:q2, :,
                             mech] = np.eye(self.numberOfAnelasticQuantities())
        selectAneFull = Tensor(
            'selectAneFull',
            (self.numberOfFullQuantities(), self.numberOfAnelasticQuantities(),
             self.numberOfMechanisms), selectAneFullSpp)

        iniShape = (self.numberOf3DQuadraturePoints(),
                    self.numberOfFullQuantities())
        iniCond = OptionalDimTensor('iniCond',
                                    self.Q.optName(),
                                    self.Q.optSize(),
                                    self.Q.optPos(),
                                    iniShape,
                                    alignStride=True)
        dofsShape = (self.numberOf3DQuadraturePoints(),
                     self.numberOfQuantities())
        dofsQP = OptionalDimTensor('dofsQP',
                                   self.Q.optName(),
                                   self.Q.optSize(),
                                   self.Q.optPos(),
                                   dofsShape,
                                   alignStride=True)

        projectIniCondEla = self.Q['kp'] <= self.db.projectQP[self.t(
            'kl')] * iniCond['lq'] * selectElaFull['qp']
        projectIniCondAne = self.Qane['kpm'] <= self.db.projectQP[self.t(
            'kl')] * iniCond['lq'] * selectAneFull['qpm']
        generator.add('projectIniCond', [projectIniCondEla, projectIniCondAne])
        generator.add(
            'evalAtQP',
            dofsQP['kp'] <= self.db.evalAtQP[self.t('kl')] * self.Q['lp'])
Beispiel #7
0
def addKernels(generator, aderdg):
  numberOf3DBasisFunctions = aderdg.numberOf3DBasisFunctions()
  numberOfQuantities = aderdg.numberOfQuantities()
  ## Point sources
  mInvJInvPhisAtSources = Tensor('mInvJInvPhisAtSources', (numberOf3DBasisFunctions,))

  momentNRF = Tensor('momentNRF', (numberOfQuantities,), spp=np.array([1]*6 + [0]*(numberOfQuantities-6), dtype=bool))
  if aderdg.Q.hasOptDim():
    sourceNRF = aderdg.Q['kp'] <= aderdg.Q['kp'] - mInvJInvPhisAtSources['k'] * momentNRF['p'] * aderdg.oneSimToMultSim['s']
  else:
    sourceNRF = aderdg.Q['kp'] <= aderdg.Q['kp'] - mInvJInvPhisAtSources['k'] * momentNRF['p']
  generator.add('sourceNRF', sourceNRF)

  momentFSRM = Tensor('momentFSRM', (numberOfQuantities,))
  stfIntegral = Scalar('stfIntegral')
  if aderdg.Q.hasOptDim():
    sourceFSRM = aderdg.Q['kp'] <= aderdg.Q['kp'] + stfIntegral * mInvJInvPhisAtSources['k'] * momentFSRM['p'] * aderdg.oneSimToMultSim['s']
  else:
    sourceFSRM = aderdg.Q['kp'] <= aderdg.Q['kp'] + stfIntegral * mInvJInvPhisAtSources['k'] * momentFSRM['p']
  generator.add('sourceFSRM', sourceFSRM)

  ## Receiver output
  basisFunctionsAtPoint = Tensor('basisFunctions', (numberOf3DBasisFunctions,))
  QAtPoint = OptionalDimTensor('QAtPoint', aderdg.Q.optName(), aderdg.Q.optSize(), aderdg.Q.optPos(), (numberOfQuantities,))
  evaluateDOFSAtPoint = QAtPoint['p'] <= aderdg.Q['kp'] * basisFunctionsAtPoint['k']
  generator.add('evaluateDOFSAtPoint', evaluateDOFSAtPoint)
Beispiel #8
0
  def __init__(self, order, multipleSimulations, matricesDir):
    self.order = order

    self.alignStride = lambda name: True
    if multipleSimulations > 1:
      self.alignStride = lambda name: name.startswith('fP')
    transpose = multipleSimulations > 1
    self.transpose = lambda name: transpose
    self.t = (lambda x: x[::-1]) if transpose else (lambda x: x)

    self.db = parseXMLMatrixFile('{}/matrices_{}.xml'.format(matricesDir, self.numberOf3DBasisFunctions()), transpose=self.transpose, alignStride=self.alignStride)
    clonesQP = {
      'v': [ 'evalAtQP' ],
      'vInv': [ 'projectQP' ]
    }
    self.db.update( parseXMLMatrixFile('{}/plasticity_ip_matrices_{}.xml'.format(matricesDir, order), clonesQP, transpose=self.transpose, alignStride=self.alignStride))

    qShape = (self.numberOf3DBasisFunctions(), self.numberOfQuantities())
    self.Q = OptionalDimTensor('Q', 's', multipleSimulations, 0, qShape, alignStride=True)
    self.I = OptionalDimTensor('I', 's', multipleSimulations, 0, qShape, alignStride=True)

    Ashape = (self.numberOfQuantities(), self.numberOfExtendedQuantities())
    self.AplusT = Tensor('AplusT', Ashape)
    self.AminusT = Tensor('AminusT', Ashape)
    Tshape = (self.numberOfExtendedQuantities(), self.numberOfExtendedQuantities())
    self.T = Tensor('T', Tshape)
    QgodShape = (self.numberOfQuantities(), self.numberOfQuantities())
    self.Tinv = Tensor('Tinv', QgodShape)
    self.QgodLocal = Tensor('QgodLocal', QgodShape)
    self.QgodNeighbor = Tensor('QgodNeighbor', QgodShape)

    self.oneSimToMultSim = Tensor('oneSimToMultSim', (self.Q.optSize(),), spp={(i,): '1.0' for i in range(self.Q.optSize())})
Beispiel #9
0
def addKernels(generator, aderdg):
    numberOf3DBasisFunctions = aderdg.numberOf3DBasisFunctions()
    numberOfQuantities = aderdg.numberOfQuantities()
    ## Point sources
    mStiffnessTensor = Tensor('stiffnessTensor', (3, 3, 3, 3))
    mSlip = Tensor('mSlip', (3, ))
    mNormal = Tensor('mNormal', (3, ))
    mArea = Scalar('mArea')
    basisFunctionsAtPoint = Tensor('basisFunctionsAtPoint',
                                   (numberOf3DBasisFunctions, ))
    mInvJInvPhisAtSources = Tensor('mInvJInvPhisAtSources',
                                   (numberOf3DBasisFunctions, ))
    JInv = Scalar('JInv')

    generator.add(
        'computeMInvJInvPhisAtSources', mInvJInvPhisAtSources['k'] <=
        JInv * aderdg.db.M3inv['kl'] * basisFunctionsAtPoint['l'])

    #extract the moment tensors entries in SeisSol ordering (xx, yy, zz, xy, yz, xz)
    assert (numberOfQuantities >= 6)
    momentToNRF_spp = np.zeros((numberOfQuantities, 3, 3))
    momentToNRF_spp[0, 0, 0] = 1
    momentToNRF_spp[1, 1, 1] = 1
    momentToNRF_spp[2, 2, 2] = 1
    momentToNRF_spp[3, 0, 1] = 1
    momentToNRF_spp[4, 1, 2] = 1
    momentToNRF_spp[5, 0, 2] = 1
    momentToNRF = Tensor('momentToNRF', (numberOfQuantities, 3, 3),
                         spp=momentToNRF_spp)

    momentNRFKernel = momentToNRF['tpq'] * mArea * mStiffnessTensor[
        'pqij'] * mSlip['i'] * mNormal['j']

    if aderdg.Q.hasOptDim():
        sourceNRF = aderdg.Q['kt'] <= aderdg.Q['kt'] + mInvJInvPhisAtSources[
            'k'] * momentNRFKernel * aderdg.oneSimToMultSim['s']
    else:
        sourceNRF = aderdg.Q['kt'] <= aderdg.Q[
            'kt'] + mInvJInvPhisAtSources['k'] * momentNRFKernel
    generator.add('sourceNRF', sourceNRF)

    momentFSRM = Tensor('momentFSRM', (numberOfQuantities, ))
    stfIntegral = Scalar('stfIntegral')
    if aderdg.Q.hasOptDim():
        sourceFSRM = aderdg.Q[
            'kp'] <= aderdg.Q['kp'] + stfIntegral * mInvJInvPhisAtSources[
                'k'] * momentFSRM['p'] * aderdg.oneSimToMultSim['s']
    else:
        sourceFSRM = aderdg.Q['kp'] <= aderdg.Q[
            'kp'] + stfIntegral * mInvJInvPhisAtSources['k'] * momentFSRM['p']
    generator.add('sourceFSRM', sourceFSRM)

    ## Receiver output
    QAtPoint = OptionalDimTensor('QAtPoint', aderdg.Q.optName(),
                                 aderdg.Q.optSize(), aderdg.Q.optPos(),
                                 (numberOfQuantities, ))
    evaluateDOFSAtPoint = QAtPoint[
        'p'] <= aderdg.Q['kp'] * basisFunctionsAtPoint['k']
    generator.add('evaluateDOFSAtPoint', evaluateDOFSAtPoint)
def addKernels(generator, aderdg):
    maxDepth = 3

    numberOf3DBasisFunctions = aderdg.numberOf3DBasisFunctions()
    numberOfQuantities = aderdg.numberOfQuantities()
    selectVelocitySpp = np.zeros((numberOfQuantities, 3))
    selectVelocitySpp[6:9, 0:3] = np.eye(3)
    selectVelocity = Tensor('selectVelocity', selectVelocitySpp.shape,
                            selectVelocitySpp, CSCMemoryLayout)

    displacement = OptionalDimTensor('displacement',
                                     aderdg.Q.optName(),
                                     aderdg.Q.optSize(),
                                     aderdg.Q.optPos(),
                                     (numberOf3DBasisFunctions, 3),
                                     alignStride=True)
    generator.add(
        'addVelocity', displacement['kp'] <=
        displacement['kp'] + aderdg.I['kq'] * selectVelocity['qp'])

    subTriangleDofs = [
        OptionalDimTensor('subTriangleDofs({})'.format(depth),
                          aderdg.Q.optName(),
                          aderdg.Q.optSize(),
                          aderdg.Q.optPos(), (4**depth, 3),
                          alignStride=True) for depth in range(maxDepth + 1)
    ]
    subTriangleProjection = [
        Tensor('subTriangleProjection({})'.format(depth),
               (4**depth, numberOf3DBasisFunctions),
               alignStride=True) for depth in range(maxDepth + 1)
    ]

    subTriangleDisplacement = lambda depth: subTriangleDofs[depth][
        'kp'] <= subTriangleProjection[depth]['kl'] * displacement['lp']
    subTriangleVelocity = lambda depth: subTriangleDofs[depth][
        'kp'] <= subTriangleProjection[depth]['kl'] * aderdg.Q[
            'lq'] * selectVelocity['qp']

    generator.addFamily('subTriangleDisplacement',
                        simpleParameterSpace(maxDepth + 1),
                        subTriangleDisplacement)
    generator.addFamily('subTriangleVelocity',
                        simpleParameterSpace(maxDepth + 1),
                        subTriangleVelocity)
Beispiel #11
0
def addKernels(generator, aderdg, include_tensors, matricesDir, dynamicRuptureMethod):
    easi_ident_map = np.stack([np.eye(aderdg.numberOfQuantities())] * aderdg.numberOf2DBasisFunctions(), axis=2)
    assert(easi_ident_map.shape ==
           (aderdg.numberOfQuantities(), aderdg.numberOfQuantities(), aderdg.numberOf2DBasisFunctions()))
    easi_ident_map = Tensor('easiIdentMap',
                            easi_ident_map.shape,
                            easi_ident_map,
                            alignStride=False)
    easi_boundary_constant = Tensor('easiBoundaryConstant',
                                    (aderdg.numberOfQuantities(), aderdg.numberOf2DBasisFunctions()),
                                    alignStride=False)
    easi_boundary_map = Tensor('easiBoundaryMap',
                               (aderdg.numberOfQuantities(), aderdg.numberOfQuantities(), aderdg.numberOf2DBasisFunctions(),),
                               alignStride=False)
    create_easi_boundary_ghost_cells = (
            aderdg.INodal['la'] <= easi_boundary_map['abl'] * aderdg.INodal['lb'] + easi_ident_map['abl'] * easi_boundary_constant['bl']
    )
    generator.add('createEasiBoundaryGhostCells', create_easi_boundary_ghost_cells)

    projectToNodalBoundary = lambda j: aderdg.INodal['kp'] <= aderdg.db.V3mTo2nFace[j]['km'] * aderdg.I['mp']

    generator.addFamily('projectToNodalBoundary',
                        simpleParameterSpace(4),
                        projectToNodalBoundary)

    projectToNodalBoundaryRotated = lambda j: aderdg.INodal['kp'] <= aderdg.db.V3mTo2nFace[j]['kl'] \
                                              * aderdg.I['lm'] \
                                              * aderdg.Tinv['pm']

    generator.addFamily('projectToNodalBoundaryRotated',
                        simpleParameterSpace(4),
                        projectToNodalBoundaryRotated)

    # To be used as Tinv in flux solver - this way we can save two rotations for
    # Dirichlet boundary, as ghost cell dofs are already rotated
    identity_rotation = np.double(aderdg.transformation_spp())
    identity_rotation[0:9, 0:9] = np.eye(9)
    identity_rotation = Tensor('identityT',
                               aderdg.transformation_spp().shape,
                               identity_rotation,
                               )
    include_tensors.add(identity_rotation)

    aderdg.INodalUpdate = OptionalDimTensor('INodalUpdate',
                                          aderdg.INodal.optName(),
                                          aderdg.INodal.optSize(),
                                          aderdg.INodal.optPos(),
                                          (aderdg.numberOf2DBasisFunctions(), aderdg.numberOfQuantities()),
                                          alignStride=True)

    factor = Scalar('factor')
    updateINodal = aderdg.INodal['kp'] <= aderdg.INodal['kp'] + factor * aderdg.INodalUpdate['kp']
    generator.add('updateINodal', updateINodal)
Beispiel #12
0
  def __init__(self, order, multipleSimulations, matricesDir, memLayout, numberOfMechanisms, **kwargs):
    super().__init__(order, multipleSimulations, matricesDir)

    self.numberOfMechanisms = numberOfMechanisms

    clones = {
      'star': ['star(0)', 'star(1)', 'star(2)'],
    }
    self.db.update( parseXMLMatrixFile('{}/matrices_viscoelastic.xml'.format(matricesDir), clones) )
    memoryLayoutFromFile(memLayout, self.db, clones)

    self._qShapeExtended = (self.numberOf3DBasisFunctions(), self.numberOfExtendedQuantities())
    self._qShapeAnelastic = (self.numberOf3DBasisFunctions(), self.numberOfAnelasticQuantities(), self.numberOfMechanisms)
    self.Qext = OptionalDimTensor('Qext', self.Q.optName(), self.Q.optSize(), self.Q.optPos(), self._qShapeExtended, alignStride=True)
    self.Qane = OptionalDimTensor('Qane', self.Q.optName(), self.Q.optSize(), self.Q.optPos(), self._qShapeAnelastic, alignStride=True)
    self.Iane = OptionalDimTensor('Iane', self.Q.optName(), self.Q.optSize(), self.Q.optPos(), self._qShapeAnelastic, alignStride=True)

    self.E = Tensor('E', (self.numberOfAnelasticQuantities(), self.numberOfMechanisms, self.numberOfQuantities()))
    self.w = Tensor('w', (self.numberOfMechanisms,))
    self.W = Tensor('W', (self.numberOfMechanisms, self.numberOfMechanisms), np.eye(self.numberOfMechanisms, dtype=bool), CSCMemoryLayout)

    selectElaSpp = np.zeros((self.numberOfExtendedQuantities(), self.numberOfQuantities()))
    selectElaSpp[0:self.numberOfQuantities(),0:self.numberOfQuantities()] = np.eye(self.numberOfQuantities())
    self.selectEla = Tensor('selectEla', (self.numberOfExtendedQuantities(), self.numberOfQuantities()), selectElaSpp, CSCMemoryLayout)

    selectAneSpp = np.zeros((self.numberOfExtendedQuantities(), self.numberOfAnelasticQuantities()))
    selectAneSpp[self.numberOfQuantities():self.numberOfExtendedQuantities(),0:self.numberOfAnelasticQuantities()] = np.eye(self.numberOfAnelasticQuantities())
    self.selectAne = Tensor('selectAne', (self.numberOfExtendedQuantities(), self.numberOfAnelasticQuantities()), selectAneSpp, CSCMemoryLayout)

    self.db.update(
      parseJSONMatrixFile('{}/nodal/nodalBoundary_matrices_{}.json'.format(matricesDir,
                                                                           self.order),
                          {},
                          alignStride=self.alignStride,
                          transpose=self.transpose,
                          namespace='nodal')
    )
Beispiel #13
0
def addKernels(generator, aderdg, matricesDir, dynamicRuptureMethod):
  if dynamicRuptureMethod == 'quadrature':
    numberOfPoints = (aderdg.order+1)**2
  elif dynamicRuptureMethod == 'cellaverage':
    numberOfPoints = int(4**math.ceil(math.log(aderdg.order*(aderdg.order+1)/2,4)))
  else:
    raise ValueError('Unknown dynamic rupture method.')

  clones = dict()

  # Load matrices
  db = parseJSONMatrixFile('{}/dr_{}_matrices_{}.json'.format(matricesDir, dynamicRuptureMethod, aderdg.order), clones, alignStride=aderdg.alignStride, transpose=aderdg.transpose)

  # Determine matrices
  # Note: This does only work because the flux does not depend on the mechanisms in the case of viscoelastic attenuation
  godShape = (aderdg.numberOfQuantities(), aderdg.numberOfQuantities())
  godunovMatrix = Tensor('godunovMatrix', godShape)
  fluxSolverShape = (aderdg.numberOfQuantities(), aderdg.numberOfExtendedQuantities())
  fluxSolver    = Tensor('fluxSolver', fluxSolverShape)
  
  gShape = (numberOfPoints, aderdg.numberOfQuantities())
  godunovState = OptionalDimTensor('godunovState', aderdg.Q.optName(), aderdg.Q.optSize(), aderdg.Q.optPos(), gShape, alignStride=True)

  generator.add('rotateGodunovStateLocal', godunovMatrix['qp'] <= aderdg.Tinv['kq'] * aderdg.QgodLocal['kp'])
  generator.add('rotateGodunovStateNeighbor', godunovMatrix['qp'] <= aderdg.Tinv['kq'] * aderdg.QgodNeighbor['kp'])

  fluxScale = Scalar('fluxScale')
  generator.add('rotateFluxMatrix', fluxSolver['qp'] <= fluxScale * aderdg.starMatrix(0)['qk'] * aderdg.T['pk'])

  def godunovStateGenerator(i,h):
    target = godunovState['kp']
    term = db.V3mTo2n[i,h][aderdg.t('kl')] * aderdg.Q['lq'] * godunovMatrix['qp']
    if h == 0:
      return target <= term
    return target <= target + term
  godunovStatePrefetch = lambda i,h: godunovState
  generator.addFamily('godunovState', simpleParameterSpace(4,4), godunovStateGenerator, godunovStatePrefetch)

  nodalFluxGenerator = lambda i,h: aderdg.extendedQTensor()['kp'] <= aderdg.extendedQTensor()['kp'] + db.V3mTo2nTWDivM[i,h][aderdg.t('kl')] * godunovState['lq'] * fluxSolver['qp']
  nodalFluxPrefetch = lambda i,h: aderdg.I
  generator.addFamily('nodalFlux', simpleParameterSpace(4,4), nodalFluxGenerator, nodalFluxPrefetch)
Beispiel #14
0
    def addTime(self, generator, targets):
        super().addTime(generator, targets)

        stiffnessValues = [
            self.db.kDivMT[d].values_as_ndarray() for d in range(3)
        ]
        fullShape = (self.numberOf3DBasisFunctions(),
                     self.numberOf3DBasisFunctions())

        qShape = (self.numberOf3DBasisFunctions(), self.numberOfQuantities())
        stpShape = (self.numberOf3DBasisFunctions(), self.numberOfQuantities(),
                    self.order)
        quantityShape = (self.numberOfQuantities(), self.numberOfQuantities())
        spaceTimePredictorRhs = OptionalDimTensor('spaceTimePredictorRhs',
                                                  self.Q.optName(),
                                                  self.Q.optSize(),
                                                  self.Q.optPos(),
                                                  stpShape,
                                                  alignStride=True)
        spaceTimePredictor = OptionalDimTensor('spaceTimePredictor',
                                               self.Q.optName(),
                                               self.Q.optSize(),
                                               self.Q.optPos(),
                                               stpShape,
                                               alignStride=True)
        testRhs = OptionalDimTensor('testRhs',
                                    self.Q.optName(),
                                    self.Q.optSize(),
                                    self.Q.optPos(),
                                    stpShape,
                                    alignStride=True)
        testLhs = OptionalDimTensor('testLhs',
                                    self.Q.optName(),
                                    self.Q.optSize(),
                                    self.Q.optPos(),
                                    stpShape,
                                    alignStride=True)
        timestep = Scalar('timestep')
        G = {10: Scalar('Gk'), 11: Scalar('Gl'), 12: Scalar('Gm')}

        ## Compute the index range for basis functions of a certain degree
        #
        # The basis functions are ordered with increasing degree, i.e. the first
        # basis function has degree 0, the next three basis functions have degree
        # 1, the next six basis functions have degree 2 and so forth.
        # This method computes the indices Bn_lower, Bn_upper, such that
        # forall Bn_lower =< i < Bn_upper: degree(phi_i) == n
        #
        # @param n The desired polynomial degree
        def modeRange(n):
            Bn_lower = choose(n - 1 + 3, 3)
            Bn_upper = choose(n + 3, 3)
            return (Bn_lower, Bn_upper)

        ## Compute a matrix, which filters out all basis function of degree n
        #
        # Compute a matrix M, such that for any DOF vector Q, M*Q only contains
        # the parts of Q, which correspond to basis functions of degree n
        #
        # @param n The desired polynomial degree
        def selectModes(n):
            Bn_1, Bn = modeRange(n)
            selectModesSpp = np.zeros(fullShape)
            selectModesSpp[Bn_1:Bn, Bn_1:Bn] = np.eye(Bn - Bn_1)
            return Tensor('selectModes({})'.format(n),
                          fullShape,
                          spp=selectModesSpp)

        ## Compute a matrix, which slices out one quantity
        #
        # @param quantityNumber The number of the quantity, which is sliced out
        def selectQuantity(quantityNumber):
            selectSpp = np.zeros(
                (self.numberOfQuantities(), self.numberOfQuantities()))
            selectSpp[quantityNumber, quantityNumber] = 1
            return Tensor('selectQuantity({})'.format(quantityNumber),
                          selectSpp.shape,
                          spp=selectSpp)

        ## Compute a matrix, which slides out one quantity from the upper triangular
        #  part of the source matrix
        #
        # Note: G = E - diag(E)
        #
        # @param quantityNumber The number of the quantity, which is sliced out
        def selectQuantityG(quantityNumber):
            selectSpp = np.zeros(
                (self.numberOfQuantities(), self.numberOfQuantities()))
            #The source matrix G only contains values at (o-4, o)
            selectSpp[quantityNumber - 4, quantityNumber] = 1
            return Tensor('selectQuantityG({})'.format(quantityNumber),
                          selectSpp.shape,
                          spp=selectSpp)

        ## Zinv(o) = $(Z - E^*_{oo} * I)^{-1}$
        #
        # @param o Index as described above
        def Zinv(o):
            return Tensor('Zinv({})'.format(o), (self.order, self.order))

        ## Submatrix of the stiffness matrix
        #
        # The stiffness matrix for derivatives in direction d, where only the
        # contribution from basis functions of degree n is considered
        #
        # @param d The direction in which derivatives are taken 0 =< d < 3
        # @param n The polynomial degree n, which is taken into account
        def kSub(d, n):
            Bn_1, Bn = modeRange(n)
            stiffnessSpp = np.zeros(fullShape)
            stiffnessSpp[:, Bn_1:Bn] = -stiffnessValues[d][:, Bn_1:Bn]
            return Tensor('kDivMTSub({},{})'.format(d, n),
                          fullShape,
                          spp=stiffnessSpp)

        kernels = list()

        kernels.append(
            spaceTimePredictorRhs['kpt'] <= self.Q['kp'] * self.db.wHat['t'])
        for n in range(self.order - 1, -1, -1):
            for o in range(self.numberOfQuantities() - 1, -1, -1):
                kernels.append(
                    spaceTimePredictor['kpt'] <= spaceTimePredictor['kpt'] +
                    selectModes(n)['kl'] * selectQuantity(o)['pq'] *
                    spaceTimePredictorRhs['lqu'] * Zinv(o)['ut'])
                #G only has one relevant non-zero entry in each iteration, so we make it a scalar
                #G[o] = E[o-4, o] * timestep
                #In addition E only has non-zero entries, if o > 10
                if o >= 10:
                    kernels.append(
                        spaceTimePredictorRhs['kpt'] <=
                        spaceTimePredictorRhs['kpt'] + G[o] *
                        selectQuantityG(o)['pv'] * selectQuantity(o)['vq'] *
                        selectModes(n)['kl'] * spaceTimePredictor['lqt'])
            if n > 0:
                derivativeSum = spaceTimePredictorRhs['kpt']
                for d in range(3):
                    derivativeSum += kSub(d, n)['kl'] * spaceTimePredictor[
                        'lqt'] * self.starMatrix(d)['qp']
            kernels.append(spaceTimePredictorRhs['kpt'] <= derivativeSum)
        kernels.append(self.I['kp'] <= timestep * spaceTimePredictor['kpt'] *
                       self.db.timeInt['t'])

        generator.add('spaceTimePredictor', kernels)

        # Test to see if the kernel actually solves the system of equations
        # This part is not used in the time kernel, but for unit testing
        deltaSppLarge = np.eye(self.numberOfQuantities())
        deltaLarge = Tensor('deltaLarge',
                            deltaSppLarge.shape,
                            spp=deltaSppLarge)
        deltaSppSmall = np.eye(self.order)
        deltaSmall = Tensor('deltaSmall',
                            deltaSppSmall.shape,
                            spp=deltaSppSmall)
        minus = Scalar('minus')

        lhs = deltaLarge['oq'] * self.db.Z['uk'] * spaceTimePredictor['lqk']
        lhs += minus * self.sourceMatrix(
        )['qo'] * deltaSmall['uk'] * spaceTimePredictor['lqk']
        generator.add('stpTestLhs', testLhs['lou'] <= lhs)

        rhs = self.Q['lo'] * self.db.wHat['u']
        for d in range(3):
            rhs += minus * self.starMatrix(
                d)['qo'] * self.db.kDivMT[d]['lm'] * spaceTimePredictor['mqu']
        generator.add('stpTestRhs', testRhs['lou'] <= rhs)
Beispiel #15
0
    def __init__(self, order, multipleSimulations, matricesDir):
        self.order = order

        self.alignStride = lambda name: True
        if multipleSimulations > 1:
            self.alignStride = lambda name: name.startswith('fP')
        transpose = multipleSimulations > 1
        self.transpose = lambda name: transpose
        self.t = (lambda x: x[::-1]) if transpose else (lambda x: x)

        self.db = parseXMLMatrixFile('{}/matrices_{}.xml'.format(
            matricesDir, self.numberOf3DBasisFunctions()),
                                     transpose=self.transpose,
                                     alignStride=self.alignStride)
        clonesQP = {'v': ['evalAtQP'], 'vInv': ['projectQP']}
        self.db.update(
            parseXMLMatrixFile('{}/plasticity_ip_matrices_{}.xml'.format(
                matricesDir, order),
                               clonesQP,
                               transpose=self.transpose,
                               alignStride=self.alignStride))
        self.db.update(
            parseJSONMatrixFile(
                '{}/sampling_directions.json'.format(matricesDir)))
        self.db.update(
            parseJSONMatrixFile('{}/mass_{}.json'.format(matricesDir, order)))

        qShape = (self.numberOf3DBasisFunctions(), self.numberOfQuantities())
        self.Q = OptionalDimTensor('Q',
                                   's',
                                   multipleSimulations,
                                   0,
                                   qShape,
                                   alignStride=True)
        self.I = OptionalDimTensor('I',
                                   's',
                                   multipleSimulations,
                                   0,
                                   qShape,
                                   alignStride=True)

        Aplusminus_spp = self.flux_solver_spp()
        self.AplusT = Tensor('AplusT',
                             Aplusminus_spp.shape,
                             spp=Aplusminus_spp)
        self.AminusT = Tensor('AminusT',
                              Aplusminus_spp.shape,
                              spp=Aplusminus_spp)
        Tshape = (self.numberOfExtendedQuantities(),
                  self.numberOfExtendedQuantities())
        trans_spp = self.transformation_spp()
        self.T = Tensor('T', trans_spp.shape, spp=trans_spp)
        trans_inv_spp = self.transformation_inv_spp()
        self.Tinv = Tensor('Tinv', trans_inv_spp.shape, spp=trans_inv_spp)
        godunov_spp = self.godunov_spp()
        self.QgodLocal = Tensor('QgodLocal',
                                godunov_spp.shape,
                                spp=godunov_spp)
        self.QgodNeighbor = Tensor('QgodNeighbor',
                                   godunov_spp.shape,
                                   spp=godunov_spp)

        self.oneSimToMultSim = Tensor('oneSimToMultSim', (self.Q.optSize(), ),
                                      spp={(i, ): '1.0'
                                           for i in range(self.Q.optSize())})

        self.db.update(
            parseJSONMatrixFile(
                '{}/nodal/nodalBoundary_matrices_{}.json'.format(
                    matricesDir, self.order), {},
                alignStride=self.alignStride,
                transpose=self.transpose,
                namespace='nodal'))

        self.INodal = OptionalDimTensor(
            'INodal',
            's',
            False,  #multipleSimulations,
            0,
            (self.numberOf2DBasisFunctions(), self.numberOfQuantities()),
            alignStride=True)

        project2nFaceTo3m = tensor_collection_from_constant_expression(
            base_name='project2nFaceTo3m',
            expressions=lambda i: self.db.rDivM[i]['jk'] * self.db.V2nTo2m['kl'
                                                                           ],
            group_indices=range(4),
            target_indices='jl')

        self.db.update(project2nFaceTo3m)
Beispiel #16
0
class ADERDGBase(ABC):
    def __init__(self, order, multipleSimulations, matricesDir):
        self.order = order

        self.alignStride = lambda name: True
        if multipleSimulations > 1:
            self.alignStride = lambda name: name.startswith('fP')
        transpose = multipleSimulations > 1
        self.transpose = lambda name: transpose
        self.t = (lambda x: x[::-1]) if transpose else (lambda x: x)

        self.db = parseXMLMatrixFile('{}/matrices_{}.xml'.format(
            matricesDir, self.numberOf3DBasisFunctions()),
                                     transpose=self.transpose,
                                     alignStride=self.alignStride)
        clonesQP = {'v': ['evalAtQP'], 'vInv': ['projectQP']}
        self.db.update(
            parseXMLMatrixFile('{}/plasticity_ip_matrices_{}.xml'.format(
                matricesDir, order),
                               clonesQP,
                               transpose=self.transpose,
                               alignStride=self.alignStride))
        self.db.update(
            parseJSONMatrixFile(
                '{}/sampling_directions.json'.format(matricesDir)))
        self.db.update(
            parseJSONMatrixFile('{}/mass_{}.json'.format(matricesDir, order)))

        qShape = (self.numberOf3DBasisFunctions(), self.numberOfQuantities())
        self.Q = OptionalDimTensor('Q',
                                   's',
                                   multipleSimulations,
                                   0,
                                   qShape,
                                   alignStride=True)
        self.I = OptionalDimTensor('I',
                                   's',
                                   multipleSimulations,
                                   0,
                                   qShape,
                                   alignStride=True)

        Aplusminus_spp = self.flux_solver_spp()
        self.AplusT = Tensor('AplusT',
                             Aplusminus_spp.shape,
                             spp=Aplusminus_spp)
        self.AminusT = Tensor('AminusT',
                              Aplusminus_spp.shape,
                              spp=Aplusminus_spp)
        Tshape = (self.numberOfExtendedQuantities(),
                  self.numberOfExtendedQuantities())
        trans_spp = self.transformation_spp()
        self.T = Tensor('T', trans_spp.shape, spp=trans_spp)
        trans_inv_spp = self.transformation_inv_spp()
        self.Tinv = Tensor('Tinv', trans_inv_spp.shape, spp=trans_inv_spp)
        godunov_spp = self.godunov_spp()
        self.QgodLocal = Tensor('QgodLocal',
                                godunov_spp.shape,
                                spp=godunov_spp)
        self.QgodNeighbor = Tensor('QgodNeighbor',
                                   godunov_spp.shape,
                                   spp=godunov_spp)

        self.oneSimToMultSim = Tensor('oneSimToMultSim', (self.Q.optSize(), ),
                                      spp={(i, ): '1.0'
                                           for i in range(self.Q.optSize())})

        self.db.update(
            parseJSONMatrixFile(
                '{}/nodal/nodalBoundary_matrices_{}.json'.format(
                    matricesDir, self.order), {},
                alignStride=self.alignStride,
                transpose=self.transpose,
                namespace='nodal'))

        self.INodal = OptionalDimTensor(
            'INodal',
            's',
            False,  #multipleSimulations,
            0,
            (self.numberOf2DBasisFunctions(), self.numberOfQuantities()),
            alignStride=True)

        project2nFaceTo3m = tensor_collection_from_constant_expression(
            base_name='project2nFaceTo3m',
            expressions=lambda i: self.db.rDivM[i]['jk'] * self.db.V2nTo2m['kl'
                                                                           ],
            group_indices=range(4),
            target_indices='jl')

        self.db.update(project2nFaceTo3m)

    def numberOf2DBasisFunctions(self):
        return self.order * (self.order + 1) // 2

    def numberOf3DBasisFunctions(self):
        return self.order * (self.order + 1) * (self.order + 2) // 6

    def numberOf3DQuadraturePoints(self):
        return (self.order + 1)**3

    def godunov_spp(self):
        shape = (self.numberOfQuantities(), self.numberOfQuantities())
        return np.ones(shape, dtype=bool)

    def flux_solver_spp(self):
        shape = (self.numberOfQuantities(), self.numberOfExtendedQuantities())
        return np.ones(shape, dtype=bool)

    def transformation_spp(self):
        shape = (self.numberOfExtendedQuantities(),
                 self.numberOfExtendedQuantities())
        return np.ones(shape, dtype=bool)

    def transformation_inv_spp(self):
        return self.godunov_spp()

    @abstractmethod
    def numberOfQuantities(self):
        pass

    @abstractmethod
    def numberOfExtendedQuantities(self):
        pass

    @abstractmethod
    def extendedQTensor(self):
        pass

    @abstractmethod
    def starMatrix(self, dim):
        pass

    def addInit(self, generator):
        fluxScale = Scalar('fluxScale')
        computeFluxSolverLocal = self.AplusT['ij'] <= fluxScale * self.Tinv[
            'ki'] * self.QgodLocal['kq'] * self.starMatrix(
                0)['ql'] * self.T['jl']
        generator.add('computeFluxSolverLocal', computeFluxSolverLocal)

        computeFluxSolverNeighbor = self.AminusT[
            'ij'] <= fluxScale * self.Tinv['ki'] * self.QgodNeighbor[
                'kq'] * self.starMatrix(0)['ql'] * self.T['jl']
        generator.add('computeFluxSolverNeighbor', computeFluxSolverNeighbor)

        QFortran = Tensor(
            'QFortran',
            (self.numberOf3DBasisFunctions(), self.numberOfQuantities()))
        multSimToFirstSim = Tensor('multSimToFirstSim', (self.Q.optSize(), ),
                                   spp={(0, ): '1.0'})
        if self.Q.hasOptDim():
            copyQToQFortran = QFortran[
                'kp'] <= self.Q['kp'] * multSimToFirstSim['s']
        else:
            copyQToQFortran = QFortran['kp'] <= self.Q['kp']

        generator.add('copyQToQFortran', copyQToQFortran)

        stiffnessTensor = Tensor('stiffnessTensor', (3, 3, 3, 3))
        direction = Tensor('direction', (3, ))
        christoffel = Tensor('christoffel', (3, 3))

        computeChristoffel = christoffel[
            'ik'] <= stiffnessTensor['ijkl'] * direction['j'] * direction['l']
        generator.add('computeChristoffel', computeChristoffel)

    @abstractmethod
    def addLocal(self, generator, targets):
        pass

    @abstractmethod
    def addNeighbor(self, generator, targets):
        pass

    @abstractmethod
    def addTime(self, generator, targets):
        pass

    def add_include_tensors(self, include_tensors):
        include_tensors.add(self.db.samplingDirections)
        include_tensors.add(self.db.M2inv)
Beispiel #17
0
def addKernels(generator, aderdg, matricesDir, PlasticityMethod, targets):
    # Load matrices
    db = parseXMLMatrixFile('{}/plasticity_{}_matrices_{}.xml'.format(
        matricesDir, PlasticityMethod, aderdg.order),
                            clones=dict(),
                            alignStride=aderdg.alignStride)
    numberOfNodes = aderdg.t(db.v.shape())[0]

    numberOf3DBasisFunctions = aderdg.numberOf3DBasisFunctions()
    sShape = (numberOf3DBasisFunctions, 6)
    QStress = OptionalDimTensor('QStress',
                                aderdg.Q.optName(),
                                aderdg.Q.optSize(),
                                aderdg.Q.optPos(),
                                sShape,
                                alignStride=True)

    sShape_eta = (numberOf3DBasisFunctions, )
    QEtaModal = OptionalDimTensor('QEtaModal',
                                  aderdg.Q.optName(),
                                  aderdg.Q.optSize(),
                                  aderdg.Q.optPos(),
                                  sShape_eta,
                                  alignStride=True)

    initialLoading = Tensor('initialLoading', (6, ))

    replicateIniLShape = (numberOfNodes, )
    replicateIniLSpp = np.ones(
        aderdg.Q.insertOptDim(replicateIniLShape, (aderdg.Q.optSize(), )))
    replicateInitialLoading = OptionalDimTensor('replicateInitialLoading',
                                                aderdg.Q.optName(),
                                                aderdg.Q.optSize(),
                                                aderdg.Q.optPos(),
                                                replicateIniLShape,
                                                spp=replicateIniLSpp,
                                                alignStride=True)

    iShape = (numberOfNodes, 6)
    QStressNodal = OptionalDimTensor('QStressNodal',
                                     aderdg.Q.optName(),
                                     aderdg.Q.optSize(),
                                     aderdg.Q.optPos(),
                                     iShape,
                                     alignStride=True)
    meanStress = OptionalDimTensor('meanStress',
                                   aderdg.Q.optName(),
                                   aderdg.Q.optSize(),
                                   aderdg.Q.optPos(), (numberOfNodes, ),
                                   alignStride=True)
    secondInvariant = OptionalDimTensor('secondInvariant',
                                        aderdg.Q.optName(),
                                        aderdg.Q.optSize(),
                                        aderdg.Q.optPos(), (numberOfNodes, ),
                                        alignStride=True)

    QEtaNodal = OptionalDimTensor('QEtaNodal',
                                  aderdg.Q.optName(),
                                  aderdg.Q.optSize(),
                                  aderdg.Q.optPos(), (numberOfNodes, ),
                                  alignStride=True)

    selectBulkAverage = Tensor('selectBulkAverage', (6, ),
                               spp={(i, ): str(1.0 / 3.0)
                                    for i in range(3)})
    selectBulkNegative = Tensor('selectBulkNegative', (6, ),
                                spp={(i, ): '-1.0'
                                     for i in range(3)})
    weightSecondInvariant = Tensor('weightSecondInvariant', (6, ),
                                   spp={(i, ):
                                        str(1.0 / 2.0) if i < 3 else '1.0'
                                        for i in range(6)})
    yieldFactor = Tensor('yieldFactor', (numberOfNodes, ))

    generator.add(
        'plConvertToNodal',
        QStressNodal['kp'] <= db.v[aderdg.t('kl')] * QStress['lp'] +
        replicateInitialLoading['k'] * initialLoading['p'])

    for target in targets:
        name_prefix = generate_kernel_name_prefix(target)
        generator.add(
            name=f'{name_prefix}plConvertToNodalNoLoading',
            ast=QStressNodal['kp'] <= db.v[aderdg.t('kl')] * QStress['lp'],
            target=target)

        generator.add(
            name=f'{name_prefix}plConvertEtaModal2Nodal',
            ast=QEtaNodal['k'] <= db.v[aderdg.t('kl')] * QEtaModal['l'],
            target=target)

        generator.add(
            name=f'{name_prefix}plConvertEtaNodal2Modal',
            ast=QEtaModal['k'] <= db.vInv[aderdg.t('kl')] * QEtaNodal['l'],
            target=target)

    generator.add(
        'plComputeMean',
        meanStress['k'] <= QStressNodal['kq'] * selectBulkAverage['q'])
    generator.add(
        'plSubtractMean', QStressNodal['kp'] <=
        QStressNodal['kp'] + meanStress['k'] * selectBulkNegative['p'])
    generator.add(
        'plComputeSecondInvariant', secondInvariant['k'] <=
        QStressNodal['kq'] * QStressNodal['kq'] * weightSecondInvariant['q'])
    generator.add(
        'plAdjustStresses', QStress['kp'] <= QStress['kp'] +
        db.vInv[aderdg.t('kl')] * QStressNodal['lp'] * yieldFactor['l'])

    gpu_target = 'gpu'
    if gpu_target in targets:
        name_prefix = generate_kernel_name_prefix(gpu_target)

        # suffix `M` stands for `Matrix`
        replicateInitialLoadingM = Tensor(name='replicateInitialLoadingM',
                                          shape=(numberOfNodes, 1),
                                          spp=np.ones((numberOfNodes, 1)))
        initialLoadingM = Tensor('initialLoadingM', (1, 6))

        # Note: the last term was change on purpose because
        # GemmForge doesn't currently support tensor product operation
        convert_to_nodal = QStressNodal['kp'] <= \
                           db.v[aderdg.t('kl')] * QStress['lp'] + \
                           replicateInitialLoadingM['km'] * initialLoadingM['mp']

        generator.add(name=f'{name_prefix}plConvertToNodal',
                      ast=convert_to_nodal,
                      target=gpu_target)

        generator.add(f'{name_prefix}plConvertToModal',
                      QStress['kp'] <= QStress['kp'] +
                      db.vInv[aderdg.t('kl')] * QStressNodal['lp'],
                      target=gpu_target)
Beispiel #18
0
def addKernels(generator, aderdg, include_tensors, matricesDir, dynamicRuptureMethod):
    easi_ident_map = np.stack([np.eye(aderdg.numberOfQuantities())] * aderdg.numberOf2DBasisFunctions(), axis=2)
    assert(easi_ident_map.shape ==
           (aderdg.numberOfQuantities(), aderdg.numberOfQuantities(), aderdg.numberOf2DBasisFunctions()))
    easi_ident_map = Tensor('easiIdentMap',
                            easi_ident_map.shape,
                            easi_ident_map,
                            alignStride=False)
    easi_boundary_constant = Tensor('easiBoundaryConstant',
                                    (aderdg.numberOfQuantities(), aderdg.numberOf2DBasisFunctions()),
                                    alignStride=False)
    easi_boundary_map = Tensor('easiBoundaryMap',
                               (aderdg.numberOfQuantities(), aderdg.numberOfQuantities(), aderdg.numberOf2DBasisFunctions(),),
                               alignStride=False)
    create_easi_boundary_ghost_cells = (
            aderdg.INodal['la'] <= easi_boundary_map['abl'] * aderdg.INodal['lb'] + easi_ident_map['abl'] * easi_boundary_constant['bl']
    )
    generator.add('createEasiBoundaryGhostCells', create_easi_boundary_ghost_cells)

    projectToNodalBoundary = lambda j: aderdg.INodal['kp'] <= aderdg.db.V3mTo2nFace[j]['km'] * aderdg.I['mp']

    generator.addFamily('projectToNodalBoundary',
                        simpleParameterSpace(4),
                        projectToNodalBoundary)

    projectToNodalBoundaryRotated = lambda j: aderdg.INodal['kp'] <= aderdg.db.V3mTo2nFace[j]['kl'] \
                                              * aderdg.I['lm'] \
                                              * aderdg.Tinv['pm']

    generator.addFamily('projectToNodalBoundaryRotated',
                        simpleParameterSpace(4),
                        projectToNodalBoundaryRotated)

    # To be used as Tinv in flux solver - this way we can save two rotations for
    # Dirichlet boundary, as ghost cell dofs are already rotated
    identity_rotation = np.double(aderdg.transformation_spp())
    identity_rotation[0:9, 0:9] = np.eye(9)
    identity_rotation = Tensor('identityT',
                               aderdg.transformation_spp().shape,
                               identity_rotation,
                               )
    include_tensors.add(identity_rotation)

    project2nFaceTo3m = tensor_collection_from_constant_expression(
        base_name='project2nFaceTo3m',
        expressions=lambda i: aderdg.db.rDivM[i]['jk'] * aderdg.db.V2nTo2m['kl'],
        group_indices=range(4),
        target_indices='jl')

    aderdg.db.update(project2nFaceTo3m)

    selectZDisplacementFromQuantities = np.zeros(aderdg.numberOfQuantities())
    selectZDisplacementFromQuantities[8] = 1
    selectZDisplacementFromQuantities= Tensor('selectZDisplacementFromQuantities',
                                              selectZDisplacementFromQuantities.shape,
                                              selectZDisplacementFromQuantities,
                                              )

    selectZDisplacementFromDisplacements = np.zeros(3)
    selectZDisplacementFromDisplacements[2] = 1
    selectZDisplacementFromDisplacements = Tensor('selectZDisplacementFromDisplacements',
                                                  selectZDisplacementFromDisplacements.shape,
                                                  selectZDisplacementFromDisplacements,
                                                  )

    aderdg.INodalDisplacement = OptionalDimTensor('INodalDisplacement',
                                                aderdg.Q.optName(),
                                                aderdg.Q.optSize(),
                                                aderdg.Q.optPos(),
                                                (aderdg.numberOf2DBasisFunctions(),),
                                                alignStride=True)

    displacement = OptionalDimTensor('displacement',
                                     aderdg.Q.optName(),
                                     aderdg.Q.optSize(),
                                     aderdg.Q.optPos(),
                                     (aderdg.numberOf3DBasisFunctions(), 3),
                                     alignStride=True)

    dt = Scalar('dt')
    displacementAvgNodal = lambda side: aderdg.INodalDisplacement['i'] <= \
                                        aderdg.db.V3mTo2nFace[side]['ij'] * aderdg.I['jk'] * selectZDisplacementFromQuantities['k'] \
                                        + dt * aderdg.db.V3mTo2nFace[side]['ij'] * displacement['jk'] * selectZDisplacementFromDisplacements['k']

    generator.addFamily('displacementAvgNodal',
                        simpleParameterSpace(4),
                        displacementAvgNodal)

    aderdg.INodalUpdate = OptionalDimTensor('INodalUpdate',
                                          aderdg.INodal.optName(),
                                          aderdg.INodal.optSize(),
                                          aderdg.INodal.optPos(),
                                          (aderdg.numberOf2DBasisFunctions(), aderdg.numberOfQuantities()),
                                          alignStride=True)

    factor = Scalar('factor')
    updateINodal = aderdg.INodal['kp'] <= aderdg.INodal['kp'] + factor * aderdg.INodalUpdate['kp']
    generator.add('updateINodal', updateINodal)
Beispiel #19
0
def addKernels(generator, aderdg, matricesDir, dynamicRuptureMethod):
    if dynamicRuptureMethod == 'quadrature':
        numberOfPoints = (aderdg.order + 1)**2
    elif dynamicRuptureMethod == 'cellaverage':
        numberOfPoints = int(4**math.ceil(
            math.log(aderdg.order * (aderdg.order + 1) / 2, 4)))
    else:
        raise ValueError('Unknown dynamic rupture method.')

    clones = dict()

    # Load matrices
    db = parseJSONMatrixFile('{}/dr_{}_matrices_{}.json'.format(
        matricesDir, dynamicRuptureMethod, aderdg.order),
                             clones,
                             alignStride=aderdg.alignStride,
                             transpose=aderdg.transpose)
    db.update(
        parseJSONMatrixFile('{}/resample_{}.json'.format(
            matricesDir, aderdg.order)))

    # Determine matrices
    # Note: This does only work because the flux does not depend on the mechanisms in the case of viscoelastic attenuation
    trans_inv_spp_T = aderdg.transformation_inv_spp().transpose()
    TinvT = Tensor('TinvT', trans_inv_spp_T.shape, spp=trans_inv_spp_T)
    flux_solver_spp = aderdg.flux_solver_spp()
    fluxSolver = Tensor('fluxSolver',
                        flux_solver_spp.shape,
                        spp=flux_solver_spp)

    gShape = (numberOfPoints, aderdg.numberOfQuantities())
    QInterpolated = OptionalDimTensor('QInterpolated',
                                      aderdg.Q.optName(),
                                      aderdg.Q.optSize(),
                                      aderdg.Q.optPos(),
                                      gShape,
                                      alignStride=True)

    generator.add('transposeTinv', TinvT['ij'] <= aderdg.Tinv['ji'])

    fluxScale = Scalar('fluxScale')
    generator.add(
        'rotateFluxMatrix', fluxSolver['qp'] <=
        fluxScale * aderdg.starMatrix(0)['qk'] * aderdg.T['pk'])

    def interpolateQGenerator(i, h):
        return QInterpolated['kp'] <= db.V3mTo2n[i, h][aderdg.t(
            'kl')] * aderdg.Q['lq'] * TinvT['qp']

    interpolateQPrefetch = lambda i, h: QInterpolated
    generator.addFamily('evaluateAndRotateQAtInterpolationPoints',
                        simpleParameterSpace(4, 4), interpolateQGenerator,
                        interpolateQPrefetch)

    nodalFluxGenerator = lambda i, h: aderdg.extendedQTensor()[
        'kp'] <= aderdg.extendedQTensor()['kp'] + db.V3mTo2nTWDivM[i, h][
            aderdg.t('kl')] * QInterpolated['lq'] * fluxSolver['qp']
    nodalFluxPrefetch = lambda i, h: aderdg.I
    generator.addFamily('nodalFlux', simpleParameterSpace(4, 4),
                        nodalFluxGenerator, nodalFluxPrefetch)

    return {db.resample}
def addKernels(generator, aderdg, include_tensors, targets):
    maxDepth = 3

    numberOf3DBasisFunctions = aderdg.numberOf3DBasisFunctions()
    numberOf2DBasisFunctions = aderdg.numberOf2DBasisFunctions()
    numberOfQuantities = aderdg.numberOfQuantities()

    selectVelocitySpp = np.zeros((numberOfQuantities, 3))
    selectVelocitySpp[6:9, 0:3] = np.eye(3)
    selectVelocity = Tensor('selectVelocity', selectVelocitySpp.shape,
                            selectVelocitySpp, CSCMemoryLayout)

    faceDisplacement = OptionalDimTensor('faceDisplacement',
                                         aderdg.Q.optName(),
                                         aderdg.Q.optSize(),
                                         aderdg.Q.optPos(),
                                         (numberOf2DBasisFunctions, 3),
                                         alignStride=True)
    averageNormalDisplacement = OptionalDimTensor('averageNormalDisplacement',
                                                  aderdg.Q.optName(),
                                                  aderdg.Q.optSize(),
                                                  aderdg.Q.optPos(),
                                                  (numberOf2DBasisFunctions, ),
                                                  alignStride=True)

    include_tensors.add(averageNormalDisplacement)

    subTriangleDofs = [
        OptionalDimTensor('subTriangleDofs({})'.format(depth),
                          aderdg.Q.optName(),
                          aderdg.Q.optSize(),
                          aderdg.Q.optPos(), (4**depth, 3),
                          alignStride=True) for depth in range(maxDepth + 1)
    ]
    subTriangleProjection = [
        Tensor('subTriangleProjection({})'.format(depth),
               (4**depth, numberOf3DBasisFunctions),
               alignStride=True) for depth in range(maxDepth + 1)
    ]
    subTriangleProjectionFromFace = [
        Tensor('subTriangleProjectionFromFace({})'.format(depth),
               (4**depth, numberOf2DBasisFunctions),
               alignStride=True) for depth in range(maxDepth + 1)
    ]

    displacementRotationMatrix = Tensor('displacementRotationMatrix', (3, 3),
                                        alignStride=True)
    subTriangleDisplacement = lambda depth: subTriangleDofs[depth]['kp'] <= \
                                            subTriangleProjectionFromFace[depth]['kl'] * aderdg.db.MV2nTo2m['lm'] * faceDisplacement['mp']
    subTriangleVelocity = lambda depth: subTriangleDofs[depth][
        'kp'] <= subTriangleProjection[depth]['kl'] * aderdg.Q[
            'lq'] * selectVelocity['qp']

    generator.addFamily('subTriangleDisplacement',
                        simpleParameterSpace(maxDepth + 1),
                        subTriangleDisplacement)
    generator.addFamily('subTriangleVelocity',
                        simpleParameterSpace(maxDepth + 1),
                        subTriangleVelocity)

    rotatedFaceDisplacement = OptionalDimTensor('rotatedFaceDisplacement',
                                                aderdg.Q.optName(),
                                                aderdg.Q.optSize(),
                                                aderdg.Q.optPos(),
                                                (numberOf2DBasisFunctions, 3),
                                                alignStride=True)
    generator.add(
        'rotateFaceDisplacement', rotatedFaceDisplacement["mp"] <=
        faceDisplacement['mn'] * displacementRotationMatrix['pn'])

    addVelocity = lambda f: faceDisplacement['kp'] <= faceDisplacement['kp'] \
                            + aderdg.db.V3mTo2nFace[f]['kl'] * aderdg.I['lq'] * selectVelocity['qp']
    generator.addFamily('addVelocity', simpleParameterSpace(4), addVelocity)

    if 'gpu' in targets:
        name_prefix = generate_kernel_name_prefix(target='gpu')

        integratedVelocities = OptionalDimTensor('integratedVelocities',
                                                 aderdg.I.optName(),
                                                 aderdg.I.optSize(),
                                                 aderdg.I.optPos(),
                                                 (numberOf3DBasisFunctions, 3),
                                                 alignStride=True)

        addVelocity = lambda f: faceDisplacement['kp'] <= faceDisplacement['kp'] \
                                + aderdg.db.V3mTo2nFace[f]['kl'] * integratedVelocities['lp']

        generator.addFamily(f'{name_prefix}addVelocity',
                            simpleParameterSpace(4),
                            addVelocity,
                            target='gpu')
Beispiel #21
0
class ADERDGBase(ABC):
    def __init__(self, order, multipleSimulations, matricesDir):
        self.order = order

        self.alignStride = lambda name: True
        if multipleSimulations > 1:
            self.alignStride = lambda name: name.startswith('fP')
        transpose = multipleSimulations > 1
        self.transpose = lambda name: transpose
        self.t = (lambda x: x[::-1]) if transpose else (lambda x: x)

        self.db = parseXMLMatrixFile('{}/matrices_{}.xml'.format(
            matricesDir, self.numberOf3DBasisFunctions()),
                                     transpose=self.transpose,
                                     alignStride=self.alignStride)
        clonesQP = {'v': ['evalAtQP'], 'vInv': ['projectQP']}
        self.db.update(
            parseXMLMatrixFile('{}/plasticity_ip_matrices_{}.xml'.format(
                matricesDir, order),
                               clonesQP,
                               transpose=self.transpose,
                               alignStride=self.alignStride))

        qShape = (self.numberOf3DBasisFunctions(), self.numberOfQuantities())
        self.Q = OptionalDimTensor('Q',
                                   's',
                                   multipleSimulations,
                                   0,
                                   qShape,
                                   alignStride=True)
        self.I = OptionalDimTensor('I',
                                   's',
                                   multipleSimulations,
                                   0,
                                   qShape,
                                   alignStride=True)

        Aplusminus_spp = self.flux_solver_spp()
        self.AplusT = Tensor('AplusT',
                             Aplusminus_spp.shape,
                             spp=Aplusminus_spp)
        self.AminusT = Tensor('AminusT',
                              Aplusminus_spp.shape,
                              spp=Aplusminus_spp)
        Tshape = (self.numberOfExtendedQuantities(),
                  self.numberOfExtendedQuantities())
        trans_spp = self.transformation_spp()
        self.T = Tensor('T', trans_spp.shape, spp=trans_spp)
        trans_inv_spp = self.transformation_inv_spp()
        self.Tinv = Tensor('Tinv', trans_inv_spp.shape, spp=trans_inv_spp)
        godunov_spp = self.godunov_spp()
        self.QgodLocal = Tensor('QgodLocal',
                                godunov_spp.shape,
                                spp=godunov_spp)
        self.QgodNeighbor = Tensor('QgodNeighbor',
                                   godunov_spp.shape,
                                   spp=godunov_spp)

        self.oneSimToMultSim = Tensor('oneSimToMultSim', (self.Q.optSize(), ),
                                      spp={(i, ): '1.0'
                                           for i in range(self.Q.optSize())})

    def numberOf2DBasisFunctions(self):
        return self.order * (self.order + 1) // 2

    def numberOf3DBasisFunctions(self):
        return self.order * (self.order + 1) * (self.order + 2) // 6

    def numberOf3DQuadraturePoints(self):
        return (self.order + 1)**3

    def godunov_spp(self):
        shape = (self.numberOfQuantities(), self.numberOfQuantities())
        return np.ones(shape, dtype=bool)

    def flux_solver_spp(self):
        shape = (self.numberOfQuantities(), self.numberOfExtendedQuantities())
        return np.ones(shape, dtype=bool)

    def transformation_spp(self):
        shape = (self.numberOfExtendedQuantities(),
                 self.numberOfExtendedQuantities())
        return np.ones(shape, dtype=bool)

    def transformation_inv_spp(self):
        return self.godunov_spp()

    @abstractmethod
    def numberOfQuantities(self):
        pass

    @abstractmethod
    def numberOfExtendedQuantities(self):
        pass

    @abstractmethod
    def extendedQTensor(self):
        pass

    @abstractmethod
    def starMatrix(self, dim):
        pass

    def addInit(self, generator):
        fluxScale = Scalar('fluxScale')
        computeFluxSolverLocal = self.AplusT['ij'] <= fluxScale * self.Tinv[
            'ki'] * self.QgodLocal['kq'] * self.starMatrix(
                0)['ql'] * self.T['jl']
        generator.add('computeFluxSolverLocal', computeFluxSolverLocal)

        computeFluxSolverNeighbor = self.AminusT[
            'ij'] <= fluxScale * self.Tinv['ki'] * self.QgodNeighbor[
                'kq'] * self.starMatrix(0)['ql'] * self.T['jl']
        generator.add('computeFluxSolverNeighbor', computeFluxSolverNeighbor)

        QFortran = Tensor(
            'QFortran',
            (self.numberOf3DBasisFunctions(), self.numberOfQuantities()))
        multSimToFirstSim = Tensor('multSimToFirstSim', (self.Q.optSize(), ),
                                   spp={(0, ): '1.0'})
        if self.Q.hasOptDim():
            copyQToQFortran = QFortran[
                'kp'] <= self.Q['kp'] * multSimToFirstSim['s']
        else:
            copyQToQFortran = QFortran['kp'] <= self.Q['kp']

        generator.add('copyQToQFortran', copyQToQFortran)

    @abstractmethod
    def addLocal(self, generator):
        pass

    @abstractmethod
    def addNeighbor(self, generator):
        pass

    @abstractmethod
    def addTime(self, generator):
        pass
Beispiel #22
0
class ADERDGBase(ABC):
  def __init__(self, order, multipleSimulations, matricesDir):
    self.order = order

    self.alignStride = lambda name: True
    if multipleSimulations > 1:
      self.alignStride = lambda name: name.startswith('fP')
    transpose = multipleSimulations > 1
    self.transpose = lambda name: transpose
    self.t = (lambda x: x[::-1]) if transpose else (lambda x: x)

    self.db = parseXMLMatrixFile('{}/matrices_{}.xml'.format(matricesDir, self.numberOf3DBasisFunctions()), transpose=self.transpose, alignStride=self.alignStride)
    clonesQP = {
      'v': [ 'evalAtQP' ],
      'vInv': [ 'projectQP' ]
    }
    self.db.update( parseXMLMatrixFile('{}/plasticity_ip_matrices_{}.xml'.format(matricesDir, order), clonesQP, transpose=self.transpose, alignStride=self.alignStride))

    qShape = (self.numberOf3DBasisFunctions(), self.numberOfQuantities())
    self.Q = OptionalDimTensor('Q', 's', multipleSimulations, 0, qShape, alignStride=True)
    self.I = OptionalDimTensor('I', 's', multipleSimulations, 0, qShape, alignStride=True)

    Ashape = (self.numberOfQuantities(), self.numberOfExtendedQuantities())
    self.AplusT = Tensor('AplusT', Ashape)
    self.AminusT = Tensor('AminusT', Ashape)
    Tshape = (self.numberOfExtendedQuantities(), self.numberOfExtendedQuantities())
    self.T = Tensor('T', Tshape)
    QgodShape = (self.numberOfQuantities(), self.numberOfQuantities())
    self.Tinv = Tensor('Tinv', QgodShape)
    self.QgodLocal = Tensor('QgodLocal', QgodShape)
    self.QgodNeighbor = Tensor('QgodNeighbor', QgodShape)

    self.oneSimToMultSim = Tensor('oneSimToMultSim', (self.Q.optSize(),), spp={(i,): '1.0' for i in range(self.Q.optSize())})

  def numberOf2DBasisFunctions(self):
    return self.order*(self.order+1)//2

  def numberOf3DBasisFunctions(self):
    return self.order*(self.order+1)*(self.order+2)//6

  def numberOf3DQuadraturePoints(self):
    return (self.order+1)**3

  @abstractmethod
  def numberOfQuantities(self):
    pass

  @abstractmethod
  def numberOfExtendedQuantities(self):
    pass

  @abstractmethod
  def extendedQTensor(self):
    pass

  @abstractmethod
  def starMatrix(self, dim):
    pass

  def addInit(self, generator):
    fluxScale = Scalar('fluxScale')
    computeFluxSolverLocal = self.AplusT['ij'] <= fluxScale * self.Tinv['ki'] * self.QgodLocal['kq'] * self.db.star[0]['ql'] * self.T['jl']
    generator.add('computeFluxSolverLocal', computeFluxSolverLocal)

    computeFluxSolverNeighbor = self.AminusT['ij'] <= fluxScale * self.Tinv['ki'] * self.QgodNeighbor['kq'] * self.db.star[0]['ql'] * self.T['jl']
    generator.add('computeFluxSolverNeighbor', computeFluxSolverNeighbor)

    QFortran = Tensor('QFortran', (self.numberOf3DBasisFunctions(), self.numberOfQuantities()))
    multSimToFirstSim = Tensor('multSimToFirstSim', (self.Q.optSize(),), spp={(0,): '1.0'})
    if self.Q.hasOptDim():
      copyQToQFortran = QFortran['kp'] <= self.Q['kp'] * multSimToFirstSim['s']
    else:
      copyQToQFortran = QFortran['kp'] <= self.Q['kp']

    generator.add('copyQToQFortran', copyQToQFortran)

  @abstractmethod
  def addLocal(self, generator):
    pass

  @abstractmethod
  def addNeighbor(self, generator):
    pass

  @abstractmethod
  def addTime(self, generator):
    pass