예제 #1
0
파일: ipPoisson.cs 프로젝트: octwanna/BoSSS
        protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L)
        {
            using (FuncTrace tr = new FuncTrace()) {
                // assemble system, create matrix
                // ------------------------------

                var volQrSch = new CellQuadratureScheme(true, CellMask.GetFullMask(this.GridData));
                var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData));

                double D              = this.GridData.SpatialDimension;
                double penalty_base   = (T.Basis.Degree + 1) * (T.Basis.Degree + D) / D;
                double penalty_factor = base.Control.penalty_poisson;

                {
                    // equation assembly
                    // -----------------
                    tr.Info("creating sparse system...");
                    Console.WriteLine("creating sparse system for {0} DOF's ...", T.Mapping.Ntotal);
                    Stopwatch stw = new Stopwatch();
                    stw.Start();

                    SpatialOperator LapaceIp = new SpatialOperator(1, 1, QuadOrderFunc.SumOfMaxDegrees(), "T", "T");
                    var             flux     = new ipFlux(penalty_base * base.Control.penalty_poisson, this.GridData.Cells.cj, base.Control);
                    LapaceIp.EquationComponents["T"].Add(flux);


                    LapaceIp.Commit();

#if DEBUG
                    var RefLaplaceMtx = new MsrMatrix(T.Mapping);
#endif
                    LaplaceMtx    = new BlockMsrMatrix(T.Mapping);
                    LaplaceAffine = new double[T.Mapping.LocalLength];

                    LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping,
                                             LaplaceMtx, LaplaceAffine,
                                             volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch);
#if DEBUG
                    LaplaceAffine.ClearEntries();
                    LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping,
                                             RefLaplaceMtx, LaplaceAffine,
                                             volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch);
                    MsrMatrix ErrMtx = RefLaplaceMtx.CloneAs();
                    ErrMtx.Acc(-1.0, LaplaceMtx);
                    double err    = ErrMtx.InfNorm();
                    double infNrm = LaplaceMtx.InfNorm();
                    Console.WriteLine("Matrix comparison error: " + err + ", matrix norm is: " + infNrm);
                    Assert.Less(err, infNrm * 1e-10, "MsrMatrix2 comparison failed.");
#endif
                    //int q = LaplaceMtx._GetTotalNoOfNonZeros();
                    //tr.Info("finished: Number of non-zeros: " + q);
                    stw.Stop();
                    Console.WriteLine("done {0} sec.", stw.Elapsed.TotalSeconds);


                    //double condNo = LaplaceMtx.condest(BatchmodeConnector.Flavor.Octave);
                    //Console.WriteLine("condition number: {0:0.####E-00} ",condNo);
                }
            }
        }
예제 #2
0
        /*
         * /// <summary>
         * /// initialized by the constructor to avoid MPI-deadlocks;
         * /// </summary>
         * Dictionary<RefElement, EdgeMask> m_Subgrid4Kref_AllEdges = new Dictionary<RefElement, EdgeMask>();
         */

        //LevelSetTracker lsTrk {
        //    get {
        //        return XDGSpaceMetrics.Tracker;
        //    }
        //}


        public EdgeQuadratureScheme Get_SurfaceElement_EdgeQuadScheme(SpeciesId sp)
        {
            if (!this.SpeciesList.Contains(sp))
            {
                throw new ArgumentException("Given species (id = " + sp.cntnt + ") is not supported.");
            }

            //var allRelevantEdges = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp].Intersect(this.m_CutCellSubgrid_InnerEdges);

            var innerCutCellEdges    = this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubGrid().InnerEdgesMask;
            var boundaryCutCellEdges = ExecutionMask.Intersect(this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubGrid().BoundaryEdgesMask, this.XDGSpaceMetrics.GridDat.BoundaryEdges);
            var allRelevantEdges     = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp].Intersect(ExecutionMask.Union(innerCutCellEdges, boundaryCutCellEdges));

            //EdgeMask AggEdges = this.CellAgglomeration != null ? this.CellAgglomeration.GetAgglomerator(sp).AggInfo.AgglomerationEdges : null;
            //if (AggEdges != null && AggEdges.NoOfItemsLocally > 0)
            //    allRelevantEdges = allRelevantEdges.Except(AggEdges);


            var edgeQrIns = new EdgeQuadratureScheme(false, allRelevantEdges);

            foreach (var Kref in XDGSpaceMetrics.GridDat.Grid.RefElements)
            {
                for (int iLevSet = 0; iLevSet < XDGSpaceMetrics.NoOfLevelSets; iLevSet++)   // loop over level sets...
                {
                    EdgeMask cutEdges = this.GetCutEdges(Kref, iLevSet);

                    var factory = this.XDGSpaceMetrics.XQuadFactoryHelper.GetSurfaceElement_BoundaryRuleFactory(iLevSet, Kref);

                    edgeQrIns.AddFactory(factory, cutEdges);
                }
            }

            return(edgeQrIns);
        }
예제 #3
0
        /// <summary>
        /// accumulates the derivative of DG field <paramref name="f"/>
        /// (along the <paramref name="d"/>-th axis) times <paramref name="alpha"/>
        /// to this field, i.e. <br/>
        /// this = this + <paramref name="alpha"/>* \f$ \frac{\partial}{\partial x_d} \f$ <paramref name="f"/>;
        /// </summary>
        /// <param name="f"></param>
        /// <param name="d">
        /// 0 for the x-derivative, 1 for the y-derivative, 2 for the z-derivative
        /// </param>
        /// <param name="alpha">
        /// scaling of <paramref name="f"/>;
        /// </param>
        /// <param name="em">
        /// An optional restriction to the domain in which the derivative is computed (it may, e.g.
        /// be only required in boundary cells, so a computation over the whole domain
        /// would be a waste of computation power. A proper execution mask for this case would be e.g.
        /// <see cref="BoSSS.Foundation.Grid.GridData.BoundaryCells"/>.)<br/>
        /// if null, the computation is carried out in the whole domain
        /// </param>
        override public void Derivative(double alpha, DGField f, int d, CellMask em)
        {
            using (var tr = new FuncTrace()) {
                MPICollectiveWatchDog.Watch(csMPI.Raw._COMM.WORLD);

                if (this.Basis.Degree < f.Basis.Degree - 1)
                {
                    throw new ArgumentException("cannot compute derivative because of incompatible basis functions.", "f");
                }
                if (f.Basis.GetType() != this.Basis.GetType())
                {
                    throw new ArgumentException("cannot compute derivative because of incompatible basis functions.", "f");
                }



                int D = GridDat.SpatialDimension;
                if (d < 0 || d >= D)
                {
                    throw new ArgumentException("spatial dimension out of range.", "d");
                }

                Quadrature.EdgeQuadratureScheme _qInsEdge;
                Quadrature.CellQuadratureScheme _qInsVol;
                {
                    _qInsEdge = (new Quadrature.EdgeQuadratureScheme(false, EdgeMask.GetEmptyMask(this.GridDat)));
                    _qInsVol  = (new Quadrature.CellQuadratureScheme(true, em));
                }

                var op = (new BrokenDerivativeForm(d)).Operator(1, g => _qInsEdge, g => _qInsVol);

                op.Evaluate(alpha, 1.0, f.Mapping, null, this.Mapping);
            }
        }
            public EdgeMask GetEdges4RefElement(RefElement Kref)
            {
                if (m_Edges4RefElement == null)
                {
                    m_Edges4RefElement = new EdgeMask[this.EdgeRefElements.Length];
                }

                int iKref = this.EdgeRefElements.IndexOf(Kref, (a, b) => object.ReferenceEquals(a, b));

                if (m_Edges4RefElement[iKref] == null)
                {
                    EdgeMask parrEdg = m_Owner.ParentGrid.iGeomEdges.GetEdges4RefElement(Kref);
                    EdgeMask thisAll = EdgeMask.GetFullMask(this.m_Owner, MaskType.Geometrical);
                    if (parrEdg.MaskType != MaskType.Geometrical)
                    {
                        throw new ApplicationException("expecting a geometrical mask");
                    }
                    if (thisAll.MaskType != MaskType.Geometrical)
                    {
                        throw new ApplicationException("expecting a geometrical mask");
                    }

                    BitArray parrBitmask = parrEdg.GetBitMask().CloneAs();
                    BitArray thisBitMask = thisAll.GetBitMask();
                    Debug.Assert(parrBitmask.Length == thisBitMask.Length);

                    BitArray intersect = parrBitmask.And(thisBitMask);
                    Debug.Assert(object.ReferenceEquals(intersect, parrBitmask));

                    m_Edges4RefElement[iKref] = new EdgeMask(m_Owner, intersect, MaskType.Geometrical);
                }

                return(m_Edges4RefElement[iKref]);
            }
