source: XIOS/dev/branch_yushan_merged/extern/remap/src/intersect.cpp @ 1149

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

bug fixed in mpi_comm_split. Key needs to be specifify.

File size: 10.7 KB
Line 
1#include <cstdlib>
2#include <cmath>
3#include <cassert>
4#include <cstring>
5#include <iostream>
6#include <fstream>
7#include "node.hpp"
8#include "elt.hpp"
9#include "gridRemap.hpp"
10#include "inside.hpp"
11#include "polyg.hpp"
12#include "intersect.hpp"
13#include "intersection_ym.hpp"
14
15namespace sphereRemap {
16
17using namespace std;
18
19/** returns index of edge of a that is shared with b,
20    or NOT_FOUND if a and b do not share an edge */
21int neighbour_idx(const Elt& a, const Elt& b)
22{
23        for (int i = 0; i < a.n; i++)
24        {
25                for (int j = 0; j < b.n; j++)
26                {
27                        assert(squaredist(a.vertex[ i       ], b.vertex[ j       ]) > EPS*EPS ||
28                               squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+1)%b.n]) > EPS*EPS);
29                        if (   squaredist(a.vertex[ i       ], b.vertex[ j           ]) < 1e-13*1e-13 &&
30                               squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+b.n-1)%b.n]) < 1e-13*1e-13)
31                        {
32                                return i;
33                        }
34                }
35        }
36        return NOT_FOUND;
37}
38
39/** New methods to find an insert a neighbour in a cell of the source mesh.
40 *  return true/false if cell b is a neighbour of a. if "insert" is true, then b will be inserted as a neighbour
41 * in cell a . This is needed for 2 order interpolation that need neighboround for gradient computing.
42 * A cell is a neighbour if :
43 *  - it shares 2 countiguous vertex (ie an edge) with a
44 *  - A vertex of b is located on one of an edge of a.
45 **/
46bool insertNeighbour( Elt& a, const Elt& b, bool insert )
47{
48  // for now suppose pole -> Oz
49  Coord pole(0,0,1) ;
50  Coord O, Oa1, Oa2,Ob1,Ob2,V1,V2 ;
51  double da,db,alpha,alpha1,alpha2,delta ;
52 
53   
54  for (int i = 0; i < a.n; i++)
55  {
56    for (int j = 0; j < b.n; j++)
57    {
58      // share a full edge ? be carefull at the orientation
59      /*
60      if(squaredist(a.vertex[i], b.vertex[j]) > 1e-10*1e-10 ||
61         squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+1)%b.n]) > 1e-10*1e-10 )
62      {     
63        printf("A : squaredist(a.vertex[%d], b.vertex[%d]) = %.10e  %d\n",
64                i, j, squaredist(a.vertex[i], b.vertex[j]),
65                squaredist(a.vertex[i], b.vertex[j]) > 1e-10*1e-10 ? true : false);
66        printf("B : squaredist(a.vertex[%d], b.vertex[%d]) = %.10e  %d\n",
67                (i+1)%a.n, (j+1)%b.n, squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+1)%b.n]),
68                squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+1)%b.n]) > 1e-10*1e-10 ? true : false);
69
70        assert(squaredist(a.vertex[ i       ], b.vertex[ j       ]) > 1e-10*1e-10 ||
71               squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+1)%b.n]) > 1e-10*1e-10);
72        exit(0);
73      }*/
74      if (   squaredist(a.vertex[ i       ], b.vertex[ j           ]) < 1e-10*1e-10 &&
75             squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+b.n-1)%b.n]) < 1e-10*1e-10)
76      {
77        if (insert) a.neighbour[i] = b.id.ind ;
78        return true;
79      }
80     
81
82// 1 or 2 vertices of b is located on an edge of a
83       da=a.d[i] ;
84       if (scalarprod(a.edge[i], pole) < 0) da=-da ;
85       db=b.d[(j+b.n-1)%b.n] ;
86       if (scalarprod(b.edge[(j+b.n-1)%b.n], pole) < 0) db=-db ;
87     
88      if ( fabs(da-db)<1e-10 ) 
89      {
90        O=pole*da ;
91        Oa1=a.vertex[i]-O ;
92        Oa2=a.vertex[(i+1)%a.n]-O ; 
93        Ob1=b.vertex[j]-O ;
94        Ob2=b.vertex[(j+b.n-1)%b.n]-O ;
95        V1=crossprod(Oa1,Oa2) ;
96        V2=crossprod(Ob1,Ob2) ;
97        if (norm(crossprod(V1,V2))/(norm(V1)*norm(V2)) < 1e-10)
98        {
99          alpha = vectAngle(Oa1,Oa2,V1) ;
100          alpha1= vectAngle(Oa1,Ob1,V1) ;
101          alpha2= vectAngle(Oa1,Ob2,V1) ;
102          delta= alpha2-alpha1 ;
103          if (delta >= M_PI) delta=2*M_PI-delta ;
104          else if (delta <= -M_PI) delta=2*M_PI+delta ;
105         
106          if (alpha >= 0)
107          {
108            if (alpha1 > 1e-10 && alpha1 < alpha-1e-10)
109            {
110              if (alpha2 > 1e-10 && alpha2 < alpha-1e-10)
111              {
112                assert(delta > 0) ;
113                if (insert)
114                {
115                // insert both
116                  a.insert_vertex(i,b.vertex[(j+b.n-1)%b.n]);
117                  a.insert_vertex(i,b.vertex[j]);
118                  a.neighbour[i+1] = b.id.ind ;
119                }
120                return true ;
121              }
122              else
123              {
124                assert( delta > 0 ) ;
125                if (insert)
126                {
127                //insert alpha1
128                  a.insert_vertex(i,b.vertex[j]);
129                  a.neighbour[i+1] = b.id.ind ;
130                }
131                return true ;
132              }
133            }
134            else if (alpha2 > 1e-10 && alpha2 < alpha-1e-10)
135            {
136              assert( delta > 0 ) ;
137              if (insert)
138              {
139              // insert alpha2
140                a.insert_vertex(i,b.vertex[(j+b.n-1)%b.n]);
141                a.neighbour[i] = b.id.ind ;
142              }
143              return true ;
144            }
145            else
146            {
147              // nothing to do
148            } 
149
150          }
151          else  // alpha < 0
152          {
153            if (alpha1 < -1e-10 && alpha1 > alpha+1e-10)
154            {
155              if (alpha2 < -1e-10 && alpha2 > alpha+1e-10)
156              {
157                assert(delta < 0) ;
158                if (insert)
159                {
160                // insert both
161                  a.insert_vertex(i,b.vertex[(j+b.n-1)%b.n]);
162                  a.insert_vertex(i,b.vertex[j]);
163                  a.neighbour[i+1] = b.id.ind ;
164                }
165                return true ;
166              }
167              else
168              {
169                assert(delta < 0) ;
170                if (insert)
171                {
172                //insert alpha1
173                  a.insert_vertex(i,b.vertex[j]);
174                  a.neighbour[i+1] = b.id.ind ;
175                }
176                return true ;
177              }
178            }
179            else if (alpha2 < -1e-10 && alpha2 > alpha+1e-10)
180            {
181              assert(delta < 0) ;
182              if (insert)
183              {
184              // insert alpha2
185                a.insert_vertex(i,b.vertex[(j+b.n-1)%b.n]);
186                a.neighbour[i] = b.id.ind ;
187              }
188              return true ;
189            }
190            else
191            {
192               // nothing to do
193            }
194          }
195        }
196      }
197    }
198  }
199  return false;
200}
201
202/**
203If `a` and `b` are neighbours (in the sense that they share an edge)
204then this information will be stored in `a` (but not in `b`)
205*/
206void set_neighbour(Elt& a, const Elt& b)
207{
208  if (b.id.ind == a.id.ind) return;
209/*
210  int idx = neighbour_idx(a, b);
211  if (idx != NOT_FOUND)
212  a.neighbour[idx] = b.id.ind;
213*/
214  insertNeighbour(a,b,true) ; 
215}
216
217/** return true if `a` and `b` share an edge */
218bool isNeighbour(Elt& a, const Elt& b)
219{
220        // return neighbour_idx(a, b) != NOT_FOUND;
221  return insertNeighbour(a,b,false) ;
222}
223
224/* computes intersection between elements a and b */
225
226void intersect(Elt *a, Elt *b)
227{
228        int na = a->n; /* vertices of a */
229        int nb = b->n; /* vertices of b */
230        Coord *c   = new Coord[na+nb];
231        Coord *c2  = new Coord[na+nb];
232        Coord *xc  = new Coord[na+nb];
233        Coord *xc2 = new Coord[na+nb];
234        Coord gc, gc2;
235        double *d = new double[na+nb];
236        double *d2 = new double[na+nb];
237        double are, are2;
238        Ipt ipt[NMAX*NMAX];
239        Ipt ipt2[NMAX*NMAX];
240        ptsec(a, b, ipt);
241        /* make ipt2 transpose of ipt */
242        for (int ii = 0; ii < na; ii++)
243                for (int jj = 0; jj < nb; jj++)
244                        ipt2[jj*na+ii] = ipt[ii*nb+jj];
245        list<Sgm> iscot;
246        recense(a, b, ipt, iscot, 0);
247        recense(b, a, ipt2, iscot, 1);
248
249        int nseg = iscot.size();
250        int nc = 0;
251        int nc2 = 0;
252        while (iscot.size() && nc < 2)
253                nc = assemble(iscot, c, d, xc);
254        while (iscot.size() && nc2 < 2)
255                nc2 = assemble(iscot, c2, d2, xc2);
256//      assert(nseg == nc + nc2 || nseg == 1); // unused segment
257
258        if (!(nseg == nc + nc2 || nseg == 1))
259        {
260
261
262//          cout<<a->x.x<<"  "<<a->x.y<<"  "<<a->x.z<<endl ;
263//          cout<<b->x.x<<"  "<<b->x.y<<"  "<<b->x.z<<endl ;
264//          cout<<" List of vertex from a and b"<<endl ;
265//          for(int i=0;i<na;i++) cout <<"polygonPoints.InsertPoint("<<i<<", "<<a->vertex[i].x<<", "<<a->vertex[i].y<<", "<<a->vertex[i].z<<")"<<endl ;
266//          for(int i=0;i<nb;i++) cout <<"polygonPoints.InsertPoint("<<i+6<<", "<<b->vertex[i].x<<", "<<b->vertex[i].y<<", "<<b->vertex[i].z<<")"<<endl ;
267//          cout<<"na : "<<na<<"   nb : "<<nb<<endl;
268//          cout<<"nc :"<<nc<<"  nc2 :"<<nc2<<"   nseg : "<<nseg<<endl ;
269//          abort() ;
270//         cout<<"**********************************************"<<endl ;
271//         intersect_ym(a,b) ;
272        }
273
274//    intersect_ym(a,b) ;
275        if (nc == 1) nc = 0;
276        if (nc2 == 1) nc2 = 0;
277        gc = barycentre(xc, nc);
278        gc2 = barycentre(xc2, nc2);
279        orient(nc, xc, c, d, gc);
280
281        Coord pole = srcGrid.pole;
282        if (pole == ORIGIN) pole = tgtGrid.pole;
283        const double MINBASE = 1e-11;
284        if (nc == 2) /* nc is the number of vertices of super mesh element */
285        {
286                double base = arcdist(xc[0], xc[1]);
287cerr << "DID ARRIVE " << base << xc[0] << xc[1] << endl;
288                gc = midpoint(gc, midpointSC(xc[0], xc[1]));
289                /* intersection area `are` must be zero here unless we have one great and one small circle */
290                are = alun(base, fabs(scalarprod(xc[0], pole)));
291        }
292        else
293        {
294                are = airbar(nc, xc, c, d, pole, gc);
295        }
296        if (nc2 == 2)
297        {
298                double base = arcdist(xc2[0], xc2[1]);
299cerr << "DID ARRIVE " << base << xc2[0] << xc2[1] << endl;
300                assert(base > MINBASE);
301                gc2 = midpoint(gc2, midpointSC(xc2[0], xc2[1]));
302                are2 = alun(base, fabs(scalarprod(xc2[0], pole))); // 0
303        }
304        else
305        {
306                are2 = airbar(nc2, xc2, c2, d2, pole, gc2);
307        }
308
309//  double ym_area=intersect_ym(a,b) ;
310
311  if (nc > 1)
312        {
313                /* create one super mesh polygon that src and dest point to */
314                Polyg *is = new Polyg;
315                is->x = gc;
316                is->area = are;
317                is->id = b->id;
318                is->src_id = b->src_id;
319                is->n = nc;
320                (a->is).push_back(is);
321                (b->is).push_back(is);
322/*
323          if (  2*fabs(are-ym_area)/(are+ym_area) > 1.1 && ym_area>1e-8)
324    {
325      cout<<"Big area difference : "<<are<<"  "<<ym_area<<endl ;
326      intersect_ym(a,b) ;
327    }
328*/
329//              cout<<"intersection : "<<are<<" "<< ym_area<<"  diff : "<<fabs(are-ym_area)<<"  ratio : "<<fabs(are-ym_area)/(0.5*(are+ym_area))<<endl ;
330        }
331        if (nc2 > 1)
332        {
333                Polyg *is = new Polyg;
334                is->x = gc2;
335                is->area = are2;
336                is->id = b->id; /* intersection holds id of corresponding source element (see Elt class definition for details about id) */
337                is->src_id = b->src_id;
338                is->n = nc2;
339                (a->is).push_back(is);
340                (b->is).push_back(is);
341/*
342    if (        2*fabs(are-ym_area)/(are+ym_area) > 1.1 && ym_area>1e-8 )
343    {
344      cout<<"Big area difference : "<<are<<"  "<<ym_area<<endl ;
345      intersect_ym(a,b) ;
346    }
347*/
348//              cout<<"intersection : "<<are2<<" "<< ym_area<<"  diff : "<<fabs(are-ym_area)<<"  ratio : "<<fabs(are-ym_area)/(0.5*(are+ym_area))<<endl ;
349        }
350/*
351  if (nc<=1 && nc2<=1)
352  {
353    if (ym_area>1e-12)
354    {
355      cout<<"Big area difference : "<<0<<"  "<<ym_area<<endl ;
356    }
357  }
358*/
359        delete [] c;
360        delete [] c2;
361        delete [] xc;
362        delete [] xc2;
363        delete [] d;
364        delete [] d2;
365}
366
367}
Note: See TracBrowser for help on using the repository browser.