Actual source code: dmshell.c

petsc-3.5.1 2014-07-24
Report Typos and Errors
  1: #include <petscdmshell.h>       /*I    "petscdmshell.h"  I*/
  2: #include <petscmat.h>
  3: #include <petsc-private/dmimpl.h>

  5: typedef struct  {
  6:   Vec        Xglobal;
  7:   Vec        Xlocal;
  8:   Mat        A;
  9:   VecScatter gtol;
 10:   VecScatter ltog;
 11:   VecScatter ltol;
 12: } DM_Shell;

 16: /*@
 17:    DMGlobalToLocalBeginDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to begin a global to local scatter
 18:    Collective

 20:    Input Arguments:
 21: +  dm - shell DM
 22: .  g - global vector
 23: .  mode - InsertMode
 24: -  l - local vector

 26:    Level: advanced

 28:    Note:  This is not normally called directly by user code, generally user code calls DMGlobalToLocalBegin() and DMGlobalToLocalEnd(). If the user provides their own custom routines to DMShellSetLocalToGlobal() then those routines might have reason to call this function. 

 30: .seealso: DMGlobalToLocalEndDefaultShell()
 31: @*/
 32: PetscErrorCode DMGlobalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
 33: {
 35:   DM_Shell       *shell = (DM_Shell*)dm->data;

 38:   if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
 39:   VecScatterBegin(shell->gtol,g,l,mode,SCATTER_FORWARD);
 40:   return(0);
 41: }

 45: /*@
 46:    DMGlobalToLocalEndDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to end a global to local scatter
 47:    Collective

 49:    Input Arguments:
 50: +  dm - shell DM
 51: .  g - global vector
 52: .  mode - InsertMode
 53: -  l - local vector

 55:    Level: advanced

 57: .seealso: DMGlobalToLocalBeginDefaultShell()
 58: @*/
 59: PetscErrorCode DMGlobalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
 60: {
 62:   DM_Shell       *shell = (DM_Shell*)dm->data;

 65:    if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
 66:   VecScatterEnd(shell->gtol,g,l,mode,SCATTER_FORWARD);
 67:   return(0);
 68: }

 72: /*@
 73:    DMLocalToGlobalBeginDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to begin a local to global scatter
 74:    Collective

 76:    Input Arguments:
 77: +  dm - shell DM
 78: .  l - local vector
 79: .  mode - InsertMode
 80: -  g - global vector

 82:    Level: advanced

 84:    Note:  This is not normally called directly by user code, generally user code calls DMLocalToGlobalBegin() and DMLocalToGlobalEnd(). If the user provides their own custom routines to DMShellSetLocalToGlobal() then those routines might have reason to call this function. 

 86: .seealso: DMLocalToGlobalEndDefaultShell()
 87: @*/
 88: PetscErrorCode DMLocalToGlobalBeginDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
 89: {
 91:   DM_Shell       *shell = (DM_Shell*)dm->data;

 94:   if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
 95:   VecScatterBegin(shell->ltog,l,g,mode,SCATTER_FORWARD);
 96:   return(0);
 97: }

101: /*@
102:    DMLocalToGlobalEndDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to end a local to global scatter
103:    Collective

105:    Input Arguments:
106: +  dm - shell DM
107: .  l - local vector
108: .  mode - InsertMode
109: -  g - global vector

111:    Level: advanced

113: .seealso: DMLocalToGlobalBeginDefaultShell()
114: @*/
115: PetscErrorCode DMLocalToGlobalEndDefaultShell(DM dm,Vec l,InsertMode mode,Vec g)
116: {
118:   DM_Shell       *shell = (DM_Shell*)dm->data;

121:    if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()");
122:   VecScatterEnd(shell->ltog,l,g,mode,SCATTER_FORWARD);
123:   return(0);
124: }