예제 #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="spatialOp"></param>
        /// <param name="Fieldsmap"></param>
        /// <param name="Parameters">
        /// optional parameter fields, can be null if
        /// <paramref name="spatialOp"/> contains no parameters; must match
        /// the parameter field list of <paramref name="spatialOp"/>, see
        /// <see cref="BoSSS.Foundation.SpatialOperator.ParameterVar"/>
        /// </param>
        /// <param name="sgrdBnd">
        /// Options for the treatment of edges at the boundary of a SubGrid,
        /// <see cref="SubGridBoundaryModes"/></param>
        /// <param name="timeStepConstraints">
        /// optional list of time step constraints <see cref="TimeStepConstraint"/>
        /// </param>
        /// <param name="sgrd">
        /// optional restriction to computational domain
        /// </param>
        public ExplicitEuler(SpatialOperator spatialOp, CoordinateMapping Fieldsmap, CoordinateMapping Parameters, SubGridBoundaryModes sgrdBnd, IList <TimeStepConstraint> timeStepConstraints = null, SubGrid sgrd = null)
        {
            using (new ilPSP.Tracing.FuncTrace()) {
                // verify input
                // ============
                TimeStepperCommon.VerifyInput(spatialOp, Fieldsmap, Parameters);


                Mapping          = Fieldsmap;
                CurrentState     = new CoordinateVector(Mapping);
                ParameterMapping = Parameters;
                IList <DGField> ParameterFields =
                    (ParameterMapping == null) ? (new DGField[0]) : ParameterMapping.Fields;

                this.TimeStepConstraints = timeStepConstraints;

                SubGrid = sgrd ?? new SubGrid(CellMask.GetFullMask(Fieldsmap.First().GridDat));

                // generate Evaluator
                // ==================

                CellMask cm = SubGrid.VolumeMask;
                EdgeMask em = SubGrid.AllEdgesMask;

                Operator    = spatialOp;
                m_Evaluator = new Lazy <IEvaluatorNonLin>(delegate() {
                    spatialOp.EdgeQuadraturSchemeProvider   = g => new EdgeQuadratureScheme(true, em);
                    spatialOp.VolumeQuadraturSchemeProvider = g => new CellQuadratureScheme(true, cm);
                    var op = spatialOp.GetEvaluatorEx(
                        Fieldsmap, ParameterFields, Fieldsmap);
                    op.ActivateSubgridBoundary(SubGrid.VolumeMask, sgrdBnd);
                    return(op);
                });
            }
        }
예제 #6
0
        /// <summary>
        /// accumulates the derivative of DG field <paramref name="f"/>
        /// (along the <paramref name="d"/>-th axis) times <paramref name="alpha"/>
        /// to this field, i.e. <br/>
        /// this = this + <paramref name="alpha"/>* \f$ \frac{\partial}{\partial x_d} \f$ <paramref name="f"/>;
        /// </summary>
        /// <param name="f"></param>
        /// <param name="d">
        /// 0 for the x-derivative, 1 for the y-derivative, 2 for the
        /// z-derivative
        /// </param>
        /// <param name="alpha">
        /// scaling of <paramref name="f"/>;
        /// </param>
        /// <param name="optionalSubGrid">
        /// An optional restriction to the domain in which the derivative is
        /// computed (it may, e.g. be only required in boundary cells, so a
        /// computation over the whole domain would be a waste of computational
        /// power. A proper execution mask would be see e.g.
        /// <see cref="GridData.BoundaryCells"/>.)
        /// <br/>
        /// if null, the computation is carried out in the whole domain.
        /// </param>
        /// <param name="bndMode">
        /// if a sub-grid is provided, this determines how the sub-grid
        /// boundary should be treated.
        /// </param>
        /// <remarks>
        /// The derivative is calculated using Riemann flux functions
        /// (central difference);<br/>
        /// In comparison to
        /// <see cref="Derivative(double, DGField, int, CellMask)"/>, this method
        /// should be slower, but produce more sane results, especially for
        /// fields of low polynomial degree (0 or 1);
        /// </remarks>
        virtual public void DerivativeByFlux(double alpha, DGField f, int d, SubGrid optionalSubGrid = null, SubGridBoundaryModes bndMode = SubGridBoundaryModes.OpenBoundary)
        {
            int D = this.Basis.GridDat.SpatialDimension;

            if (d < 0 || d >= D)
            {
                throw new ArgumentException("spatial dimension out of range.", "d");
            }
            MPICollectiveWatchDog.Watch(csMPI.Raw._COMM.WORLD);

            EdgeMask emEdge = (optionalSubGrid != null) ? optionalSubGrid.AllEdgesMask : null;
            CellMask emVol  = (optionalSubGrid != null) ? optionalSubGrid.VolumeMask : null;

            SpatialOperator d_dx = new SpatialOperator(1, 1, QuadOrderFunc.Linear(), "in", "out");

            d_dx.EdgeQuadraturSchemeProvider   = g => new Quadrature.EdgeQuadratureScheme(true, emEdge);
            d_dx.VolumeQuadraturSchemeProvider = g => new Quadrature.CellQuadratureScheme(true, emVol);
            var flux = CreateDerivativeFlux(d, f.Identification);

            d_dx.EquationComponents["out"].Add(flux);
            d_dx.Commit();


            var ev = d_dx.GetEvaluatorEx(
                new CoordinateMapping(f), null, this.Mapping);

            if (optionalSubGrid != null)
            {
                ev.ActivateSubgridBoundary(optionalSubGrid.VolumeMask, bndMode);
            }

            ev.Evaluate <CoordinateVector>(alpha, 1.0, this.CoordinateVector);
        }
예제 #7
0
        /// <summary>
        /// accumulates the projection of some vector field to this field, i.e.
        /// \f[
        ///   this = this + \alpha \cdot \| \vec{vec} \|.
        /// \f]
        /// </summary>
        /// <param name="alpha">factor \f$ \alpha \f$ </param>
        /// <param name="vec">vector field \f$ \vec{vec} \f$ </param>
        /// <param name="em">
        /// An optional restriction to the domain in which the projection is computed (it may, e.g.
        /// be only required in boundary cells, so a computation over the whole domain
        /// would be a waste of computation power. If null, the computation is carried out in the whole domain;
        /// </param>
        virtual public void ProjectAbs(double alpha, CellMask em, params DGField[] vec)
        {
            int K = vec.Length;

            string[] args = new string[K];
            for (int k = 0; k < K; k++)
            {
                args[k] = "_" + k;
            }

            SpatialOperator powOp = new SpatialOperator(args, new string[] { "res" }, QuadOrderFunc.SumOfMaxDegrees());

            powOp.EquationComponents["res"].Add(new AbsSource(args));
            powOp.Commit();

            CoordinateVector coDom = new CoordinateVector(this);

            var ev = powOp.GetEvaluatorEx(
                new CoordinateMapping(vec),
                null,
                coDom.Mapping,
                edgeQrCtx: new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.Basis.GridDat)),
                volQrCtx: new CellQuadratureScheme(true, em));

            ev.Evaluate <CoordinateVector>(alpha, 1.0, coDom); // only sources, no edge integrals required
        }
예제 #8
0
        /// <summary>
        /// All edges that have to be considered for the integration of species <paramref name="sp"/>.
        /// </summary>
        /// <param name="sp"></param>
        /// <param name="IntegrationDomainRestriction">Optional restriction to the integration domain.</param>
        public EdgeMask GetEdgeMask(SpeciesId sp, EdgeMask IntegrationDomainRestriction = null)
        {
            if (!this.SpeciesList.Contains(sp))
            {
                throw new ArgumentException("Given species ( id = " + sp.cntnt + ") is not supported.");
            }

            EdgeMask allRelevantEdges;

            if (IntegrationDomainRestriction == null)
            {
                allRelevantEdges = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp];
            }
            else
            {
                // user provides integration domain, intersect with that
                allRelevantEdges = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp].Intersect(IntegrationDomainRestriction);
            }

            //// optionally, exclude edges between agglomerated cells
            //EdgeMask AggEdges = (this.CellAgglomeration != null) ? (this.CellAgglomeration.GetAgglomerator(sp).AggInfo.AgglomerationEdges) : (default(EdgeMask));
            //if (AggEdges != null && AggEdges.NoOfItemsLocally > 0)
            //    allRelevantEdges = allRelevantEdges.Except(AggEdges);
            return(allRelevantEdges);
        }
