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)
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)
def addLocal(self, generator, targets): for target in targets: name_prefix = generate_kernel_name_prefix(target) volumeSum = self.Q['kp'] for i in range(3): volumeSum += self.db.kDivM[i][self.t( 'kl')] * self.I['lq'] * self.starMatrix(i)['qp'] if self.sourceMatrix(): volumeSum += self.I['kq'] * self.sourceMatrix()['qp'] volume = (self.Q['kp'] <= volumeSum) generator.add(f'{name_prefix}volume', volume, target=target) localFlux = lambda i: self.Q['kp'] <= self.Q['kp'] + self.db.rDivM[ i][self.t('km')] * self.db.fMrT[i][self.t('ml')] * self.I[ 'lq'] * self.AplusT['qp'] localFluxPrefetch = lambda i: self.I if i == 0 else (self.Q if i == 1 else None) generator.addFamily(f'{name_prefix}localFlux', simpleParameterSpace(4), localFlux, localFluxPrefetch, target=target) localFluxNodal = lambda i: self.Q['kp'] <= self.Q[ 'kp'] + self.db.project2nFaceTo3m[i]['kn'] * self.INodal[ 'no'] * self.AminusT['op'] localFluxNodalPrefetch = lambda i: self.I if i == 0 else ( self.Q if i == 1 else None) generator.addFamily(f'{name_prefix}localFluxNodal', simpleParameterSpace(4), localFluxNodal, localFluxNodalPrefetch, target=target)
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)
def addNeighbor(self, generator): neighbourFlux = lambda h, j, i: self.Q['kp'] <= self.Q[ 'kp'] + self.db.rDivM[i][self.t('km')] * self.db.fP[h][self.t( 'mn')] * self.db.rT[j][self.t('nl')] * self.I[ 'lq'] * self.AminusT['qp'] neighbourFluxPrefetch = lambda h, j, i: self.I generator.addFamily('neighboringFlux', simpleParameterSpace(3, 4, 4), neighbourFlux, neighbourFluxPrefetch)
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)
def addNeighbor(self, generator): neighbourFluxExt = lambda h,j,i: self.Qext['kp'] <= self.Qext['kp'] + self.db.rDivM[i][self.t('km')] * self.db.fP[h][self.t('mn')] * self.db.rT[j][self.t('nl')] * self.I['lq'] * self.AminusT['qp'] neighbourFluxExtPrefetch = lambda h,j,i: self.I generator.addFamily('neighbourFluxExt', simpleParameterSpace(3,4,4), neighbourFluxExt, neighbourFluxExtPrefetch) generator.add('neighbour', [ self.Qane['kpm'] <= self.Qane['kpm'] + self.w['m'] * self.Qext['kq'] * self.selectAne['qp'], self.Q['kp'] <= self.Q['kp'] + self.Qext['kq'] * self.selectEla['qp'] ])
def addNeighbor(self, generator): neighbourFluxExt = lambda h,j,i: self.Qext['kp'] <= self.Qext['kp'] + self.db.rDivM[i][self.t('km')] * self.db.fP[h][self.t('mn')] * self.db.rT[j][self.t('nl')] * self.I['lq'] * self.AminusT['qp'] neighbourFluxExtPrefetch = lambda h,j,i: self.I generator.addFamily('neighbourFluxExt', simpleParameterSpace(3,4,4), neighbourFluxExt, neighbourFluxExtPrefetch) generator.add('neighbour', [ self.Qane['kpm'] <= self.Qane['kpm'] + self.w['m'] * self.Qext['kq'] * self.selectAne['qp'], self.Q['kp'] <= self.Q['kp'] + self.Qext['kq'] * self.selectEla['qp'] ])
def addLocal(self, generator): volumeSum = self.Q['kp'] for i in range(3): volumeSum += self.db.kDivM[i][self.t('kl')] * self.I['lq'] * self.db.star[i]['qp'] volume = (self.Q['kp'] <= volumeSum) generator.add('volume', volume) localFlux = lambda i: self.Q['kp'] <= self.Q['kp'] + self.db.rDivM[i][self.t('km')] * self.db.fMrT[i][self.t('ml')] * self.I['lq'] * self.AplusT['qp'] localFluxPrefetch = lambda i: self.I if i == 0 else (self.Q if i == 1 else None) generator.addFamily('localFlux', simpleParameterSpace(4), localFlux, localFluxPrefetch)
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)
def addNeighbor(self, generator, targets): for target in targets: name_prefix = generate_kernel_name_prefix(target) neighbourFlux = lambda h, j, i: self.Q['kp'] <= self.Q[ 'kp'] + self.db.rDivM[i][self.t('km')] * self.db.fP[h][self.t( 'mn')] * self.db.rT[j][self.t('nl')] * self.I[ 'lq'] * self.AminusT['qp'] neighbourFluxPrefetch = lambda h, j, i: self.I generator.addFamily(f'{name_prefix}neighboringFlux', simpleParameterSpace(3, 4, 4), neighbourFlux, neighbourFluxPrefetch, target=target)
def addLocal(self, generator): volumeSum = Add() for i in range(3): volumeSum += self.db.kDivM[i][self.t('kl')] * self.I['lq'] * self.db.star[i]['qp'] volumeExt = (self.Qext['kp'] <= volumeSum) generator.add('volumeExt', volumeExt) localFluxExt = lambda i: self.Qext['kp'] <= self.Qext['kp'] + self.db.rDivM[i][self.t('km')] * self.db.fMrT[i][self.t('ml')] * self.I['lq'] * self.AplusT['qp'] localFluxExtPrefetch = lambda i: self.I if i == 0 else (self.Q if i == 1 else None) generator.addFamily('localFluxExt', simpleParameterSpace(4), localFluxExt, localFluxExtPrefetch) generator.add('local', [ self.Qane['kpm'] <= self.Qane['kpm'] + self.w['m'] * self.Qext['kq'] * self.selectAne['qp'] + self.Iane['kpl'] * self.W['lm'], self.Q['kp'] <= self.Q['kp'] + self.Qext['kq'] * self.selectEla['qp'] + self.Iane['kqm'] * self.E['qmp'] ])
def addLocal(self, generator): volumeSum = Add() for i in range(3): volumeSum += self.db.kDivM[i][self.t('kl')] * self.I['lq'] * self.db.star[i]['qp'] volumeExt = (self.Qext['kp'] <= volumeSum) generator.add('volumeExt', volumeExt) localFluxExt = lambda i: self.Qext['kp'] <= self.Qext['kp'] + self.db.rDivM[i][self.t('km')] * self.db.fMrT[i][self.t('ml')] * self.I['lq'] * self.AplusT['qp'] localFluxExtPrefetch = lambda i: self.I if i == 0 else (self.Q if i == 1 else None) generator.addFamily('localFluxExt', simpleParameterSpace(4), localFluxExt, localFluxExtPrefetch) generator.add('local', [ self.Qane['kpm'] <= self.Qane['kpm'] + self.w['m'] * self.Qext['kq'] * self.selectAne['qp'] + self.Iane['kpl'] * self.W['lm'], self.Q['kp'] <= self.Q['kp'] + self.Qext['kq'] * self.selectEla['qp'] + self.Iane['kqm'] * self.E['qmp'] ])
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')
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, 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)