00001
00050 #include "apbscfg.h"
00051
00052 #if defined(HAVE_MC_H)
00053 #if defined(HAVE_MCX_H)
00054
00055 #include "mc/mc.h"
00056 #include "apbs/vpee.h"
00057
00058 VPRIVATE int Vpee_userDefined(Vpee *thee, SS *sm);
00059 VPRIVATE int Vpee_ourSimp(Vpee *thee, SS *sm, int rcol);
00060 VEXTERNC double Aprx_estNonlinResid(Aprx *thee, SS *sm,
00061 Bvec *u, Bvec *ud, Bvec *f);
00062 VEXTERNC double Aprx_estLocalProblem(Aprx *thee, SS *sm,
00063 Bvec *u, Bvec *ud, Bvec *f);
00064 VEXTERNC double Aprx_estDualProblem(Aprx *thee, SS *sm,
00065 Bvec *u, Bvec *ud, Bvec *f);
00066
00067
00068
00070
00071
00072
00073
00074
00076
00077
00078
00079
00080
00081
00082 thee = Vmem_malloc(VNULL, 1, sizeof(Vpee) );
00083 VASSERT( thee != VNULL);
00084 VASSERT( Vpee_ctor2(thee, gm, localPartID, killFlag, killParam));
00085
00086 return thee;
00087 }
00088
00089
00090
00091
00092
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 if (killFlag == 0) {
00106 Vnm_print(0, "Vpee_ctor2: No error attenuation outside partition.\n");
00107 } else if (killFlag == 1) {
00108 Vnm_print(0, "Vpee_ctor2: Error outside local partition ignored.\n");
00109 } else if (killFlag == 2) {
00110 Vnm_print(0, "Vpee_ctor2: Error ignored outside sphere with radius %4.3f times the radius of the circumscribing sphere\n", killParam);
00111 if (killParam < 1.0) {
00112 Vnm_print(2, "Vpee_ctor2: Warning! Parameter killParam = %4.3 < 1.0!\n",
00113 killParam);
00114 Vnm_print(2, "Vpee_ctor2: This may result in non-optimal marking and refinement!\n");
00115 }
00116 } else if (killFlag == 3) {
00117 Vnm_print(0, "Vpee_ctor2: Error outside local partition and immediate neighbors ignored [NOT IMPLEMENTED].\n");
00118 } else {
00119 Vnm_print(2, "Vpee_ctor2: UNRECOGNIZED killFlag PARAMETER! BAILING!.\n");
00120 VASSERT(0);
00121 }
00122
00123 thee->gm = gm;
00124 thee->localPartID = localPartID;
00125 thee->killFlag = killFlag;
00126 thee->killParam = killParam;
00127 thee->mem = Vmem_ctor("APBS::VPEE");
00128
00129
00130
00131
00132
00133 thee->localPartCenter[0] = 0.0;
00134 thee->localPartCenter[1] = 0.0;
00135 thee->localPartCenter[2] = 0.0;
00136 nLocalVerts = 0;
00137 for (ivert=0; ivert<Gem_numVV(thee->gm); ivert++) {
00138 vert = Gem_VV(thee->gm, ivert);
00139 simp = VV_firstSS(vert);
00140 VASSERT(simp != VNULL);
00141 while (simp != VNULL) {
00142 if (SS_chart(simp) == thee->localPartID) {
00143 thee->localPartCenter[0] += VV_coord(vert, 0);
00144 thee->localPartCenter[1] += VV_coord(vert, 1);
00145 thee->localPartCenter[2] += VV_coord(vert, 2);
00146 nLocalVerts++;
00147 break;
00148 }
00149 simp = SS_link(simp, vert);
00150 }
00151 }
00152 VASSERT(nLocalVerts > 0);
00153 thee->localPartCenter[0] =
00154 thee->localPartCenter[0]/((double)(nLocalVerts));
00155 thee->localPartCenter[1] =
00156 thee->localPartCenter[1]/((double)(nLocalVerts));
00157 thee->localPartCenter[2] =
00158 thee->localPartCenter[2]/((double)(nLocalVerts));
00159 Vnm_print(0, "Vpee_ctor2: Part %d centered at (%4.3f, %4.3f, %4.3f)\n",
00160 thee->localPartID, thee->localPartCenter[0], thee->localPartCenter[1],
00161 thee->localPartCenter[2]);
00162
00163
00164
00165
00166
00167 thee->localPartRadius = 0.0;
00168 for (ivert=0; ivert<Gem_numVV(thee->gm); ivert++) {
00169 vert = Gem_VV(thee->gm, ivert);
00170 simp = VV_firstSS(vert);
00171 VASSERT(simp != VNULL);
00172 while (simp != VNULL) {
00173 if (SS_chart(simp) == thee->localPartID) {
00174 dx = thee->localPartCenter[0] - VV_coord(vert, 0);
00175 dy = thee->localPartCenter[1] - VV_coord(vert, 1);
00176 dz = thee->localPartCenter[2] - VV_coord(vert, 2);
00177 radius = dx*dx + dy*dy + dz*dz;
00178 if (radius > thee->localPartRadius) thee->localPartRadius =
00179 radius;
00180 break;
00181 }
00182 simp = SS_link(simp, vert);
00183 }
00184 }
00185 thee->localPartRadius = VSQRT(thee->localPartRadius);
00186 Vnm_print(0, "Vpee_ctor2: Part %d has circumscribing sphere of radius %4.3f\n",
00187 thee->localPartID, thee->localPartRadius);
00188
00189 return 1;
00190 }
00191
00192
00193
00194
00195
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00212
00213
00214
00215
00216
00217
00218
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 aprx = am->aprx;
00237
00238
00239 if ( ! ((-1 <= akey) && (akey <= 4)) ) {
00240 Vnm_print(0,"Vpee_markRefine: bad refine key; simplices marked = %d\n",
00241 marked);
00242 return marked;
00243 }
00244
00245
00246 if ((-1 <= akey) && (akey <= 0)) {
00247 marked = Gem_markRefine(thee->gm, akey, rcol);
00248 return marked;
00249 }
00250
00251
00252 if (akey == 2) {
00253 Vnm_print(0,"Vpee_estRefine: using Aprx_estNonlinResid().\n");
00254 } else if (akey == 3) {
00255 Vnm_print(0,"Vpee_estRefine: using Aprx_estLocalProblem().\n");
00256 } else if (akey == 4) {
00257 Vnm_print(0,"Vpee_estRefine: using Aprx_estDualProblem().\n");
00258 } else {
00259 Vnm_print(0,"Vpee_estRefine: bad key given; simplices marked = %d\n",
00260 marked);
00261 return marked;
00262 }
00263 if (thee->killFlag == 0) {
00264 Vnm_print(0, "Vpee_markRefine: No error attenuation -- simplices in all partitions will be marked.\n");
00265 } else if (thee->killFlag == 1) {
00266 Vnm_print(0, "Vpee_markRefine: Maximum error attenuation -- only simplices in local partition will be marked.\n");
00267 } else if (thee->killFlag == 2) {
00268 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",
00269 thee->killParam);
00270 } else if (thee->killFlag == 2) {
00271 Vnm_print(0, "Vpee_markRefine: Neighbor-based error attenuation -- simplices in the local and neighboring partitions will be marked [NOT IMPLEMENTED]!\n");
00272 VASSERT(0);
00273 } else {
00274 Vnm_print(2,"Vpee_markRefine: bogus killFlag given; simplices marked = %d\n",
00275 marked);
00276 return marked;
00277 }
00278
00279
00280 mlevel = (etol*etol) / Gem_numSS(thee->gm);
00281 if (bkey == 0) {
00282 barrier = (etol*etol);
00283 Vnm_print(0,"Vpee_estRefine: forcing [err per S] < [TOL] = %g\n",
00284 barrier);
00285 } else if (bkey == 1) {
00286 barrier = mlevel;
00287 Vnm_print(0,"Vpee_estRefine: forcing [err per S] < [(TOL^2/numS)^{1/2}] = %g\n",
00288 VSQRT(barrier));
00289 } else {
00290 Vnm_print(0,"Vpee_estRefine: bad bkey given; simplices marked = %d\n",
00291 marked);
00292 return marked;
00293 }
00294
00295
00296 Vnm_tstart(30, "error estimation");
00297
00298
00299 count = 1;
00300
00301
00302 currentQ = 0;
00303 if (Gem_numSQ(thee->gm,currentQ) > 0) {
00304 Vnm_print(0,"Vpee_markRefine: non-empty refinement Q%d....clearing..",
00305 currentQ);
00306 Gem_resetSQ(thee->gm,currentQ);
00307 Vnm_print(0,"..done.\n");
00308 }
00309 if (Gem_numSQ(thee->gm,!currentQ) > 0) {
00310 Vnm_print(0,"Vpee_markRefine: non-empty refinement Q%d....clearing..",
00311 !currentQ);
00312 Gem_resetSQ(thee->gm,!currentQ);
00313 Vnm_print(0,"..done.\n");
00314 }
00315 VASSERT( Gem_numSQ(thee->gm,currentQ) == 0 );
00316 VASSERT( Gem_numSQ(thee->gm,!currentQ) == 0 );
00317
00318
00319 Vnm_print(0,"Vpee_markRefine: clearing all simplex refinement flags..");
00320 for (i=0; i<Gem_numSS(thee->gm); i++) {
00321 if ( (i>0) && (i % VPRTKEY) == 0 ) Vnm_print(0,"[MS:%d]",i);
00322 sm = Gem_SS(thee->gm,i);
00323 SS_setRefineKey(sm,currentQ,0);
00324 SS_setRefineKey(sm,!currentQ,0);
00325 SS_setRefinementCount(sm,0);
00326 }
00327 Vnm_print(0,"..done.\n");
00328
00329
00330
00331 if (akey == -1) return marked;
00332
00333 if ((akey == 0) || (akey == 1)) {
00334 smid = 0;
00335 while ( smid < Gem_numSS(thee->gm)) {
00336
00337 sm = Gem_SS(thee->gm,smid);
00338 markMe = Vpee_ourSimp(thee, sm, rcol);
00339 if (markMe) {
00340 if (akey == 0) {
00341 marked++;
00342 Gem_appendSQ(thee->gm,currentQ, sm);
00343 SS_setRefineKey(sm,currentQ,1);
00344 SS_setRefinementCount(sm,count);
00345 } else if (Vpee_userDefined(thee, sm)) {
00346 marked++;
00347 Gem_appendSQ(thee->gm,currentQ, sm);
00348 SS_setRefineKey(sm,currentQ,1);
00349 SS_setRefinementCount(sm,count);
00350 }
00351 }
00352 smid++;
00353 }
00354 }
00355
00356
00357
00358 aprx->gerror = 0.;
00359
00360
00361 Vnm_print(0,"Vpee_markRefine: estimating error..");
00362 smid = 0;
00363 while ( smid < Gem_numSS(thee->gm)) {
00364
00365
00366 sm = Gem_SS(thee->gm,smid);
00367 markMe = Vpee_ourSimp(thee, sm, rcol);
00368
00369 if ( (smid>0) && (smid % VPRTKEY) == 0 ) Vnm_print(0,"[MS:%d]",smid);
00370
00371
00372 if (markMe) {
00373 if (akey == 2) {
00374 errEst = Aprx_estNonlinResid(aprx, sm, am->u,am->ud,am->f);
00375 } else if (akey == 3) {
00376 errEst = Aprx_estLocalProblem(aprx, sm, am->u,am->ud,am->f);
00377 } else if (akey == 4) {
00378 errEst = Aprx_estDualProblem(aprx, sm, am->u,am->ud,am->f);
00379 }
00380 VASSERT( errEst >= 0. );
00381
00382
00383 if ( errEst > barrier ) {
00384 marked++;
00385 Gem_appendSQ(thee->gm,currentQ, sm);
00386 SS_setRefineKey(sm,currentQ,1);
00387 SS_setRefinementCount(sm,count);
00388 }
00389
00390
00391 minError = VMIN2( VSQRT(VABS(errEst)), minError );
00392 maxError = VMAX2( VSQRT(VABS(errEst)), maxError );
00393
00394
00395 Bvec_set( aprx->wev, smid, errEst );
00396
00397
00398 aprx->gerror += errEst;
00399
00400
00401 } else {
00402 Bvec_set( aprx->wev, smid, 0. );
00403 }
00404
00405 smid++;
00406 }
00407
00408
00409 Vnm_print(0,"..done. [marked=<%d/%d>]\n",marked,Gem_numSS(thee->gm));
00410 Vnm_print(0,"Vpee_estRefine: TOL=<%g> Global_Error=<%g>\n",
00411 etol, aprx->gerror);
00412 Vnm_print(0,"Vpee_estRefine: (TOL^2/numS)^{1/2}=<%g> Max_Ele_Error=<%g>\n",
00413 VSQRT(mlevel),maxError);
00414 Vnm_tstop(30, "error estimation");
00415
00416
00417 if ((bkey == 1) && (aprx->gerror <= etol)) {
00418 Vnm_print(0,
00419 "Vpee_estRefine: *********************************************\n");
00420 Vnm_print(0,
00421 "Vpee_estRefine: Global Error criterion met; setting marked=0.\n");
00422 Vnm_print(0,
00423 "Vpee_estRefine: *********************************************\n");
00424 marked = 0;
00425 }
00426
00427
00428
00429 return marked;
00430
00431 }
00432
00433
00434
00435
00436
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 VASSERT(rcol == thee->localPartID);
00498
00499
00500
00501 dist = 0;
00502 for (ivert=0; ivert<SS_dimVV(sm); ivert++) {
00503 dx = VV_coord(SS_vertex(sm, ivert), 0) -
00504 thee->localPartCenter[0];
00505 dy = VV_coord(SS_vertex(sm, ivert), 1) -
00506 thee->localPartCenter[1];
00507 dz = VV_coord(SS_vertex(sm, ivert), 2) -
00508 thee->localPartCenter[2];
00509 dist = VSQRT((dx*dx + dy*dy + dz*dz));
00510 }
00511 if (dist < thee->localPartRadius*thee->killParam) return 1;
00512 }
00513 } else if (thee->killFlag == 3) VASSERT(0);
00514 else VASSERT(0);
00515
00516 return 0;
00517
00518 }
00519
00520 #endif
00521 #endif