Actual source code: dm.c

  1: 
  2: #include <private/dmimpl.h>     /*I      "petscdm.h"     I*/

  4: PetscClassId  DM_CLASSID;
  5: PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal;

  9: /*@
 10:   DMCreate - Creates an empty vector object. The type can then be set with DMetType().

 12:    If you never  call DMSetType()  it will generate an 
 13:    error when you try to use the vector.

 15:   Collective on MPI_Comm

 17:   Input Parameter:
 18: . comm - The communicator for the DM object

 20:   Output Parameter:
 21: . dm - The DM object

 23:   Level: beginner

 25: .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE
 26: @*/
 27: PetscErrorCode  DMCreate(MPI_Comm comm,DM *dm)
 28: {
 29:   DM             v;

 34:   *dm = PETSC_NULL;
 35: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
 36:   DMInitializePackage(PETSC_NULL);
 37: #endif

 39:   PetscHeaderCreate(v, _p_DM, struct _DMOps, DM_CLASSID, -1, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);
 40:   PetscMemzero(v->ops, sizeof(struct _DMOps));

 42:   v->ltogmap      = PETSC_NULL;
 43:   v->ltogmapb     = PETSC_NULL;
 44:   v->bs           = 1;

 46:   *dm = v;
 47:   return(0);
 48: }


 53: /*@C
 54:        DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()

 56:    Logically Collective on DMDA

 58:    Input Parameter:
 59: +  da - initial distributed array
 60: .  ctype - the vector type, currently either VECSTANDARD or VECCUSP

 62:    Options Database:
 63: .   -da_vec_type ctype

 65:    Level: intermediate

 67: .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType, VecType
 68: @*/
 69: PetscErrorCode  DMSetVecType(DM da,const VecType ctype)
 70: {

 75:   PetscFree(da->vectype);
 76:   PetscStrallocpy(ctype,&da->vectype);
 77:   return(0);
 78: }

 82: /*@C
 83:    DMSetOptionsPrefix - Sets the prefix used for searching for all 
 84:    DMDA options in the database.

 86:    Logically Collective on DMDA

 88:    Input Parameter:
 89: +  da - the DMDA context
 90: -  prefix - the prefix to prepend to all option names

 92:    Notes:
 93:    A hyphen (-) must NOT be given at the beginning of the prefix name.
 94:    The first character of all runtime options is AUTOMATICALLY the hyphen.

 96:    Level: advanced

 98: .keywords: DMDA, set, options, prefix, database

100: .seealso: DMSetFromOptions()
101: @*/
102: PetscErrorCode  DMSetOptionsPrefix(DM dm,const char prefix[])
103: {

108:   PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);
109:   return(0);
110: }

114: /*@
115:     DMDestroy - Destroys a vector packer or DMDA.

117:     Collective on DM

119:     Input Parameter:
120: .   dm - the DM object to destroy

122:     Level: developer

124: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()

126: @*/
127: PetscErrorCode  DMDestroy(DM *dm)
128: {
129:   PetscInt       i, cnt = 0;

133:   if (!*dm) return(0);

136:   /* count all the circular references of DM and its contained Vecs */
137:   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
138:     if ((*dm)->localin[i])  {cnt++;}
139:     if ((*dm)->globalin[i]) {cnt++;}
140:   }
141:   if ((*dm)->x) {
142:     PetscObject obj;
143:     PetscObjectQuery((PetscObject)(*dm)->x,"DM",&obj);
144:     if (obj == (PetscObject)*dm) cnt++;
145:   }

147:   if (--((PetscObject)(*dm))->refct - cnt > 0) {*dm = 0; return(0);}
148:   /*
149:      Need this test because the dm references the vectors that
150:      reference the dm, so destroying the dm calls destroy on the
151:      vectors that cause another destroy on the dm
152:   */
153:   if (((PetscObject)(*dm))->refct < 0) return(0);
154:   ((PetscObject) (*dm))->refct = 0;
155:   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
156:     if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()");
157:     VecDestroy(&(*dm)->localin[i]);
158:   }
159:   VecDestroy(&(*dm)->x);
160:   MatFDColoringDestroy(&(*dm)->fd);
161:   DMClearGlobalVectors(*dm);
162:   ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);
163:   ISLocalToGlobalMappingDestroy(&(*dm)->ltogmapb);
164:   PetscFree((*dm)->vectype);
165:   PetscFree((*dm)->mattype);
166:   /* if memory was published with AMS then destroy it */
167:   PetscObjectDepublish(*dm);

169:   (*(*dm)->ops->destroy)(*dm);
170:   PetscFree((*dm)->data);
171:   PetscHeaderDestroy(dm);
172:   return(0);
173: }

177: /*@
178:     DMSetUp - sets up the data structures inside a DM object

180:     Collective on DM

182:     Input Parameter:
183: .   dm - the DM object to setup

185:     Level: developer

187: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()

189: @*/
190: PetscErrorCode  DMSetUp(DM dm)
191: {

195:   if (dm->setupcalled) return(0);
196:   if (dm->ops->setup) {
197:     (*dm->ops->setup)(dm);
198:   }
199:   dm->setupcalled = PETSC_TRUE;
200:   return(0);
201: }

