Exemple #1
0
        /// <summary>
        ///
        /// </summary>
        public void AssembleMatrix_Timestepper <T>(
            int CutCellQuadOrder,
            BlockMsrMatrix OpMatrix, double[] OpAffine,
            Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales,
            IEnumerable <T> CurrentState,
            VectorField <SinglePhaseField> SurfaceForce,
            VectorField <SinglePhaseField> LevelSetGradient, SinglePhaseField ExternalyProvidedCurvature,
            UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping,
            double time, IEnumerable <T> CoupledCurrentState = null, IEnumerable <T> CoupledParams = null) where T : DGField
        {
            if (ColMapping.BasisS.Count != this.Op.DomainVar.Count)
            {
                throw new ArgumentException();
            }
            if (RowMapping.BasisS.Count != this.Op.CodomainVar.Count)
            {
                throw new ArgumentException();
            }

            // check:
            var Tracker = this.LsTrk;
            int D       = Tracker.GridDat.SpatialDimension;

            if (CurrentState != null && CurrentState.Count() != (D + 1))
            {
                throw new ArgumentException();
            }
            if (OpMatrix == null && CurrentState == null)
            {
                throw new ArgumentException();
            }
            DGField[] U0;
            if (CurrentState != null)
            {
                U0 = CurrentState.Take(D).ToArray();
            }
            else
            {
                U0 = null;
            }



            LevelSet Phi = (LevelSet)(Tracker.LevelSets[0]);

            SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray();

            IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengths = this.LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), CutCellQuadOrder).CutCellMetrics.InterfaceArea;


            // advanced settings for the navier slip boundary condition
            // ========================================================

            CellMask SlipArea;

            switch (this.dntParams.GNBC_Localization)
            {
            case NavierSlip_Localization.Bulk: {
                SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask;
                break;
            }

            case NavierSlip_Localization.ContactLine: {
                SlipArea = null;
                break;
            }

            case NavierSlip_Localization.Nearband: {
                SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask.Intersect(this.LsTrk.Regions.GetNearFieldMask(this.LsTrk.NearRegionWidth));
                break;
            }

            case NavierSlip_Localization.Prescribed: {
                throw new NotImplementedException();
            }

            default:
                throw new ArgumentException();
            }


            MultidimensionalArray SlipLengths;

            SlipLengths = this.LsTrk.GridDat.Cells.h_min.CloneAs();
            SlipLengths.Clear();
            //SlipLengths.AccConstant(-1.0);

            if (SlipArea != null)
            {
                foreach (Chunk cnk in SlipArea)
                {
                    for (int i = cnk.i0; i < cnk.JE; i++)
                    {
                        switch (this.dntParams.GNBC_SlipLength)
                        {
                        case NavierSlip_SlipLength.hmin_DG: {
                            int degU = ColMapping.BasisS.ToArray()[0].Degree;
                            SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i] / (degU + 1);
                            break;
                        }

                        case NavierSlip_SlipLength.hmin_Grid: {
                            SlipLengths[i] = SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i];
                            break;
                        }

                        case NavierSlip_SlipLength.Prescribed_SlipLength: {
                            SlipLengths[i] = this.physParams.sliplength;
                            break;
                        }

                        case NavierSlip_SlipLength.Prescribed_Beta: {
                            SlipLengths[i] = -1.0;
                            break;
                        }
                        }
                    }
                }
            }


            // parameter assembly
            // ==================

            // normals:
            SinglePhaseField[] Normals; // Normal vectors: length not normalized - will be normalized at each quad node within the flux functions.
            if (this.NormalsRequired)
            {
                if (LevelSetGradient == null)
                {
                    LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, SinglePhaseField.Factory);
                    LevelSetGradient.Gradient(1.0, Phi);
                }
                Normals = LevelSetGradient.ToArray();
            }
            else
            {
                Normals = new SinglePhaseField[D];
            }

            // curvature:
            SinglePhaseField Curvature;

            if (this.CurvatureRequired)
            {
                Curvature = ExternalyProvidedCurvature;
            }
            else
            {
                Curvature = null;
            }

            // linearization velocity:
            DGField[] U0_U0mean;
            if (this.U0meanrequired)
            {
                XDGBasis U0meanBasis          = new XDGBasis(Tracker, 0);
                VectorField <XDGField> U0mean = new VectorField <XDGField>(D, U0meanBasis, "U0mean_", XDGField.Factory);

                U0_U0mean = ArrayTools.Cat <DGField>(U0, U0mean);
            }
            else
            {
                U0_U0mean = new DGField[2 * D];
            }

            // Temperature gradient for evaporation
            VectorField <DGField> GradTemp = new VectorField <DGField>(D, U0[0].Basis, XDGField.Factory);

            if (CoupledCurrentState != null)
            {
                DGField Temp = CoupledCurrentState.ToArray()[0];
                GradTemp = new VectorField <DGField>(D, Temp.Basis, "GradTemp", XDGField.Factory);
                XNSEUtils.ComputeGradientForParam(Temp, GradTemp, this.LsTrk);
            }

            // concatenate everything
            var Params = ArrayTools.Cat <DGField>(
                U0_U0mean,
                Curvature,
                ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D]),
                Normals,
                ((evaporation) ? GradTemp.ToArray() : new SinglePhaseField[D]),
                ((evaporation) ? CoupledCurrentState.ToArray <DGField>() : new SinglePhaseField[1]),
                ((evaporation) ? CoupledParams.ToArray <DGField>() : new SinglePhaseField[1]));  //((evaporation) ? GradTemp.ToArray() : new SinglePhaseField[D]));

            // linearization velocity:
            if (this.U0meanrequired)
            {
                VectorField <XDGField> U0mean = new VectorField <XDGField>(U0_U0mean.Skip(D).Take(D).Select(f => ((XDGField)f)).ToArray());

                U0mean.Clear();
                if (this.physParams.IncludeConvection)
                {
                    ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper);
                }
            }



            // assemble the matrix & affine vector
            // ===================================

            // compute matrix
            if (OpMatrix != null)
            {
                //Op.ComputeMatrixEx(Tracker,
                //    ColMapping, Params, RowMapping,
                //    OpMatrix, OpAffine, false, time, true,
                //    AgglomeratedCellLengthScales,
                //    InterfaceLengths, SlipLengths,
                //    SpcToCompute);

                XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(LsTrk, ColMapping, Params, RowMapping, SpcToCompute);

                foreach (var kv in AgglomeratedCellLengthScales)
                {
                    mtxBuilder.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value;
                    mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths);
                }

                if (Op.SurfaceElementOperator.TotalNoOfComponents > 0)
                {
                    foreach (var kv in InterfaceLengths)
                    {
                        mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value);
                    }
                }

                mtxBuilder.time = time;

                mtxBuilder.ComputeMatrix(OpMatrix, OpAffine);
            }
            else
            {
                XSpatialOperatorMk2.XEvaluatorNonlin eval = Op.GetEvaluatorEx(Tracker,
                                                                              CurrentState.ToArray(), Params, RowMapping,
                                                                              SpcToCompute);

                foreach (var kv in AgglomeratedCellLengthScales)
                {
                    eval.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value;
                    eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths);
                }

                if (Op.SurfaceElementOperator.TotalNoOfComponents > 0)
                {
                    foreach (var kv in InterfaceLengths)
                    {
                        eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value);
                    }
                }

                eval.time = time;

                eval.Evaluate(1.0, 1.0, OpAffine);