예제 #9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="spatialOp"></param>
        /// <param name="Fieldsmap"></param>
        /// <param name="Parameters">
        /// optional parameter fields, can be null if
        /// <paramref name="spatialOp"/> contains no parameters; must match
        /// the parameter field list of <paramref name="spatialOp"/>, see
        /// <see cref="BoSSS.Foundation.SpatialOperator.ParameterVar"/>
        /// </param>
        /// <param name="sgrdBnd">
        /// Options for the treatment of edges at the boundary of a SubGrid,
        /// <see cref="SpatialOperator.SubGridBoundaryModes"/></param>
        /// <param name="timeStepConstraints">
        /// optional list of time step constraints <see cref="TimeStepConstraint"/>
        /// </param>
        /// <param name="sgrd">
        /// optional restriction to computational domain
        /// </param>
        public ExplicitEuler(SpatialOperator spatialOp, CoordinateMapping Fieldsmap, CoordinateMapping Parameters, SpatialOperator.SubGridBoundaryModes sgrdBnd, IList <TimeStepConstraint> timeStepConstraints = null, SubGrid sgrd = null)
        {
            using (new ilPSP.Tracing.FuncTrace()) {
                // verify input
                // ============

                if (!spatialOp.ContainsNonlinear && !(spatialOp.ContainsLinear()))
                {
                    throw new ArgumentException("spatial differential operator seems to contain no components.", "spatialOp");
                }
                if (spatialOp.DomainVar.Count != spatialOp.CodomainVar.Count)
                {
                    throw new ArgumentException("spatial differential operator must have the same number of domain and codomain variables.", "spatialOp");
                }
                if (Fieldsmap.Fields.Count != spatialOp.CodomainVar.Count)
                {
                    throw new ArgumentException("the number of fields in the coordinate mapping must be equal to the number of domain/codomain variables of the spatial differential operator", "fields");
                }
                if (Parameters == null)
                {
                    if (spatialOp.ParameterVar.Count != 0)
                    {
                        throw new ArgumentException("the number of fields in the parameter mapping must be equal to the number of parameter variables of the spatial differential operator", "Parameters");
                    }
                }
                else
                {
                    if (Parameters.Fields.Count != spatialOp.ParameterVar.Count)
                    {
                        throw new ArgumentException("the number of fields in the parameter mapping must be equal to the number of parameter variables of the spatial differential operator", "Parameters");
                    }
                }

                Mapping          = Fieldsmap;
                DGCoordinates    = new CoordinateVector(Mapping);
                ParameterMapping = Parameters;
                IList <DGField> ParameterFields =
                    (ParameterMapping == null) ? (new DGField[0]) : ParameterMapping.Fields;

                this.TimeStepConstraints = timeStepConstraints;

                SubGrid = sgrd ?? new SubGrid(CellMask.GetFullMask(Fieldsmap.First().GridDat));

                // generate Evaluator
                // ==================

                CellMask cm = SubGrid.VolumeMask;
                EdgeMask em = SubGrid.AllEdgesMask;

                Operator    = spatialOp;
                m_Evaluator = new Lazy <SpatialOperator.Evaluator>(() => spatialOp.GetEvaluatorEx(
                                                                       Fieldsmap, ParameterFields, Fieldsmap,
                                                                       new EdgeQuadratureScheme(true, em),
                                                                       new CellQuadratureScheme(true, cm),
                                                                       SubGrid,
                                                                       sgrdBnd));
            }
        }
예제 #10
0
        public void Evaluate(EdgeMask em, SinglePhaseField inp_LevSet, SinglePhaseField outp_Result)
        {
            MsrMatrix Matrix;

            Matrix = PenaltyMatrix(em, inp_LevSet.Basis, outp_Result.Basis);


            Matrix.SpMV(1.0, inp_LevSet.CoordinateVector, 0.0, outp_Result.CoordinateVector);
        }
예제 #11
0
        /// <summary>
        /// computes <see cref="LaplaceMtx"/> and <see cref="LaplaceAffine"/>
        /// </summary>
        private void UpdateMatrices() {
            using (var tr = new FuncTrace()) {
                // time measurement for matrix assembly
                Stopwatch stw = new Stopwatch();
                stw.Start();

                // console
                Console.WriteLine("creating sparse system for {0} DOF's ...", T.Mapping.Ntotal);

                // quadrature domain
                var volQrSch = new CellQuadratureScheme(true, CellMask.GetFullMask(this.GridData, MaskType.Geometrical));
                var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData, MaskType.Geometrical));

#if DEBUG
                // in DEBUG mode, we compare 'MsrMatrix' (old, reference implementation) and 'BlockMsrMatrix' (new standard)
                var RefLaplaceMtx = new MsrMatrix(T.Mapping);
#endif
                using (new BlockTrace("SipMatrixAssembly", tr)) {
                    LaplaceMtx = new BlockMsrMatrix(T.Mapping);
                    LaplaceAffine = new double[T.Mapping.LocalLength];

                    LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping,
                                             LaplaceMtx, LaplaceAffine,
                                             volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch);
                }
#if DEBUG
                LaplaceAffine.ClearEntries();
                LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping,
                                         RefLaplaceMtx, LaplaceAffine,
                                         volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch);
                MsrMatrix ErrMtx = RefLaplaceMtx.CloneAs();
                ErrMtx.Acc(-1.0, LaplaceMtx);
                double err = ErrMtx.InfNorm();
                double infNrm = LaplaceMtx.InfNorm();
                Console.WriteLine("Matrix comparison error: " + err + ", matrix norm is: " + infNrm);
                Assert.Less(err, infNrm * 1e-10, "MsrMatrix2 comparison failed.");
#endif
                stw.Stop();
                Console.WriteLine("done {0} sec.", stw.Elapsed.TotalSeconds);


                //var JB = LapaceIp.GetFDJacobianBuilder(T.Mapping.Fields, null, T.Mapping, edgQrSch, volQrSch);
                //var JacobiMtx = new BlockMsrMatrix(T.Mapping);
                //var JacobiAffine = new double[T.Mapping.LocalLength];
                //JB.ComputeMatrix(JacobiMtx, JacobiAffine);
                //double L2ErrAffine = GenericBlas.L2Dist(JacobiAffine, LaplaceAffine);
                //var ErrMtx2 = LaplaceMtx.CloneAs();
                //ErrMtx2.Acc(-1.0, JacobiMtx);
                //double LinfErrMtx2 = ErrMtx2.InfNorm();

                //JacobiMtx.SaveToTextFileSparse("D:\\tmp\\Jac.txt");
                //LaplaceMtx.SaveToTextFileSparse("D:\\tmp\\Lap.txt");

                //Console.WriteLine("FD Jacobi Mtx: {0:e14}, Affine: {1:e14}", LinfErrMtx2, L2ErrAffine);
            }
        }
예제 #12
0
        /// <summary>
        /// the jump-seminorm of DG-field <paramref name="f"/>:
        /// <latex mode="display">
        ///
        /// </latex>
        /// </summary>
        /// <param name="f"></param>
        /// <param name="CM"></param>
        /// <returns></returns>
        public static double JumpSemiNorm(this Field f, EdgeMask CM = null)
        {
            using (new FuncTrace()) {
                var qi = new EdgeQuadratureScheme(CM);

                var quad = new JumpSemiNormIntegrator(f, qi);
                quad.Execute();
                return(Math.Sqrt(quad.overallResult));
            }
        }
예제 #13
0
        static double JumpNorm(DGField f, EdgeMask em)
        {
            GridData grd      = grid;
            int      D        = grd.SpatialDimension;
            var      e2cTrafo = grd.Edges.Edge2CellTrafos;

            double Unorm = 0;


            EdgeQuadrature.GetQuadrature(
                new int[] { D + 1 }, grd,
                (new EdgeQuadratureScheme(true, em)).Compile(grd, f.Basis.Degree * 2),
                delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {  // Evaluate
                NodeSet NS = QR.Nodes;
                EvalResult.Clear();
                int NoOfNodes = NS.NoOfNodes;
                for (int j = 0; j < Length; j++)
                {
                    int iEdge     = j + i0;
                    int iTrafo_IN = grd.Edges.Edge2CellTrafoIndex[iEdge, 0];
                    int jCell_IN  = grd.Edges.CellIndices[iEdge, 0];
                    int iTrafo_OT = grd.Edges.Edge2CellTrafoIndex[iEdge, 1];
                    int jCell_OT  = grd.Edges.CellIndices[iEdge, 1];

                    MultidimensionalArray uIN      = MultidimensionalArray.Create(1, NoOfNodes);
                    MultidimensionalArray uOT      = MultidimensionalArray.Create(1, NoOfNodes);
                    MultidimensionalArray Grad_uIN = MultidimensionalArray.Create(1, NoOfNodes, D);
                    MultidimensionalArray Grad_uOT = MultidimensionalArray.Create(1, NoOfNodes, D);

                    NodeSet NS_IN = NS.GetVolumeNodeSet(grd, iTrafo_IN);
                    NodeSet NS_OT = NS.GetVolumeNodeSet(grd, iTrafo_OT);

                    f.Evaluate(jCell_IN, 1, NS_IN, uIN);
                    f.Evaluate(jCell_OT, 1, NS_OT, uOT);
                    f.EvaluateGradient(jCell_IN, 1, NS_IN, Grad_uIN);
                    f.EvaluateGradient(jCell_OT, 1, NS_OT, Grad_uOT);

                    var uDiff      = EvalResult.ExtractSubArrayShallow(new int[] { j, 0, 0 }, new int[] { j, NoOfNodes - 1, -1 });
                    var Grad_uDiff = EvalResult.ExtractSubArrayShallow(new int[] { j, 0, 1 }, new int[] { j, NoOfNodes - 1, D });
                    uDiff.Acc(+1.0, uIN);
                    uDiff.Acc(-1.0, uOT);
                    Grad_uDiff.Acc(+1.0, Grad_uIN);
                    Grad_uDiff.Acc(-1.0, Grad_uOT);
                }

                EvalResult.ApplyAll(x => x * x);
            },
                delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {  // SaveIntegrationResults
                Unorm += ResultsOfIntegration.Sum();
            }).Execute();

            double totNorm = Unorm.MPISum().Sqrt();

            return(totNorm);
        }
