/// <summary> /// Computes the maximum admissible step-size according to /// GassnerEtAl2008, equation 67. /// </summary> /// <param name="i0"></param> /// <param name="Length"></param> /// <returns></returns> protected override double GetCFLStepSize(int i0, int Length) { int iKref = gridData.Cells.GetRefElementIndex(i0); int noOfNodesPerCell = base.EvaluationPoints[iKref].NoOfNodes; MultidimensionalArray levelSetValues = speciesMap.Tracker.DataHistories[0].Current.GetLevSetValues(base.EvaluationPoints[iKref], i0, Length); SpeciesId species = speciesMap.Tracker.GetSpeciesId(speciesMap.Control.FluidSpeciesName); var hMinArray = speciesMap.CellAgglomeration.CellLengthScales[species]; //var volFrac = speciesMap.QuadSchemeHelper.CellAgglomeration.CellVolumeFrac[species]; //var hMinGass = speciesMap.h_min; //var hMin = gridData.Cells.h_min; double cfl = double.MaxValue; for (int i = 0; i < Length; i++) { int cell = i0 + i; //double hmin = hMin[cell] * volFrac[cell]; double hmin = hMinArray[cell]; //double hmin = hMinGass[cell]; for (int node = 0; node < noOfNodesPerCell; node++) { if (levelSetValues[i, node].Sign() != (double)speciesMap.Control.FluidSpeciesSign) { continue; } Material material = speciesMap.GetMaterial(double.NaN); Vector3D momentum = new Vector3D(); for (int d = 0; d < CNSEnvironment.NumberOfDimensions; d++) { momentum[d] = momentumValues[d][i, node]; } StateVector state = new StateVector( material, densityValues[i, node], momentum, energyValues[i, node]); double coeff = Math.Max(4.0 / 3.0, config.EquationOfState.HeatCapacityRatio / config.PrandtlNumber); double cflhere = hmin * hmin / coeff / (state.GetViscosity(cell) / config.ReynoldsNumber); #if DEBUG if (double.IsNaN(cflhere)) { throw new Exception("Could not determine CFL number"); } #endif cfl = Math.Min(cfl, cflhere); } } int degree = workingSet.ConservativeVariables.Max(f => f.Basis.Degree); int twoNPlusOne = 2 * degree + 1; return(cfl * GetBetaMax(degree) / twoNPlusOne / twoNPlusOne / Math.Sqrt(CNSEnvironment.NumberOfDimensions)); //return cfl / twoNPlusOne / twoNPlusOne; }
/// <summary> /// Computes the maximum admissible step-size according to /// GassnerEtAl2008, equation 67. /// </summary> /// <param name="i0"></param> /// <param name="Length"></param> /// <returns></returns> protected override double GetCFLStepSize(int i0, int Length) { int iKref = gridData.Cells.GetRefElementIndex(i0); int noOfNodesPerCell = base.EvaluationPoints[iKref].NoOfNodes; Material material = speciesMap.GetMaterial(double.NaN); var hmin = gridData.Cells.h_min; double scaling = Math.Max(4.0 / 3.0, config.EquationOfState.HeatCapacityRatio / config.PrandtlNumber); // Following code is performance-critical, so expect spagetti code ahead double cfl = double.MaxValue; switch (speciesMap) { // 1) IBM optimized (ignores nodes in the void part of a cell, only applies to constant viscosity gases) case ImmersedSpeciesMap ibmMap when material.ViscosityLaw is ConstantViscosity: { MultidimensionalArray levelSetValues = ibmMap.Tracker.DataHistories[0].Current.GetLevSetValues(base.EvaluationPoints[iKref], i0, Length); SpeciesId species = ibmMap.Tracker.GetSpeciesId(ibmMap.Control.FluidSpeciesName); //var hMin = speciesMap.QuadSchemeHelper.CellAgglomeration.CellLengthScales[species]; var volFrac = ibmMap.CellAgglomeration.CellVolumeFrac[species]; double nu = 1.0 / config.ReynoldsNumber; for (int i = 0; i < Length; i++) { int cell = i0 + i; double hminlocal = hmin[cell] * volFrac[cell]; //double hminlocal = hMin[cell]; //double hmin = hMinGass[cell]; for (int node = 0; node < noOfNodesPerCell; node++) { if (levelSetValues[i, node].Sign() != (double)ibmMap.Control.FluidSpeciesSign) { continue; } double cflhere = hminlocal * hminlocal / scaling / nu; #if DEBUG if (double.IsNaN(cflhere)) { throw new Exception("Could not determine CFL number"); } #endif cfl = Math.Min(cfl, cflhere); } } } break; // 2) IBM generic (ignores nodes in the void part of a cell) case ImmersedSpeciesMap ibmMap: { MultidimensionalArray levelSetValues = ibmMap.Tracker.DataHistories[0].Current.GetLevSetValues(base.EvaluationPoints[iKref], i0, Length); SpeciesId species = ibmMap.Tracker.GetSpeciesId(ibmMap.Control.FluidSpeciesName); //var hMin = speciesMap.QuadSchemeHelper.CellAgglomeration.CellLengthScales[species]; var volFrac = ibmMap.CellAgglomeration.CellVolumeFrac[species]; for (int i = 0; i < Length; i++) { int cell = i0 + i; double hminlocal = hmin[cell] * volFrac[cell]; //double hminlocal = hMin[cell]; //double hmin = hMinGass[cell]; for (int node = 0; node < noOfNodesPerCell; node++) { if (levelSetValues[i, node].Sign() != (double)ibmMap.Control.FluidSpeciesSign) { continue; } Vector3D momentum = new Vector3D(); for (int d = 0; d < CNSEnvironment.NumberOfDimensions; d++) { momentum[d] = momentumValues[d][i, node]; } StateVector state = new StateVector( material, densityValues[i, node], momentum, energyValues[i, node]); double nu = state.GetViscosity(cell) / config.ReynoldsNumber; Debug.Assert(nu > 0.0); double cflhere = hminlocal * hminlocal / scaling / nu; #if DEBUG if (double.IsNaN(cflhere)) { throw new Exception("Could not determine CFL number"); } #endif cfl = Math.Min(cfl, cflhere); } } } break; // 3) Non-IBM optimized (only applies to constant viscosity gases) case var speciesMap when material.ViscosityLaw is ConstantViscosity: { double nu = 1.0 / config.ReynoldsNumber; // Constant viscosity for (int i = 0; i < Length; i++) { int cell = i0 + i; for (int node = 0; node < noOfNodesPerCell; node++) { double hminlocal = gridData.Cells.h_min[cell]; double cflhere = hminlocal * hminlocal / scaling / nu; cfl = Math.Min(cfl, cflhere); } } } break; // 4) Non-IBM generic (works for all viscosity laws) default: { for (int i = 0; i < Length; i++) { int cell = i0 + i; for (int node = 0; node < noOfNodesPerCell; node++) { Vector3D momentum = new Vector3D(); for (int d = 0; d < CNSEnvironment.NumberOfDimensions; d++) { momentum[d] = momentumValues[d][i, node]; } StateVector state = new StateVector( material, densityValues[i, node], momentum, energyValues[i, node]); double hminlocal = hmin[cell]; double nu = state.GetViscosity(cell) / config.ReynoldsNumber; Debug.Assert(nu > 0.0); double cflhere = hminlocal * hminlocal / scaling / nu; cfl = Math.Min(cfl, cflhere); } } } break; } int degree = workingSet.ConservativeVariables.Max(f => f.Basis.Degree); int twoNPlusOne = 2 * degree + 1; return(cfl * GetBetaMax(degree) / twoNPlusOne / twoNPlusOne / Math.Sqrt(CNSEnvironment.NumberOfDimensions)); }
/// <summary> /// <see cref="SIPGFlux.UpdateTensorComponent(StateVector, bool, double[,,], int)"/> /// </summary> /// <param name="state"></param> /// <param name="adiabaticWall"></param> /// <param name="Tensor"></param> /// <param name="cellIndex"></param> protected override void UpdateTensorComponent(StateVector state, bool adiabaticWall, double[, ,] Tensor, int cellIndex) { double Viscosity = state.GetViscosity(cellIndex); double gamma = config.EquationOfState.HeatCapacityRatio; double gamma_Pr = adiabaticWall ? 0 : gamma / config.PrandtlNumber; double mu_rhoRe = Viscosity / config.ReynoldsNumber / state.Density; double MachsScaling = gamma * config.MachNumber * config.MachNumber; double v1 = state.Momentum[0] / state.Density; double v2 = state.Momentum[1] / state.Density; double v3 = state.Momentum[2] / state.Density; double E = state.Energy / state.Density; double VelocitySquared = v1 * v1 + v2 * v2 + v3 * v3; switch (dimension) { case 1: Tensor[0, 0, 0] = -(MachsScaling * (alphaPlus13 * v1 * v1 + VelocitySquared) + gamma_Pr * (E - MachsScaling * VelocitySquared)) * mu_rhoRe; Tensor[0, 0, 1] = MachsScaling * (alphaPlus43 - gamma_Pr) * v1 * mu_rhoRe; Tensor[0, 0, 2] = gamma_Pr * mu_rhoRe; break; case 2: // G_xx Tensor[0, 0, 0] = -(MachsScaling * (alphaPlus13 * v1 * v1 + VelocitySquared) + gamma_Pr * (E - MachsScaling * VelocitySquared)) * mu_rhoRe; Tensor[0, 0, 1] = MachsScaling * (alphaPlus43 - gamma_Pr) * v1 * mu_rhoRe; Tensor[0, 0, 2] = MachsScaling * (1 - gamma_Pr) * v2 * mu_rhoRe; Tensor[0, 0, 3] = gamma_Pr * mu_rhoRe; // G_xy Tensor[0, 1, 0] = -MachsScaling * alphaPlus13 * v1 * v2 * mu_rhoRe; Tensor[0, 1, 1] = MachsScaling * v2 * mu_rhoRe; Tensor[0, 1, 2] = MachsScaling * alphaMinus23 * v1 * mu_rhoRe; //Tensor[0, 1, 3] = 0*eta_rhoRe; // G_yx Tensor[1, 0, 0] = -MachsScaling * (alphaPlus43 - 1.0) * v1 * v2 * mu_rhoRe; Tensor[1, 0, 1] = MachsScaling * alphaMinus23 * v2 * mu_rhoRe; Tensor[1, 0, 2] = MachsScaling * v1 * mu_rhoRe; //Tensor[1, 0, 3] = 0*eta_rhoRe; // G_yy Tensor[1, 1, 0] = -(MachsScaling * (alphaPlus13 * v2 * v2 + VelocitySquared) + gamma_Pr * (E - MachsScaling * VelocitySquared)) * mu_rhoRe; Tensor[1, 1, 1] = MachsScaling * (1 - gamma_Pr) * v1 * mu_rhoRe; Tensor[1, 1, 2] = MachsScaling * (alphaPlus43 - gamma_Pr) * v2 * mu_rhoRe; Tensor[1, 1, 3] = gamma_Pr * mu_rhoRe; break; case 3: // G_xx Tensor[0, 0, 0] = -(MachsScaling * (alphaPlus13 * v1 * v1 + VelocitySquared) + gamma_Pr * (E - MachsScaling * VelocitySquared)) * mu_rhoRe; Tensor[0, 0, 1] = MachsScaling * (alphaPlus43 - gamma_Pr) * v1 * mu_rhoRe; Tensor[0, 0, 2] = MachsScaling * (1 - gamma_Pr) * v2 * mu_rhoRe; Tensor[0, 0, 3] = MachsScaling * (1 - gamma_Pr) * v3 * mu_rhoRe; Tensor[0, 0, 4] = gamma_Pr * mu_rhoRe; // G_xy Tensor[0, 1, 0] = -MachsScaling * alphaPlus13 * v1 * v2 * mu_rhoRe; Tensor[0, 1, 1] = MachsScaling * v2 * mu_rhoRe; Tensor[0, 1, 2] = MachsScaling * alphaMinus23 * v1 * mu_rhoRe; //Tensor[0, 1, 3] = 0 * eta_rhoRe; //Tensor[0, 1, 4] = 0 * eta_rhoRe; // G_xz Tensor[0, 2, 0] = -MachsScaling * alphaPlus13 * v1 * v3 * mu_rhoRe; Tensor[0, 2, 1] = MachsScaling * v3 * mu_rhoRe; //Tensor[0, 2, 2] = 0 * eta_rhoRe; Tensor[0, 2, 3] = MachsScaling * alphaMinus23 * v1 * mu_rhoRe; //Tensor[0, 2, 4] = 0 * eta_rhoRe; // G_yx Tensor[1, 0, 0] = -MachsScaling * alphaPlus13 * v1 * v2 * mu_rhoRe; Tensor[1, 0, 1] = MachsScaling * alphaMinus23 * v2 * mu_rhoRe; Tensor[1, 0, 2] = MachsScaling * v1 * mu_rhoRe; //Tensor[1, 0, 3] = 0 * eta_rhoRe; //Tensor[1, 0, 4] = 0 * eta_rhoRe; // G_yy Tensor[1, 1, 0] = -(MachsScaling * (alphaPlus13 * v2 * v2 + VelocitySquared) + gamma_Pr * (E - MachsScaling * VelocitySquared)) * mu_rhoRe; Tensor[1, 1, 1] = MachsScaling * (1 - gamma_Pr) * v1 * mu_rhoRe; Tensor[1, 1, 2] = MachsScaling * (alphaPlus43 - gamma_Pr) * v2 * mu_rhoRe; Tensor[1, 1, 3] = MachsScaling * (1 - gamma_Pr) * v3 * mu_rhoRe; Tensor[1, 1, 4] = gamma_Pr * mu_rhoRe; // G_yz Tensor[1, 2, 0] = -MachsScaling * alphaPlus13 * v2 * v3 * mu_rhoRe; //Tensor[1, 2, 1] = 0 * eta_rhoRe; Tensor[1, 2, 2] = MachsScaling * v3 * mu_rhoRe; Tensor[1, 2, 3] = MachsScaling * alphaMinus23 * v2 * mu_rhoRe; //Tensor[1, 2, 4] = 0 * eta_rhoRe; // G_zx Tensor[2, 0, 0] = -MachsScaling * alphaPlus13 * v1 * v3 * mu_rhoRe; Tensor[2, 0, 1] = MachsScaling * alphaMinus23 * v3 * mu_rhoRe; //Tensor[2, 0, 2] = 0 * eta_rhoRe; Tensor[2, 0, 3] = MachsScaling * v1 * mu_rhoRe; //Tensor[2, 0, 4] = 0 * eta_rhoRe; // G_zy Tensor[2, 1, 0] = -MachsScaling * alphaPlus13 * v2 * v3 * mu_rhoRe; //Tensor[2, 1, 1] = 0 * eta_rhoRe; Tensor[2, 1, 2] = MachsScaling * alphaMinus23 * v3 * mu_rhoRe; Tensor[2, 1, 3] = MachsScaling * v2 * mu_rhoRe; //Tensor[2, 1, 4] = 0 * eta_rhoRe; // G_zz Tensor[2, 2, 0] = -(MachsScaling * (alphaPlus13 * v3 * v3 + VelocitySquared) + gamma_Pr * (E - MachsScaling * VelocitySquared)) * mu_rhoRe; Tensor[2, 2, 1] = MachsScaling * (1 - gamma_Pr) * v1 * mu_rhoRe; Tensor[2, 2, 2] = MachsScaling * (1 - gamma_Pr) * v2 * mu_rhoRe; Tensor[2, 2, 3] = MachsScaling * (alphaPlus43 - gamma_Pr) * v3 * mu_rhoRe; Tensor[2, 2, 4] = gamma_Pr * mu_rhoRe; break; } }
/// <summary> /// <see cref="SIPGFlux.UpdateTensorComponent(StateVector, bool, double[,,], int)"/> /// </summary> /// <param name="state"></param> /// <param name="adiabaticWall"></param> /// <param name="Tensor"></param> /// <param name="cellIndex"></param> protected override void UpdateTensorComponent(StateVector state, bool adiabaticWall, double[, ,] Tensor, int cellIndex) { //TO-DO: temperature dependent thermal conductivity/viscosity // double ThermalConductivity = state.ThermalConductivity double Viscosity = state.GetViscosity(cellIndex); double ThermalConductivity = Viscosity; double mu_rhoRe = Viscosity / config.ReynoldsNumber / state.Density; double v1 = state.Velocity[0]; double v2 = state.Velocity[1]; double v3 = state.Velocity[2]; switch (dimension) { case 1: Tensor[0, 0, 0] = -(alphaPlus43) * v1 * mu_rhoRe; Tensor[0, 0, 1] = alphaPlus43 * mu_rhoRe; //Tensor[0, 0, 2] = 0 * eta_rhoRe; break; case 2: switch (component) { case 1: // x-momentum //G_xx Tensor[0, 0, 0] = -(alphaPlus43) * v1 * mu_rhoRe; Tensor[0, 0, 1] = alphaPlus43 * mu_rhoRe; //Tensor[0, 0, 2] = 0 * eta_rhoRe; //Tensor[0, 0, 3] = 0 * eta_rhoRe; //G_xy Tensor[0, 1, 0] = -alphaMinus23 * v2 * mu_rhoRe; //Tensor[0, 1, 1] = 0 * eta_rhoRe; Tensor[0, 1, 2] = alphaMinus23 * mu_rhoRe; //Tensor[0, 1, 3] = 0 * eta_rhoRe; // G_yx Tensor[1, 0, 0] = -v2 * mu_rhoRe; //Tensor[1, 0, 1] = 0 * eta_rhoRe; Tensor[1, 0, 2] = 1 * mu_rhoRe; //Tensor[1, 0, 3] = 0 * eta_rhoRe; //G_yy Tensor[1, 1, 0] = -v1 * mu_rhoRe; Tensor[1, 1, 1] = 1 * mu_rhoRe; //Tensor[1, 1, 2] = 0 * eta_rhoRe; //Tensor[1, 1, 3] = 0 * eta_rhoRe; break; case 2: // y-momentum //G_xx Tensor[0, 0, 0] = -v2 * mu_rhoRe; //Tensor[0, 0, 1] = 0 * eta_rhoRe; Tensor[0, 0, 2] = 1 * mu_rhoRe; //Tensor[0, 0, 3] = 0 * eta_rhoRe; //G_xy Tensor[0, 1, 0] = -v2 * mu_rhoRe; Tensor[0, 1, 1] = 1 * mu_rhoRe; //Tensor[0, 1, 2] = 0 * eta_rhoRe; //Tensor[0, 1, 3] = 0 * eta_rhoRe; // G_yx Tensor[1, 0, 0] = -alphaMinus23 * v1 * mu_rhoRe; Tensor[1, 0, 1] = alphaMinus23 * mu_rhoRe; //Tensor[1, 0, 2] = 0 * eta_rhoRe; //Tensor[1, 0, 3] = 0 * eta_rhoRe; //G_yy Tensor[1, 1, 0] = -(alphaPlus43) * v2 * mu_rhoRe; //Tensor[1, 1, 1] = 0 * eta_rhoRe; Tensor[1, 1, 2] = alphaPlus43 * mu_rhoRe; //Tensor[1, 1, 3] = 0 * eta_rhoRe; break; } break; case 3: switch (component) { case 1: // x-momentum //G_xx Tensor[0, 0, 0] = -alphaPlus43 * v1 * mu_rhoRe; Tensor[0, 0, 1] = alphaPlus43 * mu_rhoRe; //Tensor[0, 0, 2] = 0 * eta_rhoRe; //Tensor[0, 0, 3] = 0 * eta_rhoRe; //Tensor[0, 0, 4] = 0 * eta_rhoRe; //G_xy Tensor[0, 1, 0] = -alphaMinus23 * v2 * mu_rhoRe; //Tensor[0, 1, 1] = 0 * eta_rhoRe; Tensor[0, 1, 2] = alphaMinus23 * mu_rhoRe; //Tensor[0, 1, 3] = 0 * eta_rhoRe; //Tensor[0, 1, 4] = 0 * eta_rhoRe; //G_xz Tensor[0, 2, 0] = -alphaMinus23 * v3 * mu_rhoRe; //Tensor[0, 2, 1] = 0 * eta_rhoRe; //Tensor[0, 2, 2] = 0 * eta_rhoRe; Tensor[0, 2, 3] = alphaMinus23 * mu_rhoRe; //Tensor[0, 2, 4] = 0 * eta_rhoRe; // G_yx Tensor[1, 0, 0] = -v2 * mu_rhoRe; //Tensor[1, 0, 1] = 0 * eta_rhoRe; Tensor[1, 0, 2] = 1 * mu_rhoRe; //Tensor[1, 0, 3] = 0 * eta_rhoRe; //Tensor[1, 0, 4] = 0 * eta_rhoRe; //G_yy Tensor[1, 1, 0] = -v1 * mu_rhoRe; Tensor[1, 1, 1] = 1 * mu_rhoRe; //Tensor[1, 1, 2] = 0 * eta_rhoRe; //Tensor[1, 1, 3] = 0 * eta_rhoRe; //Tensor[1, 1, 4] = 0 * eta_rhoRe; //G_yz //Tensor[1, 2, 0] = 0 * eta_rhoRe; //Tensor[1, 2, 1] = 0 * eta_rhoRe; //Tensor[1, 2, 2] = 0 * eta_rhoRe; //Tensor[1, 2, 3] = 0 * eta_rhoRe; //Tensor[1, 2, 4] = 0 * eta_rhoRe; // G_zx Tensor[2, 0, 0] = -v3 * mu_rhoRe; //Tensor[2, 0, 1] = 0 * eta_rhoRe; //Tensor[2, 0, 2] = 0 * eta_rhoRe; Tensor[2, 0, 3] = 1 * mu_rhoRe; //Tensor[2, 0, 4] = 0 * eta_rhoRe; //G_zy //Tensor[2, 1, 0] = 0 * eta_rhoRe; //Tensor[2, 1, 1] = 0 * eta_rhoRe; //Tensor[2, 1, 2] = 0 * eta_rhoRe; //Tensor[2, 1, 3] = 0 * eta_rhoRe; //Tensor[2, 1, 4] = 0 * eta_rhoRe; //G_zz Tensor[2, 2, 0] = -v1 * mu_rhoRe; Tensor[2, 2, 1] = 1 * mu_rhoRe; //Tensor[2, 2, 2] = 0 * eta_rhoRe; //Tensor[2, 2, 3] = 0 * eta_rhoRe; //Tensor[2, 2, 4] = 0 * eta_rhoRe; break; case 2: // y-momentum //G_xx Tensor[0, 0, 0] = -v2 * mu_rhoRe; //Tensor[0, 0, 1] = 0 * eta_rhoRe; Tensor[0, 0, 2] = 1 * mu_rhoRe; //Tensor[0, 0, 3] = 0 * eta_rhoRe; //Tensor[0, 0, 4] = 0 * eta_rhoRe; //G_xy Tensor[0, 1, 0] = -v1 * mu_rhoRe; Tensor[0, 1, 1] = 1 * mu_rhoRe; //Tensor[0, 1, 2] = 0 * eta_rhoRe; //Tensor[0, 1, 3] = 0 * eta_rhoRe; //Tensor[0, 1, 4] = 0 * eta_rhoRe; //G_xz //Tensor[0, 2, 0] = 0 * eta_rhoRe; //Tensor[0, 2, 1] = 0 * eta_rhoRe; //Tensor[0, 2, 2] = 0 * eta_rhoRe; //Tensor[0, 2, 3] = 0 * eta_rhoRe; //Tensor[0, 2, 4] = 0 * eta_rhoRe; // G_yx Tensor[1, 0, 0] = -alphaMinus23 * v1 * mu_rhoRe; Tensor[1, 0, 1] = alphaMinus23 * mu_rhoRe; //Tensor[1, 0, 2] = 0 * eta_rhoRe; //Tensor[1, 0, 3] = 0 * eta_rhoRe; //Tensor[1, 0, 4] = 0 * eta_rhoRe; //G_yy Tensor[1, 1, 0] = -alphaPlus43 * v2 * mu_rhoRe; //Tensor[1, 1, 1] = 0 * eta_rhoRe; Tensor[1, 1, 2] = alphaPlus43 * mu_rhoRe; //Tensor[1, 1, 3] = 0 * eta_rhoRe; //Tensor[1, 1, 4] = 0 * eta_rhoRe; // G_yz Tensor[1, 2, 0] = -alphaMinus23 * v3 * mu_rhoRe; //Tensor[1, 2, 1] = 0 * eta_rhoRe; //Tensor[1, 2, 2] = 0 * eta_rhoRe; Tensor[1, 2, 3] = alphaMinus23 * mu_rhoRe; //Tensor[1, 2, 4] = 0 * eta_rhoRe; //G_zx //Tensor[2, 0, 0] = 0 * eta_rhoRe; //Tensor[2, 0, 1] = 0 * eta_rhoRe; //Tensor[2, 0, 2] = 0 * eta_rhoRe; //Tensor[2, 0, 3] = 0 * eta_rhoRe; //Tensor[2, 0, 4] = 0 * eta_rhoRe; //G_zy Tensor[2, 1, 0] = -v3 * mu_rhoRe; //Tensor[2, 1, 1] = 0 * eta_rhoRe; //Tensor[2, 1, 2] = 0 * eta_rhoRe; Tensor[2, 1, 3] = 1 * mu_rhoRe; //Tensor[2, 1, 4] = 0 * eta_rhoRe; //G_zz Tensor[2, 2, 0] = -v2 * mu_rhoRe; //Tensor[2, 2, 1] = 0 * eta_rhoRe; Tensor[2, 2, 2] = 1 * mu_rhoRe; //Tensor[2, 2, 3] = 0 * eta_rhoRe; //Tensor[2, 2, 4] = 0 * eta_rhoRe; break; case 3: // z-momentum //G_xx Tensor[0, 0, 0] = -v3 * mu_rhoRe; //Tensor[0, 0, 1] = 0 * eta_rhoRe; //Tensor[0, 0, 2] = 0 * eta_rhoRe; Tensor[0, 0, 3] = 1 * mu_rhoRe; //Tensor[0, 0, 4] = 0 * eta_rhoRe; //G_xy //Tensor[0, 1, 0] = 0 * eta_rhoRe; //Tensor[0, 1, 1] = 0 * eta_rhoRe; //Tensor[0, 1, 2] = 0 * eta_rhoRe; //Tensor[0, 1, 3] = 0 * eta_rhoRe; //Tensor[0, 1, 4] = 0 * eta_rhoRe; //G_xz Tensor[0, 2, 0] = -v1 * mu_rhoRe; Tensor[0, 2, 1] = 1 * mu_rhoRe; //Tensor[0, 2, 2] = 0 * eta_rhoRe; //Tensor[0, 2, 3] = 0 * eta_rhoRe; //Tensor[0, 2, 4] = 0 * eta_rhoRe; // G_yx //Tensor[1, 0, 0] = 0 * eta_rhoRe; //Tensor[1, 0, 1] = 0 * eta_rhoRe; //Tensor[1, 0, 2] = 0 * eta_rhoRe; //Tensor[1, 0, 3] = 0 * eta_rhoRe; //Tensor[1, 0, 4] = 0 * eta_rhoRe; //G_yy Tensor[1, 1, 0] = -v3 * mu_rhoRe; //Tensor[1, 1, 1] = 0 * eta_rhoRe; //Tensor[1, 1, 2] = 0 * eta_rhoRe; Tensor[1, 1, 3] = 1 * mu_rhoRe; //Tensor[1, 1, 4] = 0 * eta_rhoRe; // G_yz Tensor[1, 2, 0] = -v2 * mu_rhoRe; //Tensor[1, 2, 1] = 0 * eta_rhoRe; Tensor[1, 2, 2] = 1 * mu_rhoRe; //Tensor[1, 2, 3] = 0 * eta_rhoRe; //Tensor[1, 2, 4] = 0 * eta_rhoRe; //G_zx Tensor[2, 0, 0] = -alphaMinus23 * v1 * mu_rhoRe; Tensor[2, 0, 1] = alphaMinus23 * mu_rhoRe; //Tensor[2, 0, 2] = 0 * eta_rhoRe; //Tensor[2, 0, 3] = 0 * eta_rhoRe; //Tensor[2, 0, 4] = 0 * eta_rhoRe; //G_zy Tensor[2, 1, 0] = -alphaMinus23 * v2 * mu_rhoRe; //Tensor[2, 1, 1] = 0 * eta_rhoRe; Tensor[2, 1, 2] = alphaMinus23 * mu_rhoRe; //Tensor[2, 1, 3] = 0 * eta_rhoRe; //Tensor[2, 1, 4] = 0 * eta_rhoRe; //G_zz Tensor[2, 2, 0] = -alphaPlus43 * v3 * mu_rhoRe; //Tensor[2, 2, 1] = 0 * eta_rhoRe; //Tensor[2, 2, 2] = 0 * eta_rhoRe; Tensor[2, 2, 3] = alphaPlus43 * mu_rhoRe; //Tensor[2, 2, 4] = 0 * eta_rhoRe; break; } break; default: throw new ArgumentOutOfRangeException("dimension"); } }
/// <summary> /// Defines the force which is integrated over an immersed boundary, /// called by <see cref="IBMQueries.LiftOrDragForce"/> /// </summary> /// <param name="density"></param> /// <param name="momentum"></param> /// <param name="energy"></param> /// <param name="speciesMap"></param> /// <param name="direction">Direction of the force projection, e.g. 0=x-axis, 1=y-axis</param> /// <param name="cutCellMask">Cells intersected by the interface</param> /// <returns></returns> static ScalarFunctionEx GetSurfaceForce( DGField density, VectorField <DGField> momentum, DGField energy, ImmersedSpeciesMap speciesMap, int direction, CellMask cutCellMask) { return(delegate(int j0, int Len, NodeSet nodes, MultidimensionalArray result) { int noOfNodes = nodes.GetLength(0); int D = nodes.SpatialDimension; double Reynolds = speciesMap.Control.ReynoldsNumber; double Mach = speciesMap.Control.MachNumber; double gamma = speciesMap.Control.EquationOfState.HeatCapacityRatio; double MachScaling = gamma * Mach * Mach; MultidimensionalArray rho = MultidimensionalArray.Create(Len, noOfNodes); density.Evaluate(j0, Len, nodes, rho); MultidimensionalArray[] m = new MultidimensionalArray[CNSEnvironment.NumberOfDimensions]; for (int d = 0; d < CNSEnvironment.NumberOfDimensions; d++) { m[d] = MultidimensionalArray.Create(Len, noOfNodes); momentum[d].Evaluate(j0, Len, nodes, m[d]); } MultidimensionalArray rhoE = MultidimensionalArray.Create(Len, noOfNodes); energy.Evaluate(j0, Len, nodes, rhoE); MultidimensionalArray gradRho = MultidimensionalArray.Create(Len, noOfNodes, D); density.EvaluateGradient(j0, Len, nodes, gradRho); MultidimensionalArray gradM = MultidimensionalArray.Create(Len, noOfNodes, D, D); for (int d = 0; d < D; d++) { momentum[d].EvaluateGradient( j0, Len, nodes, gradM.ExtractSubArrayShallow(-1, -1, d, -1), 0, 0.0); } MultidimensionalArray normals = speciesMap.Tracker.DataHistories[0].Current.GetLevelSetNormals(nodes, j0, Len); Vector3D mVec = new Vector3D(); for (int i = 0; i < Len; i++) { for (int j = 0; j < noOfNodes; j++) { for (int d = 0; d < CNSEnvironment.NumberOfDimensions; d++) { mVec[d] = m[d][i, j]; } Material material = speciesMap.GetMaterial(double.NaN); StateVector state = new StateVector(material, rho[i, j], mVec, rhoE[i, j]); double mu = 0.0; if (Reynolds != 0.0) { mu = state.GetViscosity(j0 + j) / Reynolds; } double[,] gradU = new double[D, D]; for (int d1 = 0; d1 < D; d1++) { for (int d2 = 0; d2 < D; d2++) { // Apply chain rule gradU[d1, d2] = (gradM[i, j, d1, d2] - state.Momentum[d1] / state.Density * gradRho[i, j, d2]) / state.Density; } } double divU = gradU[0, 0] + gradU[1, 1]; switch (direction) { // Attention: Changed sign, because normal vector is pointing inwards, not outwards! case 0: // x-Direction result[i, j, 0] = -state.Pressure / MachScaling * normals[i, j, 0] + mu * (2.0 * gradU[0, 0] - 2.0 / 3.0 * divU) * normals[i, j, 0] //tau_11 * n_1 + mu * (gradU[0, 1] + gradU[1, 0]) * normals[i, j, 1]; //tau_12 * n_2 break; case 1: // y-Direction result[i, j, 0] = -state.Pressure / MachScaling * normals[i, j, 1] + mu * (gradU[0, 1] + gradU[1, 0]) * normals[i, j, 0] //tau_12 * n_1 + mu * (2.0 * gradU[1, 1] - 2.0 / 3.0 * divU) * normals[i, j, 1]; //tau_22*n_2 break; default: throw new ArgumentException("Lift and Drag currently only in 2D implemented"); } } } }); }