1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 /****************************************************************************/
4 /* */
5 /* File: ifcreate.c */
6 /* */
7 /* Purpose: routines concerning interfaces between processors */
8 /* part 1: creating and maintaining interfaces */
9 /* */
10 /* Author: Klaus Birken */
11 /* Rechenzentrum Uni Stuttgart */
12 /* Universitaet Stuttgart */
13 /* Allmandring 30 */
14 /* 70550 Stuttgart */
15 /* internet: birken@rus.uni-stuttgart.de */
16 /* */
17 /* History: 93/11/30 kb begin */
18 /* 94/03/03 kb complete rewrite */
19 /* 94/09/12 kb IFExchange & IFOneway rewrite, two bugs fixed */
20 /* 94/09/21 kb created from if.c */
21 /* 95/01/13 kb added range functionality */
22 /* 96/01/08 kb renamed range to attr */
23 /* 96/01/16 kb added DDD_OBJ shortcut to avoid indirect addr. */
24 /* 96/05/07 kb removed need for global const MAX_COUPLING */
25 /* */
26 /* Remarks: */
27 /* */
28 /****************************************************************************/
29
30 /****************************************************************************/
31 /* */
32 /* include files */
33 /* system include files */
34 /* application include files */
35 /* */
36 /****************************************************************************/
37
38 /* standard C library */
39 #include <config.h>
40 #include <cstdlib>
41 #include <cstdio>
42 #include <cstring>
43 #include <cassert>
44
45 #include <algorithm>
46 #include <iomanip>
47 #include <iostream>
48 #include <tuple>
49
50 #include <dune/common/exceptions.hh>
51 #include <dune/common/stdstreams.hh>
52
53 #include <dune/uggrid/parallel/ddd/dddi.h>
54 #include "if.h"
55
56 USING_UG_NAMESPACE
57
58 /* PPIF namespace: */
59 using namespace PPIF;
60
61 START_UGDIM_NAMESPACE
62
63 /****************************************************************************/
64 /* */
65 /* routines */
66 /* */
67 /****************************************************************************/
68
69
70 /****************************************************************************/
71 /* */
72 /* Function: sort_IFCouplings */
73 /* */
74 /* Purpose: qsort procedure for sorting interface couplings. */
75 /* coupling list will be ordered according to: */
76 /* 1. processor number of represented object copy */
77 /* (increasing order) */
78 /* 2. direction of interface according to priorities */
79 /* (increasing order) */
80 /* 3. attr property of objects */
81 /* (decreasing order) */
82 /* 4. global ids of objects */
83 /* (increasing order) */
84 /* */
85 /* Input: two couplings `a`, `b` */
86 /* */
87 /* Output: `a < b` */
88 /* */
89 /****************************************************************************/
90
sort_IFCouplings(const COUPLING * a,const COUPLING * b)91 static bool sort_IFCouplings (const COUPLING* a, const COUPLING* b)
92 {
93 const auto aDir = CPLDIR(a), bDir = CPLDIR(b);
94 // a, b switched in the third component as decreasing order is used for attr
95 return std::tie(CPL_PROC(a), aDir, OBJ_ATTR(b->obj), OBJ_GID(a->obj))
96 < std::tie(CPL_PROC(b), bDir, OBJ_ATTR(a->obj), OBJ_GID(b->obj));
97 }
98
99
100
IFDeleteAll(DDD::DDDContext & context,DDD_IF ifId)101 static void IFDeleteAll(DDD::DDDContext& context, DDD_IF ifId)
102 {
103 auto& theIF = context.ifCreateContext().theIf;
104
105 IF_PROC *ifh, *ifhNext;
106 IF_ATTR *ifr, *ifrNext;
107
108 /* free IF_PROC memory */
109 ifh=theIF[ifId].ifHead;
110 while (ifh!=NULL)
111 {
112 ifhNext = ifh->next;
113
114 /* free IF_ATTR memory */
115 ifr=ifh->ifAttr;
116 while (ifr!=NULL)
117 {
118 ifrNext = ifr->next;
119 delete ifr;
120 ifr = ifrNext;
121 }
122
123 delete ifh;
124
125 ifh = ifhNext;
126 }
127
128 /* free memory for coupling table */
129 if (theIF[ifId].cpl!=NULL)
130 {
131 FreeIF(theIF[ifId].cpl);
132 theIF[ifId].cpl=NULL;
133 }
134
135 /* free memory for shortcut object table */
136 if (theIF[ifId].obj!=NULL)
137 {
138 FreeIF(theIF[ifId].obj);
139 theIF[ifId].obj=NULL;
140 }
141
142 /* reset pointers */
143 theIF[ifId].ifHead = NULL;
144 theIF[ifId].nIfHeads = 0;
145 }
146
147
148
149
150 /* TODO el-set relation, VERY inefficient! */
is_elem(DDD_PRIO el,int n,DDD_PRIO * set)151 static bool is_elem (DDD_PRIO el, int n, DDD_PRIO *set)
152 {
153 for(int i=0; i<n; i++)
154 if (set[i]==el)
155 return(true);
156
157 return(false);
158 }
159
160
161
update_channels(DDD::DDDContext & context,DDD_IF ifId)162 static RETCODE update_channels(DDD::DDDContext& context, DDD_IF ifId)
163 {
164 auto& theIF = context.ifCreateContext().theIf;
165
166 IF_PROC *ifh;
167 int i;
168 DDD_PROC *partners = DDD_ProcArray(context);
169
170 if (theIF[ifId].nIfHeads==0)
171 {
172 RET_ON_OK;
173 }
174
175 /* MarkHeap(); */
176
177 for(i=0, ifh=theIF[ifId].ifHead; ifh!=NULL; i++, ifh=ifh->next)
178 {
179 partners[i] = ifh->proc;
180 }
181
182 if (! IS_OK(DDD_GetChannels(context, theIF[ifId].nIfHeads)))
183 {
184 RET_ON_ERROR;
185 }
186
187 for(ifh=theIF[ifId].ifHead; ifh!=NULL; ifh=ifh->next) {
188 ifh->vc = VCHAN_TO(context, ifh->proc);
189 }
190
191 /* ReleaseHeap(); */
192
193
194 RET_ON_OK;
195 }
196
197
198 /****************************************************************************/
199
200 /* collect couplings into interface array, for standard interface */
201
IFCollectStdCouplings(DDD::DDDContext & context)202 static COUPLING ** IFCollectStdCouplings(DDD::DDDContext& context)
203 {
204 const auto& nCplItems = context.couplingContext().nCplItems;
205
206 if (nCplItems == 0)
207 return nullptr;
208
209 /* get memory for couplings inside STD_IF */
210 COUPLING** cplarray = (COUPLING **) AllocIF(sizeof(COUPLING *)*nCplItems);
211 if (cplarray==NULL)
212 throw std::bad_alloc();
213
214 /* collect couplings */
215 int n = 0;
216 const auto& nCpls = context.couplingContext().nCpls;
217 for(int index=0; index < nCpls; index++)
218 {
219 for(COUPLING* cpl=IdxCplList(context, index); cpl!=NULL; cpl=CPL_NEXT(cpl))
220 {
221 cplarray[n] = cpl;
222 SETCPLDIR(cpl,0);
223 n++;
224 }
225 }
226 /*
227 printf("%04d: n=%d, nCplItems=%d\n",context.me(),n,nCplItems);
228 */
229 assert(n==nCplItems);
230 return cplarray;
231 }
232
233
234 /****************************************************************************/
235
IFCreateFromScratch(DDD::DDDContext & context,COUPLING ** tmpcpl,DDD_IF ifId)236 static RETCODE IFCreateFromScratch(DDD::DDDContext& context, COUPLING **tmpcpl, DDD_IF ifId)
237 {
238 auto& theIF = context.ifCreateContext().theIf;
239
240 IF_PROC *ifHead = nullptr, *lastIfHead;
241 IF_ATTR *ifAttr = nullptr, *lastIfAttr = nullptr;
242 int n, i;
243 DDD_PROC lastproc;
244 [[maybe_unused]] int STAT_MOD;
245
246 const auto& objTable = context.objTable();
247
248 STAT_GET_MODULE(STAT_MOD);
249 STAT_SET_MODULE(DDD_MODULE_IF);
250
251 /* first delete possible old interface */
252 IFDeleteAll(context, ifId);
253
254 STAT_RESET1;
255 if (ifId==STD_INTERFACE)
256 {
257 theIF[ifId].cpl = IFCollectStdCouplings(context);
258 n = context.couplingContext().nCplItems;
259 }
260 else
261 {
262 int index;
263
264
265 /* collect relevant couplings into tmpcpl array */
266 n=0;
267 const auto& nCpls = context.couplingContext().nCpls;
268 for(index=0; index < nCpls; index++)
269 {
270 /* determine whether object belongs to IF */
271 if ((1<<OBJ_TYPE(objTable[index])) & theIF[ifId].maskO)
272 {
273 const bool objInA = is_elem(OBJ_PRIO(objTable[index]),
274 theIF[ifId].nPrioA, theIF[ifId].A);
275 const bool objInB = is_elem(OBJ_PRIO(objTable[index]),
276 theIF[ifId].nPrioB, theIF[ifId].B);
277
278 if (objInA || objInB)
279 {
280 COUPLING *cpl;
281
282 /* test coupling list */
283 for(cpl=IdxCplList(context, index); cpl!=NULL; cpl=CPL_NEXT(cpl))
284 {
285 const bool cplInA = is_elem(cpl->prio,
286 theIF[ifId].nPrioA, theIF[ifId].A);
287 const bool cplInB = is_elem(cpl->prio,
288 theIF[ifId].nPrioB, theIF[ifId].B);
289
290 /* compute possible IF directions */
291 const int dir = ((objInA&&cplInB) ? DirAB : 0) |
292 ((objInB&&cplInA) ? DirBA : 0);
293
294 if (dir != 0)
295 {
296 SETCPLDIR(cpl,dir);
297 tmpcpl[n] = cpl;
298 n++;
299 }
300 }
301 }
302 }
303 }
304
305 if (n>0)
306 {
307 /* re-alloc cpllist, now with correct size */
308 theIF[ifId].cpl = (COUPLING **) AllocIF(sizeof(COUPLING *)*n);
309 if (theIF[ifId].cpl==NULL)
310 {
311 Dune::dwarn << "IFCreateFromScratch: " STR_NOMEM " for IF "
312 << std::setw(2) << ifId << "\n";
313 RET_ON_ERROR;
314 }
315
316 /* copy data from temporary array */
317 memcpy((void *)theIF[ifId].cpl, (void *)tmpcpl, sizeof(COUPLING *)*n);
318 }
319 else
320 {
321 theIF[ifId].cpl = NULL;
322 }
323 }
324 STAT_TIMER1(T_CREATE_COLLECT);
325
326
327
328 /* sort IF couplings */
329 STAT_RESET1;
330 if (n>1)
331 std::sort(theIF[ifId].cpl, theIF[ifId].cpl + n, sort_IFCouplings);
332 STAT_TIMER1(T_CREATE_SORT);
333
334
335 /* create IF_PROCs */
336 STAT_RESET1;
337 lastproc = PROC_INVALID;
338 lastIfHead = NULL;
339 theIF[ifId].nIfHeads = 0;
340 for(i=0; i<n; i++)
341 {
342 COUPLING **cplp = &(theIF[ifId].cpl[i]);
343 COUPLING *cpl = *cplp;
344 DDD_ATTR attr = OBJ_ATTR(cpl->obj);
345
346 if (CPL_PROC(cpl) != lastproc)
347 {
348 /* create new IfHead */
349 theIF[ifId].nIfHeads++;
350 ifHead = new IF_PROC;
351 ifHead->cpl = cplp;
352 ifHead->proc = CPL_PROC(cpl);
353 ifHead->next = lastIfHead;
354 lastIfHead = ifHead;
355 lastproc = ifHead->proc;
356
357 ifHead->nAttrs = 1;
358 ifHead->ifAttr = ifAttr = new IF_ATTR(attr);
359 lastIfAttr = ifAttr;
360 }
361
362 /* count #items per processor */
363 ifHead->nItems++;
364
365
366 /* keep current ifAttr or find new one? */
367 if (attr!=ifAttr->attr)
368 {
369 IF_ATTR *ifR;
370
371 /* does ifAttr already exist? */
372 ifR = ifHead->ifAttr;
373 while ((ifR!=NULL) && (ifR->attr!=attr))
374 {
375 ifR=ifR->next;
376 }
377
378 if (ifR!=NULL)
379 {
380 /* reuse existing ifAttr */
381 ifAttr = ifR;
382 }
383 else
384 {
385 /* create new ifAttr */
386 ifHead->nAttrs++;
387 ifAttr = new IF_ATTR(attr);
388 lastIfAttr->next = ifAttr;
389 lastIfAttr = ifAttr;
390 }
391 }
392
393
394 /* count #items per processor and attr */
395 ifAttr->nItems++;
396
397
398 /* count #items per directions AB, BA or ABA
399 and set beginnings of AB/BA/ABA subarrays */
400 if (ifId!=STD_INTERFACE)
401 {
402 switch (CPLDIR(cpl))
403 {
404 case DirAB :
405 ifHead->nAB++;
406 if (ifHead->cplAB==0) ifHead->cplAB = cplp;
407 ifAttr->nAB++;
408 if (ifAttr->cplAB==0) ifAttr->cplAB = cplp;
409 break;
410
411 case DirBA :
412 ifHead->nBA++;
413 if (ifHead->cplBA==0) ifHead->cplBA = cplp;
414 ifAttr->nBA++;
415 if (ifAttr->cplBA==0) ifAttr->cplBA = cplp;
416 break;
417
418 case DirABA :
419 ifHead->nABA++;
420 if (ifHead->cplABA==0) ifHead->cplABA = cplp;
421 ifAttr->nABA++;
422 if (ifAttr->cplABA==0) ifAttr->cplABA = cplp;
423 break;
424 }
425 }
426 }
427 STAT_TIMER1(T_CREATE_BUILD);
428
429 /* remember anchor of ifHead list */
430 if (theIF[ifId].nIfHeads>0) {
431 theIF[ifId].ifHead = ifHead;
432 }
433
434 /* store overall number of coupling items */
435 theIF[ifId].nItems = n;
436
437
438 /* establish obj-table as an addressing shortcut */
439 STAT_RESET1;
440 IFCreateObjShortcut(context, ifId);
441 STAT_TIMER1(T_CREATE_SHORTCUT);
442
443
444 STAT_RESET1;
445 if (! IS_OK(update_channels(context, ifId)))
446 {
447 DDD_PrintError('E', 4003, "couldn't create communication channels");
448 RET_ON_ERROR;
449 }
450 STAT_TIMER1(T_CREATE_COMM);
451
452 /* TODO das handling der VCs muss noch erheblich verbessert werden */
453 /* TODO durch das is_elem suchen ist alles noch VERY inefficient */
454
455 STAT_SET_MODULE(STAT_MOD);
456
457 RET_ON_OK;
458 }
459
460
461 /****************************************************************************/
462 /* */
463 /* DDD_IFDefine */
464 /* */
465 /****************************************************************************/
466
467 /**
468 Definition of a DDD Interface.
469
470 This function defines a new \ddd{interface}. Its argument list contains
471 three arrays: the first one specifies a subset of the global DDD object set,
472 the second and third ones specify a subset of all DDD priorities.
473 After the initial creation of the new interface its ID is returned.
474
475 During all following DDD operations ({\bf Identify}- as well as
476 {\bf Transfer}-operations) the interface will be kept consistent, and can
477 be used for communication via \funk{IFExchange} and
478 \funk{IFOneway} and analogous functions.
479
480 @param nO number of entries in array {\it O[\ ]} (as specified with second argument).
481 @param O array of DDD type IDs; the new interface will only contain objects with one of these types.
482 @param nA number of entries in array {\it A[\ ]} (as specified with forth argument).
483 @param A first array of DDD priorities; the object set A from the new interface will only contain objects with one of these priorities.
484 @param nB number of entries in array {\it B[\ ]} (as specified with sixth argument).
485 @param B second array of DDD priorities; the object set B from the new interface will only contain objects with one of these priorities.
486 */
487
DDD_IFDefine(DDD::DDDContext & context,int nO,DDD_TYPE O[],int nA,DDD_PRIO A[],int nB,DDD_PRIO B[])488 DDD_IF DDD_IFDefine (
489 DDD::DDDContext& context,
490 int nO, DDD_TYPE O[],
491 int nA, DDD_PRIO A[],
492 int nB, DDD_PRIO B[])
493 {
494 auto& ctx = context.ifCreateContext();
495 auto& theIF = ctx.theIf;
496 auto& nIFs = ctx.nIfs;
497
498 int i;
499
500 if (nIFs==MAX_IF) {
501 DDD_PrintError('E', 4100, "no more interfaces in DDD_IFDefine");
502 return(0);
503 }
504
505 /* construct interface definition */
506 theIF[nIFs].nObjStruct = nO;
507 theIF[nIFs].nPrioA = nA;
508 theIF[nIFs].nPrioB = nB;
509 memcpy(theIF[nIFs].O, O, nO*sizeof(DDD_TYPE));
510 memcpy(theIF[nIFs].A, A, nA*sizeof(DDD_PRIO));
511 memcpy(theIF[nIFs].B, B, nB*sizeof(DDD_PRIO));
512 if (nO>1) std::sort(theIF[nIFs].O, theIF[nIFs].O + nO);
513 if (nA>1) std::sort(theIF[nIFs].A, theIF[nIFs].A + nA);
514 if (nB>1) std::sort(theIF[nIFs].B, theIF[nIFs].B + nB);
515
516 /* reset name string */
517 theIF[nIFs].name[0] = 0;
518
519 /* compute hash tables for fast access */
520 theIF[nIFs].maskO = 0;
521 for(i=0; i<nO; i++)
522 theIF[nIFs].maskO |= (1<<(unsigned int)O[i]);
523
524
525 /* create initial interface state */
526 theIF[nIFs].ifHead = NULL;
527 const auto& nCplItems = context.couplingContext().nCplItems;
528 if (nCplItems > 0)
529 {
530 /* allocate temporary cpl-list, this will be too large for
531 average interfaces. */
532 std::vector<COUPLING*> tmpcpl(nCplItems);
533
534 if (! IS_OK(IFCreateFromScratch(context, tmpcpl.data(), nIFs)))
535 {
536 DDD_PrintError('E', 4101, "cannot create interface in DDD_IFDefine");
537 return(0);
538 }
539 }
540 else
541 {
542 if (! IS_OK(IFCreateFromScratch(context, NULL, nIFs)))
543 {
544 DDD_PrintError('E', 4102, "cannot create interface in DDD_IFDefine");
545 return(0);
546 }
547 }
548
549
550 nIFs++;
551
552 return(nIFs-1);
553 }
554
555
556
StdIFDefine(DDD::DDDContext & context)557 static void StdIFDefine(DDD::DDDContext& context)
558 {
559 auto& theIF = context.ifCreateContext().theIf;
560
561 /* exception: no OBJSTRUCT or priority entries */
562 theIF[STD_INTERFACE].nObjStruct = 0;
563 theIF[STD_INTERFACE].nPrioA = 0;
564 theIF[STD_INTERFACE].nPrioB = 0;
565
566 theIF[STD_INTERFACE].maskO = 0xffff;
567
568
569 /* reset name string */
570 theIF[STD_INTERFACE].name[0] = '\0';
571
572
573 /* create initial interface state */
574 theIF[STD_INTERFACE].ifHead = NULL;
575 if (! IS_OK(IFCreateFromScratch(context, NULL, STD_INTERFACE)))
576 DUNE_THROW(Dune::Exception,
577 "cannot create standard interface during IF initialization");
578 }
579
580
581
DDD_IFSetName(DDD::DDDContext & context,DDD_IF ifId,const char * name)582 void DDD_IFSetName(DDD::DDDContext& context, DDD_IF ifId, const char *name)
583 {
584 auto& theIF = context.ifCreateContext().theIf;
585
586 /* copy name string */
587 strncpy(theIF[ifId].name, name, IF_NAMELEN-1);
588 }
589
590
591 /****************************************************************************/
592
writeCoupling(const DDD::DDDContext & context,const IF_PROC & ifh,const COUPLING & cpl,const char * obj,std::ostream & out)593 static void writeCoupling(const DDD::DDDContext& context, const IF_PROC& ifh, const COUPLING& cpl, const char* obj, std::ostream& out)
594 {
595 using std::setw;
596
597 out << "| gid=" << OBJ_GID(cpl.obj) << " proc=" << setw(4) << CPL_PROC(&cpl)
598 << " prio=" << setw(2) << cpl.prio
599 << "osc=" << obj << "/" << OBJ_OBJ(context, cpl.obj) << "\n";
600 }
601
DDD_InfoIFImpl(DDD::DDDContext & context,DDD_IF ifId)602 void DDD_InfoIFImpl(DDD::DDDContext& context, DDD_IF ifId)
603 {
604 using std::setw;
605
606 std::ostream& out = std::cout;
607 auto& theIF = context.ifCreateContext().theIf;
608
609 out << "|\n| DDD_IFInfoImpl for proc=" << context.me() << ", IF " << ifId << "\n";
610
611 out << "| cpl=" << theIF[ifId].cpl << " nIfHeads="
612 << theIF[ifId].nIfHeads << " first=" << theIF[ifId].ifHead << "\n";
613
614 for(const IF_PROC* ifh=theIF[ifId].ifHead; ifh!=nullptr; ifh=ifh->next)
615 {
616 out << "| head=" << ifh << " cpl=" << ifh->cpl
617 << " p=" << setw(3) << ifh->proc << " nItems=" << setw(5) << ifh->nItems
618 << " nAttrs=" << setw(3) << ifh->nAttrs << "\n";
619
620 out << "| nAB= " << setw(5) << ifh->nAB << "\n";
621 for(int i = 0; i < ifh->nAB; ++i)
622 writeCoupling(context, *ifh, *ifh->cplAB[i], ifh->objAB[i], out);
623
624 out << "| nBA= " << setw(5) << ifh->nBA << "\n";
625 for(int i = 0; i < ifh->nBA; ++i)
626 writeCoupling(context, *ifh, *ifh->cplBA[i], ifh->objBA[i], out);
627
628 out << "| nABA=" << setw(5) << ifh->nABA << "\n";
629 for(int i = 0; i < ifh->nABA; ++i)
630 writeCoupling(context, *ifh, *ifh->cplABA[i], ifh->objABA[i], out);
631 }
632
633 out << "|\n";
634 }
635
636
637
IFDisplay(const DDD::DDDContext & context,DDD_IF i)638 static void IFDisplay (const DDD::DDDContext& context, DDD_IF i)
639 {
640 using std::setw;
641
642 std::ostream& out = std::cout;
643 const auto& ctx = context.ifCreateContext();
644 const auto& theIF = ctx.theIf;
645
646 out << "| IF " << i << " ";
647 if (i==STD_INTERFACE)
648 {
649 out << "including all (" << setw(8) << std::hex << theIF[i].maskO << std::dec << ")\n"
650 << "| prio all to all\n";
651 }
652 else
653 {
654 out << "including ";
655 for(int j=0; j<theIF[i].nObjStruct; j++)
656 out << context.typeDefs()[theIF[i].O[j]].name << " ";
657 out << "(" << setw(8) << std::hex << theIF[i].maskO << std::dec << ")\n"
658 << "| prio ";
659 for(int j=0; j<theIF[i].nPrioA; j++)
660 out << theIF[i].A[j] << " ";
661 out << "to ";
662 for(int j=0; j<theIF[i].nPrioB; j++)
663 out << theIF[i].B[j] << " ";
664 out << "\n";
665 }
666
667 if (theIF[i].name[0]!=0)
668 out << "| '" << theIF[i].name << "'\n";
669
670 for(const IF_PROC* ifh=theIF[i].ifHead; ifh!=NULL; ifh=ifh->next)
671 {
672 if (DDD_GetOption(context, OPT_INFO_IF_WITH_ATTR)==OPT_OFF)
673 out << "| " << setw(3) << ifh->nItems << "="
674 << setw(3) << ifh->nAB << "," << setw(3) << ifh->nBA << "," << setw(3) << ifh->nABA
675 << " - " << setw(2) << ifh->proc << "\n";
676 else
677 {
678 out << "| " << setw(3) << ifh->nItems
679 << "=" << setw(3) << ifh->nAB << "," << setw(3) << ifh->nBA << "," << setw(3) << ifh->nABA
680 << " - " << setw(2) << ifh->proc << " - #a=" << setw(5) << ifh->nAttrs << "\n";
681
682 for (const IF_ATTR* ifr=ifh->ifAttr; ifr!=NULL; ifr=ifr->next)
683 {
684 out << "| a " << setw(3) << ifr->nItems << "="
685 << setw(3) << ifr->nAB << "," << setw(3) << ifr->nBA << "," << setw(3) << ifr->nABA
686 << " - " << setw(4) << ifr->attr << "\n";
687 }
688 }
689 }
690 }
691
692
693 /****************************************************************************/
694 /* */
695 /* DDD_IFDisplay */
696 /* */
697 /****************************************************************************/
698
699 /**
700 Display overview of single DDD interface.
701 This function displays an overview table for one DDD-interface,
702 its definition parameters and the current number of constituing objects
703 on the calling processor.
704
705 For each neighbour processor corresponding
706 to that interface a relation line is displayed, which contains
707 the overall number of objects inside the interface, the number of
708 oneway relations outwards, the number of oneway relations inwards,
709 the number of exchange relations and the neighbour processor number.
710
711 @param aIF the \ddd{interface} ID.
712 */
713
DDD_IFDisplay(const DDD::DDDContext & context,DDD_IF aIF)714 void DDD_IFDisplay(const DDD::DDDContext& context, DDD_IF aIF)
715 {
716 if (aIF >= context.ifCreateContext().nIfs)
717 {
718 Dune::dwarn << "DDD_IFDisplay: invalid IF " << std::setw(2) << aIF << "\n";
719 return;
720 }
721
722 std::cout << "|\n| DDD_IF-Info for proc=" << context.me() << "\n";
723
724 IFDisplay(context, aIF);
725
726 std::cout << "|\n";
727 }
728
729
730
731 /****************************************************************************/
732 /* */
733 /* DDD_IFDisplayAll */
734 /* */
735 /****************************************************************************/
736
737 /**
738 Display overview of all DDD interfaces.
739 This function displays an overview table containing all DDD-interfaces,
740 their definition parameters and the current number of constituing objects
741 on the calling processor.
742
743 For each interface and each neighbour processor corresponding
744 to that interface a relation line is displayed, which contains
745 the overall number of objects inside the interface, the number of
746 oneway relations outwards, the number of oneway relations inwards,
747 the number of exchange relations and the neighbour processor number.
748 */
749
DDD_IFDisplayAll(const DDD::DDDContext & context)750 void DDD_IFDisplayAll(const DDD::DDDContext& context)
751 {
752 std::cout << "|\n| DDD_IF-Info for proc=" << context.me() << " (all)\n";
753
754 const auto& nIFs = context.ifCreateContext().nIfs;
755 for(int i=0; i < nIFs; ++i)
756 {
757 IFDisplay(context, i);
758 }
759
760 std::cout << "|\n";
761 }
762
763
764
IFRebuildAll(DDD::DDDContext & context)765 static void IFRebuildAll(DDD::DDDContext& context)
766 {
767 /* create standard interface */
768 if (! IS_OK(IFCreateFromScratch(context, NULL, STD_INTERFACE)))
769 DUNE_THROW(Dune::Exception,
770 "cannot create standard interface in IFRebuildAll");
771
772
773 const auto& nIFs = context.ifCreateContext().nIfs;
774 if (nIFs>1)
775 {
776 int i;
777
778 const auto& nCplItems = context.couplingContext().nCplItems;
779 if (nCplItems > 0)
780 {
781 /* allocate temporary cpl-list, this will be too large for
782 average interfaces. */
783 std::vector<COUPLING*> tmpcpl(nCplItems);
784
785 /* TODO: ausnutzen, dass STD_IF obermenge von allen interfaces ist */
786 for(i=1; i<nIFs; i++)
787 {
788 if (! IS_OK(IFCreateFromScratch(context, tmpcpl.data(), i)))
789 DUNE_THROW(Dune::Exception,
790 "cannot create interface " << i);
791 /*
792 DDD_InfoIFImpl(context, i);
793 */
794 }
795 }
796 else
797 {
798 /* delete old interface structures */
799 for(i=1; i<nIFs; i++)
800 {
801 /* delete possible old interface */
802 IFDeleteAll(context, i);
803 }
804 }
805 }
806 }
807
808
IFAllFromScratch(DDD::DDDContext & context)809 void IFAllFromScratch(DDD::DDDContext& context)
810 {
811 if (DDD_GetOption(context, OPT_IF_CREATE_EXPLICIT)==OPT_ON)
812 {
813 /* interfaces must be created explicitly by calling
814 DDD_IFRefreshAll(). This is for doing timings from
815 application level. */
816 return;
817 }
818
819 IFRebuildAll(context);
820 }
821
822
823
DDD_IFRefreshAll(DDD::DDDContext & context)824 void DDD_IFRefreshAll(DDD::DDDContext& context)
825 {
826 if (DDD_GetOption(context, OPT_IF_CREATE_EXPLICIT)==OPT_OFF)
827 {
828 /* if interfaces are not created explicit, then they
829 are always kept consistent automatically. therefore,
830 this function is senseless. */
831 /* return; nevertheless, dont return, create interfaces
832 once more. just to be sure. */
833 }
834
835 IFRebuildAll(context);
836 }
837
838
839 /****************************************************************************/
840
ddd_IFInit(DDD::DDDContext & context)841 void ddd_IFInit(DDD::DDDContext& context)
842 {
843 auto& ctx = context.ifCreateContext();
844
845 /* init lists of unused items */
846 ctx.theIf[0].ifHead = nullptr;
847 ctx.theIf[0].cpl = nullptr;
848
849 /* init standard interface */
850 StdIFDefine(context);
851
852 /* no other interfaces yet */
853 ctx.nIfs = 1;
854 }
855
856
ddd_IFExit(DDD::DDDContext & context)857 void ddd_IFExit(DDD::DDDContext& context)
858 {
859 const auto& nIFs = context.ifCreateContext().nIfs;
860 for(int i=0; i < nIFs; i++)
861 IFDeleteAll(context, i);
862 }
863
864
865 /****************************************************************************/
866
867
IFInfoMemory(const DDD::DDDContext & context,DDD_IF ifId)868 static size_t IFInfoMemory(const DDD::DDDContext& context, DDD_IF ifId)
869 {
870 const auto& theIF = context.ifCreateContext().theIf;
871
872 size_t sum=0;
873
874 sum += sizeof(IF_PROC) * theIF[ifId].nIfHeads; /* component ifHead */
875 sum += sizeof(COUPLING *) * theIF[ifId].nItems; /* component cpl */
876 sum += sizeof(IFObjPtr) * theIF[ifId].nItems; /* component obj */
877
878 for(const IF_PROC* ifp=theIF[ifId].ifHead; ifp != nullptr; ifp=ifp->next)
879 {
880 sum += sizeof(IF_ATTR) * ifp->nAttrs; /* component ifAttr */
881 }
882
883 return(sum);
884 }
885
886
887
DDD_IFInfoMemory(const DDD::DDDContext & context,DDD_IF ifId)888 size_t DDD_IFInfoMemory(const DDD::DDDContext& context, DDD_IF ifId)
889 {
890 if (ifId >= context.ifCreateContext().nIfs)
891 DUNE_THROW(Dune::Exception, "invalid interface " << ifId);
892
893 return IFInfoMemory(context, ifId);
894 }
895
896
DDD_IFInfoMemoryAll(const DDD::DDDContext & context)897 size_t DDD_IFInfoMemoryAll(const DDD::DDDContext& context)
898 {
899 const auto& nIFs = context.ifCreateContext().nIfs;
900
901 size_t sum = 0;
902 for(int i = 0; i < nIFs; ++i)
903 {
904 sum += IFInfoMemory(context, i);
905 }
906
907 return(sum);
908 }
909
910 END_UGDIM_NAMESPACE
911
912 /****************************************************************************/
913