205: /*@
206:     DMSetFromOptions - sets parameters in a DM from the options database

208:     Collective on DM

210:     Input Parameter:
211: .   dm - the DM object to set options for

213:     Options Database:
214: .   -dm_preallocate_only: Only preallocate the matrix for DMGetMatrix(), but do not fill it with zeros

216:     Level: developer

218: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()

220: @*/
221: PetscErrorCode  DMSetFromOptions(DM dm)
222: {
223:   PetscBool      flg1 = PETSC_FALSE,flg;
225:   char           mtype[256] = MATAIJ;

228:   if (dm->ops->setfromoptions) {
229:     (*dm->ops->setfromoptions)(dm);
230:   }
231:   PetscObjectOptionsBegin((PetscObject)dm);
232:     PetscOptionsBool("-dm_view", "Information on DM", "DMView", flg1, &flg1, PETSC_NULL);
233:     PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,PETSC_NULL);
234:     PetscOptionsList("-dm_mat_type","Matrix type","MatSetType",MatList,mtype,mtype,sizeof mtype,&flg);
235:     if (flg) {
236:       PetscFree(dm->mattype);
237:       PetscStrallocpy(mtype,&dm->mattype);
238:     }
239:   PetscOptionsEnd();
240:   if (flg1) {
241:     DMView(dm, PETSC_VIEWER_STDOUT_WORLD);
242:   }
243:   return(0);
244: }

248: /*@C
249:     DMView - Views a vector packer or DMDA.

251:     Collective on DM

253:     Input Parameter:
254: +   dm - the DM object to view
255: -   v - the viewer

257:     Level: developer

259: .seealso DMDestroy(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()

261: @*/
262: PetscErrorCode  DMView(DM dm,PetscViewer v)
263: {

267:  if (!v) {
268:     PetscViewerASCIIGetStdout(((PetscObject)dm)->comm,&v);
269:   }
270:   if (dm->ops->view) {
271:     (*dm->ops->view)(dm,v);
272:   }
273:   return(0);
274: }

278: /*@
279:     DMCreateGlobalVector - Creates a global vector from a DMDA or DMComposite object

281:     Collective on DM

283:     Input Parameter:
284: .   dm - the DM object

286:     Output Parameter:
287: .   vec - the global vector

289:     Level: beginner

291: .seealso DMDestroy(), DMView(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()

293: @*/
294: PetscErrorCode  DMCreateGlobalVector(DM dm,Vec *vec)
295: {

299:   (*dm->ops->createglobalvector)(dm,vec);
300:   return(0);
301: }

305: /*@
306:     DMCreateLocalVector - Creates a local vector from a DMDA or DMComposite object

308:     Not Collective

310:     Input Parameter:
311: .   dm - the DM object

313:     Output Parameter:
314: .   vec - the local vector

316:     Level: beginner

318: .seealso DMDestroy(), DMView(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix()

320: @*/
321: PetscErrorCode  DMCreateLocalVector(DM dm,Vec *vec)
322: {

326:   (*dm->ops->createlocalvector)(dm,vec);
327:   return(0);
328: }

332: /*@
333:    DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM.

335:    Collective on DM

337:    Input Parameter:
338: .  dm - the DM that provides the mapping

340:    Output Parameter:
341: .  ltog - the mapping

343:    Level: intermediate

345:    Notes:
346:    This mapping can then be used by VecSetLocalToGlobalMapping() or
347:    MatSetLocalToGlobalMapping().

349: .seealso: DMCreateLocalVector(), DMGetLocalToGlobalMappingBlock()
350: @*/
351: PetscErrorCode  DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog)
352: {

358:   if (!dm->ltogmap) {
359:     if (!dm->ops->createlocaltoglobalmapping) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping");
360:     (*dm->ops->createlocaltoglobalmapping)(dm);
361:   }
362:   *ltog = dm->ltogmap;
363:   return(0);
364: }

368: /*@
369:    DMGetLocalToGlobalMappingBlock - Accesses the blocked local-to-global mapping in a DM.

371:    Collective on DM

373:    Input Parameter:
374: .  da - the distributed array that provides the mapping

376:    Output Parameter:
377: .  ltog - the block mapping

379:    Level: intermediate

381:    Notes:
382:    This mapping can then be used by VecSetLocalToGlobalMappingBlock() or
383:    MatSetLocalToGlobalMappingBlock().

385: .seealso: DMCreateLocalVector(), DMGetLocalToGlobalMapping(), DMGetBlockSize(), VecSetBlockSize(), MatSetBlockSize()
386: @*/
387: PetscErrorCode  DMGetLocalToGlobalMappingBlock(DM dm,ISLocalToGlobalMapping *ltog)
388: {

394:   if (!dm->ltogmapb) {
395:     PetscInt bs;
396:     DMGetBlockSize(dm,&bs);
397:     if (bs > 1) {
398:       if (!dm->ops->createlocaltoglobalmappingblock) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"DM can not create LocalToGlobalMappingBlock");
399:       (*dm->ops->createlocaltoglobalmappingblock)(dm);
400:     } else {
401:       DMGetLocalToGlobalMapping(dm,&dm->ltogmapb);
402:       PetscObjectReference((PetscObject)dm->ltogmapb);
403:     }
404:   }
405:   *ltog = dm->ltogmapb;
406:   return(0);
407: }

411: /*@
412:    DMGetBlockSize - Gets the inherent block size associated with a DM

414:    Not Collective

416:    Input Parameter:
417: .  dm - the DM with block structure

419:    Output Parameter:
420: .  bs - the block size, 1 implies no exploitable block structure

422:    Level: intermediate

424: .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMappingBlock()
425: @*/
426: PetscErrorCode  DMGetBlockSize(DM dm,PetscInt *bs)
427: {
431:   if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet");
432:   *bs = dm->bs;
433:   return(0);
434: }

438: /*@
439:     DMGetInterpolation - Gets interpolation matrix between two DMDA or DMComposite objects

441:     Collective on DM

443:     Input Parameter:
444: +   dm1 - the DM object
445: -   dm2 - the second, finer DM object

447:     Output Parameter:
448: +  mat - the interpolation
449: -  vec - the scaling (optional)

451:     Level: developer

453:     Notes:  For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 
454:         DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.

456:         For DMDA objects you can use this interpolation (more precisely the interpolation from the DMDAGetCoordinateDA()) to interpolate the mesh coordinate vectors
457:         EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
458:    

460: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetColoring(), DMGetMatrix(), DMRefine(), DMCoarsen()

462: @*/
463: PetscErrorCode  DMGetInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec)
464: {

468:   (*dm1->ops->getinterpolation)(dm1,dm2,mat,vec);
469:   return(0);
470: }

