예제 #1
0
        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);
        }
예제 #2
0
        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();
            }
        }
예제 #3
0
        /// <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");
                        }
                    }
                }
            });
        }