/* * *************************************************************************** * Routine: Vcom_dtor * * Purpose: Destroy the communications object * * Author: Nathan Baker and Michael Holst * *************************************************************************** */ VPUBLIC void Vcom_dtor(Vcom **thee) { if ((*thee) != VNULL) { Vcom_dtor2(*thee); Vmem_free( VNULL, 1, sizeof(Vcom_core), (void**)&((*thee)->core) ); Vmem_free( VNULL, 1, sizeof(Vcom), (void**)thee ); } }
/* * *************************************************************************** * Routine: Mat_killStructureLN * * Purpose: Kill the nonzero structure and structure information. * * Notes: This routine does the reverse of Mat_initStructureLN * (or Mat_copyStructureLN). It leaves only the information * about the number of blocks, number of rows, and number of * columns per block. I.e., what is left is only what was * present after the initial call to Mat_ctor. * * Author: Stephen Bond and Michael Holst * *************************************************************************** */ VPUBLIC void Mat_killStructureLN(Mat *thee) { if (thee != VNULL) { if (thee->state != NULL_STATE) { /* Format-dependent destruction */ switch (thee->format) { case RLN_FORMAT: if (thee->lnkU != VNULL) { Vset_dtor( &(thee->lnkU) ); } break; case CLN_FORMAT: if (thee->lnkL != VNULL) { Vset_dtor( &(thee->lnkL) ); } break; case XLN_FORMAT: if (thee->lnkU != VNULL) Vset_dtor( &(thee->lnkU) ); if (thee->xln != VNULL) { if ( Mat_sym(thee) == ISNOT_SYM ) { Vmem_free( thee->vmem, thee->numA, sizeof(LinkRC*), (void**)&(thee->xln)); } else { Vmem_free( thee->vmem, thee->numA, sizeof(LinkRCS), (void**)&(thee->xln)); } } thee->numA = 0; break; default: VASSERT(0); break; } /* initialize the state */ thee->state = NULL_STATE; } } }
VPUBLIC void Vgreen_dtor(Vgreen **thee) { if ((*thee) != VNULL) { Vgreen_dtor2(*thee); Vmem_free(VNULL, 1, sizeof(Vgreen), (void **)thee); (*thee) = VNULL; } }
/* * *************************************************************************** * Routine: Bmat_dtor * * Purpose: The block sparse matrix destructor. * * Notes: This destructor does the reverse of Bmat_ctor, and if * necessary first reverses Bmat_initStructure * (or Bmat_copyStructure). I.e., if necessary, * it first frees the large integer and real arrays created by * Bmat_initStructure or Bmat_copyStructure, and then frees the * Bmat object itself at the last moment. * * Author: Michael Holst * *************************************************************************** */ VPUBLIC void Bmat_dtor(Bmat **thee) { int p, q; /* VASSERT( (*thee) != VNULL ); */ if ((*thee) != VNULL) { /* first free any coarse guy */ if ( (*thee)->coarse != VNULL ) { Bmat_dtor( &((*thee)->coarse) ); } /* next free the large integer and real nonzero structure */ Bmat_killStructure(*thee); /* kill the submatrices themselves */ Mat_dtor( &((*thee)->AG) ); for (p=0; p<(*thee)->numB; p++) { for (q=0; q<(*thee)->numB; q++) { if ( !(*thee)->mirror[p][q] ) { Mat_dtor( &((*thee)->AD[p][q]) ); } } } /* now kill the object itself */ VDEBUGIO("Bmat_dtor: DESTROYING object.."); if ((*thee)->iMadeVmem) Vmem_dtor( &((*thee)->vmem) ); Vmem_free( VNULL, 1, sizeof(Bmat), (void**)thee ); VDEBUGIO("..done.\n"); (*thee) = VNULL; } }
VPUBLIC void BEMparm_dtor(BEMparm **thee) { if ((*thee) != VNULL) { BEMparm_dtor2(*thee); Vmem_free(VNULL, 1, sizeof(BEMparm), (void **)thee); (*thee) = VNULL; } }
VPUBLIC void Vcsm_dtor(Vcsm **thee) { if ((*thee) != VNULL) { Vcsm_dtor2(*thee); Vmem_free(VNULL, 1, sizeof(Vcsm), (void **)thee); (*thee) = VNULL; } }
/* * *************************************************************************** * Routine: Gem_dtor * * Purpose: Geometry manager destructor. * * Author: Michael Holst * *************************************************************************** */ VPUBLIC void Gem_dtor(Gem **thee) { int i; VASSERT( (*thee) != VNULL ); if ((*thee) != VNULL) { if ((*thee)->iMadePDE) { PDE_dtor_default( &((*thee)->pde) ); } Vset_dtor( &((*thee)->vertices) ); Vset_dtor( &((*thee)->edges) ); Vset_dtor( &((*thee)->simplices) ); for (i=0; i<VMAXSQ; i++) { Vset_dtor( &((*thee)->sQueM[i]) ); } VDEBUGIO("Gem_dtor: DESTROYING object.."); if ((*thee)->iMadeVmem) Vmem_dtor( &((*thee)->vmem) ); Vmem_free( VNULL, 1, sizeof(Gem), (void**)thee ); VDEBUGIO("..done.\n"); (*thee) = VNULL; } }
/* Main (stub) destructor */ VPUBLIC void VclistCell_dtor2(VclistCell *thee) { if (thee->natoms > 0) { Vmem_free(VNULL, thee->natoms, sizeof(Vatom *), (void **)&(thee->atoms)); } }
/* * *************************************************************************** * Routine: Vmem_realloc * * Purpose: A logged version of realloc (using this is usually a bad idea). * * Author: Michael Holst * *************************************************************************** */ VPUBLIC void *Vmem_realloc(Vmem *thee, size_t num, size_t size, void **ram, size_t newNum) { void *tee = Vmem_malloc(thee, newNum, size); memcpy(tee, (*ram), size*VMIN2(num,newNum)); Vmem_free(thee, num, size, ram); return tee; }
/* /////////////////////////////////////////////////////////////////////////// // Routine: Vopot_dtor // Author: Nathan Baker /////////////////////////////////////////////////////////////////////////// */ VPUBLIC void Vopot_dtor(Vopot **thee) { if ((*thee) != VNULL) { Vopot_dtor2(*thee); Vmem_free(VNULL, 1, sizeof(Vopot), (void **)thee); (*thee) = VNULL; } }
VPUBLIC void VclistCell_dtor(VclistCell **thee) { if ((*thee) != VNULL) { VclistCell_dtor2(*thee); Vmem_free(VNULL, 1, sizeof(VclistCell), (void **)thee); (*thee) = VNULL; } }
/* /////////////////////////////////////////////////////////////////////////// // Routine: Vpee_dtor // // Author: Nathan Baker /////////////////////////////////////////////////////////////////////////// */ VPUBLIC void Vpee_dtor(Vpee **thee) { if ((*thee) != VNULL) { Vpee_dtor2(*thee); Vmem_free(VNULL, 1, sizeof(Vpee), (void **)thee); (*thee) = VNULL; } }
/* * *************************************************************************** * Routine: PDE_dtor_default * * Purpose: Destroy a fake differential equation object. * * Author: Michael Holst * *************************************************************************** */ VPUBLIC void PDE_dtor_default(PDE **thee) { VASSERT( (*thee) != VNULL ); if ((*thee) != VNULL) { Vmem_free( VNULL, 1, sizeof(PDE), (void**)thee ); (*thee) = VNULL; } }
VPRIVATE int treecleanup(Vgreen *thee) { #ifdef HAVE_TREE Vmem_free(thee->vmem, thee->np, sizeof(double), (void **)&(thee->xp)); Vmem_free(thee->vmem, thee->np, sizeof(double), (void **)&(thee->yp)); Vmem_free(thee->vmem, thee->np, sizeof(double), (void **)&(thee->zp)); Vmem_free(thee->vmem, thee->np, sizeof(double), (void **)&(thee->qp)); F77CLEANUP(); return 1; #else /* ifdef HAVE_TREE */ Vnm_print(2, "treecleanup: Error! APBS not linked with treecode!\n"); return 0; #endif /* ifdef HAVE_TREE */ }
/* * *************************************************************************** * Routine: Vmpi_dtor * * Purpose: The Vmpi destructor. * * Author: Michael Holst * *************************************************************************** */ VPUBLIC void Vmpi_dtor(Vmpi **thee) { VDEBUGIO("Vmpi_dtor: DESTROYING object.."); Vmem_free( VNULL, 1, sizeof(Vmpi), (void**)thee ); #if defined(HAVE_MPI_H) #if 0 VASSERT( MPI_SUCCESS == MPI_Finalize() ); #endif #endif VDEBUGIO("..done.\n"); }
/* * *************************************************************************** * Routine: Vcom_ctor * * Purpose: Construct the communications object * * Notes: This routine sets up data members of class and initializes MPI. * * Author: Nathan Baker and Michael Holst * *************************************************************************** */ VPUBLIC Vcom* Vcom_ctor(int commtype) { int rc; Vcom *thee = VNULL; /* Set up the structure */ thee = Vmem_malloc( VNULL, 1, sizeof(Vcom) ); thee->core = Vmem_malloc( VNULL, 1, sizeof(Vcom_core) ); /* Call the real constructor */ rc = Vcom_ctor2(thee, commtype); /* Destroy the guy if something went wrong */ if (rc == 0) { Vmem_free( VNULL, 1, sizeof(Vcom_core), (void**)&(thee->core) ); Vmem_free( VNULL, 1, sizeof(Vcom), (void**)&thee ); } return thee; }
/* /////////////////////////////////////////////////////////////////////////// // Routine: PDE_dtor // // Purpose: Destroy the differential equation object. // // Speed: This function is called by MC one time during shutdown, // and does not have to be particularly fast. // // Author: Michael Holst /////////////////////////////////////////////////////////////////////////// */ VPUBLIC void myPDE_dtor(PDE **thee) { VASSERT( (*thee) != VNULL ); if ((*thee) != VNULL) { PDE_killDyn( *thee ); Vmem_free( VNULL, 1, sizeof(PDE), (void**)thee ); (*thee) = VNULL; } }
VPUBLIC void Vcsm_dtor2(Vcsm *thee) { int i; if ((thee != VNULL) && thee->initFlag) { for (i=0; i<thee->msimp; i++) { if (thee->nsqm[i] > 0) Vmem_free(thee->vmem, thee->nsqm[i], sizeof(int), (void **)&(thee->sqm[i])); } for (i=0; i<thee->natom; i++) { if (thee->nqsm[i] > 0) Vmem_free(thee->vmem, thee->nqsm[i], sizeof(int), (void **)&(thee->qsm[i])); } Vmem_free(thee->vmem, thee->msimp, sizeof(int *), (void **)&(thee->sqm)); Vmem_free(thee->vmem, thee->msimp, sizeof(int), (void **)&(thee->nsqm)); Vmem_free(thee->vmem, thee->natom, sizeof(int *), (void **)&(thee->qsm)); Vmem_free(thee->vmem, thee->natom, sizeof(int), (void **)&(thee->nqsm)); } Vmem_dtor(&(thee->vmem)); }
VPUBLIC int Vgreen_coulomb(Vgreen *thee, int npos, double *x, double *y, double *z, double *val) { Vatom *atom; double *apos, charge, dist, dx, dy, dz, scale; double *q, qtemp, fx, fy, fz; int iatom, ipos; if (thee == VNULL) { Vnm_print(2, "Vgreen_coulomb: Got NULL thee!\n"); return 0; } for (ipos=0; ipos<npos; ipos++) val[ipos] = 0.0; #ifdef HAVE_TREE /* Allocate charge array (if necessary) */ if (Valist_getNumberAtoms(thee->alist) > 1) { if (npos > 1) { q = VNULL; q = Vmem_malloc(thee->vmem, npos, sizeof(double)); if (q == VNULL) { Vnm_print(2, "Vgreen_coulomb: Error allocating charge array!\n"); return 0; } } else { q = &(qtemp); } for (ipos=0; ipos<npos; ipos++) q[ipos] = 1.0; /* Calculate */ treecalc(thee, x, y, z, q, npos, val, thee->xp, thee->yp, thee->zp, thee->qp, thee->np, &fx, &fy, &fz, 1, 1, thee->np); } else return Vgreen_coulomb_direct(thee, npos, x, y, z, val); /* De-allocate charge array (if necessary) */ if (npos > 1) Vmem_free(thee->vmem, npos, sizeof(double), (void **)&q); scale = Vunit_ec/(4*Vunit_pi*Vunit_eps0*1.0e-10); for (ipos=0; ipos<npos; ipos++) val[ipos] = val[ipos]*scale; return 1; #else /* ifdef HAVE_TREE */ return Vgreen_coulomb_direct(thee, npos, x, y, z, val); #endif }
/* Main (stub) destructor */ VPUBLIC void Vclist_dtor2(Vclist *thee) { VclistCell *cell; int i; for (i=0; i<thee->n; i++) { cell = &(thee->cells[i]); VclistCell_dtor2(cell); } Vmem_free(thee->vmem, thee->n, sizeof(VclistCell), (void **)&(thee->cells)); Vmem_dtor(&(thee->vmem)); }
/* * *************************************************************************** * Routine: MCsh_dtor * * Purpose: The MCsh destructor. * * Author: Michael Holst * *************************************************************************** */ VPUBLIC void MCsh_dtor(MCsh **thee) { VASSERT( (*thee) != VNULL ); if ((*thee) != VNULL) { AM_dtor( &((*thee)->am) ); Aprx_dtor( &((*thee)->aprx) ); Gem_dtor( &((*thee)->gm) ); Vsh_dtor( &((*thee)->vsh) ); VDEBUGIO("MCsh_dtor: DESTROYING object.."); Vmem_dtor( &((*thee)->vmem) ); Vmem_free( VNULL, 1, sizeof(MCsh), (void**)thee ); VDEBUGIO("..done.\n"); (*thee) = VNULL; } }
/* * *************************************************************************** * Routine: Bnode_dtor * * Purpose: The Block node destructor. * * Author: Michael Holst * *************************************************************************** */ VPUBLIC void Bnode_dtor(Bnode **thee) { int i; /* VASSERT( (*thee) != VNULL ); */ if ((*thee) != VNULL) { for (i=0; i<(*thee)->numB; i++) { Node_dtor( (&(*thee)->ND[i]) ); } VDEBUGIO("Bnode_dtor: DESTROYING object.."); if ((*thee)->iMadeVmem) Vmem_dtor( &((*thee)->vmem) ); Vmem_free( VNULL, 1, sizeof(Bnode), (void**)thee ); VDEBUGIO("..done.\n"); (*thee) = VNULL; } }
/* * *************************************************************************** * Routine: Slu_dtor * * Purpose: The Slu destructor. * * Author: Michael Holst and Stephen Bond * *************************************************************************** */ VPUBLIC void Slu_dtor(Slu **thee) { VASSERT( (*thee) != VNULL ); if ((*thee) != VNULL) { /* destroy the factorization */ if( (*thee)->statLU == 1 ) { umfpack_di_free_numeric( &((*thee)->work) ); (*thee)->statLU = 0; } /* finally destroy this container */ VDEBUGIO("Slu_dtor: DESTROYING object.."); if ((*thee)->iMadeVmem) Vmem_dtor( &((*thee)->vmem) ); Vmem_free( VNULL, 1, sizeof(Slu), (void**)thee ); VDEBUGIO("..done.\n"); (*thee) = VNULL; } }
VPUBLIC int Vgreen_coulombD(Vgreen *thee, int npos, double *x, double *y, double *z, double *pot, double *gradx, double *grady, double *gradz) { Vatom *atom; double *apos, charge, dist, dist2, idist3, dy, dz, dx, scale; double *q, qtemp; int iatom, ipos; if (thee == VNULL) { Vnm_print(2, "Vgreen_coulombD: Got VNULL thee!\n"); return 0; } for (ipos=0; ipos<npos; ipos++) { pot[ipos] = 0.0; gradx[ipos] = 0.0; grady[ipos] = 0.0; gradz[ipos] = 0.0; } #ifdef HAVE_TREE if (Valist_getNumberAtoms(thee->alist) > 1) { if (npos > 1) { q = VNULL; q = Vmem_malloc(thee->vmem, npos, sizeof(double)); if (q == VNULL) { Vnm_print(2, "Vgreen_coulomb: Error allocating charge array!\n"); return 0; } } else { q = &(qtemp); } for (ipos=0; ipos<npos; ipos++) q[ipos] = 1.0; /* Calculate */ treecalc(thee, x, y, z, q, npos, pot, thee->xp, thee->yp, thee->zp, thee->qp, thee->np, gradx, grady, gradz, 2, npos, thee->np); /* De-allocate charge array (if necessary) */ if (npos > 1) Vmem_free(thee->vmem, npos, sizeof(double), (void **)&q); } else return Vgreen_coulombD_direct(thee, npos, x, y, z, pot, gradx, grady, gradz); scale = Vunit_ec/(4*VPI*Vunit_eps0*(1.0e-10)); for (ipos=0; ipos<npos; ipos++) { gradx[ipos] = gradx[ipos]*scale; grady[ipos] = grady[ipos]*scale; gradz[ipos] = gradz[ipos]*scale; pot[ipos] = pot[ipos]*scale; } return 1; #else /* ifdef HAVE_TREE */ return Vgreen_coulombD_direct(thee, npos, x, y, z, pot, gradx, grady, gradz); #endif }
/* * *************************************************************************** * Routine: Vmem_dtor * * Purpose: Destruct the dynamic memory allocation logging object. * * Author: Michael Holst * *************************************************************************** */ VPUBLIC void Vmem_dtor(Vmem **thee) { Vmem_free( VNULL, 1, sizeof(Vmem), (void**)thee ); }
/* * *************************************************************************** * Routine: Aprx_partOne * * Purpose: Do a single bisection step. * * Author: Michael Holst * *************************************************************************** */ VPUBLIC int Aprx_partOne(Aprx *thee, int pkey, int pwht, int pcolor, int poff) { int i, j, k, ii, dim, rc, numC, numS, sCount1, sCount2, cutOff; int *pord, *ford, *rord; double tm, cm[3], *evec, eCount1, eCount2, ecutOff, ePart; simHelper *simH; SS *sm; Vnm_print(0,"Aprx_partOne: [pcolor=%d] partitioning:\n", pcolor); /* dimensions */ dim = Gem_dim(thee->gm); numS = Gem_numSS(thee->gm); /* how many guys of this color */ numC = 0; for (i=0; i<numS; i++) { sm = Gem_SS(thee->gm,i); if ((int)SS_chart(sm) == pcolor) numC++; } /* grab some temporary storage */ pord = Vmem_malloc( thee->vmem, numC, sizeof(int) ); ford = Vmem_malloc( thee->vmem, numC, sizeof(int) ); rord = Vmem_malloc( thee->vmem, numS, sizeof(int) ); evec = Vmem_malloc( thee->vmem, numC, sizeof(double) ); simH = Vmem_malloc( thee->vmem, numC, sizeof(simHelper) ); /* build the simplex helper vector and forward/reverse ordering arrays */ ePart = 0.; tm = 0.; for (i=0; i<3; i++) cm[i] = 0.; i = 0; for (ii=0; ii<Gem_numSS(thee->gm); ii++) { sm = Gem_SS(thee->gm,ii); if ((int)SS_chart(sm) == pcolor) { /* initialization */ pord[i] = i; ford[i] = ii; rord[ii] = i; evec[i] = 0.; simH[i].color = SS_chart(sm); simH[i].diag = 0; simH[i].mass = 1.; simH[i].error = Bvec_valB( thee->wev, 0, ii ); for (j=0; j<4; j++) { simH[i].faceId[j] = -1; } /* accumulate error into total for this partition */ ePart += simH[i].error; /* baricenter of this simplex and center of mass of all */ tm += simH[i].mass; for (j=0; j<3; j++) { simH[i].bc[j] = 0.; for (k=0; k<dim+1; k++) { simH[i].bc[j] += VV_coord(SS_vertex(sm,k),j); } simH[i].bc[j] /= (dim+1.); cm[j] += (simH[i].mass * simH[i].bc[j]); } i++; } else { rord[ii] = -1; } } VASSERT( i == numC ); for (i=0; i<3; i++) cm[i] /= tm; /* translate coordinate systems so center of mass is at origin */ for (i=0; i<numC; i++) { for (j=0; j<3; j++) { simH[i].bc[j] -= cm[j]; } } /* okay partition it */ if (pkey == 0) { rc = Aprx_partInert(thee, pcolor, numC, evec, simH); } else if (pkey == 1) { rc = Aprx_partSpect(thee, pcolor, numC, evec, simH, ford, rord, 0); } else if (pkey == 2) { rc = Aprx_partSpect(thee, pcolor, numC, evec, simH, ford, rord, 1); } else if (pkey == 3) { rc = Aprx_partInert(thee, pcolor, numC, evec, simH); rc = Aprx_partSpect(thee, pcolor, numC, evec, simH, ford, rord, 0); } else { Vnm_print(2,"Aprx_partOne: illegal pkey value of <%d>\n", pkey); rc = -1; } /* sort the values small-to-big; allows us to have equi-size submeshes */ Vnm_dqsortOrd(evec, pord, numC); /* color the mesh using the ordering given by the eigenvector */ sCount1 = 0; sCount2 = 0; eCount1 = 0.; eCount2 = 0.; if (rc >= 0) { /* weighted partitioning; divides into two sets of equal error */ if (pwht == 1) { ecutOff = ( ePart / 2. ); for (i=0; i<numC; i++) { sm = Gem_SS(thee->gm,ford[pord[i]]); if (eCount1 < ecutOff) { SS_setChart( sm, pcolor ); sCount1++; eCount1 += Bvec_valB( thee->wev, 0, ford[pord[i]] ); } else { SS_setChart( sm, pcolor+poff ); sCount2++; eCount2 += Bvec_valB( thee->wev, 0, ford[pord[i]] ); } } /* unweighted partitioning; divides into two sets of equal number */ } else { cutOff = numC / 2; for (i=0; i<numC; i++) { sm = Gem_SS(thee->gm,ford[pord[i]]); if (sCount1 < cutOff) { SS_setChart( sm, pcolor ); sCount1++; eCount1 += Bvec_valB( thee->wev, 0, ford[pord[i]] ); } else { SS_setChart( sm, pcolor+poff ); sCount2++; eCount2 += Bvec_valB( thee->wev, 0, ford[pord[i]] ); } } } } /* free the temporary storage */ Vmem_free( thee->vmem, numC, sizeof(int), (void**)&pord ); Vmem_free( thee->vmem, numC, sizeof(int), (void**)&ford ); Vmem_free( thee->vmem, numS, sizeof(int), (void**)&rord ); Vmem_free( thee->vmem, numC, sizeof(double), (void**)&evec ); Vmem_free( thee->vmem, numC, sizeof(simHelper), (void**)&simH ); Vnm_print(0,"Aprx_partOne: done."); Vnm_print(0," [c1=%d,c2=%d,e1=%8.2e,e2=%8.2e,eT=%8.2e]\n", sCount1, sCount2, eCount1, eCount2, (eCount1+eCount2)); if (sCount1 == 0) { Vnm_print(2,"Aprx_partOne: ERROR: first partition has NO SIMPLICES!\n"); } if (sCount2 == 0) { Vnm_print(2,"Aprx_partOne: ERROR: second partition has NO SIMPLICES!\n"); } return rc; }
VPUBLIC int Vcsm_update(Vcsm *thee, SS **simps, int num) { /* Counters */ int isimp, jsimp, iatom, jatom, atomID, simpID; int nsimps, gotMem; /* Object info */ Vatom *atom; SS *simplex; double *position; /* Lists */ int *qParent, nqParent; int **sqmNew, *nsqmNew; int *affAtoms, nAffAtoms; int *dnqsm, *nqsmNew, **qsmNew; VASSERT(thee != VNULL); VASSERT(thee->initFlag); /* If we don't have enough memory to accommodate the new entries, * add more by doubling the existing amount */ isimp = thee->nsimp + num - 1; gotMem = 0; while (!gotMem) { if (isimp > thee->msimp) { isimp = 2 * isimp; thee->nsqm = Vmem_realloc(thee->vmem, thee->msimp, sizeof(int), (void **)&(thee->nsqm), isimp); VASSERT(thee->nsqm != VNULL); thee->sqm = Vmem_realloc(thee->vmem, thee->msimp, sizeof(int *), (void **)&(thee->sqm), isimp); VASSERT(thee->sqm != VNULL); thee->msimp = isimp; } else gotMem = 1; } /* Initialize the nsqm entires we just allocated */ for (isimp = thee->nsimp; isimp<thee->nsimp+num-1 ; isimp++) { thee->nsqm[isimp] = 0; } thee->nsimp = thee->nsimp + num - 1; /* There's a simple case to deal with: if simps[0] didn't have a * charge in the first place */ isimp = SS_id(simps[0]); if (thee->nsqm[isimp] == 0) { for (isimp=1; isimp<num; isimp++) { thee->nsqm[SS_id(simps[isimp])] = 0; } return 1; } /* The more complicated case has occured; the parent simplex had one or * more charges. First, generate the list of affected charges. */ isimp = SS_id(simps[0]); nqParent = thee->nsqm[isimp]; qParent = thee->sqm[isimp]; sqmNew = Vmem_malloc(thee->vmem, num, sizeof(int *)); VASSERT(sqmNew != VNULL); nsqmNew = Vmem_malloc(thee->vmem, num, sizeof(int)); VASSERT(nsqmNew != VNULL); for (isimp=0; isimp<num; isimp++) nsqmNew[isimp] = 0; /* Loop throught the affected atoms to determine how many atoms each * simplex will get. */ for (iatom=0; iatom<nqParent; iatom++) { atomID = qParent[iatom]; atom = Valist_getAtom(thee->alist, atomID); position = Vatom_getPosition(atom); nsimps = 0; jsimp = 0; for (isimp=0; isimp<num; isimp++) { simplex = simps[isimp]; if (Gem_pointInSimplex(thee->gm, simplex, position)) { nsqmNew[isimp]++; jsimp = 1; } } VASSERT(jsimp != 0); } /* Sanity check that we didn't lose any atoms... */ iatom = 0; for (isimp=0; isimp<num; isimp++) iatom += nsqmNew[isimp]; if (iatom < nqParent) { Vnm_print(2,"Vcsm_update: Lost %d (of %d) atoms!\n", nqParent - iatom, nqParent); VASSERT(0); } /* Allocate the storage */ for (isimp=0; isimp<num; isimp++) { if (nsqmNew[isimp] > 0) { sqmNew[isimp] = Vmem_malloc(thee->vmem, nsqmNew[isimp], sizeof(int)); VASSERT(sqmNew[isimp] != VNULL); } } /* Assign charges to simplices */ for (isimp=0; isimp<num; isimp++) { jsimp = 0; simplex = simps[isimp]; /* Loop over the atoms associated with the parent simplex */ for (iatom=0; iatom<nqParent; iatom++) { atomID = qParent[iatom]; atom = Valist_getAtom(thee->alist, atomID); position = Vatom_getPosition(atom); if (Gem_pointInSimplex(thee->gm, simplex, position)) { sqmNew[isimp][jsimp] = atomID; jsimp++; } } } /* Update the QSM map using the old and new SQM lists */ /* The affected atoms are those contained in the parent simplex; i.e. * thee->sqm[SS_id(simps[0])] */ affAtoms = thee->sqm[SS_id(simps[0])]; nAffAtoms = thee->nsqm[SS_id(simps[0])]; /* Each of these atoms will go somewhere else; i.e., the entries in * thee->qsm are never destroyed and thee->nqsm never decreases. * However, it is possible that a subdivision could cause an atom to be * shared by two child simplices. Here we record the change, if any, * in the number of simplices associated with each atom. */ dnqsm = Vmem_malloc(thee->vmem, nAffAtoms, sizeof(int)); VASSERT(dnqsm != VNULL); nqsmNew = Vmem_malloc(thee->vmem, nAffAtoms, sizeof(int)); VASSERT(nqsmNew != VNULL); qsmNew = Vmem_malloc(thee->vmem, nAffAtoms, sizeof(int*)); VASSERT(qsmNew != VNULL); for (iatom=0; iatom<nAffAtoms; iatom++) { dnqsm[iatom] = -1; atomID = affAtoms[iatom]; for (isimp=0; isimp<num; isimp++) { for (jatom=0; jatom<nsqmNew[isimp]; jatom++) { if (sqmNew[isimp][jatom] == atomID) dnqsm[iatom]++; } } VASSERT(dnqsm[iatom] > -1); } /* Setup the new entries in the array */ for (iatom=0;iatom<nAffAtoms; iatom++) { atomID = affAtoms[iatom]; qsmNew[iatom] = Vmem_malloc(thee->vmem, (dnqsm[iatom] + thee->nqsm[atomID]), sizeof(int)); nqsmNew[iatom] = 0; VASSERT(qsmNew[iatom] != VNULL); } /* Fill the new entries in the array */ /* First, do the modified entries */ for (isimp=0; isimp<num; isimp++) { simpID = SS_id(simps[isimp]); for (iatom=0; iatom<nsqmNew[isimp]; iatom++) { atomID = sqmNew[isimp][iatom]; for (jatom=0; jatom<nAffAtoms; jatom++) { if (atomID == affAtoms[jatom]) break; } if (jatom < nAffAtoms) { qsmNew[jatom][nqsmNew[jatom]] = simpID; nqsmNew[jatom]++; } } } /* Now do the unmodified entries */ for (iatom=0; iatom<nAffAtoms; iatom++) { atomID = affAtoms[iatom]; for (isimp=0; isimp<thee->nqsm[atomID]; isimp++) { for (jsimp=0; jsimp<num; jsimp++) { simpID = SS_id(simps[jsimp]); if (thee->qsm[atomID][isimp] == simpID) break; } if (jsimp == num) { qsmNew[iatom][nqsmNew[iatom]] = thee->qsm[atomID][isimp]; nqsmNew[iatom]++; } } } /* Replace the existing entries in the table. Do the QSM entires * first, since they require affAtoms = thee->sqm[simps[0]] */ for (iatom=0; iatom<nAffAtoms; iatom++) { atomID = affAtoms[iatom]; Vmem_free(thee->vmem, thee->nqsm[atomID], sizeof(int), (void **)&(thee->qsm[atomID])); thee->qsm[atomID] = qsmNew[iatom]; thee->nqsm[atomID] = nqsmNew[iatom]; } for (isimp=0; isimp<num; isimp++) { simpID = SS_id(simps[isimp]); if (thee->nsqm[simpID] > 0) Vmem_free(thee->vmem, thee->nsqm[simpID], sizeof(int), (void **)&(thee->sqm[simpID])); thee->sqm[simpID] = sqmNew[isimp]; thee->nsqm[simpID] = nsqmNew[isimp]; } Vmem_free(thee->vmem, num, sizeof(int *), (void **)&sqmNew); Vmem_free(thee->vmem, num, sizeof(int), (void **)&nsqmNew); Vmem_free(thee->vmem, nAffAtoms, sizeof(int *), (void **)&qsmNew); Vmem_free(thee->vmem, nAffAtoms, sizeof(int), (void **)&nqsmNew); Vmem_free(thee->vmem, nAffAtoms, sizeof(int), (void **)&dnqsm); return 1; }
/* * *************************************************************************** * Routine: Gem_speedChk * * Purpose: Calculate the cost to traverse the various structures. * * Author: Michael Holst * *************************************************************************** */ VPUBLIC void Gem_speedChk(Gem *thee) { const int N = 100000; const int loop = 1000; int i, j, itotal; double rtotal; double *d0; int *i0; VV *v0, *vx; Vnm_print(0,"Gem_speedChk: Creating normal double vec...\n"); Vnm_tstart(90, "double vec creation"); d0 = Vmem_malloc( thee->vmem, N, sizeof(double) ); Vnm_tstop(90, "double vec creation"); Vnm_print(0,"Gem_speedChk: Creating normal int vec...\n"); Vnm_tstart(90, "int vec creation"); i0 = Vmem_malloc( thee->vmem, N, sizeof(int) ); Vnm_tstop(90, "int vec creation"); Vnm_print(0,"Gem_speedChk: Creating normal VV vec...\n"); Vnm_tstart(90, "VV vec creation"); v0 = Vmem_malloc( thee->vmem, N, sizeof(VV) ); Vnm_tstop(90, "VV vec creation"); Vnm_print(0,"Gem_speedChk: Creating Vset VV vec...\n"); Vnm_tstart(90, "VV Vset creation"); for (i=0; i<N; i++) vx = Gem_createAndInitVV(thee); Vnm_tstop(90, "VV Vset creation"); Vnm_print(0,"Gem_speedChk: Looping over double vec...\n"); Vnm_print(0,"Gem_speedChk: N, loop = %d, %d\n", N, loop); Vnm_tstart(90, "double vec loop"); rtotal = 0.0; for (j=0; j<loop; j++) for (i=0; i<N; i++) rtotal += ( j * d0[i] * (j+d0[i]) ); Vnm_tstop(90, "double vec loop"); Vnm_print(0,"Gem_speedChk: Looping over int vec...\n"); Vnm_print(0,"Gem_speedChk: N, loop = %d, %d\n", N, loop); Vnm_tstart(90, "int vec loop"); itotal = 0; for (j=0; j<loop; j++) for (i=0; i<N; i++) itotal += ( j * i0[i] * (j+i0[i]) ); Vnm_tstop(90, "int vec loop"); Vnm_print(0,"Gem_speedChk: Looping over VV vec...\n"); Vnm_print(0,"Gem_speedChk: N, loop = %d, %d\n", N, loop); Vnm_tstart(90, "VV vec loop"); itotal = 0; for (j=0; j<loop; j++) for (i=0; i<N; i++) itotal += ( j * VV_id(&v0[i]) * (j+VV_id(&v0[i])) ); Vnm_tstop(90, "VV vec loop"); Vnm_print(0,"Gem_speedChk: Looping (index) over Vset VV vec...\n"); Vnm_print(0,"Gem_speedChk: N, loop = %d, %d\n", N, loop); Vnm_tstart(90, "VV Vset loop"); itotal = 0; for (j=0; j<loop; j++) for (i=0; i<N; i++) itotal += ( j * VV_id(Gem_VV(thee,i)) * (j + VV_id(Gem_VV(thee,i)) ) ); Vnm_tstop(90, "VV Vset loop"); Vnm_print(0,"Gem_speedChk: Looping (iterator) over Vset VV vec...\n"); Vnm_print(0,"Gem_speedChk: N, loop = %d, %d\n", N, loop); Vnm_tstart(90, "VV Vset loop"); itotal = 0; for (j=0; j<loop; j++) for (vx=Gem_firstVV(thee);vx!=VNULL;vx=Gem_nextVV(thee)) itotal += ( j * VV_id(vx) * (j + VV_id(vx)) ); Vnm_tstop(90, "VV Vset loop"); Vnm_print(0,"Gem_speedChk: Freeing normal double vec...\n"); Vnm_tstart(90, "Free double vec"); Vmem_free( thee->vmem, N, sizeof(double), (void**)&d0 ); Vnm_tstop(90, "Free double vec"); Vnm_print(0,"Gem_speedChk: Freeing normal int vec...\n"); Vnm_tstart(90, "Free int vec"); Vmem_free( thee->vmem, N, sizeof(int), (void**)&i0 ); Vnm_tstop(90, "Free int vec"); Vnm_print(0,"Gem_speedChk: Freeing normal VV vec...\n"); Vnm_tstart(90, "Free VV vec"); Vmem_free( thee->vmem, N, sizeof(VV), (void**)&v0 ); Vnm_tstop(90, "Free VV vec"); Vnm_print(0,"Gem_speedChk: Freeing Vset VV vec...\n"); Vnm_tstart(90, "Free VV Vset"); for (i=0; i<N; i++) Gem_destroyVV(thee); Vnm_tstop(90, "Free VV Vset"); }