Пример #1
0
        /// <summary>
        /// Determines the total curvature which is twice the mean curvature
        /// Please pay attention to the sign of this expression!
        /// </summary>
        /// <param name="Output">The total curvature</param>
        /// <param name="optionalSubGrid">
        /// Subgrid which can be defined, for example for carrying out
        /// computations on a narrow band
        /// </param>
        /// <param name="bndMode">
        /// Definition of the behavior at subgrid boundaries
        /// </param>
        public void ComputeTotalCurvatureByFlux(SinglePhaseField Output,
                                                SubGrid optionalSubGrid      = null,
                                                SubGridBoundaryModes bndMode = SubGridBoundaryModes.OpenBoundary)
        {
            if (this.m_Basis.Degree <= 1)
            {
                throw new ArgumentException("For correct computation of these level set quantities, the level set has to be at least of degree 2!");
            }

            Basis basisForNormalVec = new Basis(this.GridDat, this.m_Basis.Degree - 1);
            Basis basisForCurvature = new Basis(this.GridDat, this.m_Basis.Degree - 2);

            Func <Basis, string, SinglePhaseField> fac          = (Basis b, string id) => new SinglePhaseField(b, id);
            VectorField <SinglePhaseField>         normalVector = new VectorField <SinglePhaseField>(this.GridDat.SpatialDimension, basisForNormalVec, fac);

            ComputeNormalByFlux(normalVector, optionalSubGrid, bndMode);
            VectorField <SinglePhaseField> secondDerivatives = new VectorField <SinglePhaseField>(this.GridDat.SpatialDimension, basisForCurvature, fac);

            Output.Clear();
            for (int i = 0; i < normalVector.Dim; i++)
            {
                secondDerivatives[i].DerivativeByFlux(1.0, normalVector[i], i, optionalSubGrid, bndMode);

                Output.Acc(-1.0, secondDerivatives[i], optionalSubGrid.VolumeMask);
            }
        }
Пример #2
0
 public void ActivateSubgridBoundary(CellMask mask, SubGridBoundaryModes subGridBoundaryTreatment = SubGridBoundaryModes.BoundaryEdge)
 {
     this.SubGridBoundaryTreatment = subGridBoundaryTreatment;
     if (!object.ReferenceEquals(mask.GridData, this.GridData))
     {
         throw new ArgumentException("grid mismatch");
     }
     subMask = mask;
 }
Пример #3
0
 /// <summary>
 /// see <see cref="DGField.LaplacianByFlux(double,DGField,DGField,SubGrid,SubGridBoundaryModes,SubGridBoundaryModes)"/>;
 /// </summary>
 override public void LaplacianByFlux(double alpha, DGField f, DGField tmp,
                                      SubGrid optionalSubGrid = null,
                                      SubGridBoundaryModes bndMode_1stDeriv = SubGridBoundaryModes.OpenBoundary,
                                      SubGridBoundaryModes bndMode_2ndDeriv = SubGridBoundaryModes.OpenBoundary)
 {
     if (tmp == null)
     {
         // the base implementation will create the temporary field by cloning, which is a bad idea for
         // the species-shadow-field
         tmp = new SinglePhaseField(this.Basis, "tmp");
     }
     base.LaplacianByFlux(alpha, f, tmp, optionalSubGrid, bndMode_1stDeriv, bndMode_2ndDeriv);
 }
Пример #4
0
        /// <summary>
        /// accumulates the curl of 2D DG vector field <paramref name="vec"/>
        /// times <paramref name="alpha"/>
        /// to this vector field, i.e. <br/>
        /// this = this + <paramref name="alpha"/>* Curl(<paramref name="vec"/>)
        /// </summary>
        /// <param name="alpha"></param>
        /// <param name="vec"></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>
        /// <remarks>
        /// This method is based on <see cref="DGField.DerivativeByFlux"/>, i.e.
        /// it calculates derivatives by central-difference fluxes;
        /// </remarks>
        /// <seealso cref="VectorField{T}.Curl3DByFlux"/>
        /// <param name="bndMode"></param>
        public void Curl2DByFlux <T>(double alpha, VectorField <T> vec,
                                     SubGrid optionalSubGrid      = null,
                                     SubGridBoundaryModes bndMode = SubGridBoundaryModes.OpenBoundary)
            where T : DGField
        {
            //diff(v(x, y), x)-(diff(u(x, y), y))
            using (new FuncTrace()) {
                if (vec.Dim != 2)
                {
                    throw new ArgumentException("vector field must be 2-dim.", "vec");
                }

                this.DerivativeByFlux(alpha, vec[1], 0, optionalSubGrid, bndMode);
                this.DerivativeByFlux(-alpha, vec[0], 1, optionalSubGrid, bndMode);
            }
        }
