source: XIOS/dev/branch_yushan_merged/extern/remap/src/elt.hpp @ 1176

Last change on this file since 1176 was 1172, checked in by yushan, 7 years ago

save dev. need to unify the file type when using EP

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        Coord x; /* barycentre */
51};
52
53struct Elt : Polyg
54{
55  Elt() {}
56  Elt(const double *bounds_lon, const double *bounds_lat, int max_num_vert)
57  {
58    int k = 0;
59    vertex[k++] = xyz(bounds_lon[0], bounds_lat[0]);
60    for (int i = 1; i < max_num_vert; i++)
61    {
62      vertex[k] = xyz(bounds_lon[i], bounds_lat[i]);
63      /* netCDF convention: if first vertex repeats element is finished (at least three vertices == triagle) */
64      if (k >= 3 && squaredist(vertex[k], vertex[0]) < EPS*EPS) 
65        break;
66      /* eliminate zero edges: move to next vertex only if it is different */
67      if (squaredist(vertex[k], vertex[k-1]) > EPS*EPS)
68        k++;
69      //else cout << "Removed edge " << k << " due to zero length (coinciding endpoints)." << endl ;
70    }
71    n = k;
72    x = barycentre(vertex, n);
73  }
74
75        Elt& operator=(const Elt& rhs)
76        {
77                id    = rhs.id;
78                src_id    = rhs.src_id;
79                n    = rhs.n;
80                area = rhs.area;
81                x    = rhs.x;
82                val  = rhs.val;
83                grad = rhs.grad;
84                is   = rhs.is;
85
86                for(int i = 0; i < NMAX; i++)
87                {
88                        neighbour[i] = rhs.neighbour[i];
89                        d[i]         = rhs.d[i];
90                        edge[i]      = rhs.edge[i];
91                        vertex[i]    = rhs.vertex[i];
92                        gradNeigh[i] = rhs.gradNeigh[i];
93                }
94                return *this;
95        }
96
97  void delete_intersections()
98  {
99    for (list<Polyg*>::iterator it = this->is.begin(); it != this->is.end(); it++)
100    {
101      Polyg* poly = *it;
102      delete poly;
103    }
104  }
105
106  void insert_vertex(int i, const Coord& v)
107  {
108    for(int j=n; j > i ; j--)
109    {
110      vertex[j]=vertex[j-1] ;
111      edge[j]=edge[j-1] ;
112      d[j]=d[j-1] ;
113      neighbour[j]=neighbour[j-1] ;
114    }
115    vertex[i+1]=v ;
116    n++ ;
117  }
118 
119        int neighbour[NMAX];
120        double d[NMAX]; /**< distance of centre of small circle to origin, zero if great circle */
121        double val;     /**< value (sample if src element, interpolated if dest element) */
122        Coord vertex[NMAX];
123        Coord edge[NMAX]; /**< edge normals: if great circle tangential to sphere, if small circle parallel to pole */
124        Coord grad;    /**< gradient of the reconstructed linear function over this element */
125        Coord gradNeigh[NMAX]; /**< for weight computation: gradients for val=1 at individual neighbours */
126        struct GloId neighId[NMAX]; /**< weight computation needs to know global IDs for all sources with "link" */
127        std::list<Polyg*> is; /**< intersections */
128};
129
130static double normals(Elt &elt, const Coord &pole)
131{
132        double nmin = 17.;
133        for (int i = 0; i < elt.n; i++)  // supposed oriented
134        {
135                int j = (i+1) % elt.n;
136                elt.edge[i] = crossprod(elt.vertex[j], elt.vertex[i]); 
137                Coord t = elt.vertex[j] - elt.vertex[i];
138                /* polygonal grid || vertices not on same latitude */
139                if (pole == ORIGIN || fabs(scalarprod(t, pole)) > EPS)  // great circle
140                {
141                        double n = norm(elt.edge[i]);
142                        //assert(n > 0);
143                        if (n < nmin) nmin = n;
144                        elt.edge[i] = proj(elt.edge[i]);
145                        elt.d[i] = 0.0;
146                }
147                else /* lan lot grid && vertices on same latitude => small circle */
148                {
149                        int north = (scalarprod(elt.edge[i], pole) < 0) ? -1 : 1;
150                        elt.edge[i] = pole * north;
151                        elt.d[i] = scalarprod(elt.vertex[i], elt.edge[i]);
152                }
153        }
154        return nmin;
155}
156
157}
158
159#endif
Note: See TracBrowser for help on using the repository browser.