Exemple #1
0
        static private void EvalComponent <T>(ref EdgeFormParams _inParams,
                                              int gamma, EquationComponentArgMapping <T> bf, Stopwatch[] timers,
                                              MultidimensionalArray SumBufIn, MultidimensionalArray SumBufOt,
                                              MultidimensionalArray[] FieldValuesPos, MultidimensionalArray[] FieldValuesNeg, MultidimensionalArray[] FieldGradientValuesPos, MultidimensionalArray[] FieldGradientValuesNeg,
                                              int DELTA,
                                              Stopwatch timer,
                                              Action <T, MultidimensionalArray[], MultidimensionalArray[], MultidimensionalArray[], MultidimensionalArray[], MultidimensionalArray, MultidimensionalArray> ComponentFunc)
            where T : ILevelSetForm //
        {
            timer.Start();



            for (int i = 0; i < bf.m_AllComponentsOfMyType.Length; i++)    // loop over equation components
            {
                var comp = bf.m_AllComponentsOfMyType[i];


                int NoOfArgs = bf.NoOfArguments[i];
                Debug.Assert(NoOfArgs == comp.ArgumentOrdering.Count);
                int NoOfParams = bf.NoOfParameters[i];
                Debug.Assert(NoOfParams == ((comp.ParameterOrdering != null) ? comp.ParameterOrdering.Count : 0));

                // map arguments
                var uA      = bf.MapArguments(FieldValuesNeg, comp, true);
                var uB      = bf.MapArguments(FieldValuesPos, comp, true);
                var Grad_uA = bf.MapArguments(FieldGradientValuesNeg, comp, true);
                var Grad_uB = bf.MapArguments(FieldGradientValuesPos, comp, true);

                // map parameters
                _inParams.ParameterVars_OUT = new MultidimensionalArray[NoOfParams];
                _inParams.ParameterVars_IN  = new MultidimensionalArray[NoOfParams];
                for (int c = 0; c < NoOfParams; c++)
                {
                    int targ = bf.AllToSub[i, c + NoOfArgs];
                    Debug.Assert(targ >= 0);
                    _inParams.ParameterVars_OUT[c] = FieldValuesPos[targ];
                    _inParams.ParameterVars_IN[c]  = FieldValuesNeg[targ];
                }

                // evaluate equation components
                timers[i].Start();
                ComponentFunc(comp, uA, uB, Grad_uA, Grad_uB, SumBufIn, SumBufOt);
                timers[i].Stop();
#if DEBUG
                SumBufIn.CheckForNanOrInf();
                SumBufOt.CheckForNanOrInf();
#endif
            }
            timer.Stop();
        }
        /// <summary>
        ///
        /// </summary>
        protected void EvaluateEx(int i0, int Length, QuadRule QR, MultidimensionalArray QuadResult)
        {
            NodeSet   NodesUntransformed = QR.Nodes;
            IGridData grid          = this.GridDat;
            int       D             = grid.SpatialDimension;
            int       NoOfEquations = m_CodomainBasisS.Length;
            int       NoOfNodes     = NodesUntransformed.NoOfNodes;
            bool      isAffine      = grid.iGeomCells.IsCellAffineLinear(i0);

            int[] geom2log = grid.iGeomCells.GeomCell2LogicalCell;
#if DEBUG
            for (int i = 1; i < Length; i++)
            {
                Debug.Assert(grid.iGeomCells.IsCellAffineLinear(i + i0) == isAffine);

                if (geom2log == null)
                {
                    for (int e = 0; e < base.m_CodomainBasisS.Length; e++)
                    {
                        Debug.Assert(base.m_CodomainBasisS[e].GetLength(i + i0) == base.m_CodomainBasisS[e].GetLength(i0));
                    }
                }
                else
                {
                    for (int e = 0; e < base.m_CodomainBasisS.Length; e++)
                    {
                        Debug.Assert(base.m_CodomainBasisS[e].GetLength(geom2log[i + i0]) == base.m_CodomainBasisS[e].GetLength(geom2log[i0]));
                    }
                }
            }
#endif

            // this is an EvaluateEx: we are also responsible for multiplying with quadrature weights and summing up!
            Debug.Assert(QuadResult.Dimension == 2);
            Debug.Assert(QuadResult.GetLength(0) == Length);
            Debug.Assert(QuadResult.GetLength(1) == base.m_CodomainMapping.BasisS.Sum(basis => basis.Length));

            // ===================
            // Evaluate all fields
            // ===================

            this.Field_Eval.Start();

            for (int f = 0; f < m_DomainFields.Length; f++)
            {
                if (m_ValueRequired[f])
                {
                    Debug.Assert(m_FieldValues[f] != null);
                    if (m_DomainFields[f] != null)
                    {
                        m_DomainFields[f].Evaluate(i0, Length, NodesUntransformed, m_FieldValues[f]);
                    }
                    else
                    {
                        // field is null => set to 0.0
                        m_FieldValues[f].Clear();
                    }
                }
            }

            for (int f = 0; f < m_GradientRequired.Length; f++)
            {
                if (m_GradientRequired[f])
                {
                    Debug.Assert(m_FieldGradients[f] != null);
                    if (m_DomainFields[f] != null)
                    {
                        m_DomainFields[f].EvaluateGradient(i0, Length, NodesUntransformed, m_FieldGradients[f]);
                    }
                    else
                    {
                        // field is null => set to 0.0
                        m_FieldValues[f].Clear();
                    }
                }
            }

            this.Field_Eval.Stop();



            // =====================================
            // Transform Nodes to global coordinates
            // =====================================

            this.ParametersAndNormals.Start();

            var NodesGlobalCoords = grid.GlobalNodes.GetValue_Cell(NodesUntransformed, i0, Length);
            //var NodesGlobalCoords = MultidimensionalArray.Create(Length, NoOfNodes, D);

            this.ParametersAndNormals.Stop();

            // =======================
            // Evaluate Flux functions
            // =======================


            bool[] RequireTestFunctionGradient = new bool[NoOfEquations];
            bool[] Cleared_m_FluxValues        = new bool[NoOfEquations];

            this.Flux_Eval.Start();

            // loop over all equations ...
            for (int e = 0; e < NoOfEquations; e++)
            {
                //                Field fld = m_CodomainFields[e];

                if (m_NonlinFluxes[e].m_AllComponentsOfMyType.Length + m_NonlinFluxesEx[e].m_AllComponentsOfMyType.Length > 0)
                {
                    m_FluxValues[e].Clear();
                    Cleared_m_FluxValues[e] = true;

                    RequireTestFunctionGradient[e] = true;

                    // sum up all INonlinearFlux - objects
                    int jjj = 0;
                    foreach (INonlinearFlux nonlinFlx in m_NonlinFluxes[e].m_AllComponentsOfMyType)
                    {
                        m_NonlinFluxesWatches[e][jjj].Start();
                        nonlinFlx.Flux(m_Time,
                                       NodesGlobalCoords,
                                       m_NonlinFluxes[e].MapArguments(m_FieldValues, nonlinFlx),
                                       0, Length,
                                       m_FluxValues[e]);
                        m_NonlinFluxesWatches[e][jjj].Stop();
                        jjj++;
                    }

                    // sum up all INonlinearFluxEx - objects
                    jjj = 0;
                    foreach (INonlinearFluxEx nonlinFlxEx in m_NonlinFluxesEx[e].m_AllComponentsOfMyType)
                    {
                        m_NonlinFluxesExWatches[e][jjj].Start();
                        nonlinFlxEx.Flux(m_Time,
                                         NodesGlobalCoords,
                                         m_NonlinFluxesEx[e].MapArguments(m_FieldValues, nonlinFlxEx),
                                         0, Length,
                                         m_FluxValues[e],
                                         i0);
                        m_NonlinFluxesExWatches[e][jjj].Stop();
                        jjj++;
                    }

                    m_FluxValues[e].Scale(-1.0);
                }
            }



            // =========================
            // Evaluate Source functions
            // =========================

            bool[] RequireTestfunction    = new bool[NoOfEquations];
            bool[] Cleared_m_SourceValues = new bool[NoOfEquations];

            for (int e = 0; e < NoOfEquations; e++)
            {
                //                Equation eq = m_Equations[e];
                //                Field fld = eq.MyField;

                if (m_NonlinSources[e].m_AllComponentsOfMyType.Length > 0)
                {
                    m_SourceValues[e].Clear();
                    Cleared_m_SourceValues[e] = true;

                    RequireTestfunction[e] = true;

                    // sum up all sources
                    int jjj = 0;
                    foreach (INonlinearSource nonlinSrc in m_NonlinSources[e].m_AllComponentsOfMyType)
                    {
                        m_NonlinSources_watch[e][jjj].Start();
                        nonlinSrc.Source(m_Time,
                                         NodesGlobalCoords,
                                         m_NonlinSources[e].MapArguments(m_FieldValues, nonlinSrc),
                                         0, i0, Length,
                                         m_SourceValues[e]);
                        m_NonlinSources_watch[e][jjj].Stop();
                        jjj++;
                    }
                }
            }

            // ==============
            // Evaluate Forms
            // ==============

            for (int e = 0; e < NoOfEquations; e++)
            {
                if (m_NonlinFormV[e].m_AllComponentsOfMyType.Length > 0)
                {
                    for (int icomp = 0; icomp < m_NonlinFormV[e].m_AllComponentsOfMyType.Length; icomp++)
                    {
                        INonlinVolumeForm_V nonlinform = m_NonlinFormV[e].m_AllComponentsOfMyType[icomp];

                        if ((nonlinform.VolTerms & (TermActivationFlags.UxV | TermActivationFlags.V | TermActivationFlags.GradUxV)) == 0)
                        {
                            continue;
                        }
                        else
                        {
                            m_NonlinFormV_watch[e][icomp].Start();
                            RequireTestfunction[e] = true;

                            if (!Cleared_m_SourceValues[e])
                            {
                                m_SourceValues[e].Clear();
                                Cleared_m_SourceValues[e] = true;
                            }

                            VolumFormParams vfp;
                            vfp.GridDat = base.GridDat;
                            vfp.j0      = i0;
                            vfp.Len     = Length;
                            vfp.Xglobal = NodesGlobalCoords;
                            vfp.time    = this.m_Time;
                            int NoArgs              = m_NonlinFormV[e].NoOfArguments[icomp];
                            int NoParams            = m_NonlinFormV[e].NoOfParameters[icomp];
                            var MappedArgsAndParams = m_NonlinFormV[e].MapArguments(this.m_FieldValues, nonlinform);
                            vfp.ParameterVars = MappedArgsAndParams.GetSubVector(NoArgs, NoParams);
                            var MappedArgs = MappedArgsAndParams.GetSubVector(0, NoArgs);

                            var MappedGradients = m_NonlinFormV[e].MapArguments(this.m_FieldGradients, nonlinform, true);

                            nonlinform.Form(ref vfp, MappedArgs, MappedGradients, this.m_SourceValues[e]);
                            m_NonlinFormV_watch[e][icomp].Stop();
                        }
                    }
                }
            }

            for (int e = 0; e < NoOfEquations; e++)
            {
                if (m_NonlinFormGradV[e].m_AllComponentsOfMyType.Length > 0)
                {
                    for (int icomp = 0; icomp < m_NonlinFormGradV[e].m_AllComponentsOfMyType.Length; icomp++)
                    {
                        INonlinVolumeForm_GradV nonlinform = m_NonlinFormGradV[e].m_AllComponentsOfMyType[icomp];

                        if ((nonlinform.VolTerms & (TermActivationFlags.GradUxGradV | TermActivationFlags.UxGradV | TermActivationFlags.GradV)) == 0)
                        {
                            continue;
                        }
                        else
                        {
                            m_NonlinFormGradV_watch[e][icomp].Start();
                            RequireTestFunctionGradient[e] = true;

                            if (!Cleared_m_FluxValues[e])
                            {
                                this.m_FluxValues[e].Clear();
                                Cleared_m_FluxValues[e] = true;
                            }

                            VolumFormParams vfp;
                            vfp.GridDat = base.GridDat;
                            vfp.j0      = i0;
                            vfp.Len     = Length;
                            vfp.Xglobal = NodesGlobalCoords;
                            vfp.time    = this.m_Time;
                            int NoArgs              = m_NonlinFormGradV[e].NoOfArguments[icomp];
                            int NoParams            = m_NonlinFormGradV[e].NoOfParameters[icomp];
                            var MappedArgsAndParams = m_NonlinFormGradV[e].MapArguments(this.m_FieldValues, nonlinform);
                            vfp.ParameterVars = MappedArgsAndParams.GetSubVector(NoArgs, NoParams);
                            var MappedArgs = MappedArgsAndParams.GetSubVector(0, NoArgs);

                            var MappedGradients = m_NonlinFormGradV[e].MapArguments(this.m_FieldGradients, nonlinform, true);

                            nonlinform.Form(ref vfp, MappedArgs, MappedGradients, this.m_FluxValues[e]);
                            m_NonlinFormGradV_watch[e][icomp].Stop();
                        }
                    }
                }
            }
            this.Flux_Eval.Stop();



            // ================
            // Transform fluxes
            // ================

            // its less work to multiply the fluxes by the inverse Jacobi,
            // than each test function gradient by inverse Jacobi.
            // Could be interpreted as transforming fluxes to Refelem, i think....

            this.Flux_Trafo.Start();

            MultidimensionalArray InverseJacobi = null, JacobiDet = null;
            for (int e = 0; e < NoOfEquations; e++)
            {
                Debug.Assert((m_FluxValues[e] != null) == (m_FluxValuesTrf[e] != null));

                if (m_FluxValues[e] != null)
                {
                    if (InverseJacobi == null)
                    {
                        if (isAffine)
                        {
                            InverseJacobi = grid.iGeomCells.InverseTransformation.ExtractSubArrayShallow(new int[] { i0, 0, 0 }, new int[] { i0 + Length - 1, D - 1, D - 1 });
                        }
                        else
                        {
                            InverseJacobi = grid.InverseJacobian.GetValue_Cell(QR.Nodes, i0, Length);
                            //InverseJacobi = MultidimensionalArray.Create(Length, NoOfNodes, D, D);
                        }
                    }

                    if (JacobiDet == null && !isAffine)
                    {
                        JacobiDet = grid.JacobianDeterminat.GetValue_Cell(QR.Nodes, i0, Length);
                    }

                    if (isAffine)
                    {
                        m_FluxValuesTrf[e].Multiply(1.0, m_FluxValues[e], InverseJacobi, 0.0, "jke", "jkd", "jed");
                        // for affine-linear cells the multiplication with Jacobi determinant is done AFTER quadrature, since it is constant per cell.
                    }
                    else
                    {
                        m_FluxValuesTrf[e].Multiply(1.0, m_FluxValues[e], InverseJacobi, 0.0, "jke", "jkd", "jked");
                        m_FluxValuesTrf[e].Multiply(1.0, m_FluxValuesTrf[e], JacobiDet, 0.0, "jke", "jke", "jk"); // apply scaling with Jacobi determinant, for integral transformation
                    }
                }

                if (m_SourceValues[e] != null)
                {
                    if (JacobiDet == null && !isAffine)
                    {
                        JacobiDet = grid.JacobianDeterminat.GetValue_Cell(QR.Nodes, i0, Length);
                    }
                    //JacobiDet = MultidimensionalArray.Create(Length, NoOfNodes);

                    // apply scaling with Jacobi determinant, for integral transformation
                    if (isAffine)
                    {
                        // nop: for affine-linear cells the multiplication with Jacobi determinant is done AFTER quadrature, since it is constant per cell.
                    }
                    else
                    {
                        m_SourceValues[e].Multiply(1.0, m_SourceValues[e], JacobiDet, 0.0, "jk", "jk", "jk");
                    }
                }
            }

            this.Flux_Trafo.Stop();



            // =======================
            // evaluate test functions
            // =======================

            this.Basis_Eval.Start();

            if (this.m_MaxCodBasis != null && QR.NoOfNodes != this.m_TestFuncWeighted.GetLength(0))
            {
                this.m_TestFuncWeighted.Allocate(QR.NoOfNodes, m_MaxCodBasis.GetLength(i0));
            }
            if (this.m_MaxCodBasis_Gradient != null && QR.NoOfNodes != this.m_TestFuncGradWeighted.GetLength(0))
            {
                this.m_TestFuncGradWeighted.Allocate(QR.NoOfNodes, m_MaxCodBasis_Gradient.GetLength(i0), D);
            }

            if (m_MaxCodBasis != null)
            {
                var testFunc = m_MaxCodBasis.Evaluate(QR.Nodes);
                m_TestFuncWeighted.Multiply(1.0, QR.Weights, testFunc, 0.0, "kn", "k", "kn");
            }

            if (m_MaxCodBasis_Gradient != null)
            {
                var testFuncGrad = m_MaxCodBasis_Gradient.EvaluateGradient(QR.Nodes);
                m_TestFuncGradWeighted.Multiply(1.0, QR.Weights, testFuncGrad, 0.0, "knd", "k", "knd");
            }
            this.Basis_Eval.Stop();

            // ==========================================
            // multiply with test functions / save result
            // ==========================================

            MultidimensionalArray OrthoTrf = null; // to transform back to ONB on physical space...
            int iBufOrthoTrf;
            if (isAffine)
            {
                OrthoTrf = TempBuffer.GetTempMultidimensionalarray(out iBufOrthoTrf, Length);
                OrthoTrf.Multiply(1.0,
                                  grid.iGeomCells.JacobiDet.ExtractSubArrayShallow(new int[] { i0 }, new int[] { i0 + Length - 1 }),
                                  grid.ChefBasis.Scaling.ExtractSubArrayShallow(new int[] { i0 }, new int[] { i0 + Length - 1 }),
                                  0.0,
                                  "j", "j", "j");
            }
            else
            {
                int MaxDegree = Math.Max(this.m_MaxCodBasis != null ? m_MaxCodBasis.Degree : 0, this.m_MaxCodBasis_Gradient != null ? m_MaxCodBasis_Gradient.Degree : 0);
                OrthoTrf     = grid.ChefBasis.OrthonormalizationTrafo.GetValue_Cell(i0, Length, MaxDegree);
                iBufOrthoTrf = int.MinValue;
            }

            this.Loops.Start();
            int N0, N;
            N0 = 0;
            for (int e = 0; e < NoOfEquations; e++)   // loop over equations...

            {
                if (geom2log != null)
                {
                    N = m_CodomainBasisS[e].GetLength(geom2log[i0]);
                }
                else
                {
                    N = m_CodomainBasisS[e].GetLength(i0);
                }

                int iBuf;
                MultidimensionalArray QuadResult_e = TempBuffer.GetTempMultidimensionalarray(out iBuf, Length, N);

                // fluxes
                // ------
                if (RequireTestFunctionGradient[e])
                {
                    MultidimensionalArray
                        Fluxes_e       = m_FluxValuesTrf[e],
                        testFuncGrad_e = null;
                    if (m_TestFuncGradWeighted.GetLength(1) == N)
                    {
                        testFuncGrad_e = m_TestFuncGradWeighted;
                    }
                    else
                    {
                        testFuncGrad_e = m_TestFuncGradWeighted.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { NoOfNodes - 1, N - 1, D - 1 });
                    }

                    QuadResult_e.Multiply(1.0, Fluxes_e, testFuncGrad_e, 0.0, "jn", "jke", "kne");
                }

                // sources
                // -------

                if (RequireTestfunction[e])
                {
                    MultidimensionalArray
                        SourceValues_e = m_SourceValues[e],
                        testFunc_e     = null;
                    if (m_TestFuncWeighted.GetLength(1) == N)
                    {
                        testFunc_e = m_TestFuncWeighted;
                    }
                    else
                    {
                        testFunc_e = m_TestFuncWeighted.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { NoOfNodes - 1, N - 1 });
                    }


                    QuadResult_e.Multiply(1.0, SourceValues_e, testFunc_e, 1.0, "jn", "jk", "kn");
                }

                // final transformations
                // ---------------------
                MultidimensionalArray trfQuadResult_e = QuadResult.ExtractSubArrayShallow(new int[] { 0, N0 }, new int[] { Length - 1, N0 + N - 1 });

                if (isAffine)
                {
                    trfQuadResult_e.Multiply(1.0, OrthoTrf, QuadResult_e, 0.0, "jn", "j", "jn");
                }
                else
                {
                    MultidimensionalArray _OrthoTrf;
                    if (OrthoTrf.GetLength(1) == N)
                    {
                        _OrthoTrf = OrthoTrf;
                    }
                    else
                    {
                        _OrthoTrf = OrthoTrf.ExtractSubArrayShallow(new int[] { 0, 0, 0 }, new int[] { Length - 1, N - 1, N - 1 });
                    }

                    trfQuadResult_e.Multiply(1.0, _OrthoTrf, QuadResult_e, 0.0, "jn", "jmn", "jm");
                }

                // next
                // ----

                TempBuffer.FreeTempBuffer(iBuf);
                N0 += N;
            }

            if (isAffine)
            {
                TempBuffer.FreeTempBuffer(iBufOrthoTrf);
            }

            this.Loops.Stop();