#if DEBUG
                // remark: remove this piece in a few months from now on (09may18) if no problems occur
                //{

                //    BlockMsrMatrix checkOpMatrix = new BlockMsrMatrix(RowMapping, ColMapping);
                //    double[] checkAffine = new double[OpAffine.Length];

                //    Op.ComputeMatrixEx(Tracker,
                //    ColMapping, Params, RowMapping,
                //    OpMatrix, OpAffine, false, time, true,
                //    AgglomeratedCellLengthScales,
                //    InterfaceLengths, SlipLengths,
                //    SpcToCompute);


                //    double[] checkResult = checkAffine.CloneAs();
                //    var currentVec = new CoordinateVector(CurrentState.ToArray());
                //    checkOpMatrix.SpMV(1.0, new CoordinateVector(CurrentState.ToArray()), 1.0, checkResult);

                //    double L2_dist = GenericBlas.L2DistPow2(checkResult, OpAffine).MPISum().Sqrt();
                //    double RefNorm = (new double[] { checkResult.L2NormPow2(), OpAffine.L2NormPow2(), currentVec.L2NormPow2() }).MPISum().Max().Sqrt();

                //    Assert.LessOrEqual(L2_dist, RefNorm * 1.0e-6);
                //    Debug.Assert(L2_dist < RefNorm * 1.0e-6);
                //}
