source: XIOS3/trunk/extern/remap/src/elt.hpp @ 2572

Last change on this file since 2572 was 2538, checked in by jderouillat, 11 months ago

Backport 2506 : limitation of number of vertex max in remaper

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