source: XIOS/dev/dev_olga/extern/remap/src/elt.hpp @ 1635

Last change on this file since 1635 was 1635, checked in by oabramkina, 5 years ago

Backporting r1614 to dev before merging it to trunk.

File size: 4.1 KB
Line 
1#ifndef __ELT_H__
2#define __ELT_H__
3#include <list>
4#include "triple.hpp"
5
6#define NMAX 10 /**< maximum number of vertices for polygons */
7
8#define NOT_FOUND -1
9
10namespace sphereRemap {
11
12using namespace std;
13
14Coord barycentre(const Coord *x, int n);
15
16/** Two great or small circles (or mixed) have two or zero intersections.
17    The coordinates of the intersections are stored in `pt` and `nb` holds the number of intersections (0 or 2).
18    */
19struct Ipt
20{
21        int nb;
22        Coord pt[2];
23};
24
25struct Sgm // edge
26{
27        Coord n; // normal
28        Coord xt[2]; // endpoints
29        double d; // (see Elt)
30};
31
32struct GloId
33{
34        int rank;
35        int ind; /* local id */
36  long globalId ;
37
38        bool operator<(const GloId& other) const {
39                return (rank == other.rank) ? (ind < other.ind) : (rank < other.rank);
40        }
41};
42
43struct Polyg
44{ 
45        /* Note:  for the target grid elements the id (rank and local id) depends on the order of the target grid elements as read from the nc-file whereas for source grid elements it depends on the SS-tree (i.e. super mesh distribution, not the order in the nc-file) */
46        struct GloId id;
47        struct GloId src_id;
48        int n; /* number of vertices */
49        double area;
50  double given_area ;
51        Coord x; /* barycentre */
52};
53
54struct Elt : Polyg
55{
56        Elt() {}
57        Elt(const double *bounds_lon, const double *bounds_lat, int max_num_vert)
58        {
59                int k = 0;
60                vertex[k++] = xyz(bounds_lon[0], bounds_lat[0]);
61                for (int i = 1; i < max_num_vert; i++)
62                {
63                        vertex[k] = xyz(bounds_lon[i], bounds_lat[i]);
64                        /* netCDF convention: if first vertex repeats element is finished (at least three vertices == triagle) */
65                        if (k >= 3 && squaredist(vertex[k], vertex[0]) < EPS*EPS) 
66                                break;
67                        /* eliminate zero edges: move to next vertex only if it is different */
68                        if (squaredist(vertex[k], vertex[k-1]) > EPS*EPS)
69                                k++;
70                        else
71                                /* cout << "Removed edge " << k << " due to zero length (coinciding endpoints)." << endl */ ;
72                }
73                n = k;
74                x = barycentre(vertex, n);
75        }
76
77        Elt& operator=(const Elt& rhs)
78        {
79                id    = rhs.id;
80                src_id    = rhs.src_id;
81                n    = rhs.n;
82                area = rhs.area;
83                given_area = rhs.given_area;
84                x    = rhs.x;
85                val  = rhs.val;
86                grad = rhs.grad;
87                is   = rhs.is;
88
89                for(int i = 0; i < NMAX; i++)
90                {
91                        neighbour[i] = rhs.neighbour[i];
92                        d[i]         = rhs.d[i];
93                        edge[i]      = rhs.edge[i];
94                        vertex[i]    = rhs.vertex[i];
95                        gradNeigh[i] = rhs.gradNeigh[i];
96                }
97                return *this;
98        }
99
100        void delete_intersections()
101        {
102                for (list<Polyg*>::iterator it = this->is.begin(); it != this->is.end(); it++)
103                {
104                        Polyg* poly = *it;
105                        delete poly;
106                }
107        }
108
109  void insert_vertex(int i, const Coord& v)
110  {
111    for(int j=n; j > i ; j--)
112    {
113      vertex[j]=vertex[j-1] ;
114      edge[j]=edge[j-1] ;
115      d[j]=d[j-1] ;
116      neighbour[j]=neighbour[j-1] ;
117    }
118    vertex[i+1]=v ;
119    n++ ;
120  }
121 
122        int neighbour[NMAX];
123        double d[NMAX]; /**< distance of centre of small circle to origin, zero if great circle */
124        double val;     /**< value (sample if src element, interpolated if dest element) */
125        Coord vertex[NMAX];
126        Coord edge[NMAX]; /**< edge normals: if great circle tangential to sphere, if small circle parallel to pole */
127        Coord grad;    /**< gradient of the reconstructed linear function over this element */
128        Coord gradNeigh[NMAX]; /**< for weight computation: gradients for val=1 at individual neighbours */
129        struct GloId neighId[NMAX]; /**< weight computation needs to know global IDs for all sources with "link" */
130        std::list<Polyg*> is; /**< intersections */
131};
132
133static double normals(Elt &elt, const Coord &pole)
134{
135        double nmin = 17.;
136        for (int i = 0; i < elt.n; i++)  // supposed oriented
137        {
138                int j = (i+1) % elt.n;
139                elt.edge[i] = crossprod(elt.vertex[j], elt.vertex[i]); 
140                Coord t = elt.vertex[j] - elt.vertex[i];
141                /* polygonal grid || vertices not on same latitude */
142                if (pole == ORIGIN || fabs(scalarprod(t, pole)) > EPS)  // great circle
143                {
144                        double n = norm(elt.edge[i]);
145                        //assert(n > 0);
146                        if (n < nmin) nmin = n;
147                        elt.edge[i] = proj(elt.edge[i]);
148                        elt.d[i] = 0.0;
149                }
150                else /* lan lot grid && vertices on same latitude => small circle */
151                {
152                        int north = (scalarprod(elt.edge[i], pole) < 0) ? -1 : 1;
153                        elt.edge[i] = pole * north;
154                        elt.d[i] = scalarprod(elt.vertex[i], elt.edge[i]);
155                }
156        }
157        return nmin;
158}
159
160}
161
162#endif
Note: See TracBrowser for help on using the repository browser.