def viscositySolver(solver, rho, rhoU, rhoE, rhoa, rhoUa, rhoEa, DT): mesh = solver.mesh.symMesh def divideFields(rhoa, rhoUa, rhoEa, volumes): return rhoa / volumes, rhoUa[0] / volumes, rhoUa[1] / volumes, rhoUa[ 2] / volumes, rhoEa / volumes fields = Kernel(divideFields)(mesh.nInternalCells)(rhoa, rhoUa, rhoEa, mesh.volumes) def getFaceData(DT, areas, deltas): return areas * DT / deltas DTF = Kernel(getFaceData)(mesh.nFaces)(DT, mesh.areas, mesh.deltas) inputs = fields + (rho, rhoU, rhoE, DTF, solver.dt) outputs = tuple([Zeros(x.shape) for x in fields]) fields = ExternalFunctionOp('apply_adjoint_viscosity', inputs, outputs).outputs def multiplyFields(phi1, phi2, phi3, phi4, phi5, volumes): rhoa = phi1 * volumes rhoUa = Tensor((3, ), [phi2 * volumes, phi3 * volumes, phi4 * volumes]) rhoEa = phi5 * volumes return rhoa, rhoUa, rhoEa return Kernel(multiplyFields)(mesh.nInternalCells)(*(fields + (mesh.volumes, )))
def timeStepper(equation, initFields, solver): mesh = solver.mesh.symMesh alpha, beta, gamma = solver.timeStepCoeff nStages = alpha.shape[0] LHS = [] fields = [initFields] n = len(fields[0]) def update(*args, **kwargs): i = kwargs['i'] currFields = [0] * n LHS, S, fields, dt = args[:n], args[n:2 * n], args[2 * n:-1], args[-1] dt = dt.scalar() for j in range(0, i + 1): for index in range(0, n): currFields[index] += alpha[i, j] * fields[j * n + index] for index in range(0, n): currFields[index] += -beta[i, i] * (LHS[index] - S[index]) * dt return tuple(currFields) for i in range(0, nStages): #solver.t = solver.t0 + gamma[i]*solver.dt LHS = equation(*fields[i]) S = [x[0] for x in solver.sourceTerms] args = list(LHS) + S + sum(fields, []) + [solver.dt] currFields = Kernel(update)(mesh.nInternalCells)(*args, i=i) solver.stage += 1 fields.append(list(currFields)) return fields[-1]
def update(self, *args): if len(args) == 1: return args[0] U, T, p = args inputs = tuple([U, T, p] + [x[0] for x in self.inputs]) outputs = (U[self.cellStartFace], T[self.cellStartFace], p[self.cellStartFace]) return Kernel(self._update)(self.nFaces, outputs)(*inputs)
def __init__(self, phi, patchID): self.patchID = patchID self.dimensions = phi.dimensions self.solver = phi.solver self.mesh = phi.mesh self.patch = phi.boundary[patchID] mesh = self.mesh.symMesh patch = mesh.boundary[patchID] self.startFace, self.nFaces = patch['startFace'], patch['nFaces'] self.cellStartFace = patch['cellStartFace'] self.normals = mesh.normals[self.startFace] self.owner = mesh.owner # used by field writer self.keys = [] self.inputs = [] self._tensorUpdate = Kernel(self._update)
def computeSymmetrizedAdjointEnergy(solver, rhoa, rhoUa, rhoEa, rho, rhoU, rhoE): # optimize this function mesh = solver.mesh.symMesh def computeEnergy(rhoa, rhoUa, rhoEa, rho, rhoU, rhoE, volumes): U = rhoU / rho u1, u2, u3 = U[0], U[1], U[2] q2 = (u1 * u1 + u2 * u2 + u3 * u3) g = solver.gamma p = (rhoE - rho * q2 / 2) * (g - 1) H = g * p / (rho * (g - 1)) + q2 / 2 A = Tensor((5, 5), [ rho, rho * u1, rho * u2, rho * u3, rhoE, rho * u1, rho * u1 * u1 + p, rho * u1 * u2, rho * u1 * u3, rho * H * u1, rho * u2, rho * u2 * u1, rho * u2 * u2 + p, rho * u2 * u3, rho * H * u2, rho * u3, rho * u3 * u1, rho * u3 * u2, rho * u3 * u3 + p, rho * H * u3, rhoE, rho * H * u1, rho * H * u2, rho * H * u3, rho * H * H - g * p * p / (rho * (g - 1)) ]) # already divided by volumes # not divided by volumes rhoa = rhoa / volumes rhoUa = rhoUa / volumes rhoEa = rhoEa / volumes w = Tensor((5, ), [rhoa, rhoUa[0], rhoUa[1], rhoUa[2], rhoEa]) l2norm = w.dot(A.tensordot(w)) return (l2norm * volumes).sum() adjEnergy = Zeros((1, 1)) adjEnergy = Kernel(computeEnergy)(mesh.nInternalCells, (adjEnergy, ))(rhoa, rhoUa, rhoEa, rho, rhoU, rhoE, mesh.volumes) (adjEnergy, ) = ExternalFunctionOp('mpi_allreduce', (adjEnergy, ), (Zeros( (1, 1)), )).outputs return adjEnergy
def computeAdjointViscosity(solver, viscosityType, rho, rhoU, rhoE, scaling): g = solver.gamma mesh = solver.mesh.symMesh def _meshArgs(start=0): return [x[start] for x in mesh.getTensor()] def gradients(U, T, p, *mesh, **options): mesh = Mesh.container(mesh) neighbour = options.pop('neighbour', True) boundary = options.pop('boundary', False) if boundary: UF = U.extract(mesh.neighbour) pF = p.extract(mesh.neighbour) TF = T.extract(mesh.neighbour) cF = (g * TF * solver.R).sqrt() else: UF = interp.central(U, mesh) pF = interp.central(p, mesh) TLF, TRF = T.extract(mesh.owner), T.extract(mesh.neighbour) cLF, cRF = (g * TLF * solver.R).sqrt(), (g * TRF * solver.R).sqrt() cF = cRF * (1 - mesh.weights) + cLF * mesh.weights gradU = op.grad(UF, mesh, neighbour) divU = op.div(UF.dot(mesh.normals), mesh, neighbour) gradp = op.grad(pF, mesh, neighbour) gradc = op.grad(cF, mesh, neighbour) return gradU, divU, gradp, gradc computeGradients = Kernel(gradients) boundaryComputeGradients = Kernel(gradients) coupledComputeGradients = Kernel(gradients) U, T, p = Zeros((mesh.nCells, 3)), Zeros((mesh.nCells, 1)), Zeros( (mesh.nCells, 1)) outputs = solver._primitive(mesh.nInternalCells, (U, T, p))(rho, rhoU, rhoE) # boundary update outputs = solver.boundaryInit(*outputs) outputs = solver.boundary(*outputs) outputs = solver.boundaryEnd(*outputs) U, T, p = outputs meshArgs = _meshArgs() gradU, divU, gradp, gradc = Zeros((mesh.nInternalCells, 3, 3)), Zeros( (mesh.nInternalCells, 1)), Zeros((mesh.nInternalCells, 3)), Zeros( (mesh.nInternalCells, 3)) outputs = computeGradients(mesh.nInternalFaces, (gradU, divU, gradp, gradc))(U, T, p, *meshArgs) for patchID in solver.mesh.sortedPatches: startFace, nFaces = mesh.boundary[patchID]['startFace'], mesh.boundary[ patchID]['nFaces'] patchType = solver.mesh.boundary[patchID]['type'] meshArgs = _meshArgs(startFace) if patchType in config.coupledPatches: outputs = coupledComputeGradients(nFaces, outputs)(U, T, p, neighbour=False, boundary=False, *meshArgs) outputs[0].args[0].info += [[ x.shape for x in solver.mesh.getTensor() ], patchID, solver.mesh.boundary[patchID]['startFace'], solver.mesh.boundary[patchID]['nFaces'] ] else: outputs = boundaryComputeGradients(nFaces, outputs)(U, T, p, neighbour=False, boundary=True, *meshArgs) meshArgs = _meshArgs(mesh.nLocalFaces) outputs = coupledComputeGradients(mesh.nRemoteCells, outputs)(U, T, p, neighbour=False, boundary=False, *meshArgs) gradU, divU, gradp, gradc = outputs def getMaxEigenvalue(U, T, p, gradU, divU, gradp, gradc): Uref, Tref, pref = solver.Uref, solver.Tref, solver.pref sg = np.sqrt(g) g1 = g - 1 sg1 = np.sqrt(g1) sge = sg1 * sg rho, _, _ = solver.conservative(U, T, p) c = (g * p / rho).sqrt() gradrho = g * (gradp - c * p) / (c * c) b = c / sg a = sg1 * c / sg gradb = gradc / sg grada = gradc * sg1 / sg Z = Tensor((1, ), [ConstantOp(0.)]) U1, U2, U3 = U[0], U[1], U[2] Us = U.magSqr() c2 = c * c B = Tensor((5, 5), [ rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho, rho ]) if viscosityType == 'abarbanel' or viscosityType == 'uniform': M1 = Tensor((5, 5), [ divU, gradb[0], gradb[1], gradb[2], Z, gradb[0], divU, Z, Z, grada[0], gradb[1], Z, divU, Z, grada[1], gradb[2], Z, Z, divU, grada[2], Z, grada[0], grada[1], grada[2], divU ]) tmp1 = b * gradrho / rho tmp2 = a * gradp / (2 * p) tmp3 = 2 * grada / g1 M2 = Tensor((5, 5), [ Z, tmp1[0], tmp1[1], tmp1[2], sg1 * divU / 2, Z, gradU[0, 0], gradU[0, 1], gradU[0, 2], tmp2[0], Z, gradU[1, 0], gradU[1, 1], gradU[1, 2], tmp2[1], Z, gradU[2, 0], gradU[2, 1], gradU[2, 2], tmp2[2], Z, tmp3[0], tmp3[1], tmp3[2], g1 * divU / 2 ]) M = M1 / 2 - M2 elif viscosityType == 'turkel': M1 = Tensor((5, 5), [ divU, gradc[0], gradc[1], gradc[2], Z, gradc[0], divU, Z, Z, Z, gradc[1], Z, divU, Z, Z, gradc[2], Z, Z, divU, Z, Z, Z, Z, Z, divU ]) tmp1 = gradp / (rho * c) tmp2 = g1 * gradp / (2 * rho * c) tmp3 = gradp * pref / (2 * g * p * rho * Uref) tmp4 = (gradp - c * c * gradrho) * Uref / pref M2 = Tensor((5, 5), [ g1 * divU / 2, tmp1[0], tmp1[1], tmp1[2], divU * pref / (2 * rho * c * Uref), tmp2[0], gradU[0, 0], gradU[0, 1], gradU[0, 2], tmp3[0], tmp2[1], gradU[1, 0], gradU[1, 1], gradU[1, 2], tmp3[1], tmp2[2], gradU[2, 0], gradU[2, 1], gradU[2, 2], tmp3[2], Z, tmp4[0], tmp4[1], tmp4[2], g1 * divU / 2 ]) M = M1 / 2 - M2 #elif viscosityType == 'entropy_hughes': # from .symmetrizations.entropy_hughes_gen_code import expression # M1, M2 = expression(rho, U, p, gradrho, gradU, gradp, g, Z) # M1 = Tensor((5,5), M1) # M2 = Tensor((5,5), M2) # M = -(M1 + M2) elif viscosityType == 'entropy_hughes': from .symmetrizations.entropy_barth_mathematica import expression_code M = expression_code(rho, U, p, gradrho, gradU, gradp, g, Z) M = [item for sublist in M for item in sublist] #X = [1., 1./Uref, 1./Uref, 1./Uref, 1/pref] #M = [item*X[i]*X[j] for i, sublist in enumerate(M) for j, item in enumerate(sublist)] M = Tensor((5, 5), M) u1, u2, u3 = U[0], U[1], U[2] q2 = (u1 * u1 + u2 * u2 + u3 * u3) H = g * p / (rho * (g - 1)) + q2 / 2 rE = p / (g - 1) + 0.5 * rho * q2 B = Tensor((5, 5), [ rho, rho * u1, rho * u2, rho * u3, rE, rho * u1, rho * u1 * u1 + p, rho * u1 * u2, rho * u1 * u3, rho * H * u1, rho * u2, rho * u2 * u1, rho * u2 * u2 + p, rho * u2 * u3, rho * H * u2, rho * u3, rho * u3 * u1, rho * u3 * u2, rho * u3 * u3 + p, rho * H * u3, rE, rho * H * u1, rho * H * u2, rho * H * u3, rho * H * H - g * p * p / (rho * (g - 1)) ]) else: raise Exception('symmetrizer not recognized') #Ti = Tensor((5, 5), [rho/b, Z, Z, Z, Z, # rho*U1/b, rho, Z, Z, Z, # rho*U2/b, Z, rho, Z, Z, # rho*U3/b, Z, Z, rho, Z, # rho*(c2*2/(g1*g)+Us)/(2*b), rho*U1, rho*U2, rho*U3, c*rho/sge]) #Ti = Ti.transpose() #X = np.diag([1, 1./Uref, 1./Uref, 1./Uref, 1/pref]) #TiX = Ti.matmul(X) #Mc = TiX.transpose().matmul(M.matmul(TiX)) Mc = M MS = (Mc + Mc.transpose()) / 2 return MS, B def constant(M_2norm): return M_2norm + 1 M_2norm = Zeros((mesh.nInternalCells, 1)) if viscosityType == 'uniform': M_2norm = Kernel(constant)(mesh.nInternalCells)(M_2norm) else: MS = Zeros((mesh.nInternalCells, 5, 5)) B = Zeros((mesh.nInternalCells, 5, 5)) MS, B = Kernel(getMaxEigenvalue)(mesh.nInternalCells, (MS, B))(U, T, p, gradU, divU, gradp, gradc) if viscosityType != 'entropy_hughes': (M_2norm, ) = ExternalFunctionOp('get_max_eigenvalue', (MS, ), (M_2norm, )).outputs else: (M_2norm, ) = ExternalFunctionOp('get_max_generalized_eigenvalue', (MS, B), (M_2norm, )).outputs def computeVolume(volumes): return volumes.sum() V = Zeros((1, 1)) V = Kernel(computeVolume)(mesh.nInternalCells, (V, ))(mesh.volumes) (V, ) = ExternalFunctionOp('mpi_allreduce', (V, ), (Zeros( (1, 1)), )).outputs def computeNorm(M_2norm, volumes, V): V = V.scalar() N = (M_2norm * M_2norm * volumes / V).sum() return N N = Zeros((1, 1)) N = Kernel(computeNorm)(mesh.nInternalCells, (N, ))(M_2norm, mesh.volumes, V) (N, ) = ExternalFunctionOp('mpi_allreduce', (N, ), (Zeros( (1, 1)), )).outputs def scaleM(M_2norm, N, scaling): N, scaling = N.scalar(), scaling.scalar() return M_2norm * scaling / N.sqrt() M_2norm_out = Zeros((mesh.nCells, 1)) M_2norm = Kernel(scaleM)(mesh.nInternalCells, (M_2norm_out, ))(M_2norm, N, scaling) (phi, ) = solver.boundaryInit(M_2norm) phi = CellField('M_2norm', None, (1, )).updateGhostCells(phi) (phi, ) = ExternalFunctionOp('mpi', (phi, ), (phi, )).outputs (phi, ) = solver.boundaryEnd(phi) M_2norm = phi def interpolate(M_2norm, *mesh): mesh = Mesh.container(mesh) M_2norm = interp.central(M_2norm, mesh) return M_2norm meshArgs = _meshArgs() DT = Zeros((mesh.nFaces, 1)) DT = Kernel(interpolate)(mesh.nFaces, (DT, ))(M_2norm, *meshArgs) return M_2norm, DT
Uc = Field('U', 2 * X + X**3 * Y**2, (1, )) gradUc = gradOld(centralOld(Uc, mesh), ghost=True) gradUc.field = gradUc.field.reshape((mesh.nCells, 1, 3)) Xf, Yf = mesh.faceCentres[:, [0]], mesh.faceCentres[:, [1]] Ur = 2 * Xf + Xf**3 * Yf**2 U = Variable((mesh.symMesh.nCells, 1)) gradU = Variable((mesh.symMesh.nCells, 1, 3)) def interpolate(U, gradU, *meshArgs): mesh = Mesh.container(meshArgs) return secondOrder(U, gradU, mesh, 0) Uf = Zeros((mesh.symMesh.nFaces, 1)) meshArgs = mesh.symMesh.getTensor() Uf = Kernel(interpolate)(mesh.symMesh.nFaces, (Uf, ))(U, gradU, *meshArgs) meshArgs = mesh.symMesh.getTensor() + mesh.symMesh.getScalar() func = Function('second_order', [U, gradU] + meshArgs, (Uf, )) Function.compile(init=False, compiler_args=config.get_compiler_args()) Function.initialize(0, mesh) meshArgs = mesh.getTensor() + mesh.getScalar() Uf = func(Uc.field, gradUc.field, *meshArgs) assert relative_error(Uf, Ur) < thres def test_central(): case = '../cases/convection' mesh = Mesh.create(case) Field.setMesh(mesh)