Actual source code: nladic.c

  1: /*$Id: matadic.c,v 1.13 2001/08/07 03:03:06 balay Exp $*/
  2: /*
  3:     ADIC based nonlinear operator object that can be used with FAS

  5:     This does not really belong in the matrix directories but since it 
  6:     was cloned off of Mat_DAAD I'm leaving it here until I have a better place

  8: */

 10:  #include petscda.h
 11:  #include petscsys.h
 12: EXTERN_C_BEGIN
 13: #include "adic/ad_utils.h"
 14: EXTERN_C_END

 16:  #include src/dm/da/daimpl.h

 18: struct NLF_DAAD {
 19:   DA         da;
 20:   void       *ctx;
 21:   Vec        residual;
 22:   int        newton_its;
 23: };



 27: /*
 28:       Solves the one dimensional equation using Newton's method 
 29: */
 32: int NLFNewton_DAAD(NLF A,DALocalInfo *info,MatStencil *stencil,void *ad_vu,PetscScalar *ad_vustart,int nI,int gI,PetscScalar residual)
 33: {
 34:   int           ierr,cnt = A->newton_its;
 35:   PetscScalar   ad_f[2],J,f;

 38:   ad_vustart[1+2*gI] = 1.0;

 40:   do {
 41:     /* compute the function and Jacobian */
 42:     (*A->da->adicmf_lfi)(info,stencil,ad_vu,ad_f,A->ctx);
 43:     J    = -ad_f[1];
 44:     f    = -ad_f[0] + residual;
 45:     ad_vustart[2*gI] =  ad_vustart[2*gI] - f/J;
 46:     /* printf("nI %d f %g J %g\n",nI,f,J);   */
 47:   } while (--cnt > 0 && PetscAbsScalar(f) > 1.e-14);

 49:   ad_vustart[1+2*gI] = 0.0;
 50:   return(0);
 51: }


 54: /*
 55:         Nonlinear relax on all the equations with an initial guess in xx
 56: */
 57: EXTERN_C_BEGIN
 60: int NLFRelax_DAAD(NLF A,MatSORType flag,int its,Vec xx)
 61: {
 62:   int           ierr,j,gtdof,nI,gI;
 63:   PetscScalar   *avu,*av,*ad_vustart,*residual;
 64:   Vec           localxx;
 65:   DALocalInfo   info;
 66:   MatStencil    stencil;
 67:   void*         *ad_vu;

 70:   if (its <= 0) SETERRQ1(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %d positive",its);

 72:   DAGetLocalVector(A->da,&localxx);
 73:   /* get space for derivative object.  */
 74:   DAGetAdicMFArray(A->da,PETSC_TRUE,(void **)&ad_vu,(void**)&ad_vustart,&gtdof);
 75:   VecGetArray(A->residual,&residual);


 78:   /* tell ADIC we will be computing one dimensional Jacobians */
 79:   PetscADResetIndep();
 80:   PetscADIncrementTotalGradSize(1);
 81:   PetscADSetIndepDone();

 83:   DAGetLocalInfo(A->da,&info);
 84:   while (its--) {

 86:     /* get initial solution properly ghosted */
 87:     DAGlobalToLocalBegin(A->da,xx,INSERT_VALUES,localxx);
 88:     DAGlobalToLocalEnd(A->da,xx,INSERT_VALUES,localxx);

 90:     /* copy input vector into derivative object */
 91:     VecGetArray(localxx,&avu);
 92:     for (j=0; j<gtdof; j++) {
 93:       ad_vustart[2*j]   = avu[j];
 94:       ad_vustart[2*j+1] = 0.0;
 95:     }
 96:     VecRestoreArray(localxx,&avu);

 98:     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
 99:       nI = 0;
100:       for (stencil.k = info.zs; stencil.k<info.zs+info.zm; stencil.k++) {
101:         for (stencil.j = info.ys; stencil.j<info.ys+info.ym; stencil.j++) {
102:           for (stencil.i = info.xs; stencil.i<info.xs+info.xm; stencil.i++) {
103:             for (stencil.c = 0; stencil.c<info.dof; stencil.c++) {
104:               gI   = stencil.c + (stencil.i - info.gxs)*info.dof + (stencil.j - info.gys)*info.dof*info.gxm + (stencil.k - info.gzs)*info.dof*info.gxm*info.gym;
105:               NLFNewton_DAAD(A,&info,&stencil,ad_vu,ad_vustart,nI,gI,residual[nI]);
106:               nI++;
107:             }
108:           }
109:         }
110:       }
111:     }
112:     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
113:       nI = info.dof*info.xm*info.ym*info.zm - 1;
114:       for (stencil.k = info.zs+info.zm-1; stencil.k>=info.zs; stencil.k--) {
115:         for (stencil.j = info.ys+info.ym-1; stencil.j>=info.ys; stencil.j--) {
116:           for (stencil.i = info.xs+info.xm-1; stencil.i>=info.xs; stencil.i--) {
117:             for (stencil.c = info.dof-1; stencil.c>=0; stencil.c--) {
118:               gI   = stencil.c + (stencil.i - info.gxs)*info.dof + (stencil.j - info.gys)*info.dof*info.gxm + (stencil.k - info.gzs)*info.dof*info.gxm*info.gym;
119:               NLFNewton_DAAD(A,&info,&stencil,ad_vu,ad_vustart,nI,gI,residual[nI]);
120:               nI--;
121:             }
122:           }
123:         }
124:       }
125:     }

127:     /* copy solution back into ghosted vector from derivative object */
128:     VecGetArray(localxx,&av);
129:     for (j=0; j<gtdof; j++) {
130:       av[j] = ad_vustart[2*j];
131:     }
132:     VecRestoreArray(localxx,&av);
133:     /* stick relaxed solution back into global solution */
134:     DALocalToGlobal(A->da,localxx,INSERT_VALUES,xx);
135:   }