예제 #14
0
        void ConstructorCommon()
        {
            var Krefs = this.XDGSpaceMetrics.GridDat.Grid.RefElements;


            // initialize some mask's and subgrids
            // ===================================

            // since most methods of this class are non-collective,
            // an access to some Subgrid-member may cause an MPI-deadlock.
            // (this becomes even more unpredictable due to the on-demand-pattern in which most members of the Subgrid-class are implemented);

            //
            foreach (var spId in this.SpeciesList)
            {
                SubGrid spSgrd = this.XDGSpaceMetrics.LevelSetRegions.GetSpeciesSubGrid(spId);

                this.m_SpeciesSubgrid_InnerAndDomainEdges.Add(
                    spId,
                    spSgrd.InnerEdgesMask.Union(spSgrd.AllEdgesMask.Intersect(XDGSpaceMetrics.GridDat.BoundaryEdges)));
            }

            // all cut edges
            // =============
            m_CutCellSubgrid_InnerEdges = this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubGrid().InnerEdgesMask;

            // cut edges sorted according to reference element and level-set
            // =============================================================
            int NoOfLs = this.XDGSpaceMetrics.NoOfLevelSets;

            this.m_CutEdges       = new EdgeMask[Krefs.Length, NoOfLs];
            this.m_HMFEdgesDomain = new EdgeMask[Krefs.Length, NoOfLs];
            for (int iKref = 0; iKref < this.m_CutEdges.GetLength(0); iKref++)
            {
                for (int iLevSet = 0; iLevSet < this.m_CutEdges.GetLength(1); iLevSet++)
                {
                    EdgeMask cutEdges = this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubgrid4LevSet(iLevSet).InnerEdgesMask.Union(
                        this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubgrid4LevSet(iLevSet).AllEdgesMask.Intersect(this.XDGSpaceMetrics.GridDat.BoundaryEdges));



                    cutEdges = cutEdges.Intersect(this.XDGSpaceMetrics.GridDat.GetRefElementSubGrid(iKref).AllEdgesMask);
                    cutEdges = cutEdges.ToGeometicalMask();

                    Debug.Assert(cutEdges.MaskType == MaskType.Geometrical);
                    this.m_CutEdges[iKref, iLevSet] = cutEdges;

                    // (all edges of 'Kref'-elements) \cap (all edges of cells cut by 'iLevSet')
                    this.m_HMFEdgesDomain[iKref, iLevSet] = this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubgrid4LevSet(iLevSet).AllEdgesMask.Intersect(this.XDGSpaceMetrics.GridDat.GetRefElementSubGrid(iKref).AllEdgesMask);
                }
            }
        }
예제 #15
0
        public static void Plot(IGrid grid)
        {
            EdgeMask boundaryEdges = EdgeMask.GetFullMask(grid.iGridData, MaskType.Logical);

            boundaryEdges.SaveToTextFile(
                "edges.txt",
                false,
                (double[] CoordGlobal, int LogicalItemIndex, int GeomItemIndex) => grid.iGridData.iGeomEdges.EdgeTags[GeomItemIndex]);
            Tecplot          plt1  = new Tecplot(grid.iGridData, true, false, 0);
            Basis            b     = new Basis(grid.iGridData, 0);
            SinglePhaseField field = new SinglePhaseField(b, "u");

            plt1.PlotFields("grid", 0, field);
        }
예제 #16
0
        private MsrMatrix PenaltyMatrix(EdgeMask em, Basis LevSetBasis, Basis JumpBasis)
        {
            var OpA = new SpatialOperator(1, 0, 1, QuadOrderFunc.Linear(), "Phi", "c1");

            OpA.EquationComponents["c1"].Add(new JumpForm());
            //OpA.EquationComponents["c1"].Add(new GradientJumpForm() { ATerm = true, BTerm = true });
            OpA.EquationComponents["c1"].Add(new GradientJumpForm2());
            OpA.Commit();

            //var OpB = new SpatialOperator(1, 0, 1, "Phi", "c1");
            //Op.EquationComponents["c1"].Add(new JumpForm());
            //OpB.EquationComponents["c1"].Add(new GradientJumpForm() { BTerm = true });
            //Op.EquationComponents["c1"].Add(new GradientJumpForm2());
            //OpB.Commit();

            var inp_LevSet_Mapping  = new UnsetteledCoordinateMapping(LevSetBasis);
            var outp_Result_Mapping = new UnsetteledCoordinateMapping(JumpBasis);

            MsrMatrix MatrixA;

            MatrixA = new MsrMatrix(outp_Result_Mapping, inp_LevSet_Mapping);
            double[] AffineA = new double[inp_LevSet_Mapping.LocalLength];
            OpA.ComputeMatrixEx(inp_LevSet_Mapping, null, outp_Result_Mapping,
                                MatrixA, AffineA, OnlyAffine: false,
                                edgeQuadScheme: new EdgeQuadratureScheme(true, em),
                                volQuadScheme: new CellQuadratureScheme(true, CellMask.GetEmptyMask(em.GridData)));
            MatrixA.CheckForNanOrInfM();

            //MsrMatrix MatrixB;
            //MatrixB = new MsrMatrix(outp_Result_Mapping, inp_LevSet_Mapping);
            //double[] AffineB = new double[inp_LevSet_Mapping.LocalLength];
            //OpB.ComputeMatrixEx(inp_LevSet_Mapping, null, outp_Result_Mapping,
            //    MatrixB, AffineB, OnlyAffine: false
            //    );//,
            //    //edgeQrCtx: new EdgeQuadratureScheme(true, em),
            //    //volQrCtx: new CellQuadratureScheme(true, CellMask.GetEmptyMask(em.GridData)));

            //Debug.Assert(AffineB.L2Norm() == 0);

            //var Err = MatrixA.Transpose();
            //Err.Acc(-1.0, MatrixB);

            //double errnorm = Err.InfNorm();
            //Debug.Assert(errnorm < 1.0e-10);
            ////Console.WriteLine("Errnorm:" + errnorm);


            return(MatrixA);
        }
예제 #17
0
        internal void BuildEvaluatorsAndMasks()
        {
            CellMask fluidCells = speciesMap.SubGrid.VolumeMask.Intersect(ABSubGrid.VolumeMask);

            cutCells          = speciesMap.Tracker.Regions.GetCutCellMask().Intersect(ABSubGrid.VolumeMask);
            cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells).Intersect(ABSubGrid.VolumeMask);


            IBMControl control = speciesMap.Control;
            SpeciesId  species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName);

            CellQuadratureScheme volumeScheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme(
                species, true, fluidCells, control.LevelSetQuadratureOrder);


            // Does _not_ include agglomerated edges
            EdgeMask nonVoidEdges = speciesMap.QuadSchemeHelper.GetEdgeMask(species);

            nonVoidEdges = nonVoidEdges.Intersect(ABSubGrid.AllEdgesMask.ToGeometicalMask());
            EdgeQuadratureScheme edgeScheme = speciesMap.QuadSchemeHelper.GetEdgeQuadScheme(
                species, true, nonVoidEdges, control.LevelSetQuadratureOrder);

            this.m_Evaluator = new Lazy <IEvaluatorNonLin>(delegate() {
                this.Operator.EdgeQuadraturSchemeProvider   = g => edgeScheme;
                this.Operator.VolumeQuadraturSchemeProvider = g => volumeScheme;

                var opi = this.Operator.GetEvaluatorEx(
                    Mapping,
                    boundaryParameterMap,
                    Mapping);
                opi.ActivateSubgridBoundary(ABSubGrid.VolumeMask, subGridBoundaryTreatment: SubGridBoundaryModes.InnerEdgeLTS);
                return(opi);
            });

            // Evaluator for boundary conditions at level set zero contour
            CellQuadratureScheme boundaryVolumeScheme = speciesMap.QuadSchemeHelper.GetLevelSetquadScheme(
                0, cutCells, control.LevelSetQuadratureOrder);

            this.boundaryEvaluator = new Lazy <IEvaluatorNonLin>(delegate() {
                boundaryOperator.EdgeQuadraturSchemeProvider   = g => null; // Contains no boundary terms --> PROBLEM??????????
                boundaryOperator.VolumeQuadraturSchemeProvider = g => boundaryVolumeScheme;
                return(boundaryOperator.GetEvaluatorEx(
                           Mapping,
                           boundaryParameterMap,
                           Mapping));
            });
        }