Пример #5
0
        /// <summary>
        /// accumulates the divergence of vector field <paramref name="vec"/>
        /// times <paramref name="alpha"/>
        /// to this field.
        /// </summary>
        /// <remarks>
        /// This method is based on <see cref="DerivativeByFlux"/>;
        /// </remarks>
        public void DivergenceByFlux <T>(double alpha, VectorField <T> vec,
                                         SubGrid optionalSubGrid = null, SubGridBoundaryModes bndMode = SubGridBoundaryModes.OpenBoundary) where T : DGField
        {
            using (new FuncTrace()) {
                if (vec.Dim != GridDat.SpatialDimension)
                {
                    throw new ArgumentException("wrong number of components in vector field.", "vec");
                }

                int D = GridDat.SpatialDimension;
                for (int d = 0; d < D; d++)
                {
                    this.DerivativeByFlux(alpha, vec[d], d, optionalSubGrid, bndMode);
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Accumulates the derivative of <paramref name="f"/> with respect to
        /// x_i to the i-th component of this vector field by making use of
        /// <see cref="DGField.DerivativeByFlux"/>
        /// </summary>
        /// <param name="alpha"></param>
        /// <param 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="Grid.GridData.BoundaryCells"/>.)
        /// <br/>
        /// if null, the computation is carried out in the whole domain.
        /// </param>
        /// <param name="bndMode">
        /// </param>
        public void GradientByFlux(
            double alpha,
            DGField f,
            SubGrid optionalSubGrid      = null,
            SubGridBoundaryModes bndMode = SubGridBoundaryModes.OpenBoundary)
        {
            int D = f.Basis.GridDat.SpatialDimension;

            if (this.Dim != D)
            {
                throw new NotSupportedException("this field has not the right spatial dimension");
            }

            for (int d = 0; d < D; d++)
            {
                this.m_Components[d].DerivativeByFlux(alpha, f, d, optionalSubGrid, bndMode);
            }
        }
Пример #7
0
        /// <summary>
        /// accumulates the Laplacian of field <paramref name="f"/> times
        /// <paramref name="alpha"/> to this field.
        /// </summary>
        /// <param name="alpha"></param>
        /// <param 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="tmp">
        /// temporary storage needed for the 1st derivatives of
        /// <paramref name="f"/>; If null, a clone of <paramref name="f"/>
        /// is taken.
        /// </param>
        /// <param name="bndMode_1stDeriv"></param>
        /// <param name="bndMode_2ndDeriv"></param>
        /// <remarks>
        /// This method is based on <see cref="DGField.DerivativeByFlux"/>,
        /// i.e. it calculates derivatives by central-difference fluxes;<br/>
        /// Note that of the Laplacian requires the allocation of a temporary DG field.
        /// </remarks>
        virtual public void LaplacianByFlux(double alpha, DGField f, DGField tmp = null,
                                            SubGrid optionalSubGrid = null,
                                            SubGridBoundaryModes bndMode_1stDeriv = SubGridBoundaryModes.OpenBoundary,
                                            SubGridBoundaryModes bndMode_2ndDeriv = SubGridBoundaryModes.OpenBoundary)
        {
            using (new FuncTrace()) {
                if (tmp == null)
                {
                    tmp = (DGField)f.Clone();
                }

                int D = GridDat.SpatialDimension;
                for (int d = 0; d < D; d++)
                {
                    tmp.Clear();
                    tmp.DerivativeByFlux(1.0, f, d, optionalSubGrid, bndMode_1stDeriv);
                    this.DerivativeByFlux(alpha, tmp, d, optionalSubGrid, bndMode_2ndDeriv);
                }
            }
        }
Пример #8
0
        /// <summary>
        /// accumulates the curl of 3D DG vector field <paramref name="vec"/>
        /// times <paramref name="alpha"/>
        /// to this vector field, i.e. <br/>
        /// this = this + <paramref name="alpha"/>* Curl(<paramref name="vec"/>)
        /// </summary>
        /// <param name="alpha"></param>
        /// <param name="vec"></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="Grid.GridData.BoundaryCells"/>.)
        /// <br/> if null, the computation is carried out in the whole domain.
        /// </param>
        /// <param name="bndMode"></param>
        /// <remarks>
        /// This method is based on
        /// <see cref="DGField.DerivativeByFlux(double,DGField,int,SubGrid,SubGridBoundaryModes)"/>,
        /// i.e. it calculates derivatives by central-difference fluxes;
        /// </remarks>
        /* <seealso cref="DGField.Curl2DByFlux{T}"/> */
        public void Curl3DByFlux(double alpha, VectorField <T> vec,
                                 SubGrid optionalSubGrid = null, SubGridBoundaryModes bndMode = SubGridBoundaryModes.OpenBoundary)
        {
            if (vec.Dim != 3)
            {
                throw new ArgumentException("this method works only for 3-dimensional vector fields.", "vec");
            }
            if (this.Dim != 3)
            {
                throw new ApplicationException("this vector field must be 3-dimensional.");
            }

            this.m_Components[0].DerivativeByFlux(alpha, vec.m_Components[2], 1, optionalSubGrid, bndMode);
            this.m_Components[0].DerivativeByFlux(-alpha, vec.m_Components[1], 2, optionalSubGrid, bndMode);

            this.m_Components[1].DerivativeByFlux(alpha, vec.m_Components[0], 2, optionalSubGrid, bndMode);
            this.m_Components[1].DerivativeByFlux(-alpha, vec.m_Components[2], 0, optionalSubGrid, bndMode);

            this.m_Components[2].DerivativeByFlux(alpha, vec.m_Components[1], 0, optionalSubGrid, bndMode);
            this.m_Components[2].DerivativeByFlux(-alpha, vec.m_Components[0], 1, optionalSubGrid, bndMode);
        }
Пример #9
0
        /// <summary>
        /// Vector of the d partial derivatives of the i-th component of the
        /// normal vector
        /// </summary>
        /// <param name="Output">Vector of the partial derivatives</param>
        /// <param name="componentOfNormalVec">
        /// specifies the component i of the normal vector
        /// </param>
        /// <param name="optionalSubGrid"></param>
        /// <param name="bndMode"></param>
        public void ComputeDerivativesOfTheNormalByFlux(
            VectorField <SinglePhaseField> Output,
            int componentOfNormalVec,
            SubGrid optionalSubGrid      = null,
            SubGridBoundaryModes bndMode = SubGridBoundaryModes.OpenBoundary)
        {
            if (this.m_Basis.Degree <= 1)
            {
                throw new ArgumentException("For correct computation of these level set quantities, the level set has to be at least of degree 2!");
            }
            Basis basisForNormalVec = new Basis(this.GridDat, this.m_Basis.Degree - 1);

            Func <Basis, string, SinglePhaseField> fac          = (Basis b, string id) => new SinglePhaseField(b, id);
            VectorField <SinglePhaseField>         normalVector = new VectorField <SinglePhaseField>(this.GridDat.SpatialDimension, basisForNormalVec, fac);

            ComputeNormalByFlux(normalVector, optionalSubGrid, bndMode);

            for (int i = 0; i < Output.Dim; i++)
            {
                Output[i].DerivativeByFlux(1.0, normalVector[componentOfNormalVec], i, optionalSubGrid, bndMode);
            }
        }
Пример #10
0
        /// <summary>
        /// Computation of mean curvature according to Bonnet's formula.
        /// </summary>
        /// <param name="scale"></param>
        /// <param name="Output">
        /// output.
        /// </param>
        /// <param name="quadScheme"></param>
        /// <param name="UseCenDiffUpTo">
        /// Either 0, 1, or 2:
        /// If 0, all derivatives are computed locally (broken derivative);
        /// if 1, the first order derivatives are computed by central
        /// differences, while the second order ones are computed locally,
        /// based on the first order ones;
        /// if 2, all derivatives are computed by central differences.
        /// </param>
        /// <param name="_1stDerivDegree">
        /// Relative DG polynomial degree for the 1st order derivatives, i.e.
        /// degree is <paramref name="_1stDerivDegree"/>+<em>p</em>, where
        /// <em>p</em> is the degree of this field.
        /// Only active if <paramref name="UseCenDiffUpTo"/> is greater than 0.
        /// </param>
        /// <param name="_2ndDerivDegree">
        /// Relative DG polynomial degree for the 2nd order derivatives, i.e.
        /// degree is <paramref name="_2ndDerivDegree"/>+<em>p</em>, where
        /// <em>p</em> is the degree of this field. Only active if
        /// <paramref name="UseCenDiffUpTo"/> is greater than 1.
        /// </param>
        /// <remarks>
        /// using central differences causes memory allocation: <em>D</em>
        /// fields for <paramref name="UseCenDiffUpTo"/>=1, and
        /// <em>D</em>*(<em>D</em>+1) for <paramref name="UseCenDiffUpTo"/>=2,
        /// where <em>D</em> notates the spatial dimension.
        /// </remarks>
        public void ProjectTotalcurvature2(
            double scale,
            SinglePhaseField Output,
            int UseCenDiffUpTo,
            int _1stDerivDegree             = 0,
            int _2ndDerivDegree             = 0,
            CellQuadratureScheme quadScheme = null)
        {
            using (new FuncTrace()) {
                if (UseCenDiffUpTo < 0 || UseCenDiffUpTo > 2)
                {
                    throw new ArgumentOutOfRangeException();
                }

                //int M = Output.Basis.Length;
                //int N = this.Basis.Length;
                int D = this.GridDat.SpatialDimension;
                //var NSC = m_context.NSC;

                SubGrid sgrd = null;
                SubGridBoundaryModes bndMode = SubGridBoundaryModes.InnerEdge;
                if (UseCenDiffUpTo >= 1 && quadScheme != null && quadScheme.Domain != null)
                {
                    sgrd    = new SubGrid(quadScheme.Domain);
                    bndMode = SubGridBoundaryModes.OpenBoundary;
                }

                // compute 1st order derivatives by central differences, if desired
                // ================================================================
                Basis B2 = new Basis(this.GridDat, this.Basis.Degree + _1stDerivDegree);

                SinglePhaseField[] GradientVector = null;
                if (UseCenDiffUpTo >= 1)
                {
                    GradientVector = new SinglePhaseField[D];
                    for (int d = 0; d < D; d++)
                    {
                        GradientVector[d] = new SinglePhaseField(B2);
                        GradientVector[d].DerivativeByFlux(1.0, this, d, sgrd, bndMode);
                    }
                }

                // compute 2nd order derivatives by central differences, if desired
                // ===============================================================
                Basis B3 = new Basis(this.GridDat, this.Basis.Degree + _2ndDerivDegree);

                SinglePhaseField[,] HessianTensor = null;
                if (UseCenDiffUpTo >= 2)
                {
                    HessianTensor = new SinglePhaseField[D, D];
                    for (int d1 = 0; d1 < D; d1++)
                    {
                        for (int d2 = 0; d2 < D; d2++)
                        {
                            HessianTensor[d1, d2] = new SinglePhaseField(B3);
                            HessianTensor[d1, d2].DerivativeByFlux(1.0, GradientVector[d1], d2, sgrd, bndMode);
                        }
                    }
                }

                // compute and project
                // ===================

                // buffers:
                MultidimensionalArray Phi     = new MultidimensionalArray(2);
                MultidimensionalArray GradPhi = new MultidimensionalArray(3);
                MultidimensionalArray HessPhi = new MultidimensionalArray(4);

                MultidimensionalArray ooNormGrad = new MultidimensionalArray(2);
                MultidimensionalArray Laplace    = new MultidimensionalArray(2);
                MultidimensionalArray Q          = new MultidimensionalArray(3);

                // evaluate/project:
                //double Erracc = 0;
                Output.ProjectField(scale,
                                    (ScalarFunctionEx) delegate(int j0, int Len, NodeSet NodeSet, MultidimensionalArray result) { // ScalarFunction2
                    Debug.Assert(result.Dimension == 2);
                    Debug.Assert(Len == result.GetLength(0));
                    int K = result.GetLength(1); // number of nodes


                    // alloc buffers
                    // -------------

                    if (Phi.GetLength(0) != Len || Phi.GetLength(1) != K)
                    {
                        Phi.Allocate(Len, K);
                        GradPhi.Allocate(Len, K, D);
                        HessPhi.Allocate(Len, K, D, D);
                        ooNormGrad.Allocate(Len, K);
                        Laplace.Allocate(Len, K);
                        Q.Allocate(Len, K, D);
                    }
                    else
                    {
                        Phi.Clear();
                        GradPhi.Clear();
                        HessPhi.Clear();
                        ooNormGrad.Clear();
                        Laplace.Clear();
                        Q.Clear();
                    }

                    // evaluate Gradient and Hessian
                    // -----------------------------

                    if (UseCenDiffUpTo >= 1)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            GradientVector[d].Evaluate(j0, Len, NodeSet, GradPhi.ExtractSubArrayShallow(-1, -1, d));
                        }
                    }
                    else
                    {
                        this.EvaluateGradient(j0, Len, NodeSet, GradPhi);
                    }

                    if (UseCenDiffUpTo == 2)
                    {
                        for (int d1 = 0; d1 < D; d1++)
                        {
                            for (int d2 = 0; d2 < D; d2++)
                            {
                                HessianTensor[d1, d2].Evaluate(j0, Len, NodeSet, HessPhi.ExtractSubArrayShallow(-1, -1, d1, d2));
                            }
                        }
                    }
                    else if (UseCenDiffUpTo == 1)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            var GradientVector_d = GradientVector[d];
                            GradientVector_d.EvaluateGradient(j0, Len, NodeSet, HessPhi.ExtractSubArrayShallow(-1, -1, d, -1), 0, 0.0);
                        }
                    }
                    else if (UseCenDiffUpTo == 0)
                    {
                        this.EvaluateHessian(j0, Len, NodeSet, HessPhi);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }

                    // compute the monstrous formula
                    // -----------------------------

                    // norm of Gradient:
                    for (int d = 0; d < D; d++)
                    {
                        var GradPhi_d = GradPhi.ExtractSubArrayShallow(-1, -1, d);
                        ooNormGrad.Multiply(1.0, GradPhi_d, GradPhi_d, 1.0, "ik", "ik", "ik");
                    }
                    ooNormGrad.ApplyAll(x => 1.0 / Math.Sqrt(x));

                    // laplacian of phi:
                    for (int d = 0; d < D; d++)
                    {
                        var HessPhi_d_d = HessPhi.ExtractSubArrayShallow(-1, -1, d, d);
                        Laplace.Acc(1.0, HessPhi_d_d);
                    }

                    // result = Laplacian(phi)/|Grad phi|
                    result.Multiply(1.0, Laplace, ooNormGrad, 0.0, "ik", "ik", "ik");


                    // result = Grad(1/|Grad(phi)|)
                    for (int d1 = 0; d1 < D; d1++)
                    {
                        var Qd = Q.ExtractSubArrayShallow(-1, -1, d1);

                        for (int d2 = 0; d2 < D; d2++)
                        {
                            var Grad_d2    = GradPhi.ExtractSubArrayShallow(-1, -1, d2);
                            var Hess_d2_d1 = HessPhi.ExtractSubArrayShallow(-1, -1, d2, d1);

                            Qd.Multiply(-1.0, Grad_d2, Hess_d2_d1, 1.0, "ik", "ik", "ik");
                        }
                    }

                    ooNormGrad.ApplyAll(x => x * x * x);

                    result.Multiply(1.0, GradPhi, Q, ooNormGrad, 1.0, "ik", "ikd", "ikd", "ik");

                    //for (int i = 0; i < Len; i++) {
                    //    for (int k = 0; k < K; k++) {
                    //        double acc = 0;
                    //        for (int d = 0; d < D; d++) {
                    //            acc += GradPhi[i,k,d]*Q[i,k,d]*ooNormGrad[i,k];
                    //        }

                    //        Erracc += (acc - result[i,k]).Abs();
                    //    }
                    //}
                },
                                    quadScheme.SaveCompile(this.GridDat, (Output.Basis.Degree + this.m_Basis.Degree * (this.m_Basis.Degree - 1) * D) * 2)
                                    );
            }
        }