138:   VecRestoreArray(A->residual,&residual);
139:   DARestoreLocalVector(A->da,&localxx);
140:   DARestoreAdicMFArray(A->da,PETSC_TRUE,(void **)&ad_vu,(void**)&ad_vustart,&gtdof);
141:   return(0);
142: }
143: EXTERN_C_END


148: int NLFDestroy_DAAD(NLF A)
149: {
150:   int      ierr;

153:   DADestroy(A->da);
154:   PetscFree(A);
155:   return(0);
156: }


159: EXTERN_C_BEGIN
162: int NLFDAADSetDA_DAAD(NLF A,DA da)
163: {
164:   int      ierr;

167:   A->da = da;
168:   PetscObjectReference((PetscObject)da);
169:   return(0);
170: }
171: EXTERN_C_END

173: EXTERN_C_BEGIN
176: int NLFDAADSetNewtonIterations_DAAD(NLF A,int its)
177: {

180:   A->newton_its = its;
181:   return(0);
182: }
183: EXTERN_C_END

185: EXTERN_C_BEGIN
188: int NLFDAADSetResidual_DAAD(NLF A,Vec residual)
189: {
191:   A->residual = residual;
192:   return(0);
193: }
194: EXTERN_C_END


197: EXTERN_C_BEGIN
200: int NLFDAADSetCtx_DAAD(NLF A,void *ctx)
201: {
203:   A->ctx = ctx;
204:   return(0);
205: }
206: EXTERN_C_END

208: EXTERN_C_BEGIN
211: int NLFCreate_DAAD(NLF *A)
212: {
213:   int      ierr;

216:   PetscNew(struct NLF_DAAD,A);
217:   (*A)->da         = 0;
218:   (*A)->ctx        = 0;
219:   (*A)->newton_its = 2;
220:   return(0);
221: }
222: EXTERN_C_END