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