#endif
            }


            // check
            // =====

            /*
             * {
             *  DGField[] testDomainFieldS = ColMapping.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray();
             *  CoordinateVector test = new CoordinateVector(testDomainFieldS);
             *
             *  DGField[] errFieldS = ColMapping.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray();
             *  CoordinateVector Err = new CoordinateVector(errFieldS);
             *
             *  var eval = Op.GetEvaluatorEx(LsTrk,
             *      testDomainFieldS, Params, RowMapping);
             *
             *  foreach (var s in this.LsTrk.SpeciesIdS)
             *      eval.SpeciesOperatorCoefficients[s].CellLengthScales = AgglomeratedCellLengthScales[s];
             *
             *  eval.time = time;
             *  int L = test.Count;
             *  Random r = new Random();
             *  for(int i = 0; i < L; i++) {
             *      test[i] = r.NextDouble();
             *  }
             *
             *
             *
             *  double[] R1 = new double[L];
             *  double[] R2 = new double[L];
             *  eval.Evaluate(1.0, 1.0, R1);
             *
             *  R2.AccV(1.0, OpAffine);
             *  OpMatrix.SpMV(1.0, test, 1.0, R2);
             *
             *  Err.AccV(+1.0, R1);
             *  Err.AccV(-1.0, R2);
             *
             *  double ErrDist = GenericBlas.L2DistPow2(R1, R2).MPISum().Sqrt();
             *
             *  double Ref = test.L2NormPow2().MPISum().Sqrt();
             *
             *  Debug.Assert(ErrDist <= Ref*1.0e-5, "Mismatch between explicit evaluation of XDG operator and matrix.");
             * }
             */
        }
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="OpMatrix"></param>
        /// <param name="OpAffine"></param>
        /// <param name="RowMapping"></param>
        /// <param name="ColMapping"></param>
        /// <param name="CurrentState"></param>
        /// <param name="AgglomeratedCellLengthScales"></param>
        /// <param name="time"></param>
        /// <param name="CutCellQuadOrder"></param>
        /// <param name="SurfaceForce"></param>
        /// <param name="LevelSetGradient"></param>
        /// <param name="ExternalyProvidedCurvature"></param>
        public void AssembleMatrix <T>(BlockMsrMatrix OpMatrix, double[] OpAffine,
                                       UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping,
                                       IEnumerable <T> CurrentState, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales, double time,
                                       int CutCellQuadOrder, VectorField <SinglePhaseField> SurfaceForce,
                                       VectorField <SinglePhaseField> LevelSetGradient, SinglePhaseField ExternalyProvidedCurvature,
                                       IEnumerable <T> CoupledCurrentState = null, IEnumerable <T> CoupledParams = null) where T : DGField
        {
            // checks:
            if (ColMapping.BasisS.Count != this.m_XOp.DomainVar.Count)
            {
                throw new ArgumentException();
            }
            if (RowMapping.BasisS.Count != this.m_XOp.CodomainVar.Count)
            {
                throw new ArgumentException();
            }

            int D = this.LsTrk.GridDat.SpatialDimension;

            if (CurrentState != null && CurrentState.Count() != (D + 1))
            {
                throw new ArgumentException();
            }

            if (OpMatrix == null && CurrentState == null)
            {
                throw new ArgumentException();
            }

            DGField[] U0;
            if (CurrentState != null)
            {
                U0 = CurrentState.Take(D).ToArray();
            }
            else
            {
                U0 = null;
            }



            // advanced settings for the navier slip boundary condition
            // ========================================================

            CellMask SlipArea;

            switch (this.dntParams.GNBC_Localization)
            {
            case NavierSlip_Localization.Bulk: {
                SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask;
                break;
            }

            case NavierSlip_Localization.ContactLine: {
                SlipArea = null;
                break;
            }

            case NavierSlip_Localization.Nearband: {
                SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask.Intersect(this.LsTrk.Regions.GetNearFieldMask(this.LsTrk.NearRegionWidth));
                break;
            }

            case NavierSlip_Localization.Prescribed: {
                throw new NotImplementedException();
            }

            default:
                throw new ArgumentException();
            }


            MultidimensionalArray SlipLengths;

            SlipLengths = this.LsTrk.GridDat.Cells.h_min.CloneAs();
            SlipLengths.Clear();
            //SlipLengths.AccConstant(-1.0);
            if (SlipArea != null)
            {
                foreach (Chunk cnk in SlipArea)
                {
                    for (int i = cnk.i0; i < cnk.JE; i++)
                    {
                        switch (this.dntParams.GNBC_SlipLength)
                        {
                        case NavierSlip_SlipLength.hmin_DG: {
                            int degU = ColMapping.BasisS.ToArray()[0].Degree;
                            SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i] / (degU + 1);
                            break;
                        }

                        case NavierSlip_SlipLength.hmin_Grid: {
                            SlipLengths[i] = SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i];
                            break;
                        }

                        case NavierSlip_SlipLength.Prescribed_SlipLength: {
                            SlipLengths[i] = this.physParams.sliplength;
                            break;
                        }

                        case NavierSlip_SlipLength.Prescribed_Beta: {
                            SlipLengths[i] = -1.0;
                            break;
                        }
                        }
                    }
                }
            }


            // parameter assembly
            // ==================

            LevelSet Phi = (LevelSet)(this.LsTrk.LevelSets[0]);

            SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray();

            // normals:
            SinglePhaseField[] Normals; // Normal vectors: length not normalized - will be normalized at each quad node within the flux functions.
            if (this.NormalsRequired)
            {
                if (LevelSetGradient == null)
                {
                    LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, SinglePhaseField.Factory);
                    LevelSetGradient.Gradient(1.0, Phi);
                }
                Normals = LevelSetGradient.ToArray();
            }
            else
            {
                Normals = new SinglePhaseField[D];
            }

            // curvature:
            SinglePhaseField Curvature;

            if (this.CurvatureRequired)
            {
                Curvature = ExternalyProvidedCurvature;
            }
            else
            {
                Curvature = null;
            }

            // linearization velocity:
            DGField[] U0_U0mean;
            if (this.U0meanrequired)
            {
                XDGBasis U0meanBasis          = new XDGBasis(this.LsTrk, 0);
                VectorField <XDGField> U0mean = new VectorField <XDGField>(D, U0meanBasis, "U0mean_", XDGField.Factory);

                U0_U0mean = ArrayTools.Cat <DGField>(U0, U0mean);
            }
            else
            {
                U0_U0mean = new DGField[2 * D];
            }

            // Temperature gradient for evaporation
            VectorField <DGField> GradTemp = new VectorField <DGField>(D, new XDGBasis(LsTrk, 0), XDGField.Factory);

            if (CoupledCurrentState != null)
            {
                DGField Temp = CoupledCurrentState.ToArray()[0];
                GradTemp = new VectorField <DGField>(D, Temp.Basis, "GradTemp", XDGField.Factory);
                XNSEUtils.ComputeGradientForParam(Temp, GradTemp, this.LsTrk);
            }

            // concatenate everything
            var Params = ArrayTools.Cat <DGField>(
                U0_U0mean,
                Curvature,
                ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D]),
                Normals,
                ((CoupledCurrentState != null) ? GradTemp.ToArray() : new SinglePhaseField[D]),
                ((CoupledCurrentState != null) ? CoupledCurrentState.ToArray <DGField>() : new SinglePhaseField[1]),
                ((CoupledCurrentState != null) ? CoupledParams.ToArray <DGField>() : new SinglePhaseField[1]));  //((evaporation) ? GradTemp.ToArray() : new SinglePhaseField[D]));

            // linearization velocity:
            if (this.U0meanrequired)
            {
                VectorField <XDGField> U0mean = new VectorField <XDGField>(U0_U0mean.Skip(D).Take(D).Select(f => ((XDGField)f)).ToArray());

                U0mean.Clear();
                if (this.physParams.IncludeConvection)
                {
                    ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper);
                }
            }



            // assemble the matrix & affine vector
            // ===================================

            IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengths = this.LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), CutCellQuadOrder).CutCellMetrics.InterfaceArea;

            // compute matrix
            if (OpMatrix != null)
            {
                XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = this.m_XOp.GetMatrixBuilder(LsTrk, ColMapping, Params, RowMapping, SpcToCompute);

                foreach (var kv in AgglomeratedCellLengthScales)
                {
                    mtxBuilder.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value;
                    mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths);
                }

                if (this.m_XOp.SurfaceElementOperator.TotalNoOfComponents > 0)
                {
                    foreach (var kv in InterfaceLengths)
                    {
                        mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value);
                    }
                }

                mtxBuilder.time = time;

                mtxBuilder.ComputeMatrix(OpMatrix, OpAffine);
            }
            else
            {
                XSpatialOperatorMk2.XEvaluatorNonlin eval = this.m_XOp.GetEvaluatorEx(this.LsTrk,
                                                                                      CurrentState.ToArray(), Params, RowMapping,
                                                                                      SpcToCompute);

                foreach (var kv in AgglomeratedCellLengthScales)
                {
                    eval.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value;
                    eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths);
                }

                if (this.m_XOp.SurfaceElementOperator.TotalNoOfComponents > 0)
                {
                    foreach (var kv in InterfaceLengths)
                    {
                        eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value);
                    }
                }

                eval.time = time;

                eval.Evaluate(1.0, 1.0, OpAffine);
            }
        }
