Example #1
0
        /// <summary>
        /// Construct a field updated for the given surface.
        /// </summary>
        /// <param name="surface"></param>
        /// <param name="options"></param>
        public PrognosticFieldsUpdater(IPolyhedron surface, IModelParameters options)
        {
            _options            = options;
            _coriolisField      = SimulationUtilities.CoriolisField(surface, _options.RotationFrequency);
            _faceNormalsField   = SimulationUtilities.FaceNormalsField(surface);
            _vertexNormalsField = SimulationUtilities.VertexNormalsField(surface);

            _operators = new VectorFieldOperators(surface);

            _gravity = options.Gravity;
        }
        /// <summary>
        /// The discrete gradient, as described in Randall & Ringler 2001.
        /// </summary>
        public VectorField <Vertex> Gradient(ScalarField <Face> A)
        {
            var numberOfVertices = _polyhedron.Vertices.Count;

            var results = new Vector[numberOfVertices];

            foreach (var vertex in Enumerable.Range(0, numberOfVertices))
            {
                results[vertex] = GradientAtVertex(vertex, A);
            }
            return(new VectorField <Vertex>(_polyhedron.IndexOf, results));
        }
        /// <summary>
        /// The vertex averaging operator, as described in Randall & Ringler 2001 (p16)
        /// </summary>
        public ScalarField <Vertex> VertexAverages(ScalarField <Face> F)
        {
            var numberOfVertices = _polyhedron.Vertices.Count;

            var averages = new double[numberOfVertices];

            for (int vertex = 0; vertex < numberOfVertices; vertex++)
            {
                averages[vertex] = VertexAverage(vertex, F);
            }

            return(new ScalarField <Vertex>(_polyhedron.IndexOf, averages));
        }
        private Vector GradientAtVertex(int vertex, ScalarField <Face> A)
        {
            var faces        = _faces[vertex];
            var coefficients = _gradientCoefficients[vertex];

            var result = Vector.Zeros(3);

            for (int j = 0; j < faces.Length; j++)
            {
                result += A[faces[j]] * coefficients[j];
            }

            return(result / _vertexAreas[vertex]);
        }
        /// <summary>
        /// The discrete divergence, as described in Randall & Ringler 2001 (p7)
        /// </summary>
        public ScalarField <Face> FluxDivergence(VectorField <Vertex> V, ScalarField <Face> F)
        {
            var numberOfFaces = _polyhedron.Faces.Count;
            var fluxes        = FluxesAcrossHalfEdges(V);

            var results = new double[numberOfFaces];

            for (int face = 0; face < numberOfFaces; face++)
            {
                results[face] = DivergenceAtFace(face, fluxes, F);
            }

            return(new ScalarField <Face>(_polyhedron.IndexOf, results));
        }
        private double VertexAverage(int vertex, ScalarField <Face> F)
        {
            var faces       = _faces[vertex];
            var areaPerFace = _areaInEachFace[vertex];

            var weightedSum = 0.0;
            var totalArea   = 0.0;

            for (int index = 0; index < faces.Length; index++)
            {
                weightedSum += F[faces[index]] * areaPerFace[index];
                totalArea   += areaPerFace[index];
            }

            return(weightedSum / totalArea);
        }
        private double DivergenceAtFace(int face, double[][] fluxes, ScalarField <Face> F)
        {
            var vertices = _vertices[face];
            var faceInFacesOfVertices = _faceInFacesOfVertices[face];

            var result = 0.0;

            for (int j = 0; j < faceInFacesOfVertices.Length; j++)
            {
                var vertex = vertices[j];
                var faceInFacesOfVertex = faceInFacesOfVertices[j];

                result += ContributionOfVertexToFluxAtFace(vertex, faceInFacesOfVertex, fluxes, F);
            }

            return(result / _faceAreas[face]);
        }
Example #8
0
 private ScalarField <Face> DerivativeOfHeight(VectorField <Vertex> velocity, ScalarField <Face> height)
 {
     return(-_operators.FluxDivergence(velocity, height));
 }
Example #9
0
        private VectorField <Vertex> DerivativeOfVelocity(VectorField <Vertex> velocity, ScalarField <Face> height)
        {
            var absoluteVorticity = _operators.VertexAverages(AbsoluteVorticity(velocity));
            var curlOfVelocity    = VectorField <Vertex> .CrossProduct(_vertexNormalsField, velocity);

            var kineticEnergyGradient = _operators.Gradient(_operators.KineticEnergy(velocity));

            var potentialEnergyGradient = _operators.Gradient(_gravity * height);

            return((-absoluteVorticity) * curlOfVelocity - kineticEnergyGradient - potentialEnergyGradient);
        }
        private double ContributionOfVertexToFluxAtFace(int vertex, int faceInFacesOfVertex, double[][] fluxes, ScalarField <Face> F)
        {
            var facesOfVertex = _faces[vertex];

            var indexOfThisFace = facesOfVertex.AtCyclicIndex(faceInFacesOfVertex);
            var valueAtThisFace = F[indexOfThisFace];

            var indexOfNextFace         = facesOfVertex.AtCyclicIndex(faceInFacesOfVertex + 1);
            var valueAtNextFace         = F[indexOfNextFace];
            var valueAtNextHalfEdge     = (valueAtNextFace + valueAtThisFace) / 2;
            var fluxAtNextHalfEdge      = fluxes[vertex][faceInFacesOfVertex];
            var fieldFluxAtNextHalfEdge = valueAtNextHalfEdge * fluxAtNextHalfEdge;

            var indexOfPreviousFace         = facesOfVertex.AtCyclicIndex(faceInFacesOfVertex - 1);
            var valueAtPreviousFace         = F[indexOfPreviousFace];
            var valueAtPreviousHalfEdge     = (valueAtThisFace + valueAtPreviousFace) / 2;
            var fluxAtPreviousHalfEdge      = -fluxes[vertex].AtCyclicIndex(faceInFacesOfVertex - 1);
            var fieldFluxAtPreviousHalfEdge = valueAtPreviousHalfEdge * fluxAtPreviousHalfEdge;

            return(fieldFluxAtNextHalfEdge + fieldFluxAtPreviousHalfEdge);
        }