474: /*@
475:     DMGetInjection - Gets injection matrix between two DMDA or DMComposite objects

477:     Collective on DM

479:     Input Parameter:
480: +   dm1 - the DM object
481: -   dm2 - the second, finer DM object

483:     Output Parameter:
484: .   ctx - the injection

486:     Level: developer

488:    Notes:  For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 
489:         DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection.

491: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetColoring(), DMGetMatrix(), DMGetInterpolation()

493: @*/
494: PetscErrorCode  DMGetInjection(DM dm1,DM dm2,VecScatter *ctx)
495: {

499:   (*dm1->ops->getinjection)(dm1,dm2,ctx);
500:   return(0);
501: }

505: /*@C
506:     DMGetColoring - Gets coloring for a DMDA or DMComposite

508:     Collective on DM

510:     Input Parameter:
511: +   dm - the DM object
512: .   ctype - IS_COLORING_GHOSTED or IS_COLORING_GLOBAL
513: -   matype - either MATAIJ or MATBAIJ

515:     Output Parameter:
516: .   coloring - the coloring

518:     Level: developer

520: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetMatrix()

522: @*/
523: PetscErrorCode  DMGetColoring(DM dm,ISColoringType ctype,const MatType mtype,ISColoring *coloring)
524: {

528:   if (!dm->ops->getcoloring) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No coloring for this type of DM yet");
529:   (*dm->ops->getcoloring)(dm,ctype,mtype,coloring);
530:   return(0);
531: }

535: /*@C
536:     DMGetMatrix - Gets empty Jacobian for a DMDA or DMComposite

538:     Collective on DM

540:     Input Parameter:
541: +   dm - the DM object
542: -   mtype - Supported types are MATSEQAIJ, MATMPIAIJ, MATSEQBAIJ, MATMPIBAIJ, or
543:             any type which inherits from one of these (such as MATAIJ)

545:     Output Parameter:
546: .   mat - the empty Jacobian 

548:     Level: beginner

550:     Notes: This properly preallocates the number of nonzeros in the sparse matrix so you 
551:        do not need to do it yourself. 

553:        By default it also sets the nonzero structure and puts in the zero entries. To prevent setting 
554:        the nonzero pattern call DMDASetMatPreallocateOnly()

556:        For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used
557:        internally by PETSc.

559:        For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires 
560:        the indices for the global numbering for DMDAs which is complicated.

562: .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()

564: @*/
565: PetscErrorCode  DMGetMatrix(DM dm,const MatType mtype,Mat *mat)
566: {

570: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
571:   MatInitializePackage(PETSC_NULL);
572: #endif
575:   if (dm->mattype) {
576:     (*dm->ops->getmatrix)(dm,dm->mattype,mat);
577:   } else {
578:     (*dm->ops->getmatrix)(dm,mtype,mat);
579:   }
580:   return(0);
581: }

585: /*@
586:   DMSetMatrixPreallocateOnly - When DMGetMatrix() is called the matrix will be properly
587:     preallocated but the nonzero structure and zero values will not be set.

589:   Logically Collective on DMDA

591:   Input Parameter:
592: + dm - the DM
593: - only - PETSC_TRUE if only want preallocation

595:   Level: developer
596: .seealso DMGetMatrix()
597: @*/
598: PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
599: {
602:   dm->prealloc_only = only;
603:   return(0);
604: }

608: /*@
609:     DMRefine - Refines a DM object

611:     Collective on DM

613:     Input Parameter:
614: +   dm - the DM object
615: -   comm - the communicator to contain the new DM object (or PETSC_NULL)

617:     Output Parameter:
618: .   dmf - the refined DM

620:     Level: developer

622: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()

624: @*/
625: PetscErrorCode  DMRefine(DM dm,MPI_Comm comm,DM *dmf)
626: {

631:   (*dm->ops->refine)(dm,comm,dmf);
632:   (*dmf)->ops->initialguess = dm->ops->initialguess;
633:   (*dmf)->ops->function     = dm->ops->function;
634:   (*dmf)->ops->functionj    = dm->ops->functionj;
635:   if (dm->ops->jacobian != DMComputeJacobianDefault) {
636:     (*dmf)->ops->jacobian     = dm->ops->jacobian;
637:   }
638:   (*dmf)->ctx     = dm->ctx;
639:   (*dmf)->levelup = dm->levelup + 1;
640:   return(0);
641: }

645: /*@
646:     DMGetRefineLevel - Get's the number of refinements that have generated this DM.

648:     Not Collective

650:     Input Parameter:
651: .   dm - the DM object

653:     Output Parameter:
654: .   level - number of refinements

656:     Level: developer

658: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()

660: @*/
661: PetscErrorCode  DMGetRefineLevel(DM dm,PetscInt *level)
662: {
665:   *level = dm->levelup;
666:   return(0);
667: }

671: /*@
672:     DMGlobalToLocalBegin - Begins updating local vectors from global vector

674:     Neighbor-wise Collective on DM

676:     Input Parameters:
677: +   dm - the DM object
678: .   g - the global vector
679: .   mode - INSERT_VALUES or ADD_VALUES
680: -   l - the local vector


683:     Level: beginner

685: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()

687: @*/
688: PetscErrorCode  DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
689: {

693:   (*dm->ops->globaltolocalbegin)(dm,g,mode,l);
694:   return(0);
695: }

