/// <summary>
        /// ctor.
        /// </summary>
        internal LECQuadratureLevelSet(IGridData context,
                                       XSpatialOperatorMk2 DiffOp,
                                       M Matrix, V OffsetVec,
                                       UnsetteledCoordinateMapping RowMap, IList <DGField> ParamsMap, UnsetteledCoordinateMapping ColMap,
                                       LevelSetTracker lsTrk, int _iLevSet,
                                       Tuple <SpeciesId, SpeciesId> SpeciesPair,
                                                                                 //Tuple<CoefficientSet,CoefficientSet> NegPosCoeff,
                                       ICompositeQuadRule <QuadRule> domAndRule) //
            : base(new int[] { RowMap.MaxTotalNoOfCoordinatesPerCell, 1 + ((Matrix == null) ? 0 : ColMap.MaxTotalNoOfCoordinatesPerCell) },
                   context,
                   domAndRule) //
        {
            // ------------------
            // init custom timers
            // ------------------

            base.CustomTimers             = new Stopwatch[] { new Stopwatch(), new Stopwatch(), new Stopwatch(), new Stopwatch() };
            base.CustomTimers_Names       = new string[] { "Flux-Eval", "Basis-Eval", "Loops", "ParametersAndNormals" };
            base.CustomTimers_RootPointer = new int[4];
            ArrayTools.SetAll(base.CustomTimers_RootPointer, -1);

            // -----------------------------------
            // set members / check ctor parameters
            // -----------------------------------

            m_RowMap     = RowMap;
            m_ColMap     = ColMap;
            m_Parameters = (ParamsMap != null) ? ParamsMap.ToArray() : new DGField[0];

            if (m_RowMap.BasisS.Count != DiffOp.CodomainVar.Count)
            {
                throw new ArgumentException("mismatch between number of codomain variables in spatial operator and row mapping");
            }
            if (m_ColMap.BasisS.Count != DiffOp.DomainVar.Count)
            {
                throw new ArgumentException("mismatch between number of domain variables in spatial operator and column mapping");
            }
            if (m_Parameters.Length != DiffOp.ParameterVar.Count)
            {
                throw new ArgumentException("mismatch between number of parameter variables in spatial operator and given parameters");
            }

            int Gamma = m_RowMap.BasisS.Count;

            m_lsTrk = lsTrk;

            if (Matrix != null && (Matrix.RowPartitioning.LocalLength != RowMap.LocalLength))
            {
                throw new ArgumentException("mismatch between matrix number of rows and row mapping.");
            }
            if (Matrix != null && (Matrix.ColPartition.LocalLength != ColMap.LocalLength))
            {
                throw new ArgumentException("mismatch between matrix number of columns and column mapping.");
            }

            this.m_LevSetIdx   = _iLevSet;
            this.m_SpeciesPair = SpeciesPair;

            this.OperatorMatrix = Matrix;
            this.OperatorAffine = OffsetVec;

            // ------------------------
            // sort equation components
            // ------------------------

            //m_BiLinForms = DiffOp.GetArgMapping<IBilinearForm>(true, Compfilter<IBilinearForm>);
            //m_2ndDerivFlux = DiffOp.GetArgMapping<ILinear2ndDerivativeCouplingFlux>(true, Compfilter<ILinear2ndDerivativeCouplingFlux>);

            m_LsForm_UxV = DiffOp.GetArgMapping <ILevelSetForm_UxV>(true,
                                                                    eq => ((eq.LevelSetTerms & TermActivationFlags.UxV) != 0) && Compfilter(eq),
                                                                    eq => (eq is ILevelSetForm) ? new LinearLevelSetFormVectorizer((ILevelSetForm)eq) : null);
            m_LsForm_GradUxV = DiffOp.GetArgMapping <ILevelSetForm_GradUxV>(true,
                                                                            eq => ((eq.LevelSetTerms & TermActivationFlags.GradUxV) != 0) && Compfilter(eq),
                                                                            eq => (eq is ILevelSetForm) ? new LinearLevelSetFormVectorizer((ILevelSetForm)eq) : null);
            m_LsForm_UxGradV = DiffOp.GetArgMapping <ILevelSetForm_UxGradV>(true,
                                                                            eq => ((eq.LevelSetTerms & TermActivationFlags.UxGradV) != 0) && Compfilter(eq),
                                                                            eq => (eq is ILevelSetForm) ? new LinearLevelSetFormVectorizer((ILevelSetForm)eq) : null);
            m_LsForm_GradUxGradV = DiffOp.GetArgMapping <ILevelSetForm_GradUxGradV>(true,
                                                                                    eq => ((eq.LevelSetTerms & TermActivationFlags.GradUxGradV) != 0) && Compfilter(eq),
                                                                                    eq => (eq is ILevelSetForm) ? new LinearLevelSetFormVectorizer((ILevelSetForm)eq) : null);
            m_LsForm_V = DiffOp.GetArgMapping <ILevelSetForm_V>(true,
                                                                eq => ((eq.LevelSetTerms & TermActivationFlags.V) != 0 && Compfilter(eq)),
                                                                eq => (eq is ILevelSetForm) ? new LinearLevelSetFormVectorizer((ILevelSetForm)eq) : null);
            m_LsForm_GradV = DiffOp.GetArgMapping <ILevelSetForm_GradV>(true,
                                                                        eq => ((eq.LevelSetTerms & TermActivationFlags.GradV) != 0) && Compfilter(eq),
                                                                        eq => (eq is ILevelSetForm) ? new LinearLevelSetFormVectorizer((ILevelSetForm)eq) : null);

            this.m_LsForm_UxV_Watches         = this.m_LsForm_UxV.InitStopWatches(0, this);
            this.m_LsForm_GradUxV_Watches     = this.m_LsForm_GradUxV.InitStopWatches(0, this);
            this.m_LsForm_UxGradV_Watches     = this.m_LsForm_UxGradV.InitStopWatches(0, this);
            this.m_LsForm_GradUxGradV_Watches = this.m_LsForm_GradUxGradV.InitStopWatches(0, this);
            this.m_LsForm_V_Watches           = this.m_LsForm_V.InitStopWatches(0, this);
            this.m_LsForm_GradV_Watches       = this.m_LsForm_GradV.InitStopWatches(0, this);

            // -----
            // alloc
            // -----

            AllocEmpty(m_LsForm_UxV, out Koeff_UxV, out Sum_Koeff_UxV, 5, false);
            AllocEmpty(m_LsForm_GradUxV, out Koeff_NablaUxV, out Sum_Koeff_NablaUxV, 6, false);
            AllocEmpty(m_LsForm_UxGradV, out Koeff_UxNablaV, out Sum_Koeff_UxNablaV, 6, false);
            AllocEmpty(m_LsForm_GradUxGradV, out Koeff_NablaUxNablaV, out Sum_Koeff_NablaUxNablaV, 7, false);

            AllocEmpty(m_LsForm_V, out Koeff_V, out Sum_Koeff_V, 3, true);
            AllocEmpty(m_LsForm_GradV, out Koeff_NablaV, out Sum_Koeff_NablaV, 4, true);
        }
        /// <summary>
        /// ctor.
        /// </summary>
        internal NECQuadratureLevelSet(IGridData context,
                                       XSpatialOperatorMk2 DiffOp,
                                       V __ResultVector,
                                       IList <DGField> __DomainFields,
                                       IList <DGField> __Parameters,
                                       UnsetteledCoordinateMapping CodomainMap,
                                       LevelSetTracker lsTrk, int _iLevSet, Tuple <SpeciesId, SpeciesId> SpeciesPair,
                                       ICompositeQuadRule <QuadRule> domAndRule) //
            : base(new int[] { CodomainMap.MaxTotalNoOfCoordinatesPerCell },
                   context,
                   domAndRule) //
        {
            // -----------------------------------
            // set members / check ctor parameters
            // -----------------------------------
            m_lsTrk            = lsTrk;
            this.m_LevSetIdx   = _iLevSet;
            this.m_SpeciesPair = SpeciesPair;
            this.ResultVector  = __ResultVector;
            m_CodomainMap      = CodomainMap;
            var _Parameters = (__Parameters != null) ? __Parameters.ToArray() : new DGField[0];

            if (__DomainFields.Count != DiffOp.DomainVar.Count)
            {
                throw new ArgumentException("mismatch between number of domain variables in spatial operator and given domain variables");
            }
            if (_Parameters.Length != DiffOp.ParameterVar.Count)
            {
                throw new ArgumentException("mismatch between number of parameter variables in spatial operator and given parameters");
            }
            if (m_CodomainMap.NoOfVariables != DiffOp.CodomainVar.Count)
            {
                throw new ArgumentException("mismatch between number of codomain variables in spatial operator and given codomain mapping");
            }

            m_DomainAndParamFields = ArrayTools.Cat(__DomainFields, _Parameters);
            this.DELTA             = __DomainFields.Count;

            // ------------------------
            // sort equation components
            // ------------------------

            int Gamma = m_CodomainMap.NoOfVariables;

            m_NonlinLsForm_V = DiffOp.GetArgMapping <INonlinLevelSetForm_V>(true,
                                                                            eq => ((eq.LevelSetTerms & (TermActivationFlags.V | TermActivationFlags.UxV | TermActivationFlags.GradUxV)) != 0) && Compfilter(eq),
                                                                            eq => (eq is ILevelSetForm) ? new NonlinearLevelSetFormVectorizer((ILevelSetForm)eq) : null);
            m_NonlinLsForm_GradV = DiffOp.GetArgMapping <INonlinLevelSetForm_GradV>(true,
                                                                                    eq => ((eq.LevelSetTerms & (TermActivationFlags.GradV | TermActivationFlags.UxGradV | TermActivationFlags.GradUxGradV)) != 0) && Compfilter(eq),
                                                                                    eq => (eq is ILevelSetForm) ? new NonlinearLevelSetFormVectorizer((ILevelSetForm)eq) : null);


            m_ValueRequired    = new bool[m_DomainAndParamFields.Length];
            m_GradientRequired = new bool[m_DomainAndParamFields.Length];

            m_NonlinLsForm_V.DetermineReqFields(m_GradientRequired,
                                                comp => ((comp.LevelSetTerms & (TermActivationFlags.GradUxGradV | TermActivationFlags.GradUxV)) != 0));
            m_NonlinLsForm_GradV.DetermineReqFields(m_GradientRequired,
                                                    comp => ((comp.LevelSetTerms & (TermActivationFlags.GradUxGradV | TermActivationFlags.GradUxV)) != 0));
            m_NonlinLsForm_V.DetermineReqFields(m_ValueRequired,
                                                comp => ((comp.LevelSetTerms & (TermActivationFlags.UxGradV | TermActivationFlags.UxV)) != 0));
            m_NonlinLsForm_GradV.DetermineReqFields(m_ValueRequired,
                                                    comp => ((comp.LevelSetTerms & (TermActivationFlags.UxGradV | TermActivationFlags.UxV)) != 0));

            for (int i = __DomainFields.Count; i < m_DomainAndParamFields.Length; i++)
            {
                m_ValueRequired[i] = true; // parameters are always required!
            }


            // -----
            // alloc
            // -----

            Koeff_V     = new MultidimensionalArray[Gamma];
            Koeff_GradV = new MultidimensionalArray[Gamma];
            for (int gamma = 0; gamma < Gamma; gamma++)
            {
                Koeff_V[gamma]     = new MultidimensionalArray(3);
                Koeff_GradV[gamma] = new MultidimensionalArray(4);
            }

            int L = m_DomainAndParamFields.Length;

            m_FieldValuesPos         = new MultidimensionalArray[L];
            m_FieldValuesNeg         = new MultidimensionalArray[L];
            m_FieldGradientValuesPos = new MultidimensionalArray[L];
            m_FieldGradientValuesNeg = new MultidimensionalArray[L];

            for (int l = 0; l < L; l++)
            {
                if (m_ValueRequired[l])
                {
                    m_FieldValuesPos[l] = new MultidimensionalArray(2);
                    m_FieldValuesNeg[l] = new MultidimensionalArray(2);
                }

                if (m_GradientRequired[l])
                {
                    m_FieldGradientValuesPos[l] = new MultidimensionalArray(3);
                    m_FieldGradientValuesNeg[l] = new MultidimensionalArray(3);
                }
            }


            // ------------------
            // init custom timers
            // ------------------

            base.CustomTimers             = new Stopwatch[] { new Stopwatch(), new Stopwatch(), new Stopwatch(), new Stopwatch(), new Stopwatch() };
            base.CustomTimers_Names       = new string[] { "Flux-Eval", "Basis-Eval", "Loops", "ParametersAndNormals", "Field-Eval" };
            base.CustomTimers_RootPointer = new int[5];
            ArrayTools.SetAll(base.CustomTimers_RootPointer, -1);

            this.m_NonlinLsForm_V_Watches     = this.m_NonlinLsForm_V.InitStopWatches(0, this);
            this.m_NonlinLsForm_GradV_Watches = this.m_NonlinLsForm_GradV.InitStopWatches(0, this);

            Flux_Eval            = base.CustomTimers[0];
            Basis_Eval           = base.CustomTimers[1];
            Loops                = base.CustomTimers[2];
            ParametersAndNormals = base.CustomTimers[3];
            Field_Eval           = base.CustomTimers[4];
        }