128: /*@
129:    DMLocalToLocalBeginDefaultShell - Uses the LocalToLocal VecScatter context set by the user to begin a local to local scatter
130:    Collective

132:    Input Arguments:
133: +  dm - shell DM
134: .  g - the original local vector
135: -  mode - InsertMode

137:    Output Parameter:
138: .  l  - the local vector with correct ghost values

140:    Level: advanced

142:    Note:  This is not normally called directly by user code, generally user code calls DMLocalToLocalBegin() and DMLocalToLocalEnd(). If the user provides their own custom routines to DMShellSetLocalToLocal() then those routines might have reason to call this function. 

144: .seealso: DMLocalToLocalEndDefaultShell()
145: @*/
146: PetscErrorCode DMLocalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
147: {
149:   DM_Shell       *shell = (DM_Shell*)dm->data;

152:   if (!shell->ltol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToLocalVecScatter()");
153:   VecScatterBegin(shell->ltol,g,l,mode,SCATTER_FORWARD);
154:   return(0);
155: }

159: /*@
160:    DMLocalToLocalEndDefaultShell - Uses the LocalToLocal VecScatter context set by the user to end a local to local scatter
161:    Collective

163:    Input Arguments:
164: +  dm - shell DM
165: .  g - the original local vector
166: -  mode - InsertMode

168:    Output Parameter:
169: .  l  - the local vector with correct ghost values

171:    Level: advanced

173: .seealso: DMLocalToLocalBeginDefaultShell()
174: @*/
175: PetscErrorCode DMLocalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l)
176: {
178:   DM_Shell       *shell = (DM_Shell*)dm->data;

181:    if (!shell->ltol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()");
182:   VecScatterEnd(shell->ltol,g,l,mode,SCATTER_FORWARD);
183:   return(0);
184: }

188: static PetscErrorCode DMCreateMatrix_Shell(DM dm,Mat *J)
189: {
191:   DM_Shell       *shell = (DM_Shell*)dm->data;
192:   Mat            A;

197:   if (!shell->A) {
198:     if (shell->Xglobal) {
199:       PetscInt m,M;
200:       PetscInfo(dm,"Naively creating matrix using global vector distribution without preallocation");
201:       VecGetSize(shell->Xglobal,&M);
202:       VecGetLocalSize(shell->Xglobal,&m);
203:       MatCreate(PetscObjectComm((PetscObject)dm),&shell->A);
204:       MatSetSizes(shell->A,m,m,M,M);
205:       MatSetType(shell->A,dm->mattype);
206:       MatSetUp(shell->A);
207:     } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetMatrix(), DMShellSetCreateMatrix(), or provide a vector");
208:   }
209:   A = shell->A;
210:   /* the check below is tacky and incomplete */
211:   if (dm->mattype) {
212:     PetscBool flg,aij,seqaij,mpiaij;
213:     PetscObjectTypeCompare((PetscObject)A,dm->mattype,&flg);
214:     PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&seqaij);
215:     PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&mpiaij);
216:     PetscStrcmp(dm->mattype,MATAIJ,&aij);
217:     if (!flg) {
218:       if (!(aij && (seqaij || mpiaij))) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_NOTSAMETYPE,"Requested matrix of type %s, but only %s available",dm->mattype,((PetscObject)A)->type_name);
219:     }
220:   }
221:   if (((PetscObject)A)->refct < 2) { /* We have an exclusive reference so we can give it out */
222:     PetscObjectReference((PetscObject)A);
223:     MatZeroEntries(A);
224:     *J   = A;
225:   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
226:     MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);
227:     MatZeroEntries(*J);
228:   }
229:   return(0);
230: }

234: PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec)
235: {
237:   DM_Shell       *shell = (DM_Shell*)dm->data;
238:   Vec            X;

243:   *gvec = 0;
244:   X     = shell->Xglobal;
245:   if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()");
246:   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
247:     PetscObjectReference((PetscObject)X);
248:     VecZeroEntries(X);
249:     *gvec = X;
250:   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
251:     VecDuplicate(X,gvec);
252:     VecZeroEntries(*gvec);
253:   }
254:   VecSetDM(*gvec,dm);
255:   return(0);
256: }

