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 "ctype.h"
16 #include "surf.h"
17 #include "style_surf_collide.h"
18 #include "style_surf_react.h"
19 #include "surf_collide.h"
20 #include "surf_react.h"
21 #include "domain.h"
22 #include "region.h"
23 #include "grid.h"
24 #include "comm.h"
25 #include "geometry.h"
26 #include "input.h"
27 #include "math_extra.h"
28 #include "math_const.h"
29 #include "hash3.h"
30 #include "memory.h"
31 #include "error.h"
32
33 using namespace SPARTA_NS;
34 using namespace MathConst;
35
36 enum{TALLYAUTO,TALLYREDUCE,TALLYRVOUS}; // same as Update
37 enum{REGION_ALL,REGION_ONE,REGION_CENTER}; // same as Grid
38 enum{TYPE,MOLECULE,ID};
39 enum{LT,LE,GT,GE,EQ,NEQ,BETWEEN};
40 enum{INT,DOUBLE}; // several files
41
42 #define DELTA 1024
43 #define DELTAMODEL 4
44 #define EPSSQ 1.0e-12
45 #define EPSILON_GRID 1.0e-3
46 #define BIG 1.0e20
47 #define MAXGROUP 32
48
49 /* ---------------------------------------------------------------------- */
50
Surf(SPARTA * sparta)51 Surf::Surf(SPARTA *sparta) : Pointers(sparta)
52 {
53 me = comm->me;
54 nprocs = comm->nprocs;
55
56 exist = 0;
57 implicit = 0;
58 distributed = 0;
59 surf_collision_check = 1;
60
61 gnames = (char **) memory->smalloc(MAXGROUP*sizeof(char *),"surf:gnames");
62 bitmask = (int *) memory->smalloc(MAXGROUP*sizeof(int),"surf:bitmask");
63 inversemask = (int *) memory->smalloc(MAXGROUP*sizeof(int),
64 "surf:inversemask");
65
66 for (int i = 0; i < MAXGROUP; i++) bitmask[i] = 1 << i;
67 for (int i = 0; i < MAXGROUP; i++) inversemask[i] = bitmask[i] ^ ~0;
68
69 ngroup = 1;
70 int n = strlen("all") + 1;
71 gnames[0] = new char[n];
72 strcpy(gnames[0],"all");
73
74 nsurf = 0;
75
76 nlocal = nghost = nmax = 0;
77 lines = NULL;
78 tris = NULL;
79
80 nown = maxown = 0;
81 mylines = NULL;
82 mytris = NULL;
83
84 nsc = maxsc = 0;
85 sc = NULL;
86 nsr = maxsr = 0;
87 sr = NULL;
88
89 tally_comm = TALLYAUTO;
90
91 // custom per-surf vectors/arrays
92
93 ncustom = 0;
94 ename = NULL;
95 etype = esize = ewhich = NULL;
96
97 ncustom_ivec = ncustom_iarray = 0;
98 icustom_ivec = icustom_iarray = NULL;
99 eivec = NULL;
100 eiarray = NULL;
101 eicol = NULL;
102
103 ncustom_dvec = ncustom_darray = 0;
104 icustom_dvec = icustom_darray = NULL;
105 edvec = NULL;
106 edarray = NULL;
107 edcol = NULL;
108
109 custom_restart_flag = NULL;
110
111 // allocate hash for surf IDs
112
113 hash = new MySurfHash();
114 hashfilled = 0;
115 }
116
117 /* ---------------------------------------------------------------------- */
118
~Surf()119 Surf::~Surf()
120 {
121 for (int i = 0; i < ngroup; i++) delete [] gnames[i];
122 memory->sfree(gnames);
123 memory->sfree(bitmask);
124 memory->sfree(inversemask);
125
126 memory->sfree(lines);
127 memory->sfree(tris);
128 memory->sfree(mylines);
129 memory->sfree(mytris);
130
131 for (int i = 0; i < nsc; i++) delete sc[i];
132 memory->sfree(sc);
133 for (int i = 0; i < nsr; i++) delete sr[i];
134 memory->sfree(sr);
135
136 hash->clear();
137 delete hash;
138
139 for (int i = 0; i < ncustom; i++) delete [] ename[i];
140 memory->sfree(ename);
141 memory->destroy(etype);
142 memory->destroy(esize);
143 memory->destroy(ewhich);
144
145 for (int i = 0; i < ncustom_ivec; i++) memory->destroy(eivec[i]);
146 for (int i = 0; i < ncustom_iarray; i++) memory->destroy(eiarray[i]);
147 for (int i = 0; i < ncustom_dvec; i++) memory->destroy(edvec[i]);
148 for (int i = 0; i < ncustom_darray; i++) memory->destroy(edarray[i]);
149
150 memory->destroy(icustom_ivec);
151 memory->destroy(icustom_iarray);
152 memory->sfree(eivec);
153 memory->sfree(eiarray);
154 memory->destroy(eicol);
155 memory->destroy(icustom_dvec);
156 memory->destroy(icustom_darray);
157 memory->sfree(edvec);
158 memory->sfree(edarray);
159 memory->destroy(edcol);
160 }
161
162 /* ---------------------------------------------------------------------- */
163
global(char * arg)164 void Surf::global(char *arg)
165 {
166 if (exist)
167 error->all(FLERR,"Cannot set global surfs when surfaces already exist");
168
169 if (strcmp(arg,"explicit") == 0) {
170 implicit = 0;
171 distributed = 0;
172 } else if (strcmp(arg,"explicit/distributed") == 0) {
173 implicit = 0;
174 distributed = 1;
175 } else if (strcmp(arg,"implicit") == 0) {
176 implicit = 1;
177 distributed = 1;
178 } else error->all(FLERR,"Illegal global command");
179 }
180
181 /* ---------------------------------------------------------------------- */
182
modify_params(int narg,char ** arg)183 void Surf::modify_params(int narg, char **arg)
184 {
185 if (narg < 2) error->all(FLERR,"Illegal surf_modify command");
186 int igroup = find_group(arg[0]);
187 if (igroup < 0) error->all(FLERR,"Surf_modify surface group is not defined");
188 int groupbit = bitmask[igroup];
189
190 int dim = domain->dimension;
191
192 int iarg = 1;
193 while (iarg < narg) {
194 if (strcmp(arg[iarg],"collide") == 0) {
195 if (iarg+2 > narg) error->all(FLERR,"Illegal surf_modify command");
196 if (!exist) error->all(FLERR,"Surf_modify when surfs do not yet exist");
197
198 int isc = find_collide(arg[iarg+1]);
199 if (isc < 0) error->all(FLERR,"Could not find surf_modify sc-ID");
200
201 // NOTE: is this also needed for mylines and mytris?
202 // set surf collision model for each surf in surface group
203
204 if (dim == 2) {
205 for (int i = 0; i < nlocal+nghost; i++)
206 if (lines[i].mask & groupbit) lines[i].isc = isc;
207 }
208 if (dim == 3) {
209 for (int i = 0; i < nlocal+nghost; i++)
210 if (tris[i].mask & groupbit) tris[i].isc = isc;
211 }
212
213 iarg += 2;
214
215 } else if (strcmp(arg[iarg],"react") == 0) {
216 if (iarg+2 > narg) error->all(FLERR,"Illegal surf_modify command");
217 if (!exist) error->all(FLERR,"Surf_modify when surfs do not yet exist");
218
219 int isr;
220 if (strcmp(arg[iarg+1],"none") == 0) isr = -1;
221 else {
222 isr = find_react(arg[iarg+1]);
223 if (isr < 0) error->all(FLERR,"Could not find surf_modify sr-ID");
224 }
225
226 // set surf reaction model for each surf in surface group
227
228 if (dim == 2) {
229 for (int i = 0; i < nlocal+nghost; i++)
230 if (lines[i].mask & groupbit) lines[i].isr = isr;
231 }
232 if (dim == 3) {
233 for (int i = 0; i < nlocal+nghost; i++)
234 if (tris[i].mask & groupbit) tris[i].isr = isr;
235 }
236
237 iarg += 2;
238
239 } else error->all(FLERR,"Illegal surf_modify command");
240 }
241 }
242
243 /* ---------------------------------------------------------------------- */
244
init()245 void Surf::init()
246 {
247 int dim = domain->dimension;
248 bigint flag,allflag;
249
250 // warn if surfs are distributed (explicit or implicit)
251 // and grid->cutoff < 0.0, since each proc will have copy of all cells
252
253 if (exist && distributed && grid->cutoff < 0.0)
254 if (comm->me == 0)
255 error->warning(FLERR,"Surfs are distributed with infinite grid cutoff");
256
257 // check that surf element types are all values >= 1
258
259 flag = 0;
260 if (dim == 2) {
261 for (int i = 0; i < nlocal; i++)
262 if (lines[i].type <= 0) flag++;
263 }
264 if (dim == 3) {
265 for (int i = 0; i < nlocal; i++)
266 if (tris[i].type <= 0) flag++;
267 }
268
269 if (distributed)
270 MPI_Allreduce(&flag,&allflag,1,MPI_SPARTA_BIGINT,MPI_SUM,world);
271 else allflag = flag;
272
273 if (allflag) {
274 char str[64];
275 sprintf(str,BIGINT_FORMAT
276 " surface elements with invalid type <= 0",allflag);
277 error->all(FLERR,str);
278 }
279
280 // check that every element is assigned to a surf collision model
281 // skip if caller turned off the check, e.g. BalanceGrid, b/c too early
282
283 if (surf_collision_check) {
284 flag = 0;
285 if (dim == 2) {
286 for (int i = 0; i < nlocal+nghost; i++)
287 if (lines[i].isc < 0) flag++;
288 }
289 if (dim == 3) {
290 for (int i = 0; i < nlocal+nghost; i++)
291 if (tris[i].isc < 0) flag++;
292 }
293
294 if (distributed)
295 MPI_Allreduce(&flag,&allflag,1,MPI_SPARTA_BIGINT,MPI_SUM,world);
296 else allflag = flag;
297
298 if (allflag) {
299 char str[64];
300 sprintf(str,BIGINT_FORMAT
301 " surface elements not assigned to a collision model",allflag);
302 error->all(FLERR,str);
303 }
304 }
305
306 // if a surf element is assigned a reaction model
307 // must have a collision model that allows reactions
308
309 if (surf_collision_check) {
310 flag = 0;
311 if (dim == 2) {
312 for (int i = 0; i < nlocal+nghost; i++)
313 if (lines[i].isr >= 0 && sc[lines[i].isc]->allowreact == 0) flag++;
314 }
315 if (dim == 3) {
316 for (int i = 0; i < nlocal+nghost; i++)
317 if (tris[i].isr >= 0 && sc[tris[i].isc]->allowreact == 0) flag++;
318 }
319
320 if (distributed)
321 MPI_Allreduce(&flag,&allflag,1,MPI_SPARTA_BIGINT,MPI_SUM,world);
322 else allflag = flag;
323
324 if (allflag) {
325 char str[128];
326 sprintf(str,BIGINT_FORMAT " surface elements with reaction model, "
327 "but invalid collision model",allflag);
328 error->all(FLERR,str);
329 }
330 }
331
332 // checks on transparent surfaces
333 // must be assigned to transparent surf collision model
334
335 if (surf_collision_check) {
336 flag = 0;
337 if (dim == 2) {
338 for (int i = 0; i < nlocal+nghost; i++) {
339 if (!lines[i].transparent) continue;
340 if (!sc[lines[i].isc]->transparent) flag++;
341 }
342 }
343 if (dim == 3) {
344 for (int i = 0; i < nlocal+nghost; i++) {
345 if (!tris[i].transparent) continue;
346 if (!sc[tris[i].isc]->transparent) flag++;
347 }
348 }
349
350 if (distributed)
351 MPI_Allreduce(&flag,&allflag,1,MPI_SPARTA_BIGINT,MPI_SUM,world);
352 else allflag = flag;
353
354 if (allflag) {
355 char str[128];
356 sprintf(str,BIGINT_FORMAT " transparent surface elements "
357 "with invalid collision model or reaction model",allflag);
358 error->all(FLERR,str);
359 }
360 }
361
362 // initialize surf collision and reaction models
363
364 for (int i = 0; i < nsc; i++) sc[i]->init();
365 for (int i = 0; i < nsr; i++) sr[i]->init();
366 }
367
368 /* ----------------------------------------------------------------------
369 remove all surfs
370 called by FixAblate
371 ------------------------------------------------------------------------- */
372
clear()373 void Surf::clear()
374 {
375 nsurf = 0;
376 nlocal = nghost = 0;
377 nown = 0;
378 hash->clear();
379 hashfilled = 0;
380 }
381
382 /* ----------------------------------------------------------------------
383 remove ghost surfs
384 ------------------------------------------------------------------------- */
385
remove_ghosts()386 void Surf::remove_ghosts()
387 {
388 nghost = 0;
389 }
390
391 /* ----------------------------------------------------------------------
392 add a line to lines list
393 called by ReadSurf (for non-distributed surfs) and ReadISurf
394 ------------------------------------------------------------------------- */
395
add_line(surfint id,int itype,double * p1,double * p2)396 void Surf::add_line(surfint id, int itype, double *p1, double *p2)
397 {
398 if (nlocal == nmax) {
399 if ((bigint) nmax + DELTA > MAXSMALLINT)
400 error->one(FLERR,"Surf add_line overflowed");
401 nmax += DELTA;
402 grow(nmax-DELTA);
403 }
404
405 lines[nlocal].id = id;
406 lines[nlocal].type = itype;
407 lines[nlocal].mask = 1;
408 lines[nlocal].isc = lines[nlocal].isr = -1;
409 lines[nlocal].p1[0] = p1[0];
410 lines[nlocal].p1[1] = p1[1];
411 lines[nlocal].p1[2] = 0.0;
412 lines[nlocal].p2[0] = p2[0];
413 lines[nlocal].p2[1] = p2[1];
414 lines[nlocal].p2[2] = 0.0;
415 lines[nlocal].transparent = 0;
416 nlocal++;
417 }
418
419 /* ----------------------------------------------------------------------
420 add a line to owned or ghost lines list, depending on ownflag
421 called by Grid::unpack_one() or Grid::coarsen_cell()
422 ------------------------------------------------------------------------- */
423
add_line_copy(int ownflag,Line * line)424 void Surf::add_line_copy(int ownflag, Line *line)
425 {
426 int index;
427
428 if (ownflag) {
429 if (nlocal == nmax) {
430 if ((bigint) nmax + DELTA > MAXSMALLINT)
431 error->one(FLERR,"Surf add_line_copy overflowed");
432 nmax += DELTA;
433 grow(nmax-DELTA);
434 }
435 index = nlocal;
436 nlocal++;
437
438 } else {
439 if (nlocal+nghost == nmax) {
440 if ((bigint) nmax + DELTA > MAXSMALLINT)
441 error->one(FLERR,"Surf add_line_copy overflowed");
442 nmax += DELTA;
443 grow(nmax-DELTA);
444 }
445 index = nlocal+nghost;
446 nghost++;
447 }
448
449 memcpy(&lines[index],line,sizeof(Line));
450 }
451
452 /* ----------------------------------------------------------------------
453 add a line to mylines list
454 called by ReadSurf for distributed surfs
455 NOT adding one line at a time, rather inserting at location M based on ID
456 assume mylines has been pre-allocated to correct length
457 caller sets surf->nown
458 ------------------------------------------------------------------------- */
459
add_line_own(surfint id,int itype,double * p1,double * p2)460 void Surf::add_line_own(surfint id, int itype, double *p1, double *p2)
461 {
462 int m = (id-1) / nprocs;
463
464 mylines[m].id = id;
465 mylines[m].type = itype;
466 mylines[m].mask = 1;
467 mylines[m].isc = mylines[m].isr = -1;
468 mylines[m].p1[0] = p1[0];
469 mylines[m].p1[1] = p1[1];
470 mylines[m].p1[2] = 0.0;
471 mylines[m].p2[0] = p2[0];
472 mylines[m].p2[1] = p2[1];
473 mylines[m].p2[2] = 0.0;
474 mylines[m].transparent = 0;
475 }
476
477 /* ----------------------------------------------------------------------
478 add a line to tmplines list
479 called by ReadSurf for multiple file input
480 ------------------------------------------------------------------------- */
481
add_line_temporary(surfint id,int itype,double * p1,double * p2)482 void Surf::add_line_temporary(surfint id, int itype, double *p1, double *p2)
483 {
484 if (ntmp == nmaxtmp) {
485 if ((bigint) nmaxtmp + DELTA > MAXSMALLINT)
486 error->one(FLERR,"Surf add_line_tmeporary overflowed");
487 nmaxtmp += DELTA;
488 grow_temporary(nmaxtmp-DELTA);
489 }
490
491 tmplines[ntmp].id = id;
492 tmplines[ntmp].type = itype;
493 tmplines[ntmp].mask = 1;
494 tmplines[ntmp].isc = tmplines[ntmp].isr = -1;
495 tmplines[ntmp].p1[0] = p1[0];
496 tmplines[ntmp].p1[1] = p1[1];
497 tmplines[ntmp].p1[2] = 0.0;
498 tmplines[ntmp].p2[0] = p2[0];
499 tmplines[ntmp].p2[1] = p2[1];
500 tmplines[ntmp].p2[2] = 0.0;
501 tmplines[ntmp].transparent = 0;
502 ntmp++;
503 }
504
505 /* ----------------------------------------------------------------------
506 add a triangle to tris list
507 called by ReadSurf (for non-distributed surfs) and
508 by ReadISurf via FixAblate and Marching Cubes/Squares
509 ------------------------------------------------------------------------- */
510
add_tri(surfint id,int itype,double * p1,double * p2,double * p3)511 void Surf::add_tri(surfint id, int itype, double *p1, double *p2, double *p3)
512 {
513 if (nlocal == nmax) {
514 if ((bigint) nmax + DELTA > MAXSMALLINT)
515 error->one(FLERR,"Surf add_tri overflowed");
516 nmax += DELTA;
517 grow(nmax-DELTA);
518 }
519
520 tris[nlocal].id = id;
521 tris[nlocal].type = itype;
522 tris[nlocal].mask = 1;
523 tris[nlocal].isc = tris[nlocal].isr = -1;
524 tris[nlocal].p1[0] = p1[0];
525 tris[nlocal].p1[1] = p1[1];
526 tris[nlocal].p1[2] = p1[2];
527 tris[nlocal].p2[0] = p2[0];
528 tris[nlocal].p2[1] = p2[1];
529 tris[nlocal].p2[2] = p2[2];
530 tris[nlocal].p3[0] = p3[0];
531 tris[nlocal].p3[1] = p3[1];
532 tris[nlocal].p3[2] = p3[2];
533 tris[nlocal].transparent = 0;
534 nlocal++;
535 }
536
537 /* ----------------------------------------------------------------------
538 add a triangle to owned or ghost list, depending on ownflag
539 called by Grid::unpack_one
540 ------------------------------------------------------------------------- */
541
add_tri_copy(int ownflag,Tri * tri)542 void Surf::add_tri_copy(int ownflag, Tri *tri)
543 {
544 int index;
545
546 if (ownflag) {
547 if (nlocal == nmax) {
548 if ((bigint) nmax + DELTA > MAXSMALLINT)
549 error->one(FLERR,"Surf add_tri_copy overflowed");
550 nmax += DELTA;
551 grow(nmax-DELTA);
552 }
553 index = nlocal;
554 nlocal++;
555
556 } else {
557 if (nlocal+nghost == nmax) {
558 if ((bigint) nmax + DELTA > MAXSMALLINT)
559 error->one(FLERR,"Surf add_tri_copy overflowed");
560 nmax += DELTA;
561 grow(nmax-DELTA);
562 }
563 index = nlocal+nghost;
564 nghost++;
565 }
566
567 memcpy(&tris[index],tri,sizeof(Tri));
568 }
569
570 /* ----------------------------------------------------------------------
571 add a triangls's info to mytris list
572 called by ReadSurf for distributed surfs
573 NOT adding one tri at a time, rather inserting at location M based on ID
574 assume mytris has been pre-allocated to correct length
575 caller sets surf->nown
576 ------------------------------------------------------------------------- */
577
add_tri_own(surfint id,int itype,double * p1,double * p2,double * p3)578 void Surf::add_tri_own(surfint id, int itype, double *p1, double *p2, double *p3)
579 {
580 int m = (id-1) / nprocs;
581
582 mytris[m].id = id;
583 mytris[m].type = itype;
584 mytris[m].mask = 1;
585 mytris[m].isc = mytris[m].isr = -1;
586 mytris[m].p1[0] = p1[0];
587 mytris[m].p1[1] = p1[1];
588 mytris[m].p1[2] = p1[2];
589 mytris[m].p2[0] = p2[0];
590 mytris[m].p2[1] = p2[1];
591 mytris[m].p2[2] = p2[2];
592 mytris[m].p3[0] = p3[0];
593 mytris[m].p3[1] = p3[1];
594 mytris[m].p3[2] = p3[2];
595 mytris[m].transparent = 0;
596 }
597
598 /* ----------------------------------------------------------------------
599 add a triangls's info to mytris list
600 called by ReadSurf for distributed surfs when clip3d adds one
601 ARE adding one tri at a time, IDs will be renumbered after
602 and tris re-distributed to procs
603 check if mytris needs to be reallocated
604 increment nown
605 ------------------------------------------------------------------------- */
606
add_tri_own_clip(surfint id,int itype,double * p1,double * p2,double * p3)607 void Surf::add_tri_own_clip(surfint id, int itype,
608 double *p1, double *p2, double *p3)
609 {
610 if (nown == maxown) {
611 if ((bigint) maxown + DELTA > MAXSMALLINT)
612 error->one(FLERR,"Surf add_tri overflowed");
613 maxown += DELTA;
614 grow_own(maxown-DELTA);
615 }
616
617 mytris[nown].id = id;
618 mytris[nown].type = itype;
619 mytris[nown].mask = 1;
620 mytris[nown].isc = mytris[nown].isr = -1;
621 mytris[nown].p1[0] = p1[0];
622 mytris[nown].p1[1] = p1[1];
623 mytris[nown].p1[2] = p1[2];
624 mytris[nown].p2[0] = p2[0];
625 mytris[nown].p2[1] = p2[1];
626 mytris[nown].p2[2] = p2[2];
627 mytris[nown].p3[0] = p3[0];
628 mytris[nown].p3[1] = p3[1];
629 mytris[nown].p3[2] = p3[2];
630 mytris[nown].transparent = 0;
631 nown++;
632 }
633
634 /* ----------------------------------------------------------------------
635 add a triangle to tmptris list
636 called by ReadSurf for mutliple file input
637 ------------------------------------------------------------------------- */
638
add_tri_temporary(surfint id,int itype,double * p1,double * p2,double * p3)639 void Surf::add_tri_temporary(surfint id, int itype,
640 double *p1, double *p2, double *p3)
641 {
642 if (ntmp == nmaxtmp) {
643 if ((bigint) nmaxtmp + DELTA > MAXSMALLINT)
644 error->one(FLERR,"Surf add_tri_temporary overflowed");
645 nmaxtmp += DELTA;
646 grow_temporary(nmaxtmp-DELTA);
647 }
648
649 tmptris[ntmp].id = id;
650 tmptris[ntmp].type = itype;
651 tmptris[ntmp].mask = 1;
652 tmptris[ntmp].isc = tmptris[ntmp].isr = -1;
653 tmptris[ntmp].p1[0] = p1[0];
654 tmptris[ntmp].p1[1] = p1[1];
655 tmptris[ntmp].p1[2] = p1[2];
656 tmptris[ntmp].p2[0] = p2[0];
657 tmptris[ntmp].p2[1] = p2[1];
658 tmptris[ntmp].p2[2] = p2[2];
659 tmptris[ntmp].p3[0] = p3[0];
660 tmptris[ntmp].p3[1] = p3[1];
661 tmptris[ntmp].p3[2] = p3[2];
662 tmptris[ntmp].transparent = 0;
663 ntmp++;
664 }
665
666 /* ----------------------------------------------------------------------
667 hash all my nlocal surfs with key = ID, value = index
668 called only for distributed explicit surfs
669 ------------------------------------------------------------------------- */
670
rehash()671 void Surf::rehash()
672 {
673 if (implicit) return;
674
675 // hash all nlocal surfs
676 // key = ID, value = index into lines or tris
677
678 hash->clear();
679 hashfilled = 1;
680
681 if (domain->dimension == 2) {
682 for (int isurf = 0; isurf < nlocal; isurf++)
683 (*hash)[lines[isurf].id] = isurf;
684 } else {
685 for (int isurf = 0; isurf < nlocal; isurf++)
686 (*hash)[tris[isurf].id] = isurf;
687 }
688 }
689
690 /* ----------------------------------------------------------------------
691 return 1 if all surfs are transparent, else return 0
692 called by set_inout()
693 ------------------------------------------------------------------------- */
694
all_transparent()695 int Surf::all_transparent()
696 {
697 // implicit surfs cannot be transparent
698
699 if (implicit) return 0;
700
701 // explicit surfs may be transparent
702
703 int flag = 0;
704 if (domain->dimension == 2) {
705 for (int i = 0; i < nlocal; i++)
706 if (!lines[i].transparent) flag = 1;
707 }
708 if (domain->dimension == 3) {
709 for (int i = 0; i < nlocal; i++)
710 if (!tris[i].transparent) flag = 1;
711 }
712
713 int allflag;
714 if (distributed)
715 MPI_Allreduce(&flag,&allflag,1,MPI_INT,MPI_SUM,world);
716 else allflag = flag;
717
718 if (allflag) return 0;
719 return 1;
720 }
721
722 /* ----------------------------------------------------------------------
723 count owned surf elements = every Pth surf from global Nsurf list
724 only called when surfs = explict (all or distributed)
725 nothing to do when distributed b/c mylines/mytris already setup
726 ------------------------------------------------------------------------ */
727
setup_owned()728 void Surf::setup_owned()
729 {
730 if (distributed) return;
731
732 nown = nsurf/nprocs;
733 if (comm->me < nsurf % nprocs) nown++;
734 }
735
736 /* ----------------------------------------------------------------------
737 set bounding box around all surfs based on their pts
738 sets surf->bblo and surf->bbhi
739 for 2d, set zlo,zhi to box bounds
740 only called when surfs = explict (all or distributed)
741 ------------------------------------------------------------------------- */
742
bbox_all()743 void Surf::bbox_all()
744 {
745 int i,j;
746 double bblo_one[3],bbhi_one[3];
747 double *x;
748
749 int dim = domain->dimension;
750
751 int istart,istop,idelta;
752 Line *linelist;
753 Tri *trilist;
754
755 if (!distributed) {
756 istart = me;
757 istop = nlocal;
758 idelta = nprocs;
759 linelist = lines;
760 trilist = tris;
761 } else {
762 istart = 0;
763 istop = nown;
764 idelta = 1;
765 linelist = mylines;
766 trilist = mytris;
767 }
768
769 for (j = 0; j < 3; j++) {
770 bblo_one[j] = BIG;
771 bbhi_one[j] = -BIG;
772 }
773
774 if (dim == 2) {
775 for (i = istart; i < istop; i += idelta) {
776 x = linelist[i].p1;
777 for (j = 0; j < 2; j++) {
778 bblo_one[j] = MIN(bblo_one[j],x[j]);
779 bbhi_one[j] = MAX(bbhi_one[j],x[j]);
780 }
781 x = linelist[i].p2;
782 for (j = 0; j < 2; j++) {
783 bblo_one[j] = MIN(bblo_one[j],x[j]);
784 bbhi_one[j] = MAX(bbhi_one[j],x[j]);
785 }
786 }
787 bblo_one[2] = domain->boxlo[2];
788 bbhi_one[2] = domain->boxhi[2];
789
790 } else if (dim == 3) {
791 for (i = istart; i < istop; i += idelta) {
792 x = trilist[i].p1;
793 for (j = 0; j < 3; j++) {
794 bblo_one[j] = MIN(bblo_one[j],x[j]);
795 bbhi_one[j] = MAX(bbhi_one[j],x[j]);
796 }
797 x = trilist[i].p2;
798 for (j = 0; j < 3; j++) {
799 bblo_one[j] = MIN(bblo_one[j],x[j]);
800 bbhi_one[j] = MAX(bbhi_one[j],x[j]);
801 }
802 x = trilist[i].p3;
803 for (j = 0; j < 3; j++) {
804 bblo_one[j] = MIN(bblo_one[j],x[j]);
805 bbhi_one[j] = MAX(bbhi_one[j],x[j]);
806 }
807 }
808 }
809
810 MPI_Allreduce(bblo_one,bblo,3,MPI_DOUBLE,MPI_MIN,world);
811 MPI_Allreduce(bbhi_one,bbhi,3,MPI_DOUBLE,MPI_MAX,world);
812 }
813
814 /* ----------------------------------------------------------------------
815 set bounding box around one surf based on their pts
816 caller passes in the Line or Tri, can be from lines/tris or mylines/mytris
817 returns lo,hi which are allocated by caller
818 for 2d, set zlo,zhi to box bounds
819 only called when surfs = explict (all or distributed)
820 ------------------------------------------------------------------------- */
821
bbox_one(void * ptr,double * lo,double * hi)822 void Surf::bbox_one(void *ptr, double *lo, double *hi)
823 {
824 double *p1,*p2,*p3;
825
826 if (domain->dimension == 2) {
827 Line *line = (Line *) ptr;
828 p1 = line->p1; p2 = line->p2;
829 lo[0] = MIN(p1[0],p2[0]);
830 lo[1] = MIN(p1[1],p2[1]);
831 lo[2] = 0.0;
832 hi[0] = MAX(p1[0],p2[0]);
833 hi[1] = MAX(p1[1],p2[1]);
834 hi[2] = 0.0;
835
836 } else {
837 Tri *tri = (Tri *) ptr;
838 p1 = tri->p1; p2 = tri->p2; p3 = tri->p3;
839 lo[0] = MIN(p1[0],p2[0]);
840 lo[0] = MIN(lo[0],p3[0]);
841 lo[1] = MIN(p1[1],p2[1]);
842 lo[1] = MIN(lo[1],p3[1]);
843 lo[2] = MIN(p1[2],p2[2]);
844 lo[2] = MIN(lo[2],p3[2]);
845 hi[0] = MAX(p1[0],p2[0]);
846 hi[0] = MAX(hi[0],p3[0]);
847 hi[1] = MAX(p1[1],p2[1]);
848 hi[1] = MAX(hi[1],p3[1]);
849 hi[2] = MAX(p1[2],p2[2]);
850 hi[2] = MAX(hi[2],p3[2]);
851 }
852 }
853
854 /* ----------------------------------------------------------------------
855 compute unit outward normal vectors of all lines starting at Nold
856 outward normal = +z axis x (p2-p1)
857 ------------------------------------------------------------------------- */
858
compute_line_normal(int old)859 void Surf::compute_line_normal(int old)
860 {
861 double z[3],delta[3];
862
863 z[0] = 0.0; z[1] = 0.0; z[2] = 1.0;
864
865 int n;
866 Line *newlines;
867
868 if (!implicit && distributed) {
869 newlines = mylines;
870 n = nown;
871 } else {
872 newlines = lines;
873 n = nlocal;
874 }
875
876 for (int i = old; i < n; i++) {
877 MathExtra::sub3(newlines[i].p2,newlines[i].p1,delta);
878 MathExtra::cross3(z,delta,newlines[i].norm);
879 MathExtra::norm3(newlines[i].norm);
880 newlines[i].norm[2] = 0.0;
881 }
882 }
883
884 /* ----------------------------------------------------------------------
885 compute unit outward normal vectors of all lines starting at Nold
886 outward normal = (p2-p1) x (p3-p1)
887 ------------------------------------------------------------------------- */
888
compute_tri_normal(int old)889 void Surf::compute_tri_normal(int old)
890 {
891 int p1,p2,p3;
892 double delta12[3],delta13[3];
893
894 int n;
895 Tri *newtris;
896
897 if (!implicit && distributed) {
898 newtris = mytris;
899 n = nown;
900 } else {
901 newtris = tris;
902 n = nlocal;
903 }
904
905 for (int i = old; i < n; i++) {
906 MathExtra::sub3(newtris[i].p2,newtris[i].p1,delta12);
907 MathExtra::sub3(newtris[i].p3,newtris[i].p1,delta13);
908 MathExtra::cross3(delta12,delta13,newtris[i].norm);
909 MathExtra::norm3(newtris[i].norm);
910 }
911 }
912
913 /* ----------------------------------------------------------------------
914 return coords of a corner point in a 2d quad
915 icorner pts 1 to 4 are ordered by x, then by y
916 ------------------------------------------------------------------------- */
917
quad_corner_point(int icorner,double * lo,double * hi,double * pt)918 void Surf::quad_corner_point(int icorner, double *lo, double *hi, double *pt)
919 {
920 if (icorner % 2) pt[0] = hi[0];
921 else pt[0] = lo[0];
922 if (icorner / 2) pt[1] = hi[1];
923 else pt[1] = lo[1];
924 pt[2] = 0.0;
925 }
926
927 /* ----------------------------------------------------------------------
928 return coords of a corner point in a 3d hex
929 icorner pts 1 to 8 are ordered by x, then by y, then by z
930 ------------------------------------------------------------------------- */
931
hex_corner_point(int icorner,double * lo,double * hi,double * pt)932 void Surf::hex_corner_point(int icorner, double *lo, double *hi, double *pt)
933 {
934 if (icorner % 2) pt[0] = hi[0];
935 else pt[0] = lo[0];
936 if ((icorner/2) % 2) pt[1] = hi[1];
937 else pt[1] = lo[1];
938 if (icorner / 4) pt[2] = hi[2];
939 else pt[2] = lo[2];
940 }
941
942 /* ----------------------------------------------------------------------
943 return length of line M from lines list (not myline)
944 ------------------------------------------------------------------------- */
945
line_size(int m)946 double Surf::line_size(int m)
947 {
948 return line_size(lines[m].p1,lines[m].p2);
949 }
950
951 /* ----------------------------------------------------------------------
952 return length of line
953 ------------------------------------------------------------------------- */
954
line_size(Line * line)955 double Surf::line_size(Line *line)
956 {
957 return line_size(line->p1,line->p2);
958 }
959
960 /* ----------------------------------------------------------------------
961 return length of line bewteen 2 points
962 ------------------------------------------------------------------------- */
963
line_size(double * p1,double * p2)964 double Surf::line_size(double *p1, double *p2)
965 {
966 double delta[3];
967 MathExtra::sub3(p2,p1,delta);
968 return MathExtra::len3(delta);
969 }
970
971 /* ----------------------------------------------------------------------
972 return area associated with rotating axisymmetric line around y=0 axis
973 ------------------------------------------------------------------------- */
974
axi_line_size(int m)975 double Surf::axi_line_size(int m)
976 {
977 double *x1 = lines[m].p1;
978 double *x2 = lines[m].p2;
979 double h = x2[0]-x1[0];
980 double r = x2[1]-x1[1];
981 double area = MY_PI*(x1[1]+x2[1])*sqrt(r*r+h*h);
982 return area;
983 }
984
985 /* ----------------------------------------------------------------------
986 return area associated with rotating axisymmetric line around y=0 axis
987 ------------------------------------------------------------------------- */
988
axi_line_size(Line * line)989 double Surf::axi_line_size(Line *line)
990 {
991 double *x1 = line->p1;
992 double *x2 = line->p2;
993 double h = x2[0]-x1[0];
994 double r = x2[1]-x1[1];
995 double area = MY_PI*(x1[1]+x2[1])*sqrt(r*r+h*h);
996 return area;
997 }
998
999 /* ----------------------------------------------------------------------
1000 compute side length and area of triangle M from tri list (not mytri)
1001 return len = length of shortest edge of triangle M
1002 return area = area of triangle M
1003 ------------------------------------------------------------------------- */
1004
tri_size(int m,double & len)1005 double Surf::tri_size(int m, double &len)
1006 {
1007 return tri_size(tris[m].p1,tris[m].p2,tris[m].p3,len);
1008 }
1009
1010 /* ----------------------------------------------------------------------
1011 compute side length and area of triangle tri
1012 return len = length of shortest edge of triangle M
1013 return area = area of triangle M
1014 ------------------------------------------------------------------------- */
1015
tri_size(Tri * tri,double & len)1016 double Surf::tri_size(Tri *tri, double &len)
1017 {
1018 return tri_size(tri->p1,tri->p2,tri->p3,len);
1019 }
1020
1021 /* ----------------------------------------------------------------------
1022 compute side length and area of a triangle
1023 return len = length of shortest edge of triangle M
1024 return area = area of triangle M
1025 ------------------------------------------------------------------------- */
1026
tri_size(double * p1,double * p2,double * p3,double & len)1027 double Surf::tri_size(double *p1, double *p2, double *p3, double &len)
1028 {
1029 double delta12[3],delta13[3],delta23[3],cross[3];
1030
1031 MathExtra::sub3(p2,p1,delta12);
1032 MathExtra::sub3(p3,p1,delta13);
1033 MathExtra::sub3(p3,p2,delta23);
1034 len = MIN(MathExtra::len3(delta12),MathExtra::len3(delta13));
1035 len = MIN(len,MathExtra::len3(delta23));
1036
1037 MathExtra::cross3(delta12,delta13,cross);
1038 double area = 0.5 * MathExtra::len3(cross);
1039 return area;
1040 }
1041
1042 /* ----------------------------------------------------------------------
1043 check if 2d surf elements are watertight
1044 each end point should appear exactly once as different ends of 2 lines
1045 exception: not required of end points on simulation box surface
1046 ------------------------------------------------------------------------- */
1047
check_watertight_2d()1048 void Surf::check_watertight_2d()
1049 {
1050 if (distributed) check_watertight_2d_distributed();
1051 else check_watertight_2d_all();
1052 }
1053
1054 /* ----------------------------------------------------------------------
1055 check if 2d surf elements are watertight
1056 this is for explicit non-distributed surfs where each proc has copy of all
1057 each proc tests the entire surface, no communication needed
1058 ------------------------------------------------------------------------- */
1059
check_watertight_2d_all()1060 void Surf::check_watertight_2d_all()
1061 {
1062 // hash end points of all lines
1063 // key = end point
1064 // value = 1 if first point, 2 if second point, 3 if both points
1065
1066 MyHashPoint phash;
1067 MyPointIt it;
1068
1069 // insert each end point into hash
1070 // should appear once at each end
1071 // error if any duplicate points
1072
1073 double *p1,*p2;
1074 OnePoint2d key;
1075 int value;
1076
1077 int ndup = 0;
1078 for (int i = 0; i < nsurf; i++) {
1079 if (lines[i].transparent) continue;
1080 p1 = lines[i].p1;
1081 key.pt[0] = p1[0]; key.pt[1] = p1[1];
1082 if (phash.find(key) == phash.end()) phash[key] = 1;
1083 else {
1084 value = phash[key];
1085 if (value == 2) phash[key] = 3;
1086 else ndup++;
1087 }
1088
1089 p2 = lines[i].p2;
1090 key.pt[0] = p2[0]; key.pt[1] = p2[1];
1091 if (phash.find(key) == phash.end()) phash[key] = 2;
1092 else {
1093 value = phash[key];
1094 if (value == 1) phash[key] = 3;
1095 else ndup++;
1096 }
1097 }
1098
1099 if (ndup) {
1100 char str[128];
1101 sprintf(str,"Watertight check failed with %d duplicate points",ndup);
1102 error->all(FLERR,str);
1103 }
1104
1105 // check that each end point has a match (value = 3)
1106 // allow for exception if end point on box surface
1107
1108 double *boxlo = domain->boxlo;
1109 double *boxhi = domain->boxhi;
1110 double *kpt;
1111 double pt[3];
1112
1113 int nbad = 0;
1114 for (it = phash.begin(); it != phash.end(); ++it) {
1115 if (it->second != 3) {
1116 kpt = (double *) it->first.pt;
1117 pt[0] = kpt[0]; pt[1] = kpt[1]; pt[2] = 0.0;
1118 if (!Geometry::point_on_hex(pt,boxlo,boxhi)) nbad++;
1119 }
1120 }
1121
1122 if (nbad) {
1123 char str[128];
1124 sprintf(str,"Watertight check failed with %d unmatched points",nbad);
1125 error->all(FLERR,str);
1126 }
1127 }
1128
1129 /* ----------------------------------------------------------------------
1130 check if 2d surf elements are watertight
1131 this is for explicit distributed surfs
1132 rendezvous communication used to check that each point appears twice
1133 ------------------------------------------------------------------------- */
1134
check_watertight_2d_distributed()1135 void Surf::check_watertight_2d_distributed()
1136 {
1137 int n;
1138 Line *lines_rvous;
1139
1140 if (implicit) {
1141 n = nlocal;
1142 lines_rvous = lines;
1143 } else {
1144 n = nown;
1145 lines_rvous = mylines;
1146 }
1147
1148 // allocate memory for rvous input
1149
1150 int *proclist;
1151 memory->create(proclist,n*2,"surf:proclist");
1152 InRvousPoint *inpoint =
1153 (InRvousPoint *) memory->smalloc((bigint) n*2*sizeof(InRvousPoint),
1154 "surf:inpoint");
1155
1156 // create rvous inputs
1157 // proclist = owner of each point
1158 // each line end point is sent with flag indicating first/second
1159 // hash of point coord (xy) determines which proc to send to
1160
1161 int nrvous = 0;
1162 for (int i = 0; i < n; i++) {
1163 proclist[nrvous] = hashlittle(lines_rvous[i].p1,2*sizeof(double),0) % nprocs;
1164 inpoint[nrvous].x[0] = lines_rvous[i].p1[0];
1165 inpoint[nrvous].x[1] = lines_rvous[i].p1[1];
1166 inpoint[nrvous].which = 1;
1167 nrvous++;
1168 proclist[nrvous] = hashlittle(lines_rvous[i].p2,2*sizeof(double),0) % nprocs;
1169 inpoint[nrvous].x[0] = lines_rvous[i].p2[0];
1170 inpoint[nrvous].x[1] = lines_rvous[i].p2[1];
1171 inpoint[nrvous].which = 2;
1172 nrvous++;
1173 }
1174
1175 // perform rendezvous operation
1176 // each proc assigned subset of points
1177 // receives all copies of points, checks if count of each point is valid
1178
1179 char *buf;
1180 int nout = comm->rendezvous(1,nrvous,(char *) inpoint,sizeof(InRvousPoint),
1181 0,proclist,rendezvous_watertight_2d,
1182 0,buf,0,(void *) this);
1183
1184 memory->destroy(proclist);
1185 memory->destroy(inpoint);
1186 }
1187
1188 /* ----------------------------------------------------------------------
1189 callback from rendezvous operation
1190 process points assigned to me
1191 inbuf = list of N Inbuf datums
1192 no outbuf
1193 ------------------------------------------------------------------------- */
1194
rendezvous_watertight_2d(int n,char * inbuf,int & flag,int * & proclist,char * & outbuf,void * ptr)1195 int Surf::rendezvous_watertight_2d(int n, char *inbuf, int &flag, int *&proclist,
1196 char *&outbuf, void *ptr)
1197 {
1198 Surf *sptr = (Surf *) ptr;
1199 Domain *domain = sptr->domain;
1200 Error *error = sptr->error;
1201 MPI_Comm world = sptr->world;
1202
1203 Surf::InRvousPoint *inpoint = (Surf::InRvousPoint *) inbuf;
1204
1205 // hash all received end points
1206 // key = end point
1207 // value = 1 if first point, 2 if second point, 3 if both points
1208
1209 Surf::MyHashPoint phash;
1210 Surf::MyPointIt it;
1211
1212 // insert each point into hash
1213 // should appear once at each end of a line
1214 // error if any duplicate points
1215
1216 Surf::OnePoint2d key;
1217 int which,value;
1218
1219 int ndup = 0;
1220 for (int i = 0; i < n; i++) {
1221 key.pt[0] = inpoint[i].x[0]; key.pt[1] = inpoint[i].x[1];
1222 which = inpoint[i].which;
1223 if (phash.find(key) == phash.end()) phash[key] = which;
1224 else {
1225 value = phash[key];
1226 if (value == 3) ndup++; // point already seen twice
1227 else if (value != which) phash[key] = 3; // this is other point
1228 else ndup++; // value = which, this is duplicate point
1229 }
1230 }
1231
1232 int alldup;
1233 MPI_Allreduce(&ndup,&alldup,1,MPI_INT,MPI_SUM,world);
1234 if (alldup) {
1235 char str[128];
1236 sprintf(str,"Watertight check failed with %d duplicate points",alldup);
1237 error->all(FLERR,str);
1238 }
1239
1240 // check that each end point has a match (value = 3)
1241 // allow for exception if end point on box surface
1242
1243 double *boxlo = domain->boxlo;
1244 double *boxhi = domain->boxhi;
1245 double *kpt;
1246 double pt[3];
1247
1248 int nbad = 0;
1249 for (it = phash.begin(); it != phash.end(); ++it) {
1250 if (it->second != 3) {
1251 kpt = (double *) it->first.pt;
1252 pt[0] = kpt[0]; pt[1] = kpt[1]; pt[2] = 0.0;
1253 if (!Geometry::point_on_hex(pt,boxlo,boxhi)) nbad++;
1254 }
1255 }
1256
1257 int allbad;
1258 MPI_Allreduce(&nbad,&allbad,1,MPI_INT,MPI_SUM,world);
1259 if (nbad) {
1260 char str[128];
1261 sprintf(str,"Watertight check failed with %d unmatched points",allbad);
1262 error->all(FLERR,str);
1263 }
1264
1265 // flag = 0: no second comm needed in rendezvous
1266
1267 flag = 0;
1268 return 0;
1269 }
1270
1271 /* ----------------------------------------------------------------------
1272 check if 3d surf elements are watertight
1273 each edge should appear exactly once in each direction
1274 exception: not required of triangle edge on simulation box surface
1275 ------------------------------------------------------------------------- */
1276
check_watertight_3d()1277 void Surf::check_watertight_3d()
1278 {
1279 if (distributed) check_watertight_3d_distributed();
1280 else check_watertight_3d_all();
1281 }
1282
1283 /* ----------------------------------------------------------------------
1284 check if 3d surf elements are watertight
1285 this is for explicit non-distributed surfs where each proc has copy of all
1286 each proc tests the entire surface, no communication needed
1287 ------------------------------------------------------------------------- */
1288
check_watertight_3d_all()1289 void Surf::check_watertight_3d_all()
1290 {
1291 // hash directed edges of all triangles
1292 // key = directed edge
1293 // value = 1 if appears once, 2 if reverse also appears once
1294
1295 MyHash2Point phash;
1296 My2PointIt it;
1297
1298 // insert each edge into hash
1299 // should appear once in each direction
1300 // error if any duplicate edges
1301
1302 double *p1,*p2,*p3;
1303 TwoPoint3d key,keyinv;
1304 int value;
1305
1306 int ndup = 0;
1307 for (int i = 0; i < nsurf; i++) {
1308 if (tris[i].transparent) continue;
1309 p1 = tris[i].p1;
1310 p2 = tris[i].p2;
1311 p3 = tris[i].p3;
1312
1313 key.pts[0] = p1[0]; key.pts[1] = p1[1]; key.pts[2] = p1[2];
1314 key.pts[3] = p2[0]; key.pts[4] = p2[1]; key.pts[5] = p2[2];
1315 if (phash.find(key) == phash.end()) {
1316 keyinv.pts[0] = p2[0]; keyinv.pts[1] = p2[1]; keyinv.pts[2] = p2[2];
1317 keyinv.pts[3] = p1[0]; keyinv.pts[4] = p1[1]; keyinv.pts[5] = p1[2];
1318 if (phash.find(keyinv) == phash.end()) phash[key] = 1;
1319 else {
1320 value = phash[keyinv];
1321 if (value == 1) phash[keyinv] = 2;
1322 else ndup++;
1323 }
1324 } else ndup++;
1325
1326 key.pts[0] = p2[0]; key.pts[1] = p2[1]; key.pts[2] = p2[2];
1327 key.pts[3] = p3[0]; key.pts[4] = p3[1]; key.pts[5] = p3[2];
1328 if (phash.find(key) == phash.end()) {
1329 keyinv.pts[0] = p3[0]; keyinv.pts[1] = p3[1]; keyinv.pts[2] = p3[2];
1330 keyinv.pts[3] = p2[0]; keyinv.pts[4] = p2[1]; keyinv.pts[5] = p2[2];
1331 if (phash.find(keyinv) == phash.end()) phash[key] = 1;
1332 else {
1333 value = phash[keyinv];
1334 if (value == 1) phash[keyinv] = 2;
1335 else ndup++;
1336 }
1337 } else ndup++;
1338
1339 key.pts[0] = p3[0]; key.pts[1] = p3[1]; key.pts[2] = p3[2];
1340 key.pts[3] = p1[0]; key.pts[4] = p1[1]; key.pts[5] = p1[2];
1341 if (phash.find(key) == phash.end()) {
1342 keyinv.pts[0] = p1[0]; keyinv.pts[1] = p1[1]; keyinv.pts[2] = p1[2];
1343 keyinv.pts[3] = p3[0]; keyinv.pts[4] = p3[1]; keyinv.pts[5] = p3[2];
1344 if (phash.find(keyinv) == phash.end()) phash[key] = 1;
1345 else {
1346 value = phash[keyinv];
1347 if (value == 1) phash[keyinv] = 2;
1348 else ndup++;
1349 }
1350 } else ndup++;
1351 }
1352
1353 if (ndup) {
1354 char str[128];
1355 sprintf(str,"Watertight check failed with %d duplicate edges",ndup);
1356 error->all(FLERR,str);
1357 }
1358
1359 // check that each edge has an inverted match
1360 // allow for exception if edge is on box face
1361
1362 double *boxlo = domain->boxlo;
1363 double *boxhi = domain->boxhi;
1364 double *pts;
1365
1366 int nbad = 0;
1367 for (it = phash.begin(); it != phash.end(); ++it) {
1368 if (it->second != 2) {
1369 pts = (double *) it->first.pts;
1370 if (Geometry::edge_on_hex_face(&pts[0],&pts[3],boxlo,boxhi) < 0) nbad++;
1371 }
1372 }
1373
1374 if (nbad) {
1375 char str[128];
1376 sprintf(str,"Watertight check failed with %d unmatched edges",nbad);
1377 error->all(FLERR,str);
1378 }
1379 }
1380
1381 /* ----------------------------------------------------------------------
1382 check if 3d surf elements are watertight
1383 this is for explicit distributed surfs
1384 rendezvous communication used to check that each edge appears twice
1385 ------------------------------------------------------------------------- */
1386
check_watertight_3d_distributed()1387 void Surf::check_watertight_3d_distributed()
1388 {
1389 int n;
1390 Tri *tris_rvous;
1391
1392 if (implicit) {
1393 n = nlocal;
1394 tris_rvous = tris;
1395 } else {
1396 n = nown;
1397 tris_rvous = mytris;
1398 }
1399
1400 // allocate memory for rvous input
1401
1402 int *proclist;
1403 memory->create(proclist,n*6,"surf:proclist");
1404 InRvousEdge *inedge =
1405 (InRvousEdge *) memory->smalloc((bigint) n*6*sizeof(InRvousEdge),
1406 "surf:inedge");
1407
1408 // create rvous inputs
1409 // proclist = owner of each point
1410 // each triangle edge is sent twice with flag indicating
1411 // forward or reverse order
1412 // hash of edge coords (xyz for 2 pts) determines which proc to send to
1413
1414 double edge[6];
1415 double *p1,*p2,*p3;
1416
1417 int nbytes = 3*sizeof(double);
1418
1419 int nrvous = 0;
1420 for (int i = 0; i < n; i++) {
1421 p1 = tris_rvous[i].p1;
1422 p2 = tris_rvous[i].p2;
1423 p3 = tris_rvous[i].p3;
1424
1425 memcpy(&edge[0],p1,nbytes);
1426 memcpy(&edge[3],p2,nbytes);
1427 proclist[nrvous] = hashlittle(edge,2*nbytes,0) % nprocs;
1428 memcpy(inedge[nrvous].x1,p1,nbytes);
1429 memcpy(inedge[nrvous].x2,p2,nbytes);
1430 inedge[nrvous].which = 1;
1431 nrvous++;
1432
1433 memcpy(&edge[0],p2,nbytes);
1434 memcpy(&edge[3],p1,nbytes);
1435 proclist[nrvous] = hashlittle(edge,2*nbytes,0) % nprocs;
1436 memcpy(inedge[nrvous].x1,p2,nbytes);
1437 memcpy(inedge[nrvous].x2,p1,nbytes);
1438 inedge[nrvous].which = 2;
1439 nrvous++;
1440
1441 memcpy(&edge[0],p2,nbytes);
1442 memcpy(&edge[3],p3,nbytes);
1443 proclist[nrvous] = hashlittle(edge,2*nbytes,0) % nprocs;
1444 memcpy(inedge[nrvous].x1,p2,nbytes);
1445 memcpy(inedge[nrvous].x2,p3,nbytes);
1446 inedge[nrvous].which = 1;
1447 nrvous++;
1448
1449 memcpy(&edge[0],p3,nbytes);
1450 memcpy(&edge[3],p2,nbytes);
1451 proclist[nrvous] = hashlittle(edge,2*nbytes,0) % nprocs;
1452 memcpy(inedge[nrvous].x1,p3,nbytes);
1453 memcpy(inedge[nrvous].x2,p2,nbytes);
1454 inedge[nrvous].which = 2;
1455 nrvous++;
1456
1457 memcpy(&edge[0],p3,nbytes);
1458 memcpy(&edge[3],p1,nbytes);
1459 proclist[nrvous] = hashlittle(edge,2*nbytes,0) % nprocs;
1460 memcpy(inedge[nrvous].x1,p3,nbytes);
1461 memcpy(inedge[nrvous].x2,p1,nbytes);
1462 inedge[nrvous].which = 1;
1463 nrvous++;
1464
1465 memcpy(&edge[0],p1,nbytes);
1466 memcpy(&edge[3],p3,nbytes);
1467 proclist[nrvous] = hashlittle(edge,2*nbytes,0) % nprocs;
1468 memcpy(inedge[nrvous].x1,p1,nbytes);
1469 memcpy(inedge[nrvous].x2,p3,nbytes);
1470 inedge[nrvous].which = 2;
1471 nrvous++;
1472 }
1473
1474 // perform rendezvous operation
1475 // each proc assigned subset of edges
1476 // receives all copies of edges, checks if count of each edge is valid
1477
1478 char *buf;
1479 int nout = comm->rendezvous(1,nrvous,(char *) inedge,sizeof(InRvousEdge),
1480 0,proclist,rendezvous_watertight_3d,
1481 0,buf,0,(void *) this);
1482
1483 memory->destroy(proclist);
1484 memory->destroy(inedge);
1485 }
1486
1487 /* ----------------------------------------------------------------------
1488 callback from rendezvous operation
1489 process points assigned to me
1490 inbuf = list of N Inbuf datums
1491 no outbuf
1492 ------------------------------------------------------------------------- */
1493
rendezvous_watertight_3d(int n,char * inbuf,int & flag,int * & proclist,char * & outbuf,void * ptr)1494 int Surf::rendezvous_watertight_3d(int n, char *inbuf, int &flag, int *&proclist,
1495 char *&outbuf, void *ptr)
1496 {
1497 Surf *sptr = (Surf *) ptr;
1498 Domain *domain = sptr->domain;
1499 Error *error = sptr->error;
1500 MPI_Comm world = sptr->world;
1501
1502 Surf::InRvousEdge *inedge = (Surf::InRvousEdge *) inbuf;
1503
1504 // hash all received end points
1505 // key = end point
1506 // value = 1 if first point, 2 if second point, 3 if both points
1507
1508 Surf::MyHash2Point phash;
1509 Surf::My2PointIt it;
1510
1511 // insert each edge into hash
1512 // should appear once in each direction
1513 // error if any duplicate edges
1514
1515 Surf::TwoPoint3d key;
1516 double *x1,*x2;
1517 int which,value;
1518
1519 int ndup = 0;
1520 for (int i = 0; i < n; i++) {
1521 x1 = inedge[i].x1; x2 = inedge[i].x2;
1522 key.pts[0] = x1[0]; key.pts[1] = x1[1]; key.pts[2] = x1[2];
1523 key.pts[3] = x2[0]; key.pts[4] = x2[1]; key.pts[5] = x2[2];
1524 which = inedge[i].which;
1525 if (phash.find(key) == phash.end()) phash[key] = which;
1526 else {
1527 value = phash[key];
1528 if (value == 3) ndup++; // edge already seen twice
1529 else if (value != which) phash[key] = 3; // this is flipped edge
1530 else ndup++; // value = which, this is duplicate edge
1531 }
1532 }
1533
1534 int alldup;
1535 MPI_Allreduce(&ndup,&alldup,1,MPI_INT,MPI_SUM,world);
1536 alldup /= 2; // avoid double counting
1537 if (alldup) {
1538 char str[128];
1539 sprintf(str,"Watertight check failed with %d duplicate edges",alldup);
1540 error->all(FLERR,str);
1541 }
1542
1543 // check that each edge has an inverted match(value = 3)
1544 // allow for exception if edge is on box face
1545
1546 double *boxlo = domain->boxlo;
1547 double *boxhi = domain->boxhi;
1548 double *pts;
1549
1550 int nbad = 0;
1551 for (it = phash.begin(); it != phash.end(); ++it) {
1552 if (it->second != 3) {
1553 pts = (double *) it->first.pts;
1554 if (Geometry::edge_on_hex_face(&pts[0],&pts[3],boxlo,boxhi) < 0) nbad++;
1555 }
1556 }
1557
1558 int allbad;
1559 MPI_Allreduce(&nbad,&allbad,1,MPI_INT,MPI_SUM,world);
1560 allbad /= 2; // avoid double counting
1561 if (nbad) {
1562 char str[128];
1563 sprintf(str,"Watertight check failed with %d unmatched edges",allbad);
1564 error->all(FLERR,str);
1565 }
1566
1567 // flag = 0: no second comm needed in rendezvous
1568
1569 flag = 0;
1570 return 0;
1571 }
1572
1573 /* ----------------------------------------------------------------------
1574 check if all points are inside or on surface of global simulation box
1575 called by ReadSurf for lines or triangles
1576 old = previous # of elements
1577 ------------------------------------------------------------------------- */
1578
check_point_inside(int old)1579 void Surf::check_point_inside(int old)
1580 {
1581 int nbad;
1582 double *x;
1583
1584 int dim = domain->dimension;
1585 double *boxlo = domain->boxlo;
1586 double *boxhi = domain->boxhi;
1587
1588 if (dim == 2) {
1589 Line *newlines;
1590 int n;
1591 if (distributed) {
1592 newlines = mylines;
1593 n = nown;
1594 } else {
1595 newlines = lines;
1596 n = nlocal;
1597 }
1598
1599 nbad = 0;
1600 for (int i = old; i < n; i++) {
1601 x = newlines[i].p1;
1602 if (x[0] < boxlo[0] || x[0] > boxhi[0] ||
1603 x[1] < boxlo[1] || x[1] > boxhi[1] ||
1604 x[2] < boxlo[2] || x[2] > boxhi[2]) nbad++;
1605 x = newlines[i].p2;
1606 if (x[0] < boxlo[0] || x[0] > boxhi[0] ||
1607 x[1] < boxlo[1] || x[1] > boxhi[1] ||
1608 x[2] < boxlo[2] || x[2] > boxhi[2]) nbad++;
1609 }
1610
1611 } else if (dim == 3) {
1612 Tri *newtris;
1613 int n;
1614 if (distributed) {
1615 newtris = mytris;
1616 n = nown;
1617 } else {
1618 newtris = tris;
1619 n = nlocal;
1620 }
1621
1622 nbad = 0;
1623 for (int i = old; i < n; i++) {
1624 x = newtris[i].p1;
1625 if (x[0] < boxlo[0] || x[0] > boxhi[0] ||
1626 x[1] < boxlo[1] || x[1] > boxhi[1] ||
1627 x[2] < boxlo[2] || x[2] > boxhi[2]) nbad++;
1628 x = newtris[i].p2;
1629 if (x[0] < boxlo[0] || x[0] > boxhi[0] ||
1630 x[1] < boxlo[1] || x[1] > boxhi[1] ||
1631 x[2] < boxlo[2] || x[2] > boxhi[2]) nbad++;
1632 x = newtris[i].p3;
1633 if (x[0] < boxlo[0] || x[0] > boxhi[0] ||
1634 x[1] < boxlo[1] || x[1] > boxhi[1] ||
1635 x[2] < boxlo[2] || x[2] > boxhi[2]) nbad++;
1636 }
1637 }
1638
1639 int nbadall;
1640 if (distributed) MPI_Allreduce(&nbad,&nbadall,1,MPI_INT,MPI_SUM,world);
1641 else nbadall = nbad;
1642
1643 if (nbadall) {
1644 char str[128];
1645 sprintf(str,"%d surface points are not inside simulation box",
1646 nbadall);
1647 error->all(FLERR,str);
1648 }
1649 }
1650
1651 /* ----------------------------------------------------------------------
1652 check nearness of all points to other lines in same cell
1653 error if point is on line, including duplicate point
1654 warn if closer than EPSILON_GRID = fraction of grid cell size
1655 NOTE: this can miss a close point/line pair in 2 different grid cells
1656 ------------------------------------------------------------------------- */
1657
check_point_near_surf_2d()1658 void Surf::check_point_near_surf_2d()
1659 {
1660 int i,j,n;
1661 surfint *csurfs;
1662 double side,epssq;
1663 double *p1,*p2,*lo,*hi;
1664 Surf::Line *line;
1665
1666 Surf::Line *lines = surf->lines;
1667 Grid::ChildCell *cells = grid->cells;
1668 int nglocal = grid->nlocal;
1669
1670 int nerror = 0;
1671 int nwarn = 0;
1672
1673 for (int icell = 0; icell < nglocal; icell++) {
1674 if (cells[icell].nsplit <= 0) continue;
1675 n = cells[icell].nsurf;
1676 if (n == 0) continue;
1677
1678 lo = cells[icell].lo;
1679 hi = cells[icell].hi;
1680 side = MIN(hi[0]-lo[0],hi[1]-lo[1]);
1681 epssq = (EPSILON_GRID*side) * (EPSILON_GRID*side);
1682
1683 csurfs = cells[icell].csurfs;
1684 for (i = 0; i < n; i++) {
1685 line = &lines[csurfs[i]];
1686 // skip transparent surf elements
1687 if (line->transparent) continue;
1688 for (j = 0; j < n; j++) {
1689 if (i == j) continue;
1690 p1 = lines[csurfs[j]].p1;
1691 p2 = lines[csurfs[j]].p2;
1692 point_line_compare(p1,line->p1,line->p2,epssq,nerror,nwarn);
1693 point_line_compare(p2,line->p1,line->p2,epssq,nerror,nwarn);
1694 }
1695 }
1696 }
1697
1698 int all;
1699 MPI_Allreduce(&nerror,&all,1,MPI_INT,MPI_SUM,world);
1700 if (all) {
1701 char str[128];
1702 sprintf(str,"Surface check failed with %d points on lines",all);
1703 error->all(FLERR,str);
1704 }
1705
1706 MPI_Allreduce(&nwarn,&all,1,MPI_INT,MPI_SUM,world);
1707 if (all) {
1708 char str[128];
1709 sprintf(str,"Surface check found %d points nearly on lines",all);
1710 if (comm->me == 0) error->warning(FLERR,str);
1711 }
1712 }
1713
1714 /* ----------------------------------------------------------------------
1715 check nearness of all points to other triangles in same cell
1716 error if point is on triangle, including duplicate point
1717 warn if closer than EPSILON_GRID = fraction of grid cell size
1718 NOTE: this can miss a close point/triangle pair in 2 different grid cells
1719 ------------------------------------------------------------------------- */
1720
check_point_near_surf_3d()1721 void Surf::check_point_near_surf_3d()
1722 {
1723 int i,j,n;
1724 surfint *csurfs;
1725 double side,epssq;
1726 double *p1,*p2,*p3,*lo,*hi;
1727 Surf::Tri *tri;
1728
1729 Surf::Tri *tris = surf->tris;
1730 Grid::ChildCell *cells = grid->cells;
1731 int nglocal = grid->nlocal;
1732
1733 int nerror = 0;
1734 int nwarn = 0;
1735
1736 for (int icell = 0; icell < nglocal; icell++) {
1737 if (cells[icell].nsplit <= 0) continue;
1738 n = cells[icell].nsurf;
1739 if (n == 0) continue;
1740
1741 lo = cells[icell].lo;
1742 hi = cells[icell].hi;
1743 side = MIN(hi[0]-lo[0],hi[1]-lo[1]);
1744 side = MIN(side,hi[2]-lo[2]);
1745 epssq = (EPSILON_GRID*side) * (EPSILON_GRID*side);
1746
1747 csurfs = cells[icell].csurfs;
1748 for (i = 0; i < n; i++) {
1749 tri = &tris[csurfs[i]];
1750 // skip transparent surf elements
1751 if (tri->transparent) continue;
1752 for (j = 0; j < n; j++) {
1753 if (i == j) continue;
1754 p1 = tris[csurfs[j]].p1;
1755 p2 = tris[csurfs[j]].p2;
1756 p3 = tris[csurfs[j]].p3;
1757 point_tri_compare(p1,tri->p1,tri->p2,tri->p3,tri->norm,
1758 epssq,nerror,nwarn,icell,csurfs[i],csurfs[j]);
1759 point_tri_compare(p2,tri->p1,tri->p2,tri->p3,tri->norm,
1760 epssq,nerror,nwarn,icell,csurfs[i],csurfs[j]);
1761 point_tri_compare(p3,tri->p1,tri->p2,tri->p3,tri->norm,
1762 epssq,nerror,nwarn,icell,csurfs[i],csurfs[j]);
1763 }
1764 }
1765 }
1766
1767 int all;
1768 MPI_Allreduce(&nerror,&all,1,MPI_INT,MPI_SUM,world);
1769 if (all) {
1770 char str[128];
1771 sprintf(str,"Surface check failed with %d points on triangles",all);
1772 error->all(FLERR,str);
1773 }
1774
1775 MPI_Allreduce(&nwarn,&all,1,MPI_INT,MPI_SUM,world);
1776 if (all) {
1777 char str[128];
1778 sprintf(str,"Surface check found %d points nearly on triangles",all);
1779 if (comm->me == 0) error->warning(FLERR,str);
1780 }
1781 }
1782
1783 /* ----------------------------------------------------------------------
1784 compute extent of read-in surfs, including geometric transformations
1785 ------------------------------------------------------------------------- */
1786
output_extent(int old)1787 void Surf::output_extent(int old)
1788 {
1789 // extent of surfs after geometric transformations
1790 // compute sizes of smallest surface elements
1791
1792 double extent[3][2],extentall[3][2];
1793 extent[0][0] = extent[1][0] = extent[2][0] = BIG;
1794 extent[0][1] = extent[1][1] = extent[2][1] = -BIG;
1795
1796 int dim = domain->dimension;
1797
1798 if (dim == 2) {
1799 Line *newlines;
1800 int n;
1801 if (!implicit && distributed) {
1802 newlines = mylines;
1803 n = nown;
1804 } else {
1805 newlines = lines;
1806 n = nlocal;
1807 }
1808
1809 for (int i = old; i < n; i++) {
1810 for (int j = 0; j < 3; j++) {
1811 extent[j][0] = MIN(extent[j][0],newlines[i].p1[j]);
1812 extent[j][0] = MIN(extent[j][0],newlines[i].p2[j]);
1813 extent[j][1] = MAX(extent[j][1],newlines[i].p1[j]);
1814 extent[j][1] = MAX(extent[j][1],newlines[i].p2[j]);
1815 }
1816 }
1817
1818 } else {
1819 Tri *newtris;
1820 int n;
1821 if (!implicit && distributed) {
1822 newtris = mytris;
1823 n = nown;
1824 } else {
1825 newtris = tris;
1826 n = nlocal;
1827 }
1828
1829 for (int i = old; i < n; i++) {
1830 for (int j = 0; j < 3; j++) {
1831 extent[j][0] = MIN(extent[j][0],newtris[i].p1[j]);
1832 extent[j][0] = MIN(extent[j][0],newtris[i].p2[j]);
1833 extent[j][0] = MIN(extent[j][0],newtris[i].p3[j]);
1834 extent[j][1] = MAX(extent[j][1],newtris[i].p1[j]);
1835 extent[j][1] = MAX(extent[j][1],newtris[i].p2[j]);
1836 extent[j][1] = MAX(extent[j][1],newtris[i].p3[j]);
1837 }
1838 }
1839 }
1840
1841 extent[0][0] = -extent[0][0];
1842 extent[1][0] = -extent[1][0];
1843 extent[2][0] = -extent[2][0];
1844 MPI_Allreduce(extent,extentall,6,MPI_DOUBLE,MPI_MAX,world);
1845 extentall[0][0] = -extentall[0][0];
1846 extentall[1][0] = -extentall[1][0];
1847 extentall[2][0] = -extentall[2][0];
1848
1849 double minlen,minarea;
1850 if (dim == 2) minlen = shortest_line(old);
1851 if (dim == 3) smallest_tri(old,minlen,minarea);
1852
1853 if (comm->me == 0) {
1854 if (screen) {
1855 fprintf(screen," %g %g xlo xhi\n",extentall[0][0],extentall[0][1]);
1856 fprintf(screen," %g %g ylo yhi\n",extentall[1][0],extentall[1][1]);
1857 fprintf(screen," %g %g zlo zhi\n",extentall[2][0],extentall[2][1]);
1858 if (dim == 2)
1859 fprintf(screen," %g min line length\n",minlen);
1860 if (dim == 3) {
1861 fprintf(screen," %g min triangle edge length\n",minlen);
1862 fprintf(screen," %g min triangle area\n",minarea);
1863 }
1864 }
1865 if (logfile) {
1866 fprintf(logfile," %g %g xlo xhi\n",extentall[0][0],extentall[0][1]);
1867 fprintf(logfile," %g %g ylo yhi\n",extentall[1][0],extentall[1][1]);
1868 fprintf(logfile," %g %g zlo zhi\n",extentall[2][0],extentall[2][1]);
1869 if (dim == 2)
1870 fprintf(logfile," %g min line length\n",minlen);
1871 if (dim == 3) {
1872 fprintf(logfile," %g min triangle edge length\n",minlen);
1873 fprintf(logfile," %g min triangle area\n",minarea);
1874 }
1875 }
1876 }
1877 }
1878
1879 /* ----------------------------------------------------------------------
1880 return shortest line length
1881 ------------------------------------------------------------------------- */
1882
shortest_line(int old)1883 double Surf::shortest_line(int old)
1884 {
1885 double len = BIG;
1886
1887 if (!implicit && distributed) {
1888 for (int i = old; i < nown; i++)
1889 len = MIN(len,line_size(&mylines[i]));
1890 } else {
1891 for (int i = old; i < nlocal; i++)
1892 len = MIN(len,line_size(&lines[i]));
1893 }
1894
1895 double lenall;
1896 MPI_Allreduce(&len,&lenall,1,MPI_DOUBLE,MPI_MIN,world);
1897
1898 return lenall;
1899 }
1900
1901 /* ----------------------------------------------------------------------
1902 return shortest tri edge and smallest tri area
1903 ------------------------------------------------------------------------- */
1904
smallest_tri(int old,double & lenall,double & areaall)1905 void Surf::smallest_tri(int old, double &lenall, double &areaall)
1906 {
1907 double lenone,areaone;
1908 double len = BIG;
1909 double area = BIG;
1910
1911 if (!implicit && distributed) {
1912 for (int i = old; i < nown; i++) {
1913 areaone = tri_size(&mytris[i],lenone);
1914 len = MIN(len,lenone);
1915 area = MIN(area,areaone);
1916 }
1917 } else {
1918 for (int i = old; i < nlocal; i++) {
1919 areaone = tri_size(&tris[i],lenone);
1920 len = MIN(len,lenone);
1921 area = MIN(area,areaone);
1922 }
1923 }
1924
1925 MPI_Allreduce(&len,&lenall,1,MPI_DOUBLE,MPI_MIN,world);
1926 MPI_Allreduce(&area,&areaall,1,MPI_DOUBLE,MPI_MIN,world);
1927 }
1928
1929 /* ----------------------------------------------------------------------
1930 compute distance bewteen a point and line
1931 just return if point is an endpoint of line
1932 increment nerror if point on line
1933 increment nwarn if point is within epssq distance of line
1934 ------------------------------------------------------------------------- */
1935
point_line_compare(double * pt,double * p1,double * p2,double epssq,int & nerror,int & nwarn)1936 void Surf::point_line_compare(double *pt, double *p1, double *p2,
1937 double epssq, int &nerror, int &nwarn)
1938 {
1939 if (pt[0] == p1[0] && pt[1] == p1[1]) return;
1940 if (pt[0] == p2[0] && pt[1] == p2[1]) return;
1941 double rsq = Geometry::distsq_point_line(pt,p1,p2);
1942 if (rsq == 0.0) nerror++;
1943 else if (rsq < epssq) nwarn++;
1944 }
1945
1946 /* ----------------------------------------------------------------------
1947 compute distance bewteen a point and triangle
1948 just return if point is an endpoint of triangle
1949 increment nerror if point on triangle
1950 increment nwarn if point is within epssq distance of triangle
1951 ------------------------------------------------------------------------- */
1952
point_tri_compare(double * pt,double * p1,double * p2,double * p3,double * norm,double epssq,int & nerror,int & nwarn,int,int,int)1953 void Surf::point_tri_compare(double *pt, double *p1, double *p2, double *p3,
1954 double *norm, double epssq, int &nerror, int &nwarn,
1955 int, int, int)
1956 {
1957 if (pt[0] == p1[0] && pt[1] == p1[1] && pt[2] == p1[2]) return;
1958 if (pt[0] == p2[0] && pt[1] == p2[1] && pt[2] == p2[2]) return;
1959 if (pt[0] == p3[0] && pt[1] == p3[1] && pt[2] == p3[2]) return;
1960 double rsq = Geometry::distsq_point_tri(pt,p1,p2,p3,norm);
1961 if (rsq == 0.0) nerror++;
1962 else if (rsq < epssq) nwarn++;
1963 }
1964
1965
1966 /* ----------------------------------------------------------------------
1967 add a surface collision model
1968 ------------------------------------------------------------------------- */
1969
add_collide(int narg,char ** arg)1970 void Surf::add_collide(int narg, char **arg)
1971 {
1972 if (narg < 2) error->all(FLERR,"Illegal surf_collide command");
1973
1974 // error check
1975
1976 for (int i = 0; i < nsc; i++)
1977 if (strcmp(arg[0],sc[i]->id) == 0)
1978 error->all(FLERR,"Reuse of surf_collide ID");
1979
1980 // extend SurfCollide list if necessary
1981
1982 if (nsc == maxsc) {
1983 maxsc += DELTAMODEL;
1984 sc = (SurfCollide **)
1985 memory->srealloc(sc,maxsc*sizeof(SurfCollide *),"surf:sc");
1986 }
1987
1988 // create new SurfCollide class
1989
1990 if (sparta->suffix_enable) {
1991 if (sparta->suffix) {
1992 char estyle[256];
1993 sprintf(estyle,"%s/%s",arg[1],sparta->suffix);
1994
1995 if (0) return;
1996
1997 #define SURF_COLLIDE_CLASS
1998 #define SurfCollideStyle(key,Class) \
1999 else if (strcmp(estyle,#key) == 0) { \
2000 sc[nsc] = new Class(sparta,narg,arg); \
2001 nsc++; \
2002 return; \
2003 }
2004 #include "style_surf_collide.h"
2005 #undef SurfCollideStyle
2006 #undef SURF_COLLIDE_CLASS
2007 }
2008 }
2009
2010 if (0) return;
2011
2012 #define SURF_COLLIDE_CLASS
2013 #define SurfCollideStyle(key,Class) \
2014 else if (strcmp(arg[1],#key) == 0) \
2015 sc[nsc] = new Class(sparta,narg,arg);
2016 #include "style_surf_collide.h"
2017 #undef SurfCollideStyle
2018 #undef SURF_COLLIDE_CLASS
2019
2020 else error->all(FLERR,"Unrecognized surf_collide style");
2021
2022 nsc++;
2023 }
2024
2025 /* ----------------------------------------------------------------------
2026 find a surface collide model by ID
2027 return index of surf collide model or -1 if not found
2028 ------------------------------------------------------------------------- */
2029
find_collide(const char * id)2030 int Surf::find_collide(const char *id)
2031 {
2032 int isc;
2033 for (isc = 0; isc < nsc; isc++)
2034 if (strcmp(id,sc[isc]->id) == 0) break;
2035 if (isc == nsc) return -1;
2036 return isc;
2037 }
2038
2039 /* ----------------------------------------------------------------------
2040 add a surface reaction model
2041 ------------------------------------------------------------------------- */
2042
add_react(int narg,char ** arg)2043 void Surf::add_react(int narg, char **arg)
2044 {
2045 if (narg < 2) error->all(FLERR,"Illegal surf_react command");
2046
2047 // error check
2048
2049 for (int i = 0; i < nsr; i++)
2050 if (strcmp(arg[0],sr[i]->id) == 0)
2051 error->all(FLERR,"Reuse of surf_react ID");
2052
2053 // extend SurfReact list if necessary
2054
2055 if (nsr == maxsr) {
2056 maxsr += DELTAMODEL;
2057 sr = (SurfReact **)
2058 memory->srealloc(sr,maxsr*sizeof(SurfReact *),"surf:sr");
2059 }
2060
2061 // create new SurfReact class
2062
2063 if (0) return;
2064
2065 #define SURF_REACT_CLASS
2066 #define SurfReactStyle(key,Class) \
2067 else if (strcmp(arg[1],#key) == 0) \
2068 sr[nsr] = new Class(sparta,narg,arg);
2069 #include "style_surf_react.h"
2070 #undef SurfReactStyle
2071 #undef SURF_REACT_CLASS
2072
2073 else error->all(FLERR,"Unrecognized surf_react style");
2074
2075 nsr++;
2076 }
2077
2078 /* ----------------------------------------------------------------------
2079 find a surface reaction model by ID
2080 return index of surf reaction model or -1 if not found
2081 ------------------------------------------------------------------------- */
2082
find_react(const char * id)2083 int Surf::find_react(const char *id)
2084 {
2085 int isr;
2086 for (isr = 0; isr < nsr; isr++)
2087 if (strcmp(id,sr[isr]->id) == 0) break;
2088 if (isr == nsr) return -1;
2089 return isr;
2090 }
2091
2092 /* ----------------------------------------------------------------------
2093 group surf command called via input script
2094 NOTE: need to apply this also to mylines and mytris ??
2095 ------------------------------------------------------------------------- */
2096
group(int narg,char ** arg)2097 void Surf::group(int narg, char **arg)
2098 {
2099 int i,flag;
2100 double x[3];
2101
2102 if (narg < 3) error->all(FLERR,"Illegal group command");
2103
2104 int dim = domain->dimension;
2105
2106 int igroup = find_group(arg[0]);
2107 if (igroup < 0) igroup = add_group(arg[0]);
2108 int bit = bitmask[igroup];
2109
2110 // style = type or id
2111 // add surf to group if matches types/ids or condition
2112
2113 if (strcmp(arg[2],"type") == 0 || strcmp(arg[2],"id") == 0) {
2114 if (narg < 4) error->all(FLERR,"Illegal group command");
2115
2116 int category;
2117 if (strcmp(arg[2],"type") == 0) category = TYPE;
2118 else if (strcmp(arg[2],"id") == 0) category = ID;
2119
2120 // args = logical condition
2121
2122 if (narg > 4 &&
2123 (strcmp(arg[3],"<") == 0 || strcmp(arg[3],">") == 0 ||
2124 strcmp(arg[3],"<=") == 0 || strcmp(arg[3],">=") == 0 ||
2125 strcmp(arg[3],"==") == 0 || strcmp(arg[3],"!=") == 0 ||
2126 strcmp(arg[3],"<>") == 0)) {
2127
2128 int condition = -1;
2129 if (strcmp(arg[3],"<") == 0) condition = LT;
2130 else if (strcmp(arg[3],"<=") == 0) condition = LE;
2131 else if (strcmp(arg[3],">") == 0) condition = GT;
2132 else if (strcmp(arg[3],">=") == 0) condition = GE;
2133 else if (strcmp(arg[3],"==") == 0) condition = EQ;
2134 else if (strcmp(arg[3],"!=") == 0) condition = NEQ;
2135 else if (strcmp(arg[3],"<>") == 0) condition = BETWEEN;
2136 else error->all(FLERR,"Illegal group command");
2137
2138 int bound1,bound2;
2139 bound1 = input->inumeric(FLERR,arg[4]);
2140 bound2 = -1;
2141
2142 if (condition == BETWEEN) {
2143 if (narg != 6) error->all(FLERR,"Illegal group command");
2144 bound2 = input->inumeric(FLERR,arg[5]);
2145 } else if (narg != 5) error->all(FLERR,"Illegal group command");
2146
2147 // add surf to group if meets condition
2148
2149 if (category == ID) {
2150 if (condition == LT) {
2151 if (dim == 2) {
2152 for (i = 0; i < nlocal+nghost; i++)
2153 if (lines[i].id < bound1) lines[i].mask |= bit;
2154 } else {
2155 for (i = 0; i < nlocal+nghost; i++)
2156 if (tris[i].id < bound1) tris[i].mask |= bit;
2157 }
2158 } else if (condition == LE) {
2159 if (dim == 2) {
2160 for (i = 0; i < nlocal+nghost; i++)
2161 if (lines[i].id <= bound1) lines[i].mask |= bit;
2162 } else {
2163 for (i = 0; i < nlocal+nghost; i++)
2164 if (tris[i].id <= bound1) tris[i].mask |= bit;
2165 }
2166 } else if (condition == GT) {
2167 if (dim == 2) {
2168 for (i = 0; i < nlocal+nghost; i++)
2169 if (lines[i].id > bound1) lines[i].mask |= bit;
2170 } else {
2171 for (i = 0; i < nlocal+nghost; i++)
2172 if (tris[i].id > bound1) tris[i].mask |= bit;
2173 }
2174 } else if (condition == GE) {
2175 if (dim == 2) {
2176 for (i = 0; i < nlocal+nghost; i++)
2177 if (lines[i].id >= bound1) lines[i].mask |= bit;
2178 } else {
2179 for (i = 0; i < nlocal+nghost; i++)
2180 if (tris[i].id >= bound1) tris[i].mask |= bit;
2181 }
2182 } else if (condition == EQ) {
2183 if (dim == 2) {
2184 for (i = 0; i < nlocal+nghost; i++)
2185 if (lines[i].id == bound1) lines[i].mask |= bit;
2186 } else {
2187 for (i = 0; i < nlocal+nghost; i++)
2188 if (tris[i].id == bound1) tris[i].mask |= bit;
2189 }
2190 } else if (condition == NEQ) {
2191 if (dim == 2) {
2192 for (i = 0; i < nlocal+nghost; i++)
2193 if (lines[i].id != bound1) lines[i].mask |= bit;
2194 } else {
2195 for (i = 0; i < nlocal+nghost; i++)
2196 if (tris[i].id != bound1) tris[i].mask |= bit;
2197 }
2198 } else if (condition == BETWEEN) {
2199 if (dim == 2) {
2200 for (i = 0; i < nlocal+nghost; i++)
2201 if (lines[i].id >= bound1 && lines[i].id <= bound2)
2202 lines[i].mask |= bit;
2203 } else {
2204 for (i = 0; i < nlocal+nghost; i++)
2205 if (tris[i].id >= bound1 && tris[i].id <= bound2)
2206 tris[i].mask |= bit;
2207 }
2208 }
2209 } else if (category == TYPE) {
2210 if (condition == LT) {
2211 if (dim == 2) {
2212 for (i = 0; i < nlocal+nghost; i++)
2213 if (lines[i].type < bound1) lines[i].mask |= bit;
2214 } else {
2215 for (i = 0; i < nlocal+nghost; i++)
2216 if (tris[i].type < bound1) lines[i].mask |= bit;
2217 }
2218 } else if (condition == LE) {
2219 if (dim == 2) {
2220 for (i = 0; i < nlocal+nghost; i++)
2221 if (lines[i].type <= bound1) lines[i].mask |= bit;
2222 } else {
2223 for (i = 0; i < nlocal+nghost; i++)
2224 if (tris[i].type <= bound1) lines[i].mask |= bit;
2225 }
2226 } else if (condition == GT) {
2227 if (dim == 2) {
2228 for (i = 0; i < nlocal+nghost; i++)
2229 if (lines[i].type > bound1) lines[i].mask |= bit;
2230 } else {
2231 for (i = 0; i < nlocal+nghost; i++)
2232 if (tris[i].type > bound1) lines[i].mask |= bit;
2233 }
2234 } else if (condition == GE) {
2235 if (dim == 2) {
2236 for (i = 0; i < nlocal+nghost; i++)
2237 if (lines[i].type >= bound1) lines[i].mask |= bit;
2238 } else {
2239 for (i = 0; i < nlocal+nghost; i++)
2240 if (tris[i].type >= bound1) lines[i].mask |= bit;
2241 }
2242 } else if (condition == EQ) {
2243 if (dim == 2) {
2244 for (i = 0; i < nlocal+nghost; i++)
2245 if (lines[i].type == bound1) lines[i].mask |= bit;
2246 } else {
2247 for (i = 0; i < nlocal+nghost; i++)
2248 if (tris[i].type == bound1) lines[i].mask |= bit;
2249 }
2250 } else if (condition == NEQ) {
2251 if (dim == 2) {
2252 for (i = 0; i < nlocal+nghost; i++)
2253 if (lines[i].type != bound1) lines[i].mask |= bit;
2254 } else {
2255 for (i = 0; i < nlocal+nghost; i++)
2256 if (tris[i].type != bound1) lines[i].mask |= bit;
2257 }
2258 } else if (condition == BETWEEN) {
2259 if (dim == 2) {
2260 for (i = 0; i < nlocal+nghost; i++)
2261 if (lines[i].type >= bound1 && lines[i].type <= bound2)
2262 lines[i].mask |= bit;
2263 } else {
2264 for (i = 0; i < nlocal+nghost; i++)
2265 if (tris[i].type >= bound1 && tris[i].type <= bound2)
2266 tris[i].mask |= bit;
2267 }
2268 }
2269 }
2270
2271 // args = list of values
2272
2273 } else {
2274 char *ptr;
2275 int start,stop;
2276
2277 for (int iarg = 3; iarg < narg; iarg++) {
2278 if (strchr(arg[iarg],':')) {
2279 ptr = strchr(arg[iarg],':');
2280 *ptr = '\0';
2281 start = input->inumeric(FLERR,arg[iarg]);
2282 *ptr = ':';
2283 stop = input->inumeric(FLERR,ptr+1);
2284 } else {
2285 start = stop = input->inumeric(FLERR,arg[iarg]);
2286 }
2287
2288 // add surf to group if type/id matches value or sequence
2289
2290 if (category == ID) {
2291 if (dim == 2) {
2292 for (i = 0; i < nlocal+nghost; i++)
2293 if (lines[i].id >= start && lines[i].id <= stop)
2294 lines[i].mask |= bit;
2295 } else {
2296 for (i = 0; i < nlocal+nghost; i++)
2297 if (tris[i].id >= start && tris[i].id <= stop)
2298 tris[i].mask |= bit;
2299 }
2300 } else if (category == TYPE) {
2301 if (dim == 2) {
2302 for (i = 0; i < nlocal+nghost; i++)
2303 if (lines[i].type >= start && lines[i].type <= stop)
2304 lines[i].mask |= bit;
2305 } else {
2306 for (i = 0; i < nlocal+nghost; i++)
2307 if (tris[i].type >= start && tris[i].type <= stop)
2308 tris[i].mask |= bit;
2309 }
2310 }
2311 }
2312 }
2313
2314 // style = region
2315 // add surf to group if in region
2316
2317 } else if (strcmp(arg[2],"region") == 0) {
2318 if (narg != 5) error->all(FLERR,"Illegal group command");
2319 int iregion = domain->find_region(arg[3]);
2320 if (iregion == -1) error->all(FLERR,"Group region ID does not exist");
2321 Region *region = domain->regions[iregion];
2322
2323 int rstyle;
2324 if (strcmp(arg[4],"all") == 0) rstyle = REGION_ALL;
2325 else if (strcmp(arg[4],"one") == 0) rstyle = REGION_ONE;
2326 else if (strcmp(arg[4],"center") == 0) rstyle = REGION_CENTER;
2327 else error->all(FLERR,"Illegal group command");
2328
2329 if (dim == 2) {
2330 if (rstyle == REGION_ALL) {
2331 for (i = 0; i < nlocal+nghost; i++) {
2332 flag = 1;
2333 if (!region->match(lines[i].p1)) flag = 0;
2334 if (!region->match(lines[i].p2)) flag = 0;
2335 if (flag) lines[i].mask |= bit;
2336 }
2337 } else if (rstyle == REGION_ONE) {
2338 for (i = 0; i < nlocal+nghost; i++) {
2339 flag = 0;
2340 if (region->match(lines[i].p1)) flag = 1;
2341 if (region->match(lines[i].p2)) flag = 1;
2342 if (flag) lines[i].mask |= bit;
2343 }
2344 } else if (rstyle == REGION_CENTER) {
2345 for (i = 0; i < nlocal+nghost; i++) {
2346 x[0] = 0.5 * (lines[i].p1[0] + lines[i].p2[0]);
2347 x[1] = 0.5 * (lines[i].p1[1] + lines[i].p2[1]);
2348 x[2] = 0.0;
2349 if (region->match(x)) lines[i].mask |= bit;
2350 }
2351 }
2352
2353 } else if (dim == 3) {
2354 if (rstyle == REGION_ALL) {
2355 for (i = 0; i < nlocal+nghost; i++) {
2356 flag = 1;
2357 if (!region->match(tris[i].p1)) flag = 0;
2358 if (!region->match(tris[i].p2)) flag = 0;
2359 if (!region->match(tris[i].p3)) flag = 0;
2360 if (flag) tris[i].mask |= bit;
2361 }
2362 } else if (rstyle == REGION_ONE) {
2363 for (i = 0; i < nlocal+nghost; i++) {
2364 flag = 0;
2365 if (region->match(tris[i].p1)) flag = 1;
2366 if (region->match(tris[i].p2)) flag = 1;
2367 if (region->match(tris[i].p3)) flag = 1;
2368 if (flag) tris[i].mask |= bit;
2369 }
2370 } else if (rstyle == REGION_CENTER) {
2371 for (i = 0; i < nlocal+nghost; i++) {
2372 x[0] = (tris[i].p1[0] + tris[i].p2[0] + tris[i].p3[0]) / 3.0;
2373 x[1] = (tris[i].p1[1] + tris[i].p2[1] + tris[i].p3[1]) / 3.0;
2374 x[2] = (tris[i].p1[2] + tris[i].p2[2] + tris[i].p3[2]) / 3.0;
2375 if (region->match(x)) tris[i].mask |= bit;
2376 }
2377 }
2378 }
2379
2380 // style = subtract
2381
2382 } else if (strcmp(arg[2],"subtract") == 0) {
2383 if (narg < 5) error->all(FLERR,"Illegal group command");
2384
2385 int length = narg-3;
2386 int *list = new int[length];
2387
2388 int jgroup;
2389 for (int iarg = 3; iarg < narg; iarg++) {
2390 jgroup = find_group(arg[iarg]);
2391 if (jgroup == -1) error->all(FLERR,"Group ID does not exist");
2392 list[iarg-3] = jgroup;
2393 }
2394
2395 // add to group if in 1st group in list
2396
2397 int otherbit = bitmask[list[0]];
2398
2399 if (dim == 2) {
2400 for (i = 0; i < nlocal+nghost; i++)
2401 if (lines[i].mask & otherbit) lines[i].mask |= bit;
2402 } else {
2403 for (i = 0; i < nlocal+nghost; i++)
2404 if (tris[i].mask & otherbit) tris[i].mask |= bit;
2405 }
2406
2407 // remove surfs if they are in any of the other groups
2408 // AND with inverse mask removes the surf from group
2409
2410 int inverse = inversemask[igroup];
2411
2412 for (int ilist = 1; ilist < length; ilist++) {
2413 otherbit = bitmask[list[ilist]];
2414 if (dim == 2) {
2415 for (i = 0; i < nlocal+nghost; i++)
2416 if (lines[i].mask & otherbit) lines[i].mask &= inverse;
2417 } else {
2418 for (i = 0; i < nlocal+nghost; i++)
2419 if (tris[i].mask & otherbit) tris[i].mask &= inverse;
2420 }
2421 }
2422
2423 delete [] list;
2424
2425 // style = union
2426
2427 } else if (strcmp(arg[2],"union") == 0) {
2428 if (narg < 4) error->all(FLERR,"Illegal group command");
2429
2430 int length = narg-3;
2431 int *list = new int[length];
2432
2433 int jgroup;
2434 for (int iarg = 3; iarg < narg; iarg++) {
2435 jgroup = find_group(arg[iarg]);
2436 if (jgroup == -1) error->all(FLERR,"Group ID does not exist");
2437 list[iarg-3] = jgroup;
2438 }
2439
2440 // add to group if in any other group in list
2441
2442 int otherbit;
2443
2444 for (int ilist = 0; ilist < length; ilist++) {
2445 otherbit = bitmask[list[ilist]];
2446 if (dim == 2) {
2447 for (i = 0; i < nlocal+nghost; i++)
2448 if (lines[i].mask & otherbit) lines[i].mask |= bit;
2449 } else {
2450 for (i = 0; i < nlocal+nghost; i++)
2451 if (tris[i].mask & otherbit) tris[i].mask |= bit;
2452 }
2453 }
2454
2455 delete [] list;
2456
2457 // style = intersect
2458
2459 } else if (strcmp(arg[2],"intersect") == 0) {
2460 if (narg < 5) error->all(FLERR,"Illegal group command");
2461
2462 int length = narg-3;
2463 int *list = new int[length];
2464
2465 int jgroup;
2466 for (int iarg = 3; iarg < narg; iarg++) {
2467 jgroup = find_group(arg[iarg]);
2468 if (jgroup == -1) error->all(FLERR,"Group ID does not exist");
2469 list[iarg-3] = jgroup;
2470 }
2471
2472 // add to group if in all groups in list
2473
2474 int otherbit,ok,ilist;
2475
2476 if (dim == 2) {
2477 for (i = 0; i < nlocal+nghost; i++) {
2478 ok = 1;
2479 for (ilist = 0; ilist < length; ilist++) {
2480 otherbit = bitmask[list[ilist]];
2481 if ((lines[i].mask & otherbit) == 0) ok = 0;
2482 }
2483 if (ok) lines[i].mask |= bit;
2484 }
2485 } else {
2486 for (i = 0; i < nlocal+nghost; i++) {
2487 ok = 1;
2488 for (ilist = 0; ilist < length; ilist++) {
2489 otherbit = bitmask[list[ilist]];
2490 if ((tris[i].mask & otherbit) == 0) ok = 0;
2491 }
2492 if (ok) tris[i].mask |= bit;
2493 }
2494 }
2495
2496 delete [] list;
2497
2498 // style = clear
2499 // remove all surfs from group
2500
2501 } else if (strcmp(arg[2],"clear") == 0) {
2502 if (igroup == 0) error->all(FLERR,"Cannot clear group all");
2503 int inversebits = inversemask[igroup];
2504
2505 if (dim == 2) {
2506 for (i = 0; i < nlocal+nghost; i++) lines[i].mask &= inversebits;
2507 } else {
2508 for (i = 0; i < nlocal+nghost; i++) tris[i].mask &= inversebits;
2509 }
2510 }
2511
2512 // print stats for changed group
2513
2514 bigint n = 0;
2515 if (dim == 2) {
2516 for (i = 0; i < nlocal; i++)
2517 if (lines[i].mask & bit) n++;
2518 } else {
2519 for (i = 0; i < nlocal; i++)
2520 if (tris[i].mask & bit) n++;
2521 }
2522
2523 bigint nall;
2524 if (distributed) MPI_Allreduce(&n,&nall,1,MPI_SPARTA_BIGINT,MPI_SUM,world);
2525 else nall = n;
2526
2527 if (comm->me == 0) {
2528 if (screen)
2529 fprintf(screen,BIGINT_FORMAT " surfaces in group %s\n",
2530 nall,gnames[igroup]);
2531 if (logfile)
2532 fprintf(logfile,BIGINT_FORMAT " surfaces in group %s\n",
2533 nall,gnames[igroup]);
2534 }
2535 }
2536
2537 /* ----------------------------------------------------------------------
2538 add a new surface group ID, assumed to be unique
2539 ------------------------------------------------------------------------- */
2540
add_group(const char * id)2541 int Surf::add_group(const char *id)
2542 {
2543 if (ngroup == MAXGROUP)
2544 error->all(FLERR,"Cannot have more than 32 surface groups");
2545
2546 int n = strlen(id) + 1;
2547 gnames[ngroup] = new char[n];
2548 strcpy(gnames[ngroup],id);
2549
2550 for (int i = 0; i < n-1; i++)
2551 if (!isalnum(id[i]) && id[i] != '_')
2552 error->all(FLERR,"Group ID must be alphanumeric or "
2553 "underscore characters");
2554
2555 ngroup++;
2556 return ngroup-1;
2557 }
2558
2559 /* ----------------------------------------------------------------------
2560 find a surface group ID
2561 return index of group or -1 if not found
2562 ------------------------------------------------------------------------- */
2563
find_group(const char * id)2564 int Surf::find_group(const char *id)
2565 {
2566 int igroup;
2567 for (igroup = 0; igroup < ngroup; igroup++)
2568 if (strcmp(id,gnames[igroup]) == 0) break;
2569 if (igroup == ngroup) return -1;
2570 return igroup;
2571 }
2572
2573 /* ----------------------------------------------------------------------
2574 compress owned explicit distributed surfs to account for deleted grid cells
2575 either due to load-balancing migration or grid adapt coarsening
2576 called from Comm::migrate_cells() and AdaptGrid::coarsen()
2577 AFTER grid cells are compressed
2578 discard nlocal surfs that are no longer referenced by owned grid cells
2579 use hash to store referenced surfs
2580 only called for explicit distributed surfs
2581 ------------------------------------------------------------------------- */
2582
compress_explicit()2583 void Surf::compress_explicit()
2584 {
2585 int i,m,ns;
2586 surfint *csurfs;
2587
2588 int dim = domain->dimension;
2589
2590 // keep = 1 if a local surf is referenced by a compressed local grid cell
2591
2592 int *keep;
2593 memory->create(keep,nlocal,"surf:keep");
2594 for (i = 0; i < nlocal; i++) keep[i] = 0;
2595
2596 // convert grid cell csurfs to surf IDs so can reset after surf compression
2597 // skip cells with no surfs or sub-cells
2598
2599 Grid::ChildCell *cells = grid->cells;
2600 int nglocal = grid->nlocal;
2601
2602 for (i = 0; i < nglocal; i++) {
2603 if (!cells[i].nsurf) continue;
2604 if (cells[i].nsplit <= 0) continue;
2605 csurfs = cells[i].csurfs;
2606 ns = cells[i].nsurf;
2607 if (dim == 2) {
2608 for (m = 0; m < ns; m++) {
2609 keep[csurfs[m]] = 1;
2610 csurfs[m] = lines[csurfs[m]].id;
2611 }
2612 } else {
2613 for (m = 0; m < ns; m++) {
2614 keep[csurfs[m]] = 1;
2615 csurfs[m] = tris[csurfs[m]].id;
2616 }
2617 }
2618 }
2619
2620 // compress nlocal surfs based on keep flags
2621
2622 m = 0;
2623 while (i < nlocal) {
2624 if (!keep[i]) {
2625 if (dim == 2) memcpy(&lines[i],&lines[nlocal-1],sizeof(Line));
2626 else memcpy(&tris[i],&tris[nlocal-1],sizeof(Tri));
2627 keep[i] = keep[nlocal-1];
2628 nlocal--;
2629 } else i++;
2630 }
2631
2632 memory->destroy(keep);
2633
2634 // reset grid cell csurfs IDs back to local surf indices
2635 // hash compressed surf list, then clear hash
2636 // skip cells with no surfs or sub-cells
2637
2638 rehash();
2639
2640 for (i = 0; i < nglocal; i++) {
2641 if (!cells[i].nsurf) continue;
2642 if (cells[i].nsplit <= 0) continue;
2643 csurfs = cells[i].csurfs;
2644 ns = cells[i].nsurf;
2645 for (m = 0; m < ns; m++) csurfs[m] = (*hash)[csurfs[m]];
2646 }
2647
2648 hash->clear();
2649 hashfilled = 0;
2650 }
2651
2652 /* ----------------------------------------------------------------------
2653 compress owned implicit surfs to account for migrating grid cells
2654 called from Comm::migrate_cells() BEFORE grid cells are compressed
2655 migrating grid cells are ones with proc != me
2656 reset csurfs indices for kept cells
2657 only called for implicit surfs
2658 ------------------------------------------------------------------------- */
2659
compress_implicit()2660 void Surf::compress_implicit()
2661 {
2662 int j,ns,icell;
2663 cellint cellID;
2664 surfint *csurfs;
2665
2666 if (!grid->hashfilled) grid->rehash();
2667
2668 Grid::ChildCell *cells = grid->cells;
2669 Grid::MyHash *ghash = grid->hash;
2670 int me = comm->me;
2671 int n = 0;
2672
2673 if (domain->dimension == 2) {
2674 for (int i = 0; i < nlocal; i++) {
2675 icell = (*ghash)[lines[i].id];
2676 if (cells[icell].proc != me) continue;
2677 if (i != n) {
2678 // compress my surf list
2679 memcpy(&lines[n],&lines[i],sizeof(Line));
2680 // reset matching csurfs index in grid cell from i to n
2681 csurfs = cells[icell].csurfs;
2682 ns = cells[icell].nsurf;
2683 for (j = 0; j < ns; j++)
2684 if (csurfs[j] == i) {
2685 csurfs[j] = n;
2686 break;
2687 }
2688 }
2689 n++;
2690 }
2691
2692 } else {
2693 for (int i = 0; i < nlocal; i++) {
2694 icell = (*ghash)[tris[i].id];
2695 if (cells[icell].proc != me) continue;
2696 if (i != n) {
2697 // compress my surf list
2698 memcpy(&tris[n],&tris[i],sizeof(Tri));
2699 // reset matching csurfs index in grid cell from i to n
2700 csurfs = cells[icell].csurfs;
2701 ns = cells[icell].nsurf;
2702 for (j = 0; j < ns; j++)
2703 if (csurfs[j] == i) {
2704 csurfs[j] = n;
2705 break;
2706 }
2707 }
2708 n++;
2709 }
2710 }
2711
2712 nlocal = n;
2713 }
2714
2715 /* ----------------------------------------------------------------------
2716 comm of tallies across all procs
2717 nrow = # of tally entries in input vector
2718 tally2surf = surf index of each entry in input vector
2719 in = input vector of tallies
2720 instride = stride between entries in input vector
2721 return out = summed tallies for explicit surfs I own
2722 ------------------------------------------------------------------------- */
2723
collate_vector(int nrow,surfint * tally2surf,double * in,int instride,double * out)2724 void Surf::collate_vector(int nrow, surfint *tally2surf,
2725 double *in, int instride, double *out)
2726 {
2727 // collate version depends on tally_comm setting
2728
2729 if (tally_comm == TALLYAUTO) {
2730 if (nprocs > nsurf)
2731 collate_vector_reduce(nrow,tally2surf,in,instride,out);
2732 else collate_vector_rendezvous(nrow,tally2surf,in,instride,out);
2733 } else if (tally_comm == TALLYREDUCE) {
2734 collate_vector_reduce(nrow,tally2surf,in,instride,out);
2735 } else if (tally_comm == TALLYRVOUS) {
2736 collate_vector_rendezvous(nrow,tally2surf,in,instride,out);
2737 }
2738 }
2739
2740 /* ----------------------------------------------------------------------
2741 allreduce version of collate
2742 ------------------------------------------------------------------------- */
2743
collate_vector_reduce(int nrow,surfint * tally2surf,double * in,int instride,double * out)2744 void Surf::collate_vector_reduce(int nrow, surfint *tally2surf,
2745 double *in, int instride, double *out)
2746 {
2747 int i,j,m;
2748
2749 if (nsurf > MAXSMALLINT)
2750 error->all(FLERR,"Two many surfs to tally reduce - "
2751 "use global surf/comm auto or rvous");
2752
2753 int nglobal = nsurf;
2754
2755 double *one,*all;
2756 memory->create(one,nglobal,"surf:one");
2757 memory->create(all,nglobal,"surf:all");
2758
2759 // zero all values and add in values I accumulated
2760
2761 for (i = 0; i < nglobal; i++) one[i] = 0.0;
2762
2763 Surf::Line *lines = surf->lines;
2764 Surf::Tri *tris = surf->tris;
2765 int dim = domain->dimension;
2766 surfint id;
2767
2768 j = 0;
2769 for (i = 0; i < nrow; i++) {
2770 m = (int) tally2surf[i] - 1;
2771 one[m] = in[j];
2772 j += instride;
2773 }
2774
2775 // global allreduce
2776
2777 MPI_Allreduce(one,all,nglobal,MPI_DOUBLE,MPI_SUM,world);
2778
2779 // out = only surfs I own
2780
2781 m = 0;
2782 for (i = me; i < nglobal; i += nprocs)
2783 out[m++] = all[i];
2784
2785 // NOTE: could persist these for multiple invocations
2786
2787 memory->destroy(one);
2788 memory->destroy(all);
2789 }
2790
2791 /* ----------------------------------------------------------------------
2792 rendezvous version of collate
2793 ------------------------------------------------------------------------- */
2794
collate_vector_rendezvous(int nrow,surfint * tally2surf,double * in,int instride,double * out)2795 void Surf::collate_vector_rendezvous(int nrow, surfint *tally2surf,
2796 double *in, int instride, double *out)
2797 {
2798 // allocate memory for rvous input
2799
2800 int *proclist;
2801 memory->create(proclist,nrow,"surf:proclist");
2802 InRvousVec *in_rvous =
2803 (InRvousVec *) memory->smalloc((bigint) nrow*sizeof(InRvousVec),
2804 "surf:in_rvous");
2805
2806 // create rvous inputs
2807 // proclist = owner of each surf
2808 // logic of (id-1) % nprocs sends
2809 // surf IDs 1,11,21,etc on 10 procs to proc 0
2810
2811 Surf::Line *lines = surf->lines;
2812 Surf::Tri *tris = surf->tris;
2813 int dim = domain->dimension;
2814
2815 surfint id;
2816
2817 int m = 0;
2818 for (int i = 0; i < nrow; i++) {
2819 id = tally2surf[i];
2820 proclist[i] = (id-1) % nprocs;
2821 in_rvous[i].id = id;
2822 in_rvous[i].value = in[m];
2823 m += instride;
2824 }
2825
2826 // perform rendezvous operation
2827 // each proc owns subset of surfs
2828 // receives all tally contributions to surfs it owns
2829
2830 out_rvous = out;
2831
2832 char *buf;
2833 int nout = comm->rendezvous(1,nrow,(char *) in_rvous,sizeof(InRvousVec),
2834 0,proclist,rendezvous_vector,
2835 0,buf,0,(void *) this);
2836
2837 memory->destroy(proclist);
2838 memory->destroy(in_rvous);
2839 }
2840
2841 /* ----------------------------------------------------------------------
2842 callback from rendezvous operation
2843 process tallies for surfs assigned to me
2844 inbuf = list of N Inbuf datums
2845 no outbuf
2846 ------------------------------------------------------------------------- */
2847
rendezvous_vector(int n,char * inbuf,int & flag,int * & proclist,char * & outbuf,void * ptr)2848 int Surf::rendezvous_vector(int n, char *inbuf, int &flag, int *&proclist,
2849 char *&outbuf, void *ptr)
2850 {
2851 Surf *sptr = (Surf *) ptr;
2852 Memory *memory = sptr->memory;
2853 int nown = sptr->nown;
2854 double *out = sptr->out_rvous;
2855 int nprocs = sptr->comm->nprocs;
2856 int me = sptr->comm->me;
2857
2858 // zero my owned surf values
2859
2860 for (int i = 0; i < nown; i++) out[i] = 0.0;
2861
2862 // accumulate per-surf values from different procs to my owned surfs
2863 // logic of (id-1-me) / nprocs maps
2864 // surf IDs [1,11,21,...] on 10 procs to [0,1,2,...] on proc 0
2865
2866 Surf::InRvousVec *in_rvous = (Surf::InRvousVec *) inbuf;
2867
2868 int m;
2869 for (int i = 0; i < n; i++) {
2870 m = (in_rvous[i].id-1-me) / nprocs;
2871 out[m] += in_rvous[i].value;
2872 }
2873
2874 // flag = 0: no second comm needed in rendezvous
2875
2876 flag = 0;
2877 return 0;
2878 }
2879
2880 /* ----------------------------------------------------------------------
2881 comm of tallies across all procs
2882 nrow,ncol = # of entries and columns in input array
2883 tally2surf = global surf index of each entry in input array
2884 in = input array of tallies
2885 return out = summed tallies for explicit surfs I own
2886 ------------------------------------------------------------------------- */
2887
collate_array(int nrow,int ncol,surfint * tally2surf,double ** in,double ** out)2888 void Surf::collate_array(int nrow, int ncol, surfint *tally2surf,
2889 double **in, double **out)
2890 {
2891 // collate version depends on tally_comm setting
2892
2893 if (tally_comm == TALLYAUTO) {
2894 if (nprocs > nsurf)
2895 collate_array_reduce(nrow,ncol,tally2surf,in,out);
2896 else collate_array_rendezvous(nrow,ncol,tally2surf,in,out);
2897 } else if (tally_comm == TALLYREDUCE) {
2898 collate_array_reduce(nrow,ncol,tally2surf,in,out);
2899 } else if (tally_comm == TALLYRVOUS) {
2900 collate_array_rendezvous(nrow,ncol,tally2surf,in,out);
2901 }
2902 }
2903
2904 /* ----------------------------------------------------------------------
2905 allreduce version of collate
2906 ------------------------------------------------------------------------- */
2907
collate_array_reduce(int nrow,int ncol,surfint * tally2surf,double ** in,double ** out)2908 void Surf::collate_array_reduce(int nrow, int ncol, surfint *tally2surf,
2909 double **in, double **out)
2910 {
2911 int i,j,m;
2912
2913 bigint ntotal = (bigint) nsurf * ncol;
2914
2915 if (ntotal > MAXSMALLINT)
2916 error->all(FLERR,"Two many surfs to tally reduce - "
2917 "use global surf/comm auto or rvous");
2918
2919 int nglobal = nsurf;
2920
2921 double **one,**all;
2922 memory->create(one,nglobal,ncol,"surf:one");
2923 memory->create(all,nglobal,ncol,"surf:all");
2924
2925 // zero all values and set values I accumulated
2926
2927 for (i = 0; i < nglobal; i++)
2928 for (j = 0; j < ncol; j++)
2929 one[i][j] = 0.0;
2930
2931 Surf::Line *lines = surf->lines;
2932 Surf::Tri *tris = surf->tris;
2933 int dim = domain->dimension;
2934
2935 for (i = 0; i < nrow; i++) {
2936 m = (int) tally2surf[i] - 1;
2937 for (j = 0; j < ncol; j++)
2938 one[m][j] = in[i][j];
2939 }
2940
2941 // global allreduce
2942
2943 MPI_Allreduce(&one[0][0],&all[0][0],ntotal,MPI_DOUBLE,MPI_SUM,world);
2944
2945 // out = only surfs I own
2946
2947 m = 0;
2948 for (i = me; i < nglobal; i += nprocs) {
2949 for (j = 0; j < ncol; j++) out[m][j] = all[i][j];
2950 m++;
2951 }
2952
2953 // NOTE: could persist these for multiple invocations
2954
2955 memory->destroy(one);
2956 memory->destroy(all);
2957 }
2958
2959 /* ----------------------------------------------------------------------
2960 rendezvous version of collate
2961 ------------------------------------------------------------------------- */
2962
collate_array_rendezvous(int nrow,int ncol,surfint * tally2surf,double ** in,double ** out)2963 void Surf::collate_array_rendezvous(int nrow, int ncol, surfint *tally2surf,
2964 double **in, double **out)
2965 {
2966 int i,j,m;
2967
2968 // allocate memory for rvous input
2969
2970 int *proclist;
2971 memory->create(proclist,nrow,"surf:proclist");
2972 double *in_rvous = (double *) // worry about overflow
2973 memory->smalloc(nrow*(ncol+1)*sizeof(double*),"surf:in_rvous");
2974
2975 // create rvous inputs
2976 // proclist = owner of each surf
2977 // logic of (id-1) % nprocs sends
2978 // surf IDs 1,11,21,etc on 10 procs to proc 0
2979
2980 Surf::Line *lines = surf->lines;
2981 Surf::Tri *tris = surf->tris;
2982 int dim = domain->dimension;
2983 surfint id;
2984
2985 m = 0;
2986 for (int i = 0; i < nrow; i++) {
2987 id = tally2surf[i];
2988 proclist[i] = (id-1) % nprocs;
2989 in_rvous[m++] = ubuf(id).d;
2990 for (j = 0; j < ncol; j++)
2991 in_rvous[m++] = in[i][j];
2992 }
2993
2994 // perform rendezvous operation
2995 // each proc owns subset of surfs
2996 // receives all tally contributions to surfs it owns
2997
2998 ncol_rvous = ncol;
2999 if (out == NULL) out_rvous = NULL;
3000 else out_rvous = &out[0][0];
3001 int size = (ncol+1) * sizeof(double);
3002
3003 char *buf;
3004 int nout = comm->rendezvous(1,nrow,(char *) in_rvous,size,
3005 0,proclist,rendezvous_array,
3006 0,buf,0,(void *) this);
3007
3008 memory->destroy(proclist);
3009 memory->sfree(in_rvous);
3010 }
3011
3012 /* ----------------------------------------------------------------------
3013 callback from rendezvous operation
3014 process tallies for surfs assigned to me
3015 inbuf = list of N Inbuf datums
3016 no outbuf
3017 ------------------------------------------------------------------------- */
3018
rendezvous_array(int n,char * inbuf,int & flag,int * & proclist,char * & outbuf,void * ptr)3019 int Surf::rendezvous_array(int n, char *inbuf,
3020 int &flag, int *&proclist, char *&outbuf,
3021 void *ptr)
3022 {
3023 int i,j,k,m;
3024
3025 Surf *sptr = (Surf *) ptr;
3026 Memory *memory = sptr->memory;
3027 int nown = sptr->nown;
3028 int ncol = sptr->ncol_rvous;
3029 double *out = sptr->out_rvous;
3030 int nprocs = sptr->comm->nprocs;
3031 int me = sptr->comm->me;
3032
3033 // zero my owned surf values
3034 // NOTE: is this needed if caller zeroes ?
3035
3036 int ntotal = nown*ncol;
3037 for (m = 0; m < ntotal; m++) out[m] = 0.0;
3038
3039 // accumulate per-surf values from different procs to my owned surfs
3040 // logic of (id-1-me) / nprocs maps
3041 // surf IDs [1,11,21,...] on 10 procs to [0,1,2,...] on proc 0
3042
3043 double *in_rvous = (double *) inbuf;
3044 surfint id;
3045
3046 m = 0;
3047 for (int i = 0; i < n; i++) {
3048 id = (surfint) ubuf(in_rvous[m++]).i;
3049 k = (id-1-me) / nprocs * ncol;
3050 for (j = 0; j < ncol; j++)
3051 out[k++] += in_rvous[m++];
3052 }
3053
3054 // flag = 0: no second comm needed in rendezvous
3055
3056 flag = 0;
3057 return 0;
3058 }
3059
3060 /* ----------------------------------------------------------------------
3061 comm of tallies across all procs
3062 called from compute isurf/grid and fix ave/grid
3063 for implicit surf tallies by grid cell
3064 nrow = # of tallies
3065 tally2surf = surf ID for each tally (same as cell ID)
3066 in = vectir of tally values
3067 return out = summed tallies for grid cells I own
3068 done via rendezvous algorithm
3069 ------------------------------------------------------------------------- */
3070
collate_vector_implicit(int nrow,surfint * tally2surf,double * in,double * out)3071 void Surf::collate_vector_implicit(int nrow, surfint *tally2surf,
3072 double *in, double *out)
3073 {
3074 int i,j,m,icell;
3075 cellint cellID;
3076
3077 int me = comm->me;
3078 int nprocs = comm->nprocs;
3079
3080 // create a grid cell hash for only my owned cells
3081
3082 Grid::ChildCell *cells = grid->cells;
3083 int nglocal = grid->nlocal;
3084
3085 MyCellHash hash;
3086
3087 for (int icell = 0; icell < nglocal; icell++) {
3088 if (cells[icell].nsplit <= 0) continue;
3089 hash[cells[icell].id] = icell;
3090 }
3091
3092 // for implicit surfs, tally2surf stores cellIDs
3093
3094 cellint *tally2cell = (cellint *) tally2surf;
3095
3096 // if I own tally grid cell, sum tallies to out directly
3097 // else nsend = # of tallies to contribute to rendezvous
3098
3099 int nsend = 0;
3100 for (i = 0; i < nrow; i++) {
3101 if (hash.find(tally2cell[i]) == hash.end()) nsend++;
3102 else {
3103 icell = hash[tally2cell[i]];
3104 out[icell] += in[i];
3105 }
3106 }
3107
3108 // done if just one proc
3109
3110 if (nprocs == 1) return;
3111
3112 // ncell = # of owned grid cells with implicit surfs, excluding sub cells
3113 // NOTE: could limit to cell group of caller
3114
3115 int ncell = 0;
3116 for (int icell = 0; icell < nglocal; icell++) {
3117 if (cells[icell].nsurf <= 0) continue;
3118 if (cells[icell].nsplit <= 0) continue;
3119 ncell++;
3120 }
3121
3122 // allocate memory for rvous input
3123 // ncount = ncell + nsend
3124 // 3 doubles for each input = proc, cellID, tally
3125
3126 int ncount = ncell + nsend;
3127
3128 int *proclist;
3129 double *in_rvous;
3130 memory->create(proclist,ncount,"surf:proclist");
3131 memory->create(in_rvous,3*ncount,"surf:in_rvous");
3132
3133 // create rvous inputs
3134 // owning proc for each datum = random hash of cellID
3135 // flavor 1: one per ncell with proc and cellID, no tally
3136 // flavor 2: one per nsend with proc = -1, cellID, one tally
3137
3138 ncount = m = 0;
3139
3140 for (int icell = 0; icell < nglocal; icell++) {
3141 if (cells[icell].nsurf <= 0) continue;
3142 if (cells[icell].nsplit <= 0) continue;
3143 proclist[ncount] = hashlittle(&cells[icell].id,sizeof(cellint),0) % nprocs;
3144 in_rvous[m++] = me;
3145 in_rvous[m++] = cells[icell].id; // NOTE: should use ubuf
3146 in_rvous[m++] = 0.0;
3147 ncount++;
3148 }
3149
3150 for (i = 0; i < nrow; i++) {
3151 if (hash.find(tally2cell[i]) == hash.end()) {
3152 proclist[ncount] = hashlittle(&tally2cell[i],sizeof(cellint),0) % nprocs;
3153 in_rvous[m++] = -1;
3154 in_rvous[m++] = tally2cell[i]; // NOTE: should use ubuf
3155 in_rvous[m++] = in[i];
3156 ncount++;
3157 }
3158 }
3159
3160 // perform rendezvous operation
3161
3162 ncol_rvous = 1;
3163 char *buf;
3164 int nout = comm->rendezvous(1,ncount,(char *) in_rvous,3*sizeof(double),
3165 0,proclist,rendezvous_implicit,
3166 0,buf,2*sizeof(double),(void *) this);
3167 double *out_rvous = (double *) buf;
3168
3169 memory->destroy(proclist);
3170 memory->destroy(in_rvous);
3171
3172 // sum tallies returned for grid cells I own into out
3173
3174 m = 0;
3175 for (i = 0; i < nout; i++) {
3176 cellID = out_rvous[m++]; // NOTE: should use ubuf
3177 icell = hash[cellID];
3178 out[icell] += out_rvous[m++];
3179 }
3180
3181 // clean-up
3182
3183 memory->destroy(out_rvous);
3184 }
3185
3186 /* ----------------------------------------------------------------------
3187 comm of tallies across all procs
3188 called from compute isurf/grid and fix ave/grid
3189 for implicit surf tallies by grid cell
3190 nrow = # of tallies
3191 ncol = # of values per tally
3192 tally2surf = surf ID for each tally (same as cell ID)
3193 in = array of tally values, nrow by ncol
3194 return out = summed tallies for grid cells I own, nlocal by ncol
3195 done via rendezvous algorithm
3196 ------------------------------------------------------------------------- */
3197
collate_array_implicit(int nrow,int ncol,surfint * tally2surf,double ** in,double ** out)3198 void Surf::collate_array_implicit(int nrow, int ncol, surfint *tally2surf,
3199 double **in, double **out)
3200 {
3201 int i,j,m,icell;
3202 cellint cellID;
3203
3204 int me = comm->me;
3205 int nprocs = comm->nprocs;
3206
3207 // create a grid cell hash for only my owned cells
3208
3209 Grid::ChildCell *cells = grid->cells;
3210 int nglocal = grid->nlocal;
3211
3212 MyCellHash hash;
3213
3214 for (int icell = 0; icell < nglocal; icell++) {
3215 if (cells[icell].nsplit <= 0) continue;
3216 hash[cells[icell].id] = icell;
3217 }
3218
3219 // for implicit surfs, tally2surf stores cellIDs
3220
3221 cellint *tally2cell = (cellint *) tally2surf;
3222
3223 // if I own tally grid cell, sum tallies to out directly
3224 // else nsend = # of tallies to contribute to rendezvous
3225
3226 int nsend = 0;
3227 for (i = 0; i < nrow; i++) {
3228 if (hash.find(tally2cell[i]) == hash.end()) nsend++;
3229 else {
3230 icell = hash[tally2cell[i]];
3231 for (j = 0; j < ncol; j++)
3232 out[icell][j] += in[i][j];
3233 }
3234 }
3235
3236 // done if just one proc
3237
3238 if (nprocs == 1) return;
3239
3240 // ncell = # of owned grid cells with implicit surfs, excluding sub cells
3241 // NOTE: could limit to cell group of caller
3242
3243 int ncell = 0;
3244 for (int icell = 0; icell < nglocal; icell++) {
3245 if (cells[icell].nsurf <= 0) continue;
3246 if (cells[icell].nsplit <= 0) continue;
3247 ncell++;
3248 }
3249
3250 // allocate memory for rvous input
3251 // ncount = ncell + nsend
3252 // ncol+2 doubles for each input = proc, cellID, ncol values
3253
3254 int ncount = ncell + nsend;
3255
3256 int *proclist;
3257 double *in_rvous;
3258 memory->create(proclist,ncount,"surf:proclist");
3259 memory->create(in_rvous,ncount*(ncol+2),"surf:in_rvous");
3260
3261 // create rvous inputs
3262 // owning proc for each datum = random hash of cellID
3263 // flavor 1: one per ncell with proc and cellID, no tallies
3264 // flavor 2: one per nsend with proc = -1, cellID, tallies
3265
3266 ncount = m = 0;
3267
3268 for (int icell = 0; icell < nglocal; icell++) {
3269 if (cells[icell].nsurf <= 0) continue;
3270 if (cells[icell].nsplit <= 0) continue;
3271 proclist[ncount] = hashlittle(&cells[icell].id,sizeof(cellint),0) % nprocs;
3272 in_rvous[m++] = me;
3273 in_rvous[m++] = cells[icell].id; // NOTE: should use ubuf
3274 for (j = 0; j < ncol; j++)
3275 in_rvous[m++] = 0.0;
3276 ncount++;
3277 }
3278
3279 for (i = 0; i < nrow; i++) {
3280 if (hash.find(tally2cell[i]) == hash.end()) {
3281 proclist[ncount] = hashlittle(&tally2cell[i],sizeof(cellint),0) % nprocs;
3282 in_rvous[m++] = -1;
3283 in_rvous[m++] = tally2cell[i]; // NOTE: should use ubuf
3284 for (j = 0; j < ncol; j++)
3285 in_rvous[m++] = in[i][j];
3286 ncount++;
3287 }
3288 }
3289
3290 // perform rendezvous operation
3291
3292 ncol_rvous = ncol;
3293 char *buf;
3294 int nout = comm->rendezvous(1,ncount,(char *) in_rvous,
3295 (ncol+2)*sizeof(double),
3296 0,proclist,rendezvous_implicit,
3297 0,buf,(ncol+1)*sizeof(double),(void *) this);
3298 double *out_rvous = (double *) buf;
3299
3300 memory->destroy(proclist);
3301 memory->destroy(in_rvous);
3302
3303 // sum tallies returned for grid cells I own into out
3304
3305 m = 0;
3306 for (i = 0; i < nout; i++) {
3307 cellID = out_rvous[m++]; // NOTE: should use ubuf
3308 icell = hash[cellID] - 1; // subtract one for child cell index
3309 for (j = 0; j < ncol; j++)
3310 out[icell][j] += out_rvous[m++];
3311 }
3312
3313 // clean-up
3314
3315 memory->destroy(out_rvous);
3316 }
3317
3318 /* ----------------------------------------------------------------------
3319 callback from rendezvous operation
3320 create summed tallies for each grid cell assigned to me
3321 inbuf = list of N input datums
3322 send cellID + Ncol values back to owning proc of each grid cell
3323 ------------------------------------------------------------------------- */
3324
rendezvous_implicit(int n,char * inbuf,int & flag,int * & proclist,char * & outbuf,void * ptr)3325 int Surf::rendezvous_implicit(int n, char *inbuf,
3326 int &flag, int *&proclist, char *&outbuf, void *ptr)
3327 {
3328 int i,j,k,m,proc,iout;
3329 cellint cellID;
3330
3331 Surf *sptr = (Surf *) ptr;
3332 Memory *memory = sptr->memory;
3333 int ncol = sptr->ncol_rvous;
3334
3335 // scan inbuf for (proc,cellID) entries
3336 // create phash so can lookup the proc for each cellID
3337
3338 double *in_rvous = (double *) inbuf;
3339 MyCellHash phash;
3340
3341 m = 0;
3342 for (i = 0; i < n; i++) {
3343 proc = static_cast<int> (in_rvous[m++]);
3344 cellID = static_cast<cellint> (in_rvous[m++]);
3345 if (proc >= 0 && phash.find(cellID) == phash.end()) phash[cellID] = proc;
3346 m += ncol;
3347 }
3348
3349 // allocate proclist & outbuf, based on size of max-size of phash
3350
3351 int nmax = phash.size();
3352 memory->create(proclist,nmax,"surf:proclist");
3353 double *out;
3354 memory->create(out,nmax*(ncol+1),"surf:out");
3355
3356 // scan inbuf for (cellID,tallies) entries
3357 // create a 2nd hash so can lookup the outbuf entry for each cellID
3358 // create proclist and outbuf with summed tallies for every cellID
3359
3360 MyCellHash ohash;
3361
3362 int nout = 0;
3363 k = m = 0;
3364
3365 for (i = 0; i < n; i++) {
3366 proc = static_cast<int> (in_rvous[m++]);
3367 cellID = static_cast<cellint> (in_rvous[m++]);
3368 if (proc >= 0) {
3369 m += ncol; // skip entries with novalues
3370 continue;
3371 }
3372 if (ohash.find(cellID) == phash.end()) {
3373 ohash[cellID] = nout; // add a new set of out values
3374 proclist[nout] = phash[cellID];
3375 out[k++] = cellID;
3376 for (j = 0; j < ncol; j++)
3377 out[k++] = in_rvous[m++];
3378 nout++;
3379 } else {
3380 iout = ohash[cellID] * (ncol+1); // offset into existing out values
3381 iout++; // skip cellID;
3382 for (j = 0; j < ncol; j++)
3383 out[iout++] += in_rvous[m++]; // sum to existing values
3384 }
3385 }
3386
3387 // flag = 2: new outbuf
3388
3389 flag = 2;
3390 outbuf = (char *) out;
3391 return nout;
3392 }
3393
3394 /* ----------------------------------------------------------------------
3395 redistribute newly created distributed lines to owing procs
3396 nold = original nown value before new surfs were read in
3397 nown = current nown value that includes my new surfs to redistribute
3398 nnew = nown value after new surfs from all procs are assigned to me
3399 called by ReadSurf:clip() after proc creates new surfs via clipping
3400 only called for distributed surfs
3401 ------------------------------------------------------------------------- */
3402
redistribute_lines_clip(int nold,int nnew)3403 void Surf::redistribute_lines_clip(int nold, int nnew)
3404 {
3405 // allocate memory for rvous input
3406
3407 int nsend = nown - nold;
3408
3409 int *proclist;
3410 memory->create(proclist,nsend,"surf:proclist");
3411 Line *in_rvous = (Line *) memory->smalloc(nsend*sizeof(Line),"surf:in_rvous");
3412
3413 // create rvous inputs
3414 // proclist = owner of each surf = (id-1) % nprocs
3415
3416 surfint id;
3417
3418 int i = nold;
3419 for (int m = 0; m < nsend; m++) {
3420 id = mylines[i].id;
3421 proclist[m] = (id-1) % nprocs;
3422 memcpy(&in_rvous[m],&mylines[i],sizeof(Line));
3423 i++;
3424 }
3425
3426 // insure mylines is allocated sufficient for new lines
3427 // reset nown to new value after rendezvous
3428
3429 if (nnew > maxown) {
3430 int old = maxown;
3431 maxown = nnew;
3432 grow_own(old);
3433 }
3434 nown = nnew;
3435
3436 // perform rendezvous operation
3437 // each proc owns subset of new surfs
3438 // receives them from other procs
3439
3440 char *buf;
3441 int nout = comm->rendezvous(1,nsend,(char *) in_rvous,sizeof(Line),
3442 0,proclist,rendezvous_lines,
3443 0,buf,0,(void *) this);
3444
3445 memory->destroy(proclist);
3446 memory->sfree(in_rvous);
3447 }
3448
3449 /* ----------------------------------------------------------------------
3450 redistribute newly created distributed lines to owing procs
3451 nnew = nown value after new surfs from all procs are assigned to me
3452 called by ReadSurf:read_multiple()
3453 only called for distributed surfs
3454 ------------------------------------------------------------------------- */
3455
redistribute_lines_temporary(int nnew)3456 void Surf::redistribute_lines_temporary(int nnew)
3457 {
3458 // allocate memory for rvous input
3459
3460 int nsend = ntmp;
3461
3462 int *proclist;
3463 memory->create(proclist,nsend,"surf:proclist");
3464 Line *in_rvous = (Line *) memory->smalloc(nsend*sizeof(Line),"surf:in_rvous");
3465
3466 // create rvous inputs
3467 // proclist = owner of each surf = (id-1) % nprocs
3468
3469 surfint id;
3470
3471 for (int i = 0; i < nsend; i++) {
3472 id = tmplines[i].id;
3473 proclist[i] = (id-1) % nprocs;
3474 memcpy(&in_rvous[i],&tmplines[i],sizeof(Line));
3475 }
3476
3477 // insure mylines is allocated sufficient for new lines
3478 // reset nown to new value after rendezvous
3479
3480 if (nnew > maxown) {
3481 int old = maxown;
3482 maxown = nnew;
3483 grow_own(old);
3484 }
3485 nown = nnew;
3486
3487 // perform rendezvous operation
3488 // each proc owns subset of new surfs
3489 // receives them from other procs
3490
3491 char *buf;
3492 int nout = comm->rendezvous(1,nsend,(char *) in_rvous,sizeof(Line),
3493 0,proclist,rendezvous_lines,
3494 0,buf,0,(void *) this);
3495
3496 memory->destroy(proclist);
3497 memory->sfree(in_rvous);
3498 }
3499
3500 /* ----------------------------------------------------------------------
3501 callback from rendezvous operation
3502 store received surfs assigned to me in correct location in mylines
3503 inbuf = list of N Inbuf datums
3504 no outbuf
3505 ------------------------------------------------------------------------- */
3506
rendezvous_lines(int n,char * inbuf,int & flag,int * & proclist,char * & outbuf,void * ptr)3507 int Surf::rendezvous_lines(int n, char *inbuf,
3508 int &flag, int *&proclist, char *&outbuf,
3509 void *ptr)
3510 {
3511 int i,j,k,m;
3512
3513 Surf *sptr = (Surf *) ptr;
3514 Line *lines = sptr->mylines;
3515 int nprocs = sptr->comm->nprocs;
3516 int me = sptr->comm->me;
3517
3518 // zero my owned surf values
3519
3520 Line *in_rvous = (Line *) inbuf;
3521 surfint id;
3522
3523 for (int i = 0; i < n; i++) {
3524 id = in_rvous[i].id;
3525 m = (id-1-me) / nprocs;
3526 memcpy(&lines[m],&in_rvous[i],sizeof(Line));
3527 }
3528
3529 // flag = 0: no second comm needed in rendezvous
3530
3531 flag = 0;
3532 return 0;
3533 }
3534
3535 /* ----------------------------------------------------------------------
3536 redistribute newly created distributed tris to owing procs
3537 nold = original nown value before new surfs were read in
3538 nown = current nown value that includes my new surfs to redistribute
3539 nnew = nown value after new surfs from all procs are assigned to me
3540 old = starting index that skips previously distributed surfs
3541 called by ReadSurf:clip() after proc create new surfs via clipping
3542 only called for distributed surfs
3543 ------------------------------------------------------------------------- */
3544
redistribute_tris_clip(int nold,int nnew)3545 void Surf::redistribute_tris_clip(int nold, int nnew)
3546 {
3547 // allocate memory for rvous input
3548
3549 int nsend = nown - nold;
3550
3551 int *proclist;
3552 memory->create(proclist,nsend,"surf:proclist");
3553 Tri *in_rvous = (Tri *) memory->smalloc(nsend*sizeof(Tri),"surf:in_rvous");
3554
3555 // create rvous inputs
3556 // proclist = owner of each surf = (id-1) % nprocs
3557
3558 surfint id;
3559
3560 int i = nold;
3561 for (int m = 0; m < nsend; m++) {
3562 id = mytris[i].id;
3563 proclist[m] = (id-1) % nprocs;
3564 memcpy(&in_rvous[m],&mytris[i],sizeof(Tri));
3565 i++;
3566 }
3567
3568 // insure mytris is allocated sufficient for new tris
3569 // reset nown to new value after rendezvous
3570
3571 if (nnew > maxown) {
3572 int old = maxown;
3573 maxown = nnew;
3574 grow_own(old);
3575 }
3576 nown = nnew;
3577
3578 // perform rendezvous operation
3579 // each proc owns subset of new surfs
3580 // receives them from other procs
3581
3582 char *buf;
3583 int nout = comm->rendezvous(1,nsend,(char *) in_rvous,sizeof(Tri),
3584 0,proclist,rendezvous_tris,
3585 0,buf,0,(void *) this);
3586
3587 memory->destroy(proclist);
3588 memory->sfree(in_rvous);
3589 }
3590
3591 /* ----------------------------------------------------------------------
3592 redistribute newly created distributed tris to owing procs
3593 nnew = nown value after new surfs from all procs are assigned to me
3594 called by ReadSurf:read_multiple()
3595 only called for distributed surfs
3596 ------------------------------------------------------------------------- */
3597
redistribute_tris_temporary(int nnew)3598 void Surf::redistribute_tris_temporary(int nnew)
3599 {
3600 // allocate memory for rvous input
3601
3602 int nsend = ntmp;
3603
3604 int *proclist;
3605 memory->create(proclist,nsend,"surf:proclist");
3606 Tri *in_rvous = (Tri *) memory->smalloc(nsend*sizeof(Tri),"surf:in_rvous");
3607
3608 // create rvous inputs
3609 // proclist = owner of each surf = (id-1) % nprocs
3610
3611 surfint id;
3612
3613 for (int i = 0; i < nsend; i++) {
3614 id = tmptris[i].id;
3615 proclist[i] = (id-1) % nprocs;
3616 memcpy(&in_rvous[i],&tmptris[i],sizeof(Tri));
3617 }
3618
3619 // insure mytris is allocated sufficient for new tris
3620 // reset nown to new value after rendezvous
3621
3622 if (nnew > maxown) {
3623 int old = maxown;
3624 maxown = nnew;
3625 grow_own(old);
3626 }
3627 nown = nnew;
3628
3629 // perform rendezvous operation
3630 // each proc owns subset of new surfs
3631 // receives them from other procs
3632
3633 char *buf;
3634 int nout = comm->rendezvous(1,nsend,(char *) in_rvous,sizeof(Tri),
3635 0,proclist,rendezvous_tris,
3636 0,buf,0,(void *) this);
3637
3638 memory->destroy(proclist);
3639 memory->sfree(in_rvous);
3640 }
3641
3642 /* ----------------------------------------------------------------------
3643 callback from rendezvous operation
3644 store received surfs assigned to me in correct location in mytris
3645 inbuf = list of N Inbuf datums
3646 no outbuf
3647 ------------------------------------------------------------------------- */
3648
rendezvous_tris(int n,char * inbuf,int & flag,int * & proclist,char * & outbuf,void * ptr)3649 int Surf::rendezvous_tris(int n, char *inbuf,
3650 int &flag, int *&proclist, char *&outbuf,
3651 void *ptr)
3652 {
3653 int i,j,k,m;
3654
3655 Surf *sptr = (Surf *) ptr;
3656 Tri *tris = sptr->mytris;
3657 int nprocs = sptr->comm->nprocs;
3658 int me = sptr->comm->me;
3659
3660 // zero my owned surf values
3661
3662 Tri *in_rvous = (Tri *) inbuf;
3663 surfint id;
3664
3665 for (int i = 0; i < n; i++) {
3666 id = in_rvous[i].id;
3667 m = (id-1-me) / nprocs;
3668 memcpy(&tris[m],&in_rvous[i],sizeof(Tri));
3669 }
3670
3671 // flag = 0: no second comm needed in rendezvous
3672
3673 flag = 0;
3674 return 0;
3675 }
3676
3677 // ----------------------------------------------------------------------
3678 // methods for per-surf custom attributes
3679 // ----------------------------------------------------------------------
3680
3681 /* ----------------------------------------------------------------------
3682 find custom per-atom vector/array with name
3683 return index if found
3684 return -1 if not found
3685 ------------------------------------------------------------------------- */
3686
find_custom(char * name)3687 int Surf::find_custom(char *name)
3688 {
3689 for (int i = 0; i < ncustom; i++)
3690 if (ename[i] && strcmp(ename[i],name) == 0) return i;
3691 return -1;
3692 }
3693
3694 /* ----------------------------------------------------------------------
3695 add a custom attribute with name
3696 assumes name does not already exist, except in case of restart
3697 type = 0/1 for int/double
3698 size = 0 for vector, size > 0 for array with size columns
3699 return index of its location;
3700 ------------------------------------------------------------------------- */
3701
add_custom(char * name,int type,int size)3702 int Surf::add_custom(char *name, int type, int size)
3703 {
3704 int index;
3705
3706 // if name already exists
3707 // just return index if a restart script and re-defining the name
3708 // else error
3709
3710 index = find_custom(name);
3711 if (index >= 0) {
3712 if (custom_restart_flag == NULL || custom_restart_flag[index] == 1)
3713 error->all(FLERR,"Custom surf attribute name already exists");
3714 custom_restart_flag[index] = 1;
3715 return index;
3716 }
3717
3718 // use first available NULL entry or allocate a new one
3719
3720 for (index = 0; index < ncustom; index++)
3721 if (ename[index] == NULL) break;
3722
3723 if (index == ncustom) {
3724 ncustom++;
3725 ename = (char **) memory->srealloc(ename,ncustom*sizeof(char *),
3726 "surf:ename");
3727 memory->grow(etype,ncustom,"surf:etype");
3728 memory->grow(esize,ncustom,"surf:etype");
3729 memory->grow(ewhich,ncustom,"surf:etype");
3730 }
3731
3732 int n = strlen(name) + 1;
3733 ename[index] = new char[n];
3734 strcpy(ename[index],name);
3735 etype[index] = type;
3736 esize[index] = size;
3737
3738 if (type == INT) {
3739 if (size == 0) {
3740 ewhich[index] = ncustom_ivec++;
3741 eivec = (int **)
3742 memory->srealloc(eivec,ncustom_ivec*sizeof(int *),"surf:eivec");
3743 memory->grow(icustom_ivec,ncustom_ivec,"surf:icustom_ivec");
3744 icustom_ivec[ncustom_ivec-1] = index;
3745 } else {
3746 ewhich[index] = ncustom_iarray++;
3747 eiarray = (int ***)
3748 memory->srealloc(eiarray,ncustom_iarray*sizeof(int **),
3749 "surf:eiarray");
3750 memory->grow(icustom_iarray,ncustom_iarray,"surf:icustom_iarray");
3751 icustom_iarray[ncustom_iarray-1] = index;
3752 memory->grow(eicol,ncustom_iarray,"surf:eicol");
3753 eicol[ncustom_iarray-1] = size;
3754 }
3755 } else if (type == DOUBLE) {
3756 if (size == 0) {
3757 ewhich[index] = ncustom_dvec++;
3758 edvec = (double **)
3759 memory->srealloc(edvec,ncustom_dvec*sizeof(double *),"surf:edvec");
3760 memory->grow(icustom_dvec,ncustom_dvec,"surf:icustom_dvec");
3761 icustom_dvec[ncustom_dvec-1] = index;
3762 } else {
3763 ewhich[index] = ncustom_darray++;
3764 edarray = (double ***)
3765 memory->srealloc(edarray,ncustom_darray*sizeof(double **),
3766 "surf:edarray");
3767 memory->grow(icustom_darray,ncustom_darray,"surf:icustom_darray");
3768 icustom_darray[ncustom_darray-1] = index;
3769 memory->grow(edcol,ncustom_darray,"surf:edcol");
3770 edcol[ncustom_darray-1] = size;
3771 }
3772 }
3773
3774 allocate_custom(index,nlocal);
3775
3776 return index;
3777 }
3778
3779 /* ----------------------------------------------------------------------
3780 allocate vector/array associated with custom attribute with index
3781 set new values to 0 via memset()
3782 ------------------------------------------------------------------------- */
3783
allocate_custom(int index,int n)3784 void Surf::allocate_custom(int index, int n)
3785 {
3786 if (etype[index] == INT) {
3787 if (esize[index] == 0) {
3788 int *ivector = memory->create(eivec[ewhich[index]],n,"surf:eivec");
3789 if (ivector) memset(ivector,0,n*sizeof(int));
3790 } else {
3791 int **iarray = memory->create(eiarray[ewhich[index]],
3792 n,eicol[ewhich[index]],"surf:eiarray");
3793 if (iarray) memset(&iarray[0][0],0,n*eicol[ewhich[index]]*sizeof(int));
3794 }
3795
3796 } else {
3797 if (esize[index] == 0) {
3798 double *dvector = memory->create(edvec[ewhich[index]],n,"surf:edvec");
3799 if (dvector) memset(dvector,0,n*sizeof(double));
3800 } else {
3801 double **darray = memory->create(edarray[ewhich[index]],
3802 n,edcol[ewhich[index]],"surf:eearray");
3803 if (darray) memset(&darray[0][0],0,n*edcol[ewhich[index]]*sizeof(double));
3804 }
3805 }
3806 }
3807
3808 /* ----------------------------------------------------------------------
3809 remove a custom attribute at location index
3810 free memory for name and vector/array and set ptrs to NULL
3811 ncustom lists never shrink, but indices stored between
3812 the ncustom list and the dense vector/array lists must be reset
3813 ------------------------------------------------------------------------- */
3814
remove_custom(int index)3815 void Surf::remove_custom(int index)
3816 {
3817 delete [] ename[index];
3818 ename[index] = NULL;
3819
3820 if (etype[index] == INT) {
3821 if (esize[index] == 0) {
3822 memory->destroy(eivec[ewhich[index]]);
3823 ncustom_ivec--;
3824 for (int i = ewhich[index]; i < ncustom_ivec; i++) {
3825 icustom_ivec[i] = icustom_ivec[i+1];
3826 ewhich[icustom_ivec[i]] = i;
3827 eivec[i] = eivec[i+1];
3828 }
3829 } else{
3830 memory->destroy(eiarray[ewhich[index]]);
3831 ncustom_iarray--;
3832 for (int i = ewhich[index]; i < ncustom_iarray; i++) {
3833 icustom_iarray[i] = icustom_iarray[i+1];
3834 ewhich[icustom_iarray[i]] = i;
3835 eiarray[i] = eiarray[i+1];
3836 eicol[i] = eicol[i+1];
3837 }
3838 }
3839 } else if (etype[index] == DOUBLE) {
3840 if (esize[index] == 0) {
3841 memory->destroy(edvec[ewhich[index]]);
3842 ncustom_dvec--;
3843 for (int i = ewhich[index]; i < ncustom_dvec; i++) {
3844 icustom_dvec[i] = icustom_dvec[i+1];
3845 ewhich[icustom_dvec[i]] = i;
3846 edvec[i] = edvec[i+1];
3847 }
3848 } else{
3849 memory->destroy(edarray[ewhich[index]]);
3850 ncustom_darray--;
3851 for (int i = ewhich[index]; i < ncustom_darray; i++) {
3852 icustom_darray[i] = icustom_darray[i+1];
3853 ewhich[icustom_darray[i]] = i;
3854 edarray[i] = edarray[i+1];
3855 edcol[i] = edcol[i+1];
3856 }
3857 }
3858 }
3859
3860 // set ncustom = 0 if custom list is now entirely empty
3861
3862 int empty = 1;
3863 for (int i = 0; i < ncustom; i++)
3864 if (ename[i]) empty = 0;
3865 if (empty) ncustom = 0;
3866 }
3867
3868 // ----------------------------------------------------------------------
3869 // methods for write/read restart info
3870 // ----------------------------------------------------------------------
3871
3872 /* ----------------------------------------------------------------------
3873 proc 0 writes surf geometry to restart file
3874 NOTE: needs to be generalized for different surf styles
3875 ------------------------------------------------------------------------- */
3876
write_restart(FILE * fp)3877 void Surf::write_restart(FILE *fp)
3878 {
3879 if (distributed || implicit)
3880 error->all(FLERR,
3881 "Restart files with distributed surfaces are not yet supported");
3882
3883 fwrite(&ngroup,sizeof(int),1,fp);
3884
3885 int n;
3886 for (int i = 0; i < ngroup; i++) {
3887 n = strlen(gnames[i]) + 1;
3888 fwrite(&n,sizeof(int),1,fp);
3889 fwrite(gnames[i],sizeof(char),n,fp);
3890 }
3891
3892 if (domain->dimension == 2) {
3893 fwrite(&nsurf,sizeof(bigint),1,fp);
3894 for (int i = 0; i < nsurf; i++) {
3895 fwrite(&lines[i].id,sizeof(surfint),1,fp);
3896 fwrite(&lines[i].type,sizeof(int),1,fp);
3897 fwrite(&lines[i].mask,sizeof(int),1,fp);
3898 fwrite(&lines[i].transparent,sizeof(int),1,fp);
3899 fwrite(lines[i].p1,sizeof(double),3,fp);
3900 fwrite(lines[i].p2,sizeof(double),3,fp);
3901 }
3902 }
3903
3904 if (domain->dimension == 3) {
3905 fwrite(&nsurf,sizeof(bigint),1,fp);
3906 for (int i = 0; i < nsurf; i++) {
3907 fwrite(&tris[i].id,sizeof(surfint),1,fp);
3908 fwrite(&tris[i].type,sizeof(int),1,fp);
3909 fwrite(&tris[i].mask,sizeof(int),1,fp);
3910 fwrite(&tris[i].transparent,sizeof(int),1,fp);
3911 fwrite(tris[i].p1,sizeof(double),3,fp);
3912 fwrite(tris[i].p2,sizeof(double),3,fp);
3913 fwrite(tris[i].p3,sizeof(double),3,fp);
3914 }
3915 }
3916 }
3917
3918 /* ----------------------------------------------------------------------
3919 proc 0 reads surf geometry from restart file
3920 bcast to other procs
3921 NOTE: needs to be generalized for different surf styles
3922 ------------------------------------------------------------------------- */
3923
read_restart(FILE * fp)3924 void Surf::read_restart(FILE *fp)
3925 {
3926 if (distributed || implicit)
3927 error->all(FLERR,
3928 "Restart files with distributed surfaces are not yet supported");
3929
3930 int me = comm->me;
3931
3932 // if any exist, clear existing group names, before reading new ones
3933
3934 for (int i = 0; i < ngroup; i++) delete [] gnames[i];
3935
3936 if (me == 0) fread(&ngroup,sizeof(int),1,fp);
3937 MPI_Bcast(&ngroup,1,MPI_INT,0,world);
3938
3939 int n;
3940 for (int i = 0; i < ngroup; i++) {
3941 if (me == 0) fread(&n,sizeof(int),1,fp);
3942 MPI_Bcast(&n,1,MPI_INT,0,world);
3943 gnames[i] = new char[n];
3944 if (me == 0) fread(gnames[i],sizeof(char),n,fp);
3945 MPI_Bcast(gnames[i],n,MPI_CHAR,0,world);
3946 }
3947
3948 if (domain->dimension == 2) {
3949 if (me == 0) fread(&nsurf,sizeof(bigint),1,fp);
3950 MPI_Bcast(&nsurf,1,MPI_SPARTA_BIGINT,0,world);
3951 lines = (Line *) memory->smalloc(nsurf*sizeof(Line),"surf:lines");
3952 // NOTE: need different logic for different surf styles
3953 nlocal = nsurf;
3954
3955 if (me == 0) {
3956 for (int i = 0; i < nsurf; i++) {
3957 fread(&lines[i].id,sizeof(surfint),1,fp);
3958 fread(&lines[i].type,sizeof(int),1,fp);
3959 fread(&lines[i].mask,sizeof(int),1,fp);
3960 fread(&lines[i].transparent,sizeof(int),1,fp);
3961 lines[i].isc = lines[i].isr = -1;
3962 fread(lines[i].p1,sizeof(double),3,fp);
3963 fread(lines[i].p2,sizeof(double),3,fp);
3964 lines[i].norm[0] = lines[i].norm[1] = lines[i].norm[2] = 0.0;
3965 }
3966 }
3967 if (nsurf*sizeof(Line) > MAXSMALLINT)
3968 error->all(FLERR,"Surf restart memory exceeded");
3969 MPI_Bcast(lines,nsurf*sizeof(Line),MPI_CHAR,0,world);
3970 }
3971
3972 if (domain->dimension == 3) {
3973 if (me == 0) fread(&nsurf,sizeof(bigint),1,fp);
3974 MPI_Bcast(&nsurf,1,MPI_SPARTA_BIGINT,0,world);
3975 tris = (Tri *) memory->smalloc(nsurf*sizeof(Tri),"surf:tris");
3976 // NOTE: need different logic for different surf styles
3977 nlocal = nsurf;
3978
3979 if (me == 0) {
3980 for (int i = 0; i < nsurf; i++) {
3981 fread(&tris[i].id,sizeof(surfint),1,fp);
3982 fread(&tris[i].type,sizeof(int),1,fp);
3983 fread(&tris[i].mask,sizeof(int),1,fp);
3984 fread(&tris[i].transparent,sizeof(int),1,fp);
3985 tris[i].isc = tris[i].isr = -1;
3986 fread(tris[i].p1,sizeof(double),3,fp);
3987 fread(tris[i].p2,sizeof(double),3,fp);
3988 fread(tris[i].p3,sizeof(double),3,fp);
3989 tris[i].norm[0] = tris[i].norm[1] = tris[i].norm[2] = 0.0;
3990 }
3991 }
3992 if (nsurf*sizeof(Tri) > MAXSMALLINT)
3993 error->all(FLERR,"Surf restart memory exceeded");
3994 MPI_Bcast(tris,nsurf*sizeof(Tri),MPI_CHAR,0,world);
3995 }
3996 }
3997
3998 /* ---------------------------------------------------------------------- */
3999
grow(int old)4000 void Surf::grow(int old)
4001 {
4002 if (nmax <= old) return;
4003
4004 if (domain->dimension == 2) {
4005 lines = (Surf::Line *)
4006 memory->srealloc(lines,nmax*sizeof(Line),"surf:lines");
4007 memset(&lines[old],0,(nmax-old)*sizeof(Line));
4008 } else {
4009 tris = (Surf::Tri *)
4010 memory->srealloc(tris,nmax*sizeof(Tri),"surf:tris");
4011 memset(&tris[old],0,(nmax-old)*sizeof(Tri));
4012 }
4013 }
4014
4015 /* ---------------------------------------------------------------------- */
4016
grow_own(int old)4017 void Surf::grow_own(int old)
4018 {
4019 if (domain->dimension == 2) {
4020 mylines = (Surf::Line *)
4021 memory->srealloc(mylines,maxown*sizeof(Line),"surf:mylines");
4022 memset(&mylines[old],0,(maxown-old)*sizeof(Line));
4023 } else {
4024 mytris = (Surf::Tri *)
4025 memory->srealloc(mytris,maxown*sizeof(Tri),"surf:mytris");
4026 memset(&mytris[old],0,(maxown-old)*sizeof(Tri));
4027 }
4028 }
4029
4030 /* ---------------------------------------------------------------------- */
4031
grow_temporary(int old)4032 void Surf::grow_temporary(int old)
4033 {
4034 if (domain->dimension == 2) {
4035 tmplines = (Surf::Line *)
4036 memory->srealloc(tmplines,nmaxtmp*sizeof(Line),"surf:lines");
4037 memset(&tmplines[old],0,(nmaxtmp-old)*sizeof(Line));
4038 } else {
4039 tmptris = (Surf::Tri *)
4040 memory->srealloc(tmptris,nmaxtmp*sizeof(Tri),"surf:tris");
4041 memset(&tmptris[old],0,(nmaxtmp-old)*sizeof(Tri));
4042 }
4043 }
4044
4045 /* ---------------------------------------------------------------------- */
4046
memory_usage()4047 bigint Surf::memory_usage()
4048 {
4049 bigint bytes = 0;
4050
4051 if (implicit) {
4052 if (domain->dimension == 2) bytes += nlocal * sizeof(Line);
4053 else bytes += nlocal * sizeof(Tri);
4054 } else if (distributed) {
4055 if (domain->dimension == 2) bytes += (nlocal+nghost) * sizeof(Line);
4056 else bytes += (nlocal+nghost) * sizeof(Tri);
4057 if (domain->dimension == 2) bytes += nown * sizeof(Line);
4058 else bytes += nown * sizeof(Tri);
4059 } else {
4060 if (domain->dimension == 2) bytes += nsurf * sizeof(Line);
4061 else bytes += nsurf * sizeof(Tri);
4062 bytes += nlocal * sizeof(int);
4063 }
4064
4065 return bytes;
4066 }
4067
4068