#if DEBUG
            QuadResult.CheckForNanOrInf(true, true, true);
#endif
        }
Exemple #3
0
        static private void EvalComponent <T>(LevSetIntParams _inParams,
                                              int gamma, EquationComponentArgMapping <T> bf,
                                              MultidimensionalArray[][] argsPerComp, MultidimensionalArray[,] argsSum,
                                              int componentIdx,
                                              MultidimensionalArray ParamFieldValuesPos, MultidimensionalArray ParamFieldValuesNeg,
                                              int DELTA,
                                              Stopwatch timer,
                                              IDictionary <SpeciesId, MultidimensionalArray> LengthScales,
                                              CallComponent <T> ComponentFunc) where T : ILevelSetComponent
        {
            timer.Start();


            for (int i = 0; i < bf.m_AllComponentsOfMyType.Length; i++)    // loop over equation components
            {
                var comp = bf.m_AllComponentsOfMyType[i];

                LengthScales.TryGetValue(comp.NegativeSpecies, out _inParams.NegCellLengthScale);
                LengthScales.TryGetValue(comp.PositiveSpecies, out _inParams.PosCellLengthScale);

                argsPerComp[gamma][i].Clear();

                int NoOfArgs = bf.NoOfArguments[i];
                Debug.Assert(NoOfArgs == comp.ArgumentOrdering.Count);
                int NoOfParams = bf.NoOfParameters[i];
                Debug.Assert(NoOfParams == ((comp.ParameterOrdering != null) ? comp.ParameterOrdering.Count : 0));


                // map parameters
                _inParams.ParamsPos = new MultidimensionalArray[NoOfParams];
                _inParams.ParamsNeg = new MultidimensionalArray[NoOfParams];
                for (int c = 0; c < NoOfParams; c++)
                {
                    int targ = bf.AllToSub[i, c + NoOfArgs] - DELTA;
                    Debug.Assert(targ >= 0);
                    _inParams.ParamsPos[c] = ParamFieldValuesPos.ExtractSubArrayShallow(targ, -1, -1);
                    _inParams.ParamsNeg[c] = ParamFieldValuesNeg.ExtractSubArrayShallow(targ, -1, -1);
                }

                // evaluate equation components
                ComponentFunc(comp, gamma, i, _inParams);
#if DEBUG
                argsPerComp[gamma][i].CheckForNanOrInf();
#endif

                // sum up bilinear forms:
                {
                    MultidimensionalArray Summand = argsPerComp[gamma][i];

                    if (componentIdx >= 0)
                    {
                        for (int c = 0; c < NoOfArgs; c++)   // loop over arguments of equation component
                        {
                            int   targ   = bf.AllToSub[i, c];
                            int[] selSum = new int[Summand.Dimension];
                            selSum.SetAll(-1);
                            selSum[componentIdx] = c;

                            MultidimensionalArray Accu = argsSum[gamma, targ];

                            //int[] selAccu = new int[Accu.Dimension];
                            //selAccu.SetAll(-1);
                            //selAccu[componentIdx] = targ;
#if DEBUG
                            Summand.ExtractSubArrayShallow(selSum).CheckForNanOrInf();
#endif

                            Accu.Acc(1.0, Summand.ExtractSubArrayShallow(selSum));
                        }
                    }
                    else
                    {
                        // affin
#if DEBUG
                        Summand.CheckForNanOrInf();
#endif
                        MultidimensionalArray Accu = argsSum[gamma, 0];
                        Accu.Acc(1.0, Summand);
                    }
                }
            }
            timer.Stop();
        }