예제 #18
0
        /// <summary>
        /// Calculates the DG-projection (with respect to the DG-basis
        /// of this field, <see cref="Basis"/>) of
        /// <paramref name="alpha"/>*<paramref name="a"/>/<paramref name="b"/>
        /// and, depending on the value of <paramref name="accumulateResult"/>,
        /// either adds or assigns it to this field.
        /// </summary>
        /// <param name="a">1st multiplicand</param>
        /// <param name="b">2nd multiplicand</param>
        /// <param name="alpha">scaling for <paramref name="a"/>*<paramref name="b"/></param>
        /// <param name="accumulateResult">
        /// Tells this method whether to accumulate (true) or not (false)
        /// </param>
        /// <param name="cm">
        /// optional restriction to computational domain
        /// </param>
        virtual public void ProjectQuotient(
            double alpha, DGField a, DGField b, CellMask cm, bool accumulateResult)
        {
            if (!object.ReferenceEquals(a.Basis.GridDat, this.Basis.GridDat))
            {
                throw new ArgumentException("field is associated to another grid.", "a");
            }
            if (!object.ReferenceEquals(b.Basis.GridDat, this.Basis.GridDat))
            {
                throw new ArgumentException("field is associated to another grid.", "b");
            }

            if (!accumulateResult)
            {
                if (a == this)
                {
                    a = (DGField)a.Clone();

                    if (b == this)
                    {
                        b = a;
                    }
                }
                else if (b == this)
                {
                    b = (DGField)b.Clone();
                }

                this.Clear();
            }

            SpatialOperator fracOp = new SpatialOperator(new string[] { "a", "b" },
                                                         new string[] { "res" },
                                                         QuadOrderFunc.Linear());

            fracOp.EquationComponents["res"].Add(new QuotientSource());
            fracOp.Commit();

            CoordinateVector coDom = this.CoordinateVector;

            var ev = fracOp.GetEvaluatorEx(
                new CoordinateMapping(a, b), null, coDom.Mapping,
                edgeQrCtx: new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.Basis.GridDat)),
                volQrCtx: new CellQuadratureScheme(true, cm));

            ev.Evaluate <CoordinateVector>(alpha, 1.0, coDom);
        }
예제 #19
0
        private void BuildEvaluatorsAndMasks()
        {
            CellMask fluidCells = speciesMap.SubGrid.VolumeMask;

            cutCells          = speciesMap.Tracker.Regions.GetCutCellMask();
            cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells);

            IBMControl control = speciesMap.Control;
            SpeciesId  species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName);

            CellQuadratureScheme volumeScheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme(
                species, true, fluidCells, control.LevelSetQuadratureOrder);

            // Does _not_ include agglomerated edges
            EdgeMask             nonVoidEdges = speciesMap.QuadSchemeHelper.GetEdgeMask(species);
            EdgeQuadratureScheme edgeScheme   = speciesMap.QuadSchemeHelper.GetEdgeQuadScheme(
                species, true, nonVoidEdges, control.LevelSetQuadratureOrder);

            this.m_Evaluator = new Lazy <IEvaluatorNonLin>(delegate() {
                this.Operator.EdgeQuadraturSchemeProvider   = g => edgeScheme;
                this.Operator.VolumeQuadraturSchemeProvider = g => volumeScheme;
                var opi = this.Operator.GetEvaluatorEx(
                    Mapping,
                    null, // TO DO: I SIMPLY REMOVE PARAMETERMAP HERE; MAKE THIS MORE PRETTY
                          //this.boundaryParameterMap, // TO DO: I SIMPLY REMOVE PARAMETERMAP HERE; MAKE THIS MORE PRETTY
                    Mapping);
                opi.ActivateSubgridBoundary(volumeScheme.Domain, subGridBoundaryTreatment: SubGridBoundaryModes.InnerEdgeLTS);
                //opi.ActivateSubgridBoundary(fluidCells, subGridBoundaryTreatment: SubGridBoundaryModes.InnerEdgeLTS);
                return(opi);
            });

            // Evaluator for boundary conditions at level set zero contour
            CellQuadratureScheme boundaryVolumeScheme = speciesMap.QuadSchemeHelper.GetLevelSetquadScheme(
                0, cutCells, control.LevelSetQuadratureOrder);

            this.boundaryEvaluator = new Lazy <IEvaluatorNonLin>(delegate() {
                boundaryOperator.EdgeQuadraturSchemeProvider   = g => null; // Contains no boundary terms
                boundaryOperator.VolumeQuadraturSchemeProvider = g => boundaryVolumeScheme;
                return(boundaryOperator.GetEvaluatorEx(
                           Mapping,
                           boundaryParameterMap,
                           Mapping));
            });
        }
예제 #20
0
        internal void BuildEvaluatorsAndMasks()
        {
            CellMask fluidCells = speciesMap.SubGrid.VolumeMask.Intersect(ABSubGrid.VolumeMask);

            cutCells          = speciesMap.Tracker.Regions.GetCutCellMask().Intersect(ABSubGrid.VolumeMask);
            cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells).Intersect(ABSubGrid.VolumeMask);


            IBMControl control = speciesMap.Control;
            SpeciesId  species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName);

            CellQuadratureScheme volumeScheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme(
                species, true, fluidCells, control.LevelSetQuadratureOrder);


            // Does _not_ include agglomerated edges
            EdgeMask nonVoidEdges = speciesMap.QuadSchemeHelper.GetEdgeMask(species);

            nonVoidEdges = nonVoidEdges.Intersect(ABSubGrid.AllEdgesMask);
            EdgeQuadratureScheme edgeScheme = speciesMap.QuadSchemeHelper.GetEdgeQuadScheme(
                species, true, nonVoidEdges, control.LevelSetQuadratureOrder);

            this.m_Evaluator = new Lazy <SpatialOperator.Evaluator>(() =>
                                                                    this.Operator.GetEvaluatorEx(
                                                                        Mapping,
                                                                        boundaryParameterMap,
                                                                        Mapping,
                                                                        edgeScheme,
                                                                        volumeScheme,
                                                                        ABSubGrid,
                                                                        subGridBoundaryTreatment: SpatialOperator.SubGridBoundaryModes.InnerEdgeLTS));

            // Evaluator for boundary conditions at level set zero contour
            CellQuadratureScheme boundaryVolumeScheme = speciesMap.QuadSchemeHelper.GetLevelSetquadScheme(
                0, cutCells, control.LevelSetQuadratureOrder);

            this.boundaryEvaluator = new Lazy <SpatialOperator.Evaluator>(() =>
                                                                          boundaryOperator.GetEvaluatorEx(
                                                                              Mapping,
                                                                              boundaryParameterMap,
                                                                              Mapping,
                                                                              null, // Contains no boundary terms --> PROBLEM??????????
                                                                              boundaryVolumeScheme));
        }
예제 #21
0
        /// <summary>
        /// Saves the sum of weights of each edge rule in the given
        /// <paramref name="compositeRule"/> together with the coordinates of
        /// the corresponding edge center into a text file.
        /// </summary>
        public static void SumOfWeightsToTextFileEdge(this ICompositeQuadRule <QuadRule> compositeRule, IGridData g, string filename)
        {
            int E     = g.iLogicalEdges.Count;
            var bMask = new System.Collections.BitArray(E);

            double[] wSum = new double[E];
            foreach (IChunkRulePair <QuadRule> crp in compositeRule)
            {
                for (int iEdge = crp.Chunk.i0; iEdge < crp.Chunk.JE; iEdge++)
                {
                    bMask[iEdge] = true;
                    wSum[iEdge]  = crp.Rule.Weights.Sum();
                }
            }

            var mask = new EdgeMask(g, bMask);

            mask.SaveToTextFile(filename, false, (X, i, ii) => wSum[i]);
        }
