source: issm/trunk/src/c/shared/Triangle/TriangleUtils.cpp

Last change on this file was 27232, checked in by Mathieu Morlighem, 3 years ago

merged trunk-jpl and trunk for revision 27230

File size: 27.1 KB
Line 
1/*
2 * TriangleUtils: mesh manipulation routines:
3 */
4
5#include <stdio.h>
6
7#include "./triangle.h"
8#include "../Exceptions/exceptions.h"
9#include "../MemOps/MemOps.h"
10
11#define RIFTPENALTYPAIRSWIDTH 8
12int IsGridOnRift(int* riftsegments, int nriftsegs, int node){/*{{{*/
13
14 /*Does this node belong to 4 elements, or just 2? If it belongs to 4 elements, it is inside a rift,
15 *if it belongs to 2 elements, it is on the tip of a rift, or it has already been split across the rift (see below).*/
16
17 int i;
18 int j;
19 int count;
20
21 count=0;
22 for (i=0;i<nriftsegs;i++){
23 for (j=0;j<2;j++){
24 if ((*(riftsegments+4*i+2+j))==node) count++;
25 }
26 }
27 if (count==2){
28 return 1;
29 }
30 else{
31 return 0;
32 }
33}/*}}}*/
34int GridElementsList(int** pGridElements, int* pNumGridElements,int node,int* index,int nel){/*{{{*/
35
36 /*From a node, recover all the elements that are connected to it: */
37 int i,j;
38 int noerr=1;
39
40 int max_number_elements=12;
41 int current_size;
42 int NumGridElements;
43 int* GridElements=NULL;
44 int* GridElementsRealloc=NULL;
45
46 /*From a mesh with 30 degrees minimum angle, we get 12 possible elements that own
47 * the node. We start by allocating GridElements with that size, and realloc
48 * more if needed.*/
49
50 current_size=max_number_elements;
51 NumGridElements=0;
52 GridElements=xNew<int>(max_number_elements);
53
54 for (i=0;i<nel;i++){
55 for (j=0;j<3;j++){
56 if (index[3*i+j]==node){
57 if (NumGridElements<=(current_size-1)){
58 GridElements[NumGridElements]=i;
59 NumGridElements++;
60 break;
61 }
62 else{
63 /*Reallocate another max_number_elements slots in the GridElements: */
64 GridElementsRealloc=xReNew<int>(GridElements,current_size,(current_size+max_number_elements));
65 if (!GridElementsRealloc){
66 noerr=0;
67 goto cleanup_and_return;
68 }
69 current_size+=max_number_elements;
70 GridElements=GridElementsRealloc;
71 GridElements[NumGridElements]=i;
72 NumGridElements++;
73 break;
74 }
75 }
76 }
77 }
78 cleanup_and_return:
79 if(!noerr){
80 xDelete<int>(GridElements);
81 }
82 /*Allocate return pointers: */
83 *pGridElements=GridElements;
84 *pNumGridElements=NumGridElements;
85 return noerr;
86}/*}}}*/
87int IsNeighbor(int el1,int el2,int* index){/*{{{*/
88 /*From a triangulation held in index, figure out if elements 1 and 2 have two nodes in common: */
89 int i,j;
90 int count=0;
91 for (i=0;i<3;i++){
92 for (j=0;j<3;j++){
93 if (index[3*el1+i]==index[3*el2+j])count++;
94 }
95 }
96 if (count==2){
97 return 1;
98 }
99 else{
100 return 0;
101 }
102}/*}}}*/
103int IsOnRift(int el,int nriftsegs,int* riftsegments){/*{{{*/
104 /*From a list of elements segments, figure out if el belongs to it: */
105 int i;
106 for (i=0;i<nriftsegs;i++){
107 if ((*(riftsegments+4*i+0)==el) || (*(riftsegments+4*i+1)==el)){
108 return 1;
109 }
110 }
111 return 0;
112}/*}}}*/
113void RiftSegmentsFromSegments(int* pnriftsegs, int** priftsegments, int nel,int* index,int nsegs,int* segments){/*{{{*/
114
115 int i,counter;
116 int el,el2;
117
118 int nriftsegs;
119 int* riftsegments=NULL;
120 int* riftsegments_uncompressed=NULL;
121 int element_nodes[3];
122
123 /*Allocate segmentflags: */
124 riftsegments_uncompressed=xNewZeroInit<int>(nsegs*5);
125
126 /*Find the segments that belong to a rift: they are the ones that see two elements. The other ones belong to a boundary
127 *or a hole: */
128 nriftsegs=0;
129 for (i=0;i<nsegs;i++){
130 el=(int)*(segments+3*i+2)-1; //element found in AssociateSegmentToElements
131 /*Temporarily set nodes belonging to the segments to -1 in the triangulation index, and
132 *then proceed to find another element that owns the segment. If we don't find it, we know
133 *we are dealing with a boundary or hole, otherwise, we are dealing with a rift: */
134 element_nodes[0]=*(index+3*el+0);
135 element_nodes[1]=*(index+3*el+1);
136 element_nodes[2]=*(index+3*el+2);
137
138 index[3*el+0]=-1;
139 index[3*el+1]=-1;
140 index[3*el+2]=-1;
141
142 el2=FindElement(*(segments+3*i+0),*(segments+3*i+1),index,nel);
143
144 /*Restore index: */
145 index[3*el+0]=element_nodes[0];
146 index[3*el+1]=element_nodes[1];
147 index[3*el+2]=element_nodes[2];
148
149 if (el2!=-1){
150 /*el and el2 are on a segment rift, facing one another, plug them into riftsegments_uncompressed: */
151 riftsegments_uncompressed[5*i+0]=1;
152 riftsegments_uncompressed[5*i+1]=el;
153 riftsegments_uncompressed[5*i+2]=el2;
154 riftsegments_uncompressed[5*i+3]=segments[3*i+0];
155 riftsegments_uncompressed[5*i+4]=segments[3*i+1];
156 nriftsegs++;
157 }
158 }
159
160 /*Compress riftsegments_uncompressed:*/
161 riftsegments=xNew<int>(nriftsegs*4);
162 counter=0;
163 for (i=0;i<nsegs;i++){
164 if (riftsegments_uncompressed[5*i+0]){
165 riftsegments[counter*4+0]=riftsegments_uncompressed[5*i+1];
166 riftsegments[counter*4+1]=riftsegments_uncompressed[5*i+2];
167 riftsegments[counter*4+2]=riftsegments_uncompressed[5*i+3];
168 riftsegments[counter*4+3]=riftsegments_uncompressed[5*i+4];
169 counter++;
170 }
171 }
172 xDelete<int>(riftsegments_uncompressed);
173
174 /*Assign output pointers: */
175 *priftsegments=riftsegments;
176 *pnriftsegs=nriftsegs;
177}/*}}}*/
178int DetermineGridElementListOnOneSideOfRift(int* pNumGridElementListOnOneSideOfRift, int** pGridElementListOnOneSideOfRift, int segmentnumber, int nriftsegs, int* riftsegments, int node,int* index,int nel){/*{{{*/
179
180 int noerr=1;
181 int k,l,counter;
182 int newel;
183
184 int* GridElements=NULL;
185 int NumGridElements;
186
187 /*Output: */
188 int NumGridElementListOnOneSideOfRift;
189 int* GridElementListOnOneSideOfRift=NULL;
190
191 /*Build a list of all the elements connected to this node: */
192 GridElementsList(&GridElements,&NumGridElements,node,index,nel);
193
194 /*Figure out the list of elements that are on the same side of the rift. To do so, we start from one
195 * side of the rift and keep rotating in the same direction:*/
196 GridElementListOnOneSideOfRift=xNew<int>(NumGridElements);
197 //bootstrap the GridElementListOnOneSideOfRift by filling elements from riftsegments: */
198 GridElementListOnOneSideOfRift[0]=*(riftsegments+4*segmentnumber+0); /*this one does not belong to the same side, but is just there
199 for a rotation direction, we 'll take it out when we are
200 done rotating*/
201 GridElementListOnOneSideOfRift[1]=*(riftsegments+4*segmentnumber+1);
202 counter=1;
203 for (;;){
204 /*Find neighbour of element GridElementListOnOneSideOfRift[counter], not
205 * equal to GridElementListOnOneSideOfRift[counter-1]*/
206 for (k=0;k<NumGridElements;k++){
207 if(IsNeighbor(GridElements[k],GridElementListOnOneSideOfRift[counter],index)){
208 /*Verify this element is not already in our list of element on the same side of the rift: */
209 newel=1;
210 for (l=0;l<=counter;l++){
211 if (GridElements[k]==GridElementListOnOneSideOfRift[l]){
212 newel=0;
213 break;
214 }
215 }
216 if (newel){
217 counter++;
218 GridElementListOnOneSideOfRift[counter]=GridElements[k];
219 if (IsOnRift(GridElements[k],nriftsegs,riftsegments)){
220 break;
221 }
222 k=-1;
223 }
224 }
225 }
226 /*Reduce counter by 1 and get rift of first element in GridElementListOnOneSideOfRift:*/
227 NumGridElementListOnOneSideOfRift=counter;
228 for (l=0;l<NumGridElementListOnOneSideOfRift;l++){
229 GridElementListOnOneSideOfRift[l]=GridElementListOnOneSideOfRift[l+1];
230 }
231 break;
232 }// for (;;)
233
234 /*Free resources: */
235 xDelete<int>(GridElements);
236 /*Assign output pointers: */
237 *pNumGridElementListOnOneSideOfRift=NumGridElementListOnOneSideOfRift;
238 *pGridElementListOnOneSideOfRift=GridElementListOnOneSideOfRift;
239 return noerr;
240}/*}}}*/
241int UpdateSegments(int** psegments,int** psegmentmarkerlist, int* pnsegs,int* index, double* x,double* y,int* riftsegments,int nriftsegs,int nods,int nel){/*{{{*/
242
243 int noerr=1;
244 int i,j,k;
245 int el1,el2;
246
247 int *segments = NULL;
248 int *segmentmarkerlist = NULL;
249 int nsegs;
250
251 /*Recover input: */
252 segments = *psegments;
253 segmentmarkerlist = *psegmentmarkerlist;
254 nsegs = *pnsegs;
255
256 /*Reallocate segments: */
257 segments =xReNew<int>(segments, nsegs*3,(nsegs+nriftsegs)*3);
258 segmentmarkerlist=xReNew<int>(segmentmarkerlist,nsegs,(nsegs+nriftsegs));
259
260 /*First, update the existing segments to the new nodes :*/
261 for (i=0;i<nriftsegs;i++){
262 el1=riftsegments[4*i+0];
263 el2=riftsegments[4*i+1];
264 for (j=0;j<nsegs;j++){
265 if (segments[3*j+2]==(el1+1)){
266 /*segment j is the same as rift segment i.Let's update segments[j][:] using element el1 and the corresponding rift segment.
267 *Because riftsegments does not represent a list of rift segments anymore (it got heavily modified in SplitElementsForRifts,
268 *we can only rely on the position (x,y) of the rift nodes to create a segment:*/
269 for (k=0;k<3;k++){
270 if ((x[*(index+el1*3+k)-1]==x[*(segments+3*j+0)-1]) && (y[*(index+el1*3+k)-1]==y[*(segments+3*j+0)-1])){
271 *(segments+3*j+0)=*(index+el1*3+k); _assert_(segments[3*j+0]<nods+1);
272 break;
273 }
274 }
275 for (k=0;k<3;k++){
276 if ((x[*(index+el1*3+k)-1]==x[*(segments+3*j+1)-1]) && (y[*(index+el1*3+k)-1]==y[*(segments+3*j+1)-1])){
277 *(segments+3*j+1)=*(index+el1*3+k); _assert_(segments[3*j+1]<nods+1);
278 break;
279 }
280 }
281 /*Deal with el2: */
282 *(segments+3*(nsegs+i)+2)=el2+1;
283 *(segmentmarkerlist+(nsegs+i))=*(segmentmarkerlist+j);
284 for (k=0;k<3;k++){
285 if ((x[*(index+el2*3+k)-1]==x[*(segments+3*j+0)-1]) && (y[*(index+el2*3+k)-1]==y[*(segments+3*j+0)-1])){
286 *(segments+3*(nsegs+i)+0)=*(index+el2*3+k); _assert_(segments[3*(nsegs+i)+0]<nods+1);
287 break;
288 }
289 }
290 for (k=0;k<3;k++){
291 if ((x[*(index+el2*3+k)-1]==x[*(segments+3*j+1)-1]) && (y[*(index+el2*3+k)-1]==y[*(segments+3*j+1)-1])){
292 *(segments+3*(nsegs+i)+1)=*(index+el2*3+k); _assert_(segments[3*(nsegs+i)+1]<nods+1);
293 break;
294 }
295 }
296 }
297 if (*(segments+3*j+2)==(el2+1)){
298 /*segment j is the same as rift segment i.*/
299 /*Let's update segments[j][:] using element el2 and the corresponding rift segment: */
300 for (k=0;k<3;k++){
301 if ((x[*(index+el2*3+k)-1]==x[*(segments+3*j+0)-1]) && (y[*(index+el2*3+k)-1]==y[*(segments+3*j+0)-1])){
302 *(segments+3*j+0)=*(index+el2*3+k); _assert_(segments[3*j+0]<nods+1);
303 break;
304 }
305 }
306 for (k=0;k<3;k++){
307 if ((x[*(index+el2*3+k)-1]==x[*(segments+3*j+1)-1]) && (y[*(index+el2*3+k)-1]==y[*(segments+3*j+1)-1])){
308 *(segments+3*j+1)=*(index+el2*3+k);_assert_(segments[3*j+1]<nods+1);
309 break;
310 }
311 }
312 /*Deal with el1: */
313 *(segments+3*(nsegs+i)+2)=el1+1;
314 *(segmentmarkerlist+(nsegs+i))=*(segmentmarkerlist+j);
315 for (k=0;k<3;k++){
316 if ((x[*(index+el1*3+k)-1]==x[*(segments+3*j+0)-1]) && (y[*(index+el1*3+k)-1]==y[*(segments+3*j+0)-1])){
317 *(segments+3*(nsegs+i)+0)=*(index+el1*3+k);_assert_(segments[3*(nsegs+i)+0]<nods+1);
318 break;
319 }
320 }
321 for (k=0;k<3;k++){
322 if ((x[*(index+el1*3+k)-1]==x[*(segments+3*j+1)-1]) && (y[*(index+el1*3+k)-1]==y[*(segments+3*j+1)-1])){
323 *(segments+3*(nsegs+i)+1)=*(index+el1*3+k);_assert_(segments[3*(nsegs+i)+1]<nods+1);
324 break;
325 }
326 }
327 }
328 }
329 }
330 nsegs+=nriftsegs;
331
332 /*Assign output pointers: */
333 *psegments=segments;
334 *psegmentmarkerlist=segmentmarkerlist;
335 *pnsegs=nsegs;
336
337 return noerr;
338}/*}}}*/
339int FindElement(int A,int B,int* index,int nel){/*{{{*/
340
341 int el=-1;
342 for (int n=0;n<nel;n++){
343 if(((index[3*n+0]==A) || (index[3*n+1]==A) || (index[3*n+2]==A)) && ((index[3*n+0]==B) || (index[3*n+1]==B) || (index[3*n+2]==B))){
344 el=n;
345 break;
346 }
347 }
348 return el;
349}/*}}}*/
350int SplitRiftSegments(int** psegments,int** psegmentmarkerlist, int* pnumsegs, int* pnumrifts,int** priftsnumsegs,int*** priftssegments,int numrifts,int nods,int nel){/*{{{*/
351
352 /*Using segment markers, wring out the rift segments from the segments. Rift markers are
353 *of the form 2+i where i=0 to number of rifts */
354
355 int noerr=1;
356 int i,j,counter;
357
358 /*input: */
359 int *segments = NULL;
360 int *segmentmarkerlist = NULL;
361 int numsegs;
362
363 /*output: */
364 int new_numsegs;
365 int *riftsnumsegs = NULL;
366 int **riftssegments = NULL;
367 int *new_segments = NULL;
368 int *new_segmentmarkers = NULL;
369
370 /*intermediary: */
371 int* riftsegment=NULL;
372
373 /*Recover input arguments: */
374 segments = *psegments;
375 numsegs = *pnumsegs;
376 segmentmarkerlist = *psegmentmarkerlist;
377
378 /*First, figure out how many segments will be left in 'segments': */
379 counter=0;
380 for (i=0;i<numsegs;i++){
381 if (segmentmarkerlist[i]==1)counter++; //1 is default marker for non-rifts;
382 }
383 /*Allocate new segments: */
384 new_numsegs=counter;
385 new_segments=xNew<int>(new_numsegs*3);
386 new_segmentmarkers=xNew<int>(new_numsegs);
387
388 /*Copy new segments info : */
389 counter=0;
390 for (i=0;i<numsegs;i++){
391 if (segmentmarkerlist[i]==1){
392 new_segments[3*counter+0]=segments[3*i+0];
393 new_segments[3*counter+1]=segments[3*i+1];
394 new_segments[3*counter+2]=segments[3*i+2];
395 new_segmentmarkers[counter]=segmentmarkerlist[i];
396 counter++;
397 }
398 }
399
400 /*Now deal with rift segments: */
401 riftsnumsegs=xNew<int>(numrifts);
402 riftssegments=xNew<int*>(numrifts);
403 for (i=0;i<numrifts;i++){
404 /*Figure out how many segments for rift i: */
405 counter=0;
406 for (j=0;j<numsegs;j++){
407 if (segmentmarkerlist[j]==2+i)counter++;
408 }
409 riftsnumsegs[i]=counter;
410 riftsegment=xNew<int>(counter*3);
411 /*Copy new segments info :*/
412 counter=0;
413 for (j=0;j<numsegs;j++){
414 if (segmentmarkerlist[j]==(2+i)){
415 riftsegment[3*counter+0]=segments[3*j+0];_assert_(riftsegment[3*counter+0]<nods+1);
416 riftsegment[3*counter+1]=segments[3*j+1];_assert_(riftsegment[3*counter+1]<nods+1);
417 riftsegment[3*counter+2]=segments[3*j+2];_assert_(riftsegment[3*counter+2]<nel+1);
418 counter++;
419 }
420 }
421 *(riftssegments+i)=riftsegment;
422 }
423
424 /*Free resources: */
425 xDelete<int>(segments);
426
427 /*Assign output pointers: */
428 *psegments=new_segments;
429 *psegmentmarkerlist=new_segmentmarkers;
430 *pnumsegs=new_numsegs;
431 *pnumrifts=numrifts;
432 *priftssegments=riftssegments;
433 *priftsnumsegs=riftsnumsegs;
434 return noerr;
435}/*}}}*/
436int PairRiftElements(int** priftsnumpairs,int*** priftspairs,int numrifts,int* riftsnumsegments,int** riftssegments,double* x,double* y){/*{{{*/
437
438 int noerr=1;
439 int i,j,k;
440
441 /*output: */
442 int *riftsnumpairs = NULL;
443 int **riftspairs = NULL;
444
445 /*intermediary :*/
446 int numsegs;
447 int* segments=NULL;
448 int* pairs=NULL;
449 int node1,node2,node3,node4;
450
451 riftsnumpairs=xNew<int>(numrifts);
452 riftspairs=xNew<int*>(numrifts);
453 for (i=0;i<numrifts;i++){
454 segments=riftssegments[i];
455 numsegs =riftsnumsegments[i];
456 riftsnumpairs[i]=numsegs;
457 pairs=xNew<int>(2*numsegs);
458 for (j=0;j<numsegs;j++){
459 pairs[2*j+0]=segments[3*j+2]; //retrieve element to which this segment belongs.
460 node1=segments[3*j+0]-1; node2=segments[3*j+1]-1;
461 /*Find element facing on other side of rift: */
462 for (k=0;k<numsegs;k++){
463 if (k==j)continue;
464 node3=segments[3*k+0]-1; node4=segments[3*k+1]-1;
465 /*We are trying to find 2 elements, where position of node3 == position of node1, and position of node4 == position of node2*/
466 if ( ((x[node3]==x[node1]) && (y[node3]==y[node1]) && (x[node4]==x[node2]) && (y[node4]==y[node2]))
467 || ((x[node3]==x[node2]) && (y[node3]==y[node2]) && (x[node4]==x[node1]) && (y[node4]==y[node1])) ){
468 /*We found the corresponding element: */
469 pairs[2*j+1]=segments[3*k+2];
470 break;
471 }
472 }
473 }
474 riftspairs[i]=pairs;
475 }
476
477 /*Assign output pointers: */
478 *priftsnumpairs=riftsnumpairs;
479 *priftspairs=riftspairs;
480 return noerr;
481}/*}}}*/
482int IsRiftPresent(int* priftflag,int* pnumrifts,int* segmentmarkerlist,int nsegs){/*{{{*/
483
484 int i;
485 int noerr=1;
486
487 /*output: */
488 int riftflag=0;
489 int numrifts=0;
490
491 int maxmark=1; //default marker for regular segments
492
493 /*Any marker >=2 indicates a certain rift: */
494 numrifts=0;
495 for (i=0;i<nsegs;i++){
496 if (segmentmarkerlist[i]>maxmark){
497 numrifts++;
498 maxmark=segmentmarkerlist[i];
499 }
500 }
501 if(numrifts)riftflag=1;
502
503 /*Assign output pointers:*/
504 *priftflag=riftflag;
505 *pnumrifts=numrifts;
506 return noerr;
507}/*}}}*/
508int OrderRifts(int** priftstips,int** riftssegments,int** riftspairs,int numrifts,int* riftsnumsegments,double* x,double* y,int nods,int nels){/*{{{*/
509
510 int noerr=1;
511 int i,j,k,counter;
512
513 /*intermediary: */
514 int *riftsegments = NULL;
515 int *riftpairs = NULL;
516 int numsegs;
517
518 /*ordering and copy: */
519 int *order = NULL;
520 int *riftsegments_copy = NULL;
521 int *riftpairs_copy = NULL;
522
523 /*node and element manipulation: */
524 int node1,node2,node3,node4,temp_node,tip1,tip2,node;
525 int el2;
526 int already_ordered=0;
527
528 /*output: */
529 int* riftstips=NULL;
530
531 /*Allocate byproduct of this routine, riftstips: */
532 riftstips=xNew<int>(numrifts*2);
533
534 /*Go through all rifts: */
535 for (i=0;i<numrifts;i++){
536 riftsegments = riftssegments[i];
537 riftpairs = riftspairs[i];
538 numsegs = riftsnumsegments[i];
539
540 /*Allocate copy of riftsegments and riftpairs,
541 *as well as ordering vector: */
542 riftsegments_copy=xNew<int>(numsegs*3);
543 riftpairs_copy=xNew<int>(numsegs*2);
544 order=xNew<int>(numsegs);
545
546 /*First find the tips, using the pairs. If a pair of elements has one node in common, this node is a rift tip: */
547 tip1=-1;
548 tip2=-1;
549
550 for (j=0;j<numsegs;j++){
551 el2=*(riftpairs+2*j+1);
552 node1=*(riftsegments+3*j+0);
553 node2=*(riftsegments+3*j+1);
554 /*Summary, el1 and el2 are facing one another across the rift. node1 and node2 belong to el1 and
555 *are located on the rift. Find node3 and node4, nodes belonging to el2 and located on the rift: */
556 for (k=0;k<numsegs;k++){
557 if (*(riftsegments+3*k+2)==el2){
558 node3=*(riftsegments+3*k+0);
559 node4=*(riftsegments+3*k+1);
560 break;
561 }
562 }
563 /* Make sure node3 faces node1 and node4 faces node2: */
564 _assert_(node1<nods+1 && node4<nods+1);
565 _assert_(node1>0 && node4>0);
566 if ((x[node1-1]==x[node4-1]) && (y[node1-1]==y[node4-1])){
567 /*Swap node3 and node4:*/
568 temp_node=node3;
569 node3=node4;
570 node4=temp_node;
571 }
572
573 /*Figure out if a tip is on this element: */
574 if (node3==node1){
575 /*node1 is a tip*/
576 if (tip1==-1) {
577 tip1=node1;
578 continue;
579 }
580 if ((tip2==-1) && (node1!=tip1)){
581 tip2=node1;
582 break;
583 }
584 }
585
586 if (node4==node2){
587 /*node2 is a tip*/
588 if (tip1==-1){
589 tip1=node2;
590 continue;
591 }
592 if ((tip2==-1) && (node2!=tip1)){
593 tip2=node2;
594 break;
595 }
596 }
597 }
598
599 /*Record tips in riftstips: */
600 *(riftstips+2*i+0)=tip1;
601 *(riftstips+2*i+1)=tip2;
602
603 /*We have the two tips for this rift. Go from tip1 to tip2, and figure out the order in which segments are sequential.
604 *Because two elements are connected to tip1, we chose one first, which defines the direction we are rotating along the rift. */
605 node=tip1;
606 for (counter=0;counter<numsegs;counter++){
607 for (j=0;j<numsegs;j++){
608 node1=*(riftsegments+3*j+0);
609 node2=*(riftsegments+3*j+1);
610
611 if ((node1==node) || (node2==node)){
612 /*Ok, this segment is connected to node, plug its index into order, unless we already plugged it before: */
613 already_ordered=0;
614 for (k=0;k<counter;k++){
615 if(order[k]==j){
616 already_ordered=1;
617 break;
618 }
619 }
620 if (!already_ordered){
621 order[counter]=j;
622 if(node1==node){
623 node=node2;
624 }
625 else if(node2==node){
626 node=node1;
627 }
628 break;
629 }
630 }
631 }
632 }
633
634 /*Using the order vector, and the riftsegments_copy and riftspairs_copy, reorder the segments and the pairs: */
635 for (j=0;j<numsegs;j++){
636 _assert_(order[j]<numsegs);
637 *(riftsegments_copy+3*j+0)=*(riftsegments+3*order[j]+0);
638 *(riftsegments_copy+3*j+1)=*(riftsegments+3*order[j]+1);
639 *(riftsegments_copy+3*j+2)=*(riftsegments+3*order[j]+2);
640 *(riftpairs_copy+2*j+0)=*(riftpairs+2*order[j]+0);
641 *(riftpairs_copy+2*j+1)=*(riftpairs+2*order[j]+1);
642 }
643
644 for (j=0;j<numsegs;j++){
645 *(riftsegments+3*j+0)=*(riftsegments_copy+3*j+0);
646 *(riftsegments+3*j+1)=*(riftsegments_copy+3*j+1);
647 *(riftsegments+3*j+2)=*(riftsegments_copy+3*j+2);
648 *(riftpairs+2*j+0)=*(riftpairs_copy+2*j+0);
649 *(riftpairs+2*j+1)=*(riftpairs_copy+2*j+1);
650 }
651
652 xDelete<int>(order);
653 xDelete<int>(riftsegments_copy);
654 xDelete<int>(riftpairs_copy);
655
656 }
657
658 /*Assign output pointer:*/
659 *priftstips=riftstips;
660 return noerr;
661}/*}}}*/
662int PenaltyPairs(double*** priftspenaltypairs,int** priftsnumpenaltypairs,int numrifts,int** riftssegments,/*{{{*/
663 int* riftsnumsegs,int** riftspairs,int* riftstips,double* x,double* y){
664
665 int noerr=1;
666 int i,j,k,k0;
667
668 double el1,el2,node1,node2,node3,node4;
669 double temp_node;
670
671 /*output: */
672 double **riftspenaltypairs = NULL;
673 double *riftpenaltypairs = NULL;
674 int *riftsnumpenaltypairs = NULL;
675
676 /*intermediary: */
677 int numsegs;
678 int* riftsegments=NULL;
679 int* riftpairs=NULL;
680 int counter;
681 double normal[2];
682 double length;
683 int k1,k2;
684
685 /*Allocate: */
686 riftspenaltypairs=xNew<double*>(numrifts);
687 riftsnumpenaltypairs=xNew<int>(numrifts);
688
689 for(i=0;i<numrifts;i++){
690 numsegs=riftsnumsegs[i];
691 riftsegments=riftssegments[i];
692 riftpairs=riftspairs[i];
693
694 /*allocate riftpenaltypairs, and riftnumpenaltypairs: */
695 if((numsegs/2-1)!=0)riftpenaltypairs=xNewZeroInit<double>((numsegs/2-1)*RIFTPENALTYPAIRSWIDTH);
696
697 /*Go through only one flank of the rifts, not counting the tips: */
698 counter=0;
699 for(j=0;j<(numsegs/2);j++){
700 el1=*(riftpairs+2*j+0);
701 el2=*(riftpairs+2*j+1);
702 node1=*(riftsegments+3*j+0);
703 node2=*(riftsegments+3*j+1);
704 /*Find segment index to recover node3 and node4, facing node1 and node2: */
705 k0=-1;
706 for(k=0;k<numsegs;k++){
707 if(*(riftsegments+3*k+2)==el2){
708 k0=k;
709 break;
710 }
711 }
712 node3=*(riftsegments+3*k0+0);
713 node4=*(riftsegments+3*k0+1);
714
715 /* Make sure node3 faces node1 and node4 faces node2: */
716 if ((x[(int)node1-1]==x[(int)node4-1]) && (y[(int)node1-1]==y[(int)node4-1])){
717 /*Swap node3 and node4:*/
718 temp_node=node3;
719 node3=node4;
720 node4=temp_node;
721 }
722 /*Ok, we have node1 facing node3, and node2 facing node4. Compute the normal to
723 *this segment, and its length: */
724 normal[0]=cos(atan2(x[(int)node1-1]-x[(int)node2-1],y[(int)node2-1]-y[(int)node1-1]));
725 normal[1]=sin(atan2(x[(int)node1-1]-x[(int)node2-1],y[(int)node2-1]-y[(int)node1-1]));
726 length=sqrt(pow(x[(int)node2-1]-x[(int)node1-1],(double)2)+pow(y[(int)node2-1]-y[(int)node1-1],(double)2));
727
728 /*Be careful here, we want penalty loads on each node, not on each segment. This means we cannot plug node1,
729 * node2, node3 and node4 directly into riftpenaltypairs. We need to include node1, node2, node3 and node4,
730 * only once. We'll add the normals and the lengths : */
731
732 if(node1!=node3){ //exclude tips from loads
733 k1=-1;
734 for(k=0;k<counter;k++){
735 if( (*(riftpenaltypairs+k*7+0))==node1){
736 k1=k;
737 break;
738 }
739 }
740 if(k1==-1){
741 *(riftpenaltypairs+counter*7+0)=node1;
742 *(riftpenaltypairs+counter*7+1)=node3;
743 *(riftpenaltypairs+counter*7+2)=el1;
744 *(riftpenaltypairs+counter*7+3)=el2;
745 *(riftpenaltypairs+counter*7+4)=normal[0];
746 *(riftpenaltypairs+counter*7+5)=normal[1];
747 *(riftpenaltypairs+counter*7+6)=length/2;
748 counter++;
749 }
750 else{
751 *(riftpenaltypairs+k1*7+4)+=normal[0];
752 *(riftpenaltypairs+k1*7+5)+=normal[1];
753 *(riftpenaltypairs+k1*7+6)+=length/2;
754 }
755 }
756 if(node2!=node4){
757 k2=-1;
758 for(k=0;k<counter;k++){
759 if( (*(riftpenaltypairs+k*7+0))==node2){
760 k2=k;
761 break;
762 }
763 }
764 if(k2==-1){
765 *(riftpenaltypairs+counter*7+0)=node2;
766 *(riftpenaltypairs+counter*7+1)=node4;
767 *(riftpenaltypairs+counter*7+2)=el1;
768 *(riftpenaltypairs+counter*7+3)=el2;
769 *(riftpenaltypairs+counter*7+4)=normal[0];
770 *(riftpenaltypairs+counter*7+5)=normal[1];
771 *(riftpenaltypairs+counter*7+6)=length/2;
772 counter++;
773 }
774 else{
775 *(riftpenaltypairs+k2*7+4)+=normal[0];
776 *(riftpenaltypairs+k2*7+5)+=normal[1];
777 *(riftpenaltypairs+k2*7+6)+=length/2;
778 }
779 }
780 }
781 /*Renormalize normals: */
782 for(j=0;j<counter;j++){
783 double magnitude=sqrt(pow( double(riftpenaltypairs[j*7+4]),2) + pow( double(riftpenaltypairs[j*7+5]),2) );
784 *(riftpenaltypairs+j*7+4)=*(riftpenaltypairs+j*7+4)/magnitude;
785 *(riftpenaltypairs+j*7+5)=*(riftpenaltypairs+j*7+5)/magnitude;
786 }
787
788 riftspenaltypairs[i]=riftpenaltypairs;
789 riftsnumpenaltypairs[i]=(numsegs/2-1);
790 }
791
792 /*Assign output pointers: */
793 *priftspenaltypairs=riftspenaltypairs;
794 *priftsnumpenaltypairs=riftsnumpenaltypairs;
795 return noerr;
796}/*}}}*/
797int RemoveCornersFromRifts(int** pindex,int* pnel,double** px,double** py,int* pnods,int* segments,int* segmentmarkers,int num_seg){/*{{{*/
798
799 int noerr=1;
800 int i,j,k;
801 int node1,node2,node3;
802 int el;
803 double pair[2];
804 int pair_count=0;
805 int triple=0;
806
807 /*Recover input: */
808 int *index = *pindex;
809 int nel = *pnel;
810 double *x = *px;
811 double *y = *py;
812 int nods = *pnods;
813
814 for (i=0;i<num_seg;i++){
815 node1=*(segments+3*i+0);
816 node2=*(segments+3*i+1);
817 /*Find all elements connected to [node1 node2]: */
818 pair_count=0;
819 for (j=0;j<nel;j++){
820 if (*(index+3*j+0)==node1){
821 if ((*(index+3*j+1)==node2) || (*(index+3*j+2)==node2)){
822 pair[pair_count]=j;
823 pair_count++;
824 }
825 }
826 if (*(index+3*j+1)==node1){
827 if ((*(index+3*j+0)==node2) || (*(index+3*j+2)==node2)){
828 pair[pair_count]=j;
829 pair_count++;
830 }
831 }
832 if (*(index+3*j+2)==node1){
833 if ((*(index+3*j+0)==node2) || (*(index+3*j+1)==node2)){
834 pair[pair_count]=j;
835 pair_count++;
836 }
837 }
838 }
839 /*Ok, we have pair_count elements connected to this segment. For each of these elements,
840 *figure out if the third node also belongs to a segment: */
841 if ((pair_count==0) || (pair_count==1)){ //we only select the rift segments, which belong to 2 elements
842 continue;
843 }
844 else{
845 for (j=0;j<pair_count;j++){
846 el=(int)pair[j];
847 triple=0;
848 /*First find node3: */
849 if (*(index+3*el+0)==node1){
850 if (*(index+3*el+1)==node2)node3=*(index+3*el+2);
851 else node3=*(index+3*el+1);
852 }
853 if (*(index+3*el+1)==node1){
854 if (*(index+3*el+0)==node2)node3=*(index+3*el+2);
855 else node3=*(index+3*el+0);
856 }
857 if (*(index+3*el+2)==node1){
858 if (*(index+3*el+0)==node2)node3=*(index+3*el+1);
859 else node3=*(index+3*el+0);
860 }
861 /*Ok, we have node3. Does node3 belong to a segment? : */
862 for (k=0;k<num_seg;k++){
863 if ((node3==*(segments+3*k+0)) || (node3==*(segments+3*k+1))){
864 triple=1;
865 break;
866 }
867 }
868 if(triple==1){
869 /*el is a corner element: we need to split it in 3 triangles: */
870 x=xReNew<double>(x,nods,nods+1);
871 y=xReNew<double>(y,nods,nods+1);
872 x[nods]=(x[(int)node1-1]+x[(int)node2-1]+x[(int)node3-1])/3;
873 y[nods]=(y[(int)node1-1]+y[(int)node2-1]+y[(int)node3-1])/3;
874 index=xReNew<int>(index,nel*3,(nel+2*3));
875 /*First, reassign element el: */
876 *(index+3*el+0)=node1;
877 *(index+3*el+1)=node2;
878 *(index+3*el+2)=nods+1;
879 /*Other two elements: */
880 *(index+3*nel+0)=node2;
881 *(index+3*nel+1)=node3;
882 *(index+3*nel+2)=nods+1;
883
884 *(index+3*(nel+1)+0)=node3;
885 *(index+3*(nel+1)+1)=node1;
886 *(index+3*(nel+1)+2)=nods+1;
887 /*we need to change the segment elements corresponding to el: */
888 for (k=0;k<num_seg;k++){
889 if (*(segments+3*k+2)==(el+1)){
890 if ( ((*(segments+3*k+0)==node1) && (*(segments+3*k+1)==node2)) || ((*(segments+3*k+0)==node2) && (*(segments+3*k+1)==node1))) *(segments+3*k+2)=el+1;
891 if ( ((*(segments+3*k+0)==node2) && (*(segments+3*k+1)==node3)) || ((*(segments+3*k+0)==node3) && (*(segments+3*k+1)==node2))) *(segments+3*k+2)=nel+1;
892 if ( ((*(segments+3*k+0)==node3) && (*(segments+3*k+1)==node1)) || ((*(segments+3*k+0)==node1) && (*(segments+3*k+1)==node3))) *(segments+3*k+2)=nel+2;
893 }
894 }
895
896 nods=nods+1;
897 nel=nel+2;
898 i=0;
899 break;
900 }
901 } //for (j=0;j<pair_count;j++)
902 }
903 }// for (i=0;i<num_seg;i++)
904
905 /*Assign output pointers: */
906 *pindex=index;
907 *pnel=nel;
908 *px=x;
909 *py=y;
910 *pnods=nods;
911 return noerr;
912}/*}}}*/
Note: See TracBrowser for help on using the repository browser.