Exemple #3
0
        /// <summary>
        /// Computes the new level set field at time <paramref name="Phystime"/> + <paramref name="dt"/>.
        /// This is a 'driver function' which provides a universal interface to the various level set evolution algorithms.
        /// It also acts as a callback to the time stepper (see <see cref="m_BDF_Timestepper"/> resp. <see cref="m_RK_Timestepper"/>),
        /// i.e. it matches the signature of
        /// <see cref="BoSSS.Solution.XdgTimestepping.DelUpdateLevelset"/>.
        /// </summary>
        /// <param name="Phystime"></param>
        /// <param name="dt"></param>
        /// <param name="CurrentState">
        /// The current solution (velocity and pressure), since the complete solution is provided by the time stepper,
        /// only the velocity components(supposed to be at the beginning) are used.
        /// </param>
        /// <param name="underrelax">
        /// </param>
        public double DelUpdateLevelSet(DGField[] CurrentState, double Phystime, double dt, double underrelax, bool incremental)
        {
            using (new FuncTrace()) {
                //dt *= underrelax;
                int       D           = base.Grid.SpatialDimension;
                int       iTimestep   = hack_TimestepIndex;
                DGField[] EvoVelocity = CurrentState.GetSubVector(0, D);


                // ========================================================
                // Backup old level-set, in order to compute the residual
                // ========================================================

                SinglePhaseField LsBkUp = new SinglePhaseField(this.LevSet.Basis);
                LsBkUp.Acc(1.0, this.LevSet);
                CellMask oldCC = LsTrk.Regions.GetCutCellMask();

                // ====================================================
                // set evolution velocity, but only on the CUT-cells
                // ====================================================

                #region Calculate density averaged Velocity for each cell

                ConventionalDGField[] meanVelocity = GetMeanVelocityFromXDGField(EvoVelocity);

                #endregion


                // ===================================================================
                // backup interface properties (mass conservation, surface changerate)
                // ===================================================================

                #region backup interface props

                double oldSurfVolume  = 0.0;
                double oldSurfLength  = 0.0;
                double SurfChangerate = 0.0;
                if (this.Control.CheckInterfaceProps)
                {
                    oldSurfVolume  = XNSEUtils.GetSpeciesArea(this.LsTrk, LsTrk.GetSpeciesId("A"));
                    oldSurfLength  = XNSEUtils.GetInterfaceLength(this.LsTrk);
                    SurfChangerate = EnergyUtils.GetSurfaceChangerate(this.LsTrk, meanVelocity, this.m_HMForder);
                }

                #endregion

                // ====================================================
                // perform level-set evolution
                // ====================================================

                #region level-set evolution

                // set up for Strang splitting
                SinglePhaseField DGLevSet_old;
                if (incremental)
                {
                    DGLevSet_old = this.DGLevSet.Current.CloneAs();
                }
                else
                {
                    DGLevSet_old = this.DGLevSet[0].CloneAs();
                }


                // set up for underrelaxation
                SinglePhaseField DGLevSet_oldIter = this.DGLevSet.Current.CloneAs();

                //PlotCurrentState(hack_Phystime, new TimestepNumber(new int[] { hack_TimestepIndex, 0 }), 2);

                // actual evolution
                switch (this.Control.Option_LevelSetEvolution)
                {
                case LevelSetEvolution.None:
                    throw new ArgumentException("illegal call");

                case LevelSetEvolution.FastMarching: {
                    NarrowMarchingBand.Evolve_Mk2(
                        dt, this.LsTrk, DGLevSet_old, this.DGLevSet.Current, this.DGLevSetGradient,
                        meanVelocity, this.ExtensionVelocity.Current.ToArray(),      //new DGField[] { LevSetSrc },
                        this.m_HMForder, iTimestep);

                    //FastMarchReinitSolver = new FastMarchReinit(DGLevSet.Current.Basis);
                    //CellMask Accepted = LsTrk.Regions.GetCutCellMask();
                    //CellMask ActiveField = LsTrk.Regions.GetNearFieldMask(1);
                    //CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A");
                    //FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField);

                    break;
                }

                case LevelSetEvolution.Fourier: {
                    Fourier_Timestepper.moveLevelSet(dt, meanVelocity);
                    if (incremental)
                    {
                        Fourier_Timestepper.updateFourierLevSet();
                    }
                    Fourier_LevSet.ProjectToDGLevelSet(this.DGLevSet.Current, this.LsTrk);
                    break;
                }

                case LevelSetEvolution.Prescribed: {
                    this.DGLevSet.Current.Clear();
                    this.DGLevSet.Current.ProjectField(1.0, this.Control.Phi.Vectorize(Phystime + dt));
                    break;
                }

                case LevelSetEvolution.ScalarConvection: {
                    var LSM = new LevelSetMover(EvoVelocity,
                                                this.ExtensionVelocity,
                                                this.LsTrk,
                                                XVelocityProjection.CutCellVelocityProjectiontype.L2_plain,
                                                this.DGLevSet,
                                                this.BcMap);

                    int check1 = this.ExtensionVelocity.PushCount;
                    int check2 = this.DGLevSet.PushCount;

                    this.DGLevSet[1].Clear();
                    this.DGLevSet[1].Acc(1.0, DGLevSet_old);
                    LSM.Advect(dt);

                    if (check1 != this.ExtensionVelocity.PushCount)
                    {
                        throw new ApplicationException();
                    }
                    if (check2 != this.DGLevSet.PushCount)
                    {
                        throw new ApplicationException();
                    }

                    break;
                }

                case LevelSetEvolution.ExtensionVelocity: {
                    DGLevSetGradient.Clear();
                    DGLevSetGradient.Gradient(1.0, DGLevSet.Current);

                    ExtVelMover.Advect(dt);

                    // Fast Marching: Specify the Domains first
                    // Perform Fast Marching only on the Far Field
                    if (this.Control.AdaptiveMeshRefinement)
                    {
                        int      NoCells = ((GridData)this.GridData).Cells.Count;
                        BitArray Refined = new BitArray(NoCells);
                        for (int j = 0; j < NoCells; j++)
                        {
                            if (((GridData)this.GridData).Cells.GetCell(j).RefinementLevel > 0)
                            {
                                Refined[j] = true;
                            }
                        }
                        CellMask Accepted      = new CellMask(this.GridData, Refined);
                        CellMask AcceptedNeigh = Accepted.AllNeighbourCells();

                        Accepted = Accepted.Union(AcceptedNeigh);
                        CellMask ActiveField   = Accepted.Complement();
                        CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A");
                        FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField);
                    }
                    else
                    {
                        CellMask Accepted      = LsTrk.Regions.GetNearFieldMask(1);
                        CellMask ActiveField   = Accepted.Complement();
                        CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A");
                        FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField);
                    }
                    //SubGrid AcceptedGrid = new SubGrid(Accepted);
                    //ReInitPDE.ReInitialize(Restriction: AcceptedGrid);

                    //CellMask ActiveField = Accepted.Complement();
                    //CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A");
                    //FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField);

                    //ReInitPDE.ReInitialize();

                    break;
                }

                default:
                    throw new ApplicationException();
                }


                // performing underrelaxation
                if (underrelax < 1.0)
                {
                    this.DGLevSet.Current.Scale(underrelax);
                    this.DGLevSet.Current.Acc((1.0 - underrelax), DGLevSet_oldIter);
                }

                //PlotCurrentState(hack_Phystime, new TimestepNumber(new int[] { hack_TimestepIndex, 1 }), 2);


                #endregion


                // ======================
                // postprocessing
                // =======================

                if (this.Control.ReInitPeriod > 0 && hack_TimestepIndex % this.Control.ReInitPeriod == 0)
                {
                    Console.WriteLine("Filtering DG-LevSet");
                    SinglePhaseField FiltLevSet = new SinglePhaseField(DGLevSet.Current.Basis);
                    FiltLevSet.AccLaidBack(1.0, DGLevSet.Current);
                    Filter(FiltLevSet, 2, oldCC);
                    DGLevSet.Current.Clear();
                    DGLevSet.Current.Acc(1.0, FiltLevSet);

                    Console.WriteLine("FastMarchReInit performing FirstOrderReInit");
                    FastMarchReinitSolver = new FastMarchReinit(DGLevSet.Current.Basis);
                    CellMask Accepted      = LsTrk.Regions.GetCutCellMask();
                    CellMask ActiveField   = LsTrk.Regions.GetNearFieldMask(1);
                    CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A");
                    FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField);
                }

                #region ensure continuity

                // make level set continuous
                CellMask CC    = LsTrk.Regions.GetCutCellMask4LevSet(0);
                CellMask Near1 = LsTrk.Regions.GetNearMask4LevSet(0, 1);
                CellMask PosFF = LsTrk.Regions.GetLevelSetWing(0, +1).VolumeMask;
                ContinuityEnforcer.MakeContinuous(this.DGLevSet.Current, this.LevSet, Near1, PosFF);

                if (this.Control.Option_LevelSetEvolution == LevelSetEvolution.FastMarching)
                {
                    CellMask Nearband = Near1.Union(CC);
                    this.DGLevSet.Current.Clear(Nearband);
                    this.DGLevSet.Current.AccLaidBack(1.0, this.LevSet, Nearband);
                    //ContinuityEnforcer.SetFarField(this.DGLevSet.Current, Near1, PosFF);
                }

                //PlotCurrentState(hack_Phystime, new TimestepNumber(new int[] { hack_TimestepIndex, 2 }), 2);

                #endregion


                for (int d = 0; d < D; d++)
                {
                    this.XDGvelocity.Velocity[d].UpdateBehaviour = BehaveUnder_LevSetMoovement.AutoExtrapolate;
                }



                // ===============
                // tracker update
                // ===============

                this.LsTrk.UpdateTracker(Phystime + dt, incremental: true);

                // update near field (in case of adaptive mesh refinement)
                if (this.Control.AdaptiveMeshRefinement && this.Control.Option_LevelSetEvolution == LevelSetEvolution.FastMarching)
                {
                    Near1 = LsTrk.Regions.GetNearMask4LevSet(0, 1);
                    PosFF = LsTrk.Regions.GetLevelSetWing(0, +1).VolumeMask;
                    ContinuityEnforcer.SetFarField(this.DGLevSet.Current, Near1, PosFF);
                    ContinuityEnforcer.SetFarField(this.LevSet, Near1, PosFF);
                }


                // ==================================================================
                // check interface properties (mass conservation, surface changerate)
                // ==================================================================

                if (this.Control.CheckInterfaceProps)
                {
                    double currentSurfVolume = XNSEUtils.GetSpeciesArea(this.LsTrk, LsTrk.GetSpeciesId("A"));
                    double massChange        = ((currentSurfVolume - oldSurfVolume) / oldSurfVolume) * 100;
                    Console.WriteLine("Change of mass = {0}%", massChange);

                    double currentSurfLength    = XNSEUtils.GetInterfaceLength(this.LsTrk);
                    double actualSurfChangerate = (currentSurfLength - oldSurfLength) / dt;
                    Console.WriteLine("Interface divergence = {0}", SurfChangerate);
                    Console.WriteLine("actual surface changerate = {0}", actualSurfChangerate);
                }


                // ==================
                // compute residual
                // ==================

                var newCC = LsTrk.Regions.GetCutCellMask();
                LsBkUp.Acc(-1.0, this.LevSet);
                double LevSetResidual = LsBkUp.L2Norm(newCC.Union(oldCC));

                return(LevSetResidual);
            }
        }
        /// <summary>
        ///
        /// </summary>
        public void AssembleMatrix <T>(BlockMsrMatrix OpMatrix, double[] OpAffine,
                                       UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping,
                                       IEnumerable <T> CurrentState, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales, double time,
                                       int CutCellQuadOrder, VectorField <SinglePhaseField> SurfaceForce,
                                       VectorField <SinglePhaseField> LevelSetGradient, SinglePhaseField ExternalyProvidedCurvature,
                                       bool[] updateSolutionParams = null, DGField[] ExtParams = null) where T : DGField
        {
            //IEnumerable<T> CoupledCurrentState = null, IEnumerable<T> CoupledParams = null) where T : DGField {

            // checks:
            if (ColMapping.BasisS.Count != this.m_XOp.DomainVar.Count)
            {
                throw new ArgumentException();
            }
            if (RowMapping.BasisS.Count != this.m_XOp.CodomainVar.Count)
            {
                throw new ArgumentException();
            }

            int D = this.LsTrk.GridDat.SpatialDimension;

            if (CurrentState != null && !config.solveEnergy && !config.solveHeat && CurrentState.Count() != (D + 1))
            {
                throw new ArgumentException();
            }

            if (OpMatrix == null && CurrentState == null)
            {
                throw new ArgumentException();
            }

            DGField[] U0;
            if (CurrentState != null)
            {
                U0 = CurrentState.Take(D).ToArray();
            }
            else
            {
                U0 = null;
            }



            // parameter assembly
            // ==================
            #region param assembly

            LevelSet    Phi          = (LevelSet)(this.LsTrk.LevelSets[0]);
            SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray();


            // linearization velocity:
            DGField[] U0_U0mean;
            if (this.U0meanrequired)
            {
                XDGBasis U0meanBasis          = new XDGBasis(this.LsTrk, 0);
                VectorField <XDGField> U0mean = new VectorField <XDGField>(D, U0meanBasis, "U0mean_", XDGField.Factory);
                U0mean.Clear();
                if (this.physParams.IncludeConvection)
                {
                    ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper);
                }

                U0_U0mean = ArrayTools.Cat <DGField>(U0, U0mean);
            }
            else
            {
                U0_U0mean = new DGField[2 * D];
            }

            // linearization velocity:
            //if (this.U0meanrequired) {
            //    VectorField<XDGField> U0mean = new VectorField<XDGField>(U0_U0mean.Skip(D).Take(D).Select(f => ((XDGField)f)).ToArray());

            //    U0mean.Clear();
            //    if (this.physParams.IncludeConvection)
            //        ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper);
            //}


            // normals:
            SinglePhaseField[] Normals; // Normal vectors: length not normalized - will be normalized at each quad node within the flux functions.
            if (this.NormalsRequired)
            {
                if (LevelSetGradient == null)
                {
                    LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, SinglePhaseField.Factory);
                    LevelSetGradient.Gradient(1.0, Phi);
                }
                Normals = LevelSetGradient.ToArray();
            }
            else
            {
                Normals = new SinglePhaseField[D];
            }

            // curvature:
            SinglePhaseField Curvature;
            if (this.CurvatureRequired)
            {
                Curvature = ExternalyProvidedCurvature;
            }
            else
            {
                Curvature = null;
            }


            // velocity gradient vectors
            var       VelMap   = new CoordinateMapping(U0);
            DGField[] VelParam = VelMap.Fields.ToArray();

            VectorField <DGField> GradVelX = new VectorField <DGField>(D, VelParam[0].Basis, "VelocityXGradient", XDGField.Factory);
            for (int d = 0; d < D; d++)
            {
                foreach (var Spc in this.LsTrk.SpeciesIdS)
                {
                    DGField f_Spc = ((VelParam[0] as XDGField).GetSpeciesShadowField(Spc));
                    SubGrid sf    = this.LsTrk.Regions.GetSpeciesSubGrid(Spc);
                    (GradVelX[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf);
                }
            }
            GradVelX.ForEach(F => F.CheckForNanOrInf(true, true, true));

            VectorField <DGField> GradVelY = new VectorField <DGField>(D, VelParam[0].Basis, "VelocityYGradient", XDGField.Factory);
            for (int d = 0; d < D; d++)
            {
                foreach (var Spc in this.LsTrk.SpeciesIdS)
                {
                    DGField f_Spc = ((VelParam[1] as XDGField).GetSpeciesShadowField(Spc));
                    SubGrid sf    = this.LsTrk.Regions.GetSpeciesSubGrid(Spc);
                    (GradVelY[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf);
                }
            }
            GradVelY.ForEach(F => F.CheckForNanOrInf(true, true, true));


            VectorField <DGField> GradVelXGradX = new VectorField <DGField>(D, VelParam[0].Basis, "VelocityXGradX_Gradient", XDGField.Factory);
            for (int d = 0; d < D; d++)
            {
                foreach (var Spc in this.LsTrk.SpeciesIdS)
                {
                    DGField f_Spc = ((GradVelX[0] as XDGField).GetSpeciesShadowField(Spc));
                    SubGrid sf    = this.LsTrk.Regions.GetSpeciesSubGrid(Spc);
                    (GradVelXGradX[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf);
                }
            }
            GradVelXGradX.ForEach(F => F.CheckForNanOrInf(true, true, true));

            VectorField <DGField> GradVelXGradY = new VectorField <DGField>(D, VelParam[0].Basis, "VelocityXGradY_Gradient", XDGField.Factory);
            for (int d = 0; d < D; d++)
            {
                foreach (var Spc in this.LsTrk.SpeciesIdS)
                {
                    DGField f_Spc = ((GradVelX[1] as XDGField).GetSpeciesShadowField(Spc));
                    SubGrid sf    = this.LsTrk.Regions.GetSpeciesSubGrid(Spc);
                    (GradVelXGradY[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf);
                }
            }
            GradVelXGradY.ForEach(F => F.CheckForNanOrInf(true, true, true));

            VectorField <DGField> GradVelYGradX = new VectorField <DGField>(D, VelParam[0].Basis, "VelocityYGradX_Gradient", XDGField.Factory);
            for (int d = 0; d < D; d++)
            {
                foreach (var Spc in this.LsTrk.SpeciesIdS)
                {
                    DGField f_Spc = ((GradVelY[0] as XDGField).GetSpeciesShadowField(Spc));
                    SubGrid sf    = this.LsTrk.Regions.GetSpeciesSubGrid(Spc);
                    (GradVelYGradX[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf);
                }
            }
            GradVelYGradX.ForEach(F => F.CheckForNanOrInf(true, true, true));

            VectorField <DGField> GradVelYGradY = new VectorField <DGField>(D, VelParam[0].Basis, "VelocityYGradY_Gradient", XDGField.Factory);
            for (int d = 0; d < D; d++)
            {
                foreach (var Spc in this.LsTrk.SpeciesIdS)
                {
                    DGField f_Spc = ((GradVelY[1] as XDGField).GetSpeciesShadowField(Spc));
                    SubGrid sf    = this.LsTrk.Regions.GetSpeciesSubGrid(Spc);
                    (GradVelYGradY[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf);
                }
            }
            GradVelYGradY.ForEach(F => F.CheckForNanOrInf(true, true, true));



            // pressure and gradient
            var       PressMap   = new CoordinateMapping(CurrentState.ToArray()[D]);
            DGField[] PressParam = PressMap.Fields.ToArray();

            VectorField <DGField> PressGrad = new VectorField <DGField>(D, PressParam[0].Basis, "PressureGrad", XDGField.Factory);
            for (int d = 0; d < D; d++)
            {
                foreach (var Spc in this.LsTrk.SpeciesIdS)
                {
                    DGField f_Spc = ((PressParam[0] as XDGField).GetSpeciesShadowField(Spc));
                    SubGrid sf    = this.LsTrk.Regions.GetSpeciesSubGrid(Spc);
                    (PressGrad[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf);
                }
            }
            PressGrad.ForEach(F => F.CheckForNanOrInf(true, true, true));

            // gravity
            var       GravMap   = new CoordinateMapping(ExtParams);
            DGField[] GravParam = GravMap.Fields.ToArray();


            // heat flux for evaporation
            DGField[] HeatFluxParam = new DGField[D];
            if (config.solveHeat)
            {
                if (config.conductMode == ConductivityInSpeciesBulk.ConductivityMode.SIP && updateSolutionParams[D + 1])
                {
                    HeatFluxParam = new VectorField <XDGField>(D, CurrentState.ToArray()[D + 1].Basis, "HeatFlux0_", XDGField.Factory).ToArray();
                    Dictionary <string, double> kSpc = new Dictionary <string, double>();
                    kSpc.Add("A", -thermParams.k_A);
                    kSpc.Add("B", -thermParams.k_B);
                    XNSEUtils.ComputeGradientForParam(CurrentState.ToArray()[D + 1], HeatFluxParam, this.LsTrk, kSpc, this.LsTrk.Regions.GetCutCellSubGrid());
                }
                else if (config.conductMode != ConductivityInSpeciesBulk.ConductivityMode.SIP && updateSolutionParams[D + 2])
                {
                    var HeatFluxMap = new CoordinateMapping(CurrentState.ToArray().GetSubVector(D + 2, D));
                    HeatFluxParam = HeatFluxMap.Fields.ToArray();
                }
                else
                {
                    HeatFluxParam = storedParams.GetSubVector(2 * D + 4, D);
                }
            }
            if (ExtParams != null)
            {
                HeatFluxParam = ExtParams;
            }

            #endregion


            // concatenate everything
            var Params = ArrayTools.Cat <DGField>(
                U0_U0mean,
                Normals,
                Curvature,
                ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D]));

            if (config.solveEnergy)
            {
                Params = ArrayTools.Cat <DGField>(Params.ToArray <DGField>(),
                                                  GradVelX,
                                                  GradVelY,
                                                  GradVelXGradX,
                                                  GradVelXGradY,
                                                  GradVelYGradX,
                                                  GradVelYGradY,
                                                  PressParam,
                                                  PressGrad,
                                                  GravMap);
            }

            if (config.solveHeat)
            {
                Params = ArrayTools.Cat <DGField>(Params.ToArray <DGField>(),
                                                  CurrentState.ToArray <DGField>().GetSubVector(D + 1, 1),
                                                  HeatFluxParam,
                                                  new SinglePhaseField[1]);
            }


            // store old params
            for (int p = 0; p < Params.Length; p++)
            {
                if (Params[p] != null)
                {
                    storedParams[p] = Params[p].CloneAs();
                }
            }



            // advanced settings for the navier slip boundary condition
            // ========================================================


            CellMask SlipArea;
            switch (this.dntParams.GNBC_Localization)
            {
            case NavierSlip_Localization.Bulk: {
                SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask;
                break;
            }

            case NavierSlip_Localization.ContactLine: {
                SlipArea = null;
                break;
            }

            case NavierSlip_Localization.Nearband: {
                SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask.Intersect(this.LsTrk.Regions.GetNearFieldMask(this.LsTrk.NearRegionWidth));
                break;
            }

            case NavierSlip_Localization.Prescribed: {
                throw new NotImplementedException();
            }

            default:
                throw new ArgumentException();
            }


            MultidimensionalArray SlipLengths;
            SlipLengths = this.LsTrk.GridDat.Cells.h_min.CloneAs();
            SlipLengths.Clear();
            //SlipLengths.AccConstant(-1.0);
            if (SlipArea != null)
            {
                foreach (Chunk cnk in SlipArea)
                {
                    for (int i = cnk.i0; i < cnk.JE; i++)
                    {
                        switch (this.dntParams.GNBC_SlipLength)
                        {
                        case NavierSlip_SlipLength.hmin_DG: {
                            int degU = ColMapping.BasisS.ToArray()[0].Degree;
                            SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i] / (degU + 1);
                            break;
                        }

                        case NavierSlip_SlipLength.hmin_Grid: {
                            SlipLengths[i] = SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i];
                            break;
                        }

                        case NavierSlip_SlipLength.Prescribed_SlipLength: {
                            SlipLengths[i] = this.physParams.sliplength;
                            break;
                        }

                        case NavierSlip_SlipLength.Prescribed_Beta: {
                            SlipLengths[i] = -1.0;
                            break;
                        }
                        }
                    }
                }
            }


            // interface coefficients
            // ======================

            MultidimensionalArray lambdaI, muI;
            lambdaI = SlipLengths.CloneAs();
            lambdaI.Clear();
            muI = SlipLengths.CloneAs();
            muI.Clear();

            foreach (Chunk cnk in this.LsTrk.Regions.GetCutCellMask())
            {
                for (int i = cnk.i0; i < cnk.JE; i++)
                {
                    double lI = 0.0;
                    double mI = 0.0;

                    // do the magic!!!
                    if (this.LsTrk.GridDat.Cells.CellCenter[i, 0] > 0 && this.LsTrk.GridDat.Cells.CellCenter[i, 1] > 0)
                    {
                    }
                    if (this.LsTrk.GridDat.Cells.CellCenter[i, 0] > 0 && this.LsTrk.GridDat.Cells.CellCenter[i, 1] < 0)
                    {
                        //lI = config.physParams.Sigma;
                        mI = config.physParams.Sigma;
                    }
                    if (this.LsTrk.GridDat.Cells.CellCenter[i, 0] < 0 && this.LsTrk.GridDat.Cells.CellCenter[i, 1] < 0)
                    {
                        //lI = -config.physParams.Sigma;
                        mI = -config.physParams.Sigma;
                    }
                    if (this.LsTrk.GridDat.Cells.CellCenter[i, 0] < 0 && this.LsTrk.GridDat.Cells.CellCenter[i, 1] > 0)
                    {
                        //lI = 10 * config.physParams.Sigma;
                        mI = 10 * config.physParams.Sigma;
                    }

                    lambdaI[i] = lI;
                    muI[i]     = mI;
                }
            }



            // assemble the matrix & affine vector
            // ===================================

            IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengths = this.LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), CutCellQuadOrder).CutCellMetrics.InterfaceArea;

            BitArray EvapMicroRegion = this.LsTrk.GridDat.GetBoundaryCells().GetBitMask();
            EvapMicroRegion.SetAll(false);

            // compute matrix
            if (OpMatrix != null)
            {
                XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = this.m_XOp.GetMatrixBuilder(LsTrk, ColMapping, Params, RowMapping);

                foreach (var kv in AgglomeratedCellLengthScales)
                {
                    mtxBuilder.CellLengthScales[kv.Key] = kv.Value;
                    this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["SlipLengths"]     = SlipLengths;
                    this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["EvapMicroRegion"] = EvapMicroRegion;
                    if (config.prescribedMassflux != null)
                    {
                        double[] dummyX = new double[] { 0.0, 0.0 };
                        this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["prescribedMassflux"] = config.prescribedMassflux(dummyX, time);
                    }
                }

                if (this.m_XOp.SurfaceElementOperator.TotalNoOfComponents > 0)
                {
                    foreach (var kv in InterfaceLengths)
                    {
                        this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["InterfaceLengths"] = kv.Value;
                        this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["lambda_interface"] = lambdaI;
                        this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["mu_interface"]     = muI;
                    }
                }

                mtxBuilder.time = time;

                mtxBuilder.ComputeMatrix(OpMatrix, OpAffine);
            }
            else
            {
                XSpatialOperatorMk2.XEvaluatorNonlin eval = this.m_XOp.GetEvaluatorEx(this.LsTrk,
                                                                                      CurrentState.ToArray(), Params, RowMapping);

                foreach (var kv in AgglomeratedCellLengthScales)
                {
                    eval.CellLengthScales[kv.Key] = kv.Value;
                    this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["SlipLengths"]     = SlipLengths;
                    this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["EvapMicroRegion"] = EvapMicroRegion;
                    if (config.prescribedMassflux != null)
                    {
                        double[] dummyX = new double[] { 0.0, 0.0 };
                        this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["prescribedMassflux"] = config.prescribedMassflux(dummyX, time);
                    }
                }

                if (this.m_XOp.SurfaceElementOperator.TotalNoOfComponents > 0)
                {
                    foreach (var kv in InterfaceLengths)
                    {
                        this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["InterfaceLengths"] = kv.Value;
                        this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["lambda_interface"] = lambdaI;
                        this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["mu_interface"]     = muI;
                    }
                }

                eval.time = time;

                eval.Evaluate(1.0, 1.0, OpAffine);
            }
        }