source: XIOS2/dev/mhedley/buildCompilationPatchesA/extern/remap/src/elt.hpp

Last change on this file was 2697, checked in by mhedley, 7 weeks ago

patches for C compilation

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