699: /*@
700:     DMGlobalToLocalEnd - Ends updating local vectors from global vector

702:     Neighbor-wise Collective on DM

704:     Input Parameters:
705: +   dm - the DM object
706: .   g - the global vector
707: .   mode - INSERT_VALUES or ADD_VALUES
708: -   l - the local vector


711:     Level: beginner

713: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()

715: @*/
716: PetscErrorCode  DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
717: {

721:   (*dm->ops->globaltolocalend)(dm,g,mode,l);
722:   return(0);
723: }

727: /*@
728:     DMLocalToGlobalBegin - updates global vectors from local vectors

730:     Neighbor-wise Collective on DM

732:     Input Parameters:
733: +   dm - the DM object
734: .   l - the local vector
735: .   mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that
736:            base point. 
737: - - the global vector

739:     Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. If you would like to simply add the non-ghosted values in the local
740:            array into the global array you need to either (1) zero the ghosted locations and use ADD_VALUES or (2) use INSERT_VALUES into a work global array and then add the work 
741:            global array to the final global array with VecAXPY().

743:     Level: beginner

745: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()

747: @*/
748: PetscErrorCode  DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
749: {

753:   (*dm->ops->localtoglobalbegin)(dm,l,mode,g);
754:   return(0);
755: }

759: /*@
760:     DMLocalToGlobalEnd - updates global vectors from local vectors

762:     Neighbor-wise Collective on DM

764:     Input Parameters:
765: +   dm - the DM object
766: .   l - the local vector
767: .   mode - INSERT_VALUES or ADD_VALUES
768: -   g - the global vector


771:     Level: beginner

773: .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()

775: @*/
776: PetscErrorCode  DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
777: {

781:   (*dm->ops->localtoglobalend)(dm,l,mode,g);
782:   return(0);
783: }

787: /*@
788:     DMComputeJacobianDefault - computes the Jacobian using the DMComputeFunction() if Jacobian computer is not provided

790:     Collective on DM

792:     Input Parameter:
793: +   dm - the DM object 
794: .   x - location to compute Jacobian at; may be ignored for linear problems
795: .   A - matrix that defines the operator for the linear solve
796: -   B - the matrix used to construct the preconditioner

798:     Level: developer

800: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 
801:          DMSetFunction()

803: @*/
804: PetscErrorCode  DMComputeJacobianDefault(DM dm,Vec x,Mat A,Mat B,MatStructure *stflag)
805: {
808:   *stflag = SAME_NONZERO_PATTERN;
809:   MatFDColoringApply(B,dm->fd,x,stflag,dm);
810:   if (A != B) {
811:     MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
812:     MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
813:   }
814:   return(0);
815: }

819: /*@
820:     DMCoarsen - Coarsens a DM object

822:     Collective on DM

824:     Input Parameter:
825: +   dm - the DM object
826: -   comm - the communicator to contain the new DM object (or PETSC_NULL)

828:     Output Parameter:
829: .   dmc - the coarsened DM

831:     Level: developer

833: .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()

835: @*/
836: PetscErrorCode  DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
837: {

841:   (*dm->ops->coarsen)(dm, comm, dmc);
842:   (*dmc)->ops->initialguess = dm->ops->initialguess;
843:   (*dmc)->ops->function     = dm->ops->function;
844:   (*dmc)->ops->functionj    = dm->ops->functionj;
845:   if (dm->ops->jacobian != DMComputeJacobianDefault) {
846:     (*dmc)->ops->jacobian     = dm->ops->jacobian;
847:   }
848:   (*dmc)->ctx       = dm->ctx;
849:   (*dmc)->leveldown = dm->leveldown + 1;
850:   return(0);
851: }

855: /*@C
856:     DMRefineHierarchy - Refines a DM object, all levels at once

858:     Collective on DM

860:     Input Parameter:
861: +   dm - the DM object
862: -   nlevels - the number of levels of refinement

864:     Output Parameter:
865: .   dmf - the refined DM hierarchy

867:     Level: developer

869: .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()

871: @*/
872: PetscErrorCode  DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
873: {

877:   if (nlevels < 0) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
878:   if (nlevels == 0) return(0);
879:   if (dm->ops->refinehierarchy) {
880:     (*dm->ops->refinehierarchy)(dm,nlevels,dmf);
881:   } else if (dm->ops->refine) {
882:     PetscInt i;

884:     DMRefine(dm,((PetscObject)dm)->comm,&dmf[0]);
885:     for (i=1; i<nlevels; i++) {
886:       DMRefine(dmf[i-1],((PetscObject)dm)->comm,&dmf[i]);
887:     }
888:   } else {
889:     SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
890:   }
891:   return(0);
892: }

896: /*@C
897:     DMCoarsenHierarchy - Coarsens a DM object, all levels at once

899:     Collective on DM

901:     Input Parameter:
902: +   dm - the DM object
903: -   nlevels - the number of levels of coarsening

905:     Output Parameter:
906: .   dmc - the coarsened DM hierarchy

908:     Level: developer

910: .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMGetInterpolation()

912: @*/
913: PetscErrorCode  DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
914: {

918:   if (nlevels < 0) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
919:   if (nlevels == 0) return(0);
921:   if (dm->ops->coarsenhierarchy) {
922:     (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);
923:   } else if (dm->ops->coarsen) {
924:     PetscInt i;

926:     DMCoarsen(dm,((PetscObject)dm)->comm,&dmc[0]);
927:     for (i=1; i<nlevels; i++) {
928:       DMCoarsen(dmc[i-1],((PetscObject)dm)->comm,&dmc[i]);
929:     }
930:   } else {
931:     SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
932:   }
933:   return(0);
934: }