예제 #22
0
        /// <summary>
        /// Boundary quadrature for the surface elements, i.e. for each cut background-cell \f$ K_j \f$ a quadrature to approximate
        /// \f[
        ///    \int_{\partial K_j \cap \mathfrak{I} } \ldots \mathrm{dS} .
        /// \f]
        /// </summary>
        public EdgeQuadratureScheme GetEdgeQuadScheme(SpeciesId sp, bool UseDefaultFactories = true, EdgeMask IntegrationDomain = null, int?fixedOrder = null)
        {
            if (!this.SpeciesList.Contains(sp))
            {
                throw new ArgumentException("Given species (id = " + sp.cntnt + ") is not supported.");
            }


            // determine domain
            // ================
            var allRelevantEdges = GetEdgeMask(sp, IntegrationDomain);

            // create quadrature scheme
            // ========================
            {
                // default rules for all edges:
                EdgeQuadratureScheme edgeQrIns = new EdgeQuadratureScheme(UseDefaultFactories, allRelevantEdges);

                // overwrite with cut-cell-rules in cut-cells:
                foreach (var Kref in XDGSpaceMetrics.GridDat.Grid.RefElements)
                {
                    for (int iLevSet = 0; iLevSet < XDGSpaceMetrics.NoOfLevelSets; iLevSet++)   // loop over level sets...
                    {
                        EdgeMask cutEdges = this.GetCutEdges(Kref, iLevSet).Intersect(allRelevantEdges);
#if DEBUG
                        CellMask difference = cutEdges.GetAdjacentCells(XDGSpaceMetrics.GridDat).Except(XDGSpaceMetrics.LevelSetRegions.GetCutCellMask4LevSet(iLevSet));
                        if (difference.Count() > 0)
                        {
                            throw new ArithmeticException("Edges of the Cells" + difference.GetSummary() + " are detected as cut, but these cells are not contained in the cut Cell-Mask of the Level-Set-Tracker");
                        }
#endif


                        var jmp     = IdentifyWing(iLevSet, sp);
                        var factory = this.XDGSpaceMetrics.XQuadFactoryHelper.GetEdgeRuleFactory(iLevSet, jmp, Kref);
                        edgeQrIns.AddFactoryDomainPair(factory, cutEdges, fixedOrder);
                    }
                }

                return(edgeQrIns);
            }
        }
예제 #23
0
        /// <summary>
        /// Initializes the integral
        /// </summary>
        /// <param name="grdDat">Information about the grid</param>
        /// <param name="edgeTag">
        /// The edge tag of the boundary edges to be considered in the integral
        /// </param>
        /// <param name="flux">
        /// The integrand. To be more specific,
        /// <see cref="INonlinearFlux.BorderEdgeFlux"/> will be evaluated on
        /// every relevant edge to compute the value of the integrand
        /// </param>
        /// <param name="mapping">
        /// The coordinate mapping that maps field values to the arguments of
        /// <paramref name="flux"/> (see
        /// <see cref="IEquationComponent.ArgumentOrdering"/>)
        /// </param>
        /// <param name="integrationOrder">
        /// The desired order of the applied quadrature rule
        /// </param>
        public EdgeIntegral(GridData grdDat, byte edgeTag, INonlinearFlux flux, CoordinateMapping mapping, int integrationOrder)
        {
            byte[]   edgeTags = grdDat.Edges.EdgeTags;
            BitArray mask     = new BitArray(edgeTags.Length);

            int numberOfRelevantEdges = 0;

            for (int i = 0; i < edgeTags.Length; i++)
            {
                if (edgeTag == edgeTags[i])
                {
                    mask[i] = true;
                    numberOfRelevantEdges++;
                }
            }

            relevantEdgesMask = new EdgeMask(grdDat, mask);
            // Just use first ref element for the moment
            edgeQuadrature = new MyEdgeQuadrature(grdDat, integrationOrder, flux, mapping, 0, relevantEdgesMask);
        }
예제 #24
0
        protected void UpdateEvaluatorsAndMasks()
        {
            CellMask fluidCells = speciesMap.SubGrid.VolumeMask;

            cutCells          = speciesMap.Tracker.Regions.GetCutCellMask();
            cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells);

            IBMControl control = speciesMap.Control;
            SpeciesId  species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName);

            CellQuadratureScheme volumeScheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme(
                species, true, fluidCells, control.LevelSetQuadratureOrder);

            // Does _not_ include agglomerated edges
            EdgeMask             nonVoidEdges = speciesMap.QuadSchemeHelper.GetEdgeMask(species);
            EdgeQuadratureScheme edgeScheme   = speciesMap.QuadSchemeHelper.GetEdgeQuadScheme(
                species, true, nonVoidEdges, control.LevelSetQuadratureOrder);

            this.m_Evaluator = new Lazy <IEvaluatorNonLin>(delegate() {
                var opi = this.Operator.GetEvaluatorEx(
                    Mapping,
                    boundaryParameterMap,
                    Mapping,
                    edgeScheme,
                    volumeScheme);
                opi.ActivateSubgridBoundary(volumeScheme.Domain.ToLogicalMask(), subGridBoundaryTreatment: SpatialOperator.SubGridBoundaryModes.InnerEdgeLTS);
                return(opi);
            });

            // Evaluator for boundary conditions at level set zero contour
            CellQuadratureScheme boundaryVolumeScheme = speciesMap.QuadSchemeHelper.GetLevelSetquadScheme(
                0, cutCells, control.LevelSetQuadratureOrder);

            this.boundaryEvaluator = new Lazy <IEvaluatorNonLin>(() =>
                                                                 boundaryOperator.GetEvaluatorEx(
                                                                     Mapping,
                                                                     boundaryParameterMap,
                                                                     Mapping,
                                                                     null, // Contains no boundary terms
                                                                     boundaryVolumeScheme));
        }
예제 #25
0
        /// <summary>
        /// accumulates
        /// <paramref name="alpha"/>*<paramref name="f"/>(<paramref name="U"/>)
        /// to this field;
        /// </summary>
        /// <param name="alpha">scaling</param>
        /// <param name="f">
        /// some function
        /// - 1st argument: position in physical space
        /// - 2nd argument: values of fields in <paramref name="U"/> at respective position
        /// - 3rd argument: cell index
        /// - return value: value of function that should be projected at the respective position
        /// </param>
        /// <param name="cqs">
        /// cell quadrature scheme: domain and quadrature rule
        /// </param>
        /// <param name="U">
        /// arguments for <paramref name="f"/>
        /// </param>
        public void ProjectFunction(double alpha, Func <Vector, double[], int, double> f, CellQuadratureScheme cqs, params DGField[] U)
        {
            string[] Dom = new string[U.Length];
            for (int i = 0; i < Dom.Length; i++)
            {
                Dom[i] = "_" + i;
            }

            string[] Cod = new string[] { "res" };

            SpatialOperator src = new SpatialOperator(Dom, Cod, QuadOrderFunc.NonLinear(3));

            src.EquationComponents[Cod[0]].Add(new ProjectFunctionSource(Dom, f));
            src.EdgeQuadraturSchemeProvider   = g => new EdgeQuadratureScheme(false, EdgeMask.GetEmptyMask(this.Basis.GridDat));
            src.VolumeQuadraturSchemeProvider = g => cqs;
            src.Commit();

            var ev = src.GetEvaluatorEx(
                new CoordinateMapping(U), null, this.Mapping);

            ev.Evaluate(alpha, 1.0, this.CoordinateVector);
        }
예제 #26
0
        /// <summary>
        /// Accumulates the DG-projection (with respect to the DG-basis
        /// of this field, <see cref="Basis"/>) of
        /// <paramref name="alpha"/>*<paramref name="f"/>^<paramref name="pow"/> to this field;
        /// </summary>
        /// <param name="alpha">scaling for accumulation</param>
        /// <param name="f">operand</param>
        /// <param name="pow">exponent</param>
        /// <param name="em">
        /// An optional restriction to the domain in which the projection is
        /// computed (it may, e.g. be only required in boundary cells, so a
        /// computation over the whole domain would be a waste of computation
        /// power. A proper execution mask would be see e.g.
        /// <see cref="GridData.BoundaryCells"/>.)
        /// if null, the computation is carried out in the whole domain;
        /// </param>
        virtual public void ProjectPow(double alpha, DGField f, double pow, CellMask em)
        {
            if (!object.ReferenceEquals(f.Basis.GridDat, this.Basis.GridDat))
            {
                throw new ArgumentException("field is associated to another context.", "a");
            }

            SpatialOperator powOp = new SpatialOperator(new string[] { "f" },
                                                        new string[] { "res" },
                                                        QuadOrderFunc.SumOfMaxDegrees());

            powOp.EquationComponents["res"].Add(new PowSource(pow));
            powOp.Commit();

            CoordinateVector coDom = this.CoordinateVector;

            var ev = powOp.GetEvaluatorEx(
                new CoordinateMapping(f), null, coDom.Mapping,
                edgeQrCtx: new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.Basis.GridDat)),
                volQrCtx: new CellQuadratureScheme(true, em));

            ev.Evaluate <CoordinateVector>(alpha, 1.0, coDom); // only sources, no edge integrals required
        }