260: PetscErrorCode DMCreateLocalVector_Shell(DM dm,Vec *gvec)
261: {
263:   DM_Shell       *shell = (DM_Shell*)dm->data;
264:   Vec            X;

269:   *gvec = 0;
270:   X     = shell->Xlocal;
271:   if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetLocalVector() or DMShellSetCreateLocalVector()");
272:   if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */
273:     PetscObjectReference((PetscObject)X);
274:     VecZeroEntries(X);
275:     *gvec = X;
276:   } else {                      /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */
277:     VecDuplicate(X,gvec);
278:     VecZeroEntries(*gvec);
279:   }
280:   VecSetDM(*gvec,dm);
281:   return(0);
282: }

286: /*@
287:    DMShellSetMatrix - sets a template matrix associated with the DMShell

289:    Collective

291:    Input Arguments:
292: +  dm - shell DM
293: -  J - template matrix

295:    Level: advanced

297: .seealso: DMCreateMatrix(), DMShellSetCreateMatrix()
298: @*/
299: PetscErrorCode DMShellSetMatrix(DM dm,Mat J)
300: {
301:   DM_Shell       *shell = (DM_Shell*)dm->data;
303:   PetscBool      isshell;

308:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
309:   if (!isshell) return(0);
310:   PetscObjectReference((PetscObject)J);
311:   MatDestroy(&shell->A);
312:   shell->A = J;
313:   return(0);
314: }

318: /*@C
319:    DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM

321:    Logically Collective on DM

323:    Input Arguments:
324: +  dm - the shell DM
325: -  func - the function to create a matrix

327:    Level: advanced

329: .seealso: DMCreateMatrix(), DMShellSetMatrix()
330: @*/
331: PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,Mat*))
332: {

336:   dm->ops->creatematrix = func;
337:   return(0);
338: }

342: /*@
343:    DMShellSetGlobalVector - sets a template global vector associated with the DMShell

345:    Logically Collective on DM

347:    Input Arguments:
348: +  dm - shell DM
349: -  X - template vector

351:    Level: advanced

353: .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector()
354: @*/
355: PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X)
356: {
357:   DM_Shell       *shell = (DM_Shell*)dm->data;
359:   PetscBool      isshell;

364:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
365:   if (!isshell) return(0);
366:   PetscObjectReference((PetscObject)X);
367:   VecDestroy(&shell->Xglobal);
368:   shell->Xglobal = X;
369:   return(0);
370: }

374: /*@C
375:    DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM

377:    Logically Collective

379:    Input Arguments:
380: +  dm - the shell DM
381: -  func - the creation routine

383:    Level: advanced

385: .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix()
386: @*/
387: PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
388: {

392:   dm->ops->createglobalvector = func;
393:   return(0);
394: }

398: /*@
399:    DMShellSetLocalVector - sets a template local vector associated with the DMShell

401:    Logically Collective on DM

403:    Input Arguments:
404: +  dm - shell DM
405: -  X - template vector

407:    Level: advanced

409: .seealso: DMCreateLocalVector(), DMShellSetMatrix(), DMShellSetCreateLocalVector()
410: @*/
411: PetscErrorCode DMShellSetLocalVector(DM dm,Vec X)
412: {
413:   DM_Shell       *shell = (DM_Shell*)dm->data;
415:   PetscBool      isshell;

420:   PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);
421:   if (!isshell) return(0);
422:   PetscObjectReference((PetscObject)X);
423:   VecDestroy(&shell->Xlocal);
424:   shell->Xlocal = X;
425:   return(0);
426: }

430: /*@C
431:    DMShellSetCreateLocalVector - sets the routine to create a local vector associated with the shell DM

433:    Logically Collective

435:    Input Arguments:
436: +  dm - the shell DM
437: -  func - the creation routine

439:    Level: advanced

441: .seealso: DMShellSetLocalVector(), DMShellSetCreateMatrix()
442: @*/
443: PetscErrorCode DMShellSetCreateLocalVector(DM dm,PetscErrorCode (*func)(DM,Vec*))
444: {

448:   dm->ops->createlocalvector = func;
449:   return(0);
450: }