938: /*@
939:    DMGetAggregates - Gets the aggregates that map between 
940:    grids associated with two DMs.

942:    Collective on DM

944:    Input Parameters:
945: +  dmc - the coarse grid DM
946: -  dmf - the fine grid DM

948:    Output Parameters:
949: .  rest - the restriction matrix (transpose of the projection matrix)

951:    Level: intermediate

953: .keywords: interpolation, restriction, multigrid 

955: .seealso: DMRefine(), DMGetInjection(), DMGetInterpolation()
956: @*/
957: PetscErrorCode  DMGetAggregates(DM dmc, DM dmf, Mat *rest)
958: {

962:   (*dmc->ops->getaggregates)(dmc, dmf, rest);
963:   return(0);
964: }

968: /*@
969:     DMSetApplicationContext - Set a user context into a DM object

971:     Not Collective

973:     Input Parameters:
974: +   dm - the DM object 
975: -   ctx - the user context

977:     Level: intermediate

979: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext()

981: @*/
982: PetscErrorCode  DMSetApplicationContext(DM dm,void *ctx)
983: {
985:   dm->ctx = ctx;
986:   return(0);
987: }

991: /*@
992:     DMGetApplicationContext - Gets a user context from a DM object

994:     Not Collective

996:     Input Parameter:
997: .   dm - the DM object 

999:     Output Parameter:
1000: .   ctx - the user context

1002:     Level: intermediate

1004: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext()

1006: @*/
1007: PetscErrorCode  DMGetApplicationContext(DM dm,void *ctx)
1008: {
1010:   *(void**)ctx = dm->ctx;
1011:   return(0);
1012: }

1016: /*@
1017:     DMSetInitialGuess - sets a function to compute an initial guess vector entries for the solvers

1019:     Logically Collective on DM

1021:     Input Parameter:
1022: +   dm - the DM object to destroy
1023: -   f - the function to compute the initial guess

1025:     Level: intermediate

1027: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian()

1029: @*/
1030: PetscErrorCode  DMSetInitialGuess(DM dm,PetscErrorCode (*f)(DM,Vec))
1031: {
1033:   dm->ops->initialguess = f;
1034:   return(0);
1035: }