예제 #27
0
        /// <summary>
        /// Calculates the DG-projection (with respect to the DG-basis
        /// of this field, <see cref="Basis"/>) of
        /// <paramref name="alpha"/>*<paramref name="a"/>*<paramref name="b"/>
        /// and, depending on the value of <paramref name="accumulateResult"/>,
        /// either adds or assigns it to this field.
        /// </summary>
        /// <param name="a">1st multiplicand</param>
        /// <param name="b">2nd multiplicand</param>
        /// <param name="alpha">scaling for <paramref name="a"/>*<paramref name="b"/></param>
        /// <param name="em">
        /// An optional restriction to the domain in which the projection is
        /// computed (it may, e.g. be only required in boundary cells, so a
        /// computation over the whole domain would be a waste of computational
        /// power. A proper execution mask would be see e.g.
        /// <see cref="GridData.BoundaryCells"/>.)<br/>
        /// if null, the computation is carried out in the whole domain;
        /// </param>
        /// <param name="accumulateResult">
        /// Tells this method whether to accumulate (true) or not (false)
        /// </param>
        virtual public void ProjectProduct(double alpha, DGField a, DGField b, CellMask em, bool accumulateResult)
        {
            if (!object.ReferenceEquals(a.Basis.GridDat, this.Basis.GridDat))
            {
                throw new ArgumentException("field is associated to another grid.", "a");
            }
            if (!object.ReferenceEquals(b.Basis.GridDat, this.Basis.GridDat))
            {
                throw new ArgumentException("field is associated to another grid.", "b");
            }

            if (!accumulateResult)
            {
                if (a == this)
                {
                    a = (DGField)a.Clone();

                    if (b == this)
                    {
                        b = a;
                    }
                }
                else if (b == this)
                {
                    b = (DGField)b.Clone();
                }

                this.Clear();
            }

            SpatialOperator multOp = new SpatialOperator(new string[] { "a", "b" },
                                                         new string[] { "res" },
                                                         QuadOrderFunc.NonLinear(2));

            multOp.EdgeQuadraturSchemeProvider   = g => new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(g));
            multOp.VolumeQuadraturSchemeProvider = g => new CellQuadratureScheme(true, em);
            multOp.EquationComponents["res"].Add(new MultiplySource());
            multOp.Commit();

            var ev = multOp.GetEvaluatorEx(
                new[] { a, b }, null, this.Mapping);

            ev.Evaluate <CoordinateVector>(alpha, 1.0, this.CoordinateVector);
        }
예제 #28
0
        /// <summary>
        /// Calculates the drag (x-component) and lift (y-component) forces acting on a wall of a boundary fitted grid
        /// </summary>
        /// <param name="U"></param>
        /// <param name="P"></param>
        /// <param name="muA"></param>
        /// <returns></returns>
        static public double[] GetForces_BoundaryFitted(VectorField <SinglePhaseField> GradU, VectorField <SinglePhaseField> GradV, SinglePhaseField StressXX,
                                                        SinglePhaseField StressXY, SinglePhaseField StressYY, SinglePhaseField P, LevelSetTracker LsTrk, double muA, double beta)
        {
            int D = LsTrk.GridDat.SpatialDimension;

            if (D > 2)
            {
                throw new ArgumentException("Method GetForces_BoundaryFitted only implemented for 2D (viscoelastic)!");
            }
            // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray();
            //var UA = U.ToArray();
            MultidimensionalArray Grad_U = new MultidimensionalArray(D);
            var _GradU = GradU.ToArray();
            var _GradV = GradV.ToArray();


            int RequiredOrder = _GradU[0].Basis.Degree * 3 + 2;

            //int RequiredOrder = U[0].Basis.Degree * 3 + 2;
            //int RequiredOrder = LsTrk.GetXQuadFactoryHelper(momentFittingVariant).GetCachedSurfaceOrders(0).Max();
            //Console.WriteLine("Order reduction: {0} -> {1}", _RequiredOrder, RequiredOrder);

            //if (RequiredOrder > agg.HMForder)
            //    throw new ArgumentException();

            Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder);

            SinglePhaseField _StressXX = StressXX;
            SinglePhaseField _StressXY = StressXY;
            SinglePhaseField _StressYY = StressYY;

            SinglePhaseField pA = null;

            //pA = P.GetSpeciesShadowField("A");
            pA = P;



            double[] forces = new double[D];
            for (int d = 0; d < D; d++)
            {
                ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) {
                    int K = result.GetLength(1); // No nof Nodes
                    MultidimensionalArray Grad_URes   = MultidimensionalArray.Create(Len, K, D);
                    MultidimensionalArray Grad_VRes   = MultidimensionalArray.Create(Len, K, D);
                    MultidimensionalArray pARes       = MultidimensionalArray.Create(Len, K);
                    MultidimensionalArray StressXXRes = MultidimensionalArray.Create(Len, K);
                    MultidimensionalArray StressXYRes = MultidimensionalArray.Create(Len, K);
                    MultidimensionalArray StressYYRes = MultidimensionalArray.Create(Len, K);

                    var Normals = LsTrk.GridDat.Edges.NormalsCache.GetNormals_Edge(Ns, j0, Len);
                    //var Normals = MultidimensionalArray.Create(1, Ns.Length, 1);
                    //var Normals = LsTrk.GridDat.Edges.NormalsForAffine;


                    for (int i = 0; i < D; i++)
                    {
                        _GradU[i].EvaluateEdge(j0, Len, Ns, Grad_URes.ExtractSubArrayShallow(-1, -1, i),
                                               Grad_URes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1);

                        _GradV[i].EvaluateEdge(j0, Len, Ns, Grad_VRes.ExtractSubArrayShallow(-1, -1, i),
                                               Grad_VRes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1);

                        //UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                    }

                    //pA.Evaluate(j0, Len, Ns, pARes);
                    pA.EvaluateEdge(j0, Len, Ns, pARes, pARes, ResultIndexOffset: 0, ResultPreScale: 1);
                    _StressXX.EvaluateEdge(j0, Len, Ns, StressXXRes, StressXXRes, ResultIndexOffset: 0, ResultPreScale: 1);
                    _StressXY.EvaluateEdge(j0, Len, Ns, StressXYRes, StressXYRes, ResultIndexOffset: 0, ResultPreScale: 1);
                    _StressYY.EvaluateEdge(j0, Len, Ns, StressYYRes, StressYYRes, ResultIndexOffset: 0, ResultPreScale: 1);


                    //if (LsTrk.GridDat.SpatialDimension == 2)
                    //{

                    for (int j = 0; j < Len; j++)
                    {
                        for (int k = 0; k < K; k++)
                        {
                            double acc = 0.0;

                            // pressure
                            switch (d)
                            {
                            case 0:
                                acc += pARes[j, k] * Normals[j, k, 0];
                                acc -= (2 * muA * beta) * Grad_URes[j, k, 0] * Normals[j, k, 0];
                                acc -= (muA * beta) * Grad_URes[j, k, 1] * Normals[j, k, 1];
                                acc -= (muA * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 1];
                                acc -= (muA * (1 - beta)) * StressXXRes[j, k] * Normals[j, k, 0];
                                acc -= (muA * (1 - beta)) * StressXYRes[j, k] * Normals[j, k, 1];
                                break;

                            case 1:
                                acc += pARes[j, k] * Normals[j, k, 1];
                                acc -= (2 * muA * beta) * Grad_VRes[j, k, 1] * Normals[j, k, 1];
                                acc -= (muA * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 0];
                                acc -= (muA * beta) * Grad_URes[j, k, 1] * Normals[j, k, 0];
                                acc -= (muA * (1 - beta)) * StressXYRes[j, k] * Normals[j, k, 0];
                                acc -= (muA * (1 - beta)) * StressYYRes[j, k] * Normals[j, k, 1];
                                break;

                            default:
                                throw new NotImplementedException();
                            }

                            result[j, k] = acc;
                        }
                    }

                    //}
                    //else
                    //{
                    //    for (int j = 0; j < Len; j++)
                    //    {
                    //        for (int k = 0; k < K; k++)
                    //        {
                    //            double acc = 0.0;

                    //            // pressure
                    //            switch (d)
                    //            {
                    //                case 0:
                    //                    acc += pARes[j, k] * Normals[j, k, 0];
                    //                    acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0];
                    //                    acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 2];
                    //                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1];
                    //                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1];
                    //                    acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 2];
                    //                    break;
                    //                case 1:
                    //                    acc += pARes[j, k] * Normals[j, k, 1];
                    //                    acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1];
                    //                    acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 2];
                    //                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0];
                    //                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0];
                    //                    acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 2];
                    //                    break;
                    //                case 2:
                    //                    acc += pARes[j, k] * Normals[j, k, 2];
                    //                    acc -= (2 * muA) * Grad_UARes[j, k, 2, 2] * Normals[j, k, 2];
                    //                    acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 0];
                    //                    acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 1];
                    //                    acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 0];
                    //                    acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 1];
                    //                    break;
                    //                default:
                    //                    throw new NotImplementedException();
                    //            }

                    //    result[j, k] = acc;
                    //}
                    //}
                    //}
                };


                var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper;

                EdgeMask Mask = new EdgeMask(LsTrk.GridDat, "Wall_cylinder");

                EdgeQuadratureScheme eqs = SchemeHelper.GetEdgeQuadScheme(LsTrk.GetSpeciesId("A"), IntegrationDomain: Mask);

                EdgeQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                             eqs.Compile(LsTrk.GridDat, RequiredOrder), //  agg.HMForder),
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                    ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                },
                                             delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    for (int i = 0; i < Length; i++)
                    {
                        forces[d] += ResultsOfIntegration[i, 0];
                    }
                }
                                             ).Execute();
            }

            //for (int i = 0; i < D; i++)
            //    forces[i] = MPI.Wrappers.MPIExtensions.MPISum(forces[i]);

            return(forces);
        }
