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