1039: /*@
1040:     DMSetFunction - sets a function to compute the right hand side vector entries for the KSP solver or nonlinear function for SNES

1042:     Logically Collective on DM

1044:     Input Parameter:
1045: +   dm - the DM object 
1046: -   f - the function to compute (use PETSC_NULL to cancel a previous function that was set)

1048:     Level: intermediate

1050:     Notes: This sets both the function for function evaluations and the function used to compute Jacobians via finite differences if no Jacobian 
1051:            computer is provided with DMSetJacobian(). Canceling cancels the function, but not the function used to compute the Jacobian.

1053: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetInitialGuess(),
1054:          DMSetJacobian()

1056: @*/
1057: PetscErrorCode  DMSetFunction(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
1058: {
1060:   dm->ops->function = f;
1061:   if (f) {
1062:     dm->ops->functionj = f;
1063:   }
1064:   return(0);
1065: }

1069: /*@
1070:     DMSetJacobian - sets a function to compute the matrix entries for the KSP solver or Jacobian for SNES

1072:     Logically Collective on DM

1074:     Input Parameter:
1075: +   dm - the DM object to destroy
1076: -   f - the function to compute the matrix entries

1078:     Level: intermediate

1080: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 
1081:          DMSetFunction()

1083: @*/
1084: PetscErrorCode  DMSetJacobian(DM dm,PetscErrorCode (*f)(DM,Vec,Mat,Mat,MatStructure*))
1085: {
1087:   dm->ops->jacobian = f;
1088:   return(0);
1089: }

1093: /*@
1094:     DMComputeInitialGuess - computes an initial guess vector entries for the KSP solvers

1096:     Collective on DM

1098:     Input Parameter:
1099: +   dm - the DM object to destroy
1100: -   x - the vector to hold the initial guess values

1102:     Level: developer

1104: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetRhs(), DMSetMat()

1106: @*/
1107: PetscErrorCode  DMComputeInitialGuess(DM dm,Vec x)
1108: {
1111:   if (!dm->ops->initialguess) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to provide function with DMSetInitialGuess()");
1112:   (*dm->ops->initialguess)(dm,x);
1113:   return(0);
1114: }

1118: /*@
1119:     DMHasInitialGuess - does the DM object have an initial guess function

1121:     Not Collective

1123:     Input Parameter:
1124: .   dm - the DM object to destroy

1126:     Output Parameter:
1127: .   flg - PETSC_TRUE if function exists

1129:     Level: developer

1131: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian()

1133: @*/
1134: PetscErrorCode  DMHasInitialGuess(DM dm,PetscBool  *flg)
1135: {
1137:   *flg =  (dm->ops->initialguess) ? PETSC_TRUE : PETSC_FALSE;
1138:   return(0);
1139: }

1143: /*@
1144:     DMHasFunction - does the DM object have a function

1146:     Not Collective

1148:     Input Parameter:
1149: .   dm - the DM object to destroy

1151:     Output Parameter:
1152: .   flg - PETSC_TRUE if function exists

1154:     Level: developer

1156: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian()

1158: @*/
1159: PetscErrorCode  DMHasFunction(DM dm,PetscBool  *flg)
1160: {
1162:   *flg =  (dm->ops->function) ? PETSC_TRUE : PETSC_FALSE;
1163:   return(0);
1164: }

1168: /*@
1169:     DMHasJacobian - does the DM object have a matrix function

1171:     Not Collective

1173:     Input Parameter:
1174: .   dm - the DM object to destroy

1176:     Output Parameter:
1177: .   flg - PETSC_TRUE if function exists

1179:     Level: developer

1181: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian()

1183: @*/
1184: PetscErrorCode  DMHasJacobian(DM dm,PetscBool  *flg)
1185: {
1187:   *flg =  (dm->ops->jacobian) ? PETSC_TRUE : PETSC_FALSE;
1188:   return(0);
1189: }

1193: /*@
1194:     DMComputeFunction - computes the right hand side vector entries for the KSP solver or nonlinear function for SNES

1196:     Collective on DM

1198:     Input Parameter:
1199: +   dm - the DM object to destroy
1200: .   x - the location where the function is evaluationed, may be ignored for linear problems
1201: -   b - the vector to hold the right hand side entries

1203:     Level: developer

1205: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetInitialGuess(),
1206:          DMSetJacobian()

1208: @*/
1209: PetscErrorCode  DMComputeFunction(DM dm,Vec x,Vec b)
1210: {
1213:   if (!dm->ops->function) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to provide function with DMSetFunction()");
1214:   PetscStackPush("DM user function");
1215:   (*dm->ops->function)(dm,x,b);
1216:   PetscStackPop;
1217:   return(0);
1218: }


1223: /*@
1224:     DMComputeJacobian - compute the matrix entries for the solver

1226:     Collective on DM

1228:     Input Parameter:
1229: +   dm - the DM object 
1230: .   x - location to compute Jacobian at; will be PETSC_NULL for linear problems, for nonlinear problems if not provided then pulled from DM
1231: .   A - matrix that defines the operator for the linear solve
1232: -   B - the matrix used to construct the preconditioner

1234:     Level: developer

1236: .seealso DMView(), DMCreateGlobalVector(), DMGetInterpolation(), DMGetColoring(), DMGetMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 
1237:          DMSetFunction()

1239: @*/
1240: PetscErrorCode  DMComputeJacobian(DM dm,Vec x,Mat A,Mat B,MatStructure *stflag)
1241: {

1245:   if (!dm->ops->jacobian) {
1246:     ISColoring     coloring;
1247:     MatFDColoring  fd;

1249:     DMGetColoring(dm,IS_COLORING_GLOBAL,MATAIJ,&coloring);
1250:     MatFDColoringCreate(B,coloring,&fd);
1251:     ISColoringDestroy(&coloring);
1252:     MatFDColoringSetFunction(fd,(PetscErrorCode (*)(void))dm->ops->functionj,dm);
1253:     PetscObjectSetOptionsPrefix((PetscObject)fd,((PetscObject)dm)->prefix);
1254:     MatFDColoringSetFromOptions(fd);

1256:     dm->fd = fd;
1257:     dm->ops->jacobian = DMComputeJacobianDefault;

1259:     /* don't know why this is needed */
1260:     PetscObjectDereference((PetscObject)dm);
1261:   }
1262:   if (!x) x = dm->x;
1263:   (*dm->ops->jacobian)(dm,x,A,B,stflag);

1265:   /* if matrix depends on x; i.e. nonlinear problem, keep copy of input vector since needed by multigrid methods to generate coarse grid matrices */
1266:   if (x) {
1267:     if (!dm->x) {
1268:       DMCreateGlobalVector(dm,&dm->x);
1269:     }
1270:     VecCopy(x,dm->x);
1271:   }
1272:   if (A != B) {
1273:     MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
1274:     MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
1275:   }
1276:   return(0);
1277: }


1280: PetscFList DMList                       = PETSC_NULL;
1281: PetscBool  DMRegisterAllCalled          = PETSC_FALSE;

1285: /*@C
1286:   DMSetType - Builds a DM, for a particular DM implementation.

1288:   Collective on DM

1290:   Input Parameters:
1291: + dm     - The DM object
1292: - method - The name of the DM type

1294:   Options Database Key:
1295: . -dm_type <type> - Sets the DM type; use -help for a list of available types

1297:   Notes:
1298:   See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).

1300:   Level: intermediate

1302: .keywords: DM, set, type
1303: .seealso: DMGetType(), DMCreate()
1304: @*/
1305: PetscErrorCode  DMSetType(DM dm, const DMType method)
1306: {
1307:   PetscErrorCode (*r)(DM);
1308:   PetscBool      match;

1313:   PetscTypeCompare((PetscObject) dm, method, &match);
1314:   if (match) return(0);

1316:   if (!DMRegisterAllCalled) {DMRegisterAll(PETSC_NULL);}
1317:   PetscFListFind(DMList, ((PetscObject)dm)->comm, method,PETSC_TRUE,(void (**)(void)) &r);
1318:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);

1320:   if (dm->ops->destroy) {
1321:     (*dm->ops->destroy)(dm);
1322:   }
1323:   (*r)(dm);
1324:   PetscObjectChangeTypeName((PetscObject)dm,method);
1325:   return(0);
1326: }

1330: /*@C
1331:   DMGetType - Gets the DM type name (as a string) from the DM.

1333:   Not Collective

1335:   Input Parameter:
1336: . dm  - The DM

1338:   Output Parameter:
1339: . type - The DM type name

1341:   Level: intermediate

1343: .keywords: DM, get, type, name
1344: .seealso: DMSetType(), DMCreate()
1345: @*/
1346: PetscErrorCode  DMGetType(DM dm, const DMType *type)
1347: {

1353:   if (!DMRegisterAllCalled) {
1354:     DMRegisterAll(PETSC_NULL);
1355:   }
1356:   *type = ((PetscObject)dm)->type_name;
1357:   return(0);
1358: }