454: /*@C
455:    DMShellSetGlobalToLocal - Sets the routines used to perform a global to local scatter

457:    Logically Collective on DM

459:    Input Arguments
460: +  dm - the shell DM
461: .  begin - the routine that begins the global to local scatter
462: -  end - the routine that ends the global to local scatter

464:    Notes: If these functions are not provided but DMShellSetGlobalToLocalVecScatter() is called then
465:    DMGlobalToLocalBeginDefaultShell()/DMGlobalToLocalEndDefaultShell() are used to to perform the transfers 

467:    Level: advanced

469: .seealso: DMShellSetLocalToGlobal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell()
470: @*/
471: PetscErrorCode DMShellSetGlobalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
473:   dm->ops->globaltolocalbegin = begin;
474:   dm->ops->globaltolocalend = end;
475:   return(0);
476: }

480: /*@C
481:    DMShellSetLocalToGlobal - Sets the routines used to perform a local to global scatter

483:    Logically Collective on DM

485:    Input Arguments
486: +  dm - the shell DM
487: .  begin - the routine that begins the local to global scatter
488: -  end - the routine that ends the local to global scatter

490:    Notes: If these functions are not provided but DMShellSetLocalToGlobalVecScatter() is called then
491:    DMLocalToGlobalBeginDefaultShell()/DMLocalToGlobalEndDefaultShell() are used to to perform the transfers 

493:    Level: advanced

495: .seealso: DMShellSetGlobalToLocal()
496: @*/
497: PetscErrorCode DMShellSetLocalToGlobal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
499:   dm->ops->localtoglobalbegin = begin;
500:   dm->ops->localtoglobalend = end;
501:   return(0);
502: }

506: /*@C
507:    DMShellSetLocalToLocal - Sets the routines used to perform a local to local scatter

509:    Logically Collective on DM

511:    Input Arguments
512: +  dm - the shell DM
513: .  begin - the routine that begins the local to local scatter
514: -  end - the routine that ends the local to local scatter

516:    Notes: If these functions are not provided but DMShellSetLocalToLocalVecScatter() is called then
517:    DMLocalToLocalBeginDefaultShell()/DMLocalToLocalEndDefaultShell() are used to to perform the transfers 

519:    Level: advanced

521: .seealso: DMShellSetGlobalToLocal(), DMLocalToLocalBeginDefaultShell(), DMLocalToLocalEndDefaultShell()
522: @*/
523: PetscErrorCode DMShellSetLocalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) {
525:   dm->ops->localtolocalbegin = begin;
526:   dm->ops->localtolocalend = end;
527:   return(0);
528: }

532: /*@
533:    DMShellSetGlobalToLocalVecScatter - Sets a VecScatter context for global to local communication

535:    Logically Collective on DM

537:    Input Arguments
538: +  dm - the shell DM
539: -  gtol - the global to local VecScatter context

541:    Level: advanced

543: .seealso: DMShellSetGlobalToLocal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell()
544: @*/
545: PetscErrorCode DMShellSetGlobalToLocalVecScatter(DM dm, VecScatter gtol)
546: {
547:   DM_Shell       *shell = (DM_Shell*)dm->data;

551:   PetscObjectReference((PetscObject)gtol);
552:   /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
553:   VecScatterDestroy(&shell->gtol);
554:   shell->gtol = gtol;
555:   return(0);
556: }

560: /*@
561:    DMShellSetLocalToGlobalVecScatter - Sets a VecScatter context for local to global communication

563:    Logically Collective on DM

565:    Input Arguments
566: +  dm - the shell DM
567: -  ltog - the local to global VecScatter context

569:    Level: advanced

571: .seealso: DMShellSetLocalToGlobal(), DMLocalToGlobalBeginDefaultShell(), DMLocalToGlobalEndDefaultShell()
572: @*/
573: PetscErrorCode DMShellSetLocalToGlobalVecScatter(DM dm, VecScatter ltog)
574: {
575:   DM_Shell       *shell = (DM_Shell*)dm->data;

579:   PetscObjectReference((PetscObject)ltog);
580:   /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
581:   VecScatterDestroy(&shell->ltog);
582:   shell->ltog = ltog;
583:   return(0);
584: }

