/* Calculate the gridpoints an atom spans */ VPRIVATE void Vclist_gridSpan(Vclist *thee, Vatom *atom, /* Atom */ int imin[VAPBS_DIM], /* Set to min grid indices */ int imax[VAPBS_DIM] /* Set to max grid indices */ ) { int i; double *coord, dc, idc, rtot; /* Get the position in the grid's frame of reference */ coord = Vatom_getPosition(atom); /* Get the range the atom radius + probe radius spans */ rtot = Vatom_getRadius(atom) + thee->max_radius; /* Calculate the range of grid points the inflated atom spans in the x * direction. */ for (i=0; i<VAPBS_DIM; i++) { dc = coord[i] - (thee->lower_corner)[i]; idc = (dc + rtot)/(thee->spacs[i]); imax[i] = (int)(ceil(idc)); imax[i] = VMIN2(imax[i], thee->npts[i]-1); idc = (dc - rtot)/(thee->spacs[i]); imin[i] = (int)(floor(idc)); imin[i] = VMAX2(imin[i], 0); } }
VPUBLIC void Vdpbfa(double *abd, int *lda, int *n, int *m, int *info) { double t, s; int ik, j, jk, k, mu; MAT2(abd, *lda, 1); *info = 0; for(j = 1; j <= *n; j++) { s = 0.0; ik = *m + 1; jk = VMAX2(j - *m, 1); mu = VMAX2(*m + 2 - j, 1); if (*m >= mu ) { for(k = mu; k <= *m; k++) { t = VAT2(abd, k, j) - Vddot(k - mu, RAT2(abd, ik, jk), 1, RAT2(abd, mu, j), 1); t /= VAT2(abd, *m + 1, jk); VAT2(abd, k, j) = t; s += t * t; ik--; jk++; } } s = VAT2(abd, *m + 1, j) - s; if (s <= 0.0) { *info = j; break; } VAT2(abd, *m + 1, j) = VSQRT(s); } }
/* /////////////////////////////////////////////////////////////////////////// // Routine: Vpee_markRefine // // Author: Nathan Baker (and Michael Holst: the author of AM_markRefine, on // which this is based) /////////////////////////////////////////////////////////////////////////// */ VPUBLIC int Vpee_markRefine(Vpee *thee, AM *am, int level, int akey, int rcol, double etol, int bkey ) { Aprx *aprx; int marked = 0, markMe, i, smid, count, currentQ; double minError = 0.0, maxError = 0.0, errEst = 0.0, mlevel, barrier; SS *sm; VASSERT(thee != VNULL); /* Get the Aprx object from AM */ aprx = am->aprx; /* input check and some i/o */ if ( ! ((-1 <= akey) && (akey <= 4)) ) { Vnm_print(0,"Vpee_markRefine: bad refine key; simplices marked = %d\n", marked); return marked; } /* For uniform markings, we have no effect */ if ((-1 <= akey) && (akey <= 0)) { marked = Gem_markRefine(thee->gm, akey, rcol); return marked; } /* Informative I/O */ if (akey == 2) { Vnm_print(0,"Vpee_estRefine: using Aprx_estNonlinResid().\n"); } else if (akey == 3) { Vnm_print(0,"Vpee_estRefine: using Aprx_estLocalProblem().\n"); } else if (akey == 4) { Vnm_print(0,"Vpee_estRefine: using Aprx_estDualProblem().\n"); } else { Vnm_print(0,"Vpee_estRefine: bad key given; simplices marked = %d\n", marked); return marked; } if (thee->killFlag == 0) { Vnm_print(0, "Vpee_markRefine: No error attenuation -- simplices in all partitions will be marked.\n"); } else if (thee->killFlag == 1) { Vnm_print(0, "Vpee_markRefine: Maximum error attenuation -- only simplices in local partition will be marked.\n"); } else if (thee->killFlag == 2) { Vnm_print(0, "Vpee_markRefine: Spherical error attenutation -- simplices within a sphere of %4.3f times the size of the partition will be marked\n", thee->killParam); } else if (thee->killFlag == 2) { Vnm_print(0, "Vpee_markRefine: Neighbor-based error attenuation -- simplices in the local and neighboring partitions will be marked [NOT IMPLEMENTED]!\n"); VASSERT(0); } else { Vnm_print(2,"Vpee_markRefine: bogus killFlag given; simplices marked = %d\n", marked); return marked; } /* set the barrier type */ mlevel = (etol*etol) / Gem_numSS(thee->gm); if (bkey == 0) { barrier = (etol*etol); Vnm_print(0,"Vpee_estRefine: forcing [err per S] < [TOL] = %g\n", barrier); } else if (bkey == 1) { barrier = mlevel; Vnm_print(0,"Vpee_estRefine: forcing [err per S] < [(TOL^2/numS)^{1/2}] = %g\n", VSQRT(barrier)); } else { Vnm_print(0,"Vpee_estRefine: bad bkey given; simplices marked = %d\n", marked); return marked; } /* timer */ Vnm_tstart(30, "error estimation"); /* count = num generations to produce from marked simplices (minimally) */ count = 1; /* must be >= 1 */ /* check the refinement Q for emptyness */ currentQ = 0; if (Gem_numSQ(thee->gm,currentQ) > 0) { Vnm_print(0,"Vpee_markRefine: non-empty refinement Q%d....clearing..", currentQ); Gem_resetSQ(thee->gm,currentQ); Vnm_print(0,"..done.\n"); } if (Gem_numSQ(thee->gm,!currentQ) > 0) { Vnm_print(0,"Vpee_markRefine: non-empty refinement Q%d....clearing..", !currentQ); Gem_resetSQ(thee->gm,!currentQ); Vnm_print(0,"..done.\n"); } VASSERT( Gem_numSQ(thee->gm,currentQ) == 0 ); VASSERT( Gem_numSQ(thee->gm,!currentQ) == 0 ); /* clear everyone's refinement flags */ Vnm_print(0,"Vpee_markRefine: clearing all simplex refinement flags.."); for (i=0; i<Gem_numSS(thee->gm); i++) { if ( (i>0) && (i % VPRTKEY) == 0 ) Vnm_print(0,"[MS:%d]",i); sm = Gem_SS(thee->gm,i); SS_setRefineKey(sm,currentQ,0); SS_setRefineKey(sm,!currentQ,0); SS_setRefinementCount(sm,0); } Vnm_print(0,"..done.\n"); /* NON-ERROR-BASED METHODS */ /* Simplex flag clearing */ if (akey == -1) return marked; /* Uniform & user-defined refinement*/ if ((akey == 0) || (akey == 1)) { smid = 0; while ( smid < Gem_numSS(thee->gm)) { /* Get the simplex and find out if it's markable */ sm = Gem_SS(thee->gm,smid); markMe = Vpee_ourSimp(thee, sm, rcol); if (markMe) { if (akey == 0) { marked++; Gem_appendSQ(thee->gm,currentQ, sm); SS_setRefineKey(sm,currentQ,1); SS_setRefinementCount(sm,count); } else if (Vpee_userDefined(thee, sm)) { marked++; Gem_appendSQ(thee->gm,currentQ, sm); SS_setRefineKey(sm,currentQ,1); SS_setRefinementCount(sm,count); } } smid++; } } /* ERROR-BASED METHODS */ /* gerror = global error accumulation */ aprx->gerror = 0.; /* traverse the simplices and process the error estimates */ Vnm_print(0,"Vpee_markRefine: estimating error.."); smid = 0; while ( smid < Gem_numSS(thee->gm)) { /* Get the simplex and find out if it's markable */ sm = Gem_SS(thee->gm,smid); markMe = Vpee_ourSimp(thee, sm, rcol); if ( (smid>0) && (smid % VPRTKEY) == 0 ) Vnm_print(0,"[MS:%d]",smid); /* Produce an error estimate for this element if it is in the set */ if (markMe) { if (akey == 2) { errEst = Aprx_estNonlinResid(aprx, sm, am->u,am->ud,am->f); } else if (akey == 3) { errEst = Aprx_estLocalProblem(aprx, sm, am->u,am->ud,am->f); } else if (akey == 4) { errEst = Aprx_estDualProblem(aprx, sm, am->u,am->ud,am->f); } VASSERT( errEst >= 0. ); /* if error estimate above tol, mark element for refinement */ if ( errEst > barrier ) { marked++; Gem_appendSQ(thee->gm,currentQ, sm); /*add to refinement Q*/ SS_setRefineKey(sm,currentQ,1); /* note now on refine Q */ SS_setRefinementCount(sm,count); /* refine X many times? */ } /* keep track of min/max errors over the mesh */ minError = VMIN2( VSQRT(VABS(errEst)), minError ); maxError = VMAX2( VSQRT(VABS(errEst)), maxError ); /* store the estimate */ Bvec_set( aprx->wev, smid, errEst ); /* accumlate into global error (errEst is SQUAREd already) */ aprx->gerror += errEst; /* otherwise store a zero for the estimate */ } else { Bvec_set( aprx->wev, smid, 0. ); } smid++; } /* do some i/o */ Vnm_print(0,"..done. [marked=<%d/%d>]\n",marked,Gem_numSS(thee->gm)); Vnm_print(0,"Vpee_estRefine: TOL=<%g> Global_Error=<%g>\n", etol, aprx->gerror); Vnm_print(0,"Vpee_estRefine: (TOL^2/numS)^{1/2}=<%g> Max_Ele_Error=<%g>\n", VSQRT(mlevel),maxError); Vnm_tstop(30, "error estimation"); /* check for making the error tolerance */ if ((bkey == 1) && (aprx->gerror <= etol)) { Vnm_print(0, "Vpee_estRefine: *********************************************\n"); Vnm_print(0, "Vpee_estRefine: Global Error criterion met; setting marked=0.\n"); Vnm_print(0, "Vpee_estRefine: *********************************************\n"); marked = 0; } /* return */ return marked; }