1362: /*@C
1363:   DMConvert - Converts a DM to another DM, either of the same or different type.

1365:   Collective on DM

1367:   Input Parameters:
1368: + dm - the DM
1369: - newtype - new DM type (use "same" for the same type)

1371:   Output Parameter:
1372: . M - pointer to new DM

1374:   Notes:
1375:   Cannot be used to convert a sequential DM to parallel or parallel to sequential,
1376:   the MPI communicator of the generated DM is always the same as the communicator
1377:   of the input DM.

1379:   Level: intermediate

1381: .seealso: DMCreate()
1382: @*/
1383: PetscErrorCode DMConvert(DM dm, const DMType newtype, DM *M)
1384: {
1385:   DM             B;
1386:   char           convname[256];
1387:   PetscBool      sametype, issame;

1394:   PetscTypeCompare((PetscObject) dm, newtype, &sametype);
1395:   PetscStrcmp(newtype, "same", &issame);
1396:   {
1397:     PetscErrorCode (*conv)(DM, const DMType, DM *) = PETSC_NULL;

1399:     /*
1400:        Order of precedence:
1401:        1) See if a specialized converter is known to the current DM.
1402:        2) See if a specialized converter is known to the desired DM class.
1403:        3) See if a good general converter is registered for the desired class
1404:        4) See if a good general converter is known for the current matrix.
1405:        5) Use a really basic converter.
1406:     */

1408:     /* 1) See if a specialized converter is known to the current DM and the desired class */
1409:     PetscStrcpy(convname,"DMConvert_");
1410:     PetscStrcat(convname,((PetscObject) dm)->type_name);
1411:     PetscStrcat(convname,"_");
1412:     PetscStrcat(convname,newtype);
1413:     PetscStrcat(convname,"_C");
1414:     PetscObjectQueryFunction((PetscObject)dm,convname,(void (**)(void))&conv);
1415:     if (conv) goto foundconv;

1417:     /* 2)  See if a specialized converter is known to the desired DM class. */
1418:     DMCreate(((PetscObject) dm)->comm, &B);
1419:     DMSetType(B, newtype);
1420:     PetscStrcpy(convname,"DMConvert_");
1421:     PetscStrcat(convname,((PetscObject) dm)->type_name);
1422:     PetscStrcat(convname,"_");
1423:     PetscStrcat(convname,newtype);
1424:     PetscStrcat(convname,"_C");
1425:     PetscObjectQueryFunction((PetscObject)B,convname,(void (**)(void))&conv);
1426:     if (conv) {
1427:       DMDestroy(&B);
1428:       goto foundconv;
1429:     }

1431: #if 0
1432:     /* 3) See if a good general converter is registered for the desired class */
1433:     conv = B->ops->convertfrom;
1434:     DMDestroy(&B);
1435:     if (conv) goto foundconv;

1437:     /* 4) See if a good general converter is known for the current matrix */
1438:     if (dm->ops->convert) {
1439:       conv = dm->ops->convert;
1440:     }
1441:     if (conv) goto foundconv;
1442: #endif

1444:     /* 5) Use a really basic converter. */
1445:     SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);

1447:     foundconv:
1448:     PetscLogEventBegin(DM_Convert,dm,0,0,0);
1449:     (*conv)(dm,newtype,M);
1450:     PetscLogEventEnd(DM_Convert,dm,0,0,0);
1451:   }
1452:   PetscObjectStateIncrease((PetscObject) *M);
1453:   return(0);
1454: }

1456: /*--------------------------------------------------------------------------------------------------------------------*/

1460: /*@C
1461:   DMRegister - See DMRegisterDynamic()

1463:   Level: advanced
1464: @*/
1465: PetscErrorCode  DMRegister(const char sname[], const char path[], const char name[], PetscErrorCode (*function)(DM))
1466: {
1467:   char fullname[PETSC_MAX_PATH_LEN];

1471:   PetscStrcpy(fullname, path);
1472:   PetscStrcat(fullname, ":");
1473:   PetscStrcat(fullname, name);
1474:   PetscFListAdd(&DMList, sname, fullname, (void (*)(void)) function);
1475:   return(0);
1476: }


1479: /*--------------------------------------------------------------------------------------------------------------------*/
1482: /*@C
1483:    DMRegisterDestroy - Frees the list of DM methods that were registered by DMRegister()/DMRegisterDynamic().

1485:    Not Collective

1487:    Level: advanced

1489: .keywords: DM, register, destroy
1490: .seealso: DMRegister(), DMRegisterAll(), DMRegisterDynamic()
1491: @*/
1492: PetscErrorCode  DMRegisterDestroy(void)
1493: {

1497:   PetscFListDestroy(&DMList);
1498:   DMRegisterAllCalled = PETSC_FALSE;
1499:   return(0);
1500: }

1502: #if defined(PETSC_HAVE_MATLAB_ENGINE)
1503: #include <mex.h>

1505: typedef struct {char *funcname; char *jacname; mxArray *ctx;} DMMatlabContext;

1509: /*
1510:    DMComputeFunction_Matlab - Calls the function that has been set with
1511:                          DMSetFunctionMatlab().  

1513:    For linear problems x is null
1514:    
1515: .seealso: DMSetFunction(), DMGetFunction()
1516: */
1517: PetscErrorCode  DMComputeFunction_Matlab(DM dm,Vec x,Vec y)
1518: {
1519:   PetscErrorCode    ierr;
1520:   DMMatlabContext   *sctx;
1521:   int               nlhs = 1,nrhs = 4;
1522:   mxArray            *plhs[1],*prhs[4];
1523:   long long int     lx = 0,ly = 0,ls = 0;
1524: 

1530:   /* call Matlab function in ctx with arguments x and y */
1531:   DMGetApplicationContext(dm,&sctx);
1532:   PetscMemcpy(&ls,&dm,sizeof(dm));
1533:   PetscMemcpy(&lx,&x,sizeof(x));
1534:   PetscMemcpy(&ly,&y,sizeof(y));
1535:   prhs[0] =  mxCreateDoubleScalar((double)ls);
1536:   prhs[1] =  mxCreateDoubleScalar((double)lx);
1537:   prhs[2] =  mxCreateDoubleScalar((double)ly);
1538:   prhs[3] =  mxCreateString(sctx->funcname);
1539:    mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscDMComputeFunctionInternal");
1540:    mxGetScalar(plhs[0]);
1541:   mxDestroyArray(prhs[0]);
1542:   mxDestroyArray(prhs[1]);
1543:   mxDestroyArray(prhs[2]);
1544:   mxDestroyArray(prhs[3]);
1545:   mxDestroyArray(plhs[0]);
1546:   return(0);
1547: }


