1 /* ----------------------------------------------------------------------
2 SPARTA - Stochastic PArallel Rarefied-gas Time-accurate Analyzer
3 http://sparta.sandia.gov
4 Steve Plimpton, sjplimp@sandia.gov, Michael Gallis, magalli@sandia.gov
5 Sandia National Laboratories
6
7 Copyright (2014) Sandia Corporation. Under the terms of Contract
8 DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
9 certain rights in this software. This software is distributed under
10 the GNU General Public License.
11
12 See the README file in the top-level SPARTA directory.
13 ------------------------------------------------------------------------- */
14
15 #include "stdio.h"
16 #include "string.h"
17 #include "move_surf.h"
18 #include "surf.h"
19 #include "grid.h"
20 #include "comm.h"
21 #include "update.h"
22 #include "domain.h"
23 #include "input.h"
24 #include "math_extra.h"
25 #include "math_const.h"
26 #include "memory.h"
27 #include "error.h"
28
29 using namespace SPARTA_NS;
30 using namespace MathExtra;
31 using namespace MathConst;
32
33 enum{READFILE,TRANSLATE,ROTATE};
34 enum{UNKNOWN,OUTSIDE,INSIDE,OVERLAP}; // several files
35
36 #define MAXLINE 256
37
38 /* ---------------------------------------------------------------------- */
39
MoveSurf(SPARTA * sparta)40 MoveSurf::MoveSurf(SPARTA *sparta) : Pointers(sparta)
41 {
42 me = comm->me;
43 nprocs = comm->nprocs;
44
45 // pselect = 1 if point is moved, else 0
46
47 if (domain->dimension == 2)
48 memory->create(pselect,2*surf->nsurf,"move_surf:pselect");
49 else
50 memory->create(pselect,3*surf->nsurf,"move_surf:pselect");
51
52 file = NULL;
53 fp = NULL;
54 }
55
56 /* ---------------------------------------------------------------------- */
57
~MoveSurf()58 MoveSurf::~MoveSurf()
59 {
60 memory->destroy(pselect);
61 delete [] file;
62 if (fp) fclose(fp);
63 }
64
65 /* ---------------------------------------------------------------------- */
66
command(int narg,char ** arg)67 void MoveSurf::command(int narg, char **arg)
68 {
69 if (!surf->exist)
70 error->all(FLERR,"Cannot move_surf with no surf elements defined");
71
72 if (surf->distributed)
73 error->all(FLERR,
74 "Cannot yet use move_surf with distributed surf elements");
75
76 if (narg < 2) error->all(FLERR,"Illegal move_surf command");
77
78 // process command-line args
79
80 int igroup = surf->find_group(arg[0]);
81 if (igroup < 0) error->all(FLERR,"Move_surf group ID does not exist");
82 groupbit = surf->bitmask[igroup];
83
84 process_args(narg-1,&arg[1]);
85 mode = 0;
86
87 if (action == READFILE)
88 error->all(FLERR,"Move_surf file option is not yet implemented");
89
90 // perform surface move
91
92 if (me == 0) {
93 if (screen) fprintf(screen,"Moving surfs ...\n");
94 if (logfile) fprintf(logfile,"Moving surfs ...\n");
95 }
96
97 MPI_Barrier(world);
98 double time1 = MPI_Wtime();
99
100 dim = domain->dimension;
101
102 // sort particles
103
104 if (particle->exist) particle->sort();
105
106 MPI_Barrier(world);
107 double time2 = MPI_Wtime();
108
109 // move line/tri points via chosen action by full amount
110
111 if (dim == 2) move_lines(1.0,surf->lines);
112 else move_tris(1.0,surf->tris);
113
114 // remake list of surf elements I own
115 // assign split cell particles to parent split cell
116 // assign surfs to grid cells
117
118 grid->unset_neighbors();
119 grid->remove_ghosts();
120
121 if (particle->exist && grid->nsplitlocal) {
122 Grid::ChildCell *cells = grid->cells;
123 int nglocal = grid->nlocal;
124 for (int icell = 0; icell < nglocal; icell++)
125 if (cells[icell].nsplit > 1)
126 grid->combine_split_cell_particles(icell,1);
127 }
128
129 grid->clear_surf();
130 grid->surf2grid(1);
131
132 if (dim == 2) surf->check_point_near_surf_2d();
133 else surf->check_point_near_surf_3d();
134
135 if (dim == 2) surf->check_watertight_2d();
136 else surf->check_watertight_3d();
137
138 MPI_Barrier(world);
139 double time3 = MPI_Wtime();
140
141 // re-setup owned and ghost cell info
142
143 grid->setup_owned();
144 grid->acquire_ghosts();
145 grid->reset_neighbors();
146 comm->reset_neighbors();
147
148 MPI_Barrier(world);
149 double time4 = MPI_Wtime();
150
151 // flag cells and corners as OUTSIDE or INSIDE
152 // reallocate per grid cell arrays in per grid computes
153 // local grid cell counts could have changed due to split cell changes
154
155 grid->set_inout();
156 grid->type_check();
157
158 // DEBUG
159 //grid->debug();
160
161 MPI_Barrier(world);
162 double time5 = MPI_Wtime();
163
164 // remove particles as needed due to surface move
165
166 bigint ndeleted;
167 if (particle->exist) ndeleted = remove_particles();
168
169 MPI_Barrier(world);
170 double time6 = MPI_Wtime();
171
172 double time_total = time6-time1;
173
174 if (comm->me == 0) {
175 if (screen) {
176 if (particle->exist)
177 fprintf(screen," " BIGINT_FORMAT " deleted particles\n",ndeleted);
178 fprintf(screen," CPU time = %g secs\n",time_total);
179 fprintf(screen," sort/surf2grid/ghost/inout/particle percent = "
180 "%g %g %g %g %g\n",
181 100.0*(time2-time1)/time_total,100.0*(time3-time2)/time_total,
182 100.0*(time4-time3)/time_total,100.0*(time5-time4)/time_total,
183 100.0*(time6-time5)/time_total);
184 }
185 if (logfile) {
186 if (particle->exist)
187 fprintf(logfile," " BIGINT_FORMAT " deleted particles\n",ndeleted);
188 fprintf(logfile," CPU time = %g secs\n",time_total);
189 fprintf(logfile," sort/surf2grid/ghost/inout/particle percent = "
190 "%g %g %g %g %g\n",
191 100.0*(time2-time1)/time_total,100.0*(time3-time2)/time_total,
192 100.0*(time4-time3)/time_total,100.0*(time5-time4)/time_total,
193 100.0*(time6-time5)/time_total);
194 }
195 }
196 }
197
198 /* ----------------------------------------------------------------------
199 process command args for both move_surf and fix move/surf
200 ------------------------------------------------------------------------- */
201
process_args(int narg,char ** arg)202 void MoveSurf::process_args(int narg, char **arg)
203 {
204 if (narg < 1) error->all(FLERR,"Illegal move surf command");
205
206 int iarg = 0;
207 if (strcmp(arg[0],"file") == 0) {
208 if (narg < 3) error->all(FLERR,"Illegal move surf command");
209 action = READFILE;
210 int n = strlen(arg[1]) + 1;
211 file = new char[n];
212 strcpy(file,arg[1]);
213 n = strlen(arg[2]) + 1;
214 entry = new char[n];
215 strcpy(entry,arg[2]);
216 iarg = 3;
217 } else if (strcmp(arg[0],"trans") == 0) {
218 if (narg < 4) error->all(FLERR,"Illegal move surf command");
219 action = TRANSLATE;
220 delta[0] = input->numeric(FLERR,arg[1]);
221 delta[1] = input->numeric(FLERR,arg[2]);
222 delta[2] = input->numeric(FLERR,arg[3]);
223 if (domain->dimension == 2 && delta[2] != 0.0)
224 error->all(FLERR,"Invalid move surf translation for 2d simulation");
225 iarg = 4;
226 } else if (strcmp(arg[0],"rotate") == 0) {
227 if (narg < 8) error->all(FLERR,"Illegal move surf command");
228 action = ROTATE;
229 theta = input->numeric(FLERR,arg[1]);
230 rvec[0] = input->numeric(FLERR,arg[2]);
231 rvec[1] = input->numeric(FLERR,arg[3]);
232 rvec[2] = input->numeric(FLERR,arg[4]);
233 origin[0] = input->numeric(FLERR,arg[5]);
234 origin[1] = input->numeric(FLERR,arg[6]);
235 origin[2] = input->numeric(FLERR,arg[7]);
236 if (domain->dimension == 2 && (rvec[0] != 0.0 || rvec[1] != 0.0))
237 error->all(FLERR,"Invalid move surf rotation for 2d simulation");
238 if (rvec[0] == 0.0 && rvec[1] == 0.0 && rvec[2] == 0.0)
239 error->all(FLERR,"Invalid move surf rotation");
240 theta *= MY_PI/180.0;
241 MathExtra::norm3(rvec);
242 iarg = 8;
243 } else error->all(FLERR,"Illegal move surf command");
244
245 // optional args
246
247 connectflag = 0;
248
249 while (iarg < narg) {
250 if (strcmp(arg[iarg],"connect") == 0) {
251 if (iarg+2 > narg) error->all(FLERR,"Illegal move surf command");
252 if (strcmp(arg[iarg+1],"yes") == 0) connectflag = 1;
253 else if (strcmp(arg[iarg+1],"no") == 0) connectflag = 0;
254 iarg += 2;
255 } else error->all(FLERR,"Illegal move surf command");
256 }
257 }
258
259 /* ----------------------------------------------------------------------
260 move points in lines via specified action
261 each method sets pselect = 1 for moved points
262 fraction = portion of full distance points should move
263 ------------------------------------------------------------------------- */
264
move_lines(double fraction,Surf::Line * origlines)265 void MoveSurf::move_lines(double fraction, Surf::Line *origlines)
266 {
267 if (connectflag && groupbit != 1) connect_2d_pre();
268
269 if (action == READFILE) {
270 readfile();
271 update_points(fraction);
272 }
273 else if (action == TRANSLATE) translate_2d(fraction,origlines);
274 else if (action == ROTATE) rotate_2d(fraction,origlines);
275
276 if (connectflag && groupbit != 1) connect_2d_post();
277
278 surf->compute_line_normal(0);
279
280 // check that all points are still inside simulation box
281
282 surf->check_point_inside(0);
283 }
284
285 /* ----------------------------------------------------------------------
286 move points in triangles via specified action
287 each method sets pselect = 1 for moved points
288 fraction = portion of full distance points should move
289 ------------------------------------------------------------------------- */
290
move_tris(double fraction,Surf::Tri * origtris)291 void MoveSurf::move_tris(double fraction, Surf::Tri *origtris)
292 {
293 if (connectflag && groupbit != 1) connect_3d_pre();
294
295 if (action == READFILE) {
296 readfile();
297 update_points(fraction);
298 }
299 else if (action == TRANSLATE) translate_3d(fraction,origtris);
300 else if (action == ROTATE) rotate_3d(fraction,origtris);
301
302 if (connectflag && groupbit != 1) connect_3d_post();
303
304 surf->compute_tri_normal(0);
305
306 // check that all points are still inside simulation box
307
308 surf->check_point_inside(0);
309 }
310
311 /* ----------------------------------------------------------------------
312 read entry of new point coords from file
313 ------------------------------------------------------------------------- */
314
readfile()315 void MoveSurf::readfile()
316 {
317 /*
318 int i;
319 char line[MAXLINE];
320 char *word,*eof;
321
322 // open point file if necessary
323 // if already open, will just continue scanning below
324 // NOTE: allow for file name with wildcard char
325
326 if (me == 0 && fp == NULL) {
327 fp = fopen(file,"r");
328 if (fp == NULL) {
329 char str[128];
330 sprintf(str,"Cannot open move surf file %s",file);
331 error->one(FLERR,str);
332 }
333 }
334
335 // loop until section found that matches entry
336
337 if (me == 0) {
338 while (1) {
339 if (fgets(line,MAXLINE,fp) == NULL)
340 error->one(FLERR,"Did not find entry in move surf file");
341 if (strspn(line," \t\n\r") == strlen(line)) continue; // blank line
342 if (line[0] == '#') continue; // comment
343 word = strtok(line," \t\n\r");
344 if (strcmp(word,entry) != 0) continue; // non-matching entry
345 if (fgets(line,MAXLINE,fp) == NULL)
346 error->one(FLERR,"Incompete entry in move surf file");
347 word = strtok(line," \t\n\r"); // npoints value after entry
348 nread = input->inumeric(FLERR,word);
349 }
350 }
351
352 // allocate index and coord arrays for nread points
353
354 MPI_Bcast(&nread,1,MPI_INT,0,world);
355
356 if (oldcoord) {
357 memory->destroy(readindex);
358 memory->destroy(oldcoord);
359 memory->destroy(newcoord);
360 memory->create(readindex,nread,"move_surf:readindex");
361 memory->create(oldcoord,nread,3,"move_surf:oldcoord");
362 memory->create(newcoord,nread,3,"move_surf:newcoord");
363 }
364
365 // read nread point coords in entry
366 // store old current point and new point coords so can move by fraction
367 // rindex = ID (index) of this read-in point in master list
368 // skip points that are out-of-range
369
370 Surf::Point *pts = surf->pts;
371 int npoint = surf->npoint;
372
373 if (me == 0) {
374 int id;
375 double x,y,z;
376
377 for (int i = 0; i < nread; i++) {
378 eof = fgets(line,MAXLINE,fp);
379 if (eof == NULL) error->one(FLERR,"Incomplete entry in move surf file");
380 id = input->inumeric(FLERR,strtok(line," \t\n\r"));
381 x = input->numeric(FLERR,strtok(NULL," \t\n\r"));
382 y = input->numeric(FLERR,strtok(NULL," \t\n\r"));
383 if (dim == 3) z = input->numeric(FLERR,strtok(NULL," \t\n\r"));
384 else z = 0.0;
385 if (id < 1 || id > npoint)
386 error->one(FLERR,"Invalid point index in move surf file");
387 id--;
388 readindex[i] = id;
389 oldcoord[i][0] = pts[id].x[0];
390 oldcoord[i][1] = pts[id].x[1];
391 oldcoord[i][2] = pts[id].x[2];
392 newcoord[i][0] = x;
393 newcoord[i][1] = y;
394 newcoord[i][2] = z;
395 }
396 }
397
398 // broadcast point info to all procs
399
400 MPI_Bcast(readindex,nread,MPI_INT,0,world);
401 MPI_Bcast(&oldcoord[0][0],3*nread,MPI_DOUBLE,0,world);
402 MPI_Bcast(&newcoord[0][0],3*nread,MPI_DOUBLE,0,world);
403
404 // pselect[I] = index of Ith surf point in nread points (for now)
405 // NOTE: check that same surf point does not appear twice in nread list?
406
407 for (i = 0; i < npoint; i++) pselect[i] = -1;
408 for (i = 0; i < nread; i++) pselect[readindex[i]] = i;
409
410 int *rflag;
411 memory->create(rflag,nread,"move_surf:rflag");
412 for (i =0; i < nread; i++) rflag[i] = 0;
413
414 Surf::Line *lines = surf->lines;
415 Surf::Tri *tris = surf->tris;
416 int nline = surf->nline;
417 int ntri = surf->ntri;
418 int p1,p2,p3;
419
420 if (dim == 2) {
421 for (i = 0; i < nline; i++) {
422 if (!(lines[i].mask & groupbit)) continue;
423 p1 = lines[i].p1;
424 p2 = lines[i].p2;
425 if (pselect[p1] >= 0) rflag[pselect[p1]] = 1;
426 if (pselect[p2] >= 0) rflag[pselect[p2]] = 1;
427 }
428 } else {
429 for (i = 0; i < ntri; i++) {
430 if (!(tris[i].mask & groupbit)) continue;
431 p1 = tris[i].p1;
432 p2 = tris[i].p2;
433 p3 = tris[i].p3;
434 if (pselect[p1] >= 0) rflag[pselect[p1]] = 1;
435 if (pselect[p2] >= 0) rflag[pselect[p2]] = 1;
436 if (pselect[p3] >= 0) rflag[pselect[p3]] = 1;
437 }
438 }
439
440
441 // pselect[I] = 1 if Ith surf point is moved by nread points, else 0
442
443 for (i = 0; i < npoint; i++) pselect[i] = 0;
444 for (i = 0; i < nread; i++)
445 if (rflag[i]) pselect[readindex[i]] = 1;
446
447 // clean up
448
449 memory->destroy(rflag);
450 */
451 }
452
453 /* ----------------------------------------------------------------------
454 update points using info from file
455 ------------------------------------------------------------------------- */
456
update_points(double fraction)457 void MoveSurf::update_points(double fraction)
458 {
459 /*
460 int i;
461
462 // update points by fraction of old to new move
463
464 Surf::Point *pts = surf->pts;
465 Surf::Point *p;
466
467 for (i = 0; i < nread; i++) {
468 if (pselect[readindex[i]] == 0) continue;
469 p = &pts[readindex[i]];
470 p->x[0] = oldcoord[i][0] + fraction * (newcoord[i][0]-oldcoord[i][0]);
471 p->x[1] = oldcoord[i][1] + fraction * (newcoord[i][1]-oldcoord[i][1]);
472 p->x[2] = oldcoord[i][2] + fraction * (newcoord[i][2]-oldcoord[i][2]);
473 }
474 */
475 }
476
477 /* ----------------------------------------------------------------------
478 translate surf points in 2d
479 ------------------------------------------------------------------------- */
480
translate_2d(double fraction,Surf::Line * origlines)481 void MoveSurf::translate_2d(double fraction, Surf::Line *origlines)
482 {
483 double *p1,*p2,*op1,*op2;
484
485 Surf::Line *lines = surf->lines;
486 int nsurf = surf->nsurf;
487
488 for (int i = 0; i < 2*nsurf; i++) pselect[i] = 0;
489
490 double dx = fraction * delta[0];
491 double dy = fraction * delta[1];
492
493 for (int i = 0; i < nsurf; i++) {
494 if (!(lines[i].mask & groupbit)) continue;
495 p1 = lines[i].p1;
496 p2 = lines[i].p2;
497 op1 = origlines[i].p1;
498 op2 = origlines[i].p2;
499
500 p1[0] = op1[0] + dx;
501 p1[1] = op1[1] + dy;
502 pselect[2*i] = 1;
503
504 p2[0] = op2[0] + dx;
505 p2[1] = op2[1] + dy;
506 pselect[2*i+1] = 1;
507 }
508 }
509
510 /* ----------------------------------------------------------------------
511 translate surf points in 3d
512 ------------------------------------------------------------------------- */
513
translate_3d(double fraction,Surf::Tri * origtris)514 void MoveSurf::translate_3d(double fraction, Surf::Tri *origtris)
515 {
516 double *p1,*p2,*p3,*op1,*op2,*op3;
517
518 Surf::Tri *tris = surf->tris;
519 int nsurf = surf->nsurf;
520
521 for (int i = 0; i < 3*nsurf; i++) pselect[i] = 0;
522
523 double dx = fraction * delta[0];
524 double dy = fraction * delta[1];
525 double dz = fraction * delta[2];
526
527 for (int i = 0; i < nsurf; i++) {
528 if (!(tris[i].mask & groupbit)) continue;
529 p1 = tris[i].p1;
530 p2 = tris[i].p2;
531 p3 = tris[i].p3;
532 op1 = origtris[i].p1;
533 op2 = origtris[i].p2;
534 op3 = origtris[i].p3;
535
536 p1[0] = op1[0] + dx;
537 p1[1] = op1[1] + dy;
538 p1[2] = op1[2] + dz;
539 pselect[3*i] = 1;
540
541 p2[0] = op2[0] + dx;
542 p2[1] = op2[1] + dy;
543 p2[2] = op2[2] + dz;
544 pselect[3*i+1] = 1;
545
546 p3[0] = op3[0] + dx;
547 p3[1] = op3[1] + dy;
548 p3[2] = op3[2] + dz;
549 pselect[3*i+2] = 1;
550 }
551 }
552
553 /* ----------------------------------------------------------------------
554 rotate surf points in 2d
555 ------------------------------------------------------------------------- */
556
rotate_2d(double fraction,Surf::Line * origlines)557 void MoveSurf::rotate_2d(double fraction, Surf::Line *origlines)
558 {
559 double *p1,*p2,*op1,*op2;
560 double q[4],d[3],dnew[3];
561 double rotmat[3][3];
562
563 Surf::Line *lines = surf->lines;
564 int nsurf = surf->nsurf;
565
566 for (int i = 0; i < 2*nsurf; i++) pselect[i] = 0;
567
568 double angle = fraction * theta;
569 MathExtra::axisangle_to_quat(rvec,angle,q);
570 MathExtra::quat_to_mat(q,rotmat);
571
572 for (int i = 0; i < nsurf; i++) {
573 if (!(lines[i].mask & groupbit)) continue;
574 p1 = lines[i].p1;
575 p2 = lines[i].p2;
576 op1 = origlines[i].p1;
577 op2 = origlines[i].p2;
578
579 d[0] = op1[0] - origin[0];
580 d[1] = op1[1] - origin[1];
581 d[2] = op1[2] - origin[2];
582 MathExtra::matvec(rotmat,d,dnew);
583 p1[0] = dnew[0] + origin[0];
584 p1[1] = dnew[1] + origin[1];
585 pselect[2*i] = 1;
586
587 d[0] = op2[0] - origin[0];
588 d[1] = op2[1] - origin[1];
589 d[2] = op2[2] - origin[2];
590 MathExtra::matvec(rotmat,d,dnew);
591 p2[0] = dnew[0] + origin[0];
592 p2[1] = dnew[1] + origin[1];
593 pselect[2*i+1] = 1;
594 }
595 }
596
597 /* ----------------------------------------------------------------------
598 rotate surf points in 3d
599 ------------------------------------------------------------------------- */
600
rotate_3d(double fraction,Surf::Tri * origtris)601 void MoveSurf::rotate_3d(double fraction, Surf::Tri *origtris)
602 {
603 double *p1,*p2,*p3,*op1,*op2,*op3;
604 double q[4],d[3],dnew[3];
605 double rotmat[3][3];
606
607 Surf::Tri *tris = surf->tris;
608 int nsurf = surf->nsurf;
609
610 for (int i = 0; i < 3*nsurf; i++) pselect[i] = 0;
611
612 double angle = fraction * theta;
613 MathExtra::axisangle_to_quat(rvec,angle,q);
614 MathExtra::quat_to_mat(q,rotmat);
615
616 for (int i = 0; i < nsurf; i++) {
617 if (!(tris[i].mask & groupbit)) continue;
618 p1 = tris[i].p1;
619 p2 = tris[i].p2;
620 p3 = tris[i].p3;
621 op1 = origtris[i].p1;
622 op2 = origtris[i].p2;
623 op3 = origtris[i].p3;
624
625 d[0] = op1[0] - origin[0];
626 d[1] = op1[1] - origin[1];
627 d[2] = op1[2] - origin[2];
628 MathExtra::matvec(rotmat,d,dnew);
629 p1[0] = dnew[0] + origin[0];
630 p1[1] = dnew[1] + origin[1];
631 p1[2] = dnew[2] + origin[2];
632 pselect[3*i] = 1;
633
634 d[0] = op2[0] - origin[0];
635 d[1] = op2[1] - origin[1];
636 d[2] = op2[2] - origin[2];
637 MathExtra::matvec(rotmat,d,dnew);
638 p2[0] = dnew[0] + origin[0];
639 p2[1] = dnew[1] + origin[1];
640 p2[2] = dnew[2] + origin[2];
641 pselect[3*i+1] = 1;
642
643 d[0] = op3[0] - origin[0];
644 d[1] = op3[1] - origin[1];
645 d[2] = op3[2] - origin[2];
646 MathExtra::matvec(rotmat,d,dnew);
647 p3[0] = dnew[0] + origin[0];
648 p3[1] = dnew[1] + origin[1];
649 p3[2] = dnew[2] + origin[2];
650 pselect[3*i+2] = 1;
651 }
652 }
653
654 /* ----------------------------------------------------------------------
655 add points in moved lines to hash
656 ------------------------------------------------------------------------- */
657
connect_2d_pre()658 void MoveSurf::connect_2d_pre()
659 {
660 // hash for end points of moved lines
661 // key = end point
662 // value = global index (0 to 2*Nline-1) of the point
663 // NOTE: could prealloc hash to correct size here
664
665 hash = new MyHash();
666
667 // add moved points to hash
668
669 double *p1,*p2;
670 OnePoint3d key;
671
672 Surf::Line *lines = surf->lines;
673 int nsurf = surf->nsurf;
674
675 for (int i = 0; i < nsurf; i++) {
676 if (!(lines[i].mask & groupbit)) continue;
677 p1 = lines[i].p1;
678 p2 = lines[i].p2;
679 key.pt[0] = p1[0]; key.pt[1] = p1[1]; key.pt[2] = 0.0;
680 if (hash->find(key) == hash->end()) (*hash)[key] = 2*i+0;
681 key.pt[0] = p2[0]; key.pt[1] = p2[1]; key.pt[2] = 0.0;
682 if (hash->find(key) == hash->end()) (*hash)[key] = 2*i+1;
683 }
684 }
685
686 /* ----------------------------------------------------------------------
687 move points in lines connected to line points that were moved
688 ------------------------------------------------------------------------- */
689
connect_2d_post()690 void MoveSurf::connect_2d_post()
691 {
692 // check if non-moved points are in hash
693 // if so, set their coords to matching point
694 // set pselect for newly moved points so remove_particles() will work
695
696 int m,value,j,jwhich;
697 double *p[2],*q;
698 OnePoint3d key;
699
700 Surf::Line *lines = surf->lines;
701 int nsurf = surf->nsurf;
702
703 for (int i = 0; i < nsurf; i++) {
704 if (lines[i].mask & groupbit) continue;
705 p[0] = lines[i].p1;
706 p[1] = lines[i].p2;
707
708 for (m = 0; m < 2; m++) {
709 key.pt[0] = p[m][0]; key.pt[1] = p[m][1]; key.pt[2] = 0.0;
710 if (hash->find(key) != hash->end()) {
711 value = (*hash)[key];
712 j = value/2;
713 jwhich = value % 2;
714 if (jwhich == 0) q = lines[j].p1;
715 else q = lines[j].p2;
716 p[m][0] = q[0];
717 p[m][1] = q[1];
718 if (m == 0) pselect[2*i] = 1;
719 else pselect[2*i+1] = 1;
720 }
721 }
722 }
723
724 // free the hash
725
726 delete hash;
727 }
728
729 /* ----------------------------------------------------------------------
730 add points in moved triangles to hash
731 ------------------------------------------------------------------------- */
732
connect_3d_pre()733 void MoveSurf::connect_3d_pre()
734 {
735 // hash for corner points of moved triangles
736 // key = corner point
737 // value = global index (0 to 3*Ntri-1) of the point
738 // NOTE: could prealloc hash to correct size here
739
740 hash = new MyHash();
741
742 // add moved points to hash
743
744 double *p1,*p2,*p3;
745 OnePoint3d key;
746
747 Surf::Tri *tris = surf->tris;
748 int nsurf = surf->nsurf;
749
750 for (int i = 0; i < nsurf; i++) {
751 if (!(tris[i].mask & groupbit)) continue;
752 p1 = tris[i].p1;
753 p2 = tris[i].p2;
754 p3 = tris[i].p3;
755 key.pt[0] = p1[0]; key.pt[1] = p1[1]; key.pt[2] = p1[2];
756 if (hash->find(key) == hash->end()) (*hash)[key] = 3*i+0;
757 key.pt[0] = p2[0]; key.pt[1] = p2[1]; key.pt[2] = p2[2];
758 if (hash->find(key) == hash->end()) (*hash)[key] = 3*i+1;
759 key.pt[0] = p3[0]; key.pt[1] = p3[1]; key.pt[2] = p3[2];
760 if (hash->find(key) == hash->end()) (*hash)[key] = 3*i+2;
761 }
762 }
763
764 /* ----------------------------------------------------------------------
765 move points in tris connected to tri points that were moved
766 ------------------------------------------------------------------------- */
767
connect_3d_post()768 void MoveSurf::connect_3d_post()
769 {
770 // check if non-moved points are in hash
771 // if so, set their coords to matching point
772 // set pselect for newly moved points so remove_particles() will work
773
774 int m,value,j,jwhich;
775 double *p[3],*q;
776 OnePoint3d key;
777
778 Surf::Tri *tris = surf->tris;
779 int nsurf = surf->nsurf;
780
781 for (int i = 0; i < nsurf; i++) {
782 if (tris[i].mask & groupbit) continue;
783 p[0] = tris[i].p1;
784 p[1] = tris[i].p2;
785 p[2] = tris[i].p3;
786
787 for (m = 0; m < 3; m++) {
788 key.pt[0] = p[m][0]; key.pt[1] = p[m][1]; key.pt[2] = p[m][2];
789 if (hash->find(key) != hash->end()) {
790 value = (*hash)[key];
791 j = value/3;
792 jwhich = value % 3;
793 if (jwhich == 0) q = tris[j].p1;
794 else if (jwhich == 1) q = tris[j].p2;
795 else q = tris[j].p3;
796 p[m][0] = q[0];
797 p[m][1] = q[1];
798 p[m][2] = q[2];
799 if (m == 0) pselect[3*i] = 1;
800 else if (m == 1) pselect[3*i+1] = 1;
801 else pselect[3*i+2] = 1;
802 }
803 }
804 }
805
806 // free the hash
807
808 delete hash;
809 }
810
811 /* ----------------------------------------------------------------------
812 remove particles in any cell that is now INSIDE or contains moved surfs
813 surfs that moved determined by pselect for any of its points
814 reassign particles in split cells to sub cell owner
815 compress particles if any flagged for deletion
816 NOTE: doc this logic better
817 ------------------------------------------------------------------------- */
818
remove_particles()819 bigint MoveSurf::remove_particles()
820 {
821 int isurf,nsurf;
822 surfint *csurfs;
823
824 dim = domain->dimension;
825 Grid::ChildCell *cells = grid->cells;
826 Grid::ChildInfo *cinfo = grid->cinfo;
827 int nglocal = grid->nlocal;
828 int delflag = 0;
829
830 for (int icell = 0; icell < nglocal; icell++) {
831
832 // cell is inside surfs
833 // remove particles in case it wasn't before
834
835 if (cinfo[icell].type == INSIDE) {
836 if (cinfo[icell].count) delflag = 1;
837 particle->remove_all_from_cell(cinfo[icell].first);
838 cinfo[icell].count = 0;
839 cinfo[icell].first = -1;
840 continue;
841 }
842
843 // cell has surfs or is split
844 // if m < nsurf, loop over csurfs did not finish
845 // which means cell contains a moved surf, so delete all its particles
846
847 if (cells[icell].nsurf && cells[icell].nsplit >= 1) {
848 nsurf = cells[icell].nsurf;
849 csurfs = cells[icell].csurfs;
850
851 int m;
852 if (dim == 2) {
853 for (m = 0; m < nsurf; m++) {
854 isurf = csurfs[m];
855 if (pselect[2*isurf]) break;
856 if (pselect[2*isurf+1]) break;
857 }
858 } else {
859 for (m = 0; m < nsurf; m++) {
860 isurf = csurfs[m];
861 if (pselect[3*isurf]) break;
862 if (pselect[3*isurf+1]) break;
863 if (pselect[3*isurf+2]) break;
864 }
865 }
866
867 if (m < nsurf) {
868 if (cinfo[icell].count) delflag = 1;
869 particle->remove_all_from_cell(cinfo[icell].first);
870 cinfo[icell].count = 0;
871 cinfo[icell].first = -1;
872 }
873 }
874
875 if (cells[icell].nsplit > 1)
876 grid->assign_split_cell_particles(icell);
877 }
878
879 int nlocal_old = particle->nlocal;
880 if (delflag) particle->compress_rebalance();
881 bigint delta = nlocal_old - particle->nlocal;
882 bigint ndeleted;
883 MPI_Allreduce(&delta,&ndeleted,1,MPI_SPARTA_BIGINT,MPI_SUM,world);
884 return ndeleted;
885 }
886