588: /*@
589:    DMShellSetLocalToLocalVecScatter - Sets a VecScatter context for local to local communication

591:    Logically Collective on DM

593:    Input Arguments
594: +  dm - the shell DM
595: -  ltol - the local to local VecScatter context

597:    Level: advanced

599: .seealso: DMShellSetLocalToLocal(), DMLocalToLocalBeginDefaultShell(), DMLocalToLocalEndDefaultShell()
600: @*/
601: PetscErrorCode DMShellSetLocalToLocalVecScatter(DM dm, VecScatter ltol)
602: {
603:   DM_Shell       *shell = (DM_Shell*)dm->data;

607:   PetscObjectReference((PetscObject)ltol);
608:   /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */
609:   VecScatterDestroy(&shell->ltol);
610:   shell->ltol = ltol;
611:   return(0);
612: }

616: static PetscErrorCode DMDestroy_Shell(DM dm)
617: {
619:   DM_Shell       *shell = (DM_Shell*)dm->data;

622:   MatDestroy(&shell->A);
623:   VecDestroy(&shell->Xglobal);
624:   VecDestroy(&shell->Xlocal);
625:   VecScatterDestroy(&shell->gtol);
626:   VecScatterDestroy(&shell->ltog);
627:   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
628:   PetscFree(shell);
629:   return(0);
630: }

634: static PetscErrorCode DMView_Shell(DM dm,PetscViewer v)
635: {
637:   DM_Shell       *shell = (DM_Shell*)dm->data;

640:   VecView(shell->Xglobal,v);
641:   return(0);
642: }

646: static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v)
647: {
649:   DM_Shell       *shell = (DM_Shell*)dm->data;

652:   VecCreate(PetscObjectComm((PetscObject)dm),&shell->Xglobal);
653:   VecLoad(shell->Xglobal,v);
654:   return(0);
655: }

659: PetscErrorCode DMCreateSubDM_Shell(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
660: {

664:   if (subdm) {DMShellCreate(PetscObjectComm((PetscObject) dm), subdm);}
665:   DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);
666:   return(0);
667: }

671: PETSC_EXTERN PetscErrorCode DMCreate_Shell(DM dm)
672: {
674:   DM_Shell       *shell;

677:   PetscNewLog(dm,&shell);
678:   dm->data = shell;

680:   PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);

682:   dm->ops->destroy            = DMDestroy_Shell;
683:   dm->ops->createglobalvector = DMCreateGlobalVector_Shell;
684:   dm->ops->createlocalvector  = DMCreateLocalVector_Shell;
685:   dm->ops->creatematrix       = DMCreateMatrix_Shell;
686:   dm->ops->view               = DMView_Shell;
687:   dm->ops->load               = DMLoad_Shell;
688:   dm->ops->globaltolocalbegin = DMGlobalToLocalBeginDefaultShell;
689:   dm->ops->globaltolocalend   = DMGlobalToLocalEndDefaultShell;
690:   dm->ops->localtoglobalbegin = DMLocalToGlobalBeginDefaultShell;
691:   dm->ops->localtoglobalend   = DMLocalToGlobalEndDefaultShell;
692:   dm->ops->localtolocalbegin  = DMLocalToLocalBeginDefaultShell;
693:   dm->ops->localtolocalend    = DMLocalToLocalEndDefaultShell;
694:   dm->ops->createsubdm        = DMCreateSubDM_Shell;
695:   return(0);
696: }

700: /*@
701:     DMShellCreate - Creates a shell DM object, used to manage user-defined problem data

703:     Collective on MPI_Comm

705:     Input Parameter:
706: .   comm - the processors that will share the global vector

708:     Output Parameters:
709: .   shell - the shell DM

711:     Level: advanced

713: .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateLocalVector()
714: @*/
715: PetscErrorCode  DMShellCreate(MPI_Comm comm,DM *dm)
716: {

721:   DMCreate(comm,dm);
722:   DMSetType(*dm,DMSHELL);
723:   DMSetUp(*dm);
724:   return(0);
725: }