예제 #29
0
        /// <summary>
        /// checks whether the linear and nonlinear implementation of operator evaluation are mathematically equal
        /// </summary>
        void LinearNonlinComparisonTest()
        {
            int L = this.bnd.CoordinateVector.Count();

            // need to assure to use the same quadrature oder on both evaluation variants
            var volQrSch = (new CellQuadratureScheme(false, CellMask.GetFullMask(this.GridData, MaskType.Geometrical)))
                           .AddFixedOrderRules(this.GridData, this.PolynomialDegree * 3);
            var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData, MaskType.Geometrical))
                           .AddFixedOrderRules(this.GridData, this.PolynomialDegree * 3);

            //var volQrSch = new CellQuadratureScheme(true, CellMask.GetEmptyMask(this.GridData));
            //var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.GridData));
            //var edgQrSch = new EdgeQuadratureScheme(true, this.GridData.BoundaryEdges)
            //                        .AddFixedOrderRules(this.GridData, this.PolynomialDegree * 3);
            //var edgQrSch = new EdgeQuadratureScheme(true, this.GridData.BoundaryEdges.Complement())
            //                          .AddFixedOrderRules(this.GridData, this.PolynomialDegree * 3);



            for (int run = 0; run < 1; run++)
            {
                // setup a random test vector
                Random rnd          = new Random();
                var    TestArgument = this.bnd.CloneAs().CoordinateVector;
                for (int i = 0; i < L; i++)
                {
                    TestArgument[i] = rnd.NextDouble();
                }

                Stopwatch lin = new Stopwatch();
                Stopwatch nol = new Stopwatch();

                // linear evaluation
                CoordinateVector LinResult = this.ViscU_linear.CoordinateVector;
                LinResult.Clear();
                lin.Start();
                {
                    var map             = this.U.Mapping;
                    var tempOperatorMtx = new MsrMatrix(map, map);
                    var tempAffine      = new double[L];
                    Operator.ComputeMatrixEx(map, new DGField[] { this.mu }, map,
                                             tempOperatorMtx, tempAffine,
                                             volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch);


                    tempOperatorMtx.SpMVpara(1.0, TestArgument, 0.0, LinResult);
                    LinResult.AccV(1.0, tempAffine);
                }
                lin.Stop();

                // nonliner evaluation
                CoordinateVector NolResult = this.ViscU_nonlinear.CoordinateVector;
                NolResult.Clear();
                nol.Start();
                {
                    var evaluator = Operator.GetEvaluatorEx(TestArgument.Mapping, new DGField[] { this.mu }, this.Residual.Mapping,
                                                            volQrCtx: volQrSch, edgeQrCtx: edgQrSch);
                    evaluator.Evaluate(1.0, 0.0, NolResult);
                }
                nol.Stop();

                double L2Dist = GenericBlas.L2DistPow2(LinResult, NolResult).MPISum().Sqrt();
                Console.WriteLine("L2 dist of linear/Nonlinear evaluation comparison: {0}", L2Dist);

                LinResult.Acc(-1.0, NolResult);

                foreach (SinglePhaseField DGfield in LinResult.Mapping.Fields)
                {
                    for (int p = 0; p <= DGfield.Basis.Degree; p++)
                    {
                        double L2err_p = DGfield.L2NormPerMode(p);
                        Console.WriteLine("   ERR{2} {1} \t{0}", L2err_p, DGfield.Identification, p);
                    }
                }

                Console.WriteLine("Time linear {0}, time nonlinear: {1}", lin.Elapsed, nol.Elapsed);

                Assert.LessOrEqual(L2Dist, 1.0e-4, "L2 distance between linear and nonlinear evaluation of the same flux.");
            }
        }
        /// <summary>
        /// Legacy interface, preserved as static function.
        /// </summary>
        static public void ComputeMatrixEx <M, V>(
            this XSpatialOperator xOp,
            LevelSetTracker lsTrk,
            UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap,
            M Matrix, V AffineOffset, bool OnlyAffine, double time, bool MPIParameterExchange,
            IDictionary <SpeciesId, XSpatialOperator.QrSchemPair> SpeciesSchemes,
            IDictionary <SpeciesId, MultidimensionalArray> CellLengthScales,
            IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengthScales,
            MultidimensionalArray SlipLengths = null,
            SubGrid SubGrid = null)
            where M : IMutableMatrixEx
            where V : IList <double> //
        {
            CellMask SubGridCellMask = null;
            EdgeMask SubGridEdgeMask = null;

            if (SubGrid != null)
            {
                SubGridCellMask = SubGrid.VolumeMask;
                /// I don't know why, but this seems to work:
                SubGridEdgeMask = SubGrid.AllEdgesMask;
                /// And this does not:
                //SubGridEdgeMask = SubGrid.InnerEdgesMask;
            }

            SpeciesId[] ReqSpecies = SpeciesSchemes.Keys.ToArray();

            //int order = xOp.GetOrderFromQuadOrderFunction(DomainMap, Parameters, CodomainMap);
            //var SchemeHelper = lsTrk.GetXDGSpaceMetrics(ReqSpecies, order, 1).XQuadSchemeHelper;

            //var SpeciesSchemes_out = new Dictionary<SpeciesId, XSpatialOperator.QrSchemPair>();

            //foreach(var SpeciesId in SpeciesSchemes.Keys) {
            //    EdgeQuadratureScheme edgeScheme;
            //    CellQuadratureScheme cellScheme;

            //    var qrSchemes = SpeciesSchemes[SpeciesId];

            //    bool AssembleOnFullGrid = (SubGrid == null);
            //    if(qrSchemes.EdgeScheme == null) {
            //        edgeScheme = SchemeHelper.GetEdgeQuadScheme(SpeciesId, AssembleOnFullGrid, SubGridEdgeMask);
            //    } else {
            //        //edgeScheme = qrSchemes.EdgeScheme;
            //        //throw new ArgumentException();
            //    }

            //    if(qrSchemes.CellScheme == null) {
            //        cellScheme = SchemeHelper.GetVolumeQuadScheme(SpeciesId, AssembleOnFullGrid, SubGridCellMask);
            //    } else {
            //        //cellScheme = qrSchemes.CellScheme;
            //        throw new ArgumentException();
            //    }

            //    SpeciesSchemes_out.Add(SpeciesId,
            //        new XSpatialOperator.QrSchemPair() {
            //            CellScheme = cellScheme,
            //            EdgeScheme = edgeScheme
            //        });

            //}


            var ev = xOp.GetMatrixBuilder(lsTrk, DomainMap, Parameters, CodomainMap, SpeciesSchemes);


            ev.time           = time;
            ev.MPITtransceive = MPIParameterExchange;

            foreach (var s in CellLengthScales.Keys)
            {
                if (ev.SpeciesOperatorCoefficients.ContainsKey(s))
                {
                    ev.SpeciesOperatorCoefficients[s].CellLengthScales = CellLengthScales[s];
                }
                else
                {
                    ev.SpeciesOperatorCoefficients.Add(s,
                                                       new CoefficientSet()
                    {
                        CellLengthScales = CellLengthScales[s],
                        GrdDat           = lsTrk.GridDat
                    });
                }

                if (InterfaceLengthScales != null)
                {
                    ev.SpeciesOperatorCoefficients[s].UserDefinedValues["InterfaceLengths"] = InterfaceLengthScales[s];
                }

                if (SlipLengths != null)
                {
                    ev.SpeciesOperatorCoefficients[s].UserDefinedValues["SlipLengths"] = SlipLengths;
                }
            }


            if (OnlyAffine)
            {
                ev.ComputeAffine(AffineOffset);
            }
            else
            {
                ev.ComputeMatrix(Matrix, AffineOffset);
            }
        }