static double JumpNorm(DGField f, EdgeMask em) { GridData grd = grid; int D = grd.SpatialDimension; var e2cTrafo = grd.Edges.Edge2CellTrafos; double Unorm = 0; EdgeQuadrature.GetQuadrature( new int[] { D + 1 }, grd, (new EdgeQuadratureScheme(true, em)).Compile(grd, f.Basis.Degree * 2), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { // Evaluate NodeSet NS = QR.Nodes; EvalResult.Clear(); int NoOfNodes = NS.NoOfNodes; for (int j = 0; j < Length; j++) { int iEdge = j + i0; int iTrafo_IN = grd.Edges.Edge2CellTrafoIndex[iEdge, 0]; int jCell_IN = grd.Edges.CellIndices[iEdge, 0]; int iTrafo_OT = grd.Edges.Edge2CellTrafoIndex[iEdge, 1]; int jCell_OT = grd.Edges.CellIndices[iEdge, 1]; MultidimensionalArray uIN = MultidimensionalArray.Create(1, NoOfNodes); MultidimensionalArray uOT = MultidimensionalArray.Create(1, NoOfNodes); MultidimensionalArray Grad_uIN = MultidimensionalArray.Create(1, NoOfNodes, D); MultidimensionalArray Grad_uOT = MultidimensionalArray.Create(1, NoOfNodes, D); NodeSet NS_IN = NS.GetVolumeNodeSet(grd, iTrafo_IN); NodeSet NS_OT = NS.GetVolumeNodeSet(grd, iTrafo_OT); f.Evaluate(jCell_IN, 1, NS_IN, uIN); f.Evaluate(jCell_OT, 1, NS_OT, uOT); f.EvaluateGradient(jCell_IN, 1, NS_IN, Grad_uIN); f.EvaluateGradient(jCell_OT, 1, NS_OT, Grad_uOT); var uDiff = EvalResult.ExtractSubArrayShallow(new int[] { j, 0, 0 }, new int[] { j, NoOfNodes - 1, -1 }); var Grad_uDiff = EvalResult.ExtractSubArrayShallow(new int[] { j, 0, 1 }, new int[] { j, NoOfNodes - 1, D }); uDiff.Acc(+1.0, uIN); uDiff.Acc(-1.0, uOT); Grad_uDiff.Acc(+1.0, Grad_uIN); Grad_uDiff.Acc(-1.0, Grad_uOT); } EvalResult.ApplyAll(x => x * x); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults Unorm += ResultsOfIntegration.Sum(); }).Execute(); double totNorm = Unorm.MPISum().Sqrt(); return(totNorm); }
protected override void Evaluate(int i0, int Len, QuadRule QR, MultidimensionalArray EvalResult) { NodeSet QuadNodes = QR.Nodes; int D = gridData.SpatialDimension; int NoOfNodes = QuadNodes.NoOfNodes; int GAMMA = m_CodomainMap.NoOfVariables; // GAMMA: number of codom variables // Evaluate Domain & Parameter fields // -------------------------------- Field_Eval.Start(); for (int i = 0; i < m_DomainAndParamFields.Length; i++) { if (m_ValueRequired[i]) { DGField _Field = m_DomainAndParamFields[i]; if (_Field != null) { if (_Field is XDGField) { // jump in parameter i at level-set: separate evaluation for both sides var _xField = _Field as XDGField; _xField.GetSpeciesShadowField(this.SpeciesA).Evaluate(i0, Len, QuadNodes, m_FieldValuesNeg[i]); _xField.GetSpeciesShadowField(this.SpeciesB).Evaluate(i0, Len, QuadNodes, m_FieldValuesPos[i]); } else { // no jump at level set: positive and negative limit of parameter i are equal _Field.Evaluate(i0, Len, QuadNodes, m_FieldValuesPos[i]); m_FieldValuesNeg[i].Set(m_FieldValuesPos[i]); } } else { m_FieldValuesPos[i].Clear(); m_FieldValuesNeg[i].Clear(); } } if (m_GradientRequired[i]) { DGField _Field = m_DomainAndParamFields[i]; if (_Field != null) { if (_Field is XDGField) { // jump in parameter i at level-set: separate evaluation for both sides var _xField = _Field as XDGField; _xField.GetSpeciesShadowField(this.SpeciesA).EvaluateGradient(i0, Len, QuadNodes, m_FieldGradientValuesNeg[i]); _xField.GetSpeciesShadowField(this.SpeciesB).EvaluateGradient(i0, Len, QuadNodes, m_FieldGradientValuesPos[i]); } else { // no jump at level set: positive and negative limit of parameter i are equal _Field.EvaluateGradient(i0, Len, QuadNodes, m_FieldGradientValuesPos[i]); m_FieldGradientValuesNeg[i].Set(m_FieldGradientValuesPos[i]); } } else { m_FieldGradientValuesPos[i].Clear(); m_FieldGradientValuesNeg[i].Clear(); } } } Field_Eval.Stop(); // Evaluate level sets and normals // ------------------------------- ParametersAndNormals.Start(); var NoOfLevSets = m_lsTrk.LevelSets.Count; MultidimensionalArray Normals = m_lsTrk.DataHistories[m_LevSetIdx].Current.GetLevelSetNormals(QuadNodes, i0, Len); MultidimensionalArray NodesGlobal = gridData.GlobalNodes.GetValue_Cell(QuadNodes, i0, Len); ParametersAndNormals.Stop(); // Evaluate basis and test functions // --------------------------------- bool[] ReqV = new bool[GAMMA]; bool[] ReqGradV = new bool[GAMMA]; for (int gamma = 0; gamma < GAMMA; gamma++) { if (Koeff_V[gamma] != null) { ReqV[gamma] = true; } if (Koeff_GradV[gamma] != null) { ReqGradV[gamma] = true; } } MultidimensionalArray[] TestValues; // index: codom variable/test function MultidimensionalArray[] TestGradientValues; // index: codom variable/test function int[,] sectionsTest; Basis_Eval.Start(); LECQuadratureLevelSet <IMutableMatrixEx, double[]> .EvalBasis(i0, Len, this.m_CodomainMap.BasisS, ReqV, ReqGradV, out TestValues, out TestGradientValues, out sectionsTest, QuadNodes); Basis_Eval.Stop(); // Evaluate Integral components // ---------------------------- // loop over codomain variables ... for (int gamma = 0; gamma < GAMMA; gamma++) { // prepare parameters // - - - - - - - - - // set Normal's LevSetIntParams _inParams = new LevSetIntParams(); _inParams.Normal = Normals; // set Nodes Global _inParams.X = NodesGlobal; _inParams.time = this.time; _inParams.LsTrk = this.m_lsTrk; _inParams.i0 = i0; Debug.Assert(_inParams.Len == Len); // clear summation buffers // - - - - - - - - - - - - if (Koeff_V[gamma] != null) { Koeff_V[gamma].Clear(); } if (Koeff_GradV[gamma] != null) { Koeff_GradV[gamma].Clear(); } // Evaluate Bilin. forms // - - - - - - - - - - - { EvalComponent(_inParams, gamma, this.m_NonlinLsForm_V[gamma], this.m_NonlinLsForm_V_Watches[gamma], Koeff_V[gamma], m_FieldValuesPos, m_FieldValuesNeg, m_FieldGradientValuesPos, m_FieldGradientValuesNeg, DELTA, Flux_Eval, delegate(INonlinLevelSetForm_V _comp, LevSetIntParams inp, MultidimensionalArray[] uA, MultidimensionalArray[] uB, MultidimensionalArray[] Grad_uA, MultidimensionalArray[] Grad_uB, MultidimensionalArray SumBuf) { _comp.LevelSetForm_V(_inParams, uA, uB, Grad_uA, Grad_uB, SumBuf); }); } { EvalComponent(_inParams, gamma, this.m_NonlinLsForm_GradV[gamma], this.m_NonlinLsForm_GradV_Watches[gamma], Koeff_GradV[gamma], m_FieldValuesPos, m_FieldValuesNeg, m_FieldGradientValuesPos, m_FieldGradientValuesNeg, DELTA, Flux_Eval, delegate(INonlinLevelSetForm_GradV _comp, LevSetIntParams inp, MultidimensionalArray[] uA, MultidimensionalArray[] uB, MultidimensionalArray[] Grad_uA, MultidimensionalArray[] Grad_uB, MultidimensionalArray SumBuf) { _comp.LevelSetForm_GradV(_inParams, uA, uB, Grad_uA, Grad_uB, SumBuf); }); } } // Summation Loops: multiply with test and trial functions // ------------------------------------------------------- int[] offsetCod = new int[GAMMA]; LECQuadratureLevelSet <IMutableMatrixEx, double[]> . CompOffsets(i0, Len, offsetCod, m_CodomainMap); for (int gamma = 0; gamma < GAMMA; gamma++) { // Evaluate Integrand // - - - - - - - - - var TestVal = TestValues[gamma]; var TestGradVal = TestGradientValues[gamma]; int N; if (TestVal != null) { N = TestVal.GetLength(2); } else if (TestGradVal != null) { N = TestGradVal.GetLength(2); } else { N = 0; } Loops.Start(); // affine offset for (int cr = 0; cr < 2; cr++) // loop over negative/positive species { int[] extr0 = new int[] { 0, 0, sectionsTest[gamma, cr] * N + offsetCod[gamma] }; int[] extrE = new int[] { Len - 1, NoOfNodes - 1, extr0[2] + N - 1 }; var SubRes = EvalResult.ExtractSubArrayShallow(extr0, extrE); if (Koeff_V[gamma] != null) { var Sum_Koeff_V_Cr = Koeff_V[gamma].ExtractSubArrayShallow(-1, -1, cr); SubRes.Multiply(1.0, Sum_Koeff_V_Cr, TestVal, 1.0, "jkn", "jk", "jkn"); } if (Koeff_GradV[gamma] != null) { var Sum_Koeff_NablaV_Cr = Koeff_GradV[gamma].ExtractSubArrayShallow(-1, -1, cr, -1); SubRes.Multiply(1.0, Sum_Koeff_NablaV_Cr, TestGradVal, 1.0, "jkn", "jkd", "jknd"); } } Loops.Stop(); } }
/// <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"); } } } }); }