Пример #11
0
        /// <summary>
        /// Assigns the normalized gradient of the level set to the Output
        /// vector
        /// </summary>
        /// <param name="Output">Normal vector</param>
        /// <param name="optionalSubGrid">
        /// Restriction of the computations to a an optional subgrid
        /// </param>
        /// <param name="bndMode"></param>
        public void ComputeNormalByFlux(VectorField <SinglePhaseField> Output, SubGrid optionalSubGrid = null, SubGridBoundaryModes bndMode = SubGridBoundaryModes.OpenBoundary)
        {
            if (this.m_Basis.Degree < 1)
            {
                throw new ArgumentException("For correct computation of these level set quantities, the level set has to be at least of degree 1!");
            }
            SinglePhaseField absval = new SinglePhaseField(Output[0].Basis);

            //Output.Clear();
            for (int i = 0; i < Output.Dim; i++)
            {
                Output[i].DerivativeByFlux(1.0, this, i, optionalSubGrid, bndMode);
            }

            absval.ProjectAbs(1.0, Output);
            for (int i = 0; i < Output.Dim; i++)
            {
                Output[i].ProjectQuotient(1.0, Output[i], absval, null, false);
            }
        }
Пример #12
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);
        }
Пример #13
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);
                });
            }
        }
Пример #14
0
        /// <summary>
        /// And another wrapper.
        /// </summary>
        static public void Evaluate(this SpatialOperator op, double time, SubGrid subGrid = null, SubGridBoundaryModes subGridBoundaryMode = SubGridBoundaryModes.OpenBoundary, params DGField[] f)
        {
            if (op.DomainVar.Count + op.ParameterVar.Count + op.CodomainVar.Count != f.Length)
            {
                throw new ArgumentException("wrong number of domain/parameter/codomain fields", "f");
            }

            CoordinateMapping inp = new CoordinateMapping(f.GetSubVector(0, op.DomainVar.Count));

            DGField[]         Parameters = f.GetSubVector(op.DomainVar.Count, op.ParameterVar.Count);
            CoordinateMapping outp       = new CoordinateMapping(f.GetSubVector(op.DomainVar.Count + op.ParameterVar.Count, op.CodomainVar.Count));

            Evaluate(op, 1.0, 0.0, inp, Parameters, outp, subGrid, null, null, subGridBoundaryMode, time);
        }
        /// <summary>
        /// Evaluates this operator for given DG fields;
        /// </summary>
        /// <param name="DomainMapping">
        /// the domain variables, or "input data" for the operator; the number
        /// of elements must be equal to the number of elements in the
        /// <see cref="DomainVar"/>-list;
        /// </param>
        /// <param name="Params">
        /// List of parameter fields; May be null
        /// </param>
        /// <param name="CodomainMapping">
        /// the co-domain variables, or "output" for the evaluation of the
        /// operator; the number of elements must be equal to the number of
        /// elements in the <see cref="CodomainVar"/>-list;
        /// </param>
        /// <param name="alpha">
        /// scaling of the operator
        /// </param>
        /// <param name="beta">
        /// scaling of the accumulator (<paramref name="CodomainMapping"/>);
        /// </param>
        /// <param name="sgrd">
        /// subgrid, for restricted evaluation; null indicates evaluation on
        /// the full grid.
        /// </param>
        /// <param name="bndMode">
        /// Treatment of subgrid boundaries, if <paramref name="sgrd"/> is not
        /// null. See <see cref="Evaluator"/>
        /// </param>
        /// <param name="qInsEdge">
        /// Optional definition of the edge quadrature scheme. Since this
        /// already implies a domain of integration, must be null if
        /// <paramref name="sgrd"/> is not null.
        /// </param>
        /// <param name="qInsVol">
        /// Optional definition of the volume quadrature scheme. Since this
        /// already implies a domain of integration, must be null if
        /// <paramref name="sgrd"/> is not null.
        /// </param>
        /// <remarks>
        /// If some of the input data, <paramref name="DomainMapping"/>, is
        /// contained in the  output data, <paramref name="CodomainMapping"/>,
        /// these DG fields will be cloned to ensure correct operation of the
        /// operator evaluation.<br/>
        /// It is not a good choice to use this function if this operator
        /// should be evaluated multiple times and  contains linear components
        /// (i.e. <see cref="ContainsLinear"/> returns true); If the latter is
        /// the case, the matrix which represents the linear components of the
        /// operator must be computed first, which is computational- and
        /// memory-intensive; After execution of this method, the matrix will
        /// be lost; If multiple evaluation is desired, the
        /// <see cref="Evaluator"/>-class should be used, in which the matrix
        /// of the operator will persist; However, if no linear components are
        /// present, the performance of this function should be almost
        /// comparable to the use of the <see cref="Evaluator"/>-class;
        /// </remarks>
        static public void Evaluate(
            this SpatialOperator op,
            double alpha, double beta,
            CoordinateMapping DomainMapping, IList <DGField> Params, CoordinateMapping CodomainMapping,
            SubGrid sgrd = null,
            EdgeQuadratureScheme qInsEdge = null,
            CellQuadratureScheme qInsVol  = null,
            SubGridBoundaryModes bndMode  = SubGridBoundaryModes.OpenBoundary,
            double time = double.NaN)                  //
        {
            using (new FuncTrace()) {
                if (sgrd != null && (qInsEdge != null || qInsVol != null))
                {
                    throw new ArgumentException("Specification of Subgrid and quadrature schemes is exclusive: not allowed to specify both at the same time.", "sgrd");
                }
#if DEBUG
                op.Verify();
#endif


                IList <DGField> _DomainFields          = DomainMapping.Fields;
                IList <DGField> _CodomainFields        = CodomainMapping.Fields;
                DGField[]       _DomainFieldsRevisited = new DGField[_DomainFields.Count];

                bool a = false;
                for (int i = 0; i < _DomainFields.Count; i++)
                {
                    DGField f = _DomainFields[i];

                    if (_CodomainFields.Contains(f))
                    {
                        // some of the domain variables (input data)
                        // is also a member of the codomain variables (output);
                        // the data need to be cloned to provide correct results
                        a = true;
                        _DomainFieldsRevisited[i] = (DGField)f.Clone();
                    }
                    else
                    {
                        _DomainFieldsRevisited[i] = f;
                    }
                }

                CoordinateMapping domainMappingRevisited;
                if (a)
                {
                    domainMappingRevisited = new CoordinateMapping(_DomainFieldsRevisited);
                }
                else
                {
                    domainMappingRevisited = DomainMapping;
                }

                if (sgrd != null)
                {
                    CellMask cm = (sgrd == null) ? null : sgrd.VolumeMask;
                    EdgeMask em = (sgrd == null) ? null : sgrd.AllEdgesMask;

                    qInsEdge = new EdgeQuadratureScheme(true, em);
                    qInsVol  = new CellQuadratureScheme(true, cm);
                }

                var bkup = op.LegacySupport_ModifyQuadSchemProvider(qInsEdge, qInsVol);


                var ev = op.GetEvaluatorEx(
                    domainMappingRevisited, Params, CodomainMapping);

                if (sgrd != null)
                {
                    ev.ActivateSubgridBoundary(sgrd.VolumeMask, bndMode);
                }
                CoordinateVector outp = new CoordinateVector(CodomainMapping);
                ev.time = time;
                ev.Evaluate <CoordinateVector>(alpha, beta, outp);

                op.LegacySupport_RestoreQuadSchemeProvider(bkup);
            }
        }