1552: /*
1553:    DMSetFunctionMatlab - Sets the function evaluation routine 

1555: */
1556: PetscErrorCode  DMSetFunctionMatlab(DM dm,const char *func)
1557: {
1558:   PetscErrorCode    ierr;
1559:   DMMatlabContext   *sctx;

1562:   /* currently sctx is memory bleed */
1563:   DMGetApplicationContext(dm,&sctx);
1564:   if (!sctx) {
1565:     PetscMalloc(sizeof(DMMatlabContext),&sctx);
1566:   }
1567:   PetscStrallocpy(func,&sctx->funcname);
1568:   DMSetApplicationContext(dm,sctx);
1569:   DMSetFunction(dm,DMComputeFunction_Matlab);
1570:   return(0);
1571: }

1575: /*
1576:    DMComputeJacobian_Matlab - Calls the function that has been set with
1577:                          DMSetJacobianMatlab().  

1579:    For linear problems x is null
1580:    
1581: .seealso: DMSetFunction(), DMGetFunction()
1582: */
1583: PetscErrorCode  DMComputeJacobian_Matlab(DM dm,Vec x,Mat A,Mat B,MatStructure *str)
1584: {
1585:   PetscErrorCode    ierr;
1586:   DMMatlabContext   *sctx;
1587:   int               nlhs = 2,nrhs = 5;
1588:   mxArray            *plhs[2],*prhs[5];
1589:   long long int     lx = 0,lA = 0,lB = 0,ls = 0;
1590: 

1595:   /* call MATLAB function in ctx with arguments x, A, and B */
1596:   DMGetApplicationContext(dm,&sctx);
1597:   PetscMemcpy(&ls,&dm,sizeof(dm));
1598:   PetscMemcpy(&lx,&x,sizeof(x));
1599:   PetscMemcpy(&lA,&A,sizeof(A));
1600:   PetscMemcpy(&lB,&B,sizeof(B));
1601:   prhs[0] =  mxCreateDoubleScalar((double)ls);
1602:   prhs[1] =  mxCreateDoubleScalar((double)lx);
1603:   prhs[2] =  mxCreateDoubleScalar((double)lA);
1604:   prhs[3] =  mxCreateDoubleScalar((double)lB);
1605:   prhs[4] =  mxCreateString(sctx->jacname);
1606:    mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscDMComputeJacobianInternal");
1607:   *str    =  (MatStructure) mxGetScalar(plhs[0]);
1608:    (PetscInt) mxGetScalar(plhs[1]);
1609:   mxDestroyArray(prhs[0]);
1610:   mxDestroyArray(prhs[1]);
1611:   mxDestroyArray(prhs[2]);
1612:   mxDestroyArray(prhs[3]);
1613:   mxDestroyArray(prhs[4]);
1614:   mxDestroyArray(plhs[0]);
1615:   mxDestroyArray(plhs[1]);
1616:   return(0);
1617: }


1622: /*
1623:    DMSetJacobianMatlab - Sets the Jacobian function evaluation routine 

1625: */
1626: PetscErrorCode  DMSetJacobianMatlab(DM dm,const char *func)
1627: {
1628:   PetscErrorCode    ierr;
1629:   DMMatlabContext   *sctx;

1632:   /* currently sctx is memory bleed */
1633:   DMGetApplicationContext(dm,&sctx);
1634:   if (!sctx) {
1635:     PetscMalloc(sizeof(DMMatlabContext),&sctx);
1636:   }
1637:   PetscStrallocpy(func,&sctx->jacname);
1638:   DMSetApplicationContext(dm,sctx);
1639:   DMSetJacobian(dm,DMComputeJacobian_Matlab);
1640:   return(0);
1641: }
1642: #endif

1646: /*@C
1647:   DMLoad - Loads a DM that has been stored in binary or HDF5 format
1648:   with DMView().

1650:   Collective on PetscViewer 

1652:   Input Parameters:
1653: + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
1654:            some related function before a call to DMLoad(). 
1655: - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
1656:            HDF5 file viewer, obtained from PetscViewerHDF5Open()

1658:    Level: intermediate

1660:   Notes:
1661:   Defaults to the DM DA.

1663:   Notes for advanced users:
1664:   Most users should not need to know the details of the binary storage
1665:   format, since DMLoad() and DMView() completely hide these details.
1666:   But for anyone who's interested, the standard binary matrix storage
1667:   format is  
1668: .vb
1669:      has not yet been determined
1670: .ve

1672:    In addition, PETSc automatically does the byte swapping for
1673: machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1674: linux, Windows and the paragon; thus if you write your own binary
1675: read/write routines you have to swap the bytes; see PetscBinaryRead()
1676: and PetscBinaryWrite() to see how this may be done.

1678:   Concepts: vector^loading from file

1680: .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 
1681: @*/
1682: PetscErrorCode  DMLoad(DM newdm, PetscViewer viewer)
1683: {


1690:   if (!((PetscObject)newdm)->type_name) {
1691:     DMSetType(newdm, DMDA);
1692:   }
1693:   (*newdm->ops->load)(newdm,viewer);
1694:   return(0);
1695: }